## Corrections Critiques ### Race Condition - Statuts de Messages - Fix : Les icônes de statut (✓, ✓✓, ✓✓ bleu) ne s'affichaient pas - Cause : WebSocket delivery confirmations arrivaient avant messages locaux - Solution : Pattern Optimistic UI dans chat_bloc.dart - Création message temporaire immédiate - Ajout à la liste AVANT requête HTTP - Remplacement par message serveur à la réponse - Fichier : lib/presentation/state_management/chat_bloc.dart ## Implémentation TODOs (13/21) ### Social (social_header_widget.dart) - ✅ Copier lien du post dans presse-papiers - ✅ Partage natif via Share.share() - ✅ Dialogue de signalement avec 5 raisons ### Partage (share_post_dialog.dart) - ✅ Interface sélection d'amis avec checkboxes - ✅ Partage externe via Share API ### Média (media_upload_service.dart) - ✅ Parsing JSON réponse backend - ✅ Méthode deleteMedia() pour suppression - ✅ Génération miniature vidéo ### Posts (create_post_dialog.dart, edit_post_dialog.dart) - ✅ Extraction URL depuis uploads - ✅ Documentation chargement médias ### Chat (conversations_screen.dart) - ✅ Navigation vers notifications - ✅ ConversationSearchDelegate pour recherche ## Nouveaux Fichiers ### Configuration - build-prod.ps1 : Script build production avec dart-define - lib/core/constants/env_config.dart : Gestion environnements ### Documentation - TODOS_IMPLEMENTED.md : Documentation complète TODOs ## Améliorations ### Architecture - Refactoring injection de dépendances - Amélioration routing et navigation - Optimisation providers (UserProvider, FriendsProvider) ### UI/UX - Amélioration thème et couleurs - Optimisation animations - Meilleure gestion erreurs ### Services - Configuration API avec env_config - Amélioration datasources (events, users) - Optimisation modèles de données
327 lines
11 KiB
Dart
327 lines
11 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// Design System centralisé pour Afterwork
|
|
///
|
|
/// Ce fichier contient toutes les constantes de design pour assurer
|
|
/// une cohérence visuelle à travers toute l'application.
|
|
///
|
|
/// **Sections:**
|
|
/// - Spacing: Espacements standardisés
|
|
/// - BorderRadius: Rayons de bordure
|
|
/// - Shadows: Ombres et élévations
|
|
/// - Durations: Durées d'animations
|
|
/// - Curves: Courbes d'animations
|
|
/// - Sizes: Tailles standardisées
|
|
class DesignSystem {
|
|
// ============================================================================
|
|
// SPACING
|
|
// ============================================================================
|
|
|
|
/// Espacements standardisés
|
|
///
|
|
/// Utiliser ces constantes pour tous les paddings, margins, gaps, etc.
|
|
/// Cela garantit une cohérence visuelle et facilite les ajustements.
|
|
static const double spacing2xs = 2.0;
|
|
static const double spacingXs = 4.0;
|
|
static const double spacingSm = 8.0;
|
|
static const double spacingMd = 12.0;
|
|
static const double spacingLg = 16.0;
|
|
static const double spacingXl = 24.0;
|
|
static const double spacing2xl = 32.0;
|
|
static const double spacing3xl = 48.0;
|
|
static const double spacing4xl = 64.0;
|
|
|
|
/// Padding horizontal standard des écrans
|
|
static const double screenPaddingHorizontal = spacingLg;
|
|
|
|
/// Padding vertical standard des écrans
|
|
static const double screenPaddingVertical = spacingLg;
|
|
|
|
/// Gap entre éléments de liste
|
|
static const double listItemGap = spacingMd;
|
|
|
|
/// Gap entre sections
|
|
static const double sectionGap = spacingXl;
|
|
|
|
// ============================================================================
|
|
// BORDER RADIUS
|
|
// ============================================================================
|
|
|
|
/// Rayons de bordure standardisés
|
|
static const double radiusXs = 4.0;
|
|
static const double radiusSm = 8.0;
|
|
static const double radiusMd = 12.0;
|
|
static const double radiusLg = 16.0;
|
|
static const double radiusXl = 20.0;
|
|
static const double radius2xl = 24.0;
|
|
static const double radiusRound = 999.0;
|
|
|
|
/// BorderRadius objets pour utilisation directe
|
|
static final BorderRadius borderRadiusXs = BorderRadius.circular(radiusXs);
|
|
static final BorderRadius borderRadiusSm = BorderRadius.circular(radiusSm);
|
|
static final BorderRadius borderRadiusMd = BorderRadius.circular(radiusMd);
|
|
static final BorderRadius borderRadiusLg = BorderRadius.circular(radiusLg);
|
|
static final BorderRadius borderRadiusXl = BorderRadius.circular(radiusXl);
|
|
static final BorderRadius borderRadius2xl = BorderRadius.circular(radius2xl);
|
|
static final BorderRadius borderRadiusRound = BorderRadius.circular(radiusRound);
|
|
|
|
// ============================================================================
|
|
// SHADOWS
|
|
// ============================================================================
|
|
|
|
/// Ombres standardisées pour Material Design
|
|
///
|
|
/// Niveaux d'élévation:
|
|
/// - None: Pas d'ombre
|
|
/// - Sm: Petite élévation (cartes au repos)
|
|
/// - Md: Élévation moyenne (cartes survolées)
|
|
/// - Lg: Grande élévation (dialogs, bottom sheets)
|
|
/// - Xl: Très grande élévation (navigation drawer)
|
|
|
|
static const List<BoxShadow> shadowNone = [];
|
|
|
|
static const List<BoxShadow> shadowSm = [
|
|
BoxShadow(
|
|
color: Color(0x0F000000), // 6% opacity
|
|
blurRadius: 4,
|
|
offset: Offset(0, 1),
|
|
spreadRadius: 0,
|
|
),
|
|
];
|
|
|
|
static const List<BoxShadow> shadowMd = [
|
|
BoxShadow(
|
|
color: Color(0x14000000), // 8% opacity
|
|
blurRadius: 8,
|
|
offset: Offset(0, 2),
|
|
spreadRadius: 0,
|
|
),
|
|
];
|
|
|
|
static const List<BoxShadow> shadowLg = [
|
|
BoxShadow(
|
|
color: Color(0x1F000000), // 12% opacity
|
|
blurRadius: 16,
|
|
offset: Offset(0, 4),
|
|
spreadRadius: 0,
|
|
),
|
|
];
|
|
|
|
static const List<BoxShadow> shadowXl = [
|
|
BoxShadow(
|
|
color: Color(0x29000000), // 16% opacity
|
|
blurRadius: 24,
|
|
offset: Offset(0, 8),
|
|
spreadRadius: 0,
|
|
),
|
|
];
|
|
|
|
/// Ombres pour mode sombre (plus subtiles)
|
|
static const List<BoxShadow> shadowSmDark = [
|
|
BoxShadow(
|
|
color: Color(0x33000000), // 20% opacity
|
|
blurRadius: 4,
|
|
offset: Offset(0, 1),
|
|
spreadRadius: 0,
|
|
),
|
|
];
|
|
|
|
static const List<BoxShadow> shadowMdDark = [
|
|
BoxShadow(
|
|
color: Color(0x3D000000), // 24% opacity
|
|
blurRadius: 8,
|
|
offset: Offset(0, 2),
|
|
spreadRadius: 0,
|
|
),
|
|
];
|
|
|
|
static const List<BoxShadow> shadowLgDark = [
|
|
BoxShadow(
|
|
color: Color(0x47000000), // 28% opacity
|
|
blurRadius: 16,
|
|
offset: Offset(0, 4),
|
|
spreadRadius: 0,
|
|
),
|
|
];
|
|
|
|
// ============================================================================
|
|
// DURATIONS (Durées d'animations)
|
|
// ============================================================================
|
|
|
|
/// Durées d'animations standardisées
|
|
///
|
|
/// Suivent les Material Design motion guidelines:
|
|
/// - Fast: Micro-interactions rapides (100-200ms)
|
|
/// - Medium: Transitions standard (200-300ms)
|
|
/// - Slow: Animations complexes (300-500ms)
|
|
static const Duration durationInstant = Duration(milliseconds: 100);
|
|
static const Duration durationFast = Duration(milliseconds: 200);
|
|
static const Duration durationMedium = Duration(milliseconds: 300);
|
|
static const Duration durationSlow = Duration(milliseconds: 400);
|
|
static const Duration durationSlower = Duration(milliseconds: 500);
|
|
|
|
// ============================================================================
|
|
// CURVES (Courbes d'animations)
|
|
// ============================================================================
|
|
|
|
/// Courbes d'animations standardisées
|
|
///
|
|
/// Material Design recommande:
|
|
/// - easeIn: Accélération au début (sortie d'écran)
|
|
/// - easeOut: Décélération à la fin (entrée d'écran)
|
|
/// - easeInOut: Accélération puis décélération (transitions)
|
|
/// - bounce: Effet rebond (micro-interactions fun)
|
|
static const Curve curveStandard = Curves.easeInOut;
|
|
static const Curve curveDecelerate = Curves.easeOut;
|
|
static const Curve curveAccelerate = Curves.easeIn;
|
|
static const Curve curveSharp = Curves.easeInOutCubic;
|
|
static const Curve curveBounce = Curves.elasticOut;
|
|
|
|
// ============================================================================
|
|
// SIZES (Tailles standardisées)
|
|
// ============================================================================
|
|
|
|
/// Tailles d'icônes
|
|
static const double iconSizeXs = 16.0;
|
|
static const double iconSizeSm = 20.0;
|
|
static const double iconSizeMd = 24.0;
|
|
static const double iconSizeLg = 32.0;
|
|
static const double iconSizeXl = 48.0;
|
|
static const double iconSize2xl = 64.0;
|
|
|
|
/// Tailles d'avatars
|
|
static const double avatarSizeXs = 24.0;
|
|
static const double avatarSizeSm = 32.0;
|
|
static const double avatarSizeMd = 40.0;
|
|
static const double avatarSizeLg = 56.0;
|
|
static const double avatarSizeXl = 72.0;
|
|
static const double avatarSize2xl = 96.0;
|
|
|
|
/// Hauteurs de boutons
|
|
static const double buttonHeightSm = 36.0;
|
|
static const double buttonHeightMd = 44.0;
|
|
static const double buttonHeightLg = 52.0;
|
|
|
|
/// Hauteurs de champs de saisie
|
|
static const double inputHeightSm = 40.0;
|
|
static const double inputHeightMd = 48.0;
|
|
static const double inputHeightLg = 56.0;
|
|
|
|
/// Tailles de FAB (Floating Action Button)
|
|
static const double fabSizeSm = 48.0;
|
|
static const double fabSizeMd = 56.0;
|
|
static const double fabSizeLg = 64.0;
|
|
|
|
// ============================================================================
|
|
// OPACITIES (Opacités standardisées)
|
|
// ============================================================================
|
|
|
|
static const double opacityDisabled = 0.38;
|
|
static const double opacityInactive = 0.54;
|
|
static const double opacitySecondary = 0.7;
|
|
static const double opacityPrimary = 0.87;
|
|
static const double opacityFull = 1.0;
|
|
|
|
// ============================================================================
|
|
// Z-INDEX / ELEVATION
|
|
// ============================================================================
|
|
|
|
static const double elevationNone = 0.0;
|
|
static const double elevationXs = 1.0;
|
|
static const double elevationSm = 2.0;
|
|
static const double elevationMd = 4.0;
|
|
static const double elevationLg = 8.0;
|
|
static const double elevationXl = 16.0;
|
|
|
|
// ============================================================================
|
|
// BREAKPOINTS (pour responsive design)
|
|
// ============================================================================
|
|
|
|
static const double breakpointMobile = 600.0;
|
|
static const double breakpointTablet = 900.0;
|
|
static const double breakpointDesktop = 1200.0;
|
|
|
|
// ============================================================================
|
|
// HELPER METHODS
|
|
// ============================================================================
|
|
|
|
/// Retourne les ombres appropriées selon le thème
|
|
static List<BoxShadow> getShadow(
|
|
BuildContext context,
|
|
ShadowSize size,
|
|
) {
|
|
final isDark = Theme.of(context).brightness == Brightness.dark;
|
|
|
|
switch (size) {
|
|
case ShadowSize.none:
|
|
return shadowNone;
|
|
case ShadowSize.sm:
|
|
return isDark ? shadowSmDark : shadowSm;
|
|
case ShadowSize.md:
|
|
return isDark ? shadowMdDark : shadowMd;
|
|
case ShadowSize.lg:
|
|
return isDark ? shadowLgDark : shadowLg;
|
|
case ShadowSize.xl:
|
|
return shadowXl;
|
|
}
|
|
}
|
|
|
|
/// Retourne un EdgeInsets avec padding uniforme
|
|
static EdgeInsets paddingAll(double value) => EdgeInsets.all(value);
|
|
|
|
/// Retourne un EdgeInsets avec padding horizontal
|
|
static EdgeInsets paddingHorizontal(double value) =>
|
|
EdgeInsets.symmetric(horizontal: value);
|
|
|
|
/// Retourne un EdgeInsets avec padding vertical
|
|
static EdgeInsets paddingVertical(double value) =>
|
|
EdgeInsets.symmetric(vertical: value);
|
|
|
|
/// Retourne un EdgeInsets avec padding screen standard
|
|
static EdgeInsets get paddingScreen => const EdgeInsets.symmetric(
|
|
horizontal: screenPaddingHorizontal,
|
|
vertical: screenPaddingVertical,
|
|
);
|
|
|
|
/// Retourne un SizedBox avec hauteur
|
|
static SizedBox verticalSpace(double height) => SizedBox(height: height);
|
|
|
|
/// Retourne un SizedBox avec largeur
|
|
static SizedBox horizontalSpace(double width) => SizedBox(width: width);
|
|
}
|
|
|
|
/// Énumération pour les tailles d'ombres
|
|
enum ShadowSize {
|
|
none,
|
|
sm,
|
|
md,
|
|
lg,
|
|
xl,
|
|
}
|
|
|
|
/// Extensions pour faciliter l'utilisation du Design System
|
|
extension DesignSystemExtensions on BuildContext {
|
|
/// Retourne les ombres selon le thème
|
|
List<BoxShadow> shadow(ShadowSize size) => DesignSystem.getShadow(this, size);
|
|
|
|
/// Retourne true si on est en mode sombre
|
|
bool get isDarkMode => Theme.of(this).brightness == Brightness.dark;
|
|
|
|
/// Retourne la largeur de l'écran
|
|
double get screenWidth => MediaQuery.of(this).size.width;
|
|
|
|
/// Retourne la hauteur de l'écran
|
|
double get screenHeight => MediaQuery.of(this).size.height;
|
|
|
|
/// Retourne true si on est sur mobile
|
|
bool get isMobile => screenWidth < DesignSystem.breakpointMobile;
|
|
|
|
/// Retourne true si on est sur tablette
|
|
bool get isTablet =>
|
|
screenWidth >= DesignSystem.breakpointMobile &&
|
|
screenWidth < DesignSystem.breakpointTablet;
|
|
|
|
/// Retourne true si on est sur desktop
|
|
bool get isDesktop => screenWidth >= DesignSystem.breakpointDesktop;
|
|
}
|