2022-11-30 09:58:07 -07:00
import ' dart:async ' ;
2022-11-05 18:21:55 -07:00
import ' package:auto_route/auto_route.dart ' ;
import ' package:easy_localization/easy_localization.dart ' ;
2022-02-03 09:06:44 -07:00
import ' package:flutter/material.dart ' ;
import ' package:flutter_hooks/flutter_hooks.dart ' ;
2022-11-08 10:00:24 -07:00
import ' package:fluttertoast/fluttertoast.dart ' ;
2022-02-03 09:06:44 -07:00
import ' package:hooks_riverpod/hooks_riverpod.dart ' ;
2022-11-05 18:21:55 -07:00
import ' package:immich_mobile/modules/album/providers/album.provider.dart ' ;
import ' package:immich_mobile/modules/album/services/album.service.dart ' ;
2022-09-28 09:30:38 -07:00
import ' package:immich_mobile/modules/home/providers/home_page_render_list_provider.dart ' ;
2022-10-14 13:37:15 -07:00
import ' package:immich_mobile/modules/home/providers/multiselect.provider.dart ' ;
2022-10-01 01:33:06 -07:00
import ' package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart ' ;
2022-02-09 11:41:02 -07:00
import ' package:immich_mobile/modules/home/ui/control_bottom_app_bar.dart ' ;
2022-02-03 09:06:44 -07:00
import ' package:immich_mobile/modules/home/ui/immich_sliver_appbar.dart ' ;
2022-08-13 13:51:09 -07:00
import ' package:immich_mobile/modules/home/ui/profile_drawer/profile_drawer.dart ' ;
2022-08-20 14:19:40 -07:00
import ' package:immich_mobile/modules/settings/providers/app_settings.provider.dart ' ;
import ' package:immich_mobile/modules/settings/services/app_settings.service.dart ' ;
2022-11-05 18:21:55 -07:00
import ' package:immich_mobile/routing/router.dart ' ;
2022-11-08 10:00:24 -07:00
import ' package:immich_mobile/shared/models/asset.dart ' ;
2022-04-23 19:08:45 -07:00
import ' package:immich_mobile/shared/providers/asset.provider.dart ' ;
2022-03-21 23:22:04 -07:00
import ' package:immich_mobile/shared/providers/server_info.provider.dart ' ;
2022-02-14 09:40:41 -07:00
import ' package:immich_mobile/shared/providers/websocket.provider.dart ' ;
2022-10-06 13:41:56 -07:00
import ' package:immich_mobile/shared/services/share.service.dart ' ;
2022-11-30 09:58:07 -07:00
import ' package:immich_mobile/shared/ui/immich_loading_indicator.dart ' ;
2022-11-05 18:21:55 -07:00
import ' package:immich_mobile/shared/ui/immich_toast.dart ' ;
2022-10-06 13:41:56 -07:00
import ' package:openapi/api.dart ' ;
2022-02-03 09:06:44 -07:00
class HomePage extends HookConsumerWidget {
const HomePage ( { Key ? key } ) : super ( key: key ) ;
@ override
Widget build ( BuildContext context , WidgetRef ref ) {
2022-08-20 14:19:40 -07:00
final appSettingService = ref . watch ( appSettingsServiceProvider ) ;
2022-09-28 09:30:38 -07:00
var renderList = ref . watch ( renderListProvider ) ;
2022-10-14 13:37:15 -07:00
final multiselectEnabled = ref . watch ( multiselectProvider . notifier ) ;
2022-11-05 18:21:55 -07:00
final selectionEnabledHook = useState ( false ) ;
2022-11-08 10:00:24 -07:00
final selection = useState ( < Asset > { } ) ;
2022-11-05 18:21:55 -07:00
final albums = ref . watch ( albumProvider ) ;
final albumService = ref . watch ( albumServiceProvider ) ;
2022-02-03 21:08:22 -07:00
2022-11-30 09:58:07 -07:00
final tipOneOpacity = useState ( 0.0 ) ;
2022-07-13 05:23:48 -07:00
useEffect (
( ) {
ref . read ( websocketProvider . notifier ) . connect ( ) ;
ref . read ( assetProvider . notifier ) . getAllAsset ( ) ;
2022-11-05 18:21:55 -07:00
ref . read ( albumProvider . notifier ) . getAllAlbums ( ) ;
2022-07-13 05:23:48 -07:00
ref . watch ( serverInfoProvider . notifier ) . getServerVersion ( ) ;
2022-11-05 18:21:55 -07:00
selectionEnabledHook . addListener ( ( ) {
multiselectEnabled . state = selectionEnabledHook . value ;
} ) ;
return ( ) {
selectionEnabledHook . dispose ( ) ;
} ;
2022-07-13 05:23:48 -07:00
} ,
[ ] ,
) ;
2022-02-03 20:01:14 -07:00
2022-04-03 10:31:45 -07:00
void reloadAllAsset ( ) {
ref . read ( assetProvider . notifier ) . getAllAsset ( ) ;
}
2022-10-01 01:33:06 -07:00
Widget buildBody ( ) {
2022-10-06 13:41:56 -07:00
void selectionListener (
2022-10-14 13:37:15 -07:00
bool multiselect ,
2022-11-08 10:00:24 -07:00
Set < Asset > selectedAssets ,
2022-10-14 13:37:15 -07:00
) {
2022-11-05 18:21:55 -07:00
selectionEnabledHook . value = multiselect ;
2022-10-06 13:41:56 -07:00
selection . value = selectedAssets ;
2022-04-30 08:55:27 -07:00
}
2022-10-06 13:41:56 -07:00
void onShareAssets ( ) {
ref . watch ( shareServiceProvider ) . shareAssets ( selection . value . toList ( ) ) ;
2022-11-05 18:21:55 -07:00
selectionEnabledHook . value = false ;
2022-10-06 13:41:56 -07:00
}
void onDelete ( ) {
ref . watch ( assetProvider . notifier ) . deleteAssets ( selection . value ) ;
2022-11-05 18:21:55 -07:00
selectionEnabledHook . value = false ;
}
2022-11-08 10:00:24 -07:00
Iterable < Asset > remoteOnlySelection ( ) {
final Set < Asset > assets = selection . value ;
final bool onlyRemote = assets . every ( ( e ) = > e . isRemote ) ;
if ( ! onlyRemote ) {
ImmichToast . show (
context: context ,
msg: " Can not add local assets to albums yet, skipping " ,
gravity: ToastGravity . BOTTOM ,
) ;
return assets . where ( ( a ) = > a . isRemote ) ;
}
return assets ;
}
2022-11-05 18:21:55 -07:00
void onAddToAlbum ( AlbumResponseDto album ) async {
2022-11-08 10:00:24 -07:00
final Iterable < Asset > assets = remoteOnlySelection ( ) ;
if ( assets . isEmpty ) {
return ;
}
2022-11-05 18:21:55 -07:00
final result = await albumService . addAdditionalAssetToAlbum (
2022-11-08 10:00:24 -07:00
assets ,
2022-11-06 19:41:10 -07:00
album . id ,
) ;
2022-11-05 18:21:55 -07:00
if ( result ! = null ) {
if ( result . alreadyInAlbum . isNotEmpty ) {
ImmichToast . show (
context: context ,
msg: " home_page_add_to_album_conflicts " . tr (
namedArgs: {
" album " : album . albumName ,
" added " : result . successfullyAdded . toString ( ) ,
" failed " : result . alreadyInAlbum . length . toString ( )
} ,
) ,
) ;
} else {
ImmichToast . show (
context: context ,
msg: " home_page_add_to_album_success " . tr (
namedArgs: {
" album " : album . albumName ,
" added " : result . successfullyAdded . toString ( ) ,
} ,
) ,
2022-11-08 10:00:24 -07:00
toastType: ToastType . success ,
2022-11-05 18:21:55 -07:00
) ;
}
selectionEnabledHook . value = false ;
}
}
void onCreateNewAlbum ( ) async {
2022-11-08 10:00:24 -07:00
final Iterable < Asset > assets = remoteOnlySelection ( ) ;
if ( assets . isEmpty ) {
return ;
}
final result = await albumService . createAlbumWithGeneratedName ( assets ) ;
2022-11-05 18:21:55 -07:00
if ( result ! = null ) {
ref . watch ( albumProvider . notifier ) . getAllAlbums ( ) ;
selectionEnabledHook . value = false ;
AutoRouter . of ( context ) . push ( AlbumViewerRoute ( albumId: result . id ) ) ;
}
2022-10-01 10:19:40 -07:00
}
2022-11-30 09:58:07 -07:00
buildLoadingIndicator ( ) {
Timer ( const Duration ( seconds: 2 ) , ( ) {
tipOneOpacity . value = 1 ;
} ) ;
return Center (
child: Column (
mainAxisAlignment: MainAxisAlignment . center ,
children: [
const ImmichLoadingIndicator ( ) ,
Padding (
padding: const EdgeInsets . only ( top: 16.0 ) ,
child: Text (
' Building the timeline ' ,
style: TextStyle (
fontWeight: FontWeight . w600 ,
fontSize: 16 ,
color: Theme . of ( context ) . primaryColor ,
) ,
) ,
) ,
AnimatedOpacity (
duration: const Duration ( milliseconds: 500 ) ,
opacity: tipOneOpacity . value ,
child: const SizedBox (
width: 250 ,
child: Padding (
padding: EdgeInsets . only ( top: 8.0 ) ,
child: Text (
' If this is your first time using the app, please make sure to choose a backup album(s) so that the timeline can populate photos and videos in the album(s). ' ,
textAlign: TextAlign . justify ,
style: TextStyle (
fontSize: 12 ,
) ,
) ,
) ,
) ,
)
] ,
) ,
) ;
}
2022-02-03 21:18:21 -07:00
return SafeArea (
2022-10-14 13:37:15 -07:00
bottom: ! multiselectEnabled . state ,
2022-11-05 18:21:55 -07:00
top: true ,
2022-02-09 11:41:02 -07:00
child: Stack (
children: [
2022-04-30 15:03:45 -07:00
CustomScrollView (
slivers: [
2022-11-05 18:21:55 -07:00
if ( ! multiselectEnabled . state )
2022-11-06 19:41:10 -07:00
ImmichSliverAppBar (
onPopBack: reloadAllAsset ,
) ,
2022-04-30 15:03:45 -07:00
] ,
) ,
Padding (
2022-11-05 18:21:55 -07:00
padding: EdgeInsets . only (
2022-11-06 19:41:10 -07:00
top: selectionEnabledHook . value ? 0 : 60 ,
bottom: 0.0 ,
) ,
2022-11-30 09:58:07 -07:00
child: ref . watch ( assetProvider ) . isEmpty
? buildLoadingIndicator ( )
: ImmichAssetGrid (
renderList: renderList ,
assetsPerRow: appSettingService
. getSetting ( AppSettingsEnum . tilesPerRow ) ,
showStorageIndicator: appSettingService
. getSetting ( AppSettingsEnum . storageIndicator ) ,
listener: selectionListener ,
selectionActive: selectionEnabledHook . value ,
) ,
2022-02-09 11:41:02 -07:00
) ,
2022-11-06 19:41:10 -07:00
if ( selectionEnabledHook . value )
2022-10-06 13:41:56 -07:00
ControlBottomAppBar (
onShare: onShareAssets ,
onDelete: onDelete ,
2022-11-05 18:21:55 -07:00
onAddToAlbum: onAddToAlbum ,
albums: albums ,
onCreateNewAlbum: onCreateNewAlbum ,
2022-10-06 13:41:56 -07:00
) ,
2022-02-09 11:41:02 -07:00
] ,
2022-02-03 21:08:22 -07:00
) ,
2022-02-03 20:01:14 -07:00
) ;
2022-02-03 09:06:44 -07:00
}
return Scaffold (
drawer: const ProfileDrawer ( ) ,
2022-10-01 01:33:06 -07:00
body: buildBody ( ) ,
2022-02-03 21:08:22 -07:00
) ;
}
}