chore: migrate mobile translations accessor (3) (#30670)

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

View file

@ -1,7 +1,6 @@
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/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart';
@ -10,7 +9,6 @@ import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/extensions/platform_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/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/backup/backup_toggle_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/backup/backup_toggle_button.widget.dart';
import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart';
@ -108,7 +106,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
elevation: 0, elevation: 0,
title: Text("backup_controller_page_backup".t()), title: Text(context.t.backup_controller_page_backup),
leading: IconButton( leading: IconButton(
onPressed: () { onPressed: () {
unawaited(context.maybePop(true)); unawaited(context.maybePop(true));
@ -122,7 +120,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
unawaited(context.pushRoute(const DriftBackupOptionsRoute())); unawaited(context.pushRoute(const DriftBackupOptionsRoute()));
}, },
icon: const Icon(Icons.settings_outlined), icon: const Icon(Icons.settings_outlined),
tooltip: "backup_options".t(context: context), tooltip: context.t.backup_options,
), ),
], ],
), ),
@ -319,7 +317,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
Widget buildSelectedAlbumName() { Widget buildSelectedAlbumName() {
String text = "backup_controller_page_backup_selected".tr(); String text = context.t.backup_controller_page_backup_selected;
final albums = ref final albums = ref
.read(backupAlbumProvider) .read(backupAlbumProvider)
.where((album) => album.backupSelection == BackupSelection.selected) .where((album) => album.backupSelection == BackupSelection.selected)
@ -328,7 +326,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
if (albums.isNotEmpty) { if (albums.isNotEmpty) {
for (var album in albums) { for (var album in albums) {
if (album.name == "Recent" || album.name == "Recents") { if (album.name == "Recent" || album.name == "Recents") {
text += "${album.name} (${'all'.tr()}), "; text += "${album.name} (${context.t.all}), ";
} else { } else {
text += "${album.name}, "; text += "${album.name}, ";
} }
@ -345,7 +343,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
return Padding( return Padding(
padding: const EdgeInsets.only(top: 8.0), padding: const EdgeInsets.only(top: 8.0),
child: Text( child: Text(
"backup_controller_page_none_selected".tr(), context.t.backup_controller_page_none_selected,
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor), style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
), ),
); );
@ -353,7 +351,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
} }
Widget buildExcludedAlbumName() { Widget buildExcludedAlbumName() {
String text = "backup_controller_page_excluded".tr(); String text = context.t.backup_controller_page_excluded;
final albums = ref final albums = ref
.read(backupAlbumProvider) .read(backupAlbumProvider)
.where((album) => album.backupSelection == BackupSelection.excluded) .where((album) => album.backupSelection == BackupSelection.excluded)
@ -385,16 +383,16 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
borderOnForeground: false, borderOnForeground: false,
child: ListTile( child: ListTile(
minVerticalPadding: 18, minVerticalPadding: 18,
title: Text("backup_controller_page_albums", style: context.textTheme.titleMedium).tr(), title: Text(context.t.backup_controller_page_albums, style: context.textTheme.titleMedium),
subtitle: Padding( subtitle: Padding(
padding: const EdgeInsets.only(top: 8.0), padding: const EdgeInsets.only(top: 8.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"backup_controller_page_to_backup", context.t.backup_controller_page_to_backup,
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
).tr(), ),
buildSelectedAlbumName(), buildSelectedAlbumName(),
buildExcludedAlbumName(), buildExcludedAlbumName(),
], ],
@ -413,7 +411,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
} }
unawaited(ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id)); unawaited(ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id));
}, },
child: const Text("select", style: TextStyle(fontWeight: FontWeight.bold)).tr(), child: Text(context.t.select, style: const TextStyle(fontWeight: FontWeight.bold)),
), ),
), ),
); );
@ -428,8 +426,8 @@ class _TotalCard extends ConsumerWidget {
final totalCount = ref.watch(driftBackupProvider.select((p) => p.totalCount)); final totalCount = ref.watch(driftBackupProvider.select((p) => p.totalCount));
return BackupInfoCard( return BackupInfoCard(
title: "total".tr(), title: context.t.total,
subtitle: "backup_controller_page_total_sub".tr(), subtitle: context.t.backup_controller_page_total_sub,
info: totalCount.toString(), info: totalCount.toString(),
); );
} }
@ -444,8 +442,8 @@ class _BackupCard extends ConsumerWidget {
final syncStatus = ref.watch(syncStatusProvider); final syncStatus = ref.watch(syncStatusProvider);
return BackupInfoCard( return BackupInfoCard(
title: "backup_controller_page_backup".tr(), title: context.t.backup_controller_page_backup,
subtitle: "backup_controller_page_backup_sub".tr(), subtitle: context.t.backup_controller_page_backup_sub,
info: backupCount.toString(), info: backupCount.toString(),
isLoading: syncStatus.isRemoteSyncing, isLoading: syncStatus.isRemoteSyncing,
); );
@ -472,11 +470,11 @@ class _RemainderCard extends ConsumerWidget {
ListTile( ListTile(
minVerticalPadding: 18, minVerticalPadding: 18,
isThreeLine: true, isThreeLine: true,
title: Text("backup_controller_page_remainder".t(context: context), style: context.textTheme.titleMedium), title: Text(context.t.backup_controller_page_remainder, style: context.textTheme.titleMedium),
subtitle: Padding( subtitle: Padding(
padding: const EdgeInsets.only(top: 4.0, right: 18.0), padding: const EdgeInsets.only(top: 4.0, right: 18.0),
child: Text( child: Text(
"backup_controller_page_remainder_sub".t(context: context), context.t.backup_controller_page_remainder_sub,
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
), ),
@ -509,11 +507,11 @@ class _RemainderCard extends ConsumerWidget {
], ],
), ),
Text( Text(
"backup_info_card_assets", context.t.backup_info_card_assets,
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(
color: context.colorScheme.onSurface.withAlpha(syncStatus.isRemoteSyncing ? 50 : 255), color: context.colorScheme.onSurface.withAlpha(syncStatus.isRemoteSyncing ? 50 : 255),
), ),
).tr(), ),
], ],
), ),
), ),
@ -530,7 +528,7 @@ class _RemainderCard extends ConsumerWidget {
), ),
onTap: () => context.pushRoute(const DriftBackupAssetDetailRoute()), onTap: () => context.pushRoute(const DriftBackupAssetDetailRoute()),
title: Text( title: Text(
"view_details".t(context: context), context.t.view_details,
style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)), style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)),
), ),
trailing: Icon(Icons.arrow_forward_ios, size: 16, color: context.colorScheme.onSurfaceVariant), trailing: Icon(Icons.arrow_forward_ios, size: 16, color: context.colorScheme.onSurfaceVariant),
@ -622,7 +620,7 @@ class _PreparingStatusState extends ConsumerState {
Row( Row(
children: [ children: [
Text( Text(
"preparing".t(context: context), context.t.preparing,
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(
color: context.colorScheme.onSurface.withAlpha(200), color: context.colorScheme.onSurface.withAlpha(200),
), ),
@ -652,7 +650,7 @@ class _PreparingStatusState extends ConsumerState {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Text( Text(
"ready_for_upload".t(context: context), context.t.ready_for_upload,
style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)), style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)),
), ),
const SizedBox(height: 2), const SizedBox(height: 2),

View file

@ -1,13 +1,12 @@
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/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart';
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; import 'package:immich_mobile/domain/services/sync_linked_album.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/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart';
import 'package:immich_mobile/providers/backup/backup_album.provider.dart'; import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
@ -154,13 +153,13 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
), ),
title: _isSearchMode title: _isSearchMode
? SearchField( ? SearchField(
hintText: 'search_albums'.t(context: context), hintText: context.t.search_albums,
autofocus: true, autofocus: true,
controller: _searchController, controller: _searchController,
focusNode: _searchFocusNode, focusNode: _searchFocusNode,
onChanged: (value) => setState(() => _searchQuery = value.trim()), onChanged: (value) => setState(() => _searchQuery = value.trim()),
) )
: const Text("backup_album_selection_page_select_albums").t(context: context), : Text(context.t.backup_album_selection_page_select_albums),
actions: [ actions: [
if (!_isSearchMode) if (!_isSearchMode)
IconButton( IconButton(
@ -194,9 +193,9 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: Text( child: Text(
"backup_album_selection_page_selection_info", context.t.backup_album_selection_page_selection_info,
style: context.textTheme.titleSmall, style: context.textTheme.titleSmall,
).t(context: context), ),
), ),
// Selected Album Chips // Selected Album Chips
@ -211,15 +210,15 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
), ),
ListTile( ListTile(
title: Text( title: Text(
"albums_on_device_count".t(context: context, args: {'count': albumCount.toString()}), context.t.albums_on_device_count(count: albumCount),
style: context.textTheme.titleSmall, style: context.textTheme.titleSmall,
), ),
subtitle: Padding( subtitle: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text( child: Text(
"backup_album_selection_page_albums_tap", context.t.backup_album_selection_page_albums_tap,
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor), style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
).t(context: context), ),
), ),
trailing: IconButton( trailing: IconButton(
splashRadius: 16, splashRadius: 16,
@ -235,20 +234,20 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
), ),
elevation: 5, elevation: 5,
title: Text( title: Text(
'backup_album_selection_page_selection_info', context.t.backup_album_selection_page_selection_info,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: context.primaryColor, color: context.primaryColor,
), ),
).t(context: context), ),
content: SingleChildScrollView( content: SingleChildScrollView(
child: ListBody( child: ListBody(
children: [ children: [
const Text( Text(
'backup_album_selection_page_assets_scatter', context.t.backup_album_selection_page_assets_scatter,
style: TextStyle(fontSize: 14), style: const TextStyle(fontSize: 14),
).t(context: context), ),
], ],
), ),
), ),
@ -268,16 +267,10 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
SliverToBoxAdapter( SliverToBoxAdapter(
child: Center( child: Center(
child: _searchQuery.isNotEmpty child: _searchQuery.isNotEmpty
? Padding( ? Padding(padding: const EdgeInsets.all(24.0), child: Text(context.t.album_search_not_found))
padding: const EdgeInsets.all(24.0),
child: Text('album_search_not_found'.t(context: context)),
)
: isLoading : isLoading
? const CircularProgressIndicator() ? const CircularProgressIndicator()
: Padding( : Padding(padding: const EdgeInsets.all(24.0), child: Text(context.t.no_albums_found)),
padding: const EdgeInsets.all(24.0),
child: Text('no_albums_found'.t(context: context)),
),
), ),
) )
else else
@ -309,7 +302,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: [ children: [
const CircularProgressIndicator(strokeWidth: 4), const CircularProgressIndicator(strokeWidth: 4),
Text('creating_linked_albums'.tr(), style: context.textTheme.labelLarge), Text(context.t.creating_linked_albums, style: context.textTheme.labelLarge),
], ],
), ),
), ),
@ -476,10 +469,7 @@ class _SelectAllButton extends ConsumerWidget {
} }
: null, : null,
icon: const Icon(Icons.select_all), icon: const Icon(Icons.select_all),
label: AnimatedSwitcher( label: AnimatedSwitcher(duration: const Duration(milliseconds: 200), child: Text(context.t.select_all)),
duration: const Duration(milliseconds: 200),
child: Text("select_all".t(context: context)),
),
style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12.0)), style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12.0)),
), ),
), ),
@ -496,7 +486,7 @@ class _SelectAllButton extends ConsumerWidget {
} }
: null, : null,
icon: const Icon(Icons.deselect), icon: const Icon(Icons.deselect),
label: Text('deselect_all'.t(context: context)), label: Text(context.t.deselect_all),
style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12.0)), style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12.0)),
), ),
), ),

