Ajoute la synchronisation client incrémentale LWW vers l'API serveur (application/use_cases.dart: SyncUseCases, ports.dart, migration Drift schemaVersion 10→11 pour les métadonnées de sync et mappings de ressources, infrastructure/remote/sync_api.dart) et l'écran de profil avec entrée sur l'accueil (presentation/profile_screen.dart, home_screen.dart, presentation.dart). Développés dans le même worktree partagé par DevBackend et DevFrontend ; commit combiné car test/presentation/home_screen_test.dart mélange authentiquement les deux tickets (le test de l'entrée Profil et la mise à jour du fake de bootstrap requise par le nouveau getter syncUseCases sur AppDependencies). Corrige au passage une couleur `crimson` inexistante dans le thème (remplacée par colorScheme.error) et une signature de paramètres positionnels/nommés incohérente sur un fake de test. flutter pub get OK, build_runner OK, dart format appliqué, analyze propre (mêmes infos préexistantes), 119/119 tests verts, build APK debug validé. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -4,6 +4,7 @@ import '../application/app_bootstrap.dart';
|
||||
import '../domain/domain.dart';
|
||||
import 'exercise_library_screen.dart';
|
||||
import 'history_screen.dart';
|
||||
import 'profile_screen.dart';
|
||||
import 'program_screen.dart';
|
||||
import 'theme.dart';
|
||||
import 'workout_execution_screen.dart';
|
||||
@ -178,6 +179,34 @@ final class _HomeScreenState extends State<HomeScreen> with RouteAware {
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: FutureBuilder<UserAccountSession?>(
|
||||
future: widget.bootstrap.authUseCases.currentSession(),
|
||||
builder: (context, snapshot) {
|
||||
final session = snapshot.data;
|
||||
if (session == null || !session.isLoggedIn) {
|
||||
return const Icon(Icons.account_circle_outlined);
|
||||
}
|
||||
final displayName = session.displayName?.trim();
|
||||
final label = displayName == null || displayName.isEmpty
|
||||
? session.email
|
||||
: displayName;
|
||||
return CircleAvatar(
|
||||
radius: 12,
|
||||
child: Text(_profileInitials(label)),
|
||||
);
|
||||
},
|
||||
),
|
||||
title: const Text('Profil'),
|
||||
subtitle: const Text('Compte, synchronisation et partages'),
|
||||
trailing: const Icon(Icons.chevron_right),
|
||||
onTap: () => Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
ProfileScreen(authUseCases: widget.bootstrap.authUseCases),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -211,3 +240,14 @@ final class _HomeScreenState extends State<HomeScreen> with RouteAware {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
String _profileInitials(String value) {
|
||||
final trimmed = value.trim();
|
||||
if (trimmed.isEmpty) return '?';
|
||||
final words = trimmed.split(RegExp(r'\s+'));
|
||||
if (words.length == 1) {
|
||||
return words.first.substring(0, 1).toUpperCase();
|
||||
}
|
||||
return '${words.first.substring(0, 1)}${words.last.substring(0, 1)}'
|
||||
.toUpperCase();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user