@@ -21,12 +21,34 @@ import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_shee
2121
2222enum AddToMenuItem { album, archive, unarchive, lockedFolder }
2323
24- class AddActionButton extends ConsumerWidget {
24+ class AddActionButton extends ConsumerStatefulWidget {
2525 const AddActionButton ({super .key});
2626
27- Future <void > _showAddOptions (BuildContext context, WidgetRef ref) async {
27+ @override
28+ ConsumerState <AddActionButton > createState () => _AddActionButtonState ();
29+ }
30+
31+ class _AddActionButtonState extends ConsumerState <AddActionButton > {
32+ void _handleMenuSelection (AddToMenuItem selected) {
33+ switch (selected) {
34+ case AddToMenuItem .album:
35+ _openAlbumSelector ();
36+ break ;
37+ case AddToMenuItem .archive:
38+ performArchiveAction (context, ref, source: ActionSource .viewer);
39+ break ;
40+ case AddToMenuItem .unarchive:
41+ performUnArchiveAction (context, ref, source: ActionSource .viewer);
42+ break ;
43+ case AddToMenuItem .lockedFolder:
44+ performMoveToLockFolderAction (context, ref, source: ActionSource .viewer);
45+ break ;
46+ }
47+ }
48+
49+ List <Widget > _buildMenuChildren () {
2850 final asset = ref.read (currentAssetNotifier);
29- if (asset == null ) return ;
51+ if (asset == null ) return [] ;
3052
3153 final user = ref.read (currentUserProvider);
3254 final isOwner = asset is RemoteAsset && asset.ownerId == user? .id;
@@ -35,93 +57,57 @@ class AddActionButton extends ConsumerWidget {
3557 final hasRemote = asset is RemoteAsset ;
3658 final showArchive = isOwner && ! isInLockedView && hasRemote && ! isArchived;
3759 final showUnarchive = isOwner && ! isInLockedView && hasRemote && isArchived;
38- final menuItemHeight = 30.0 ;
39-
40- final List <PopupMenuEntry <AddToMenuItem >> items = [
41- PopupMenuItem (
42- enabled: false ,
43- textStyle: context.textTheme.labelMedium,
44- height: 40 ,
45- child: Text ("add_to_bottom_bar" .tr ()),
60+
61+ return [
62+ Padding (
63+ padding: const EdgeInsets .symmetric (horizontal: 16 , vertical: 8 ),
64+ child: Text ("add_to_bottom_bar" .tr (), style: context.textTheme.labelMedium),
4665 ),
47- PopupMenuItem (
48- height: menuItemHeight,
49- value: AddToMenuItem .album,
50- child: ListTile (leading: const Icon (Icons .photo_album_outlined), title: Text ("album" .tr ())),
66+ BaseActionButton (
67+ iconData: Icons .photo_album_outlined,
68+ label: "album" .tr (),
69+ menuItem: true ,
70+ onPressed: () => _handleMenuSelection (AddToMenuItem .album),
5171 ),
52- const PopupMenuDivider (),
53- PopupMenuItem (enabled: false , textStyle: context.textTheme.labelMedium, height: 40 , child: Text ("move_to" .tr ())),
72+
5473 if (isOwner) ...[
74+ const PopupMenuDivider (),
75+ Padding (
76+ padding: const EdgeInsets .symmetric (horizontal: 16 , vertical: 8 ),
77+ child: Text ("move_to" .tr (), style: context.textTheme.labelMedium),
78+ ),
5579 if (showArchive)
56- PopupMenuItem (
57- height: menuItemHeight,
58- value: AddToMenuItem .archive,
59- child: ListTile (leading: const Icon (Icons .archive_outlined), title: Text ("archive" .tr ())),
80+ BaseActionButton (
81+ iconData: Icons .archive_outlined,
82+ label: "archive" .tr (),
83+ menuItem: true ,
84+ onPressed: () => _handleMenuSelection (AddToMenuItem .archive),
6085 ),
6186 if (showUnarchive)
62- PopupMenuItem (
63- height: menuItemHeight,
64- value: AddToMenuItem .unarchive,
65- child: ListTile (leading: const Icon (Icons .unarchive_outlined), title: Text ("unarchive" .tr ())),
87+ BaseActionButton (
88+ iconData: Icons .unarchive_outlined,
89+ label: "unarchive" .tr (),
90+ menuItem: true ,
91+ onPressed: () => _handleMenuSelection (AddToMenuItem .unarchive),
6692 ),
67- PopupMenuItem (
68- height: menuItemHeight,
69- value: AddToMenuItem .lockedFolder,
70- child: ListTile (leading: const Icon (Icons .lock_outline), title: Text ("locked_folder" .tr ())),
93+ BaseActionButton (
94+ iconData: Icons .lock_outline,
95+ label: "locked_folder" .tr (),
96+ menuItem: true ,
97+ onPressed: () => _handleMenuSelection (AddToMenuItem .lockedFolder),
7198 ),
7299 ],
73100 ];
74-
75- final AddToMenuItem ? selected = await showMenu <AddToMenuItem >(
76- context: context,
77- color: context.themeData.scaffoldBackgroundColor,
78- position: _menuPosition (context),
79- items: items,
80- popUpAnimationStyle: AnimationStyle .noAnimation,
81- );
82-
83- if (selected == null ) {
84- return ;
85- }
86-
87- switch (selected) {
88- case AddToMenuItem .album:
89- _openAlbumSelector (context, ref);
90- break ;
91- case AddToMenuItem .archive:
92- await performArchiveAction (context, ref, source: ActionSource .viewer);
93- break ;
94- case AddToMenuItem .unarchive:
95- await performUnArchiveAction (context, ref, source: ActionSource .viewer);
96- break ;
97- case AddToMenuItem .lockedFolder:
98- await performMoveToLockFolderAction (context, ref, source: ActionSource .viewer);
99- break ;
100- }
101101 }
102102
103- RelativeRect _menuPosition (BuildContext context) {
104- final renderObject = context.findRenderObject ();
105- if (renderObject is ! RenderBox ) {
106- return RelativeRect .fill;
107- }
108-
109- final size = renderObject.size;
110- final position = renderObject.localToGlobal (Offset .zero);
111-
112- return RelativeRect .fromLTRB (position.dx, position.dy - size.height - 200 , position.dx + size.width, position.dy);
113- }
114-
115- void _openAlbumSelector (BuildContext context, WidgetRef ref) {
103+ void _openAlbumSelector () {
116104 final currentAsset = ref.read (currentAssetNotifier);
117105 if (currentAsset == null ) {
118106 ImmichToast .show (context: context, msg: "Cannot load asset information." , toastType: ToastType .error);
119107 return ;
120108 }
121109
122- final List <Widget > slivers = [
123- AlbumSelector (onAlbumSelected: (album) => _addCurrentAssetToAlbum (context, ref, album)),
124- ];
110+ final List <Widget > slivers = [AlbumSelector (onAlbumSelected: (album) => _addCurrentAssetToAlbum (album))];
125111
126112 showModalBottomSheet (
127113 context: context,
@@ -141,7 +127,7 @@ class AddActionButton extends ConsumerWidget {
141127 );
142128 }
143129
144- Future <void > _addCurrentAssetToAlbum (BuildContext context, WidgetRef ref, RemoteAlbum album) async {
130+ Future <void > _addCurrentAssetToAlbum (RemoteAlbum album) async {
145131 final latest = ref.read (currentAssetNotifier);
146132
147133 if (latest == null ) {
@@ -174,17 +160,27 @@ class AddActionButton extends ConsumerWidget {
174160 }
175161
176162 @override
177- Widget build (BuildContext context, WidgetRef ref ) {
163+ Widget build (BuildContext context) {
178164 final asset = ref.watch (currentAssetNotifier);
179165 if (asset == null ) {
180166 return const SizedBox .shrink ();
181167 }
182- return Builder (
183- builder: (buttonContext) {
168+
169+ return MenuAnchor (
170+ consumeOutsideTap: true ,
171+ style: MenuStyle (
172+ backgroundColor: WidgetStatePropertyAll (context.themeData.scaffoldBackgroundColor),
173+ elevation: const WidgetStatePropertyAll (4 ),
174+ shape: const WidgetStatePropertyAll (
175+ RoundedRectangleBorder (borderRadius: BorderRadius .all (Radius .circular (12 ))),
176+ ),
177+ ),
178+ menuChildren: _buildMenuChildren (),
179+ builder: (context, controller, child) {
184180 return BaseActionButton (
185181 iconData: Icons .add,
186182 label: "add_to_bottom_bar" .tr (),
187- onPressed: () => _showAddOptions (buttonContext, ref ),
183+ onPressed: () => controller.isOpen ? controller. close () : controller. open ( ),
188184 );
189185 },
190186 );
0 commit comments