View file

@ -1,5 +1,4 @@
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/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
@ -7,7 +6,7 @@ import 'package:immich_mobile/domain/models/events.model.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/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/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
@ -22,7 +21,7 @@ class DriftBackupAssetDetailPage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final AsyncValue<List<LocalAsset>> result = ref.watch(driftBackupCandidateProvider); final AsyncValue<List<LocalAsset>> result = ref.watch(driftBackupCandidateProvider);
return Scaffold( return Scaffold(
appBar: AppBar(title: Text('backup_controller_page_remainder'.t(context: context))), appBar: AppBar(title: Text(context.t.backup_controller_page_remainder)),
body: result.when( body: result.when(
data: (List<LocalAsset> candidates) { data: (List<LocalAsset> candidates) {
return ListView.separated( return ListView.separated(
@ -66,7 +65,7 @@ class DriftBackupAssetDetailPage extends ConsumerWidget {
); );
}, },
error: (error, stackTrace) => Text( error: (error, stackTrace) => Text(
'error_saving_image'.tr(args: [error.toString()]), context.t.error_saving_image(error: error.toString()),
style: TextStyle(color: context.colorScheme.error), style: TextStyle(color: context.colorScheme.error),
), ),
loading: () => loading: () =>
@ -102,7 +101,7 @@ class DriftBackupAssetDetailPage extends ConsumerWidget {
); );
}, },
error: (Object error, StackTrace stackTrace) { error: (Object error, StackTrace stackTrace) {
return Center(child: Text('error_saving_image'.tr(args: [error.toString()]))); return Center(child: Text(context.t.error_saving_image(error: error.toString())));
}, },
loading: () { loading: () {
return const SizedBox(height: 48, width: 48, child: Center(child: CircularProgressIndicator.adaptive())); return const SizedBox(height: 48, width: 48, child: Center(child: CircularProgressIndicator.adaptive()));

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/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/infrastructure/repositories/settings.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart';
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
@ -51,10 +51,7 @@ class DriftBackupOptionsPage extends ConsumerWidget {
} }
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(content: Text(context.t.network_requirements_updated), duration: const Duration(seconds: 4)),
content: Text("network_requirements_updated".t(context: context)),
duration: const Duration(seconds: 4),
),
); );
final backupNotifier = ref.read(driftBackupProvider.notifier); final backupNotifier = ref.read(driftBackupProvider.notifier);
@ -72,7 +69,7 @@ class DriftBackupOptionsPage extends ConsumerWidget {
} }
}, },
child: Scaffold( child: Scaffold(
appBar: AppBar(title: Text("backup_options".t(context: context))), appBar: AppBar(title: Text(context.t.backup_options)),
body: const DriftBackupSettings(), body: const DriftBackupSettings(),
), ),
); );

View file

