29
This commit is contained in:
18185
mobile/lib/generated/codegen_loader.g.dart
generated
18185
mobile/lib/generated/codegen_loader.g.dart
generated
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@ import 'package:timezone/data/latest.dart';
|
||||
|
||||
void main() async {
|
||||
ImmichWidgetsBinding();
|
||||
EasyLocalization.logger.enableBuildModes = [];
|
||||
final db = await Bootstrap.initIsar();
|
||||
await Bootstrap.initDomain(db);
|
||||
await initApp();
|
||||
|
||||
@@ -43,7 +43,7 @@ class AlbumControlButton extends ConsumerWidget {
|
||||
key: const ValueKey('add_users_button'),
|
||||
iconData: Icons.person_add_alt_rounded,
|
||||
onPressed: onAddUsersPressed,
|
||||
labelText: "album_viewer_page_share_add_users".tr(),
|
||||
labelText: "page_share_add_users".tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -46,7 +46,7 @@ class AlbumViewer extends HookConsumerWidget {
|
||||
if (!isSuccess) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "album_viewer_appbar_share_err_remove".tr(),
|
||||
msg: "appbar_share_err_remove".tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
|
||||
@@ -85,7 +85,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
Widget buildSelectedAlbumName() {
|
||||
var text = "backup_controller_page_backup_selected".tr();
|
||||
var text = "backup_selected".tr();
|
||||
var albums = ref.watch(backupProvider).selectedBackupAlbums;
|
||||
|
||||
if (albums.isNotEmpty) {
|
||||
@@ -110,7 +110,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
"backup_controller_page_none_selected".tr(),
|
||||
"none_selected".tr(),
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
@@ -120,7 +120,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
Widget buildExcludedAlbumName() {
|
||||
var text = "backup_controller_page_excluded".tr();
|
||||
var text = "excluded".tr();
|
||||
var albums = ref.watch(backupProvider).excludedBackupAlbums;
|
||||
|
||||
if (albums.isNotEmpty) {
|
||||
@@ -309,22 +309,22 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
? [
|
||||
buildFolderSelectionTile(),
|
||||
BackupInfoCard(
|
||||
title: "backup_controller_page_total".tr(),
|
||||
subtitle: "backup_controller_page_total_sub".tr(),
|
||||
title: "total".tr(),
|
||||
subtitle: "total_sub".tr(),
|
||||
info: ref.watch(backupProvider).availableAlbums.isEmpty
|
||||
? "..."
|
||||
: "${backupState.allUniqueAssets.length}",
|
||||
),
|
||||
BackupInfoCard(
|
||||
title: "backup_controller_page_backup".tr(),
|
||||
subtitle: "backup_controller_page_backup_sub".tr(),
|
||||
title: "backup".tr(),
|
||||
subtitle: "backup_sub".tr(),
|
||||
info: ref.watch(backupProvider).availableAlbums.isEmpty
|
||||
? "..."
|
||||
: "${backupState.selectedAlbumsBackupAssetsIds.length}",
|
||||
),
|
||||
BackupInfoCard(
|
||||
title: "backup_controller_page_remainder".tr(),
|
||||
subtitle: "backup_controller_page_remainder_sub".tr(),
|
||||
title: "remainder".tr(),
|
||||
subtitle: "remainder_sub".tr(),
|
||||
info: ref.watch(backupProvider).availableAlbums.isEmpty
|
||||
? "..."
|
||||
: "${max(0, backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length)}",
|
||||
|
||||
@@ -309,7 +309,7 @@ class SearchPage extends HookConsumerWidget {
|
||||
),
|
||||
helpText: 'search_filter_date_title'.tr(),
|
||||
cancelText: 'action_common_cancel'.tr(),
|
||||
confirmText: 'action_common_select'.tr(),
|
||||
confirmText: "select".tr(),
|
||||
saveText: 'action_common_save'.tr(),
|
||||
errorFormatText: 'invalid_date_format'.tr(),
|
||||
errorInvalidText: 'invalid_date'.tr(),
|
||||
@@ -804,7 +804,7 @@ class SearchEmptyContent extends StatelessWidget {
|
||||
const SizedBox(height: 16),
|
||||
Center(
|
||||
child: Text(
|
||||
'search_page_search_photos_videos'.tr(),
|
||||
"search_photos_videos".tr(),
|
||||
style: context.textTheme.labelLarge,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -63,7 +63,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
if (!success) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "album_viewer_appbar_share_err_delete".tr(),
|
||||
msg: "appbar_share_err_delete".tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
@@ -118,7 +118,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
context.pop();
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "album_viewer_appbar_share_err_leave".tr(),
|
||||
msg: "appbar_share_err_leave".tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
@@ -284,7 +284,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
if (!isSuccess) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "album_viewer_appbar_share_err_title".tr(),
|
||||
msg: "appbar_share_err_title".tr(),
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
toastType: ToastType.error,
|
||||
);
|
||||
|
||||
@@ -1,387 +1,387 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||
import 'package:immich_mobile/widgets/album/add_to_album_sliverlist.dart';
|
||||
import 'package:immich_mobile/models/asset_selection_state.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/delete_dialog.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/upload_dialog.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/drag_sheet.dart';
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/utils/draggable_scroll_controller.dart';
|
||||
|
||||
final controlBottomAppBarNotifier = ControlBottomAppBarNotifier();
|
||||
|
||||
class ControlBottomAppBarNotifier with ChangeNotifier {
|
||||
void minimize() {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
class ControlBottomAppBar extends HookConsumerWidget {
|
||||
final void Function(bool shareLocal) onShare;
|
||||
final void Function()? onFavorite;
|
||||
final void Function()? onArchive;
|
||||
final void Function([bool force])? onDelete;
|
||||
final void Function([bool force])? onDeleteServer;
|
||||
final void Function(bool onlyBackedUp)? onDeleteLocal;
|
||||
final Function(Album album) onAddToAlbum;
|
||||
final void Function() onCreateNewAlbum;
|
||||
final void Function() onUpload;
|
||||
final void Function()? onStack;
|
||||
final void Function()? onEditTime;
|
||||
final void Function()? onEditLocation;
|
||||
final void Function()? onRemoveFromAlbum;
|
||||
|
||||
final bool enabled;
|
||||
final bool unfavorite;
|
||||
final bool unarchive;
|
||||
final AssetSelectionState selectionAssetState;
|
||||
|
||||
const ControlBottomAppBar({
|
||||
super.key,
|
||||
required this.onShare,
|
||||
this.onFavorite,
|
||||
this.onArchive,
|
||||
this.onDelete,
|
||||
this.onDeleteServer,
|
||||
this.onDeleteLocal,
|
||||
required this.onAddToAlbum,
|
||||
required this.onCreateNewAlbum,
|
||||
required this.onUpload,
|
||||
this.onStack,
|
||||
this.onEditTime,
|
||||
this.onEditLocation,
|
||||
this.onRemoveFromAlbum,
|
||||
this.selectionAssetState = const AssetSelectionState(),
|
||||
this.enabled = true,
|
||||
this.unarchive = false,
|
||||
this.unfavorite = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final hasRemote =
|
||||
selectionAssetState.hasRemote || selectionAssetState.hasMerged;
|
||||
final hasLocal =
|
||||
selectionAssetState.hasLocal || selectionAssetState.hasMerged;
|
||||
final trashEnabled =
|
||||
ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash));
|
||||
final albums = ref.watch(albumProvider).where((a) => a.isRemote).toList();
|
||||
final sharedAlbums =
|
||||
ref.watch(albumProvider).where((a) => a.shared).toList();
|
||||
const bottomPadding = 0.20;
|
||||
final scrollController = useDraggableScrollController();
|
||||
|
||||
void minimize() {
|
||||
scrollController.animateTo(
|
||||
bottomPadding,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOut,
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
controlBottomAppBarNotifier.addListener(minimize);
|
||||
return () {
|
||||
controlBottomAppBarNotifier.removeListener(minimize);
|
||||
};
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
void showForceDeleteDialog(
|
||||
Function(bool) deleteCb, {
|
||||
String? alertMsg,
|
||||
}) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return DeleteDialog(
|
||||
alert: alertMsg,
|
||||
onDelete: () => deleteCb(true),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void handleRemoteDelete(
|
||||
bool force,
|
||||
Function(bool) deleteCb, {
|
||||
String? alertMsg,
|
||||
}) {
|
||||
if (!force) {
|
||||
deleteCb(force);
|
||||
return;
|
||||
}
|
||||
return showForceDeleteDialog(deleteCb, alertMsg: alertMsg);
|
||||
}
|
||||
|
||||
List<Widget> renderActionButtons() {
|
||||
return [
|
||||
if (hasRemote)
|
||||
ControlBoxButton(
|
||||
iconData: Platform.isAndroid
|
||||
? Icons.share_rounded
|
||||
: Icons.ios_share_rounded,
|
||||
label: "control_bottom_app_bar_share".tr(),
|
||||
onPressed: enabled ? () => onShare(true) : null,
|
||||
),
|
||||
ControlBoxButton(
|
||||
iconData: Icons.link_rounded,
|
||||
label: "control_bottom_app_bar_share_link".tr(),
|
||||
onPressed: enabled ? () => onShare(false) : null,
|
||||
),
|
||||
if (hasRemote && onArchive != null)
|
||||
ControlBoxButton(
|
||||
iconData:
|
||||
unarchive ? Icons.unarchive_outlined : Icons.archive_outlined,
|
||||
label: (unarchive
|
||||
? "control_bottom_app_bar_unarchive"
|
||||
: "control_bottom_app_bar_archive")
|
||||
.tr(),
|
||||
onPressed: enabled ? onArchive : null,
|
||||
),
|
||||
if (hasRemote && onFavorite != null)
|
||||
ControlBoxButton(
|
||||
iconData: unfavorite
|
||||
? Icons.favorite_border_rounded
|
||||
: Icons.favorite_rounded,
|
||||
label: (unfavorite
|
||||
? "control_bottom_app_bar_unfavorite"
|
||||
: "control_bottom_app_bar_favorite")
|
||||
.tr(),
|
||||
onPressed: enabled ? onFavorite : null,
|
||||
),
|
||||
if (hasLocal && hasRemote && onDelete != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 90),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.delete_sweep_outlined,
|
||||
label: "control_bottom_app_bar_delete".tr(),
|
||||
onPressed: enabled
|
||||
? () => handleRemoteDelete(!trashEnabled, onDelete!)
|
||||
: null,
|
||||
onLongPressed:
|
||||
enabled ? () => showForceDeleteDialog(onDelete!) : null,
|
||||
),
|
||||
),
|
||||
if (hasRemote && onDeleteServer != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 85),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.cloud_off_outlined,
|
||||
label: trashEnabled
|
||||
? "control_bottom_app_bar_trash_from_immich".tr()
|
||||
: "control_bottom_app_bar_delete_from_immich".tr(),
|
||||
onPressed: enabled
|
||||
? () => handleRemoteDelete(
|
||||
!trashEnabled,
|
||||
onDeleteServer!,
|
||||
alertMsg: "delete_dialog_alert_remote",
|
||||
)
|
||||
: null,
|
||||
onLongPressed: enabled
|
||||
? () => showForceDeleteDialog(
|
||||
onDeleteServer!,
|
||||
alertMsg: "delete_dialog_alert_remote",
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
if (hasLocal && onDeleteLocal != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 85),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.no_cell_outlined,
|
||||
label: "control_bottom_app_bar_delete_from_local".tr(),
|
||||
onPressed: enabled
|
||||
? () {
|
||||
if (!selectionAssetState.hasLocal) {
|
||||
return onDeleteLocal?.call(true);
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return DeleteLocalOnlyDialog(
|
||||
onDeleteLocal: onDeleteLocal!,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
: null,
|
||||
),
|
||||
),
|
||||
if (hasRemote && onEditTime != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 95),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.edit_calendar_outlined,
|
||||
label: "control_bottom_app_bar_edit_time".tr(),
|
||||
onPressed: enabled ? onEditTime : null,
|
||||
),
|
||||
),
|
||||
if (hasRemote && onEditLocation != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 90),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.edit_location_alt_outlined,
|
||||
label: "control_bottom_app_bar_edit_location".tr(),
|
||||
onPressed: enabled ? onEditLocation : null,
|
||||
),
|
||||
),
|
||||
if (!selectionAssetState.hasLocal &&
|
||||
selectionAssetState.selectedCount > 1 &&
|
||||
onStack != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 90),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.filter_none_rounded,
|
||||
label: "control_bottom_app_bar_stack".tr(),
|
||||
onPressed: enabled ? onStack : null,
|
||||
),
|
||||
),
|
||||
if (onRemoveFromAlbum != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 90),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.remove_circle_outline,
|
||||
label: 'album_viewer_appbar_share_remove'.tr(),
|
||||
onPressed: enabled ? onRemoveFromAlbum : null,
|
||||
),
|
||||
),
|
||||
if (selectionAssetState.hasLocal)
|
||||
ControlBoxButton(
|
||||
iconData: Icons.backup_outlined,
|
||||
label: "control_bottom_app_bar_upload".tr(),
|
||||
onPressed: enabled
|
||||
? () => showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return UploadDialog(
|
||||
onUpload: onUpload,
|
||||
);
|
||||
},
|
||||
)
|
||||
: null,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return DraggableScrollableSheet(
|
||||
controller: scrollController,
|
||||
initialChildSize: hasRemote ? 0.35 : bottomPadding,
|
||||
minChildSize: bottomPadding,
|
||||
maxChildSize: hasRemote ? 0.65 : bottomPadding,
|
||||
snap: true,
|
||||
builder: (
|
||||
BuildContext context,
|
||||
ScrollController scrollController,
|
||||
) {
|
||||
return Card(
|
||||
color: context.colorScheme.surfaceContainerLow,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
elevation: 18.0,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(12),
|
||||
topRight: Radius.circular(12),
|
||||
),
|
||||
),
|
||||
margin: const EdgeInsets.all(0),
|
||||
child: CustomScrollView(
|
||||
controller: scrollController,
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
const SizedBox(height: 12),
|
||||
const CustomDraggingHandle(),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
height: 100,
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: renderActionButtons(),
|
||||
),
|
||||
),
|
||||
if (hasRemote)
|
||||
const Divider(
|
||||
indent: 16,
|
||||
endIndent: 16,
|
||||
thickness: 1,
|
||||
),
|
||||
if (hasRemote)
|
||||
_AddToAlbumTitleRow(
|
||||
onCreateNewAlbum: enabled ? onCreateNewAlbum : null,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (hasRemote)
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
sliver: AddToAlbumSliverList(
|
||||
albums: albums,
|
||||
sharedAlbums: sharedAlbums,
|
||||
onAddToAlbum: onAddToAlbum,
|
||||
enabled: enabled,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AddToAlbumTitleRow extends StatelessWidget {
|
||||
const _AddToAlbumTitleRow({
|
||||
required this.onCreateNewAlbum,
|
||||
});
|
||||
|
||||
final VoidCallback? onCreateNewAlbum;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
"common_add_to_album",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
TextButton.icon(
|
||||
onPressed: onCreateNewAlbum,
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
color: context.primaryColor,
|
||||
),
|
||||
label: Text(
|
||||
"common_create_new_album",
|
||||
style: TextStyle(
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||
import 'package:immich_mobile/widgets/album/add_to_album_sliverlist.dart';
|
||||
import 'package:immich_mobile/models/asset_selection_state.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/delete_dialog.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/upload_dialog.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/drag_sheet.dart';
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/utils/draggable_scroll_controller.dart';
|
||||
|
||||
final controlBottomAppBarNotifier = ControlBottomAppBarNotifier();
|
||||
|
||||
class ControlBottomAppBarNotifier with ChangeNotifier {
|
||||
void minimize() {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
class ControlBottomAppBar extends HookConsumerWidget {
|
||||
final void Function(bool shareLocal) onShare;
|
||||
final void Function()? onFavorite;
|
||||
final void Function()? onArchive;
|
||||
final void Function([bool force])? onDelete;
|
||||
final void Function([bool force])? onDeleteServer;
|
||||
final void Function(bool onlyBackedUp)? onDeleteLocal;
|
||||
final Function(Album album) onAddToAlbum;
|
||||
final void Function() onCreateNewAlbum;
|
||||
final void Function() onUpload;
|
||||
final void Function()? onStack;
|
||||
final void Function()? onEditTime;
|
||||
final void Function()? onEditLocation;
|
||||
final void Function()? onRemoveFromAlbum;
|
||||
|
||||
final bool enabled;
|
||||
final bool unfavorite;
|
||||
final bool unarchive;
|
||||
final AssetSelectionState selectionAssetState;
|
||||
|
||||
const ControlBottomAppBar({
|
||||
super.key,
|
||||
required this.onShare,
|
||||
this.onFavorite,
|
||||
this.onArchive,
|
||||
this.onDelete,
|
||||
this.onDeleteServer,
|
||||
this.onDeleteLocal,
|
||||
required this.onAddToAlbum,
|
||||
required this.onCreateNewAlbum,
|
||||
required this.onUpload,
|
||||
this.onStack,
|
||||
this.onEditTime,
|
||||
this.onEditLocation,
|
||||
this.onRemoveFromAlbum,
|
||||
this.selectionAssetState = const AssetSelectionState(),
|
||||
this.enabled = true,
|
||||
this.unarchive = false,
|
||||
this.unfavorite = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final hasRemote =
|
||||
selectionAssetState.hasRemote || selectionAssetState.hasMerged;
|
||||
final hasLocal =
|
||||
selectionAssetState.hasLocal || selectionAssetState.hasMerged;
|
||||
final trashEnabled =
|
||||
ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash));
|
||||
final albums = ref.watch(albumProvider).where((a) => a.isRemote).toList();
|
||||
final sharedAlbums =
|
||||
ref.watch(albumProvider).where((a) => a.shared).toList();
|
||||
const bottomPadding = 0.20;
|
||||
final scrollController = useDraggableScrollController();
|
||||
|
||||
void minimize() {
|
||||
scrollController.animateTo(
|
||||
bottomPadding,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOut,
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
controlBottomAppBarNotifier.addListener(minimize);
|
||||
return () {
|
||||
controlBottomAppBarNotifier.removeListener(minimize);
|
||||
};
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
void showForceDeleteDialog(
|
||||
Function(bool) deleteCb, {
|
||||
String? alertMsg,
|
||||
}) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return DeleteDialog(
|
||||
alert: alertMsg,
|
||||
onDelete: () => deleteCb(true),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void handleRemoteDelete(
|
||||
bool force,
|
||||
Function(bool) deleteCb, {
|
||||
String? alertMsg,
|
||||
}) {
|
||||
if (!force) {
|
||||
deleteCb(force);
|
||||
return;
|
||||
}
|
||||
return showForceDeleteDialog(deleteCb, alertMsg: alertMsg);
|
||||
}
|
||||
|
||||
List<Widget> renderActionButtons() {
|
||||
return [
|
||||
if (hasRemote)
|
||||
ControlBoxButton(
|
||||
iconData: Platform.isAndroid
|
||||
? Icons.share_rounded
|
||||
: Icons.ios_share_rounded,
|
||||
label: "control_bottom_app_bar_share".tr(),
|
||||
onPressed: enabled ? () => onShare(true) : null,
|
||||
),
|
||||
ControlBoxButton(
|
||||
iconData: Icons.link_rounded,
|
||||
label: "share_link".tr(),
|
||||
onPressed: enabled ? () => onShare(false) : null,
|
||||
),
|
||||
if (hasRemote && onArchive != null)
|
||||
ControlBoxButton(
|
||||
iconData:
|
||||
unarchive ? Icons.unarchive_outlined : Icons.archive_outlined,
|
||||
label: (unarchive
|
||||
? "control_bottom_app_bar_unarchive"
|
||||
: "control_bottom_app_bar_archive")
|
||||
.tr(),
|
||||
onPressed: enabled ? onArchive : null,
|
||||
),
|
||||
if (hasRemote && onFavorite != null)
|
||||
ControlBoxButton(
|
||||
iconData: unfavorite
|
||||
? Icons.favorite_border_rounded
|
||||
: Icons.favorite_rounded,
|
||||
label: (unfavorite
|
||||
? "control_bottom_app_bar_unfavorite"
|
||||
: "control_bottom_app_bar_favorite")
|
||||
.tr(),
|
||||
onPressed: enabled ? onFavorite : null,
|
||||
),
|
||||
if (hasLocal && hasRemote && onDelete != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 90),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.delete_sweep_outlined,
|
||||
label: "control_bottom_app_bar_delete".tr(),
|
||||
onPressed: enabled
|
||||
? () => handleRemoteDelete(!trashEnabled, onDelete!)
|
||||
: null,
|
||||
onLongPressed:
|
||||
enabled ? () => showForceDeleteDialog(onDelete!) : null,
|
||||
),
|
||||
),
|
||||
if (hasRemote && onDeleteServer != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 85),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.cloud_off_outlined,
|
||||
label: trashEnabled
|
||||
? "trash_from_immich".tr()
|
||||
: "delete_from_immich".tr(),
|
||||
onPressed: enabled
|
||||
? () => handleRemoteDelete(
|
||||
!trashEnabled,
|
||||
onDeleteServer!,
|
||||
alertMsg: "delete_dialog_alert_remote",
|
||||
)
|
||||
: null,
|
||||
onLongPressed: enabled
|
||||
? () => showForceDeleteDialog(
|
||||
onDeleteServer!,
|
||||
alertMsg: "delete_dialog_alert_remote",
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
if (hasLocal && onDeleteLocal != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 85),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.no_cell_outlined,
|
||||
label: "delete_from_local".tr(),
|
||||
onPressed: enabled
|
||||
? () {
|
||||
if (!selectionAssetState.hasLocal) {
|
||||
return onDeleteLocal?.call(true);
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return DeleteLocalOnlyDialog(
|
||||
onDeleteLocal: onDeleteLocal!,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
: null,
|
||||
),
|
||||
),
|
||||
if (hasRemote && onEditTime != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 95),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.edit_calendar_outlined,
|
||||
label: "edit_time".tr(),
|
||||
onPressed: enabled ? onEditTime : null,
|
||||
),
|
||||
),
|
||||
if (hasRemote && onEditLocation != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 90),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.edit_location_alt_outlined,
|
||||
label: "control_bottom_app_bar_edit_location".tr(),
|
||||
onPressed: enabled ? onEditLocation : null,
|
||||
),
|
||||
),
|
||||
if (!selectionAssetState.hasLocal &&
|
||||
selectionAssetState.selectedCount > 1 &&
|
||||
onStack != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 90),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.filter_none_rounded,
|
||||
label: "control_bottom_app_bar_stack".tr(),
|
||||
onPressed: enabled ? onStack : null,
|
||||
),
|
||||
),
|
||||
if (onRemoveFromAlbum != null)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 90),
|
||||
child: ControlBoxButton(
|
||||
iconData: Icons.remove_circle_outline,
|
||||
label: "appbar_share_remove".tr(),
|
||||
onPressed: enabled ? onRemoveFromAlbum : null,
|
||||
),
|
||||
),
|
||||
if (selectionAssetState.hasLocal)
|
||||
ControlBoxButton(
|
||||
iconData: Icons.backup_outlined,
|
||||
label: "control_bottom_app_bar_upload".tr(),
|
||||
onPressed: enabled
|
||||
? () => showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return UploadDialog(
|
||||
onUpload: onUpload,
|
||||
);
|
||||
},
|
||||
)
|
||||
: null,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return DraggableScrollableSheet(
|
||||
controller: scrollController,
|
||||
initialChildSize: hasRemote ? 0.35 : bottomPadding,
|
||||
minChildSize: bottomPadding,
|
||||
maxChildSize: hasRemote ? 0.65 : bottomPadding,
|
||||
snap: true,
|
||||
builder: (
|
||||
BuildContext context,
|
||||
ScrollController scrollController,
|
||||
) {
|
||||
return Card(
|
||||
color: context.colorScheme.surfaceContainerLow,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
elevation: 18.0,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(12),
|
||||
topRight: Radius.circular(12),
|
||||
),
|
||||
),
|
||||
margin: const EdgeInsets.all(0),
|
||||
child: CustomScrollView(
|
||||
controller: scrollController,
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
const SizedBox(height: 12),
|
||||
const CustomDraggingHandle(),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
height: 100,
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: renderActionButtons(),
|
||||
),
|
||||
),
|
||||
if (hasRemote)
|
||||
const Divider(
|
||||
indent: 16,
|
||||
endIndent: 16,
|
||||
thickness: 1,
|
||||
),
|
||||
if (hasRemote)
|
||||
_AddToAlbumTitleRow(
|
||||
onCreateNewAlbum: enabled ? onCreateNewAlbum : null,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (hasRemote)
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
sliver: AddToAlbumSliverList(
|
||||
albums: albums,
|
||||
sharedAlbums: sharedAlbums,
|
||||
onAddToAlbum: onAddToAlbum,
|
||||
enabled: enabled,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AddToAlbumTitleRow extends StatelessWidget {
|
||||
const _AddToAlbumTitleRow({
|
||||
required this.onCreateNewAlbum,
|
||||
});
|
||||
|
||||
final VoidCallback? onCreateNewAlbum;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
"common_add_to_album",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
TextButton.icon(
|
||||
onPressed: onCreateNewAlbum,
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
color: context.primaryColor,
|
||||
),
|
||||
label: Text(
|
||||
"common_create_new_album",
|
||||
style: TextStyle(
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ class BottomGalleryBar extends ConsumerWidget {
|
||||
} else {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "album_viewer_appbar_share_err_remove".tr(),
|
||||
msg: "appbar_share_err_remove".tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
@@ -327,8 +327,8 @@ class BottomGalleryBar extends ConsumerWidget {
|
||||
{
|
||||
BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.remove_circle_outline),
|
||||
label: 'album_viewer_appbar_share_remove'.tr(),
|
||||
tooltip: 'album_viewer_appbar_share_remove'.tr(),
|
||||
label: "appbar_share_remove".tr(),
|
||||
tooltip: "appbar_share_remove".tr(),
|
||||
): (_) => handleRemoveFromAlbum(),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -82,7 +82,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||
strokeWidth: 2,
|
||||
strokeCap: StrokeCap.round,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(iconColor),
|
||||
semanticsLabel: 'backup_controller_page_backup'.tr(),
|
||||
semanticsLabel: "backup".tr(),
|
||||
),
|
||||
);
|
||||
} else if (backupState.backupProgress !=
|
||||
@@ -92,7 +92,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||
Icons.check_outlined,
|
||||
size: 9,
|
||||
color: iconColor,
|
||||
semanticLabel: 'backup_controller_page_backup'.tr(),
|
||||
semanticLabel: "backup".tr(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||
Icons.cloud_off_rounded,
|
||||
size: 9,
|
||||
color: iconColor,
|
||||
semanticLabel: 'backup_controller_page_backup'.tr(),
|
||||
semanticLabel: "backup".tr(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class PersonNameEditForm extends HookConsumerWidget {
|
||||
controller: controller,
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'search_page_person_add_name_dialog_hint'.tr(),
|
||||
hintText: "person_add_name_dialog_hint".tr(),
|
||||
border: const OutlineInputBorder(),
|
||||
errorText: isError.value ? 'Error occured' : null,
|
||||
),
|
||||
|
||||
@@ -18,7 +18,7 @@ class SearchMapThumbnail extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ThumbnailWithInfoContainer(
|
||||
label: 'search_page_your_map'.tr(),
|
||||
label: "your_map".tr(),
|
||||
onTap: () {
|
||||
context.pushRoute(const MapRoute());
|
||||
},
|
||||
|
||||
@@ -32,19 +32,19 @@ class GroupSettings extends HookConsumerWidget {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SettingsSubTitle(title: "asset_list_group_by_sub_title".tr()),
|
||||
SettingsSubTitle(title: "group_by_sub_title".tr()),
|
||||
SettingsRadioListTile(
|
||||
groups: [
|
||||
SettingsRadioGroup(
|
||||
title: 'asset_list_layout_settings_group_by_month_day'.tr(),
|
||||
title: "layout_settings_group_by_month_day".tr(),
|
||||
value: GroupAssetsBy.day,
|
||||
),
|
||||
SettingsRadioGroup(
|
||||
title: 'asset_list_layout_settings_group_by_month'.tr(),
|
||||
title: "layout_settings_group_by_month".tr(),
|
||||
value: GroupAssetsBy.month,
|
||||
),
|
||||
SettingsRadioGroup(
|
||||
title: 'asset_list_layout_settings_group_automatically'.tr(),
|
||||
title: "layout_settings_group_automatically".tr(),
|
||||
value: GroupAssetsBy.auto,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -21,10 +21,10 @@ class LayoutSettings extends HookConsumerWidget {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SettingsSubTitle(title: "asset_list_layout_sub_title".tr()),
|
||||
SettingsSubTitle(title: "layout_sub_title".tr()),
|
||||
SettingsSwitchListTile(
|
||||
valueNotifier: useDynamicLayout,
|
||||
title: "asset_list_layout_settings_dynamic_layout_title".tr(),
|
||||
title: "layout_settings_dynamic_layout_title".tr(),
|
||||
onChanged: (_) => ref.invalidate(appSettingsServiceProvider),
|
||||
),
|
||||
SettingsSliderListTile(
|
||||
|
||||
@@ -22,7 +22,7 @@ class AssetListSettings extends HookConsumerWidget {
|
||||
final assetListSetting = [
|
||||
SettingsSwitchListTile(
|
||||
valueNotifier: showStorageIndicator,
|
||||
title: 'theme_setting_asset_list_storage_indicator_title'.tr(),
|
||||
title: "asset_list_storage_indicator_title".tr(),
|
||||
onChanged: (_) => ref.invalidate(appSettingsServiceProvider),
|
||||
),
|
||||
const LayoutSettings(),
|
||||
|
||||
@@ -77,9 +77,9 @@ class BackgroundBackupSettings extends ConsumerWidget {
|
||||
if (!isBackgroundEnabled) {
|
||||
return SettingsButtonListTile(
|
||||
icon: Icons.cloud_sync_outlined,
|
||||
title: 'backup_controller_page_background_is_off'.tr(),
|
||||
subtileText: 'backup_controller_page_background_description'.tr(),
|
||||
buttonText: 'backup_controller_page_background_turn_on'.tr(),
|
||||
title: "background_is_off".tr(),
|
||||
subtileText: "background_description".tr(),
|
||||
buttonText: "background_turn_on".tr(),
|
||||
onButtonTap: () =>
|
||||
ref.read(backupProvider.notifier).configureBackgroundBackup(
|
||||
enabled: true,
|
||||
@@ -111,9 +111,9 @@ class _IOSBackgroundRefreshDisabled extends StatelessWidget {
|
||||
return SettingsButtonListTile(
|
||||
icon: Icons.task_outlined,
|
||||
title:
|
||||
'backup_controller_page_background_app_refresh_disabled_title'.tr(),
|
||||
"background_app_refresh_disabled_title".tr(),
|
||||
subtileText:
|
||||
'backup_controller_page_background_app_refresh_disabled_content'.tr(),
|
||||
"background_app_refresh_disabled_content".tr(),
|
||||
buttonText:
|
||||
'backup_controller_page_background_app_refresh_enable_button_text'
|
||||
.tr(),
|
||||
@@ -185,8 +185,8 @@ class _BackgroundSettingsEnabled extends HookConsumerWidget {
|
||||
return SettingsButtonListTile(
|
||||
icon: Icons.cloud_sync_rounded,
|
||||
iconColor: context.primaryColor,
|
||||
title: 'backup_controller_page_background_is_on'.tr(),
|
||||
buttonText: 'backup_controller_page_background_turn_off'.tr(),
|
||||
title: "background_is_on".tr(),
|
||||
buttonText: "background_turn_off".tr(),
|
||||
onButtonTap: () =>
|
||||
ref.read(backupProvider.notifier).configureBackgroundBackup(
|
||||
enabled: false,
|
||||
@@ -197,7 +197,7 @@ class _BackgroundSettingsEnabled extends HookConsumerWidget {
|
||||
children: [
|
||||
SettingsSwitchListTile(
|
||||
valueNotifier: isWifiRequiredNotifier,
|
||||
title: 'backup_controller_page_background_wifi'.tr(),
|
||||
title: "background_wifi".tr(),
|
||||
icon: Icons.wifi,
|
||||
onChanged: (enabled) =>
|
||||
ref.read(backupProvider.notifier).configureBackgroundBackup(
|
||||
@@ -208,7 +208,7 @@ class _BackgroundSettingsEnabled extends HookConsumerWidget {
|
||||
),
|
||||
SettingsSwitchListTile(
|
||||
valueNotifier: isChargingRequiredNotifier,
|
||||
title: 'backup_controller_page_background_charging'.tr(),
|
||||
title: "background_charging".tr(),
|
||||
icon: Icons.charging_station,
|
||||
onChanged: (enabled) =>
|
||||
ref.read(backupProvider.notifier).configureBackgroundBackup(
|
||||
|
||||
@@ -19,17 +19,17 @@ class ForegroundBackupSettings extends ConsumerWidget {
|
||||
return SettingsButtonListTile(
|
||||
icon: Icons.cloud_done_rounded,
|
||||
iconColor: context.primaryColor,
|
||||
title: 'backup_controller_page_status_on'.tr(),
|
||||
buttonText: 'backup_controller_page_turn_off'.tr(),
|
||||
title: "status_on".tr(),
|
||||
buttonText: "turn_off".tr(),
|
||||
onButtonTap: onButtonTap,
|
||||
);
|
||||
}
|
||||
|
||||
return SettingsButtonListTile(
|
||||
icon: Icons.cloud_off_rounded,
|
||||
title: 'backup_controller_page_status_off'.tr(),
|
||||
subtileText: 'backup_controller_page_desc_backup'.tr(),
|
||||
buttonText: 'backup_controller_page_turn_on'.tr(),
|
||||
title: "status_off".tr(),
|
||||
subtileText: "desc_backup".tr(),
|
||||
buttonText: "turn_on".tr(),
|
||||
onButtonTap: onButtonTap,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ class PrimaryColorSetting extends HookConsumerWidget {
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
"theme_setting_primary_color_title".tr(),
|
||||
"primary_color_title".tr(),
|
||||
style: context.textTheme.titleLarge,
|
||||
),
|
||||
),
|
||||
@@ -140,7 +140,7 @@ class PrimaryColorSetting extends HookConsumerWidget {
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
title: Text(
|
||||
'theme_setting_system_primary_color_title'.tr(),
|
||||
"system_primary_color_title".tr(),
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1.5,
|
||||
@@ -194,13 +194,13 @@ class PrimaryColorSetting extends HookConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"theme_setting_primary_color_title".tr(),
|
||||
"primary_color_title".tr(),
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"theme_setting_primary_color_subtitle".tr(),
|
||||
"primary_color_subtitle".tr(),
|
||||
style: context.textTheme.bodyMedium
|
||||
?.copyWith(color: context.colorScheme.onSurfaceSecondary),
|
||||
),
|
||||
|
||||
@@ -81,23 +81,23 @@ class ThemeSetting extends HookConsumerWidget {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SettingsSubTitle(title: "theme_setting_theme_title".tr()),
|
||||
SettingsSubTitle(title: "theme_title".tr()),
|
||||
SettingsSwitchListTile(
|
||||
valueNotifier: isSystemTheme,
|
||||
title: 'theme_setting_system_theme_switch'.tr(),
|
||||
title: "system_theme_switch".tr(),
|
||||
onChanged: onSystemThemeChange,
|
||||
),
|
||||
if (currentTheme.value != ThemeMode.system)
|
||||
SettingsSwitchListTile(
|
||||
valueNotifier: isDarkTheme,
|
||||
title: 'theme_setting_dark_mode_switch'.tr(),
|
||||
title: "dark_mode_switch".tr(),
|
||||
onChanged: onThemeChange,
|
||||
),
|
||||
const PrimaryColorSetting(),
|
||||
SettingsSwitchListTile(
|
||||
valueNotifier: applyThemeToBackgroundProvider,
|
||||
title: "theme_setting_colorful_interface_title".tr(),
|
||||
subtitle: 'theme_setting_colorful_interface_subtitle'.tr(),
|
||||
title: "colorful_interface_title".tr(),
|
||||
subtitle: "colorful_interface_subtitle".tr(),
|
||||
onChanged: onSurfaceColorSettingChange,
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user