Aves_mio0.88/lib/widgets/collection/album_controller.dart
2026-10-03 12:51:15 +02:00

247 lines
5.8 KiB
Dart

// 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<AlbumRow> _allAlbums = [];
AlbumSortType _sortType = AlbumSortType.priorityThenName;
List<AlbumRow> get allAlbums => List.unmodifiable(_allAlbums);
Future<void> load() async {
loading = true;
notifyListeners();
final rows = await localMediaDb.loadFolders(
contentType: FolderContentType.media,
);
final entries = await localMediaDb.loadEntries();
final entriesMap = <int, AvesEntry>{
for (final entry in entries) entry.id: entry,
};
final list = <AlbumRow>[];
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<void> refresh() async => load();
List<AlbumRow> 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<AlbumRow> 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<void> 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<void> 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<void> toggleHidden(AlbumRow album) async {
final db = localMediaDb as dynamic;
final newHidden = album.hidden ? 0 : 1;
await db.updateFolderHidden(
album.path,
newHidden,
);
await load();
}
Future<void> renameAlbum(
AlbumRow album,
String newName,
) async {
final db = localMediaDb as dynamic;
await db.updateFolderDisplayName(
album.path,
newName,
);
await load();
}
Future<void> setCover(
AlbumRow album,
AvesEntry entry,
) async {
final db = localMediaDb as dynamic;
await db.updateFolderCover(
album.path,
entry.id,
);
await load();
}
Future<void> 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;
}
}