feat(online): partage client - use cases, inbox cache et import local (ticket #66)

Ajoute l'adapter API distant de partage (infrastructure/remote/share_api.dart)
et les use cases associés (application/use_cases.dart), avec cache
d'inbox et import local des ressources partagées acceptées. Étend le
modèle Drift (migration schemaVersion 11→12) et les entités du domaine
en conséquence. flutter pub get OK, build_runner OK, dart format
appliqué, analyze propre (mêmes infos préexistantes), 124/124 tests
verts, build APK debug validé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 21:54:45 +02:00
parent 715fdd4335
commit 010e055404
12 changed files with 3445 additions and 1 deletions

View File

@ -259,6 +259,69 @@ abstract interface class LocalSyncChangeRepository {
Future<bool> applyRemoteItem(RemoteSyncedItem item);
}
final class RemoteShareSendResult {
const RemoteShareSendResult({
required this.shareId,
required this.recipientUserIds,
required this.unresolvedEmails,
});
final String shareId;
final List<String> recipientUserIds;
final List<String> unresolvedEmails;
}
enum ShareSendStatus { sent, notConnected, queued }
final class ShareSendResult {
const ShareSendResult({
required this.status,
this.shareId,
this.recipientUserIds = const [],
this.unresolvedEmails = const [],
this.pendingActionId,
});
final ShareSendStatus status;
final String? shareId;
final List<String> recipientUserIds;
final List<String> unresolvedEmails;
final String? pendingActionId;
}
abstract interface class RemoteShareApi {
Future<RemoteShareSendResult> sendShare({
required ShareResourceType resourceType,
required Map<String, Object?> payload,
required List<String> recipientEmails,
required String token,
});
Future<List<ShareInboxItem>> fetchInbox(String token);
Future<RemoteSyncedItem> acceptShare(String shareId, String token);
Future<void> declineShare(String shareId, String token);
Future<void> revokeShare(String shareId, String token);
}
abstract interface class ShareInboxRepository {
Future<List<ShareInboxItem>> listAll();
Future<ShareInboxItem?> findByShareId(String shareId);
Future<void> upsert(ShareInboxItem item);
Future<void> upsertAll(List<ShareInboxItem> items);
Future<void> markStatus(
String shareId,
ShareInboxStatus status,
DateTime respondedAt,
);
}
abstract interface class PendingShareActionRepository {
Future<List<PendingShareAction>> listPending();
Future<void> add(PendingShareAction action);
Future<void> markSucceeded(String id, DateTime attemptedAt);
Future<void> markFailed(String id, DateTime attemptedAt);
}
const Object _portsUnchanged = Object();
abstract interface class ExerciseRepository {