// lib/widgets/collection/album_controller.dart import 'package:aves/model/db/db.dart'; import 'package:aves/model/db/folder_content_type.dart'; import 'package:aves/model/entry/entry.dart'; import 'package:aves/model/vaults/vaults.dart'; import 'package:aves/services/common/services.dart' as services; import 'package:flutter/material.dart'; import 'album_sort.dart'; /// Controller che gestisce la lista degli album basata sulla tabella `folders`. class AlbumController extends ChangeNotifier { final LocalMediaDb localMediaDb; AlbumController({ LocalMediaDb? localMediaDb, }) : localMediaDb = localMediaDb ?? services.localMediaDb; bool loading = true; List _allAlbums = []; AlbumSortType _sortType = AlbumSortType.priorityThenName; List get allAlbums => List.unmodifiable(_allAlbums); Future load() async { loading = true; notifyListeners(); final rows = await localMediaDb.loadFolders( contentType: FolderContentType.media, ); final entries = await localMediaDb.loadEntries(); final entriesMap = { for (final entry in entries) entry.id: entry, }; final list = []; for (final row in rows) { final thumbEntryId = row.thumbEntryId; list.add( AlbumRow( path: row.path, displayName: row.displayName, albumType: row.albumType, priority: row.priority, totalSize: row.totalSize, fileCount: row.fileCount, isRemote: row.isRemote != 0, isVault: vaults.vaultDirectories.contains(row.path), hybridFolder: _parseHybridFolder(row.hybridFolder), hidden: row.hidden == 1, thumbEntry: thumbEntryId != null ? entriesMap[thumbEntryId] : null, ), ); } _allAlbums = sortAlbums(list, _sortType); loading = false; notifyListeners(); } Future refresh() async => load(); List get pinnedAlbums { final list = _allAlbums.where((album) => album.priority > 0 && !album.hidden).toList(); list.sort((a, b) => a.priority.compareTo(b.priority)); return list; } List get normalAlbums { final list = _allAlbums.where((album) => album.priority == 0 && !album.hidden).toList(); list.sort(_compareByNameAsc); return list; } void sortBy(AlbumSortType type) { _sortType = type; switch (type) { case AlbumSortType.priorityThenName: _allAlbums.sort(_compareByPriorityThenName); break; case AlbumSortType.nameAsc: _allAlbums.sort(_compareByNameAsc); break; case AlbumSortType.nameDesc: _allAlbums.sort(_compareByNameDesc); break; case AlbumSortType.sizeAsc: _allAlbums.sort(_compareBySizeAsc); break; default: _allAlbums.sort(_compareByPriorityThenName); break; } notifyListeners(); } static int _compareByPriorityThenName(AlbumRow a, AlbumRow b) { final aPinned = a.priority > 0; final bPinned = b.priority > 0; if (aPinned && !bPinned) return -1; if (!aPinned && bPinned) return 1; if (aPinned && bPinned) { final priorityCompare = a.priority.compareTo(b.priority); if (priorityCompare != 0) return priorityCompare; } return _compareByNameAsc(a, b); } static int _compareByNameAsc(AlbumRow a, AlbumRow b) { return a.displayName.toLowerCase().compareTo( b.displayName.toLowerCase(), ); } static int _compareByNameDesc(AlbumRow a, AlbumRow b) { return b.displayName.toLowerCase().compareTo( a.displayName.toLowerCase(), ); } static int _compareBySizeAsc(AlbumRow a, AlbumRow b) { final sizeCompare = a.totalSize.compareTo(b.totalSize); if (sizeCompare != 0) return sizeCompare; return _compareByNameAsc(a, b); } Future togglePin(AlbumRow album) async { final db = localMediaDb as dynamic; final newPriority = album.priority > 0 ? 0 : _computeNewPinPriority(); await db.updateFolderPriority( album.path, newPriority, ); await load(); } int _computeNewPinPriority() { final pinned = pinnedAlbums; if (pinned.isEmpty) return 1000; return pinned.first.priority + 1000; } Future reorderPinned(int oldIndex, int newIndex) async { final db = localMediaDb as dynamic; final pinned = pinnedAlbums; if (newIndex > oldIndex) { newIndex -= 1; } final item = pinned.removeAt(oldIndex); pinned.insert(newIndex, item); for (var i = 0; i < pinned.length; i++) { final album = pinned[i]; final newPriority = i + 1; if (album.priority != newPriority) { await db.updateFolderPriority( album.path, newPriority, ); } } await load(); } Future toggleHidden(AlbumRow album) async { final db = localMediaDb as dynamic; final newHidden = album.hidden ? 0 : 1; await db.updateFolderHidden( album.path, newHidden, ); await load(); } Future renameAlbum( AlbumRow album, String newName, ) async { final db = localMediaDb as dynamic; await db.updateFolderDisplayName( album.path, newName, ); await load(); } Future setCover( AlbumRow album, AvesEntry entry, ) async { final db = localMediaDb as dynamic; await db.updateFolderCover( album.path, entry.id, ); await load(); } Future deleteAlbum(AlbumRow album) async { final db = localMediaDb as dynamic; await db.deleteFolder(album.path); await load(); } static int _parseHybridFolder(Object? value) { if (value == null) return 0; if (value is int) return value; if (value is num) return value.toInt(); return int.tryParse('$value') ?? 0; } }