From cf270a36ff16c8addc98e0d1127f219f94b2a722 Mon Sep 17 00:00:00 2001 From: zarzet Date: Fri, 26 Jun 2026 18:35:41 +0700 Subject: [PATCH] feat(library): add rename action to playlist folder screen Add an edit button in the playlist folder app bar that opens a rename dialog with validation, calling renamePlaylist on the collections provider. --- lib/screens/library_tracks_folder_screen.dart | 88 ++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/lib/screens/library_tracks_folder_screen.dart b/lib/screens/library_tracks_folder_screen.dart index 47acea8a..7a4d3f54 100644 --- a/lib/screens/library_tracks_folder_screen.dart +++ b/lib/screens/library_tracks_folder_screen.dart @@ -639,7 +639,27 @@ class _LibraryTracksFolderScreenState ), ), actions: [ - if (isPlaylistMode && !_isSelectionMode) + if (isPlaylistMode && !_isSelectionMode) ...[ + IconButton( + tooltip: context.l10n.collectionRenamePlaylist, + icon: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.black.withValues(alpha: 0.4), + shape: BoxShape.circle, + ), + child: const Icon( + Icons.edit_outlined, + color: Colors.white, + size: 20, + ), + ), + onPressed: () { + final id = widget.playlistId ?? playlist?.id; + if (id == null || id.isEmpty) return; + _showRenamePlaylistDialog(context, id, playlist?.name ?? title); + }, + ), IconButton( icon: Container( padding: const EdgeInsets.all(8), @@ -655,6 +675,7 @@ class _LibraryTracksFolderScreenState ), onPressed: () => _showCoverOptionsSheet(context, hasCustomCover), ), + ], ], flexibleSpace: LayoutBuilder( builder: (context, constraints) { @@ -1073,6 +1094,71 @@ class _LibraryTracksFolderScreenState ), ); } + + Future _showRenamePlaylistDialog( + BuildContext context, + String playlistId, + String currentName, + ) async { + final controller = TextEditingController(text: currentName); + final formKey = GlobalKey(); + + final nextName = await showDialog( + context: context, + builder: (dialogContext) { + return AlertDialog( + title: Text(dialogContext.l10n.collectionRenamePlaylist), + content: Form( + key: formKey, + child: TextFormField( + controller: controller, + autofocus: true, + decoration: InputDecoration( + hintText: dialogContext.l10n.collectionPlaylistNameHint, + ), + validator: (value) { + final trimmed = value?.trim() ?? ''; + if (trimmed.isEmpty) { + return dialogContext.l10n.collectionPlaylistNameRequired; + } + return null; + }, + onFieldSubmitted: (_) { + if (formKey.currentState?.validate() != true) return; + Navigator.of(dialogContext).pop(controller.text.trim()); + }, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(dialogContext).pop(), + child: Text(dialogContext.l10n.dialogCancel), + ), + FilledButton( + onPressed: () { + if (formKey.currentState?.validate() != true) return; + Navigator.of(dialogContext).pop(controller.text.trim()); + }, + child: Text(dialogContext.l10n.dialogSave), + ), + ], + ); + }, + ); + + if (nextName == null || nextName.trim().isEmpty || !context.mounted) { + return; + } + + await ref + .read(libraryCollectionsProvider.notifier) + .renamePlaylist(playlistId, nextName.trim()); + + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(context.l10n.collectionPlaylistRenamed)), + ); + } } class _CollectionTrackTile extends ConsumerWidget {