diff --git a/mobile/lib/pages/collections/collections.page.dart b/mobile/lib/pages/collections/collections.page.dart new file mode 100644 index 0000000000000..6863bb9a7de88 --- /dev/null +++ b/mobile/lib/pages/collections/collections.page.dart @@ -0,0 +1,118 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/widgets/common/immich_app_bar.dart'; + +@RoutePage() +class CollectionsPage extends StatelessWidget { + const CollectionsPage({super.key}); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: const ImmichAppBar( + action: CreateNewButton(), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + shrinkWrap: true, + children: [ + Row( + children: [ + ActionButton( + onPressed: () {}, + icon: Icons.favorite_outline_rounded, + label: 'Favorite', + ), + const SizedBox(width: 8), + ActionButton( + onPressed: () {}, + icon: Icons.delete_outline_rounded, + label: 'Trash', + ), + ], + ), + const SizedBox(height: 8), + Row( + children: [ + ActionButton( + onPressed: () {}, + icon: Icons.link_outlined, + label: 'Shared links', + ), + const SizedBox(width: 8), + ActionButton( + onPressed: () {}, + icon: Icons.archive_outlined, + label: 'Archive', + ), + ], + ), + const SizedBox(height: 8), + ], + ), + ), + ); + } +} + +class ActionButton extends StatelessWidget { + final VoidCallback onPressed; + final IconData icon; + final String label; + + const ActionButton({ + super.key, + required this.onPressed, + required this.icon, + required this.label, + }); + + @override + Widget build(BuildContext context) { + return Expanded( + child: FilledButton.icon( + onPressed: onPressed, + label: Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Text( + label, + style: TextStyle( + color: context.colorScheme.onSurface, + ), + ), + ), + style: FilledButton.styleFrom( + elevation: 0, + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), + backgroundColor: context.colorScheme.surfaceContainer, + alignment: Alignment.centerLeft, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + ), + icon: Icon( + icon, + color: context.primaryColor, + ), + ), + ); + } +} + +class CreateNewButton extends StatelessWidget { + const CreateNewButton({super.key}); + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () {}, + borderRadius: const BorderRadius.all(Radius.circular(25)), + child: Icon( + Icons.add, + size: 32, + semanticLabel: 'profile_drawer_trash'.tr(), + ), + ); + } +} diff --git a/mobile/lib/pages/common/tab_controller.page.dart b/mobile/lib/pages/common/tab_controller.page.dart index b619e003d2c3a..f862213040e89 100644 --- a/mobile/lib/pages/common/tab_controller.page.dart +++ b/mobile/lib/pages/common/tab_controller.page.dart @@ -94,6 +94,12 @@ class TabControllerPage extends HookConsumerWidget { selectedIcon: const Icon(Icons.photo_album), label: const Text('tab_controller_nav_library').tr(), ), + NavigationRailDestination( + padding: const EdgeInsets.all(4), + icon: const Icon(Icons.photo_album_outlined), + selectedIcon: const Icon(Icons.photo_album), + label: const Text('Collections').tr(), + ), ], ); } @@ -156,6 +162,18 @@ class TabControllerPage extends HookConsumerWidget { ), ), ), + NavigationDestination( + label: 'Collections'.tr(), + icon: const Icon( + Icons.photo_album_outlined, + ), + selectedIcon: buildIcon( + Icon( + Icons.photo_album_rounded, + color: context.primaryColor, + ), + ), + ), ], ); } @@ -167,6 +185,7 @@ class TabControllerPage extends HookConsumerWidget { SearchRoute(), SharingRoute(), LibraryRoute(), + CollectionsRoute(), ], duration: const Duration(milliseconds: 600), transitionBuilder: (context, child, animation) => FadeTransition( diff --git a/mobile/lib/providers/app_life_cycle.provider.dart b/mobile/lib/providers/app_life_cycle.provider.dart index 938961efb62ac..5dd02d6ad7e55 100644 --- a/mobile/lib/providers/app_life_cycle.provider.dart +++ b/mobile/lib/providers/app_life_cycle.provider.dart @@ -63,6 +63,8 @@ class AppLifeCycleNotifier extends StateNotifier { _ref.read(sharedAlbumProvider.notifier).getAllSharedAlbums(); case TabEnum.library: _ref.read(albumProvider.notifier).getAllAlbums(); + case TabEnum.collections: + // nothing to do } } diff --git a/mobile/lib/providers/tab.provider.dart b/mobile/lib/providers/tab.provider.dart index 2abed7c395e50..16dfbfd5eaa12 100644 --- a/mobile/lib/providers/tab.provider.dart +++ b/mobile/lib/providers/tab.provider.dart @@ -1,11 +1,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; -enum TabEnum { - home, - search, - sharing, - library, -} +enum TabEnum { home, search, sharing, library, collections } /// Provides the currently active tab final tabProvider = StateProvider( diff --git a/mobile/lib/routing/router.dart b/mobile/lib/routing/router.dart index 211c847726095..0d9842f2eccf1 100644 --- a/mobile/lib/routing/router.dart +++ b/mobile/lib/routing/router.dart @@ -13,6 +13,7 @@ import 'package:immich_mobile/pages/backup/backup_album_selection.page.dart'; import 'package:immich_mobile/pages/backup/backup_controller.page.dart'; import 'package:immich_mobile/pages/backup/backup_options.page.dart'; import 'package:immich_mobile/pages/backup/failed_backup_status.page.dart'; +import 'package:immich_mobile/pages/collections/collections.page.dart'; import 'package:immich_mobile/pages/common/activities.page.dart'; import 'package:immich_mobile/pages/common/album_additional_shared_user_selection.page.dart'; import 'package:immich_mobile/pages/common/album_asset_selection.page.dart'; @@ -114,6 +115,10 @@ class AppRouter extends RootStackRouter { page: LibraryRoute.page, guards: [_authGuard, _duplicateGuard], ), + AutoRoute( + page: CollectionsRoute.page, + guards: [_authGuard, _duplicateGuard], + ), ], transitionsBuilder: TransitionsBuilders.fadeIn, ), diff --git a/mobile/lib/routing/router.gr.dart b/mobile/lib/routing/router.gr.dart index 90fc4cb0fe96c..1e4dcee1254fd 100644 --- a/mobile/lib/routing/router.gr.dart +++ b/mobile/lib/routing/router.gr.dart @@ -555,6 +555,25 @@ class ChangePasswordRoute extends PageRouteInfo { ); } +/// generated route for +/// [CollectionsPage] +class CollectionsRoute extends PageRouteInfo { + const CollectionsRoute({List? children}) + : super( + CollectionsRoute.name, + initialChildren: children, + ); + + static const String name = 'CollectionsRoute'; + + static PageInfo page = PageInfo( + name, + builder: (data) { + return const CollectionsPage(); + }, + ); +} + /// generated route for /// [CreateAlbumPage] class CreateAlbumRoute extends PageRouteInfo { diff --git a/mobile/lib/widgets/common/immich_app_bar.dart b/mobile/lib/widgets/common/immich_app_bar.dart index 8e2465fc9ca3d..4b1640f698396 100644 --- a/mobile/lib/widgets/common/immich_app_bar.dart +++ b/mobile/lib/widgets/common/immich_app_bar.dart @@ -185,7 +185,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { ), actions: [ if (action != null) - Padding(padding: const EdgeInsets.only(right: 20), child: action!), + Padding(padding: const EdgeInsets.only(right: 16), child: action!), Padding( padding: const EdgeInsets.only(right: 20), child: buildBackupIndicator(),