// lib/model/activity/activity_folder_stats.dart import 'package:aves/model/activity/activity_entry.dart'; import 'package:aves/model/db/folder_content_type.dart'; import 'package:aves/model/db/folder_stats.dart'; class ActivityFolderStats { const ActivityFolderStats._(); static List build(Iterable activities) { final folders = {}; for (final entry in activities) { final folderPath = _folderPathForEntry(entry); if (folderPath == null || folderPath.isEmpty) continue; final stats = folders.putIfAbsent(folderPath, () { return FolderStats( path: folderPath, displayName: _displayNameForPath(folderPath), contentType: FolderContentType.activity, fileCount: 0, totalSize: 0, thumbEntryId: null, thumbDate: null, albumType: 0, priority: 0, isRemote: entry.origin, user: null, deviceId: null, hidden: 0, hybridFolder: null, ); }); stats.fileCount++; stats.totalSize += entry.sizeBytes ?? 0; final date = entry.startTimeMillis ?? entry.dateModifiedMillis; if (stats.thumbDate == null || date > stats.thumbDate!) { stats.thumbDate = date; stats.thumbEntryId = entry.id; } // If one activity folder ever contains both local and remote activities, // for now the most recently processed activity defines the folder origin. stats.isRemote = entry.origin; } return folders.values.toList()..sort( (a, b) => a.displayName.toLowerCase().compareTo( b.displayName.toLowerCase(), ), ); } static String? _folderPathForEntry(ActivityEntry entry) { final relativePath = entry.relativePath?.trim(); if (relativePath != null && relativePath.isNotEmpty) { return _normalizePath(relativePath); } final directoryName = entry.directoryName?.trim(); if (directoryName != null && directoryName.isNotEmpty) { return _normalizePath(directoryName); } return 'Activity'; } static String _normalizePath(String path) { var normalized = path.replaceAll('\\', '/').trim(); while (normalized.contains('//')) { normalized = normalized.replaceAll('//', '/'); } if (normalized.endsWith('/')) { normalized = normalized.substring(0, normalized.length - 1); } return normalized.isEmpty ? 'Activity' : normalized; } static String _displayNameForPath(String path) { final normalized = _normalizePath(path); final parts = normalized.split('/').where((part) => part.isNotEmpty); if (parts.isEmpty) return 'Activity'; return parts.last; } }