mirror of
https://github.com/immich-app/immich.git
synced 2026-07-21 13:54:36 +03:00
Compare commits
2 Commits
refactor/a
...
refactor/u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9f4cd398d | ||
|
|
da0742ab8c |
@@ -16,7 +16,6 @@ import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/constants/locales.dart';
|
||||
import 'package:immich_mobile/domain/services/background_worker.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/codegen_loader.g.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
||||
@@ -24,13 +23,13 @@ import 'package:immich_mobile/pages/common/splash_screen.page.dart';
|
||||
import 'package:immich_mobile/platform/background_worker_lock_api.g.dart';
|
||||
import 'package:immich_mobile/providers/app_life_cycle.provider.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart';
|
||||
import 'package:immich_mobile/providers/view_intent/view_intent_handler.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/locale_provider.dart';
|
||||
import 'package:immich_mobile/providers/routes.provider.dart';
|
||||
import 'package:immich_mobile/providers/theme.provider.dart';
|
||||
import 'package:immich_mobile/providers/view_intent/view_intent_handler.provider.dart';
|
||||
import 'package:immich_mobile/routing/app_navigation_observer.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/services/deep_link.service.dart';
|
||||
@@ -272,8 +271,9 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
|
||||
theme: getThemeData(colorScheme: immichTheme.light, locale: context.locale),
|
||||
builder: (context, child) => ImmichTranslationProvider(
|
||||
translations: ImmichTranslations(
|
||||
submit: "submit".t(context: context),
|
||||
password: "password".t(context: context),
|
||||
submit: context.t.submit,
|
||||
password: context.t.password,
|
||||
undo: context.t.undo,
|
||||
),
|
||||
child: ImmichThemeProvider(colorScheme: context.colorScheme, child: child!),
|
||||
),
|
||||
|
||||
@@ -27,11 +27,17 @@ class ArchiveAction extends BaseAction {
|
||||
final context = ref.context;
|
||||
|
||||
final ids = assetsForAction(ref, assets).map((asset) => asset.id).toList(growable: false);
|
||||
await ref.read(assetServiceProvider).update(ids, visibility: const .some(.archive));
|
||||
final assetService = ref.read(assetServiceProvider);
|
||||
await assetService.update(ids, visibility: const .some(.archive));
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
ref.read(toastRepositoryProvider).success(context.t.archive_action_prompt(count: ids.length));
|
||||
ref
|
||||
.read(toastRepositoryProvider)
|
||||
.success(
|
||||
context.t.archive_action_prompt(count: ids.length),
|
||||
toast: .new(onUndo: () async => await assetService.update(ids, visibility: const .some(.timeline))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,10 +64,16 @@ class UnarchiveAction extends BaseAction {
|
||||
final context = ref.context;
|
||||
|
||||
final ids = assetsForAction(ref, assets).map((asset) => asset.id).toList(growable: false);
|
||||
await ref.read(assetServiceProvider).update(ids, visibility: const .some(.timeline));
|
||||
final assetService = ref.read(assetServiceProvider);
|
||||
await assetService.update(ids, visibility: const .some(.timeline));
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
ref.read(toastRepositoryProvider).success(context.t.unarchive_action_prompt(count: ids.length));
|
||||
ref
|
||||
.read(toastRepositoryProvider)
|
||||
.success(
|
||||
context.t.unarchive_action_prompt(count: ids.length),
|
||||
toast: .new(onUndo: () async => await assetService.update(ids, visibility: const .some(.archive))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,12 +45,18 @@ class TrashAction extends BaseAction {
|
||||
}
|
||||
|
||||
final ids = remoteIds.toList(growable: false);
|
||||
await ref.read(assetServiceProvider).trash(ids);
|
||||
final assetService = ref.read(assetServiceProvider);
|
||||
await assetService.trash(ids);
|
||||
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
ref.read(toastRepositoryProvider).success(context.t.trash_action_prompt(count: ids.length));
|
||||
ref
|
||||
.read(toastRepositoryProvider)
|
||||
.success(
|
||||
context.t.trash_action_prompt(count: ids.length),
|
||||
toast: .new(onUndo: () async => await assetService.restoreTrash(ids)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,10 +59,16 @@ class UnlockAction extends BaseAction {
|
||||
final context = ref.context;
|
||||
final ids = assetsForAction(ref, assets).map((asset) => asset.id).toList(growable: false);
|
||||
|
||||
await ref.read(assetServiceProvider).update(ids, visibility: const .some(.timeline));
|
||||
final assetService = ref.read(assetServiceProvider);
|
||||
await assetService.update(ids, visibility: const .some(.timeline));
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
ref.read(toastRepositoryProvider).success(context.t.remove_from_lock_folder_action_prompt(count: ids.length));
|
||||
ref
|
||||
.read(toastRepositoryProvider)
|
||||
.success(
|
||||
context.t.remove_from_lock_folder_action_prompt(count: ids.length),
|
||||
toast: .new(onUndo: () async => await assetService.update(ids, visibility: const .some(.locked))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,16 @@ class RestoreAction extends BaseAction {
|
||||
final context = ref.context;
|
||||
final ids = assetsForAction(ref, assets).map((asset) => asset.id).toList(growable: false);
|
||||
|
||||
await ref.read(assetServiceProvider).restoreTrash(ids);
|
||||
final assetService = ref.read(assetServiceProvider);
|
||||
await assetService.restoreTrash(ids);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
ref.read(toastRepositoryProvider).success(context.t.assets_restored_count(count: ids.length));
|
||||
ref
|
||||
.read(toastRepositoryProvider)
|
||||
.success(
|
||||
context.t.assets_restored_count(count: ids.length),
|
||||
toast: .new(onUndo: () async => await assetService.trash(ids)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,23 @@ class ToastRepository {
|
||||
const ToastRepository();
|
||||
|
||||
FutureOr<void> success(String message, {ToastOption? toast}) {
|
||||
snackbar.success(message, duration: toast?.timeout);
|
||||
snackbar.success(message, duration: toast?.timeout, action: toast?.action);
|
||||
}
|
||||
|
||||
FutureOr<void> info(String message, {ToastOption? toast}) {
|
||||
snackbar.info(message, duration: toast?.timeout);
|
||||
snackbar.info(message, duration: toast?.timeout, action: toast?.action);
|
||||
}
|
||||
|
||||
FutureOr<void> error(String message, {ToastOption? toast}) {
|
||||
snackbar.error(message, duration: toast?.timeout);
|
||||
snackbar.error(message, duration: toast?.timeout, action: toast?.action);
|
||||
}
|
||||
}
|
||||
|
||||
extension on ToastOption {
|
||||
SnackbarAction? get action {
|
||||
if (onUndo == null) {
|
||||
return null;
|
||||
}
|
||||
return SnackbarAction(onPressed: onUndo!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_ui/immich_ui.dart';
|
||||
import 'package:immich_ui/src/internal.dart';
|
||||
|
||||
final scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
|
||||
|
||||
class SnackbarAction {
|
||||
final String? label;
|
||||
final FutureOr<void> Function() onPressed;
|
||||
|
||||
const SnackbarAction({this.label, required this.onPressed});
|
||||
}
|
||||
|
||||
class SnackbarManager {
|
||||
const SnackbarManager();
|
||||
|
||||
@@ -10,6 +20,7 @@ class SnackbarManager {
|
||||
String message,
|
||||
SnackbarType type, {
|
||||
Duration? duration,
|
||||
SnackbarAction? action,
|
||||
}) {
|
||||
final messenger = scaffoldMessengerKey.currentState;
|
||||
final context = scaffoldMessengerKey.currentContext;
|
||||
@@ -19,10 +30,10 @@ class SnackbarManager {
|
||||
|
||||
duration ??= const .new(seconds: 4);
|
||||
messenger.hideCurrentSnackBar();
|
||||
return messenger.showSnackBar(_build(context, message, type, duration));
|
||||
return messenger.showSnackBar(_build(context, message, type, duration, action));
|
||||
}
|
||||
|
||||
SnackBar _build(BuildContext context, String message, SnackbarType type, Duration duration) {
|
||||
SnackBar _build(BuildContext context, String message, SnackbarType type, Duration duration, SnackbarAction? action) {
|
||||
final theme = Theme.of(context);
|
||||
final colors = theme.extension<ImmichColors>() ?? ImmichColors.harmonized(theme.colorScheme);
|
||||
final (IconData icon, Color background, Color foreground) = switch (type) {
|
||||
@@ -31,11 +42,21 @@ class SnackbarManager {
|
||||
.error => (Icons.warning_rounded, colors.error, colors.onError),
|
||||
};
|
||||
|
||||
SnackBarAction? snackAction;
|
||||
if (action != null) {
|
||||
snackAction = .new(
|
||||
label: action.label ?? context.translations.undo,
|
||||
onPressed: action.onPressed,
|
||||
textColor: foreground,
|
||||
);
|
||||
}
|
||||
|
||||
return SnackBar(
|
||||
behavior: .floating,
|
||||
backgroundColor: background,
|
||||
duration: duration,
|
||||
shape: const RoundedRectangleBorder(borderRadius: .all(.circular(ImmichRadius.sm))),
|
||||
persist: false,
|
||||
content: Row(
|
||||
children: [
|
||||
Icon(icon, color: foreground, size: ImmichIconSize.sm),
|
||||
@@ -50,17 +71,27 @@ class SnackbarManager {
|
||||
),
|
||||
],
|
||||
),
|
||||
action: snackAction,
|
||||
);
|
||||
}
|
||||
|
||||
ScaffoldFeatureController<SnackBar, SnackBarClosedReason>? info(String message, {Duration? duration}) =>
|
||||
show(message, .info, duration: duration);
|
||||
ScaffoldFeatureController<SnackBar, SnackBarClosedReason>? info(
|
||||
String message, {
|
||||
Duration? duration,
|
||||
SnackbarAction? action,
|
||||
}) => show(message, .info, duration: duration, action: action);
|
||||
|
||||
ScaffoldFeatureController<SnackBar, SnackBarClosedReason>? success(String message, {Duration? duration}) =>
|
||||
show(message, .success, duration: duration);
|
||||
ScaffoldFeatureController<SnackBar, SnackBarClosedReason>? success(
|
||||
String message, {
|
||||
Duration? duration,
|
||||
SnackbarAction? action,
|
||||
}) => show(message, .success, duration: duration, action: action);
|
||||
|
||||
ScaffoldFeatureController<SnackBar, SnackBarClosedReason>? error(String message, {Duration? duration}) =>
|
||||
show(message, .error, duration: duration);
|
||||
ScaffoldFeatureController<SnackBar, SnackBarClosedReason>? error(
|
||||
String message, {
|
||||
Duration? duration,
|
||||
SnackbarAction? action,
|
||||
}) => show(message, .error, duration: duration, action: action);
|
||||
}
|
||||
|
||||
const snackbar = SnackbarManager();
|
||||
|
||||
@@ -1,27 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ImmichTranslations {
|
||||
late String submit;
|
||||
late String password;
|
||||
final String submit;
|
||||
final String password;
|
||||
final String undo;
|
||||
|
||||
ImmichTranslations({String? submit, String? password}) {
|
||||
this.submit = submit ?? 'Submit';
|
||||
this.password = password ?? 'Password';
|
||||
}
|
||||
const ImmichTranslations({String? submit, String? password, String? undo})
|
||||
: submit = submit ?? 'Submit',
|
||||
password = password ?? 'Password',
|
||||
undo = undo ?? 'Undo';
|
||||
}
|
||||
|
||||
class ImmichTranslationProvider extends InheritedWidget {
|
||||
final ImmichTranslations? translations;
|
||||
|
||||
const ImmichTranslationProvider({
|
||||
super.key,
|
||||
this.translations,
|
||||
required super.child,
|
||||
});
|
||||
const ImmichTranslationProvider({super.key, this.translations, required super.child});
|
||||
|
||||
static ImmichTranslations of(BuildContext context) {
|
||||
final provider = context.dependOnInheritedWidgetOfExactType<ImmichTranslationProvider>();
|
||||
return provider?.translations ?? ImmichTranslations();
|
||||
return provider?.translations ?? const ImmichTranslations();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user