chore: migrate mobile translations accessor (4) (#30671)

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong 2026-08-11 14:41:13 +05:30 committed by GitHub
parent d799698c51
commit a8b3b30aba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 305 additions and 344 deletions

View file

@ -2,7 +2,6 @@ import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
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';
@ -10,6 +9,7 @@ import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/domain/services/timeline.service.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/models/folder/recursive_folder.model.dart'; import 'package:immich_mobile/models/folder/recursive_folder.model.dart';
import 'package:immich_mobile/models/folder/root_folder.model.dart'; import 'package:immich_mobile/models/folder/root_folder.model.dart';
import 'package:immich_mobile/pages/common/large_leading_tile.dart'; import 'package:immich_mobile/pages/common/large_leading_tile.dart';
@ -20,6 +20,7 @@ import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:immich_mobile/utils/bytes_units.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:intl/intl.dart';
RecursiveFolder? _findFolderInStructure(RootFolder rootFolder, RecursiveFolder targetFolder) { RecursiveFolder? _findFolderInStructure(RootFolder rootFolder, RecursiveFolder targetFolder) {
for (final folder in rootFolder.subfolders) { for (final folder in rootFolder.subfolders) {
@ -81,7 +82,7 @@ class FolderPage extends HookConsumerWidget {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(currentFolder.value?.name ?? tr("folders")), title: Text(currentFolder.value?.name ?? context.t.folders),
elevation: 0, elevation: 0,
centerTitle: false, centerTitle: false,
actions: [IconButton(icon: const Icon(Icons.swap_vert), onPressed: onToggleSortOrder)], actions: [IconButton(icon: const Icon(Icons.swap_vert), onPressed: onToggleSortOrder)],
@ -96,8 +97,8 @@ class FolderPage extends HookConsumerWidget {
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) { error: (error, stack) {
ImmichToast.show(context: context, msg: "failed_to_load_folder".tr(), toastType: ToastType.error); ImmichToast.show(context: context, msg: context.t.failed_to_load_folder, toastType: ToastType.error);
return Center(child: const Text("failed_to_load_folder").tr()); return Center(child: Text(context.t.failed_to_load_folder));
}, },
), ),
); );
@ -125,16 +126,16 @@ class FolderContent extends HookConsumerWidget {
}, [folder]); }, [folder]);
if (folder == null) { if (folder == null) {
return Center(child: const Text("folder_not_found").tr()); return Center(child: Text(context.t.folder_not_found));
} }
String getSubtitle(int subFolderCount) { String getSubtitle(int subFolderCount) {
if (subFolderCount > 0) { if (subFolderCount > 0) {
return "$subFolderCount ${tr("folders")}".toLowerCase(); return "$subFolderCount ${context.t.folders}".toLowerCase();
} }
if (subFolderCount == 1) { if (subFolderCount == 1) {
return "1 ${tr("folder")}".toLowerCase(); return "1 ${context.t.folder}".toLowerCase();
} }
return ""; return "";
@ -147,7 +148,7 @@ class FolderContent extends HookConsumerWidget {
child: folderRenderlist.when( child: folderRenderlist.when(
data: (folderAssets) { data: (folderAssets) {
if (folder!.subfolders.isEmpty && folderAssets.isEmpty) { if (folder!.subfolders.isEmpty && folderAssets.isEmpty) {
return Center(child: const Text("empty_folder").tr()); return Center(child: Text(context.t.empty_folder));
} }
return ListView( return ListView(
@ -211,8 +212,8 @@ class FolderContent extends HookConsumerWidget {
}, },
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) { error: (error, stack) {
ImmichToast.show(context: context, msg: "failed_to_load_assets".tr(), toastType: ToastType.error); ImmichToast.show(context: context, msg: context.t.failed_to_load_assets, toastType: ToastType.error);
return Center(child: const Text("failed_to_load_assets").tr()); return Center(child: Text(context.t.failed_to_load_assets));
}, },
), ),
), ),

View file

@ -1,11 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' show useState; import 'package:flutter_hooks/flutter_hooks.dart' show useState;
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/providers/local_auth.provider.dart'; import 'package:immich_mobile/providers/local_auth.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/widgets/forms/pin_registration_form.dart'; import 'package:immich_mobile/widgets/forms/pin_registration_form.dart';
@ -31,7 +31,7 @@ class PinAuthPage extends HookConsumerWidget {
context.showSnackBar( context.showSnackBar(
SnackBar( SnackBar(
content: Text('biometric_auth_enabled'.tr(), style: context.textTheme.labelLarge), content: Text(context.t.biometric_auth_enabled, style: context.textTheme.labelLarge),
duration: const Duration(seconds: 3), duration: const Duration(seconds: 3),
backgroundColor: context.colorScheme.primaryContainer, backgroundColor: context.colorScheme.primaryContainer,
), ),
@ -52,7 +52,7 @@ class PinAuthPage extends HookConsumerWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
PinVerificationForm( PinVerificationForm(
description: 'enable_biometric_auth_description'.tr(), description: context.t.enable_biometric_auth_description,
onSuccess: (pinCode) { onSuccess: (pinCode) {
Navigator.pop(buildContext); Navigator.pop(buildContext);
unawaited(registerBiometric(pinCode)); unawaited(registerBiometric(pinCode));
@ -71,7 +71,7 @@ class PinAuthPage extends HookConsumerWidget {
} }
return Scaffold( return Scaffold(
appBar: AppBar(title: Text('locked_folder'.tr())), appBar: AppBar(title: Text(context.t.locked_folder)),
body: ListView( body: ListView(
shrinkWrap: true, shrinkWrap: true,
children: [ children: [
@ -97,7 +97,7 @@ class PinAuthPage extends HookConsumerWidget {
icon: const Icon(Icons.fingerprint, size: 28), icon: const Icon(Icons.fingerprint, size: 28),
onPressed: () => unawaited(enableBiometricAuth()), onPressed: () => unawaited(enableBiometricAuth()),
label: Text( label: Text(
'use_biometric'.tr(), context.t.use_biometric,
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor, fontSize: 18), style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor, fontSize: 18),
), ),
), ),

View file

@ -1,11 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
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/asyncvalue_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/models/shared_link/shared_link.model.dart'; import 'package:immich_mobile/models/shared_link/shared_link.model.dart';
import 'package:immich_mobile/providers/shared_link.provider.dart'; import 'package:immich_mobile/providers/shared_link.provider.dart';
import 'package:immich_mobile/widgets/shared_link/shared_link_item.dart'; import 'package:immich_mobile/widgets/shared_link/shared_link_item.dart';
@ -36,7 +36,7 @@ class SharedLinkPage extends HookConsumerWidget {
children: [ children: [
Icon(Icons.link_off, size: 100, color: Theme.of(context).colorScheme.onSurface.withAlpha(128)), Icon(Icons.link_off, size: 100, color: Theme.of(context).colorScheme.onSurface.withAlpha(128)),
const SizedBox(height: 20), const SizedBox(height: 20),
const Text("you_dont_have_any_shared_links", style: TextStyle(fontSize: 14)).tr(), Text(context.t.you_dont_have_any_shared_links, style: const TextStyle(fontSize: 14)),
], ],
), ),
); );
@ -68,7 +68,7 @@ class SharedLinkPage extends HookConsumerWidget {
} }
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text("shared_link_app_bar_title").tr(), elevation: 0, centerTitle: false), appBar: AppBar(title: Text(context.t.shared_link_app_bar_title), elevation: 0, centerTitle: false),
body: SafeArea( body: SafeArea(
child: sharedLinks.widgetWhen( child: sharedLinks.widgetWhen(
onError: (error, stackTrace) => buildNoShares(), onError: (error, stackTrace) => buildNoShares(),

View file

@ -10,7 +10,7 @@ import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/pages/drift_user_selection.page.dart'; import 'package:immich_mobile/presentation/pages/drift_user_selection.page.dart';
import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/auth.provider.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
@ -37,7 +37,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
ContextHelper(context).pop(); ContextHelper(context).pop();
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: "shared_album_section_people_action_error".t(context: context), msg: context.t.shared_album_section_people_action_error,
toastType: ToastType.error, toastType: ToastType.error,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
@ -87,7 +87,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: "users_added_to_album_count".t(context: context, args: {'count': newUsers.length}), msg: context.t.users_added_to_album_count(count: newUsers.length),
toastType: ToastType.success, toastType: ToastType.success,
); );
} catch (e) { } catch (e) {
@ -106,7 +106,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
actions = [ actions = [
ListTile( ListTile(
leading: const Icon(Icons.exit_to_app_rounded), leading: const Icon(Icons.exit_to_app_rounded),
title: const Text("leave_album").t(context: context), title: Text(context.t.leave_album),
onTap: leaveAlbum, onTap: leaveAlbum,
), ),
]; ];
@ -116,7 +116,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
actions = [ actions = [
ListTile( ListTile(
leading: const Icon(Icons.person_remove_rounded), leading: const Icon(Icons.person_remove_rounded),
title: const Text("remove_user").t(context: context), title: Text(context.t.remove_user),
onTap: () => removeUserFromAlbum(user), onTap: () => removeUserFromAlbum(user),
), ),
]; ];
@ -146,7 +146,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
leading: owner != null ? UserCircleAvatar(user: owner) : const SizedBox(), leading: owner != null ? UserCircleAvatar(user: owner) : const SizedBox(),
title: Text(album.ownerName, style: const TextStyle(fontWeight: FontWeight.w500)), title: Text(album.ownerName, style: const TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text(owner?.email ?? "", style: TextStyle(color: context.colorScheme.onSurfaceSecondary)), subtitle: Text(owner?.email ?? "", style: TextStyle(color: context.colorScheme.onSurfaceSecondary)),
trailing: Text("owner", style: context.textTheme.labelLarge).t(context: context), trailing: Text(context.t.owner, style: context.textTheme.labelLarge),
); );
} else { } else {
final usersProvider = ref.read(driftUsersProvider); final usersProvider = ref.read(driftUsersProvider);
@ -162,7 +162,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
leading: UserCircleAvatar(user: user), leading: UserCircleAvatar(user: user),
title: Text(user.name, style: const TextStyle(fontWeight: FontWeight.w500)), title: Text(user.name, style: const TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text(user.email, style: TextStyle(color: context.colorScheme.onSurfaceSecondary)), subtitle: Text(user.email, style: TextStyle(color: context.colorScheme.onSurfaceSecondary)),
trailing: Text("owner", style: context.textTheme.labelLarge).t(context: context), trailing: Text(context.t.owner, style: context.textTheme.labelLarge),
); );
}, },
orElse: () => const SizedBox(), orElse: () => const SizedBox(),
@ -207,7 +207,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
onPressed: () => context.maybePop(null), onPressed: () => context.maybePop(null),
), ),
centerTitle: true, centerTitle: true,
title: Text("options".t(context: context)), title: Text(context.t.options),
), ),
body: ListView( body: ListView(
children: [ children: [
@ -222,19 +222,19 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
activeThumbColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor, activeThumbColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor,
dense: true, dense: true,
title: Text( title: Text(
"comments_and_likes", context.t.comments_and_likes,
style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w500), style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w500),
).t(context: context), ),
subtitle: Text( subtitle: Text(
"let_others_respond", context.t.let_others_respond,
style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary),
).t(context: context), ),
), ),
buildSectionTitle("shared_album_section_people_title".t(context: context)), buildSectionTitle(context.t.shared_album_section_people_title),
if (isOwner) ...[ if (isOwner) ...[
ListTile( ListTile(
leading: const Icon(Icons.person_add_rounded), leading: const Icon(Icons.person_add_rounded),
title: Text("invite_people".t(context: context)), title: Text(context.t.invite_people),
onTap: () async => addUsers(), onTap: () async => addUsers(),
), ),
const Divider(indent: 16), const Divider(indent: 16),

View file

@ -1,7 +1,7 @@
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.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/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart'; import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
@ -28,10 +28,7 @@ class DriftArchivePage extends StatelessWidget {
}), }),
], ],
child: Timeline( child: Timeline(
appBar: MesmerizingSliverAppBar( appBar: MesmerizingSliverAppBar(title: context.t.archive, icon: Icons.archive_outlined),
title: 'archive'.t(context: context),
icon: Icons.archive_outlined,
),
bottomSheet: const ArchiveBottomSheet(), bottomSheet: const ArchiveBottomSheet(),
), ),
); );

