@@ -39,20 +39,35 @@ class CollabFolderSyncService {
3939 final outgoing = await service.getOutgoingCollaborations ();
4040 final accepted = await service.getAcceptedCollaborations ();
4141
42+ // Collect all groups that need sync, deduplicating by folder path
43+ // (multiple collabs may point to the same folder — only watch once per folder)
44+ final groupsToSync = < String , String > {}; // groupId → folderPath
4245 for (final c in outgoing) {
4346 if (c.syncEnabled && c.localFolderPath != null ) {
44- debugPrint ('[CollabFolderSync] Starting sync for outgoing "${c .name }" → ${c .localFolderPath }' );
45- await startSync (c.id);
46- } else {
47- debugPrint ('[CollabFolderSync] Skipping outgoing "${c .name }" (syncEnabled=${c .syncEnabled }, folder=${c .localFolderPath })' );
47+ if (groupsToSync.values.contains (c.localFolderPath)) {
48+ debugPrint ('[CollabFolderSync] Skipping duplicate folder for outgoing "${c .name }" → ${c .localFolderPath }' );
49+ continue ;
50+ }
51+ groupsToSync[c.id] = c.localFolderPath! ;
4852 }
4953 }
5054 for (final c in accepted) {
5155 if (c.syncEnabled && c.localFolderPath != null ) {
52- debugPrint ('[CollabFolderSync] Starting sync for accepted "${c .name }" → ${c .localFolderPath }' );
53- await startSync (c.id);
54- } else {
55- debugPrint ('[CollabFolderSync] Skipping accepted "${c .name }" (syncEnabled=${c .syncEnabled }, folder=${c .localFolderPath })' );
56+ if (groupsToSync.values.contains (c.localFolderPath)) {
57+ debugPrint ('[CollabFolderSync] Skipping duplicate folder for accepted "${c .name }" → ${c .localFolderPath }' );
58+ continue ;
59+ }
60+ groupsToSync[c.id] = c.localFolderPath! ;
61+ }
62+ }
63+
64+ // Start sync for each group, catching per-group errors so one failure
65+ // doesn't abort the rest (SecureStorage file locks can cause transient errors)
66+ for (final entry in groupsToSync.entries) {
67+ try {
68+ await _startSyncDirect (entry.key, entry.value);
69+ } catch (e) {
70+ debugPrint ('[CollabFolderSync] Failed to start sync for ${entry .key }: $e ' );
5671 }
5772 }
5873 debugPrint ('[CollabFolderSync] Initialized. Active syncs: ${_watchers .length }' );
@@ -116,13 +131,15 @@ class CollabFolderSyncService {
116131
117132 /// Start watching and polling for a group.
118133 Future <void > startSync (String groupId) async {
119- // Prevent duplicates
120- await stopSync (groupId);
121-
122134 final info = await _getGroupInfo (groupId);
123135 if (info == null || info.folderPath == null ) return ;
136+ await _startSyncDirect (groupId, info.folderPath! );
137+ }
124138
125- final folderPath = info.folderPath! ;
139+ /// Start watching and polling with a known folder path (avoids SecureStorage re-read).
140+ Future <void > _startSyncDirect (String groupId, String folderPath) async {
141+ // Prevent duplicates
142+ await stopSync (groupId);
126143
127144 // Start directory watcher
128145 final dir = Directory (folderPath);
@@ -385,8 +402,21 @@ class CollabFolderSyncService {
385402 }
386403 }
387404
405+ // If not in sync metadata, fall back to searching the manifest by fileName
406+ // (handles files added before sync metadata tracking or after a metadata reset)
407+ if (matchedFileId == null ) {
408+ debugPrint ('[CollabFolderSync] File not in sync metadata, checking manifest: $fileName ' );
409+ final group = info.group;
410+ for (final f in group.files) {
411+ if (f.fileName == fileName) {
412+ matchedFileId = f.id;
413+ break ;
414+ }
415+ }
416+ }
417+
388418 if (matchedFileId == null ) {
389- debugPrint ('[CollabFolderSync] Deleted file not found in sync metadata: $fileName ' );
419+ debugPrint ('[CollabFolderSync] Deleted file not found in sync metadata or manifest : $fileName ' );
390420 return ;
391421 }
392422
0 commit comments