diff --git a/mobile/lib/ui/components/title_bar_title_widget.dart b/mobile/lib/ui/components/title_bar_title_widget.dart index a685ea0456..e838849ef3 100644 --- a/mobile/lib/ui/components/title_bar_title_widget.dart +++ b/mobile/lib/ui/components/title_bar_title_widget.dart @@ -6,11 +6,13 @@ class TitleBarTitleWidget extends StatelessWidget { final bool isTitleH2; final IconData? icon; final VoidCallback? onTap; + final String? heroTag; const TitleBarTitleWidget({ this.title, this.isTitleH2 = false, this.icon, this.onTap, + this.heroTag, super.key, }); @@ -51,7 +53,10 @@ class TitleBarTitleWidget extends StatelessWidget { maxLines: 1, ); } - return GestureDetector(onTap: onTap, child: widget); + return GestureDetector( + onTap: onTap, + child: heroTag != null ? Hero(tag: heroTag!, child: widget) : widget, + ); } return const SizedBox.shrink(); diff --git a/mobile/lib/ui/tabs/shared/all_quick_links_page.dart b/mobile/lib/ui/tabs/shared/all_quick_links_page.dart new file mode 100644 index 0000000000..3a42ad0b61 --- /dev/null +++ b/mobile/lib/ui/tabs/shared/all_quick_links_page.dart @@ -0,0 +1,69 @@ +import "package:flutter/material.dart"; +import "package:photos/generated/l10n.dart"; +import "package:photos/models/collection/collection.dart"; +import "package:photos/ui/components/title_bar_title_widget.dart"; +import "package:photos/ui/tabs/shared/quick_link_album_item.dart"; + +class AllQuickLinksPage extends StatelessWidget { + final List quickLinks; + final String titleHeroTag; + const AllQuickLinksPage({ + required this.quickLinks, + required this.titleHeroTag, + super.key, + }); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + toolbarHeight: 48, + leadingWidth: 48, + leading: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: const Icon( + Icons.arrow_back_outlined, + ), + ), + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TitleBarTitleWidget( + title: S.of(context).quickLinks, + heroTag: titleHeroTag, + ), + Text(quickLinks.length.toString()), + ], + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 20, + horizontal: 16, + ), + child: ListView.separated( + itemBuilder: (context, index) { + return QuickLinkAlbumItem(c: quickLinks[index]); + }, + separatorBuilder: (context, index) { + return const SizedBox(height: 10); + }, + itemCount: quickLinks.length, + physics: const BouncingScrollPhysics(), + ), + ), + ), + ], + ), + ); + } +} diff --git a/mobile/lib/ui/tabs/shared_collections_tab.dart b/mobile/lib/ui/tabs/shared_collections_tab.dart index 161f0908cd..a0d78192ac 100644 --- a/mobile/lib/ui/tabs/shared_collections_tab.dart +++ b/mobile/lib/ui/tabs/shared_collections_tab.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import "dart:math"; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; @@ -17,6 +18,7 @@ import "package:photos/ui/components/buttons/icon_button_widget.dart"; import "package:photos/ui/components/divider_widget.dart"; import "package:photos/ui/components/models/button_type.dart"; import 'package:photos/ui/tabs/section_title.dart'; +import "package:photos/ui/tabs/shared/all_quick_links_page.dart"; import "package:photos/ui/tabs/shared/empty_state.dart"; import "package:photos/ui/tabs/shared/quick_link_album_item.dart"; import "package:photos/utils/debouncer.dart"; @@ -97,7 +99,9 @@ class _SharedCollectionsTabState extends State Widget _getSharedCollectionsGallery(SharedCollections collections) { const maxThumbnailWidth = 160.0; - final bool hasQuickLinks = collections.quickLinks.isNotEmpty; + const maxQuickLinks = 6; + final numberOfQuickLinks = collections.quickLinks.length; + const quickLinkTitleHeroTag = "quick_link_title"; final SectionTitle sharedWithYou = SectionTitle(title: S.of(context).sharedWithYou); final SectionTitle sharedByYou = @@ -216,7 +220,7 @@ class _SharedCollectionsTabState extends State ], ), ), - hasQuickLinks + numberOfQuickLinks > 0 ? Padding( padding: const EdgeInsets.symmetric( vertical: 8.0, @@ -224,7 +228,29 @@ class _SharedCollectionsTabState extends State child: Column( children: [ SectionOptions( - SectionTitle(title: S.of(context).quickLinks), + Hero( + tag: quickLinkTitleHeroTag, + child: SectionTitle( + title: S.of(context).quickLinks, + ), + ), + trailingWidget: numberOfQuickLinks > maxQuickLinks + ? IconButtonWidget( + icon: Icons.chevron_right, + iconButtonType: IconButtonType.secondary, + onTap: () { + unawaited( + routeToPage( + context, + AllQuickLinksPage( + titleHeroTag: quickLinkTitleHeroTag, + quickLinks: collections.quickLinks, + ), + ), + ); + }, + ) + : null, ), const SizedBox(height: 2), ListView.separated( @@ -241,9 +267,9 @@ class _SharedCollectionsTabState extends State ); }, separatorBuilder: (context, index) { - return const SizedBox(height: 8); + return const SizedBox(height: 4); }, - itemCount: collections.quickLinks.length, + itemCount: min(numberOfQuickLinks, maxQuickLinks), ), ], ), @@ -257,10 +283,10 @@ class _SharedCollectionsTabState extends State Padding( padding: const EdgeInsets.fromLTRB(24, 0, 24, 12), child: ButtonWidget( - buttonType: - !hasQuickLinks && collections.outgoing.isEmpty - ? ButtonType.trailingIconSecondary - : ButtonType.trailingIconPrimary, + buttonType: numberOfQuickLinks == 0 && + collections.outgoing.isEmpty + ? ButtonType.trailingIconSecondary + : ButtonType.trailingIconPrimary, labelText: S.of(context).inviteYourFriendsToEnte, icon: Icons.ios_share_outlined, onTap: () async {