View file

@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
@ -52,9 +52,7 @@ class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
bool get _canCreateAlbum => albumTitleController.text.trim().isNotEmpty && !isCreatingAlbum; bool get _canCreateAlbum => albumTitleController.text.trim().isNotEmpty && !isCreatingAlbum;
String _getEffectiveTitle() { String _getEffectiveTitle() {
return albumTitleController.text.isNotEmpty return albumTitleController.text.isNotEmpty ? albumTitleController.text : context.t.create_album_page_untitled;
? albumTitleController.text
: 'create_album_page_untitled'.t(context: context);
} }
Widget _buildSliverAppBar() { Widget _buildSliverAppBar() {
@ -93,7 +91,7 @@ class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
Widget _buildEmptyState() { Widget _buildEmptyState() {
return Padding( return Padding(
padding: const EdgeInsets.only(top: 0, left: 18), padding: const EdgeInsets.only(top: 0, left: 18),
child: Text('create_shared_album_page_share_add_assets', style: context.textTheme.labelLarge).t(), child: Text(context.t.create_shared_album_page_share_add_assets, style: context.textTheme.labelLarge),
); );
} }
@ -112,9 +110,9 @@ class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
label: Padding( label: Padding(
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: Text( child: Text(
'create_shared_album_page_share_select_photos', context.t.create_shared_album_page_share_select_photos,
style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor), style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor),
).t(), ),
), ),
), ),
); );
@ -148,7 +146,7 @@ class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
}); });
if (albumTitleController.text.isEmpty) { if (albumTitleController.text.isEmpty) {
final untitledText = 'create_album_page_untitled'.t(); final untitledText = context.t.create_album_page_untitled;
albumTitleController.text = untitledText; albumTitleController.text = untitledText;
} }
} }
@ -196,7 +194,7 @@ class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
return; return;
} }
ImmichToast.show(context: context, toastType: ToastType.error, msg: 'errors.failed_to_create_album'.t()); ImmichToast.show(context: context, toastType: ToastType.error, msg: context.t.errors.failed_to_create_album);
} finally { } finally {
if (mounted) { if (mounted) {
setState(() => isCreatingAlbum = false); setState(() => isCreatingAlbum = false);
@ -241,7 +239,7 @@ class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
AlbumActionFilledButton( AlbumActionFilledButton(
iconData: Icons.add_photo_alternate_outlined, iconData: Icons.add_photo_alternate_outlined,
onPressed: onSelectPhotos, onPressed: onSelectPhotos,
labelText: "add_photos".t(), labelText: context.t.add_photos,
), ),
], ],
), ),
@ -257,12 +255,12 @@ class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
centerTitle: false, centerTitle: false,
backgroundColor: context.scaffoldBackgroundColor, backgroundColor: context.scaffoldBackgroundColor,
leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.close_rounded)), leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.close_rounded)),
title: const Text('create_album').t(), title: Text(context.t.create_album),
actions: [ actions: [
TextButton( TextButton(
onPressed: _canCreateAlbum ? createAlbum : null, onPressed: _canCreateAlbum ? createAlbum : null,
child: Text( child: Text(
'create'.t(), context.t.create,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: _canCreateAlbum ? context.primaryColor : context.themeData.disabledColor, color: _canCreateAlbum ? context.primaryColor : context.themeData.disabledColor,
@ -320,7 +318,7 @@ class _AlbumTitleTextFieldState extends State<_AlbumTitleTextField> {
style: TextStyle(fontSize: 28.0, color: context.colorScheme.onSurface, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 28.0, color: context.colorScheme.onSurface, fontWeight: FontWeight.bold),
controller: widget.textController, controller: widget.textController,
onTap: () { onTap: () {
if (widget.textController.text == 'create_album_page_untitled'.t(context: context)) { if (widget.textController.text == context.t.create_album_page_untitled) {
widget.textController.clear(); widget.textController.clear();
} }
}, },
@ -343,7 +341,7 @@ class _AlbumTitleTextFieldState extends State<_AlbumTitleTextField> {
borderSide: BorderSide(color: context.primaryColor.withValues(alpha: 0.3)), borderSide: BorderSide(color: context.primaryColor.withValues(alpha: 0.3)),
borderRadius: const BorderRadius.all(Radius.circular(16.0)), borderRadius: const BorderRadius.all(Radius.circular(16.0)),
), ),
hintText: 'add_a_title'.t(), hintText: context.t.add_a_title,
hintStyle: context.themeData.inputDecorationTheme.hintStyle?.copyWith( hintStyle: context.themeData.inputDecorationTheme.hintStyle?.copyWith(
fontSize: 28.0, fontSize: 28.0,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -430,7 +428,7 @@ class _AlbumViewerEditableDescriptionState extends State<_AlbumViewerEditableDes
focusColor: Colors.grey[300], focusColor: Colors.grey[300],
fillColor: context.scaffoldBackgroundColor, fillColor: context.scaffoldBackgroundColor,
filled: widget.focusNode.hasFocus, filled: widget.focusNode.hasFocus,
hintText: 'add_a_description'.t(), hintText: context.t.add_a_description,
), ),
), ),
); );

View file

@ -1,11 +1,10 @@
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.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/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/extensions/asyncvalue_extensions.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/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/images/local_album_thumbnail.widget.dart'; import 'package:immich_mobile/presentation/widgets/images/local_album_thumbnail.widget.dart';
import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart';
import 'package:immich_mobile/presentation/widgets/people/partner_user_avatar.widget.dart'; import 'package:immich_mobile/presentation/widgets/people/partner_user_avatar.widget.dart';
@ -56,13 +55,13 @@ class _ActionButtonGrid extends ConsumerWidget {
_ActionButton( _ActionButton(
icon: Icons.favorite_outline_rounded, icon: Icons.favorite_outline_rounded,
onTap: () => context.pushRoute(const DriftFavoriteRoute()), onTap: () => context.pushRoute(const DriftFavoriteRoute()),
label: 'favorites'.t(context: context), label: context.t.favorites,
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
_ActionButton( _ActionButton(
icon: Icons.archive_outlined, icon: Icons.archive_outlined,
onTap: () => context.pushRoute(const DriftArchiveRoute()), onTap: () => context.pushRoute(const DriftArchiveRoute()),
label: 'archived'.t(context: context), label: context.t.archived,
), ),
], ],
), ),
@ -72,14 +71,14 @@ class _ActionButtonGrid extends ConsumerWidget {
_ActionButton( _ActionButton(
icon: Icons.link_outlined, icon: Icons.link_outlined,
onTap: () => context.pushRoute(const SharedLinkRoute()), onTap: () => context.pushRoute(const SharedLinkRoute()),
label: 'shared_links'.t(context: context), label: context.t.shared_links,
), ),
isTrashEnable ? const SizedBox(width: 8) : const SizedBox.shrink(), isTrashEnable ? const SizedBox(width: 8) : const SizedBox.shrink(),
isTrashEnable isTrashEnable
? _ActionButton( ? _ActionButton(
icon: Icons.delete_outline_rounded, icon: Icons.delete_outline_rounded,
onTap: () => context.pushRoute(const DriftTrashRoute()), onTap: () => context.pushRoute(const DriftTrashRoute()),
label: 'trash'.t(context: context), label: context.t.trash,
) )
: const SizedBox.shrink(), : const SizedBox.shrink(),
], ],
@ -193,7 +192,7 @@ class _PeopleCollectionCard extends ConsumerWidget {
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
'people'.t(context: context), context.t.people,
style: context.textTheme.titleSmall?.copyWith( style: context.textTheme.titleSmall?.copyWith(
color: context.colorScheme.onSurface, color: context.colorScheme.onSurface,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -245,7 +244,7 @@ class _PlacesCollectionCard extends StatelessWidget {
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
'places'.t(), context.t.places,
style: context.textTheme.titleSmall?.copyWith( style: context.textTheme.titleSmall?.copyWith(
color: context.colorScheme.onSurface, color: context.colorScheme.onSurface,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -303,9 +302,7 @@ class _LocalAlbumsCollectionCard extends ConsumerWidget {
}).toList(); }).toList();
}, },
error: (error, _) { error: (error, _) {
return [ return [Center(child: Text(context.t.error_saving_image(error: error.toString())))];
Center(child: Text('error_saving_image'.tr(args: [error.toString()]))),
];
}, },
loading: () { loading: () {
return [const Center(child: CircularProgressIndicator())]; return [const Center(child: CircularProgressIndicator())];
@ -317,7 +314,7 @@ class _LocalAlbumsCollectionCard extends ConsumerWidget {
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
'on_this_device'.t(context: context), context.t.on_this_device,
style: context.textTheme.titleSmall?.copyWith( style: context.textTheme.titleSmall?.copyWith(
color: context.colorScheme.onSurface, color: context.colorScheme.onSurface,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -384,7 +381,7 @@ class _QuickAccessButtonList extends ConsumerWidget {
), ),
leading: const Icon(Icons.folder_outlined, size: 26), leading: const Icon(Icons.folder_outlined, size: 26),
title: Text( title: Text(
'folders'.t(context: context), context.t.folders,
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500),
), ),
onTap: () => context.pushRoute(FolderRoute()), onTap: () => context.pushRoute(FolderRoute()),
@ -392,7 +389,7 @@ class _QuickAccessButtonList extends ConsumerWidget {
ListTile( ListTile(
leading: const Icon(Icons.lock_outline_rounded, size: 26), leading: const Icon(Icons.lock_outline_rounded, size: 26),
title: Text( title: Text(
'locked_folder'.t(context: context), context.t.locked_folder,
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500),
), ),
onTap: () => context.pushRoute(const DriftLockedFolderRoute()), onTap: () => context.pushRoute(const DriftLockedFolderRoute()),
@ -400,7 +397,7 @@ class _QuickAccessButtonList extends ConsumerWidget {
ListTile( ListTile(
leading: const Icon(Icons.group_outlined, size: 26), leading: const Icon(Icons.group_outlined, size: 26),
title: Text( title: Text(
'partners'.t(context: context), context.t.partners,
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500),
), ),
onTap: () => context.pushRoute(const PartnerRoute()), onTap: () => context.pushRoute(const PartnerRoute()),
@ -438,10 +435,10 @@ class _PartnerList extends StatelessWidget {
), ),
contentPadding: const EdgeInsets.only(left: 12.0, right: 18.0), contentPadding: const EdgeInsets.only(left: 12.0, right: 18.0),
leading: PartnerUserAvatar(userId: partner.id, name: partner.name), leading: PartnerUserAvatar(userId: partner.id, name: partner.name),
title: const Text( title: Text(
"partner_list_user_photos", context.t.partner_list_user_photos(user: partner.name),
style: TextStyle(fontWeight: FontWeight.w500), style: const TextStyle(fontWeight: FontWeight.w500),
).t(context: context, args: {'user': partner.name}), ),
onTap: () => context.pushRoute(DriftPartnerDetailRoute(partner: partner)), onTap: () => context.pushRoute(DriftPartnerDetailRoute(partner: partner)),
); );
}, },

View file

@ -1,10 +1,9 @@
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.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/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/pages/common/large_leading_tile.dart'; import 'package:immich_mobile/pages/common/large_leading_tile.dart';
import 'package:immich_mobile/presentation/widgets/images/local_album_thumbnail.widget.dart'; import 'package:immich_mobile/presentation/widgets/images/local_album_thumbnail.widget.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
@ -49,7 +48,7 @@ class _AlbumList extends ConsumerWidget {
if (albums.isEmpty) { if (albums.isEmpty) {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: Center( child: Center(
child: Padding(padding: const EdgeInsets.all(20.0), child: Text('no_albums_yet'.tr())), child: Padding(padding: const EdgeInsets.all(20.0), child: Text(context.t.no_albums_yet)),
), ),
); );
} }
@ -67,7 +66,7 @@ class _AlbumList extends ConsumerWidget {
leading: SizedBox(width: 80, height: 80, child: LocalAlbumThumbnail(albumId: album.id)), leading: SizedBox(width: 80, height: 80, child: LocalAlbumThumbnail(albumId: album.id)),
title: Text(album.name, style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600)), title: Text(album.name, style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600)),
subtitle: Text( subtitle: Text(
'items_count'.t(context: context, args: {'count': album.assetCount}), context.t.items_count(count: album.assetCount),
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
onTap: () => context.pushRoute(LocalTimelineRoute(album: album)), onTap: () => context.pushRoute(LocalTimelineRoute(album: album)),

View file

@ -3,7 +3,7 @@ import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/locked_folder_bottom_sheet.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/locked_folder_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart'; import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/auth.provider.dart';
@ -70,7 +70,7 @@ class _DriftLockedFolderPageState extends ConsumerState<DriftLockedFolderPage> w
: PopScope( : PopScope(
onPopInvokedWithResult: (didPop, _) => didPop ? ref.read(authProvider.notifier).lockPinCode() : null, onPopInvokedWithResult: (didPop, _) => didPop ? ref.read(authProvider.notifier).lockPinCode() : null,
child: Timeline( child: Timeline(
appBar: MesmerizingSliverAppBar(title: 'locked_folder'.t(context: context)), appBar: MesmerizingSliverAppBar(title: context.t.locked_folder),
bottomSheet: const LockedFolderBottomSheet(), bottomSheet: const LockedFolderBottomSheet(),
), ),
), ),

View file

@ -1,11 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.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/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/string_extensions.dart'; import 'package:immich_mobile/extensions/string_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart';
import 'package:immich_mobile/providers/infrastructure/people.provider.dart'; import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
@ -49,10 +49,10 @@ class _DriftPeopleCollectionPageState extends ConsumerState<DriftPeopleCollectio
onTapOutside: (_) => _formFocus.unfocus(), onTapOutside: (_) => _formFocus.unfocus(),
onChanged: (value) => setState(() => _search = value), onChanged: (value) => setState(() => _search = value),
filled: true, filled: true,
hintText: 'filter_people'.tr(), hintText: context.t.filter_people,
autofocus: true, autofocus: true,
) )
: Text('people'.tr()), : Text(context.t.people),
actions: [ actions: [
IconButton( IconButton(
icon: Icon(_search != null ? Icons.close : Icons.search), icon: Icon(_search != null ? Icons.close : Icons.search),
@ -107,7 +107,7 @@ class _DriftPeopleCollectionPageState extends ConsumerState<DriftPeopleCollectio
onTap: () => showNameEditModal(context, person), onTap: () => showNameEditModal(context, person),
child: person.name.isEmpty child: person.name.isEmpty
? Text( ? Text(
'add_a_name'.tr(), context.t.add_a_name,
style: context.textTheme.titleSmall?.copyWith( style: context.textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: context.colorScheme.primary, color: context.colorScheme.primary,

View file

@ -7,7 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/album/pending_uploads_banner.widget.dart'; import 'package:immich_mobile/presentation/widgets/album/pending_uploads_banner.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/remote_album/drift_album_option.widget.dart'; import 'package:immich_mobile/presentation/widgets/remote_album/drift_album_option.widget.dart';
@ -62,7 +62,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
if (added > 0) { if (added > 0) {
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: "assets_added_to_album_count".t(context: context, args: {'count': added.toString()}), msg: context.t.assets_added_to_album_count(count: added),
toastType: ToastType.success, toastType: ToastType.success,
); );
} }
@ -88,7 +88,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: "users_added_to_album_count".t(context: context, args: {'count': newUsers.length}), msg: context.t.users_added_to_album_count(count: newUsers.length),
toastType: ToastType.success, toastType: ToastType.success,
); );
} catch (e) { } catch (e) {
@ -111,24 +111,21 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text('delete_album'.t(context: context)), title: Text(context.t.delete_album),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text('album_delete_confirmation'.t(context: context, args: {'album': _album.name})), Text(context.t.album_delete_confirmation(album: _album.name)),
const SizedBox(height: 8), const SizedBox(height: 8),
Text('album_delete_confirmation_description'.t(context: context)), Text(context.t.album_delete_confirmation_description),
], ],
), ),
actions: [ actions: [
TextButton( TextButton(onPressed: () => Navigator.of(context).pop(false), child: Text(context.t.cancel)),
onPressed: () => Navigator.of(context).pop(false),
child: Text('cancel'.t(context: context)),
),
TextButton( TextButton(
onPressed: () => Navigator.of(context).pop(true), onPressed: () => Navigator.of(context).pop(true),
style: TextButton.styleFrom(foregroundColor: Theme.of(context).colorScheme.error), style: TextButton.styleFrom(foregroundColor: Theme.of(context).colorScheme.error),
child: Text('delete_album'.t(context: context)), child: Text(context.t.delete_album),
), ),
], ],
); );
@ -146,11 +143,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
return; return;
} }
ImmichToast.show( ImmichToast.show(context: context, msg: context.t.album_deleted, toastType: ToastType.success);
context: context,
msg: 'album_deleted'.t(context: context),
toastType: ToastType.success,
);
unawaited(context.pushRoute(const DriftAlbumsRoute())); unawaited(context.pushRoute(const DriftAlbumsRoute()));
} catch (e) { } catch (e) {
@ -160,7 +153,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: 'album_viewer_appbar_share_err_delete'.t(context: context), msg: context.t.album_viewer_appbar_share_err_delete,
toastType: ToastType.error, toastType: ToastType.error,
); );
} }
@ -288,11 +281,7 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> {
return; return;
} }
ImmichToast.show( ImmichToast.show(context: context, msg: context.t.errors.unable_to_update_album_info, toastType: ToastType.error);
context: context,
msg: 'album_update_error'.t(context: context),
toastType: ToastType.error,
);
} }
} }
@ -315,14 +304,14 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> {
children: [ children: [
Icon(Icons.edit_outlined, color: context.colorScheme.primary, size: 24), Icon(Icons.edit_outlined, color: context.colorScheme.primary, size: 24),
const SizedBox(width: 12), const SizedBox(width: 12),
Text('edit_album'.t(context: context), style: context.textTheme.titleMedium), Text(context.t.edit_album, style: context.textTheme.titleMedium),
], ],
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
// Album Name // Album Name
Text( Text(
'album_name'.t(context: context).toUpperCase(), context.t.album_name.toUpperCase(),
style: context.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.w600), style: context.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.w600),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
@ -337,7 +326,7 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> {
), ),
validator: (value) { validator: (value) {
if (value == null || value.trim().isEmpty) { if (value == null || value.trim().isEmpty) {
return 'album_name_required'.t(context: context); return context.t.name_required;
} }
return null; return null;
@ -347,7 +336,7 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> {
// Description // Description
Text( Text(
'description'.t(context: context).toUpperCase(), context.t.description.toUpperCase(),
style: context.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.w600), style: context.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.w600),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
@ -367,15 +356,9 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
TextButton( TextButton(onPressed: () => Navigator.of(context).pop(null), child: Text(context.t.cancel)),
onPressed: () => Navigator.of(context).pop(null),
child: Text('cancel'.t(context: context)),
),
const SizedBox(width: 12), const SizedBox(width: 12),
FilledButton( FilledButton(onPressed: _handleSave, child: Text(context.t.save)),
onPressed: _handleSave,
child: Text('save'.t(context: context)),
),
], ],
), ),
], ],

