From 2ebb920faa1d4c30b3b31d8580f0ef932afad805 Mon Sep 17 00:00:00 2001 From: AmanRajSinghMourya Date: Fri, 29 Aug 2025 20:20:49 +0530 Subject: [PATCH] Show leave collection options --- .../ui/components/collection_row_widget.dart | 121 +++++++++++------ .../locker/lib/ui/pages/collection_page.dart | 126 +++++++++++++----- 2 files changed, 173 insertions(+), 74 deletions(-) diff --git a/mobile/apps/locker/lib/ui/components/collection_row_widget.dart b/mobile/apps/locker/lib/ui/components/collection_row_widget.dart index 4f5aab38ed..5fb2f1c857 100644 --- a/mobile/apps/locker/lib/ui/components/collection_row_widget.dart +++ b/mobile/apps/locker/lib/ui/components/collection_row_widget.dart @@ -1,8 +1,11 @@ - +import "package:ente_events/event_bus.dart"; import "package:ente_ui/theme/ente_theme.dart"; import "package:flutter/material.dart"; +import "package:locker/events/collections_updated_event.dart"; import "package:locker/l10n/l10n.dart"; import "package:locker/services/collections/models/collection.dart"; +import "package:locker/services/collections/models/collection_view_type.dart"; +import "package:locker/services/configuration.dart"; import "package:locker/ui/components/item_list_view.dart"; import "package:locker/ui/pages/collection_page.dart"; import "package:locker/utils/collection_actions.dart"; @@ -34,7 +37,7 @@ class CollectionRowWidget extends StatelessWidget { ? null : Border( bottom: BorderSide( - color: Theme.of(context).dividerColor.withOpacity(0.3), + color: Theme.of(context).dividerColor.withAlpha(30), width: 0.5, ), ), @@ -87,45 +90,7 @@ class CollectionRowWidget extends StatelessWidget { size: 20, ), itemBuilder: (BuildContext context) { - if (overflowActions != null && overflowActions!.isNotEmpty) { - return overflowActions! - .map( - (action) => PopupMenuItem( - value: action.id, - child: Row( - children: [ - Icon(action.icon, size: 16), - const SizedBox(width: 8), - Text(action.label), - ], - ), - ), - ) - .toList(); - } else { - return [ - PopupMenuItem( - value: 'edit', - child: Row( - children: [ - const Icon(Icons.edit, size: 16), - const SizedBox(width: 8), - Text(context.l10n.edit), - ], - ), - ), - PopupMenuItem( - value: 'delete', - child: Row( - children: [ - const Icon(Icons.delete, size: 16), - const SizedBox(width: 8), - Text(context.l10n.delete), - ], - ), - ), - ]; - } + return _buildPopupMenuItems(context); }, ), ], @@ -134,6 +99,67 @@ class CollectionRowWidget extends StatelessWidget { ); } + List> _buildPopupMenuItems(BuildContext context) { + final collectionViewType = + getCollectionViewType(collection, Configuration.instance.getUserID()!); + if (overflowActions != null && overflowActions!.isNotEmpty) { + return overflowActions! + .map( + (action) => PopupMenuItem( + value: action.id, + child: Row( + children: [ + Icon(action.icon, size: 16), + const SizedBox(width: 8), + Text(action.label), + ], + ), + ), + ) + .toList(); + } else { + return [ + if (collectionViewType == CollectionViewType.ownedCollection || + collectionViewType == CollectionViewType.hiddenOwnedCollection || + collectionViewType == CollectionViewType.quickLink) + PopupMenuItem( + value: 'edit', + child: Row( + children: [ + const Icon(Icons.edit, size: 16), + const SizedBox(width: 8), + Text(context.l10n.edit), + ], + ), + ), + if (collectionViewType == CollectionViewType.ownedCollection || + collectionViewType == CollectionViewType.hiddenOwnedCollection || + collectionViewType == CollectionViewType.quickLink) + PopupMenuItem( + value: 'delete', + child: Row( + children: [ + const Icon(Icons.delete, size: 16), + const SizedBox(width: 8), + Text(context.l10n.delete), + ], + ), + ), + if (collectionViewType == CollectionViewType.sharedCollection) + PopupMenuItem( + value: 'leave_collection', + child: Row( + children: [ + const Icon(Icons.logout), + const SizedBox(width: 12), + Text(context.l10n.leaveCollection), + ], + ), + ), + ]; + } + } + void _handleMenuAction(BuildContext context, String action) { if (overflowActions != null && overflowActions!.isNotEmpty) { final customAction = overflowActions!.firstWhere( @@ -149,6 +175,9 @@ class CollectionRowWidget extends StatelessWidget { case 'delete': _deleteCollection(context); break; + case 'leave_collection': + _leaveCollection(context); + break; } } } @@ -168,4 +197,14 @@ class CollectionRowWidget extends StatelessWidget { ), ); } + + Future _leaveCollection(BuildContext context) async { + await CollectionActions.leaveCollection( + context, + collection, + onSuccess: () { + Bus.instance.fire(CollectionsUpdatedEvent()); + }, + ); + } } diff --git a/mobile/apps/locker/lib/ui/pages/collection_page.dart b/mobile/apps/locker/lib/ui/pages/collection_page.dart index 907bff93a1..65204e88cc 100644 --- a/mobile/apps/locker/lib/ui/pages/collection_page.dart +++ b/mobile/apps/locker/lib/ui/pages/collection_page.dart @@ -38,12 +38,15 @@ class CollectionPage extends UploaderPage { class _CollectionPageState extends UploaderPageState with SearchMixin { final _logger = Logger("CollectionPage"); + late StreamSubscription + _collectionUpdateSubscription; late Collection _collection; List _files = []; List _filteredFiles = []; late CollectionViewType collectionViewType; bool isQuickLink = false; + bool showFAB = true; @override void onFileUploadComplete() { @@ -82,6 +85,12 @@ class _CollectionPageState extends UploaderPageState } } + @override + void dispose() { + _collectionUpdateSubscription.cancel(); + super.dispose(); + } + List get _displayedFiles => isSearchActive ? _filteredFiles : _files; @@ -89,18 +98,40 @@ class _CollectionPageState extends UploaderPageState void initState() { super.initState(); _initializeData(widget.collection); - Bus.instance.on().listen((event) async { - final collection = (await CollectionService.instance.getCollections()) - .where( - (c) => c.id == widget.collection.id, - ) - .first; - await _initializeData(collection); + _collectionUpdateSubscription = + Bus.instance.on().listen((event) async { + if (!mounted) return; + + try { + final collections = await CollectionService.instance.getCollections(); + + final matchingCollection = collections.where( + (c) => c.id == widget.collection.id, + ); + + if (matchingCollection.isNotEmpty) { + await _initializeData(matchingCollection.first); + } else { + _logger.warning( + 'Collection ${widget.collection.id} no longer exists, navigating back', + ); + if (mounted) { + Navigator.of(context).pop(); + } + } + } catch (e) { + _logger.severe('Error updating collection: $e'); + } }); + collectionViewType = getCollectionViewType( _collection, Configuration.instance.getUserID()!, ); + + showFAB = collectionViewType == CollectionViewType.ownedCollection || + collectionViewType == CollectionViewType.hiddenOwnedCollection || + collectionViewType == CollectionViewType.quickLink; } Future _initializeData(Collection collection) async { @@ -167,6 +198,13 @@ class _CollectionPageState extends UploaderPageState } } + Future _leaveCollection() async { + await CollectionActions.leaveCollection( + context, + _collection, + ); + } + @override Widget build(BuildContext context) { return KeyboardListener( @@ -218,33 +256,53 @@ class _CollectionPageState extends UploaderPageState case 'delete': _deleteCollection(); break; + case 'leave_collection': + _leaveCollection(); + break; } }, itemBuilder: (BuildContext context) { return [ - PopupMenuItem( - value: 'edit', - child: Row( - children: [ - const Icon(Icons.edit), - const SizedBox(width: 12), - Text(context.l10n.edit), - ], + if (collectionViewType == CollectionViewType.ownedCollection || + collectionViewType == CollectionViewType.hiddenOwnedCollection || + collectionViewType == CollectionViewType.quickLink) + PopupMenuItem( + value: 'edit', + child: Row( + children: [ + const Icon(Icons.edit), + const SizedBox(width: 12), + Text(context.l10n.edit), + ], + ), ), - ), - PopupMenuItem( - value: 'delete', - child: Row( - children: [ - const Icon(Icons.delete, color: Colors.red), - const SizedBox(width: 12), - Text( - context.l10n.delete, - style: const TextStyle(color: Colors.red), - ), - ], + if (collectionViewType == CollectionViewType.ownedCollection || + collectionViewType == CollectionViewType.hiddenOwnedCollection || + collectionViewType == CollectionViewType.quickLink) + PopupMenuItem( + value: 'delete', + child: Row( + children: [ + const Icon(Icons.delete, color: Colors.red), + const SizedBox(width: 12), + Text( + context.l10n.delete, + style: const TextStyle(color: Colors.red), + ), + ], + ), + ), + if (collectionViewType == CollectionViewType.sharedCollection) + PopupMenuItem( + value: 'leave_collection', + child: Row( + children: [ + const Icon(Icons.logout), + const SizedBox(width: 12), + Text(context.l10n.leaveCollection), + ], + ), ), - ), ]; }, ); @@ -329,10 +387,12 @@ class _CollectionPageState extends UploaderPageState } Widget _buildFAB() { - return FloatingActionButton( - onPressed: addFile, - tooltip: context.l10n.addFiles, - child: const Icon(Icons.add), - ); + return showFAB + ? FloatingActionButton( + onPressed: addFile, + tooltip: context.l10n.addFiles, + child: const Icon(Icons.add), + ) + : const SizedBox.shrink(); } }