@ -3,7 +3,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/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
@ -80,7 +80,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text("upload_details".t(context: context)), title: Text(context.t.upload_details),
backgroundColor: context.colorScheme.surface, backgroundColor: context.colorScheme.surface,
elevation: 0, elevation: 0,
scrolledUnderElevation: 1, scrolledUnderElevation: 1,
@ -125,7 +125,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
SliverToBoxAdapter( SliverToBoxAdapter(
child: _buildSectionHeader( child: _buildSectionHeader(
context, context,
title: "uploading".t(context: context), title: context.t.uploading,
count: uploadingItems.length, count: uploadingItems.length,
color: context.colorScheme.primary, color: context.colorScheme.primary,
), ),
@ -151,7 +151,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
SliverToBoxAdapter( SliverToBoxAdapter(
child: _buildSectionHeader( child: _buildSectionHeader(
context, context,
title: "errors_text".t(context: context), title: context.t.errors_text,
count: failedItems.length, count: failedItems.length,
color: context.colorScheme.error, color: context.colorScheme.error,
), ),
@ -231,7 +231,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"downloading_from_icloud".t(context: context), context.t.downloading_from_icloud,
style: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500), style: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -318,7 +318,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
const SizedBox(height: 2), const SizedBox(height: 2),
Text( Text(
isFailed isFailed
? item.error ?? "unable_to_upload_file".t(context: context) ? item.error ?? context.t.errors.unable_to_upload_file
: "${formatHumanReadableBytes(item.fileSize, 1)}${item.networkSpeedAsString}", : "${formatHumanReadableBytes(item.fileSize, 1)}${item.networkSpeedAsString}",
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(
color: isFailed color: isFailed
@ -395,7 +395,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
item.error ?? "unable_to_upload_file".t(context: context), item.error ?? context.t.errors.unable_to_upload_file,
style: context.textTheme.bodySmall?.copyWith(color: context.colorScheme.error), style: context.textTheme.bodySmall?.copyWith(color: context.colorScheme.error),
maxLines: 4, maxLines: 4,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -556,7 +556,7 @@ class FileDetailDialog extends ConsumerWidget {
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( Expanded(
child: Text( child: Text(
"details".t(context: context), context.t.details,
style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor), style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor),
), ),
), ),
@ -595,20 +595,14 @@ class FileDetailDialog extends ConsumerWidget {
const SizedBox(height: 24), const SizedBox(height: 24),
if (asset != null) if (asset != null)
_buildInfoSection(context, [ _buildInfoSection(context, [
_buildInfoRow(context, "filename".t(context: context), path.basename(uploadStatus.filename)), _buildInfoRow(context, context.t.filename, path.basename(uploadStatus.filename)),
_buildInfoRow(context, "local_id".t(context: context), asset.id), _buildInfoRow(context, context.t.local_id, asset.id),
_buildInfoRow( _buildInfoRow(context, context.t.file_size, formatHumanReadableBytes(uploadStatus.fileSize, 2)),
context, if (asset.width != null) _buildInfoRow(context, context.t.width, "${asset.width}px"),
"file_size".t(context: context), if (asset.height != null) _buildInfoRow(context, context.t.height, "${asset.height}px"),
formatHumanReadableBytes(uploadStatus.fileSize, 2), _buildInfoRow(context, context.t.created_at, asset.createdAt.toString()),
), _buildInfoRow(context, context.t.updated_at, asset.updatedAt.toString()),
if (asset.width != null) _buildInfoRow(context, "width".t(context: context), "${asset.width}px"), if (asset.checksum != null) _buildInfoRow(context, context.t.checksum, asset.checksum!),
if (asset.height != null)
_buildInfoRow(context, "height".t(context: context), "${asset.height}px"),
_buildInfoRow(context, "created_at".t(context: context), asset.createdAt.toString()),
_buildInfoRow(context, "updated_at".t(context: context), asset.updatedAt.toString()),
if (asset.checksum != null)
_buildInfoRow(context, "checksum".t(context: context), asset.checksum!),
]), ]),
], ],
), ),
@ -620,7 +614,7 @@ class FileDetailDialog extends ConsumerWidget {
TextButton( TextButton(
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
child: Text( child: Text(
"close".t(), context.t.close,
style: TextStyle(fontWeight: FontWeight.w600, color: context.primaryColor), style: TextStyle(fontWeight: FontWeight.w600, color: context.primaryColor),
), ),
), ),

View file

@ -1,5 +1,4 @@
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' hide Store; import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
@ -18,21 +17,45 @@ import 'package:immich_mobile/widgets/settings/preference_settings/preference_se
import 'package:immich_mobile/widgets/settings/settings_card.dart'; import 'package:immich_mobile/widgets/settings/settings_card.dart';
enum SettingSection { enum SettingSection {
advanced('advanced', Icons.build_outlined, "advanced_settings_tile_subtitle"), advanced(Icons.build_outlined),
assetViewer('asset_viewer_settings_title', Icons.image_outlined, "asset_viewer_settings_subtitle"), assetViewer(Icons.image_outlined),
backup('backup', Icons.cloud_upload_outlined, "backup_settings_subtitle"), backup(Icons.cloud_upload_outlined),
freeUpSpace('free_up_space', Icons.cleaning_services_outlined, "free_up_space_settings_subtitle"), freeUpSpace(Icons.cleaning_services_outlined),
languages('language', Icons.language, "setting_languages_subtitle"), languages(Icons.language),
networking('networking_settings', Icons.wifi, "networking_subtitle"), networking(Icons.wifi),
notifications('notifications', Icons.notifications_none_rounded, "setting_notifications_subtitle"), notifications(Icons.notifications_none_rounded),
preferences('preferences_settings_title', Icons.interests_outlined, "preferences_settings_subtitle"), preferences(Icons.interests_outlined),
timeline('asset_list_settings_title', Icons.auto_awesome_mosaic_outlined, "asset_list_settings_subtitle"), timeline(Icons.auto_awesome_mosaic_outlined),
beta('sync_status', Icons.sync_outlined, "sync_status_subtitle"); beta(Icons.sync_outlined);
final String title;
final String subtitle;
final IconData icon; final IconData icon;
String title(Translations t) => switch (this) {
SettingSection.advanced => t.advanced,
SettingSection.assetViewer => t.asset_viewer_settings_title,
SettingSection.backup => t.backup,
SettingSection.freeUpSpace => t.free_up_space,
SettingSection.languages => t.language,
SettingSection.networking => t.networking_settings,
SettingSection.notifications => t.notifications,
SettingSection.preferences => t.preferences_settings_title,
SettingSection.timeline => t.asset_list_settings_title,
SettingSection.beta => t.sync_status,
};
String subtitle(Translations t) => switch (this) {
SettingSection.advanced => t.advanced_settings_tile_subtitle,
SettingSection.assetViewer => t.asset_viewer_settings_subtitle,
SettingSection.backup => t.backup_settings_subtitle,
SettingSection.freeUpSpace => t.free_up_space_settings_subtitle,
SettingSection.languages => t.setting_languages_subtitle,
SettingSection.networking => t.networking_subtitle,
SettingSection.notifications => t.setting_notifications_subtitle,
SettingSection.preferences => t.preferences_settings_subtitle,
SettingSection.timeline => t.asset_list_settings_subtitle,
SettingSection.beta => t.sync_status_subtitle,
};
Widget get widget => switch (this) { Widget get widget => switch (this) {
SettingSection.advanced => const AdvancedSettings(), SettingSection.advanced => const AdvancedSettings(),
SettingSection.assetViewer => const AssetViewerSettings(), SettingSection.assetViewer => const AssetViewerSettings(),
@ -46,7 +69,7 @@ enum SettingSection {
SettingSection.beta => const SyncStatusAndActions(), SettingSection.beta => const SyncStatusAndActions(),
}; };
const SettingSection(this.title, this.icon, this.subtitle); const SettingSection(this.icon);
} }
@RoutePage() @RoutePage()
@ -55,9 +78,8 @@ class SettingsPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
context.locale;
return Scaffold( return Scaffold(
appBar: AppBar(centerTitle: false, title: const Text('settings').tr()), appBar: AppBar(centerTitle: false, title: Text(context.t.settings)),
body: context.isMobile ? const _MobileLayout() : const _TabletLayout(), body: context.isMobile ? const _MobileLayout() : const _TabletLayout(),
); );
} }
@ -73,15 +95,15 @@ class _MobileLayout extends StatelessWidget {
? [ ? [
SettingsCard( SettingsCard(
icon: Icons.sync_outlined, icon: Icons.sync_outlined,
title: 'sync_status'.tr(), title: context.t.sync_status,
subtitle: 'sync_status_subtitle'.tr(), subtitle: context.t.sync_status_subtitle,
settingRoute: const SyncStatusRoute(), settingRoute: const SyncStatusRoute(),
), ),
] ]
: [ : [
SettingsCard( SettingsCard(
title: setting.title.tr(), title: setting.title(context.t),
subtitle: setting.subtitle.tr(), subtitle: setting.subtitle(context.t),
icon: setting.icon, icon: setting.icon,
settingRoute: SettingsSubRoute(section: setting), settingRoute: SettingsSubRoute(section: setting),
), ),
@ -116,7 +138,7 @@ class _TabletLayout extends HookWidget {
...SettingSection.values.map( ...SettingSection.values.map(
(s) => SliverToBoxAdapter( (s) => SliverToBoxAdapter(
child: ListTile( child: ListTile(
title: Text(s.title).tr(), title: Text(s.title(context.t)),
leading: Icon(s.icon), leading: Icon(s.icon),
selected: s.index == selectedSection.value.index, selected: s.index == selectedSection.value.index,
selectedColor: context.primaryColor, selectedColor: context.primaryColor,
@ -127,7 +149,7 @@ class _TabletLayout extends HookWidget {
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: ListTile( child: ListTile(
title: Text('whats_new'.tr()), title: Text(context.t.whats_new),
leading: const Icon(Icons.auto_awesome_outlined), leading: const Icon(Icons.auto_awesome_outlined),
onTap: () => context.pushRoute(const WhatsNewRoute()), onTap: () => context.pushRoute(const WhatsNewRoute()),
), ),
@ -150,9 +172,8 @@ class SettingsSubPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
context.locale;
return Scaffold( return Scaffold(
appBar: AppBar(centerTitle: false, title: Text(section.title).tr()), appBar: AppBar(centerTitle: false, title: Text(section.title(context.t))),
body: section.widget, body: section.widget,
); );
} }

View file

@ -2,12 +2,12 @@ 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:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.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/maplibrecontroller_extensions.dart'; import 'package:immich_mobile/extensions/maplibrecontroller_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/utils/map_utils.dart'; import 'package:immich_mobile/utils/map_utils.dart';
import 'package:immich_mobile/widgets/map/map_theme_override.dart'; import 'package:immich_mobile/widgets/map/map_theme_override.dart';
import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:maplibre_gl/maplibre_gl.dart';
@ -148,10 +148,7 @@ class _BottomBar extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
ElevatedButton( ElevatedButton(onPressed: onUseLocation, child: Text(context.t.map_location_picker_page_use_location)),
onPressed: onUseLocation,
child: const Text("map_location_picker_page_use_location").tr(),
),
ElevatedButton(onPressed: onGetCurrentLocation, child: const Icon(Icons.my_location)), ElevatedButton(onPressed: onGetCurrentLocation, child: const Icon(Icons.my_location)),
], ],
), ),

View file

@ -1,6 +1,6 @@
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:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/widgets/settings/beta_sync_settings/sync_status_and_actions.dart'; import 'package:immich_mobile/widgets/settings/beta_sync_settings/sync_status_and_actions.dart';
@RoutePage() @RoutePage()
@ -12,7 +12,7 @@ class SyncStatusPage extends StatelessWidget {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
elevation: 0, elevation: 0,
title: const Text("sync_status").t(context: context), title: Text(context.t.sync_status),
leading: IconButton( leading: IconButton(
onPressed: () => context.maybePop(true), onPressed: () => context.maybePop(true),
splashRadius: 24, splashRadius: 24,

View file

@ -1,7 +1,7 @@
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/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
@ -135,7 +135,7 @@ class BackupToggleButtonState extends ConsumerState<BackupToggleButton> with Sin
children: [ children: [
Flexible( Flexible(
child: Text( child: Text(
"enable_backup".t(context: context), context.t.enable_backup,
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: context.primaryColor, color: context.primaryColor,
@ -148,7 +148,7 @@ class BackupToggleButtonState extends ConsumerState<BackupToggleButton> with Sin
Padding( Padding(
padding: const EdgeInsets.only(top: 2), padding: const EdgeInsets.only(top: 2),
child: Text( child: Text(
"upload_error_with_count".t(context: context, args: {'count': '$errorCount'}), context.t.upload_error_with_count(count: errorCount),
style: context.textTheme.labelMedium?.copyWith(color: context.colorScheme.error), style: context.textTheme.labelMedium?.copyWith(color: context.colorScheme.error),
), ),
), ),

View file

@ -10,7 +10,7 @@ import 'package:immich_mobile/domain/models/events.model.dart';
import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/domain/utils/event_stream.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/bottom_sheet/base_bottom_sheet.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/map/map.state.dart'; import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
@ -164,7 +164,7 @@ class _DriftMapState extends ConsumerState<DriftMap> {
context: context, context: context,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
toastType: ToastType.error, toastType: ToastType.error,
msg: "map_cannot_get_user_location".t(context: context), msg: context.t.map_cannot_get_user_location,
); );
} }
return; return;

View file

@ -1,7 +1,6 @@
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/time_range.model.dart'; import 'package:immich_mobile/domain/models/time_range.model.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/map/map.state.dart'; import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
import 'package:immich_mobile/widgets/map/map_settings/map_custom_time_range.dart'; import 'package:immich_mobile/widgets/map/map_settings/map_custom_time_range.dart';
@ -50,18 +49,18 @@ class _DriftMapSettingsSheetState extends ConsumerState<DriftMapSettingsSheet> {
), ),
const Divider(height: 30, thickness: 1), const Divider(height: 30, thickness: 1),
MapSettingsListTile( MapSettingsListTile(
title: "map_settings_only_show_favorites".t(context: context), title: context.t.map_settings_only_show_favorites,
selected: mapState.onlyFavorites, selected: mapState.onlyFavorites,
onChanged: (favoriteOnly) => ref.read(mapStateProvider.notifier).switchFavoriteOnly(favoriteOnly), onChanged: (favoriteOnly) => ref.read(mapStateProvider.notifier).switchFavoriteOnly(favoriteOnly),
), ),
MapSettingsListTile( MapSettingsListTile(
title: "map_settings_include_show_archived".t(context: context), title: context.t.map_settings_include_show_archived,
selected: mapState.includeArchived, selected: mapState.includeArchived,
onChanged: (includeArchive) => onChanged: (includeArchive) =>
ref.read(mapStateProvider.notifier).switchIncludeArchived(includeArchive), ref.read(mapStateProvider.notifier).switchIncludeArchived(includeArchive),
), ),
MapSettingsListTile( MapSettingsListTile(
title: "map_settings_include_show_partners".t(context: context), title: context.t.map_settings_include_show_partners,
selected: mapState.withPartners, selected: mapState.withPartners,
onChanged: (withPartners) => ref.read(mapStateProvider.notifier).switchWithPartners(withPartners), onChanged: (withPartners) => ref.read(mapStateProvider.notifier).switchWithPartners(withPartners),
), ),

View file

@ -2,7 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart'; import 'package:geolocator/geolocator.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/widgets/common/confirm_dialog.dart'; import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:maplibre_gl/maplibre_gl.dart';
@ -124,10 +124,10 @@ class MapUtils {
class _LocationServiceDisabledDialog extends ConfirmDialog { class _LocationServiceDisabledDialog extends ConfirmDialog {
_LocationServiceDisabledDialog(BuildContext context) _LocationServiceDisabledDialog(BuildContext context)
: super( : super(
title: 'map_location_service_disabled_title'.t(context: context), title: context.t.map_location_service_disabled_title,
content: 'map_location_service_disabled_content'.t(context: context), content: context.t.map_location_service_disabled_content,
cancel: 'cancel'.t(context: context), cancel: context.t.cancel,
ok: 'yes'.t(context: context), ok: context.t.yes,
onOk: () async { onOk: () async {
await Geolocator.openLocationSettings(); await Geolocator.openLocationSettings();
}, },
@ -137,10 +137,10 @@ class _LocationServiceDisabledDialog extends ConfirmDialog {
class _LocationPermissionDisabledDialog extends ConfirmDialog { class _LocationPermissionDisabledDialog extends ConfirmDialog {
_LocationPermissionDisabledDialog(BuildContext context) _LocationPermissionDisabledDialog(BuildContext context)
: super( : super(
title: 'map_no_location_permission_title'.t(context: context), title: context.t.map_no_location_permission_title,
content: 'map_no_location_permission_content'.t(context: context), content: context.t.map_no_location_permission_content,
cancel: 'cancel'.t(context: context), cancel: context.t.cancel,
ok: 'yes'.t(context: context), ok: context.t.yes,
onOk: () {}, onOk: () {},
); );
} }

View file

@ -1,8 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart'; import 'package:geolocator/geolocator.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/models/map/map_marker.model.dart'; import 'package:immich_mobile/models/map/map_marker.model.dart';
import 'package:immich_mobile/widgets/common/confirm_dialog.dart'; import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
@ -121,10 +121,10 @@ class MapUtils {
class _LocationServiceDisabledDialog extends ConfirmDialog { class _LocationServiceDisabledDialog extends ConfirmDialog {
_LocationServiceDisabledDialog() _LocationServiceDisabledDialog()
: super( : super(
title: 'map_location_service_disabled_title'.tr(), title: StaticTranslations.instance.map_location_service_disabled_title,
content: 'map_location_service_disabled_content'.tr(), content: StaticTranslations.instance.map_location_service_disabled_content,
cancel: 'cancel'.tr(), cancel: StaticTranslations.instance.cancel,
ok: 'yes'.tr(), ok: StaticTranslations.instance.yes,
onOk: () async { onOk: () async {
await Geolocator.openLocationSettings(); await Geolocator.openLocationSettings();
}, },
@ -134,10 +134,10 @@ class _LocationServiceDisabledDialog extends ConfirmDialog {
class _LocationPermissionDisabledDialog extends ConfirmDialog { class _LocationPermissionDisabledDialog extends ConfirmDialog {
_LocationPermissionDisabledDialog() _LocationPermissionDisabledDialog()
: super( : super(
title: 'map_no_location_permission_title'.tr(), title: StaticTranslations.instance.map_no_location_permission_title,
content: 'map_no_location_permission_content'.tr(), content: StaticTranslations.instance.map_no_location_permission_content,
cancel: 'cancel'.tr(), cancel: StaticTranslations.instance.cancel,
ok: 'yes'.tr(), ok: StaticTranslations.instance.yes,
onOk: () {}, onOk: () {},
); );
} }

View file

@ -1,8 +1,7 @@
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/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';
class BackupInfoCard extends StatelessWidget { class BackupInfoCard extends StatelessWidget {
final String title; final String title;
@ -73,11 +72,11 @@ class BackupInfoCard extends StatelessWidget {
], ],
), ),
Text( Text(
"backup_info_card_assets", context.t.backup_info_card_assets,
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(
color: context.colorScheme.onSurface.withAlpha(isLoading ? 50 : 255), color: context.colorScheme.onSurface.withAlpha(isLoading ? 50 : 255),
), ),
).tr(), ),
], ],
), ),
), ),
@ -93,7 +92,7 @@ class BackupInfoCard extends StatelessWidget {
), ),
onTap: onTap, onTap: onTap,
title: Text( title: Text(
"view_details".t(context: context), context.t.view_details,
style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)), style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)),
), ),
trailing: Icon(Icons.arrow_forward_ios, size: 16, color: context.colorScheme.onSurfaceVariant), trailing: Icon(Icons.arrow_forward_ios, size: 16, color: context.colorScheme.onSurfaceVariant),

View file

@ -1,7 +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/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
class MapTimeDropDown extends StatelessWidget { class MapTimeDropDown extends StatelessWidget {
final int relativeTime; final int relativeTime;
@ -20,7 +19,7 @@ class MapTimeDropDown extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
"date_range".t(context: context), context.t.date_range,
style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5), style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5),
), ),
Flexible( Flexible(
@ -30,24 +29,21 @@ class MapTimeDropDown extends StatelessWidget {
initialSelection: relativeTime, initialSelection: relativeTime,
onSelected: (value) => onTimeChange(value!), onSelected: (value) => onTimeChange(value!),
dropdownMenuEntries: [ dropdownMenuEntries: [
DropdownMenuEntry(value: 0, label: "all".t(context: context)), DropdownMenuEntry(value: 0, label: context.t.all),
DropdownMenuEntry(value: 1, label: "map_settings_date_range_option_day".t(context: context)), DropdownMenuEntry(value: 1, label: context.t.map_settings_date_range_option_day),
DropdownMenuEntry(value: 7, label: "map_settings_date_range_option_days".tr(namedArgs: {'days': "7"})), DropdownMenuEntry(value: 7, label: context.t.map_settings_date_range_option_days(days: 7)),
DropdownMenuEntry( DropdownMenuEntry(value: 30, label: context.t.map_settings_date_range_option_days(days: 30)),
value: 30,
label: "map_settings_date_range_option_days".tr(namedArgs: {'days': "30"}),
),
DropdownMenuEntry( DropdownMenuEntry(
value: now value: now
.difference(DateTime(now.year - 1, now.month, now.day, now.hour, now.minute, now.second)) .difference(DateTime(now.year - 1, now.month, now.day, now.hour, now.minute, now.second))
.inDays, .inDays,
label: "map_settings_date_range_option_year".t(context: context), label: context.t.map_settings_date_range_option_year,
), ),
DropdownMenuEntry( DropdownMenuEntry(
value: now value: now
.difference(DateTime(now.year - 3, now.month, now.day, now.hour, now.minute, now.second)) .difference(DateTime(now.year - 3, now.month, now.day, now.hour, now.minute, now.second))
.inDays, .inDays,
label: "map_settings_date_range_option_years".t(args: {'years': "3"}), label: context.t.map_settings_date_range_option_years(years: 3),
), ),
], ],
), ),

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/widgets/map/map_thumbnail.dart'; import 'package:immich_mobile/widgets/map/map_thumbnail.dart';
import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:maplibre_gl/maplibre_gl.dart';
@ -18,7 +18,7 @@ class MapThemePicker extends StatelessWidget {
padding: const EdgeInsets.only(bottom: 20), padding: const EdgeInsets.only(bottom: 20),
child: Center( child: Center(
child: Text( child: Text(
"map_settings_theme_settings".t(context: context), context.t.map_settings_theme_settings,
style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5), style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5),
), ),
), ),

View file

@ -2,12 +2,12 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.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' hide Store; import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/services/log.service.dart'; import 'package:immich_mobile/domain/services/log.service.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/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart'; import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
@ -71,8 +71,8 @@ class AdvancedSettings extends HookConsumerWidget {
SettingsSwitchListTile( SettingsSwitchListTile(
enabled: true, enabled: true,
valueNotifier: advancedTroubleshooting, valueNotifier: advancedTroubleshooting,
title: "advanced_settings_troubleshooting_title".tr(), title: context.t.advanced_settings_troubleshooting_title,
subtitle: "advanced_settings_troubleshooting_subtitle".tr(), subtitle: context.t.advanced_settings_troubleshooting_subtitle,
), ),
if (isManageMediaSupported.value) if (isManageMediaSupported.value)
Column( Column(
@ -80,8 +80,8 @@ class AdvancedSettings extends HookConsumerWidget {
SettingsSwitchListTile( SettingsSwitchListTile(
enabled: true, enabled: true,
valueNotifier: manageLocalMediaAndroid, valueNotifier: manageLocalMediaAndroid,
title: "advanced_settings_sync_remote_deletions_title".tr(), title: context.t.advanced_settings_sync_remote_deletions_title,
subtitle: "advanced_settings_sync_remote_deletions_subtitle".tr(), subtitle: context.t.advanced_settings_sync_remote_deletions_subtitle,
onChanged: (value) async { onChanged: (value) async {
if (value) { if (value) {
final result = await ref.read(permissionRepositoryProvider).requestManageMediaPermission(); final result = await ref.read(permissionRepositoryProvider).requestManageMediaPermission();
@ -91,9 +91,9 @@ class AdvancedSettings extends HookConsumerWidget {
}, },
), ),
SettingsActionTile( SettingsActionTile(
title: "manage_media_access_title".tr(), title: context.t.manage_media_access_title,
statusText: manageMediaAndroidPermission.value ? "allowed".tr() : "not_allowed".tr(), statusText: manageMediaAndroidPermission.value ? context.t.allowed : context.t.not_allowed,
subtitle: "manage_media_access_rationale".tr(), subtitle: context.t.manage_media_access_rationale,
statusColor: manageLocalMediaAndroid.value && !manageMediaAndroidPermission.value statusColor: manageLocalMediaAndroid.value && !manageMediaAndroidPermission.value
? const Color.fromARGB(255, 243, 188, 106) ? const Color.fromARGB(255, 243, 188, 106)
: null, : null,
@ -105,7 +105,7 @@ class AdvancedSettings extends HookConsumerWidget {
], ],
), ),
SettingsSliderListTile( SettingsSliderListTile(
text: "advanced_settings_log_level_title".tr(namedArgs: {'level': logLevel}), text: context.t.advanced_settings_log_level_title(level: logLevel),
valueNotifier: levelId, valueNotifier: levelId,
maxValue: 8, maxValue: 8,
minValue: 1, minValue: 1,
@ -114,15 +114,15 @@ class AdvancedSettings extends HookConsumerWidget {
), ),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: preferRemote, valueNotifier: preferRemote,
title: "advanced_settings_prefer_remote_title".tr(), title: context.t.advanced_settings_prefer_remote_title,
subtitle: "advanced_settings_prefer_remote_subtitle".tr(), subtitle: context.t.advanced_settings_prefer_remote_subtitle,
), ),
const CustomProxyHeaderSettings(), const CustomProxyHeaderSettings(),
const SslClientCertSettings(), const SslClientCertSettings(),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: readonlyModeEnabled, valueNotifier: readonlyModeEnabled,
title: "advanced_settings_readonly_mode_title".tr(), title: context.t.advanced_settings_readonly_mode_title,
subtitle: "advanced_settings_readonly_mode_subtitle".tr(), subtitle: context.t.advanced_settings_readonly_mode_subtitle,
onChanged: (value) { onChanged: (value) {
readonlyModeEnabled.value = value; readonlyModeEnabled.value = value;
ref.read(readonlyModeProvider.notifier).setReadonlyMode(value); ref.read(readonlyModeProvider.notifier).setReadonlyMode(value);
@ -130,7 +130,7 @@ class AdvancedSettings extends HookConsumerWidget {
SnackBar( SnackBar(
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
content: Text( content: Text(
(value ? "readonly_mode_enabled" : "readonly_mode_disabled").tr(), value ? context.t.readonly_mode_enabled : context.t.readonly_mode_disabled,
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
), ),
), ),
@ -138,7 +138,7 @@ class AdvancedSettings extends HookConsumerWidget {
}, },
), ),
ListTile( ListTile(
title: Text("advanced_settings_clear_image_cache".tr(), style: const TextStyle(fontWeight: FontWeight.w500)), title: Text(context.t.advanced_settings_clear_image_cache, style: const TextStyle(fontWeight: FontWeight.w500)),
leading: const Icon(Icons.playlist_remove_rounded), leading: const Icon(Icons.playlist_remove_rounded),
onTap: () async { onTap: () async {
final int clearedBytes; final int clearedBytes;
@ -153,7 +153,7 @@ class AdvancedSettings extends HookConsumerWidget {
SnackBar( SnackBar(
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
content: Text( content: Text(
"advanced_settings_clear_image_cache_error".tr(), context.t.advanced_settings_clear_image_cache_error,
style: context.textTheme.bodyLarge?.copyWith(color: context.themeData.colorScheme.error), style: context.textTheme.bodyLarge?.copyWith(color: context.themeData.colorScheme.error),
), ),
), ),
@ -171,7 +171,7 @@ class AdvancedSettings extends HookConsumerWidget {
SnackBar( SnackBar(
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
content: Text( content: Text(
"advanced_settings_clear_image_cache_success".tr(namedArgs: {'size': clearedMB}), context.t.advanced_settings_clear_image_cache_success(size: clearedMB),
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
), ),
), ),

View file

@ -4,7 +4,7 @@ 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/timeline.model.dart'; import 'package:immich_mobile/domain/models/timeline.model.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
@ -34,20 +34,14 @@ class GroupSettings extends HookConsumerWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SettingGroupTitle( SettingGroupTitle(title: context.t.asset_list_group_by_sub_title, icon: Icons.group_work_outlined),
title: "asset_list_group_by_sub_title".t(context: context),
icon: Icons.group_work_outlined,
),
SettingsRadioListTile( SettingsRadioListTile(
groups: [ groups: [
SettingsRadioGroup( SettingsRadioGroup(
title: 'asset_list_layout_settings_group_by_month_day'.t(context: context), title: context.t.asset_list_layout_settings_group_by_month_day,
value: GroupAssetsBy.day, value: GroupAssetsBy.day,
), ),
SettingsRadioGroup( SettingsRadioGroup(title: context.t.month, value: GroupAssetsBy.month),
title: 'month'.t(context: context),
value: GroupAssetsBy.month,
),
], ],
groupBy: groupBy.value, groupBy: groupBy.value,
onRadioChanged: changeGroupValue, onRadioChanged: changeGroupValue,

View file

@ -1,10 +1,9 @@
import 'dart:async'; import 'dart:async';
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/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; import 'package:immich_mobile/widgets/settings/setting_group_title.dart';
@ -23,13 +22,10 @@ class LayoutSettings extends HookConsumerWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SettingGroupTitle( SettingGroupTitle(title: context.t.asset_list_layout_sub_title, icon: Icons.view_module_outlined),
title: "asset_list_layout_sub_title".t(context: context),
icon: Icons.view_module_outlined,
),
SettingsSliderListTile( SettingsSliderListTile(
valueNotifier: tilesPerRow, valueNotifier: tilesPerRow,
text: 'theme_setting_asset_list_tiles_per_row_title'.tr(namedArgs: {'count': "${tilesPerRow.value}"}), text: context.t.theme_setting_asset_list_tiles_per_row_title(count: tilesPerRow.value),
label: "${tilesPerRow.value}", label: "${tilesPerRow.value}",
maxValue: 6, maxValue: 6,
minValue: 2, minValue: 2,

View file

@ -1,9 +1,9 @@
import 'dart:async'; import 'dart:async';
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/generated/translations.g.dart';
import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/widgets/settings/asset_list_settings/asset_list_group_settings.dart'; import 'package:immich_mobile/widgets/settings/asset_list_settings/asset_list_group_settings.dart';
@ -21,7 +21,7 @@ class AssetListSettings extends HookConsumerWidget {
final assetListSetting = [ final assetListSetting = [
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: storageIndicator, valueNotifier: storageIndicator,
title: 'theme_setting_asset_list_storage_indicator_title'.tr(), title: context.t.theme_setting_asset_list_storage_indicator_title,
onChanged: (value) { onChanged: (value) {
unawaited(ref.read(settingsProvider).write(.timelineStorageIndicator, value)); unawaited(ref.read(settingsProvider).write(.timelineStorageIndicator, value));
ref.invalidate(appSettingsServiceProvider); ref.invalidate(appSettingsServiceProvider);

View file

@ -8,7 +8,6 @@ import 'package:immich_mobile/domain/models/settings_key.dart';
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; import 'package:immich_mobile/domain/services/sync_linked_album.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/platform_extensions.dart'; import 'package:immich_mobile/extensions/platform_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/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart';
import 'package:immich_mobile/providers/backup/backup_album.provider.dart'; import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
@ -26,26 +25,17 @@ class DriftBackupSettings extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SettingsSubPageScaffold( return SettingsSubPageScaffold(
settings: [ settings: [
SettingGroupTitle( SettingGroupTitle(title: context.t.network_requirements, icon: Icons.cell_tower),
title: "network_requirements".t(context: context),
icon: Icons.cell_tower,
),
const _UseCellularForVideosButton(), const _UseCellularForVideosButton(),
const _UseCellularForPhotosButton(), const _UseCellularForPhotosButton(),
if (CurrentPlatform.isAndroid) ...[ if (CurrentPlatform.isAndroid) ...[
const Divider(), const Divider(),
SettingGroupTitle( SettingGroupTitle(title: context.t.background_options, icon: Icons.charging_station_rounded),
title: "background_options".t(context: context),
icon: Icons.charging_station_rounded,
),
const _BackupOnlyWhenChargingButton(), const _BackupOnlyWhenChargingButton(),
const _BackupDelaySlider(), const _BackupDelaySlider(),
], ],
const Divider(), const Divider(),
SettingGroupTitle( SettingGroupTitle(title: context.t.backup_albums_sync, icon: Icons.sync),
title: "backup_albums_sync".t(context: context),
icon: Icons.sync,
),
const _AlbumSyncActionButton(), const _AlbumSyncActionButton(),
], ],
); );
@ -108,8 +98,8 @@ class _AlbumSyncActionButtonState extends ConsumerState<_AlbumSyncActionButton>
Column( Column(
children: [ children: [
SettingListTile( SettingListTile(
title: "sync_albums".t(context: context), title: context.t.sync_albums,
subtitle: "sync_upload_album_setting_subtitle".t(context: context), subtitle: context.t.sync_upload_album_setting_subtitle,
trailing: Switch( trailing: Switch(
value: albumSyncEnable, value: albumSyncEnable,
onChanged: (bool newValue) async { onChanged: (bool newValue) async {
@ -131,8 +121,8 @@ class _AlbumSyncActionButtonState extends ConsumerState<_AlbumSyncActionButton>
? SettingListTile( ? SettingListTile(
onTap: _manualSyncAlbums, onTap: _manualSyncAlbums,
contentPadding: const EdgeInsets.only(left: 32, right: 16), contentPadding: const EdgeInsets.only(left: 32, right: 16),
title: "organize_into_albums".t(context: context), title: context.t.organize_into_albums,
subtitle: "organize_into_albums_description".t(context: context), subtitle: context.t.organize_into_albums_description,
trailing: isAlbumSyncInProgress trailing: isAlbumSyncInProgress
? const SizedBox( ? const SizedBox(
width: 32, width: 32,
@ -161,15 +151,15 @@ class _AlbumSyncActionButtonState extends ConsumerState<_AlbumSyncActionButton>
class _BackupSwitchTile extends ConsumerWidget { class _BackupSwitchTile extends ConsumerWidget {
final SettingsKey<bool> metadataKey; final SettingsKey<bool> metadataKey;
final bool Function(AppConfig) selector; final bool Function(AppConfig) selector;
final String titleKey; final String title;
final String subtitleKey; final String subtitle;
final void Function(bool)? onChanged; final void Function(bool)? onChanged;
const _BackupSwitchTile({ const _BackupSwitchTile({
required this.metadataKey, required this.metadataKey,
required this.selector, required this.selector,
required this.titleKey, required this.title,
required this.subtitleKey, required this.subtitle,
this.onChanged, this.onChanged,
}); });
@ -179,8 +169,8 @@ class _BackupSwitchTile extends ConsumerWidget {
return Padding( return Padding(
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: SettingListTile( child: SettingListTile(
title: titleKey.t(context: context), title: title,
subtitle: subtitleKey.t(context: context), subtitle: subtitle,
trailing: Switch( trailing: Switch(
value: value, value: value,
onChanged: (bool newValue) async { onChanged: (bool newValue) async {
@ -201,8 +191,8 @@ class _UseCellularForVideosButton extends StatelessWidget {
return _BackupSwitchTile( return _BackupSwitchTile(
metadataKey: SettingsKey.backupUseCellularForVideos, metadataKey: SettingsKey.backupUseCellularForVideos,
selector: (c) => c.backup.useCellularForVideos, selector: (c) => c.backup.useCellularForVideos,
titleKey: "videos", title: context.t.videos,
subtitleKey: "network_requirement_videos_upload", subtitle: context.t.network_requirement_videos_upload,
); );
} }
} }
@ -215,8 +205,8 @@ class _UseCellularForPhotosButton extends StatelessWidget {
return _BackupSwitchTile( return _BackupSwitchTile(
metadataKey: SettingsKey.backupUseCellularForPhotos, metadataKey: SettingsKey.backupUseCellularForPhotos,
selector: (c) => c.backup.useCellularForPhotos, selector: (c) => c.backup.useCellularForPhotos,
titleKey: "photos", title: context.t.photos,
subtitleKey: "network_requirement_photos_upload", subtitle: context.t.network_requirement_photos_upload,
); );
} }
} }
@ -230,8 +220,8 @@ class _BackupOnlyWhenChargingButton extends ConsumerWidget {
return _BackupSwitchTile( return _BackupSwitchTile(
metadataKey: SettingsKey.backupRequireCharging, metadataKey: SettingsKey.backupRequireCharging,
selector: (c) => c.backup.requireCharging, selector: (c) => c.backup.requireCharging,
titleKey: "charging", title: context.t.charging,
subtitleKey: "charging_requirement_mobile_backup", subtitle: context.t.charging_requirement_mobile_backup,
onChanged: (value) { onChanged: (value) {
unawaited(fgService.configure(requireCharging: value)); unawaited(fgService.configure(requireCharging: value));
}, },

View file

@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:immich_mobile/constants/locales.dart'; import 'package:immich_mobile/constants/locales.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/services/localization.service.dart'; import 'package:immich_mobile/services/localization.service.dart';
import 'package:immich_mobile/widgets/common/search_field.dart'; import 'package:immich_mobile/widgets/common/search_field.dart';
@ -152,7 +152,7 @@ class _LanguageSearchBar extends StatelessWidget {
child: SearchField( child: SearchField(
autofocus: false, autofocus: false,
contentPadding: const EdgeInsets.all(12), contentPadding: const EdgeInsets.all(12),
hintText: 'language_search_hint'.t(context: context), hintText: context.t.language_search_hint,
prefixIcon: const Icon(Icons.search_rounded), prefixIcon: const Icon(Icons.search_rounded),
suffixIcon: controller.text.isNotEmpty suffixIcon: controller.text.isNotEmpty
? IconButton(icon: const Icon(Icons.clear_rounded), onPressed: onClear) ? IconButton(icon: const Icon(Icons.clear_rounded), onPressed: onClear)
@ -179,12 +179,12 @@ class _LanguageNotFound extends StatelessWidget {
Icon(Icons.search_off_rounded, size: 64, color: context.colorScheme.onSurface.withValues(alpha: 0.4)), Icon(Icons.search_off_rounded, size: 64, color: context.colorScheme.onSurface.withValues(alpha: 0.4)),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'language_no_results_title'.t(context: context), context.t.language_no_results_title,
style: context.textTheme.titleMedium?.copyWith(color: context.colorScheme.onSurface), style: context.textTheme.titleMedium?.copyWith(color: context.colorScheme.onSurface),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
'language_no_results_subtitle'.t(context: context), context.t.language_no_results_subtitle,
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurface.withValues(alpha: 0.8)), style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurface.withValues(alpha: 0.8)),
), ),
], ],
@ -214,7 +214,7 @@ class _LanguageApplyButton extends StatelessWidget {
child: isLoading child: isLoading
? const SizedBox.square(dimension: 24, child: CircularProgressIndicator(strokeWidth: 2)) ? const SizedBox.square(dimension: 24, child: CircularProgressIndicator(strokeWidth: 2))
: Text( : Text(
'setting_languages_apply'.t(context: context), context.t.setting_languages_apply,
style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16.0), style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16.0),
), ),
), ),

View file

@ -1,9 +1,9 @@
import 'dart:async'; import 'dart:async';
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/permission.provider.dart'; import 'package:immich_mobile/providers/permission.provider.dart';
import 'package:immich_mobile/widgets/settings/settings_button_list_tile.dart'; import 'package:immich_mobile/widgets/settings/settings_button_list_tile.dart';
import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart'; import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart';
@ -29,10 +29,10 @@ class NotificationSetting extends HookConsumerWidget {
showDialog( showDialog(
context: context, context: context,
builder: (ctx) => AlertDialog( builder: (ctx) => AlertDialog(
content: const Text('notification_permission_dialog_content').tr(), content: Text(ctx.t.notification_permission_dialog_content),
actions: [ actions: [
TextButton(child: const Text('cancel').tr(), onPressed: () => ctx.pop()), TextButton(child: Text(ctx.t.cancel), onPressed: () => ctx.pop()),
TextButton(onPressed: () => openAppNotificationSettings(ctx), child: const Text('settings').tr()), TextButton(onPressed: () => openAppNotificationSettings(ctx), child: Text(ctx.t.settings)),
], ],
), ),
), ),
@ -43,9 +43,9 @@ class NotificationSetting extends HookConsumerWidget {
if (!hasPermission) if (!hasPermission)
SettingsButtonListTile( SettingsButtonListTile(
icon: Icons.notifications_outlined, icon: Icons.notifications_outlined,
title: 'notification_permission_list_tile_title'.tr(), title: context.t.notification_permission_list_tile_title,
subtileText: 'notification_permission_list_tile_content'.tr(), subtileText: context.t.notification_permission_list_tile_content,
buttonText: 'notification_permission_list_tile_enable_button'.tr(), buttonText: context.t.notification_permission_list_tile_enable_button,
onButtonTap: () => onButtonTap: () =>
ref.read(notificationPermissionProvider.notifier).requestNotificationPermission().then((permission) { ref.read(notificationPermissionProvider.notifier).requestNotificationPermission().then((permission) {
if (permission == PermissionStatus.permanentlyDenied) { if (permission == PermissionStatus.permanentlyDenied) {
@ -56,9 +56,9 @@ class NotificationSetting extends HookConsumerWidget {
else else
SettingsButtonListTile( SettingsButtonListTile(
icon: Icons.notifications_active_outlined, icon: Icons.notifications_active_outlined,
title: 'notification_enabled_list_tile_title'.tr(), title: context.t.notification_enabled_list_tile_title,
subtileText: 'notification_enabled_list_tile_content'.tr(), subtileText: context.t.notification_enabled_list_tile_content,
buttonText: 'notification_enabled_list_tile_open_button'.tr(), buttonText: context.t.notification_enabled_list_tile_open_button,
onButtonTap: () => openAppSettings(), onButtonTap: () => openAppSettings(),
), ),
]; ];

View file

@ -1,6 +1,6 @@
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:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/services/app_settings.service.dart';
import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart';
import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; import 'package:immich_mobile/widgets/settings/setting_group_title.dart';
@ -21,13 +21,10 @@ class HapticSetting extends HookWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SettingGroupTitle( SettingGroupTitle(title: context.t.haptic_feedback_title, icon: Icons.vibration_outlined),
title: "haptic_feedback_title".t(context: context),
icon: Icons.vibration_outlined,
),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: isHapticFeedbackEnabled, valueNotifier: isHapticFeedbackEnabled,
title: 'enabled'.t(context: context), title: context.t.enabled,
onChanged: onHapticFeedbackChange, onChanged: onHapticFeedbackChange,
), ),
], ],

View file

@ -1,11 +1,11 @@
import 'dart:async'; import 'dart:async';
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/colors.dart'; import 'package:immich_mobile/constants/colors.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/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/providers/theme.provider.dart'; import 'package:immich_mobile/providers/theme.provider.dart';
import 'package:immich_mobile/theme/color_scheme.dart'; import 'package:immich_mobile/theme/color_scheme.dart';
@ -97,7 +97,7 @@ class PrimaryColorSetting extends HookConsumerWidget {
children: [ children: [
Align( Align(
alignment: Alignment.center, alignment: Alignment.center,
child: Text("theme_setting_primary_color_title".tr(), style: context.textTheme.titleLarge), child: Text(context.t.theme_setting_primary_color_title, style: context.textTheme.titleLarge),
), ),
if (DynamicTheme.isAvailable) if (DynamicTheme.isAvailable)
Container( Container(
@ -110,7 +110,7 @@ class PrimaryColorSetting extends HookConsumerWidget {
tileColor: context.colorScheme.surfaceContainerHigh, tileColor: context.colorScheme.surfaceContainerHigh,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15))),
title: Text( title: Text(
'theme_setting_system_primary_color_title'.tr(), context.t.theme_setting_system_primary_color_title,
style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500, height: 1.5), style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500, height: 1.5),
), ),
value: themeConfig.dynamicTheme, value: themeConfig.dynamicTheme,
@ -157,11 +157,11 @@ class PrimaryColorSetting extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"theme_setting_primary_color_title".tr(), context.t.theme_setting_primary_color_title,
style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500), style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500),
), ),
Text( Text(
"theme_setting_primary_color_subtitle".tr(), context.t.theme_setting_primary_color_subtitle,
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
], ],

View file

@ -4,7 +4,7 @@ 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/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/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/widgets/settings/preference_settings/primary_color_setting.dart'; import 'package:immich_mobile/widgets/settings/preference_settings/primary_color_setting.dart';
import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; import 'package:immich_mobile/widgets/settings/setting_group_title.dart';
@ -52,26 +52,23 @@ class ThemeSetting extends HookConsumerWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SettingGroupTitle( SettingGroupTitle(title: context.t.theme, icon: Icons.color_lens_outlined),
title: "theme".t(context: context),
icon: Icons.color_lens_outlined,
),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: isSystemTheme, valueNotifier: isSystemTheme,
title: 'theme_setting_system_theme_switch'.t(context: context), title: context.t.theme_setting_system_theme_switch,
onChanged: onSystemThemeChange, onChanged: onSystemThemeChange,
), ),
if (currentTheme.value != ThemeMode.system) if (currentTheme.value != ThemeMode.system)
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: isDarkTheme, valueNotifier: isDarkTheme,
title: 'map_settings_dark_mode'.t(context: context), title: context.t.map_settings_dark_mode,
onChanged: onThemeChange, onChanged: onThemeChange,
), ),
const PrimaryColorSetting(), const PrimaryColorSetting(),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: colorfulInterface, valueNotifier: colorfulInterface,
title: "theme_setting_colorful_interface_title".t(context: context), title: context.t.theme_setting_colorful_interface_title,
subtitle: 'theme_setting_colorful_interface_subtitle'.t(context: context), subtitle: context.t.theme_setting_colorful_interface_subtitle,
onChanged: onSurfaceColorSettingChange, onChanged: onSurfaceColorSettingChange,
), ),
], ],