View file

@ -2,7 +2,6 @@ import 'package:auto_route/auto_route.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/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/trash_bottom_sheet.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/trash_bottom_sheet.widget.dart';
@ -35,7 +34,7 @@ class DriftTrashPage extends StatelessWidget {
], ],
child: Timeline( child: Timeline(
appBar: SliverAppBar( appBar: SliverAppBar(
title: Text('trash'.t(context: context)), title: Text(context.t.trash),
floating: true, floating: true,
snap: true, snap: true,
pinned: true, pinned: true,

View file

@ -2,14 +2,13 @@ import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.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/constants/enums.dart'; import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/models/albums/album_search.model.dart'; import 'package:immich_mobile/models/albums/album_search.model.dart';
import 'package:immich_mobile/presentation/widgets/album/album_tile.dart'; import 'package:immich_mobile/presentation/widgets/album/album_tile.dart';
import 'package:immich_mobile/presentation/widgets/album/new_album_name_modal.widget.dart'; import 'package:immich_mobile/presentation/widgets/album/new_album_name_modal.widget.dart';
@ -326,7 +325,7 @@ class _SortButtonState extends ConsumerState<_SortButton> {
), ),
), ),
child: Text( child: Text(
sortMode.label.t(context: context), sortMode.label(context.t),
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(
color: albumSortOption == sortMode color: albumSortOption == sortMode
? context.colorScheme.onPrimary ? context.colorScheme.onPrimary
@ -354,7 +353,7 @@ class _SortButtonState extends ConsumerState<_SortButton> {
: Icon(Icons.keyboard_arrow_up_rounded, color: context.colorScheme.onSurface), : Icon(Icons.keyboard_arrow_up_rounded, color: context.colorScheme.onSurface),
), ),
Text( Text(
albumSortOption.label.t(context: context), albumSortOption.label(context.t),
style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(225)), style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(225)),
), ),
isSorting isSorting
@ -413,7 +412,7 @@ class _SearchBar extends StatelessWidget {
child: SearchField( child: SearchField(
autofocus: false, autofocus: false,
contentPadding: const EdgeInsets.all(16), contentPadding: const EdgeInsets.all(16),
hintText: 'search_albums'.tr(), hintText: context.t.search_albums,
prefixIcon: const Icon(Icons.search_rounded), prefixIcon: const Icon(Icons.search_rounded),
suffixIcon: searchController.text.isNotEmpty suffixIcon: searchController.text.isNotEmpty
? IconButton(icon: const Icon(Icons.clear_rounded), onPressed: onClearSearch) ? IconButton(icon: const Icon(Icons.clear_rounded), onPressed: onClearSearch)
@ -452,7 +451,7 @@ class _QuickFilterButtonRow extends StatelessWidget {
runSpacing: 4, runSpacing: 4,
children: [ children: [
_QuickFilterButton( _QuickFilterButton(
label: 'all'.tr(), label: context.t.all,
isSelected: filterMode == QuickFilterMode.all, isSelected: filterMode == QuickFilterMode.all,
onTap: () { onTap: () {
onChangeFilter(QuickFilterMode.all); onChangeFilter(QuickFilterMode.all);
@ -460,7 +459,7 @@ class _QuickFilterButtonRow extends StatelessWidget {
}, },
), ),
_QuickFilterButton( _QuickFilterButton(
label: 'shared_with_me'.tr(), label: context.t.shared_with_me,
isSelected: filterMode == QuickFilterMode.sharedWithMe, isSelected: filterMode == QuickFilterMode.sharedWithMe,
onTap: () { onTap: () {
onChangeFilter(QuickFilterMode.sharedWithMe); onChangeFilter(QuickFilterMode.sharedWithMe);
@ -468,7 +467,7 @@ class _QuickFilterButtonRow extends StatelessWidget {
}, },
), ),
_QuickFilterButton( _QuickFilterButton(
label: 'my_albums'.tr(), label: context.t.my_albums,
isSelected: filterMode == QuickFilterMode.myAlbums, isSelected: filterMode == QuickFilterMode.myAlbums,
onTap: () { onTap: () {
onChangeFilter(QuickFilterMode.myAlbums); onChangeFilter(QuickFilterMode.myAlbums);
@ -571,7 +570,7 @@ class _AlbumList extends ConsumerWidget {
if (albums.isEmpty) { if (albums.isEmpty) {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: Center( child: Center(
child: Padding(padding: const EdgeInsets.all(20.0), child: Text('album_search_not_found'.tr())), child: Padding(padding: const EdgeInsets.all(20.0), child: Text(context.t.album_search_not_found)),
), ),
); );
} }
@ -600,9 +599,9 @@ class _AlbumList extends ConsumerWidget {
context: context, context: context,
builder: (context) => ConfirmDialog( builder: (context) => ConfirmDialog(
onOk: () => true, onOk: () => true,
title: "delete_album".t(context: context), title: context.t.delete_album,
content: "album_delete_confirmation".t(context: context, args: {'album': album.name}), content: context.t.album_delete_confirmation(album: album.name),
ok: "delete".t(context: context), ok: context.t.delete,
), ),
); );
}, },
@ -637,7 +636,7 @@ class _AlbumGrid extends StatelessWidget {
if (albums.isEmpty) { if (albums.isEmpty) {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: Center( child: Center(
child: Padding(padding: const EdgeInsets.all(20.0), child: Text('album_search_not_found'.tr())), child: Padding(padding: const EdgeInsets.all(20.0), child: Text(context.t.album_search_not_found)),
), ),
); );
} }
@ -723,7 +722,7 @@ class _GridAlbumCard extends ConsumerWidget {
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600), style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600),
), ),
Text( Text(
'${'items_count'.t(context: context, args: {'count': album.assetCount})}${album.ownerId != userId ? 'shared_by_user'.t(context: context, args: {'user': album.ownerName}) : 'owned'.t(context: context)}', '${context.t.items_count(count: album.assetCount)}${album.ownerId != userId ? context.t.shared_by_user(user: album.ownerName) : context.t.owned}',
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: context.textTheme.labelMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.labelMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
@ -760,7 +759,7 @@ class AddToAlbumHeader extends ConsumerWidget {
} }
if (newAlbum == null) { if (newAlbum == null) {
ImmichToast.show(context: context, toastType: ToastType.error, msg: 'errors.failed_to_create_album'.tr()); ImmichToast.show(context: context, toastType: ToastType.error, msg: context.t.errors.failed_to_create_album);
return; return;
} }
@ -774,7 +773,7 @@ class AddToAlbumHeader extends ConsumerWidget {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text("add_to_album", style: context.textTheme.titleSmall).tr(), Text(context.t.add_to_album, style: context.textTheme.titleSmall),
TextButton.icon( TextButton.icon(
style: TextButton.styleFrom( style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), // remove internal padding padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), // remove internal padding
@ -784,9 +783,9 @@ class AddToAlbumHeader extends ConsumerWidget {
onPressed: onCreateAlbum, onPressed: onCreateAlbum,
icon: Icon(Icons.add, color: context.primaryColor), icon: Icon(Icons.add, color: context.primaryColor),
label: Text( label: Text(
"common_create_new_album", context.t.common_create_new_album,
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 14), style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 14),
).tr(), ),
), ),
], ],
), ),
@ -822,13 +821,13 @@ class CreateAlbumButton extends ConsumerWidget {
} }
if (album == null) { if (album == null) {
ImmichToast.show(context: context, toastType: ToastType.error, msg: 'errors.failed_to_create_album'.tr()); ImmichToast.show(context: context, toastType: ToastType.error, msg: context.t.errors.failed_to_create_album);
return; return;
} }
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}), msg: context.t.add_to_album_bottom_sheet_added(album: album.name),
); );
// Invalidate using the asset's remote ID to refresh the "Appears in" list // Invalidate using the asset's remote ID to refresh the "Appears in" list
@ -843,7 +842,7 @@ class CreateAlbumButton extends ConsumerWidget {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text("add_to_album", style: context.textTheme.titleSmall).tr(), Text(context.t.add_to_album, style: context.textTheme.titleSmall),
TextButton.icon( TextButton.icon(
style: TextButton.styleFrom( style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
@ -853,9 +852,9 @@ class CreateAlbumButton extends ConsumerWidget {
onPressed: onCreateAlbum, onPressed: onCreateAlbum,
icon: Icon(Icons.add, color: context.primaryColor), icon: Icon(Icons.add, color: context.primaryColor),
label: Text( label: Text(
"common_create_new_album", context.t.common_create_new_album,
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 14), style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 14),
).tr(), ),
), ),
], ],
), ),

