2020-05-05 12:56:24 +00:00
|
|
|
import 'dart:async';
|
2022-11-24 10:54:59 +00:00
|
|
|
import 'dart:io';
|
2023-06-30 06:08:53 +00:00
|
|
|
import 'dart:math' as math;
|
2021-09-15 11:22:58 +00:00
|
|
|
|
2023-06-30 06:08:53 +00:00
|
|
|
import "package:flutter/cupertino.dart";
|
2020-04-18 18:46:38 +00:00
|
|
|
import 'package:flutter/material.dart';
|
2020-10-30 19:57:14 +00:00
|
|
|
import 'package:logging/logging.dart';
|
2020-05-30 21:15:21 +00:00
|
|
|
import 'package:photos/core/configuration.dart';
|
2020-11-15 07:19:44 +00:00
|
|
|
import 'package:photos/core/event_bus.dart';
|
2023-06-05 03:40:25 +00:00
|
|
|
import "package:photos/db/files_db.dart";
|
2021-02-02 16:35:38 +00:00
|
|
|
import 'package:photos/events/subscription_purchased_event.dart';
|
2023-04-07 05:06:43 +00:00
|
|
|
import "package:photos/generated/l10n.dart";
|
2022-11-24 10:54:59 +00:00
|
|
|
import 'package:photos/models/backup_status.dart';
|
2020-10-29 12:56:30 +00:00
|
|
|
import 'package:photos/models/collection.dart';
|
2022-09-06 16:49:02 +00:00
|
|
|
import 'package:photos/models/device_collection.dart';
|
2022-07-03 10:09:01 +00:00
|
|
|
import 'package:photos/models/gallery_type.dart';
|
2023-05-25 05:51:56 +00:00
|
|
|
import "package:photos/models/metadata/common_keys.dart";
|
2020-07-15 20:29:29 +00:00
|
|
|
import 'package:photos/models/selected_files.dart';
|
2020-10-13 05:22:20 +00:00
|
|
|
import 'package:photos/services/collections_service.dart';
|
2022-11-24 10:54:59 +00:00
|
|
|
import 'package:photos/services/sync_service.dart';
|
2022-12-07 08:41:52 +00:00
|
|
|
import 'package:photos/services/update_service.dart';
|
2023-01-12 10:13:11 +00:00
|
|
|
import 'package:photos/ui/actions/collection/collection_sharing_actions.dart';
|
2023-01-31 11:24:09 +00:00
|
|
|
import 'package:photos/ui/components/action_sheet_widget.dart';
|
2023-03-10 08:08:51 +00:00
|
|
|
import 'package:photos/ui/components/buttons/button_widget.dart';
|
2022-12-29 13:52:04 +00:00
|
|
|
import 'package:photos/ui/components/models/button_type.dart';
|
2023-06-15 12:45:26 +00:00
|
|
|
import "package:photos/ui/map/enable_map.dart";
|
2023-06-05 03:40:25 +00:00
|
|
|
import "package:photos/ui/map/map_screen.dart";
|
2022-12-08 13:40:27 +00:00
|
|
|
import 'package:photos/ui/sharing/album_participants_page.dart';
|
2023-08-04 08:35:27 +00:00
|
|
|
import "package:photos/ui/sharing/manage_links_widget.dart";
|
2022-11-20 11:55:12 +00:00
|
|
|
import 'package:photos/ui/sharing/share_collection_page.dart';
|
2022-11-24 10:54:59 +00:00
|
|
|
import 'package:photos/ui/tools/free_space_page.dart';
|
2023-06-27 09:15:25 +00:00
|
|
|
import "package:photos/ui/viewer/gallery/hooks/add_photos_sheet.dart";
|
|
|
|
import 'package:photos/ui/viewer/gallery/hooks/pick_cover_photo.dart';
|
2022-11-24 10:54:59 +00:00
|
|
|
import 'package:photos/utils/data_util.dart';
|
2020-07-15 19:14:37 +00:00
|
|
|
import 'package:photos/utils/dialog_util.dart';
|
2021-10-30 05:43:56 +00:00
|
|
|
import 'package:photos/utils/magic_util.dart';
|
2022-11-20 04:33:24 +00:00
|
|
|
import 'package:photos/utils/navigation_util.dart';
|
2022-09-13 06:44:10 +00:00
|
|
|
import 'package:photos/utils/toast_util.dart';
|
2020-04-18 18:46:38 +00:00
|
|
|
|
2021-05-02 11:19:05 +00:00
|
|
|
class GalleryAppBarWidget extends StatefulWidget {
|
2022-05-08 04:34:55 +00:00
|
|
|
final GalleryType type;
|
2022-12-30 12:10:17 +00:00
|
|
|
final String? title;
|
2020-07-15 20:29:29 +00:00
|
|
|
final SelectedFiles selectedFiles;
|
2022-12-30 12:10:17 +00:00
|
|
|
final DeviceCollection? deviceCollection;
|
|
|
|
final Collection? collection;
|
2020-04-18 18:46:38 +00:00
|
|
|
|
2022-07-04 08:43:01 +00:00
|
|
|
const GalleryAppBarWidget(
|
2020-07-15 17:17:53 +00:00
|
|
|
this.type,
|
2020-07-15 20:29:29 +00:00
|
|
|
this.title,
|
2020-10-29 12:56:30 +00:00
|
|
|
this.selectedFiles, {
|
2022-12-30 12:10:17 +00:00
|
|
|
Key? key,
|
2022-08-31 18:39:39 +00:00
|
|
|
this.deviceCollection,
|
2020-10-29 12:56:30 +00:00
|
|
|
this.collection,
|
2022-07-03 07:47:15 +00:00
|
|
|
}) : super(key: key);
|
2020-04-18 18:46:38 +00:00
|
|
|
|
|
|
|
@override
|
2022-07-03 09:45:00 +00:00
|
|
|
State<GalleryAppBarWidget> createState() => _GalleryAppBarWidgetState();
|
2020-04-18 18:46:38 +00:00
|
|
|
}
|
|
|
|
|
2023-06-22 10:00:27 +00:00
|
|
|
enum AlbumPopupAction {
|
|
|
|
rename,
|
|
|
|
delete,
|
|
|
|
map,
|
|
|
|
ownedArchive,
|
|
|
|
sharedArchive,
|
2023-08-10 06:38:04 +00:00
|
|
|
ownedHide,
|
2023-06-22 10:00:27 +00:00
|
|
|
sort,
|
|
|
|
leave,
|
2023-06-22 10:10:21 +00:00
|
|
|
freeUpSpace,
|
|
|
|
setCover,
|
2023-06-27 08:34:58 +00:00
|
|
|
addPhotos,
|
2023-06-30 04:31:15 +00:00
|
|
|
pinAlbum,
|
2023-08-04 07:41:23 +00:00
|
|
|
removeLink,
|
2023-06-22 10:00:27 +00:00
|
|
|
}
|
|
|
|
|
2020-04-18 18:46:38 +00:00
|
|
|
class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
2020-10-30 19:57:14 +00:00
|
|
|
final _logger = Logger("GalleryAppBar");
|
2022-12-30 12:10:17 +00:00
|
|
|
late StreamSubscription _userAuthEventSubscription;
|
|
|
|
late Function() _selectedFilesListener;
|
|
|
|
String? _appBarTitle;
|
2023-01-12 10:13:11 +00:00
|
|
|
late CollectionActions collectionActions;
|
2022-04-22 16:05:30 +00:00
|
|
|
final GlobalKey shareButtonKey = GlobalKey();
|
2023-08-04 07:41:23 +00:00
|
|
|
bool isQuickLink = false;
|
|
|
|
late GalleryType galleryType;
|
2022-10-11 01:35:09 +00:00
|
|
|
|
2020-04-30 15:09:41 +00:00
|
|
|
@override
|
|
|
|
void initState() {
|
2023-08-04 07:41:23 +00:00
|
|
|
super.initState();
|
2021-01-08 16:40:03 +00:00
|
|
|
_selectedFilesListener = () {
|
2020-07-15 20:29:29 +00:00
|
|
|
setState(() {});
|
2021-01-08 16:40:03 +00:00
|
|
|
};
|
2023-01-12 10:13:11 +00:00
|
|
|
collectionActions = CollectionActions(CollectionsService.instance);
|
2021-01-08 16:40:03 +00:00
|
|
|
widget.selectedFiles.addListener(_selectedFilesListener);
|
2022-07-03 09:49:33 +00:00
|
|
|
_userAuthEventSubscription =
|
|
|
|
Bus.instance.on<SubscriptionPurchasedEvent>().listen((event) {
|
2020-11-15 07:19:44 +00:00
|
|
|
setState(() {});
|
|
|
|
});
|
2021-09-23 10:41:48 +00:00
|
|
|
_appBarTitle = widget.title;
|
2023-08-04 07:41:23 +00:00
|
|
|
galleryType = widget.type;
|
2020-04-30 15:09:41 +00:00
|
|
|
}
|
|
|
|
|
2020-11-15 07:19:44 +00:00
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
_userAuthEventSubscription.cancel();
|
2021-01-08 16:40:03 +00:00
|
|
|
widget.selectedFiles.removeListener(_selectedFilesListener);
|
2020-11-15 07:19:44 +00:00
|
|
|
super.dispose();
|
|
|
|
}
|
|
|
|
|
2020-04-18 18:46:38 +00:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2023-08-04 07:41:23 +00:00
|
|
|
return galleryType == GalleryType.homepage
|
2022-10-12 08:26:37 +00:00
|
|
|
? const SizedBox.shrink()
|
|
|
|
: AppBar(
|
2023-08-04 07:41:23 +00:00
|
|
|
backgroundColor: galleryType == GalleryType.homepage
|
2022-10-12 08:26:37 +00:00
|
|
|
? const Color(0x00000000)
|
|
|
|
: null,
|
|
|
|
elevation: 0,
|
|
|
|
centerTitle: false,
|
2023-08-04 07:41:23 +00:00
|
|
|
title: galleryType == GalleryType.homepage
|
2022-10-12 08:26:37 +00:00
|
|
|
? const SizedBox.shrink()
|
|
|
|
: TextButton(
|
|
|
|
child: Text(
|
2022-12-30 12:10:17 +00:00
|
|
|
_appBarTitle!,
|
2022-10-12 08:26:37 +00:00
|
|
|
style: Theme.of(context)
|
|
|
|
.textTheme
|
2023-06-13 06:41:31 +00:00
|
|
|
.headlineSmall!
|
2022-10-12 08:26:37 +00:00
|
|
|
.copyWith(fontSize: 16),
|
|
|
|
),
|
|
|
|
onPressed: () => _renameAlbum(context),
|
|
|
|
),
|
|
|
|
actions: _getDefaultActions(context),
|
|
|
|
);
|
2020-04-18 18:46:38 +00:00
|
|
|
}
|
|
|
|
|
2021-09-22 14:17:45 +00:00
|
|
|
Future<dynamic> _renameAlbum(BuildContext context) async {
|
2023-08-04 07:41:23 +00:00
|
|
|
if (galleryType != GalleryType.ownedCollection &&
|
|
|
|
galleryType != GalleryType.quickLink) {
|
|
|
|
showToast(
|
|
|
|
context,
|
|
|
|
'Type of galler $galleryType is not supported for '
|
|
|
|
'rename',
|
|
|
|
);
|
2021-09-22 14:17:45 +00:00
|
|
|
return;
|
|
|
|
}
|
2023-02-07 05:28:57 +00:00
|
|
|
final result = await showTextInputDialog(
|
2023-02-07 03:14:11 +00:00
|
|
|
context,
|
2023-08-04 07:59:27 +00:00
|
|
|
title: isQuickLink
|
|
|
|
? S.of(context).enterAlbumName
|
|
|
|
: S.of(context).renameAlbum,
|
|
|
|
submitButtonLabel:
|
|
|
|
isQuickLink ? S.of(context).done : S.of(context).rename,
|
2023-04-07 05:06:43 +00:00
|
|
|
hintText: S.of(context).enterAlbumName,
|
2023-02-09 04:56:06 +00:00
|
|
|
alwaysShowSuccessState: true,
|
2023-06-28 07:47:37 +00:00
|
|
|
initialValue: widget.collection?.displayName ?? "",
|
2023-02-09 05:12:40 +00:00
|
|
|
textCapitalization: TextCapitalization.words,
|
2023-02-08 05:43:46 +00:00
|
|
|
onSubmit: (String text) async {
|
2023-02-07 05:13:22 +00:00
|
|
|
// indicates user cancelled the rename request
|
|
|
|
if (text == "" || text.trim() == _appBarTitle!.trim()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
await CollectionsService.instance.rename(widget.collection!, text);
|
|
|
|
if (mounted) {
|
|
|
|
_appBarTitle = text;
|
2023-08-04 07:41:23 +00:00
|
|
|
if (isQuickLink) {
|
|
|
|
// update the gallery type to owned collection so that correct
|
|
|
|
// actions are shown
|
|
|
|
galleryType = GalleryType.ownedCollection;
|
|
|
|
}
|
2023-02-07 05:13:22 +00:00
|
|
|
setState(() {});
|
|
|
|
}
|
2023-02-09 01:13:54 +00:00
|
|
|
} catch (e, s) {
|
|
|
|
_logger.severe("Failed to rename album", e, s);
|
2023-02-07 05:28:57 +00:00
|
|
|
rethrow;
|
2023-02-07 05:13:22 +00:00
|
|
|
}
|
2021-09-22 14:27:50 +00:00
|
|
|
},
|
|
|
|
);
|
2023-02-09 01:13:54 +00:00
|
|
|
if (result is Exception) {
|
2022-12-26 11:09:29 +00:00
|
|
|
showGenericErrorDialog(context: context);
|
2021-09-22 14:17:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-11 01:35:09 +00:00
|
|
|
Future<dynamic> _leaveAlbum(BuildContext context) async {
|
2023-02-09 13:18:01 +00:00
|
|
|
final actionResult = await showActionSheet(
|
2023-01-31 11:24:09 +00:00
|
|
|
context: context,
|
|
|
|
buttons: [
|
|
|
|
ButtonWidget(
|
|
|
|
buttonType: ButtonType.critical,
|
|
|
|
isInAlert: true,
|
|
|
|
shouldStickToDarkTheme: true,
|
|
|
|
buttonAction: ButtonAction.first,
|
|
|
|
shouldSurfaceExecutionStates: true,
|
2023-04-07 05:06:43 +00:00
|
|
|
labelText: S.of(context).leaveAlbum,
|
2023-01-31 11:24:09 +00:00
|
|
|
onTap: () async {
|
|
|
|
await CollectionsService.instance.leaveAlbum(widget.collection!);
|
|
|
|
},
|
|
|
|
),
|
2023-04-07 05:06:43 +00:00
|
|
|
ButtonWidget(
|
2023-01-31 11:24:09 +00:00
|
|
|
buttonType: ButtonType.secondary,
|
|
|
|
buttonAction: ButtonAction.cancel,
|
|
|
|
isInAlert: true,
|
|
|
|
shouldStickToDarkTheme: true,
|
2023-04-07 05:06:43 +00:00
|
|
|
labelText: S.of(context).cancel,
|
2023-01-31 11:24:09 +00:00
|
|
|
)
|
|
|
|
],
|
2023-04-07 05:06:43 +00:00
|
|
|
title: S.of(context).leaveSharedAlbum,
|
|
|
|
body: S.of(context).photosAddedByYouWillBeRemovedFromTheAlbum,
|
2022-10-11 01:35:09 +00:00
|
|
|
);
|
2023-02-09 13:18:01 +00:00
|
|
|
if (actionResult?.action != null && mounted) {
|
|
|
|
if (actionResult!.action == ButtonAction.error) {
|
2023-01-31 11:24:09 +00:00
|
|
|
showGenericErrorDialog(context: context);
|
2023-02-09 13:18:01 +00:00
|
|
|
} else if (actionResult.action == ButtonAction.first) {
|
2023-01-31 11:24:09 +00:00
|
|
|
Navigator.of(context).pop();
|
|
|
|
}
|
2022-10-11 01:35:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-24 10:54:59 +00:00
|
|
|
// todo: In the new design, clicking on free up space will directly open
|
|
|
|
// the free up space page and show loading indicator while calculating
|
|
|
|
// the space which can be claimed up. This code duplication should be removed
|
|
|
|
// whenever we move to the new design for free up space.
|
2022-11-24 13:08:27 +00:00
|
|
|
Future<dynamic> _deleteBackedUpFiles(BuildContext context) async {
|
2023-04-07 05:27:06 +00:00
|
|
|
final dialog = createProgressDialog(context, S.of(context).calculating);
|
2022-11-24 10:54:59 +00:00
|
|
|
await dialog.show();
|
|
|
|
BackupStatus status;
|
|
|
|
try {
|
|
|
|
status = await SyncService.instance
|
2022-12-30 12:10:17 +00:00
|
|
|
.getBackupStatus(pathID: widget.deviceCollection!.id);
|
2022-11-24 10:54:59 +00:00
|
|
|
} catch (e) {
|
|
|
|
await dialog.hide();
|
2022-12-26 11:09:29 +00:00
|
|
|
showGenericErrorDialog(context: context);
|
2022-11-24 10:54:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
await dialog.hide();
|
|
|
|
if (status.localIDs.isEmpty) {
|
|
|
|
showErrorDialog(
|
|
|
|
context,
|
2023-04-07 05:06:43 +00:00
|
|
|
S.of(context).allClear,
|
|
|
|
S.of(context).youveNoFilesInThisAlbumThatCanBeDeleted,
|
2022-11-24 10:54:59 +00:00
|
|
|
);
|
|
|
|
} else {
|
2022-12-30 12:10:17 +00:00
|
|
|
final bool? result = await routeToPage(
|
2022-11-24 11:09:05 +00:00
|
|
|
context,
|
|
|
|
FreeSpacePage(status, clearSpaceForFolder: true),
|
|
|
|
);
|
2022-11-24 10:54:59 +00:00
|
|
|
if (result == true) {
|
|
|
|
_showSpaceFreedDialog(status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void _showSpaceFreedDialog(BackupStatus status) {
|
2023-07-21 09:08:10 +00:00
|
|
|
showChoiceDialog(
|
|
|
|
context,
|
2023-04-07 05:27:06 +00:00
|
|
|
title: S.of(context).success,
|
|
|
|
body: S.of(context).youHaveSuccessfullyFreedUp(formatBytes(status.size)),
|
|
|
|
firstButtonLabel: S.of(context).rateUs,
|
2022-12-29 13:52:04 +00:00
|
|
|
firstButtonOnTap: () async {
|
2023-01-07 10:32:24 +00:00
|
|
|
UpdateService.instance.launchReviewUrl();
|
2022-12-29 13:52:04 +00:00
|
|
|
},
|
|
|
|
firstButtonType: ButtonType.primary,
|
2023-04-07 05:27:06 +00:00
|
|
|
secondButtonLabel: S.of(context).ok,
|
2022-12-29 13:52:04 +00:00
|
|
|
secondButtonOnTap: () async {
|
|
|
|
if (Platform.isIOS) {
|
|
|
|
showToast(
|
|
|
|
context,
|
2023-04-07 05:27:06 +00:00
|
|
|
S.of(context).remindToEmptyDeviceTrash,
|
2022-12-29 13:52:04 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
},
|
2022-11-24 10:54:59 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-04-30 15:09:41 +00:00
|
|
|
List<Widget> _getDefaultActions(BuildContext context) {
|
2022-08-29 14:43:31 +00:00
|
|
|
final List<Widget> actions = <Widget>[];
|
2023-06-27 08:34:58 +00:00
|
|
|
// If the user has selected files, don't show any actions
|
|
|
|
if (widget.selectedFiles.files.isNotEmpty ||
|
|
|
|
!Configuration.instance.hasConfiguredAccount()) {
|
2023-06-16 03:57:46 +00:00
|
|
|
return actions;
|
|
|
|
}
|
2023-06-27 09:15:25 +00:00
|
|
|
final int userID = Configuration.instance.getUserID()!;
|
2023-08-04 07:41:23 +00:00
|
|
|
isQuickLink = widget.collection?.isQuickLinkCollection() ?? false;
|
|
|
|
if ((galleryType == GalleryType.ownedCollection ||
|
|
|
|
galleryType == GalleryType.sharedCollection ||
|
|
|
|
isQuickLink) &&
|
2022-11-26 07:56:54 +00:00
|
|
|
widget.collection?.type != CollectionType.favorites) {
|
2023-08-04 07:41:23 +00:00
|
|
|
final bool canAddFiles = galleryType == GalleryType.ownedCollection ||
|
2023-06-27 09:15:25 +00:00
|
|
|
widget.collection!.getRole(userID) ==
|
|
|
|
CollectionParticipantRole.collaborator;
|
|
|
|
if (canAddFiles) {
|
|
|
|
actions.add(
|
|
|
|
Tooltip(
|
2023-06-27 11:26:16 +00:00
|
|
|
message: "Add Files",
|
2023-06-27 09:15:25 +00:00
|
|
|
child: IconButton(
|
|
|
|
icon: const Icon(Icons.add_photo_alternate_outlined),
|
|
|
|
onPressed: () async {
|
2023-06-27 11:26:16 +00:00
|
|
|
await _showAddPhotoDialog(context);
|
2023-06-27 09:15:25 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2021-09-23 09:52:59 +00:00
|
|
|
actions.add(
|
|
|
|
Tooltip(
|
2022-05-30 11:13:55 +00:00
|
|
|
message: "Share",
|
2021-09-23 09:52:59 +00:00
|
|
|
child: IconButton(
|
2023-08-04 06:53:58 +00:00
|
|
|
icon: Icon(
|
2023-08-10 06:38:04 +00:00
|
|
|
isQuickLink && (widget.collection!.hasLink)
|
|
|
|
? Icons.link_outlined
|
|
|
|
: Icons.people_outlined,
|
2023-08-04 06:53:58 +00:00
|
|
|
),
|
2022-08-27 07:30:40 +00:00
|
|
|
onPressed: () async {
|
2022-09-01 09:39:59 +00:00
|
|
|
await _showShareCollectionDialog();
|
2021-09-23 09:52:59 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
2020-04-30 15:09:41 +00:00
|
|
|
}
|
2023-06-22 10:00:27 +00:00
|
|
|
final List<PopupMenuItem<AlbumPopupAction>> items = [];
|
2023-08-04 07:41:23 +00:00
|
|
|
if (galleryType == GalleryType.ownedCollection || isQuickLink) {
|
2022-12-30 12:10:17 +00:00
|
|
|
if (widget.collection!.type != CollectionType.favorites) {
|
2022-10-11 01:35:09 +00:00
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
2023-06-22 10:00:27 +00:00
|
|
|
value: AlbumPopupAction.rename,
|
2022-10-11 01:35:09 +00:00
|
|
|
child: Row(
|
2023-04-07 05:27:06 +00:00
|
|
|
children: [
|
2023-08-04 07:33:52 +00:00
|
|
|
Icon(isQuickLink ? Icons.photo_album_outlined : Icons.edit),
|
2023-04-07 05:27:06 +00:00
|
|
|
const Padding(
|
2022-10-11 01:35:09 +00:00
|
|
|
padding: EdgeInsets.all(8),
|
2022-03-21 09:32:24 +00:00
|
|
|
),
|
2023-08-04 07:33:52 +00:00
|
|
|
Text(
|
|
|
|
isQuickLink
|
|
|
|
? S.of(context).convertToAlbum
|
|
|
|
: S.of(context).renameAlbum,
|
|
|
|
),
|
2022-10-11 01:35:09 +00:00
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
2023-08-04 07:59:27 +00:00
|
|
|
if (!isQuickLink) {
|
2023-08-04 07:12:13 +00:00
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
|
|
|
value: AlbumPopupAction.setCover,
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
const Icon(Icons.image_outlined),
|
|
|
|
const Padding(
|
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
|
|
|
Text(S.of(context).setCover),
|
|
|
|
],
|
|
|
|
),
|
2023-06-22 10:10:21 +00:00
|
|
|
),
|
2023-08-04 07:12:13 +00:00
|
|
|
);
|
|
|
|
}
|
2022-10-11 01:35:09 +00:00
|
|
|
}
|
2023-08-04 07:41:23 +00:00
|
|
|
if (galleryType == GalleryType.ownedCollection ||
|
|
|
|
galleryType == GalleryType.sharedCollection ||
|
|
|
|
isQuickLink) {
|
2023-06-05 03:40:25 +00:00
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
2023-06-22 10:00:27 +00:00
|
|
|
value: AlbumPopupAction.map,
|
2023-06-05 03:40:25 +00:00
|
|
|
child: Row(
|
2023-06-15 12:53:47 +00:00
|
|
|
children: [
|
|
|
|
const Icon(Icons.map_outlined),
|
|
|
|
const Padding(
|
2023-06-05 03:40:25 +00:00
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
2023-06-15 13:06:18 +00:00
|
|
|
Text(S.of(context).map),
|
2023-06-05 03:40:25 +00:00
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2022-12-30 12:10:17 +00:00
|
|
|
final bool isArchived = widget.collection!.isArchived();
|
2023-08-10 06:38:04 +00:00
|
|
|
final bool isHidden = widget.collection!.isHidden();
|
2022-11-17 09:51:17 +00:00
|
|
|
// Do not show archive option for favorite collection. If collection is
|
|
|
|
// already archived, allow user to unarchive that collection.
|
2022-12-30 12:10:17 +00:00
|
|
|
if (isArchived || widget.collection!.type != CollectionType.favorites) {
|
2022-11-17 09:51:17 +00:00
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
2023-06-22 10:00:27 +00:00
|
|
|
value: AlbumPopupAction.sort,
|
2022-11-17 09:51:17 +00:00
|
|
|
child: Row(
|
|
|
|
children: [
|
2023-05-26 04:46:31 +00:00
|
|
|
const Icon(Icons.sort_outlined),
|
2022-11-17 09:51:17 +00:00
|
|
|
const Padding(
|
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
2023-04-18 09:05:21 +00:00
|
|
|
Text(
|
2023-08-04 07:59:27 +00:00
|
|
|
S.of(context).sortAlbumsBy,
|
2023-04-18 09:05:21 +00:00
|
|
|
),
|
2022-11-17 09:51:17 +00:00
|
|
|
],
|
|
|
|
),
|
2022-10-11 01:35:09 +00:00
|
|
|
),
|
2022-11-17 09:51:17 +00:00
|
|
|
);
|
2023-08-04 07:12:13 +00:00
|
|
|
if (!isQuickLink) {
|
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
|
|
|
value: AlbumPopupAction.pinAlbum,
|
|
|
|
child: Row(
|
|
|
|
children: [
|
2023-06-30 05:02:59 +00:00
|
|
|
widget.collection!.isPinned
|
2023-08-04 07:12:13 +00:00
|
|
|
? const Icon(CupertinoIcons.pin_slash)
|
|
|
|
: Transform.rotate(
|
2023-08-04 07:59:27 +00:00
|
|
|
angle: 45 * math.pi / 180, // rotate by 45 degrees
|
|
|
|
child: const Icon(CupertinoIcons.pin),
|
|
|
|
),
|
2023-08-04 07:12:13 +00:00
|
|
|
const Padding(
|
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
|
|
|
Text(
|
|
|
|
widget.collection!.isPinned
|
2023-08-04 07:59:27 +00:00
|
|
|
? S.of(context).unpinAlbum
|
|
|
|
: S.of(context).pinAlbum,
|
2023-08-04 07:12:13 +00:00
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
2023-06-30 04:31:15 +00:00
|
|
|
),
|
2023-08-04 07:12:13 +00:00
|
|
|
);
|
|
|
|
}
|
2023-06-30 04:31:15 +00:00
|
|
|
|
2023-08-04 07:12:13 +00:00
|
|
|
if (!isQuickLink) {
|
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
|
|
|
value: AlbumPopupAction.ownedArchive,
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Icon(isArchived ? Icons.unarchive : Icons.archive_outlined),
|
|
|
|
const Padding(
|
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
|
|
|
Text(
|
|
|
|
isArchived
|
2023-08-04 07:59:27 +00:00
|
|
|
? S.of(context).unarchiveAlbum
|
|
|
|
: S.of(context).archiveAlbum,
|
2023-08-04 07:12:13 +00:00
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
2023-05-25 11:07:55 +00:00
|
|
|
),
|
2023-08-04 07:12:13 +00:00
|
|
|
);
|
2023-08-10 06:38:04 +00:00
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
|
|
|
value: AlbumPopupAction.ownedHide,
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Icon(
|
|
|
|
isHidden
|
|
|
|
? Icons.visibility_outlined
|
|
|
|
: Icons.visibility_off_outlined,
|
|
|
|
),
|
|
|
|
const Padding(
|
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
|
|
|
Text(
|
|
|
|
isHidden ? S.of(context).unhide : S.of(context).hide,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
2023-08-04 07:12:13 +00:00
|
|
|
}
|
2023-05-26 04:46:31 +00:00
|
|
|
}
|
|
|
|
if (widget.collection!.type != CollectionType.favorites) {
|
2022-10-11 01:35:09 +00:00
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
2023-08-04 07:41:23 +00:00
|
|
|
value: isQuickLink
|
|
|
|
? AlbumPopupAction.removeLink
|
|
|
|
: AlbumPopupAction.delete,
|
2022-10-11 01:35:09 +00:00
|
|
|
child: Row(
|
2023-04-07 05:27:06 +00:00
|
|
|
children: [
|
2023-08-04 07:59:27 +00:00
|
|
|
Icon(
|
|
|
|
isQuickLink
|
|
|
|
? Icons.remove_circle_outline
|
|
|
|
: Icons.delete_outline,
|
|
|
|
),
|
2023-04-07 05:27:06 +00:00
|
|
|
const Padding(
|
2022-10-11 01:35:09 +00:00
|
|
|
padding: EdgeInsets.all(8),
|
2022-09-13 06:44:10 +00:00
|
|
|
),
|
2023-08-04 07:59:27 +00:00
|
|
|
Text(
|
|
|
|
isQuickLink
|
|
|
|
? S.of(context).removeLink
|
|
|
|
: S.of(context).deleteAlbum,
|
|
|
|
),
|
2022-10-11 01:35:09 +00:00
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} // ownedCollection open ends
|
|
|
|
|
2023-08-04 07:41:23 +00:00
|
|
|
if (galleryType == GalleryType.sharedCollection) {
|
2023-05-29 13:28:04 +00:00
|
|
|
final bool hasShareeArchived = widget.collection!.hasShareeArchived();
|
2022-10-11 01:35:09 +00:00
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
2023-06-22 10:00:27 +00:00
|
|
|
value: AlbumPopupAction.leave,
|
2022-10-11 01:35:09 +00:00
|
|
|
child: Row(
|
2023-04-07 05:27:06 +00:00
|
|
|
children: [
|
|
|
|
const Icon(Icons.logout),
|
|
|
|
const Padding(
|
2022-10-11 01:35:09 +00:00
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
2023-04-07 05:27:06 +00:00
|
|
|
Text(S.of(context).leaveAlbum),
|
2022-10-11 01:35:09 +00:00
|
|
|
],
|
|
|
|
),
|
2022-06-11 08:23:52 +00:00
|
|
|
),
|
|
|
|
);
|
2023-08-10 06:38:04 +00:00
|
|
|
|
|
|
|
//here
|
2023-05-29 13:28:04 +00:00
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
2023-06-22 10:00:27 +00:00
|
|
|
value: AlbumPopupAction.sharedArchive,
|
2023-05-29 13:28:04 +00:00
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Icon(
|
|
|
|
hasShareeArchived ? Icons.unarchive : Icons.archive_outlined,
|
|
|
|
),
|
|
|
|
const Padding(
|
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
|
|
|
Text(
|
|
|
|
hasShareeArchived
|
|
|
|
? S.of(context).unarchiveAlbum
|
|
|
|
: S.of(context).archiveAlbum,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
2021-09-23 02:34:15 +00:00
|
|
|
}
|
2023-08-04 07:41:23 +00:00
|
|
|
if (galleryType == GalleryType.localFolder) {
|
2022-11-24 10:54:59 +00:00
|
|
|
items.add(
|
|
|
|
PopupMenuItem(
|
2023-06-22 10:00:27 +00:00
|
|
|
value: AlbumPopupAction.freeUpSpace,
|
2022-11-24 10:54:59 +00:00
|
|
|
child: Row(
|
2023-04-07 05:27:06 +00:00
|
|
|
children: [
|
|
|
|
const Icon(Icons.delete_sweep_outlined),
|
|
|
|
const Padding(
|
2022-11-24 10:54:59 +00:00
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
2023-04-07 05:27:06 +00:00
|
|
|
Text(S.of(context).freeUpDeviceSpace),
|
2022-11-24 10:54:59 +00:00
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2022-10-20 10:52:51 +00:00
|
|
|
if (items.isNotEmpty) {
|
|
|
|
actions.add(
|
|
|
|
PopupMenuButton(
|
|
|
|
itemBuilder: (context) {
|
|
|
|
return items;
|
|
|
|
},
|
2023-06-22 10:00:27 +00:00
|
|
|
onSelected: (AlbumPopupAction value) async {
|
|
|
|
if (value == AlbumPopupAction.rename) {
|
2022-10-20 10:52:51 +00:00
|
|
|
await _renameAlbum(context);
|
2023-06-30 04:31:15 +00:00
|
|
|
} else if (value == AlbumPopupAction.pinAlbum) {
|
|
|
|
await updateOrder(
|
|
|
|
context,
|
|
|
|
widget.collection!,
|
|
|
|
widget.collection!.isPinned ? 0 : 1,
|
|
|
|
);
|
|
|
|
if (mounted) setState(() {});
|
2023-06-22 10:00:27 +00:00
|
|
|
} else if (value == AlbumPopupAction.ownedArchive) {
|
2022-10-20 10:52:51 +00:00
|
|
|
await changeCollectionVisibility(
|
|
|
|
context,
|
2022-12-30 12:10:17 +00:00
|
|
|
widget.collection!,
|
|
|
|
widget.collection!.isArchived()
|
2023-05-25 05:51:56 +00:00
|
|
|
? visibleVisibility
|
|
|
|
: archiveVisibility,
|
2022-10-20 10:52:51 +00:00
|
|
|
);
|
2023-08-10 06:38:04 +00:00
|
|
|
} else if (value == AlbumPopupAction.ownedHide) {
|
|
|
|
await changeCollectionVisibility(
|
|
|
|
context,
|
|
|
|
widget.collection!,
|
|
|
|
widget.collection!.isHidden()
|
|
|
|
? visibleVisibility
|
|
|
|
: hiddenVisibility,
|
|
|
|
);
|
2023-06-22 10:00:27 +00:00
|
|
|
} else if (value == AlbumPopupAction.delete) {
|
2022-10-20 10:52:51 +00:00
|
|
|
await _trashCollection();
|
2023-08-04 07:59:27 +00:00
|
|
|
} else if (value == AlbumPopupAction.removeLink) {
|
|
|
|
await _removeQuickLink();
|
2023-06-22 10:00:27 +00:00
|
|
|
} else if (value == AlbumPopupAction.leave) {
|
2022-10-20 10:52:51 +00:00
|
|
|
await _leaveAlbum(context);
|
2023-06-22 10:00:27 +00:00
|
|
|
} else if (value == AlbumPopupAction.freeUpSpace) {
|
2022-11-24 13:08:27 +00:00
|
|
|
await _deleteBackedUpFiles(context);
|
2023-06-22 10:51:56 +00:00
|
|
|
} else if (value == AlbumPopupAction.setCover) {
|
|
|
|
await setCoverPhoto(context);
|
2023-06-22 10:00:27 +00:00
|
|
|
} else if (value == AlbumPopupAction.sort) {
|
2023-05-25 11:07:55 +00:00
|
|
|
await _showSortOption(context);
|
2023-06-22 10:00:27 +00:00
|
|
|
} else if (value == AlbumPopupAction.sharedArchive) {
|
2023-05-29 13:37:02 +00:00
|
|
|
await changeCollectionVisibility(
|
|
|
|
context,
|
|
|
|
widget.collection!,
|
|
|
|
widget.collection!.hasShareeArchived()
|
|
|
|
? visibleVisibility
|
|
|
|
: archiveVisibility,
|
|
|
|
isOwner: false,
|
|
|
|
);
|
|
|
|
if (mounted) {
|
|
|
|
setState(() {});
|
|
|
|
}
|
2023-06-22 10:00:27 +00:00
|
|
|
} else if (value == AlbumPopupAction.map) {
|
2023-06-05 03:40:25 +00:00
|
|
|
await showOnMap();
|
2022-10-20 10:52:51 +00:00
|
|
|
} else {
|
2023-04-07 05:27:06 +00:00
|
|
|
showToast(context, S.of(context).somethingWentWrong);
|
2022-10-20 10:52:51 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2022-10-11 01:35:09 +00:00
|
|
|
|
2020-04-30 15:09:41 +00:00
|
|
|
return actions;
|
|
|
|
}
|
|
|
|
|
2023-06-22 10:51:56 +00:00
|
|
|
Future<void> setCoverPhoto(BuildContext context) async {
|
2023-08-04 07:59:27 +00:00
|
|
|
final int? coverPhotoID = await showPickCoverPhotoSheet(
|
|
|
|
context,
|
|
|
|
widget.collection!,
|
|
|
|
);
|
2023-07-24 07:38:00 +00:00
|
|
|
if (coverPhotoID != null) {
|
|
|
|
changeCoverPhoto(context, widget.collection!, coverPhotoID);
|
2023-06-22 10:51:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-05 03:40:25 +00:00
|
|
|
Future<void> showOnMap() async {
|
2023-06-15 12:45:26 +00:00
|
|
|
final bool result = await requestForMapEnable(context);
|
|
|
|
if (result) {
|
|
|
|
Navigator.of(context).push(
|
|
|
|
MaterialPageRoute(
|
|
|
|
builder: (context) => MapScreen(
|
|
|
|
filesFutureFn: () async {
|
|
|
|
return FilesDB.instance.getAllFilesCollection(
|
|
|
|
widget.collection!.id,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
),
|
2023-06-05 03:40:25 +00:00
|
|
|
),
|
2023-06-15 12:45:26 +00:00
|
|
|
);
|
|
|
|
}
|
2023-06-05 03:40:25 +00:00
|
|
|
}
|
|
|
|
|
2023-05-25 11:07:55 +00:00
|
|
|
Future<void> _showSortOption(BuildContext bContext) async {
|
|
|
|
final bool? sortByAsc = await showMenu<bool>(
|
|
|
|
context: bContext,
|
|
|
|
position: RelativeRect.fromLTRB(
|
|
|
|
MediaQuery.of(context).size.width,
|
|
|
|
kToolbarHeight + 12,
|
|
|
|
12,
|
|
|
|
0,
|
|
|
|
),
|
|
|
|
items: [
|
|
|
|
PopupMenuItem(
|
|
|
|
value: false,
|
|
|
|
child: Text(S.of(context).sortNewestFirst),
|
|
|
|
),
|
|
|
|
PopupMenuItem(
|
|
|
|
value: true,
|
|
|
|
child: Text(S.of(context).sortOldestFirst),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
if (sortByAsc != null) {
|
2023-05-26 02:33:58 +00:00
|
|
|
changeSortOrder(bContext, widget.collection!, sortByAsc);
|
2023-05-25 11:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-13 06:44:10 +00:00
|
|
|
Future<void> _trashCollection() async {
|
2023-07-06 07:59:31 +00:00
|
|
|
// Fetch the count by-passing the cache to avoid any stale data
|
2023-06-19 05:59:57 +00:00
|
|
|
final int count =
|
|
|
|
await FilesDB.instance.collectionFileCount(widget.collection!.id);
|
|
|
|
final bool isEmptyCollection = count == 0;
|
2023-01-12 10:13:11 +00:00
|
|
|
if (isEmptyCollection) {
|
|
|
|
final dialog = createProgressDialog(
|
2022-11-17 09:49:34 +00:00
|
|
|
context,
|
2023-04-07 05:27:06 +00:00
|
|
|
S.of(context).pleaseWaitDeletingAlbum,
|
2022-11-17 09:49:34 +00:00
|
|
|
);
|
2023-01-12 10:13:11 +00:00
|
|
|
await dialog.show();
|
|
|
|
try {
|
|
|
|
await CollectionsService.instance
|
2023-01-12 11:32:52 +00:00
|
|
|
.trashEmptyCollection(widget.collection!);
|
2023-01-12 10:13:11 +00:00
|
|
|
await dialog.hide();
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
} catch (e, s) {
|
|
|
|
_logger.severe("failed to trash collection", e, s);
|
|
|
|
await dialog.hide();
|
|
|
|
showGenericErrorDialog(context: context);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
final bool result = await collectionActions.deleteCollectionSheet(
|
|
|
|
context,
|
|
|
|
widget.collection!,
|
|
|
|
);
|
|
|
|
if (result == true) {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
} else {
|
|
|
|
debugPrint("No pop");
|
2022-11-17 09:49:34 +00:00
|
|
|
}
|
2022-09-13 06:44:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-04 07:59:27 +00:00
|
|
|
Future<void> _removeQuickLink() async {
|
|
|
|
try {
|
|
|
|
final bool result =
|
|
|
|
await CollectionActions(CollectionsService.instance).disableUrl(
|
|
|
|
context,
|
|
|
|
widget.collection!,
|
|
|
|
);
|
|
|
|
if (result && mounted) {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
}
|
|
|
|
} catch (e, s) {
|
|
|
|
_logger.severe("failed to trash collection", e, s);
|
|
|
|
showGenericErrorDialog(context: context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-27 11:26:16 +00:00
|
|
|
Future<void> _showShareCollectionDialog() async {
|
2022-12-08 11:12:51 +00:00
|
|
|
final collection = widget.collection;
|
2022-01-07 16:04:51 +00:00
|
|
|
try {
|
2022-12-08 13:40:27 +00:00
|
|
|
if (collection == null ||
|
2023-08-04 07:41:23 +00:00
|
|
|
(galleryType != GalleryType.ownedCollection &&
|
|
|
|
galleryType != GalleryType.sharedCollection &&
|
|
|
|
!isQuickLink)) {
|
2022-09-07 10:58:38 +00:00
|
|
|
throw Exception(
|
2023-08-04 07:41:23 +00:00
|
|
|
"Cannot share empty collection of type $galleryType",
|
2022-12-08 13:40:27 +00:00
|
|
|
);
|
|
|
|
}
|
2022-12-30 12:10:17 +00:00
|
|
|
if (Configuration.instance.getUserID() == widget.collection!.owner!.id) {
|
2022-12-08 13:40:27 +00:00
|
|
|
unawaited(
|
|
|
|
routeToPage(
|
|
|
|
context,
|
2023-08-10 06:38:04 +00:00
|
|
|
(isQuickLink && (collection.hasLink))
|
|
|
|
? ManageSharedLinkWidget(collection: collection!)
|
|
|
|
: ShareCollectionPage(collection),
|
2022-12-08 13:40:27 +00:00
|
|
|
),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
unawaited(
|
|
|
|
routeToPage(
|
|
|
|
context,
|
|
|
|
AlbumParticipantsPage(collection),
|
|
|
|
),
|
2022-09-07 10:58:38 +00:00
|
|
|
);
|
2020-10-29 12:56:30 +00:00
|
|
|
}
|
2022-01-07 16:04:51 +00:00
|
|
|
} catch (e, s) {
|
|
|
|
_logger.severe(e, s);
|
2022-12-26 11:09:29 +00:00
|
|
|
showGenericErrorDialog(context: context);
|
2020-10-29 12:56:30 +00:00
|
|
|
}
|
2020-05-17 12:39:38 +00:00
|
|
|
}
|
2023-06-27 09:15:25 +00:00
|
|
|
|
2023-06-27 11:26:16 +00:00
|
|
|
Future<void> _showAddPhotoDialog(BuildContext bContext) async {
|
2023-06-27 09:15:25 +00:00
|
|
|
final collection = widget.collection;
|
|
|
|
try {
|
2023-06-28 07:28:40 +00:00
|
|
|
await showAddPhotosSheet(bContext, collection!);
|
2023-06-27 09:15:25 +00:00
|
|
|
} catch (e, s) {
|
|
|
|
_logger.severe(e, s);
|
2023-06-27 11:26:16 +00:00
|
|
|
showGenericErrorDialog(context: bContext);
|
2023-06-27 09:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
2020-04-18 18:46:38 +00:00
|
|
|
}
|