浏览代码

Revamp Quick link options (#1299)

Neeraj Gupta 2 年之前
父节点
当前提交
9ae658c954

+ 2 - 0
lib/generated/intl/messages_en.dart

@@ -432,6 +432,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "continueLabel": MessageLookupByLibrary.simpleMessage("Continue"),
         "continueOnFreeTrial":
             MessageLookupByLibrary.simpleMessage("Continue on free trial"),
+        "convertToAlbum":
+            MessageLookupByLibrary.simpleMessage("Convert to album"),
         "copyEmailAddress":
             MessageLookupByLibrary.simpleMessage("Copy email address"),
         "copyLink": MessageLookupByLibrary.simpleMessage("Copy link"),

+ 11 - 0
lib/generated/l10n.dart

@@ -1,6 +1,7 @@
 // GENERATED CODE - DO NOT MODIFY BY HAND
 import 'package:flutter/material.dart';
 import 'package:intl/intl.dart';
+
 import 'intl/messages_all.dart';
 
 // **************************************************************************
@@ -5385,6 +5386,16 @@ class S {
     );
   }
 
+  /// `Convert to album`
+  String get convertToAlbum {
+    return Intl.message(
+      'Convert to album',
+      name: 'convertToAlbum',
+      desc: '',
+      args: [],
+    );
+  }
+
   /// `Set cover`
   String get setCover {
     return Intl.message(

+ 1 - 0
lib/l10n/intl_en.arb

@@ -776,6 +776,7 @@
   },
   "deleteAll": "Delete All",
   "renameAlbum": "Rename album",
+  "convertToAlbum": "Convert to album",
   "setCover": "Set cover",
   "@setCover": {
     "description": "Text to set cover photo for an album"

+ 3 - 2
lib/models/collection.dart

@@ -115,8 +115,9 @@ class Collection {
     return (magicMetadata.subType ?? 0) == subTypeDefaultHidden;
   }
 
-  bool isSharedFilesCollection() {
-    return (magicMetadata.subType ?? 0) == subTypeSharedFilesCollection;
+  bool isQuickLinkCollection() {
+    return (magicMetadata.subType ?? 0) == subTypeSharedFilesCollection &&
+        !hasSharees;
   }
 
   List<User> getSharees() {

+ 12 - 0
lib/models/gallery_type.dart

@@ -11,6 +11,7 @@ enum GalleryType {
   ownedCollection,
   searchResults,
   locationTag,
+  quickLink,
 }
 
 extension GalleyTypeExtension on GalleryType {
@@ -23,6 +24,7 @@ extension GalleyTypeExtension on GalleryType {
       case GalleryType.searchResults:
       case GalleryType.favorite:
       case GalleryType.locationTag:
+      case GalleryType.quickLink:
         return true;
 
       case GalleryType.hidden:
@@ -37,6 +39,7 @@ extension GalleyTypeExtension on GalleryType {
     switch (this) {
       case GalleryType.ownedCollection:
       case GalleryType.uncategorized:
+      case GalleryType.quickLink:
         return true;
 
       case GalleryType.hidden:
@@ -63,6 +66,7 @@ extension GalleyTypeExtension on GalleryType {
       case GalleryType.localFolder:
       case GalleryType.uncategorized:
       case GalleryType.locationTag:
+      case GalleryType.quickLink:
         return true;
       case GalleryType.trash:
       case GalleryType.archive:
@@ -83,6 +87,7 @@ extension GalleyTypeExtension on GalleryType {
       case GalleryType.hidden:
       case GalleryType.localFolder:
       case GalleryType.locationTag:
+      case GalleryType.quickLink:
         return true;
       case GalleryType.trash:
       case GalleryType.sharedCollection:
@@ -104,6 +109,7 @@ extension GalleyTypeExtension on GalleryType {
       case GalleryType.localFolder:
       case GalleryType.trash:
       case GalleryType.sharedCollection:
+      case GalleryType.quickLink:
         return false;
     }
   }
@@ -112,6 +118,7 @@ extension GalleyTypeExtension on GalleryType {
     switch (this) {
       case GalleryType.ownedCollection:
       case GalleryType.sharedCollection:
+      case GalleryType.quickLink:
         return true;
       case GalleryType.hidden:
       case GalleryType.uncategorized:
@@ -131,9 +138,11 @@ extension GalleyTypeExtension on GalleryType {
       case GalleryType.ownedCollection:
       case GalleryType.homepage:
       case GalleryType.uncategorized:
+      case GalleryType.quickLink:
         return true;
 
       case GalleryType.hidden:
+
       case GalleryType.favorite:
       case GalleryType.searchResults:
       case GalleryType.archive:
@@ -157,9 +166,11 @@ extension GalleyTypeExtension on GalleryType {
       case GalleryType.archive:
       case GalleryType.uncategorized:
       case GalleryType.locationTag:
+      case GalleryType.quickLink:
         return true;
 
       case GalleryType.hidden:
+
       case GalleryType.localFolder:
       case GalleryType.trash:
       case GalleryType.favorite:
@@ -182,6 +193,7 @@ extension GalleyTypeExtension on GalleryType {
         return true;
 
       case GalleryType.hidden:
+      case GalleryType.quickLink:
       case GalleryType.favorite:
       case GalleryType.archive:
       case GalleryType.localFolder:

+ 4 - 4
lib/services/collections_service.dart

@@ -328,9 +328,9 @@ class CollectionsService {
     final List<Collection> collections = getCollectionsForUI(includedShared: true);
     for (final c in collections) {
       if (c.owner!.id == Configuration.instance.getUserID()) {
-        if (c.hasSharees || c.hasLink && !c.isSharedFilesCollection()) {
+        if (c.hasSharees || c.hasLink && !c.isQuickLinkCollection()) {
           outgoing.add(c);
-        } else if (c.isSharedFilesCollection()) {
+        } else if (c.isQuickLinkCollection()) {
           quickLinks.add(c);
         }
       } else {
@@ -375,7 +375,7 @@ class CollectionsService {
     final List<Collection> rest = [];
     for (final collection in collections) {
       if (collection.type == CollectionType.uncategorized ||
-          collection.isSharedFilesCollection() ||
+          collection.isQuickLinkCollection() ||
           collection.isHidden()) {
         continue;
       }
@@ -638,7 +638,7 @@ class CollectionsService {
     try {
       // Note: when collection created to sharing few files is renamed
       // convert that collection to a regular collection type.
-      if (collection.isSharedFilesCollection()) {
+      if (collection.isQuickLinkCollection()) {
         await updateMagicMetadata(collection, {"subType": 0});
       }
       final encryptedName = CryptoUtil.encryptSync(

+ 15 - 6
lib/ui/actions/collection/collection_sharing_actions.dart

@@ -70,7 +70,12 @@ class CollectionActions {
           shouldSurfaceExecutionStates: true,
           labelText: S.of(context).yesRemove,
           onTap: () async {
-            await CollectionsService.instance.disableShareUrl(collection);
+            // for quickLink collection, we need to trash the collection
+            if(collection.isQuickLinkCollection() && !collection.hasSharees) {
+              await trashCollectionKeepingPhotos(collection, context);
+            } else {
+              await CollectionsService.instance.disableShareUrl(collection);
+            }
           },
         ),
         ButtonWidget(
@@ -303,11 +308,7 @@ class CollectionActions {
           isInAlert: true,
           onTap: () async {
             try {
-              final List<File> files =
-                  await FilesDB.instance.getAllFilesCollection(collection.id);
-              await moveFilesFromCurrentCollection(bContext, collection, files);
-              // collection should be empty on server now
-              await collectionsService.trashEmptyCollection(collection);
+              await trashCollectionKeepingPhotos(collection, bContext);
             } catch (e, s) {
               logger.severe("Failed to keep photos & delete collection", e, s);
               rethrow;
@@ -363,6 +364,14 @@ class CollectionActions {
     return false;
   }
 
+  Future<void> trashCollectionKeepingPhotos(Collection collection, BuildContext bContext) async {
+    final List<File> files =
+        await FilesDB.instance.getAllFilesCollection(collection.id);
+    await moveFilesFromCurrentCollection(bContext, collection, files);
+    // collection should be empty on server now
+    await collectionsService.trashEmptyCollection(collection);
+  }
+
   // _confirmSharedAlbumDeletion should be shown when user tries to delete an
   // album shared with other ente users.
   Future<bool> _confirmSharedAlbumDeletion(

+ 1 - 1
lib/ui/collections/collection_action_sheet.dart

@@ -262,7 +262,7 @@ class _CollectionActionSheetState extends State<CollectionActionSheet> {
     final List<Collection> pinned = [];
     final List<Collection> unpinned = [];
     for (final collection in collections) {
-      if (collection.isSharedFilesCollection() ||
+      if (collection.isQuickLinkCollection() ||
           collection.type == CollectionType.favorites ||
           collection.type == CollectionType.uncategorized) {
         continue;

+ 58 - 0
lib/ui/sharing/manage_links_widget.dart

@@ -2,7 +2,9 @@ import 'dart:convert';
 import 'dart:typed_data';
 
 import 'package:collection/collection.dart';
+import "package:fast_base58/fast_base58.dart";
 import 'package:flutter/material.dart';
+import "package:flutter/services.dart";
 import "package:photos/generated/l10n.dart";
 import "package:photos/models/api/collection/public_url.dart";
 import 'package:photos/models/collection.dart';
@@ -20,6 +22,7 @@ import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/date_time_util.dart';
 import 'package:photos/utils/dialog_util.dart';
 import 'package:photos/utils/navigation_util.dart';
+import "package:photos/utils/share_util.dart";
 import 'package:photos/utils/toast_util.dart';
 
 class ManageSharedLinkWidget extends StatefulWidget {
@@ -50,6 +53,10 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
         widget.collection!.publicURLs?.firstOrNull?.passwordEnabled ?? false;
     final enteColorScheme = getEnteColorScheme(context);
     final PublicURL url = widget.collection!.publicURLs!.firstOrNull!;
+    final String collectionKey = Base58Encode(
+      CollectionsService.instance.getCollectionKey(widget.collection!.id),
+    );
+    final String urlValue = "${url.url}#$collectionKey";
     return Scaffold(
       appBar: AppBar(
         elevation: 0,
@@ -226,6 +233,54 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
                   const SizedBox(
                     height: 24,
                   ),
+                  if (url.isExpired)
+                    MenuItemWidget(
+                      captionedTextWidget: CaptionedTextWidget(
+                        title: S.of(context).linkHasExpired,
+                        textColor: getEnteColorScheme(context).warning500,
+                      ),
+                      leadingIcon: Icons.error_outline,
+                      leadingIconColor: getEnteColorScheme(context).warning500,
+                      menuItemColor: getEnteColorScheme(context).fillFaint,
+                      isBottomBorderRadiusRemoved: true,
+                    ),
+                  if (!url.isExpired)
+                    MenuItemWidget(
+                      captionedTextWidget: CaptionedTextWidget(
+                        title: S.of(context).copyLink,
+                        makeTextBold: true,
+                      ),
+                      leadingIcon: Icons.copy,
+                      menuItemColor: getEnteColorScheme(context).fillFaint,
+                      showOnlyLoadingState: true,
+                      onTap: () async {
+                        await Clipboard.setData(ClipboardData(text: urlValue));
+                        showShortToast(
+                            context, S.of(context).linkCopiedToClipboard);
+                      },
+                      isBottomBorderRadiusRemoved: true,
+                    ),
+                  if (!url.isExpired)
+                    DividerWidget(
+                      dividerType: DividerType.menu,
+                      bgColor: getEnteColorScheme(context).fillFaint,
+                    ),
+                  if (!url.isExpired)
+                    MenuItemWidget(
+                      captionedTextWidget: CaptionedTextWidget(
+                        title: S.of(context).sendLink,
+                        makeTextBold: true,
+                      ),
+                      leadingIcon: Icons.adaptive.share,
+                      menuItemColor: getEnteColorScheme(context).fillFaint,
+                      onTap: () async {
+                        shareText(urlValue);
+                      },
+                      isTopBorderRadiusRemoved: true,
+                    ),
+                  const SizedBox(
+                    height: 24,
+                  ),
                   MenuItemWidget(
                     captionedTextWidget: CaptionedTextWidget(
                       title: S.of(context).removeLink,
@@ -243,6 +298,9 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
                       );
                       if (result && mounted) {
                         Navigator.of(context).pop();
+                        if (widget.collection!.isQuickLinkCollection()) {
+                          Navigator.of(context).pop();
+                        }
                       }
                     },
                   ),

+ 2 - 0
lib/ui/viewer/gallery/collection_page.dart

@@ -124,6 +124,8 @@ class CollectionPage extends StatelessWidget {
       return GalleryType.uncategorized;
     } else if (c.type == CollectionType.favorites) {
       return GalleryType.favorite;
+    } else if (c.isQuickLinkCollection()) {
+      return GalleryType.quickLink;
     }
     return appBarType;
   }

+ 147 - 79
lib/ui/viewer/gallery/gallery_app_bar_widget.dart

@@ -26,6 +26,7 @@ import 'package:photos/ui/components/models/button_type.dart';
 import "package:photos/ui/map/enable_map.dart";
 import "package:photos/ui/map/map_screen.dart";
 import 'package:photos/ui/sharing/album_participants_page.dart';
+import "package:photos/ui/sharing/manage_links_widget.dart";
 import 'package:photos/ui/sharing/share_collection_page.dart';
 import 'package:photos/ui/tools/free_space_page.dart';
 import "package:photos/ui/viewer/gallery/hooks/add_photos_sheet.dart";
@@ -68,6 +69,7 @@ enum AlbumPopupAction {
   setCover,
   addPhotos,
   pinAlbum,
+  removeLink,
 }
 
 class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
@@ -77,9 +79,12 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
   String? _appBarTitle;
   late CollectionActions collectionActions;
   final GlobalKey shareButtonKey = GlobalKey();
+  bool isQuickLink = false;
+  late GalleryType galleryType;
 
   @override
   void initState() {
+    super.initState();
     _selectedFilesListener = () {
       setState(() {});
     };
@@ -90,7 +95,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
       setState(() {});
     });
     _appBarTitle = widget.title;
-    super.initState();
+    galleryType = widget.type;
   }
 
   @override
@@ -102,15 +107,15 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
 
   @override
   Widget build(BuildContext context) {
-    return widget.type == GalleryType.homepage
+    return galleryType == GalleryType.homepage
         ? const SizedBox.shrink()
         : AppBar(
-            backgroundColor: widget.type == GalleryType.homepage
+            backgroundColor: galleryType == GalleryType.homepage
                 ? const Color(0x00000000)
                 : null,
             elevation: 0,
             centerTitle: false,
-            title: widget.type == GalleryType.homepage
+            title: galleryType == GalleryType.homepage
                 ? const SizedBox.shrink()
                 : TextButton(
                     child: Text(
@@ -127,13 +132,22 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
   }
 
   Future<dynamic> _renameAlbum(BuildContext context) async {
-    if (widget.type != GalleryType.ownedCollection) {
+    if (galleryType != GalleryType.ownedCollection &&
+        galleryType != GalleryType.quickLink) {
+      showToast(
+        context,
+        'Type of galler $galleryType is not supported for '
+        'rename',
+      );
       return;
     }
     final result = await showTextInputDialog(
       context,
-      title: S.of(context).renameAlbum,
-      submitButtonLabel: S.of(context).rename,
+      title: isQuickLink
+          ? S.of(context).enterAlbumName
+          : S.of(context).renameAlbum,
+      submitButtonLabel:
+          isQuickLink ? S.of(context).done : S.of(context).rename,
       hintText: S.of(context).enterAlbumName,
       alwaysShowSuccessState: true,
       initialValue: widget.collection?.displayName ?? "",
@@ -148,6 +162,11 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
           await CollectionsService.instance.rename(widget.collection!, text);
           if (mounted) {
             _appBarTitle = text;
+            if (isQuickLink) {
+              // update the gallery type to owned collection so that correct
+              // actions are shown
+              galleryType = GalleryType.ownedCollection;
+            }
             setState(() {});
           }
         } catch (e, s) {
@@ -261,10 +280,12 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
       return actions;
     }
     final int userID = Configuration.instance.getUserID()!;
-    if ((widget.type == GalleryType.ownedCollection ||
-            widget.type == GalleryType.sharedCollection) &&
+    isQuickLink = widget.collection?.isQuickLinkCollection() ?? false;
+    if ((galleryType == GalleryType.ownedCollection ||
+            galleryType == GalleryType.sharedCollection ||
+            isQuickLink) &&
         widget.collection?.type != CollectionType.favorites) {
-      final bool canAddFiles = widget.type == GalleryType.ownedCollection ||
+      final bool canAddFiles = galleryType == GalleryType.ownedCollection ||
           widget.collection!.getRole(userID) ==
               CollectionParticipantRole.collaborator;
       if (canAddFiles) {
@@ -284,7 +305,11 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
         Tooltip(
           message: "Share",
           child: IconButton(
-            icon: const Icon(Icons.people_outlined),
+            icon: Icon(
+               isQuickLink && (widget.collection!.hasLink) ? Icons
+                   .link_outlined : Icons
+                   .people_outlined,
+            ),
             onPressed: () async {
               await _showShareCollectionDialog();
             },
@@ -293,39 +318,46 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
       );
     }
     final List<PopupMenuItem<AlbumPopupAction>> items = [];
-    if (widget.type == GalleryType.ownedCollection) {
+    if (galleryType == GalleryType.ownedCollection || isQuickLink) {
       if (widget.collection!.type != CollectionType.favorites) {
         items.add(
           PopupMenuItem(
             value: AlbumPopupAction.rename,
             child: Row(
               children: [
-                const Icon(Icons.edit),
+                Icon(isQuickLink ? Icons.photo_album_outlined : Icons.edit),
                 const Padding(
                   padding: EdgeInsets.all(8),
                 ),
-                Text(S.of(context).renameAlbum),
-              ],
-            ),
-          ),
-        );
-        items.add(
-          PopupMenuItem(
-            value: AlbumPopupAction.setCover,
-            child: Row(
-              children: [
-                const Icon(Icons.image_outlined),
-                const Padding(
-                  padding: EdgeInsets.all(8),
+                Text(
+                  isQuickLink
+                      ? S.of(context).convertToAlbum
+                      : S.of(context).renameAlbum,
                 ),
-                Text(S.of(context).setCover),
               ],
             ),
           ),
         );
+        if (!isQuickLink) {
+          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),
+                ],
+              ),
+            ),
+          );
+        }
       }
-      if (widget.type == GalleryType.ownedCollection ||
-          widget.type == GalleryType.sharedCollection) {
+      if (galleryType == GalleryType.ownedCollection ||
+          galleryType == GalleryType.sharedCollection ||
+          isQuickLink) {
         items.add(
           PopupMenuItem(
             value: AlbumPopupAction.map,
@@ -361,61 +393,74 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
             ),
           ),
         );
-
-        items.add(
-          PopupMenuItem(
-            value: AlbumPopupAction.pinAlbum,
-            child: Row(
-              children: [
-                widget.collection!.isPinned
-                    ? const Icon(CupertinoIcons.pin_slash)
-                    : Transform.rotate(
-                        angle: 45 * math.pi / 180, // rotate by 45 degrees
-                        child: const Icon(CupertinoIcons.pin),
-                      ),
-                const Padding(
-                  padding: EdgeInsets.all(8),
-                ),
-                Text(
+        if (!isQuickLink) {
+          items.add(
+            PopupMenuItem(
+              value: AlbumPopupAction.pinAlbum,
+              child: Row(
+                children: [
                   widget.collection!.isPinned
-                      ? S.of(context).unpinAlbum
-                      : S.of(context).pinAlbum,
-                ),
-              ],
+                      ? const Icon(CupertinoIcons.pin_slash)
+                      : Transform.rotate(
+                          angle: 45 * math.pi / 180, // rotate by 45 degrees
+                          child: const Icon(CupertinoIcons.pin),
+                        ),
+                  const Padding(
+                    padding: EdgeInsets.all(8),
+                  ),
+                  Text(
+                    widget.collection!.isPinned
+                        ? S.of(context).unpinAlbum
+                        : S.of(context).pinAlbum,
+                  ),
+                ],
+              ),
             ),
-          ),
-        );
+          );
+        }
 
-        items.add(
-          PopupMenuItem(
-            value: AlbumPopupAction.ownedArchive,
-            child: Row(
-              children: [
-                Icon(isArchived ? Icons.unarchive : Icons.archive_outlined),
-                const Padding(
-                  padding: EdgeInsets.all(8),
-                ),
-                Text(
-                  isArchived
-                      ? S.of(context).unarchiveAlbum
-                      : S.of(context).archiveAlbum,
-                ),
-              ],
+        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
+                        ? S.of(context).unarchiveAlbum
+                        : S.of(context).archiveAlbum,
+                  ),
+                ],
+              ),
             ),
-          ),
-        );
+          );
+        }
       }
       if (widget.collection!.type != CollectionType.favorites) {
         items.add(
           PopupMenuItem(
-            value: AlbumPopupAction.delete,
+            value: isQuickLink
+                ? AlbumPopupAction.removeLink
+                : AlbumPopupAction.delete,
             child: Row(
               children: [
-                const Icon(Icons.delete_outline),
+                Icon(
+                  isQuickLink
+                      ? Icons.remove_circle_outline
+                      : Icons.delete_outline,
+                ),
                 const Padding(
                   padding: EdgeInsets.all(8),
                 ),
-                Text(S.of(context).deleteAlbum),
+                Text(
+                  isQuickLink
+                      ? S.of(context).removeLink
+                      : S.of(context).deleteAlbum,
+                ),
               ],
             ),
           ),
@@ -423,7 +468,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
       }
     } // ownedCollection open ends
 
-    if (widget.type == GalleryType.sharedCollection) {
+    if (galleryType == GalleryType.sharedCollection) {
       final bool hasShareeArchived = widget.collection!.hasShareeArchived();
       items.add(
         PopupMenuItem(
@@ -460,7 +505,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
         ),
       );
     }
-    if (widget.type == GalleryType.localFolder) {
+    if (galleryType == GalleryType.localFolder) {
       items.add(
         PopupMenuItem(
           value: AlbumPopupAction.freeUpSpace,
@@ -502,6 +547,8 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
               );
             } else if (value == AlbumPopupAction.delete) {
               await _trashCollection();
+            } else if (value == AlbumPopupAction.removeLink) {
+              await _removeQuickLink();
             } else if (value == AlbumPopupAction.leave) {
               await _leaveAlbum(context);
             } else if (value == AlbumPopupAction.freeUpSpace) {
@@ -536,8 +583,10 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
   }
 
   Future<void> setCoverPhoto(BuildContext context) async {
-    final int? coverPhotoID = await showPickCoverPhotoSheet(context, widget
-        .collection!,);
+    final int? coverPhotoID = await showPickCoverPhotoSheet(
+      context,
+      widget.collection!,
+    );
     if (coverPhotoID != null) {
       changeCoverPhoto(context, widget.collection!, coverPhotoID);
     }
@@ -619,21 +668,40 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
     }
   }
 
+  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);
+    }
+  }
+
   Future<void> _showShareCollectionDialog() async {
     final collection = widget.collection;
     try {
       if (collection == null ||
-          (widget.type != GalleryType.ownedCollection &&
-              widget.type != GalleryType.sharedCollection)) {
+          (galleryType != GalleryType.ownedCollection &&
+              galleryType != GalleryType.sharedCollection &&
+              !isQuickLink)) {
         throw Exception(
-          "Cannot share empty collection of typex ${widget.type}",
+          "Cannot share empty collection of type $galleryType",
         );
       }
       if (Configuration.instance.getUserID() == widget.collection!.owner!.id) {
         unawaited(
           routeToPage(
             context,
-            ShareCollectionPage(collection),
+              (isQuickLink && (collection.hasLink)) ? ManageSharedLinkWidget(collection: collection!) :
+              ShareCollectionPage
+              (collection),
           ),
         );
       } else {