View file

@ -3,7 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/pages/common/large_leading_tile.dart'; import 'package:immich_mobile/pages/common/large_leading_tile.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
@ -27,7 +27,7 @@ class AlbumTile extends ConsumerWidget {
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600), style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600),
), ),
subtitle: Text( subtitle: Text(
'${'items_count'.t(context: context, args: {'count': album.assetCount})} • ${isOwner ? 'owned'.t(context: context) : 'shared_by_user'.t(context: context, args: {'user': album.ownerName})}', '${context.t.items_count(count: album.assetCount)}${isOwner ? context.t.owned : context.t.shared_by_user(user: album.ownerName)}',
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),

View file

@ -1,7 +1,7 @@
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/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/widgets/common/user_circle_avatar.dart'; import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
@ -98,7 +98,7 @@ class _DriftActivityTextFieldState extends ConsumerState<DriftActivityTextField>
color: context.primaryColor, color: context.primaryColor,
disabledColor: context.colorScheme.secondaryContainer, disabledColor: context.colorScheme.secondaryContainer,
), ),
hintText: !widget.isEnabled ? 'shared_album_activities_input_disable'.tr() : 'say_something'.tr(), hintText: !widget.isEnabled ? context.t.shared_album_activities_input_disable : context.t.say_something,
hintStyle: TextStyle(fontWeight: FontWeight.normal, fontSize: 14, color: Colors.grey[600]), hintStyle: TextStyle(fontWeight: FontWeight.normal, fontSize: 14, color: Colors.grey[600]),
), ),
onEditingComplete: onEditingComplete, onEditingComplete: onEditingComplete,

