aves_mio0.31/lib/widgets/collection/album_actions.dart
2026-07-18 13:39:22 +02:00

307 lines
9.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:aves/model/entry/entry.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves/utils/file_utils.dart';
import 'album_controller.dart';
import 'album_sort.dart';
import 'package:aves/widgets/collection/collection_page.dart';
class AlbumActions {
// ============================================================
// MENU RAPIDO (3 dots)
// ============================================================
static void showMenu(BuildContext context, AlbumRow album) {
showModalBottomSheet<void>(
context: context,
backgroundColor: Colors.grey.shade900,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
builder: (context) {
return buildBottomSheet(
context: context,
controller: AlbumController.of(context),
album: album,
);
},
);
}
// ============================================================
// BOTTOM SHEET COMPLETO
// ============================================================
static Widget buildBottomSheet({
required BuildContext context,
required AlbumController controller,
required AlbumRow album,
}) {
return SafeArea(
child: Wrap(
children: [
_item(
icon: Icons.folder_open,
text: 'Apri album',
onTap: () {
Navigator.pop(context);
openAlbum(context, album);
},
),
_item(
icon: Icons.drive_file_rename_outline,
text: 'Rinomina',
onTap: () {
Navigator.pop(context);
renameAlbum(context, controller, album);
},
),
_item(
icon: Icons.image,
text: 'Cambia cover',
onTap: () {
Navigator.pop(context);
changeCover(context, controller, album);
},
),
_item(
icon: album.priority > 0 ? Icons.push_pin : Icons.push_pin_outlined,
text: album.priority > 0 ? 'Unpin' : 'Pin',
onTap: () {
Navigator.pop(context);
controller.togglePin(album);
},
),
_item(
icon: album.hidden ? Icons.visibility : Icons.visibility_off,
text: album.hidden ? 'Mostra album' : 'Nascondi album',
onTap: () {
Navigator.pop(context);
controller.toggleHidden(album);
},
),
_item(
icon: Icons.delete,
text: 'Elimina album',
onTap: () {
Navigator.pop(context);
deleteAlbum(context, controller, album);
},
),
_item(
icon: Icons.share,
text: 'Condividi album',
onTap: () {
Navigator.pop(context);
shareAlbum(album);
},
),
_item(
icon: Icons.info,
text: 'Info album',
onTap: () {
Navigator.pop(context);
showInfo(context, album);
},
),
_item(
icon: Icons.folder,
text: 'Apri nel file manager',
onTap: () {
Navigator.pop(context);
openInFileManager(album);
},
),
],
),
);
}
static Widget _item({
required IconData icon,
required String text,
required VoidCallback onTap,
}) {
return ListTile(
leading: Icon(icon, color: Colors.white),
title: Text(text, style: const TextStyle(color: Colors.white)),
onTap: onTap,
);
}
// ============================================================
// APRI ALBUM → CollectionPage
// ============================================================
static void openAlbum(BuildContext context, AlbumRow album) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => CollectionPage(
folderPath: album.path, // ⭐ niente PathFilter
albumName: album.displayName,
),
),
);
}
// ============================================================
// RINOMINA
// ============================================================
static Future<void> renameAlbum(
BuildContext context,
AlbumController controller,
AlbumRow album,
) async {
final controllerText = TextEditingController(text: album.displayName);
final newName = await showDialog<String>(
context: context,
builder: (context) {
return AlertDialog(
backgroundColor: Colors.grey.shade900,
title: const Text('Rinomina album', style: TextStyle(color: Colors.white)),
content: TextField(
controller: controllerText,
autofocus: true,
style: const TextStyle(color: Colors.white),
decoration: const InputDecoration(
hintText: 'Nuovo nome',
hintStyle: TextStyle(color: Colors.white54),
),
),
actions: [
TextButton(
child: const Text('Annulla'),
onPressed: () => Navigator.pop(context),
),
TextButton(
child: const Text('OK'),
onPressed: () => Navigator.pop(context, controllerText.text.trim()),
),
],
);
},
);
if (newName != null && newName.isNotEmpty) {
await controller.renameAlbum(album, newName);
}
}
// ============================================================
// CAMBIA COVER
// ============================================================
static Future<void> changeCover(
BuildContext context,
AlbumController controller,
AlbumRow album,
) async {
final entry = await pickEntry(context);
if (entry != null) {
await controller.setCover(album, entry);
}
}
static Future<AvesEntry?> pickEntry(BuildContext context) async {
return await Navigator.push<AvesEntry>(
context,
MaterialPageRoute(
builder: (_) => CollectionPage(
pickMode: true,
onPick: (entry) => Navigator.pop(context, entry),
),
),
);
}
// ============================================================
// ELIMINA ALBUM
// ============================================================
static Future<void> deleteAlbum(
BuildContext context,
AlbumController controller,
AlbumRow album,
) async {
final ok = await showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog(
backgroundColor: Colors.grey.shade900,
title: const Text('Elimina album', style: TextStyle(color: Colors.white)),
content: Text('Vuoi eliminare l\'album "${album.displayName}"?'),
actions: [
TextButton(
child: const Text('Annulla'),
onPressed: () => Navigator.pop(context, false),
),
TextButton(
child: const Text('Elimina'),
onPressed: () => Navigator.pop(context, true),
),
],
);
},
);
if (ok == true) {
await controller.deleteAlbum(album);
}
}
// ============================================================
// SHARE ALBUM
// ============================================================
static Future<void> shareAlbum(AlbumRow album) async {
await shareService.shareText(album.path);
}
// ============================================================
// INFO ALBUM
// ============================================================
static Future<void> showInfo(BuildContext context, AlbumRow album) async {
showDialog<void>(
context: context,
builder: (context) {
return AlertDialog(
backgroundColor: Colors.grey.shade900,
title: Text(album.displayName, style: const TextStyle(color: Colors.white)),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Percorso: ${album.path}', style: const TextStyle(color: Colors.white70)),
Text('Elementi: ${album.fileCount}', style: const TextStyle(color: Colors.white70)),
Text('Dimensione: ${_formatSize(album.totalSize)}', style: const TextStyle(color: Colors.white70)),
Text('Remoto: ${album.isRemote}', style: const TextStyle(color: Colors.white70)),
Text('Vault: ${album.isVault}', style: const TextStyle(color: Colors.white70)),
Text('Hybrid: ${album.hybridType}', style: const TextStyle(color: Colors.white70)),
Text('Pinned: ${album.priority > 0}', style: const TextStyle(color: Colors.white70)),
Text('Hidden: ${album.hidden}', style: const TextStyle(color: Colors.white70)),
],
),
actions: [
TextButton(
child: const Text('OK'),
onPressed: () => Navigator.pop(context),
),
],
);
},
);
}
// ============================================================
// APRI IN FILE MANAGER
// ============================================================
static Future<void> openInFileManager(AlbumRow album) async {
await deviceService.openFile(album.path);
}
// ============================================================
// UTILS
// ============================================================
static String _formatSize(int bytes) {
if (bytes < 1024) return '$bytes B';
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)} KB';
if (bytes < 1024 * 1024 * 1024) return '${(bytes / 1024 / 1024).toStringAsFixed(1)} MB';
return '${(bytes / 1024 / 1024 / 1024).toStringAsFixed(1)} GB';
}
}