mirror of
https://github.com/immich-app/immich.git
synced 2024-11-24 08:52:28 +02:00
refactor(mobile): log asyncvalue errors (#5327)
* refactor: scaffoldwhen to log errors during scaffold body render * refactor: onError and onLoading scaffoldbody * refactor: more scaffold body to custom extension * refactor: add skiploadingonrefresh * Snackbar color --------- Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
parent
0fe704c6f9
commit
513f252a0c
@ -4,22 +4,32 @@ import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|||||||
import 'package:immich_mobile/shared/ui/scaffold_error_body.dart';
|
import 'package:immich_mobile/shared/ui/scaffold_error_body.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
extension ScaffoldBody<T> on AsyncValue<T> {
|
extension LogOnError<T> on AsyncValue<T> {
|
||||||
static final Logger _scaffoldBodyLog = Logger("ScaffoldBody");
|
static final Logger _asyncErrorLogger = Logger("AsyncValue");
|
||||||
|
|
||||||
Widget scaffoldBodyWhen({
|
Widget widgetWhen({
|
||||||
|
bool skipLoadingOnRefresh = true,
|
||||||
|
Widget Function()? onLoading,
|
||||||
|
Widget Function(Object? error, StackTrace? stack)? onError,
|
||||||
required Widget Function(T data) onData,
|
required Widget Function(T data) onData,
|
||||||
Widget? onError,
|
|
||||||
}) {
|
}) {
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return const Center(
|
bool skip = false;
|
||||||
child: ImmichLoadingIndicator(),
|
if (isRefreshing) {
|
||||||
);
|
skip = skipLoadingOnRefresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skip) {
|
||||||
|
return onLoading?.call() ??
|
||||||
|
const Center(
|
||||||
|
child: ImmichLoadingIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasError && !hasValue) {
|
if (hasError && !hasValue) {
|
||||||
_scaffoldBodyLog.severe("Error occured in AsyncValue", error, stackTrace);
|
_asyncErrorLogger.severe("Error occured", error, stackTrace);
|
||||||
return onError ?? const ScaffoldErrorBody();
|
return onError?.call(error, stackTrace) ?? const ScaffoldErrorBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
return onData(requireValue);
|
return onData(requireValue);
|
||||||
|
@ -4,12 +4,12 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/activities/models/activity.model.dart';
|
import 'package:immich_mobile/modules/activities/models/activity.model.dart';
|
||||||
import 'package:immich_mobile/modules/activities/providers/activity.provider.dart';
|
import 'package:immich_mobile/modules/activities/providers/activity.provider.dart';
|
||||||
import 'package:immich_mobile/shared/models/store.dart';
|
import 'package:immich_mobile/shared/models/store.dart';
|
||||||
import 'package:immich_mobile/shared/ui/confirm_dialog.dart';
|
import 'package:immich_mobile/shared/ui/confirm_dialog.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
||||||
import 'package:immich_mobile/extensions/datetime_extensions.dart';
|
import 'package:immich_mobile/extensions/datetime_extensions.dart';
|
||||||
import 'package:immich_mobile/utils/image_url_builder.dart';
|
import 'package:immich_mobile/utils/image_url_builder.dart';
|
||||||
@ -88,7 +88,7 @@ class ActivitiesPage extends HookConsumerWidget {
|
|||||||
width: 40,
|
width: 40,
|
||||||
height: 30,
|
height: 30,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: CachedNetworkImageProvider(
|
image: CachedNetworkImageProvider(
|
||||||
getThumbnailUrlForRemoteId(
|
getThumbnailUrlForRemoteId(
|
||||||
@ -231,11 +231,8 @@ class ActivitiesPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: Text(appBarTitle)),
|
appBar: AppBar(title: Text(appBarTitle)),
|
||||||
body: activities.maybeWhen(
|
body: activities.widgetWhen(
|
||||||
orElse: () {
|
onData: (data) {
|
||||||
return const Center(child: ImmichLoadingIndicator());
|
|
||||||
},
|
|
||||||
data: (data) {
|
|
||||||
final liked = data.firstWhereOrNull(
|
final liked = data.firstWhereOrNull(
|
||||||
(a) =>
|
(a) =>
|
||||||
a.type == ActivityType.like &&
|
a.type == ActivityType.like &&
|
||||||
|
@ -180,9 +180,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: const Icon(Icons.arrow_back_ios_new_rounded),
|
icon: const Icon(Icons.arrow_back_ios_new_rounded),
|
||||||
onPressed: () {
|
onPressed: () => context.autoPop(null),
|
||||||
context.autoPop(null);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: Text("translated_text_options".tr()),
|
title: Text("translated_text_options".tr()),
|
||||||
|
@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
|
import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
|
||||||
import 'package:immich_mobile/modules/album/providers/album_detail.provider.dart';
|
import 'package:immich_mobile/modules/album/providers/album_detail.provider.dart';
|
||||||
@ -17,7 +18,6 @@ import 'package:immich_mobile/routing/router.dart';
|
|||||||
import 'package:immich_mobile/shared/models/album.dart';
|
import 'package:immich_mobile/shared/models/album.dart';
|
||||||
import 'package:immich_mobile/shared/models/asset.dart';
|
import 'package:immich_mobile/shared/models/asset.dart';
|
||||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
||||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||||
|
|
||||||
@ -260,13 +260,11 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||||||
error: (error, stackTrace) => AppBar(title: const Text("Error")),
|
error: (error, stackTrace) => AppBar(title: const Text("Error")),
|
||||||
loading: () => AppBar(),
|
loading: () => AppBar(),
|
||||||
),
|
),
|
||||||
body: album.when(
|
body: album.widgetWhen(
|
||||||
data: (data) => WillPopScope(
|
onData: (data) => WillPopScope(
|
||||||
onWillPop: onWillPop,
|
onWillPop: onWillPop,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () => titleFocusNode.unfocus(),
|
||||||
titleFocusNode.unfocus();
|
|
||||||
},
|
|
||||||
child: ImmichAssetGrid(
|
child: ImmichAssetGrid(
|
||||||
renderList: data.renderList,
|
renderList: data.renderList,
|
||||||
listener: selectionListener,
|
listener: selectionListener,
|
||||||
@ -285,10 +283,6 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
error: (e, _) => Center(child: Text("Error loading album info!\n$e")),
|
|
||||||
loading: () => const Center(
|
|
||||||
child: ImmichLoadingIndicator(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
|
import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/providers/render_list.provider.dart';
|
import 'package:immich_mobile/modules/asset_viewer/providers/render_list.provider.dart';
|
||||||
@ -85,12 +86,8 @@ class AssetSelectionPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: renderList.when(
|
body: renderList.widgetWhen(
|
||||||
data: (data) => buildBody(data),
|
onData: (data) => buildBody(data),
|
||||||
error: (error, stackTrace) => Center(
|
|
||||||
child: Text(error.toString()),
|
|
||||||
),
|
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/album/providers/suggested_shared_users.provider.dart';
|
import 'package:immich_mobile/modules/album/providers/suggested_shared_users.provider.dart';
|
||||||
import 'package:immich_mobile/shared/models/album.dart';
|
import 'package:immich_mobile/shared/models/album.dart';
|
||||||
import 'package:immich_mobile/shared/models/user.dart';
|
import 'package:immich_mobile/shared/models/user.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
||||||
|
|
||||||
class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
||||||
@ -137,8 +137,8 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: suggestedShareUsers.when(
|
body: suggestedShareUsers.widgetWhen(
|
||||||
data: (users) {
|
onData: (users) {
|
||||||
for (var sharedUsers in album.sharedUsers) {
|
for (var sharedUsers in album.sharedUsers) {
|
||||||
users.removeWhere(
|
users.removeWhere(
|
||||||
(u) => u.id == sharedUsers.id || u.id == album.ownerId,
|
(u) => u.id == sharedUsers.id || u.id == album.ownerId,
|
||||||
@ -147,10 +147,6 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
return buildUserList(users);
|
return buildUserList(users);
|
||||||
},
|
},
|
||||||
error: (e, _) => Text("Error loading suggested users $e"),
|
|
||||||
loading: () => const Center(
|
|
||||||
child: ImmichLoadingIndicator(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/album/providers/album_title.provider.dart';
|
import 'package:immich_mobile/modules/album/providers/album_title.provider.dart';
|
||||||
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
|
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
|
||||||
@ -9,7 +10,6 @@ import 'package:immich_mobile/modules/album/providers/suggested_shared_users.pro
|
|||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/shared/models/asset.dart';
|
import 'package:immich_mobile/shared/models/asset.dart';
|
||||||
import 'package:immich_mobile/shared/models/user.dart';
|
import 'package:immich_mobile/shared/models/user.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
||||||
|
|
||||||
class SelectUserForSharingPage extends HookConsumerWidget {
|
class SelectUserForSharingPage extends HookConsumerWidget {
|
||||||
@ -42,7 +42,12 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
ScaffoldMessenger(
|
ScaffoldMessenger(
|
||||||
child: SnackBar(
|
child: SnackBar(
|
||||||
content: const Text('select_user_for_sharing_page_err_album').tr(),
|
content: Text(
|
||||||
|
'select_user_for_sharing_page_err_album',
|
||||||
|
style: context.textTheme.bodyLarge?.copyWith(
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
).tr(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -166,14 +171,10 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: suggestedShareUsers.when(
|
body: suggestedShareUsers.widgetWhen(
|
||||||
data: (users) {
|
onData: (users) {
|
||||||
return buildUserList(users);
|
return buildUserList(users);
|
||||||
},
|
},
|
||||||
error: (e, _) => Text("Error loading suggested users $e"),
|
|
||||||
loading: () => const Center(
|
|
||||||
child: ImmichLoadingIndicator(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/archive/providers/archive_asset_provider.dart';
|
import 'package:immich_mobile/modules/archive/providers/archive_asset_provider.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||||
@ -48,37 +49,33 @@ class ArchivePage extends HookConsumerWidget {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 64,
|
height: 64,
|
||||||
child: Card(
|
child: Card(
|
||||||
child: Column(
|
child: ListTile(
|
||||||
children: [
|
shape: const RoundedRectangleBorder(
|
||||||
ListTile(
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
shape: RoundedRectangleBorder(
|
),
|
||||||
borderRadius: BorderRadius.circular(10),
|
leading: const Icon(
|
||||||
),
|
Icons.unarchive_rounded,
|
||||||
leading: const Icon(
|
),
|
||||||
Icons.unarchive_rounded,
|
title: Text(
|
||||||
),
|
'control_bottom_app_bar_unarchive'.tr(),
|
||||||
title: Text(
|
style: const TextStyle(fontSize: 14),
|
||||||
'control_bottom_app_bar_unarchive'.tr(),
|
),
|
||||||
style: const TextStyle(fontSize: 14),
|
onTap: processing.value
|
||||||
),
|
? null
|
||||||
onTap: processing.value
|
: () async {
|
||||||
? null
|
processing.value = true;
|
||||||
: () async {
|
try {
|
||||||
processing.value = true;
|
await handleArchiveAssets(
|
||||||
try {
|
ref,
|
||||||
await handleArchiveAssets(
|
context,
|
||||||
ref,
|
selection.value.toList(),
|
||||||
context,
|
shouldArchive: false,
|
||||||
selection.value.toList(),
|
);
|
||||||
shouldArchive: false,
|
} finally {
|
||||||
);
|
processing.value = false;
|
||||||
} finally {
|
selectionEnabledHook.value = false;
|
||||||
processing.value = false;
|
}
|
||||||
selectionEnabledHook.value = false;
|
},
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -86,18 +83,13 @@ class ArchivePage extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return archivedAssets.when(
|
return Scaffold(
|
||||||
loading: () => Scaffold(
|
appBar: archivedAssets.maybeWhen(
|
||||||
appBar: buildAppBar("?"),
|
data: (data) => buildAppBar(data.totalAssets.toString()),
|
||||||
body: const Center(child: CircularProgressIndicator()),
|
orElse: () => buildAppBar("?"),
|
||||||
),
|
),
|
||||||
error: (error, stackTrace) => Scaffold(
|
body: archivedAssets.widgetWhen(
|
||||||
appBar: buildAppBar("Error"),
|
onData: (data) => data.isEmpty
|
||||||
body: Center(child: Text(error.toString())),
|
|
||||||
),
|
|
||||||
data: (data) => Scaffold(
|
|
||||||
appBar: buildAppBar(data.totalAssets.toString()),
|
|
||||||
body: data.isEmpty
|
|
||||||
? Center(
|
? Center(
|
||||||
child: Text('archive_page_no_archived_assets'.tr()),
|
child: Text('archive_page_no_archived_assets'.tr()),
|
||||||
)
|
)
|
||||||
|
@ -62,8 +62,14 @@ class AdvancedBottomSheet extends HookConsumerWidget {
|
|||||||
ClipboardData(text: assetDetail.toString()),
|
ClipboardData(text: assetDetail.toString()),
|
||||||
).then((_) {
|
).then((_) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
SnackBar(
|
||||||
content: Text("Copied to clipboard"),
|
content: Text(
|
||||||
|
"Copied to clipboard",
|
||||||
|
style: context.textTheme.bodyLarge
|
||||||
|
?.copyWith(
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -229,6 +229,9 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||||||
final snackBar = SnackBar(
|
final snackBar = SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
msg.tr(),
|
msg.tr(),
|
||||||
|
style: context.textTheme.bodyLarge?.copyWith(
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
);
|
);
|
||||||
|
@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/favorite/providers/favorite_provider.dart';
|
import 'package:immich_mobile/modules/favorite/providers/favorite_provider.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||||
@ -62,22 +63,18 @@ class FavoritesPage extends HookConsumerWidget {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 64,
|
height: 64,
|
||||||
child: Card(
|
child: Card(
|
||||||
child: Column(
|
child: ListTile(
|
||||||
children: [
|
shape: const RoundedRectangleBorder(
|
||||||
ListTile(
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
shape: RoundedRectangleBorder(
|
),
|
||||||
borderRadius: BorderRadius.circular(10),
|
leading: const Icon(
|
||||||
),
|
Icons.star_border,
|
||||||
leading: const Icon(
|
),
|
||||||
Icons.star_border,
|
title: const Text(
|
||||||
),
|
"Unfavorite",
|
||||||
title: const Text(
|
style: TextStyle(fontSize: 14),
|
||||||
"Unfavorite",
|
),
|
||||||
style: TextStyle(fontSize: 14),
|
onTap: processing.value ? null : unfavorite,
|
||||||
),
|
|
||||||
onTap: processing.value ? null : unfavorite,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -87,10 +84,8 @@ class FavoritesPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: buildAppBar(),
|
appBar: buildAppBar(),
|
||||||
body: ref.watch(favoriteAssetsProvider).when(
|
body: ref.watch(favoriteAssetsProvider).widgetWhen(
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
onData: (data) => data.isEmpty
|
||||||
error: (error, stackTrace) => Center(child: Text(error.toString())),
|
|
||||||
data: (data) => data.isEmpty
|
|
||||||
? Center(
|
? Center(
|
||||||
child: Text('favorites_page_no_favorites'.tr()),
|
child: Text('favorites_page_no_favorites'.tr()),
|
||||||
)
|
)
|
||||||
|
@ -5,13 +5,13 @@ import 'package:flutter/gestures.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/providers/render_list.provider.dart';
|
import 'package:immich_mobile/modules/asset_viewer/providers/render_list.provider.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
|
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid_view.dart';
|
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid_view.dart';
|
||||||
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
|
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
|
||||||
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
||||||
import 'package:immich_mobile/shared/models/asset.dart';
|
import 'package:immich_mobile/shared/models/asset.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||||
|
|
||||||
class ImmichAssetGrid extends HookConsumerWidget {
|
class ImmichAssetGrid extends HookConsumerWidget {
|
||||||
@ -130,12 +130,8 @@ class ImmichAssetGrid extends HookConsumerWidget {
|
|||||||
if (renderList != null) return buildAssetGridView(renderList!);
|
if (renderList != null) return buildAssetGridView(renderList!);
|
||||||
|
|
||||||
final renderListFuture = ref.watch(renderListProvider(assets!));
|
final renderListFuture = ref.watch(renderListProvider(assets!));
|
||||||
return renderListFuture.when(
|
return renderListFuture.widgetWhen(
|
||||||
data: (renderList) => buildAssetGridView(renderList),
|
onData: (renderList) => buildAssetGridView(renderList),
|
||||||
error: (err, stack) => Center(child: Text("$err")),
|
|
||||||
loading: () => const Center(
|
|
||||||
child: ImmichLoadingIndicator(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||||
import 'package:immich_mobile/modules/partner/providers/partner.provider.dart';
|
import 'package:immich_mobile/modules/partner/providers/partner.provider.dart';
|
||||||
import 'package:immich_mobile/shared/models/user.dart';
|
import 'package:immich_mobile/shared/models/user.dart';
|
||||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||||
|
|
||||||
class PartnerDetailPage extends HookConsumerWidget {
|
class PartnerDetailPage extends HookConsumerWidget {
|
||||||
@ -71,8 +71,8 @@ class PartnerDetailPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: assets.when(
|
body: assets.widgetWhen(
|
||||||
data: (renderList) => renderList.isEmpty
|
onData: (renderList) => renderList.isEmpty
|
||||||
? Padding(
|
? Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -84,8 +84,6 @@ class PartnerDetailPage extends HookConsumerWidget {
|
|||||||
onRefresh: () =>
|
onRefresh: () =>
|
||||||
ref.read(assetProvider.notifier).getPartnerAssets(partner),
|
ref.read(assetProvider.notifier).getPartnerAssets(partner),
|
||||||
),
|
),
|
||||||
error: (e, _) => Text("Error loading partners:\n$e"),
|
|
||||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||||
import 'package:immich_mobile/modules/search/providers/all_motion_photos.provider.dart';
|
import 'package:immich_mobile/modules/search/providers/all_motion_photos.provider.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
|
|
||||||
class AllMotionPhotosPage extends HookConsumerWidget {
|
class AllMotionPhotosPage extends HookConsumerWidget {
|
||||||
const AllMotionPhotosPage({super.key});
|
const AllMotionPhotosPage({super.key});
|
||||||
@ -21,14 +21,10 @@ class AllMotionPhotosPage extends HookConsumerWidget {
|
|||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: motionPhotos.when(
|
body: motionPhotos.widgetWhen(
|
||||||
data: (assets) => ImmichAssetGrid(
|
onData: (assets) => ImmichAssetGrid(
|
||||||
assets: assets,
|
assets: assets,
|
||||||
),
|
),
|
||||||
error: (e, s) => Text(e.toString()),
|
|
||||||
loading: () => const Center(
|
|
||||||
child: ImmichLoadingIndicator(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
|
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
|
||||||
import 'package:immich_mobile/modules/search/ui/explore_grid.dart';
|
import 'package:immich_mobile/modules/search/ui/explore_grid.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
|
|
||||||
class AllPeoplePage extends HookConsumerWidget {
|
class AllPeoplePage extends HookConsumerWidget {
|
||||||
const AllPeoplePage({super.key});
|
const AllPeoplePage({super.key});
|
||||||
@ -23,12 +23,8 @@ class AllPeoplePage extends HookConsumerWidget {
|
|||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: curatedPeople.when(
|
body: curatedPeople.widgetWhen(
|
||||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
onData: (people) => ExploreGrid(
|
||||||
error: (err, stack) => Center(
|
|
||||||
child: Text('Error: $err'),
|
|
||||||
),
|
|
||||||
data: (people) => ExploreGrid(
|
|
||||||
isPeople: true,
|
isPeople: true,
|
||||||
curatedContent: people,
|
curatedContent: people,
|
||||||
),
|
),
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||||
import 'package:immich_mobile/modules/search/providers/all_video_assets.provider.dart';
|
import 'package:immich_mobile/modules/search/providers/all_video_assets.provider.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
|
|
||||||
class AllVideosPage extends HookConsumerWidget {
|
class AllVideosPage extends HookConsumerWidget {
|
||||||
const AllVideosPage({super.key});
|
const AllVideosPage({super.key});
|
||||||
@ -21,14 +21,10 @@ class AllVideosPage extends HookConsumerWidget {
|
|||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: videos.when(
|
body: videos.widgetWhen(
|
||||||
data: (assets) => ImmichAssetGrid(
|
onData: (assets) => ImmichAssetGrid(
|
||||||
assets: assets,
|
assets: assets,
|
||||||
),
|
),
|
||||||
error: (e, s) => Text(e.toString()),
|
|
||||||
loading: () => const Center(
|
|
||||||
child: ImmichLoadingIndicator(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/search/models/curated_content.dart';
|
import 'package:immich_mobile/modules/search/models/curated_content.dart';
|
||||||
import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart';
|
import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart';
|
||||||
import 'package:immich_mobile/modules/search/ui/explore_grid.dart';
|
import 'package:immich_mobile/modules/search/ui/explore_grid.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class CuratedLocationPage extends HookConsumerWidget {
|
class CuratedLocationPage extends HookConsumerWidget {
|
||||||
@ -26,12 +26,8 @@ class CuratedLocationPage extends HookConsumerWidget {
|
|||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: curatedLocation.when(
|
body: curatedLocation.widgetWhen(
|
||||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
onData: (curatedLocations) => ExploreGrid(
|
||||||
error: (err, stack) => Center(
|
|
||||||
child: Text('Error: $err'),
|
|
||||||
),
|
|
||||||
data: (curatedLocations) => ExploreGrid(
|
|
||||||
curatedContent: curatedLocations
|
curatedContent: curatedLocations
|
||||||
.map(
|
.map(
|
||||||
(l) => CuratedContent(
|
(l) => CuratedContent(
|
||||||
|
@ -8,7 +8,6 @@ import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'
|
|||||||
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
|
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
|
||||||
import 'package:immich_mobile/modules/search/ui/person_name_edit_form.dart';
|
import 'package:immich_mobile/modules/search/ui/person_name_edit_form.dart';
|
||||||
import 'package:immich_mobile/shared/models/store.dart' as isar_store;
|
import 'package:immich_mobile/shared/models/store.dart' as isar_store;
|
||||||
import 'package:immich_mobile/shared/ui/scaffold_error_body.dart';
|
|
||||||
import 'package:immich_mobile/utils/image_url_builder.dart';
|
import 'package:immich_mobile/utils/image_url_builder.dart';
|
||||||
|
|
||||||
class PersonResultPage extends HookConsumerWidget {
|
class PersonResultPage extends HookConsumerWidget {
|
||||||
@ -112,7 +111,7 @@ class PersonResultPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: ref.watch(personAssetsProvider(personId)).scaffoldBodyWhen(
|
body: ref.watch(personAssetsProvider(personId)).widgetWhen(
|
||||||
onData: (renderList) => ImmichAssetGrid(
|
onData: (renderList) => ImmichAssetGrid(
|
||||||
renderList: renderList,
|
renderList: renderList,
|
||||||
topWidget: Padding(
|
topWidget: Padding(
|
||||||
@ -137,7 +136,6 @@ class PersonResultPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onError: const ScaffoldErrorBody(icon: Icons.person_off_outlined),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||||
import 'package:immich_mobile/modules/search/providers/recently_added.provider.dart';
|
import 'package:immich_mobile/modules/search/providers/recently_added.provider.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
|
|
||||||
class RecentlyAddedPage extends HookConsumerWidget {
|
class RecentlyAddedPage extends HookConsumerWidget {
|
||||||
const RecentlyAddedPage({super.key});
|
const RecentlyAddedPage({super.key});
|
||||||
@ -21,14 +21,10 @@ class RecentlyAddedPage extends HookConsumerWidget {
|
|||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: recents.when(
|
body: recents.widgetWhen(
|
||||||
data: (searchResponse) => ImmichAssetGrid(
|
onData: (searchResponse) => ImmichAssetGrid(
|
||||||
assets: searchResponse,
|
assets: searchResponse,
|
||||||
),
|
),
|
||||||
error: (e, s) => Text(e.toString()),
|
|
||||||
loading: () => const Center(
|
|
||||||
child: ImmichLoadingIndicator(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/search/models/curated_content.dart';
|
import 'package:immich_mobile/modules/search/models/curated_content.dart';
|
||||||
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
|
import 'package:immich_mobile/modules/search/providers/people.provider.dart';
|
||||||
@ -15,7 +16,7 @@ import 'package:immich_mobile/modules/search/ui/search_row_title.dart';
|
|||||||
import 'package:immich_mobile/modules/search/ui/search_suggestion_list.dart';
|
import 'package:immich_mobile/modules/search/ui/search_suggestion_list.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
import 'package:immich_mobile/shared/ui/scaffold_error_body.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class SearchPage extends HookConsumerWidget {
|
class SearchPage extends HookConsumerWidget {
|
||||||
@ -73,10 +74,9 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
buildPeople() {
|
buildPeople() {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: imageSize,
|
height: imageSize,
|
||||||
child: curatedPeople.when(
|
child: curatedPeople.widgetWhen(
|
||||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
onError: (error, stack) => const ScaffoldErrorBody(withIcon: false),
|
||||||
error: (err, stack) => Center(child: Text('Error: $err')),
|
onData: (people) => CuratedPeopleRow(
|
||||||
data: (people) => CuratedPeopleRow(
|
|
||||||
content: people.take(12).toList(),
|
content: people.take(12).toList(),
|
||||||
onTap: (content, index) {
|
onTap: (content, index) {
|
||||||
context.autoPush(
|
context.autoPush(
|
||||||
@ -97,10 +97,9 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
buildPlaces() {
|
buildPlaces() {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: imageSize,
|
height: imageSize,
|
||||||
child: curatedLocation.when(
|
child: curatedLocation.widgetWhen(
|
||||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
onError: (error, stack) => const ScaffoldErrorBody(withIcon: false),
|
||||||
error: (err, stack) => Center(child: Text('Error: $err')),
|
onData: (locations) => CuratedPlacesRow(
|
||||||
data: (locations) => CuratedPlacesRow(
|
|
||||||
isMapEnabled: isMapEnabled,
|
isMapEnabled: isMapEnabled,
|
||||||
content: locations
|
content: locations
|
||||||
.map(
|
.map(
|
||||||
|
@ -46,9 +46,11 @@ class SharedLinkItem extends ConsumerWidget {
|
|||||||
} else if (difference.inHours > 0) {
|
} else if (difference.inHours > 0) {
|
||||||
expiresText = "shared_link_expires_hours".plural(difference.inHours);
|
expiresText = "shared_link_expires_hours".plural(difference.inHours);
|
||||||
} else if (difference.inMinutes > 0) {
|
} else if (difference.inMinutes > 0) {
|
||||||
expiresText = "shared_link_expires_minutes".plural(difference.inMinutes);
|
expiresText =
|
||||||
|
"shared_link_expires_minutes".plural(difference.inMinutes);
|
||||||
} else if (difference.inSeconds > 0) {
|
} else if (difference.inSeconds > 0) {
|
||||||
expiresText = "shared_link_expires_seconds".plural(difference.inSeconds);
|
expiresText =
|
||||||
|
"shared_link_expires_seconds".plural(difference.inSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Text(
|
return Text(
|
||||||
@ -85,7 +87,12 @@ class SharedLinkItem extends ConsumerWidget {
|
|||||||
).then((_) {
|
).then((_) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: const Text("shared_link_clipboard_copied_massage").tr(),
|
content: Text(
|
||||||
|
"shared_link_clipboard_copied_massage",
|
||||||
|
style: context.textTheme.bodyLarge?.copyWith(
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
).tr(),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -162,9 +169,12 @@ class SharedLinkItem extends ConsumerWidget {
|
|||||||
Widget buildBottomInfo() {
|
Widget buildBottomInfo() {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
if (sharedLink.allowUpload) buildInfoChip("shared_link_info_chip_upload".tr()),
|
if (sharedLink.allowUpload)
|
||||||
if (sharedLink.allowDownload) buildInfoChip("shared_link_info_chip_download".tr()),
|
buildInfoChip("shared_link_info_chip_upload".tr()),
|
||||||
if (sharedLink.showMetadata) buildInfoChip("shared_link_info_chip_metadata".tr()),
|
if (sharedLink.allowDownload)
|
||||||
|
buildInfoChip("shared_link_info_chip_download".tr()),
|
||||||
|
if (sharedLink.showMetadata)
|
||||||
|
buildInfoChip("shared_link_info_chip_metadata".tr()),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -275,7 +275,12 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
|||||||
).then((_) {
|
).then((_) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: const Text("shared_link_clipboard_copied_massage").tr(),
|
content: Text(
|
||||||
|
"shared_link_clipboard_copied_massage",
|
||||||
|
style: context.textTheme.bodyLarge?.copyWith(
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
).tr(),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -2,11 +2,11 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/shared_link/models/shared_link.dart';
|
import 'package:immich_mobile/modules/shared_link/models/shared_link.dart';
|
||||||
import 'package:immich_mobile/modules/shared_link/providers/shared_link.provider.dart';
|
import 'package:immich_mobile/modules/shared_link/providers/shared_link.provider.dart';
|
||||||
import 'package:immich_mobile/modules/shared_link/ui/shared_link_item.dart';
|
import 'package:immich_mobile/modules/shared_link/ui/shared_link_item.dart';
|
||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
|
||||||
|
|
||||||
class SharedLinkPage extends HookConsumerWidget {
|
class SharedLinkPage extends HookConsumerWidget {
|
||||||
const SharedLinkPage({Key? key}) : super(key: key);
|
const SharedLinkPage({Key? key}) : super(key: key);
|
||||||
@ -18,7 +18,10 @@ class SharedLinkPage extends HookConsumerWidget {
|
|||||||
useEffect(
|
useEffect(
|
||||||
() {
|
() {
|
||||||
ref.read(sharedLinksStateProvider.notifier).fetchLinks();
|
ref.read(sharedLinksStateProvider.notifier).fetchLinks();
|
||||||
return () => ref.invalidate(sharedLinksStateProvider);
|
return () {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
ref.invalidate(sharedLinksStateProvider);
|
||||||
|
};
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
@ -113,11 +116,10 @@ class SharedLinkPage extends HookConsumerWidget {
|
|||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: sharedLinks.when(
|
child: sharedLinks.widgetWhen(
|
||||||
data: (links) =>
|
onError: (error, stackTrace) => buildNoShares(),
|
||||||
|
onData: (links) =>
|
||||||
links.isNotEmpty ? buildSharesList(links) : buildNoShares(),
|
links.isNotEmpty ? buildSharesList(links) : buildNoShares(),
|
||||||
error: (error, stackTrace) => buildNoShares(),
|
|
||||||
loading: () => const Center(child: ImmichLoadingIndicator()),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/delete_dialog.dart';
|
import 'package:immich_mobile/modules/home/ui/delete_dialog.dart';
|
||||||
@ -229,18 +230,13 @@ class TrashPage extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return trashedAssets.when(
|
return Scaffold(
|
||||||
loading: () => Scaffold(
|
appBar: trashedAssets.maybeWhen(
|
||||||
appBar: buildAppBar("?"),
|
orElse: () => buildAppBar("?"),
|
||||||
body: const Center(child: CircularProgressIndicator()),
|
data: (data) => buildAppBar(data.totalAssets.toString()),
|
||||||
),
|
),
|
||||||
error: (error, stackTrace) => Scaffold(
|
body: trashedAssets.widgetWhen(
|
||||||
appBar: buildAppBar("!"),
|
onData: (data) => data.isEmpty
|
||||||
body: Center(child: Text(error.toString())),
|
|
||||||
),
|
|
||||||
data: (data) => Scaffold(
|
|
||||||
appBar: buildAppBar(data.totalAssets.toString()),
|
|
||||||
body: data.isEmpty
|
|
||||||
? Center(
|
? Center(
|
||||||
child: Text('trash_page_no_assets'.tr()),
|
child: Text('trash_page_no_assets'.tr()),
|
||||||
)
|
)
|
||||||
@ -254,11 +250,9 @@ class TrashPage extends HookConsumerWidget {
|
|||||||
showMultiSelectIndicator: false,
|
showMultiSelectIndicator: false,
|
||||||
showStack: true,
|
showStack: true,
|
||||||
topWidget: Padding(
|
topWidget: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.symmetric(
|
||||||
top: 24,
|
horizontal: 12,
|
||||||
bottom: 24,
|
vertical: 24,
|
||||||
left: 12,
|
|
||||||
right: 12,
|
|
||||||
),
|
),
|
||||||
child: const Text(
|
child: const Text(
|
||||||
"trash_page_info",
|
"trash_page_info",
|
||||||
|
@ -4,9 +4,9 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|||||||
|
|
||||||
// Error widget to be used in Scaffold when an AsyncError is received
|
// Error widget to be used in Scaffold when an AsyncError is received
|
||||||
class ScaffoldErrorBody extends StatelessWidget {
|
class ScaffoldErrorBody extends StatelessWidget {
|
||||||
final IconData icon;
|
final bool withIcon;
|
||||||
|
|
||||||
const ScaffoldErrorBody({this.icon = Icons.error_outline, super.key});
|
const ScaffoldErrorBody({super.key, this.withIcon = true});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -14,19 +14,22 @@ class ScaffoldErrorBody extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
Text(
|
||||||
"scaffold_body_error_occured",
|
"scaffold_body_error_occured",
|
||||||
style:
|
style: context.textTheme.displayMedium,
|
||||||
TextStyle(fontSize: 14, fontWeight: FontWeight.bold, height: 3),
|
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
).tr(),
|
).tr(),
|
||||||
Center(
|
if (withIcon)
|
||||||
child: Icon(
|
Center(
|
||||||
icon,
|
child: Padding(
|
||||||
size: 100,
|
padding: const EdgeInsets.only(top: 15),
|
||||||
color: context.themeData.iconTheme.color?.withOpacity(0.5),
|
child: Icon(
|
||||||
|
Icons.error_outline,
|
||||||
|
size: 100,
|
||||||
|
color: context.themeData.iconTheme.color?.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,14 @@ class AppLogDetailPage extends HookConsumerWidget {
|
|||||||
Clipboard.setData(ClipboardData(text: stackTrace))
|
Clipboard.setData(ClipboardData(text: stackTrace))
|
||||||
.then((_) {
|
.then((_) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text("Copied to clipboard")),
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
"Copied to clipboard",
|
||||||
|
style: context.textTheme.bodyLarge?.copyWith(
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -98,7 +105,14 @@ class AppLogDetailPage extends HookConsumerWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
Clipboard.setData(ClipboardData(text: message)).then((_) {
|
Clipboard.setData(ClipboardData(text: message)).then((_) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text("Copied to clipboard")),
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
"Copied to clipboard",
|
||||||
|
style: context.textTheme.bodyLarge?.copyWith(
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user