View file

@ -1,6 +1,6 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
class NewAlbumNameModal extends StatefulWidget { class NewAlbumNameModal extends StatefulWidget {
const NewAlbumNameModal({super.key}); const NewAlbumNameModal({super.key});
@ -21,31 +21,31 @@ class _NewAlbumNameModalState extends State<NewAlbumNameModal> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
title: const Text("album_name", style: TextStyle(fontWeight: FontWeight.bold)).tr(), title: Text(context.t.album_name, style: const TextStyle(fontWeight: FontWeight.bold)),
content: SingleChildScrollView( content: SingleChildScrollView(
child: TextFormField( child: TextFormField(
controller: nameController, controller: nameController,
textCapitalization: TextCapitalization.words, textCapitalization: TextCapitalization.words,
autofocus: true, autofocus: true,
decoration: InputDecoration(hintText: 'name'.tr(), border: const OutlineInputBorder()), decoration: InputDecoration(hintText: context.t.name, border: const OutlineInputBorder()),
), ),
), ),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => context.pop(null), onPressed: () => context.pop(null),
child: Text( child: Text(
"cancel", context.t.cancel,
style: TextStyle(color: Colors.red[300], fontWeight: FontWeight.bold), style: TextStyle(color: Colors.red[300], fontWeight: FontWeight.bold),
).tr(), ),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
context.pop(nameController.text.trim()); context.pop(nameController.text.trim());
}, },
child: Text( child: Text(
"create_album", context.t.create_album,
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold), style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold),
).tr(), ),
), ),
], ],
); );

