diff options
Diffstat (limited to 'player-android/lib/screens/media_detail_screen.dart')
| -rw-r--r-- | player-android/lib/screens/media_detail_screen.dart | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/player-android/lib/screens/media_detail_screen.dart b/player-android/lib/screens/media_detail_screen.dart index bee0d0e..b4d7e1f 100644 --- a/player-android/lib/screens/media_detail_screen.dart +++ b/player-android/lib/screens/media_detail_screen.dart @@ -157,6 +157,20 @@ class _MediaDetailScreenState extends ConsumerState<MediaDetailScreen> { } // --------------------------------------------------------------------------- + // Notes navigation + // --------------------------------------------------------------------------- + + /// Navigates to [NotesEditorScreen] for the current media item. + /// + /// Uses [AppRoutes.notesPath] so the routing logic stays in one place + /// (Open-Closed: no URL construction scattered across the screen). + void _openNotes() { + final media = _media; + if (media == null) return; + context.go(AppRoutes.notesPath(media.id.toString())); + } + + // --------------------------------------------------------------------------- // Share // --------------------------------------------------------------------------- @@ -230,12 +244,11 @@ class _MediaDetailScreenState extends ConsumerState<MediaDetailScreen> { /// Builds the app bar with title and a three-dot overflow menu. /// - /// The overflow menu currently contains a single "Share" action that opens - /// [showCreateShareDialog]. Using a [PopupMenuButton] rather than a plain - /// [IconButton] keeps the pattern open for future menu items without layout + /// The overflow menu contains "Notes" and "Share" actions. Using a + /// [PopupMenuButton] keeps the pattern open for future items without layout /// changes. The [onSelected] callback uses a [Map]-based dispatch so adding /// a new action requires only a new enum value and one map entry — no - /// if/else chain to extend (Open-Closed Principle). The Share action is + /// if/else chain to extend (Open-Closed Principle). All actions are /// disabled while media is still loading (null) to prevent calling the API /// with a stale ID. AppBar _buildAppBar() { @@ -249,12 +262,24 @@ class _MediaDetailScreenState extends ConsumerState<MediaDetailScreen> { // enum value, a handler method, and one entry here — no if/else // chain to extend (Open-Closed Principle). final handlers = <_MenuAction, VoidCallback>{ + _MenuAction.notes: _openNotes, _MenuAction.share: _share, }; handlers[action]?.call(); }, itemBuilder: (_) => [ PopupMenuItem<_MenuAction>( + key: const Key('media_detail_notes_menu_item'), + // Disable the item until media has loaded so the mediaId is valid. + enabled: _media != null, + value: _MenuAction.notes, + child: const ListTile( + leading: Icon(Icons.notes_outlined), + title: Text('Notes'), + contentPadding: EdgeInsets.zero, + ), + ), + PopupMenuItem<_MenuAction>( key: const Key('media_detail_share_menu_item'), // Disable the item until media has loaded so the mediaId is valid. enabled: _media != null, @@ -318,7 +343,7 @@ class _MediaDetailScreenState extends ConsumerState<MediaDetailScreen> { /// Using a typed enum (rather than raw strings) makes [PopupMenuButton] type /// safe and avoids stringly-typed comparisons in [onSelected] (type safety / /// Open-Closed: add new actions here without touching the menu-builder switch). -enum _MenuAction { share } +enum _MenuAction { notes, share } // --------------------------------------------------------------------------- // _MediaDetailContent |
