307 lines
9.7 KiB
Dart
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';
|
|
}
|
|
}
|