View file

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/album/pending_album_uploads.provider.dart'; import 'package:immich_mobile/providers/album/pending_album_uploads.provider.dart';
import 'package:immich_mobile/providers/backup/asset_upload_progress.provider.dart'; import 'package:immich_mobile/providers/backup/asset_upload_progress.provider.dart';
@ -115,7 +115,7 @@ class _PendingUploadsBannerContent extends StatelessWidget {
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
child: Text( child: Text(
'${'uploading'.t(context: context)} $count$percentLabel', '${context.t.uploading} $count$percentLabel',
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500), style: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500),
@ -183,10 +183,7 @@ class _PendingUploadsSheet extends ConsumerWidget {
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
child: Text( child: Text('${context.t.uploading} (${pending.length})', style: context.textTheme.titleMedium),
'${'uploading'.t(context: context)} (${pending.length})',
style: context.textTheme.titleMedium,
),
), ),
if (canAbort) if (canAbort)
TextButton.icon( TextButton.icon(
@ -199,14 +196,14 @@ class _PendingUploadsSheet extends ConsumerWidget {
ref.read(pendingAlbumUploadsProvider(albumId).notifier).clear(); ref.read(pendingAlbumUploadsProvider(albumId).notifier).clear();
}, },
icon: const Icon(Icons.stop_circle_outlined, size: 18), icon: const Icon(Icons.stop_circle_outlined, size: 18),
label: Text('cancel'.t(context: context)), label: Text(context.t.cancel),
style: TextButton.styleFrom(foregroundColor: context.colorScheme.error), style: TextButton.styleFrom(foregroundColor: context.colorScheme.error),
) )
else if (failedCount > 0) else if (failedCount > 0)
TextButton.icon( TextButton.icon(
onPressed: () => ref.read(pendingAlbumUploadsProvider(albumId).notifier).clearFailed(), onPressed: () => ref.read(pendingAlbumUploadsProvider(albumId).notifier).clearFailed(),
icon: const Icon(Icons.clear_rounded, size: 18), icon: const Icon(Icons.clear_rounded, size: 18),
label: Text('clear_failed_count'.t(context: context, args: {'count': failedCount})), label: Text(context.t.clear_failed_count(count: failedCount)),
style: TextButton.styleFrom(foregroundColor: context.colorScheme.error), style: TextButton.styleFrom(foregroundColor: context.colorScheme.error),
), ),
], ],

View file

@ -1,8 +1,8 @@
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/constants/enums.dart'; import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/actions/action.widget.dart'; import 'package:immich_mobile/presentation/actions/action.widget.dart';
import 'package:immich_mobile/presentation/actions/archive.action.dart'; import 'package:immich_mobile/presentation/actions/archive.action.dart';
import 'package:immich_mobile/presentation/actions/asset_debug.action.dart'; import 'package:immich_mobile/presentation/actions/asset_debug.action.dart';
@ -52,15 +52,15 @@ class _ArchiveBottomSheetState extends ConsumerState<ArchiveBottomSheet> {
} }
if (!result.success) { if (!result.success) {
ImmichToast.show(context: context, msg: 'scaffold_body_error_occurred'.tr(), toastType: ToastType.error); ImmichToast.show(context: context, msg: context.t.scaffold_body_error_occurred, toastType: ToastType.error);
return; return;
} }
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: result.count == 0 msg: result.count == 0
? 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name}) ? context.t.add_to_album_bottom_sheet_already_exists(album: album.name)
: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}), : context.t.add_to_album_bottom_sheet_added(album: album.name),
); );
} }

View file

@ -1,8 +1,8 @@
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/constants/enums.dart'; import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/actions/action.widget.dart'; import 'package:immich_mobile/presentation/actions/action.widget.dart';
import 'package:immich_mobile/presentation/actions/asset_debug.action.dart'; import 'package:immich_mobile/presentation/actions/asset_debug.action.dart';
import 'package:immich_mobile/presentation/actions/delete.action.dart'; import 'package:immich_mobile/presentation/actions/delete.action.dart';
@ -45,15 +45,15 @@ class _LocalAlbumBottomSheetState extends ConsumerState<LocalAlbumBottomSheet> {
} }
if (!result.success) { if (!result.success) {
ImmichToast.show(context: context, msg: 'scaffold_body_error_occurred'.tr(), toastType: ToastType.error); ImmichToast.show(context: context, msg: context.t.scaffold_body_error_occurred, toastType: ToastType.error);
return; return;
} }
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: result.count == 0 msg: result.count == 0
? 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name}) ? context.t.add_to_album_bottom_sheet_already_exists(album: album.name)
: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}), : context.t.add_to_album_bottom_sheet_added(album: album.name),
); );
} }

View file

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/actions/action.widget.dart'; import 'package:immich_mobile/presentation/actions/action.widget.dart';
import 'package:immich_mobile/presentation/actions/archive.action.dart'; import 'package:immich_mobile/presentation/actions/archive.action.dart';
import 'package:immich_mobile/presentation/actions/asset_debug.action.dart'; import 'package:immich_mobile/presentation/actions/asset_debug.action.dart';
@ -58,19 +58,15 @@ class _RemoteAlbumBottomSheetState extends ConsumerState<RemoteAlbumBottomSheet>
} }
if (!result.success) { if (!result.success) {
ImmichToast.show( ImmichToast.show(context: context, msg: context.t.scaffold_body_error_occurred, toastType: ToastType.error);
context: context,
msg: 'scaffold_body_error_occurred'.t(context: context),
toastType: ToastType.error,
);
return; return;
} }
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: result.count == 0 msg: result.count == 0
? 'add_to_album_bottom_sheet_already_exists'.t(context: context, args: {"album": album.name}) ? context.t.add_to_album_bottom_sheet_already_exists(album: album.name)
: 'add_to_album_bottom_sheet_added'.t(context: context, args: {"album": album.name}), : context.t.add_to_album_bottom_sheet_added(album: album.name),
); );
} }

View file

@ -4,7 +4,7 @@ import 'package:fluttertoast/fluttertoast.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/person.model.dart'; import 'package:immich_mobile/domain/models/person.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/providers/infrastructure/people.provider.dart'; import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
import 'package:immich_mobile/utils/debug_print.dart'; import 'package:immich_mobile/utils/debug_print.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart';
@ -49,7 +49,7 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonBirthdayEdi
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: 'scaffold_body_error_occurred'.t(context: context), msg: context.t.scaffold_body_error_occurred,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
toastType: ToastType.error, toastType: ToastType.error,
); );
@ -59,10 +59,7 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonBirthdayEdi
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text( title: Text(context.t.edit_birthday, style: const TextStyle(fontWeight: FontWeight.bold)),
"edit_birthday".t(context: context),
style: const TextStyle(fontWeight: FontWeight.bold),
),
content: SizedBox( content: SizedBox(
width: double.maxFinite, width: double.maxFinite,
height: 300, height: 300,
@ -108,16 +105,16 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonBirthdayEdi
TextButton( TextButton(
onPressed: () => context.pop(null), onPressed: () => context.pop(null),
child: Text( child: Text(
"cancel", context.t.cancel,
style: TextStyle(color: Colors.red[300], fontWeight: FontWeight.bold), style: TextStyle(color: Colors.red[300], fontWeight: FontWeight.bold),
).tr(), ),
), ),
TextButton( TextButton(
onPressed: () => saveBirthday(), onPressed: () => saveBirthday(),
child: Text( child: Text(
"save", context.t.save,
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold), style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold),
).tr(), ),
), ),
], ],
); );

View file

@ -1,10 +1,9 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.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/domain/models/person.model.dart'; import 'package:immich_mobile/domain/models/person.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/providers/infrastructure/people.provider.dart'; import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
import 'package:immich_mobile/utils/debug_print.dart'; import 'package:immich_mobile/utils/debug_print.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart';
@ -47,7 +46,7 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonNameEditFor
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: 'scaffold_body_error_occurred'.t(context: context), msg: context.t.scaffold_body_error_occurred,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
toastType: ToastType.error, toastType: ToastType.error,
); );
@ -57,29 +56,29 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonNameEditFor
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
title: const Text("edit_name", style: TextStyle(fontWeight: FontWeight.bold)).tr(), title: Text(context.t.edit_name, style: const TextStyle(fontWeight: FontWeight.bold)),
content: SingleChildScrollView( content: SingleChildScrollView(
child: TextFormField( child: TextFormField(
controller: _formController, controller: _formController,
textCapitalization: TextCapitalization.words, textCapitalization: TextCapitalization.words,
autofocus: true, autofocus: true,
decoration: InputDecoration(hintText: 'name'.tr(), border: const OutlineInputBorder()), decoration: InputDecoration(hintText: context.t.name, border: const OutlineInputBorder()),
), ),
), ),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => context.pop(null), onPressed: () => context.pop(null),
child: Text( child: Text(
"cancel", context.t.cancel,
style: TextStyle(color: Colors.red[300], fontWeight: FontWeight.bold), style: TextStyle(color: Colors.red[300], fontWeight: FontWeight.bold),
).tr(), ),
), ),
TextButton( TextButton(
onPressed: () => onEdit(widget.person.id, _formController.text), onPressed: () => onEdit(widget.person.id, _formController.text),
child: Text( child: Text(
"save", context.t.save,
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold), style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold),
).tr(), ),
), ),
], ],
); );

View file

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
class PersonOptionSheet extends StatelessWidget { class PersonOptionSheet extends StatelessWidget {
const PersonOptionSheet({super.key, this.onEditName, this.onEditBirthday, this.birthdayExists = false}); const PersonOptionSheet({super.key, this.onEditName, this.onEditBirthday, this.birthdayExists = false});
@ -20,12 +20,12 @@ class PersonOptionSheet extends StatelessWidget {
children: [ children: [
ListTile( ListTile(
leading: const Icon(Icons.edit), leading: const Icon(Icons.edit),
title: Text('edit_name'.t(context: context), style: textStyle), title: Text(context.t.edit_name, style: textStyle),
onTap: onEditName, onTap: onEditName,
), ),
ListTile( ListTile(
leading: const Icon(Icons.cake), leading: const Icon(Icons.cake),
title: Text((birthdayExists ? 'edit_birthday' : "add_birthday").t(context: context), style: textStyle), title: Text(birthdayExists ? context.t.edit_birthday : context.t.add_birthday, style: textStyle),
onTap: onEditBirthday, onTap: onEditBirthday,
), ),
], ],

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
class DriftRemoteAlbumOption extends StatelessWidget { class DriftRemoteAlbumOption extends StatelessWidget {
@ -36,19 +36,14 @@ class DriftRemoteAlbumOption extends StatelessWidget {
if (onEditAlbum != null) { if (onEditAlbum != null) {
menuChildren.add( menuChildren.add(
BaseActionButton( BaseActionButton(label: context.t.edit_album, iconData: Icons.edit, onPressed: onEditAlbum, menuItem: true),
label: 'edit_album'.t(context: context),
iconData: Icons.edit,
onPressed: onEditAlbum,
menuItem: true,
),
); );
} }
if (onAddPhotos != null) { if (onAddPhotos != null) {
menuChildren.add( menuChildren.add(
BaseActionButton( BaseActionButton(
label: 'add_photos'.t(context: context), label: context.t.add_photos,
iconData: Icons.add_a_photo, iconData: Icons.add_a_photo,
onPressed: onAddPhotos, onPressed: onAddPhotos,
menuItem: true, menuItem: true,
@ -59,7 +54,7 @@ class DriftRemoteAlbumOption extends StatelessWidget {
if (onAddUsers != null) { if (onAddUsers != null) {
menuChildren.add( menuChildren.add(
BaseActionButton( BaseActionButton(
label: 'album_viewer_page_share_add_users'.t(context: context), label: context.t.album_viewer_page_share_add_users,
iconData: Icons.group_add, iconData: Icons.group_add,
onPressed: onAddUsers, onPressed: onAddUsers,
menuItem: true, menuItem: true,
@ -70,7 +65,7 @@ class DriftRemoteAlbumOption extends StatelessWidget {
if (onLeaveAlbum != null) { if (onLeaveAlbum != null) {
menuChildren.add( menuChildren.add(
BaseActionButton( BaseActionButton(
label: 'leave_album'.t(context: context), label: context.t.leave_album,
iconData: Icons.person_remove_rounded, iconData: Icons.person_remove_rounded,
onPressed: onLeaveAlbum, onPressed: onLeaveAlbum,
menuItem: true, menuItem: true,
@ -81,7 +76,7 @@ class DriftRemoteAlbumOption extends StatelessWidget {
if (onToggleAlbumOrder != null) { if (onToggleAlbumOrder != null) {
menuChildren.add( menuChildren.add(
BaseActionButton( BaseActionButton(
label: 'change_display_order'.t(context: context), label: context.t.change_display_order,
iconData: Icons.swap_vert_rounded, iconData: Icons.swap_vert_rounded,
onPressed: onToggleAlbumOrder, onPressed: onToggleAlbumOrder,
menuItem: true, menuItem: true,
@ -92,7 +87,7 @@ class DriftRemoteAlbumOption extends StatelessWidget {
if (onCreateSharedLink != null) { if (onCreateSharedLink != null) {
menuChildren.add( menuChildren.add(
BaseActionButton( BaseActionButton(
label: 'create_shared_link'.t(context: context), label: context.t.create_shared_link,
iconData: Icons.link, iconData: Icons.link,
onPressed: onCreateSharedLink, onPressed: onCreateSharedLink,
menuItem: true, menuItem: true,
@ -102,12 +97,7 @@ class DriftRemoteAlbumOption extends StatelessWidget {
if (onShowOptions != null) { if (onShowOptions != null) {
menuChildren.add( menuChildren.add(
BaseActionButton( BaseActionButton(label: context.t.options, iconData: Icons.settings, onPressed: onShowOptions, menuItem: true),
label: 'options'.t(context: context),
iconData: Icons.settings,
onPressed: onShowOptions,
menuItem: true,
),
); );
} }
@ -115,7 +105,7 @@ class DriftRemoteAlbumOption extends StatelessWidget {
menuChildren.add(const Divider(height: 1)); menuChildren.add(const Divider(height: 1));
menuChildren.add( menuChildren.add(
BaseActionButton( BaseActionButton(
label: 'delete_album'.t(context: context), label: context.t.delete_album,
iconData: Icons.delete, iconData: Icons.delete,
iconColor: context.isDarkTheme ? Colors.red[400] : Colors.red[800], iconColor: context.isDarkTheme ? Colors.red[400] : Colors.red[800],
onPressed: onDeleteAlbum, onPressed: onDeleteAlbum,

View file

@ -1,19 +1,28 @@
import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/generated/translations.g.dart';
// Store index allows us to re-arrange the values without affecting the saved prefs // Store index allows us to re-arrange the values without affecting the saved prefs
enum AlbumSortMode { enum AlbumSortMode {
title(1, "library_page_sort_title", SortOrder.asc), title(1, SortOrder.asc),
assetCount(4, "library_page_sort_asset_count", SortOrder.desc), assetCount(4, SortOrder.desc),
lastModified(3, "library_page_sort_last_modified", SortOrder.desc), lastModified(3, SortOrder.desc),
created(0, "library_page_sort_created", SortOrder.desc), created(0, SortOrder.desc),
mostRecent(2, "sort_recent", SortOrder.desc), mostRecent(2, SortOrder.desc),
mostOldest(5, "sort_oldest", SortOrder.asc); mostOldest(5, SortOrder.asc);
final int storeIndex; final int storeIndex;
final String label;
final SortOrder defaultOrder; final SortOrder defaultOrder;
const AlbumSortMode(this.storeIndex, this.label, this.defaultOrder); const AlbumSortMode(this.storeIndex, this.defaultOrder);
String label(Translations t) => switch (this) {
AlbumSortMode.title => t.library_page_sort_title,
AlbumSortMode.assetCount => t.library_page_sort_asset_count,
AlbumSortMode.lastModified => t.library_page_sort_last_modified,
AlbumSortMode.created => t.library_page_sort_created,
AlbumSortMode.mostRecent => t.sort_recent,
AlbumSortMode.mostOldest => t.sort_oldest,
};
SortOrder effectiveOrder(bool isReverse) => isReverse ? defaultOrder.reverse() : defaultOrder; SortOrder effectiveOrder(bool isReverse) => isReverse ? defaultOrder.reverse() : defaultOrder;
} }

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
class LocalAlbumsSliverAppBar extends StatelessWidget { class LocalAlbumsSliverAppBar extends StatelessWidget {
const LocalAlbumsSliverAppBar({super.key}); const LocalAlbumsSliverAppBar({super.key});
@ -15,7 +15,7 @@ class LocalAlbumsSliverAppBar extends StatelessWidget {
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5))),
automaticallyImplyLeading: true, automaticallyImplyLeading: true,
centerTitle: true, centerTitle: true,
title: Text("on_this_device".t(context: context)), title: Text(context.t.on_this_device),
); );
} }
} }

View file

@ -11,7 +11,7 @@ import 'package:immich_mobile/domain/models/person.model.dart';
import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/domain/services/timeline.service.dart';
import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/domain/utils/event_stream.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
@ -261,7 +261,7 @@ class _ExpandedBackgroundState extends ConsumerState<_ExpandedBackground> with S
), ),
) )
: Text( : Text(
'add_a_name'.tr(), context.t.add_a_name,
style: context.textTheme.titleLarge?.copyWith( style: context.textTheme.titleLarge?.copyWith(
color: Colors.grey[400], color: Colors.grey[400],
fontSize: 36, fontSize: 36,
@ -293,7 +293,7 @@ class _ExpandedBackgroundState extends ConsumerState<_ExpandedBackground> with S
) )
else else
Text( Text(
'add_birthday'.tr(), context.t.add_birthday,
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(
color: Colors.grey[400], color: Colors.grey[400],
height: 1.2, height: 1.2,
@ -344,7 +344,7 @@ class _ItemCountTextState extends ConsumerState<_ItemCountText> {
final assetCount = ref.watch(timelineServiceProvider.select((s) => s.totalAssets)); final assetCount = ref.watch(timelineServiceProvider.select((s) => s.totalAssets));
return Text( return Text(
'items_count'.t(context: context, args: {"count": assetCount}), context.t.items_count(count: assetCount),
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.white, color: Colors.white,

View file

@ -12,7 +12,7 @@ import 'package:immich_mobile/domain/services/timeline.service.dart';
import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/domain/utils/event_stream.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/datetime_extensions.dart'; import 'package:immich_mobile/extensions/datetime_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/remote_album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/remote_album.provider.dart';
@ -318,7 +318,7 @@ class _ItemCountTextState extends ConsumerState<_ItemCountText> {
final assetCount = ref.watch(timelineServiceProvider.select((s) => s.totalAssets)); final assetCount = ref.watch(timelineServiceProvider.select((s) => s.totalAssets));
return Text( return Text(
'items_count'.t(context: context, args: {"count": assetCount}), context.t.items_count(count: assetCount),
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(
color: Colors.white, color: Colors.white,
shadows: [const Shadow(offset: Offset(0, 2), blurRadius: 12, color: Colors.black87)], shadows: [const Shadow(offset: Offset(0, 2), blurRadius: 12, color: Colors.black87)],

View file

@ -1,112 +1,112 @@
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/domain/models/person.model.dart';
import 'package:immich_mobile/domain/models/person.model.dart'; import 'package:immich_mobile/extensions/asyncvalue_extensions.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/extensions/string_extensions.dart';
import 'package:immich_mobile/extensions/string_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/pages/common/large_leading_tile.dart'; import 'package:immich_mobile/pages/common/large_leading_tile.dart';
import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart';
import 'package:immich_mobile/providers/search/people.provider.dart'; import 'package:immich_mobile/providers/search/people.provider.dart';
import 'package:immich_mobile/utils/image_url_builder.dart'; import 'package:immich_mobile/utils/image_url_builder.dart';
import 'package:immich_mobile/widgets/common/search_field.dart'; import 'package:immich_mobile/widgets/common/search_field.dart';
class PeoplePicker extends HookConsumerWidget { class PeoplePicker extends HookConsumerWidget {
const PeoplePicker({super.key, required this.onSelect, this.filter}); const PeoplePicker({super.key, required this.onSelect, this.filter});
final Function(Set<PersonDto>) onSelect; final Function(Set<PersonDto>) onSelect;
final Set<PersonDto>? filter; final Set<PersonDto>? filter;
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final formFocus = useFocusNode(); final formFocus = useFocusNode();
const imageSize = 60.0; const imageSize = 60.0;
final searchQuery = useState(''); final searchQuery = useState('');
final people = ref.watch(getAllPeopleProvider); final people = ref.watch(getAllPeopleProvider);
final selectedPeople = useState<Set<PersonDto>>(filter ?? {}); final selectedPeople = useState<Set<PersonDto>>(filter ?? {});
return Column( return Column(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: SearchField( child: SearchField(
focusNode: formFocus, focusNode: formFocus,
onChanged: (value) => searchQuery.value = value, onChanged: (value) => searchQuery.value = value,
onTapOutside: (_) => formFocus.unfocus(), onTapOutside: (_) => formFocus.unfocus(),
filled: true, filled: true,
hintText: 'filter_people'.tr(), hintText: context.t.filter_people,
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 0), padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 0),
child: Divider(color: context.colorScheme.surfaceContainerHighest, thickness: 1), child: Divider(color: context.colorScheme.surfaceContainerHighest, thickness: 1),
), ),
Expanded( Expanded(
child: people.widgetWhen( child: people.widgetWhen(
onData: (people) { onData: (people) {
final filtered = people final filtered = people
.where( .where(
(person) => person.name.toLowerCase().removeDiacritics().contains( (person) => person.name.toLowerCase().removeDiacritics().contains(
searchQuery.value.toLowerCase().removeDiacritics(), searchQuery.value.toLowerCase().removeDiacritics(),
), ),
) )
.toList(); .toList();
return ListView.builder( return ListView.builder(
shrinkWrap: true, shrinkWrap: true,
itemCount: filtered.length, itemCount: filtered.length,
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final person = filtered[index]; final person = filtered[index];
final isSelected = selectedPeople.value.contains(person); final isSelected = selectedPeople.value.contains(person);
return Padding( return Padding(
key: ValueKey(person.id), key: ValueKey(person.id),
padding: const EdgeInsets.only(bottom: 2.0), padding: const EdgeInsets.only(bottom: 2.0),
child: LargeLeadingTile( child: LargeLeadingTile(
title: Text( title: Text(
person.name, person.name,
style: context.textTheme.bodyLarge?.copyWith( style: context.textTheme.bodyLarge?.copyWith(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: isSelected ? context.colorScheme.onPrimary : context.colorScheme.onSurface, color: isSelected ? context.colorScheme.onPrimary : context.colorScheme.onSurface,
), ),
), ),
leading: SizedBox( leading: SizedBox(
height: imageSize, height: imageSize,
child: Material( child: Material(
shape: const CircleBorder(side: BorderSide.none), shape: const CircleBorder(side: BorderSide.none),
elevation: 3, elevation: 3,
child: CircleAvatar( child: CircleAvatar(
key: ValueKey(person.id), key: ValueKey(person.id),
maxRadius: imageSize / 2, maxRadius: imageSize / 2,
backgroundImage: RemoteImageProvider( backgroundImage: RemoteImageProvider(
url: getFaceThumbnailUrl(person.id, updatedAt: person.updatedAt), url: getFaceThumbnailUrl(person.id, updatedAt: person.updatedAt),
), ),
), ),
), ),
), ),
onTap: () { onTap: () {
if (selectedPeople.value.contains(person)) { if (selectedPeople.value.contains(person)) {
selectedPeople.value.remove(person); selectedPeople.value.remove(person);
} else { } else {
selectedPeople.value.add(person); selectedPeople.value.add(person);
} }
selectedPeople.value = {...selectedPeople.value}; selectedPeople.value = {...selectedPeople.value};
onSelect(selectedPeople.value); onSelect(selectedPeople.value);
}, },
selected: isSelected, selected: isSelected,
selectedTileColor: context.primaryColor, selectedTileColor: context.primaryColor,
tileColor: context.primaryColor.withAlpha(25), tileColor: context.primaryColor.withAlpha(25),
), ),
); );
}, },
); );
}, },
), ),
), ),
], ],
); );
} }
} }