chore: migrate mobile translations accessor (2) (#30668)

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 565fbe4917
commit 835c35e940
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 304 additions and 401 deletions

View file

@ -8,7 +8,7 @@ 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/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/memory.model.dart'; import 'package:immich_mobile/domain/models/memory.model.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/memory/memory_bottom_info.widget.dart'; import 'package:immich_mobile/presentation/widgets/memory/memory_bottom_info.widget.dart';
import 'package:immich_mobile/presentation/widgets/memory/memory_card.widget.dart'; import 'package:immich_mobile/presentation/widgets/memory/memory_card.widget.dart';
@ -248,7 +248,7 @@ class DriftMemoryPage extends HookConsumerWidget {
} }
final yearsAgo = DateTime.now().year - memories[mIndex].data.year; final yearsAgo = DateTime.now().year - memories[mIndex].data.year;
final title = 'years_ago'.t(context: context, args: {'years': yearsAgo.toString()}); final title = context.t.years_ago(years: yearsAgo);
// Build horizontal page // Build horizontal page
final assetController = memoryAssetPageControllers[mIndex]; final assetController = memoryAssetPageControllers[mIndex];
return Column( return Column(

View file

@ -1,13 +1,12 @@
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/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/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/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/lock.action.dart'; import 'package:immich_mobile/presentation/actions/lock.action.dart';
@ -52,11 +51,11 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
return [ return [
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text("add_to_bottom_bar".tr(), style: context.textTheme.labelMedium), child: Text(context.t.add_to_bottom_bar, style: context.textTheme.labelMedium),
), ),
BaseActionButton( BaseActionButton(
iconData: Icons.photo_album_outlined, iconData: Icons.photo_album_outlined,
label: "album".tr(), label: context.t.album,
menuItem: true, menuItem: true,
onPressed: () => _handleMenuSelection(AddToMenuItem.album), onPressed: () => _handleMenuSelection(AddToMenuItem.album),
), ),
@ -65,7 +64,7 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
const Divider(), const Divider(),
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text("move_to".tr(), style: context.textTheme.labelMedium), child: Text(context.t.move_to, style: context.textTheme.labelMedium),
), ),
const ActionMenuItem(action: ArchiveAction(source: .viewer)), const ActionMenuItem(action: ArchiveAction(source: .viewer)),
const ActionMenuItem(action: LockAction(source: .viewer)), const ActionMenuItem(action: LockAction(source: .viewer)),
@ -120,7 +119,7 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
} }
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;
} }
@ -128,7 +127,7 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
if (result.count > 0) { if (result.count > 0) {
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),
); );
// Refresh the "Appears in" list on the asset's info panel. // Refresh the "Appears in" list on the asset's info panel.
@ -136,13 +135,13 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
} else if (result.failedCount > 0) { } else if (result.failedCount > 0) {
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: 'assets_cannot_be_added_to_album_count'.t(context: context, args: {'count': result.failedCount}), msg: context.t.assets_cannot_be_added_to_album_count(count: result.failedCount),
toastType: ToastType.error, toastType: ToastType.error,
); );
} else { } else {
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name}), msg: context.t.add_to_album_bottom_sheet_already_exists(album: album.name),
); );
} }
@ -183,7 +182,7 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
builder: (context, controller, child) { builder: (context, controller, child) {
return BaseActionButton( return BaseActionButton(
iconData: Icons.add, iconData: Icons.add,
label: "add_to_bottom_bar".tr(), label: context.t.add_to_bottom_bar,
onPressed: () => controller.isOpen ? controller.close() : controller.open(), onPressed: () => controller.isOpen ? controller.close() : controller.open(),
); );
}, },

View file

@ -1,9 +1,8 @@
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: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/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/models/activities/activity.model.dart'; import 'package:immich_mobile/models/activities/activity.model.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/providers/activity.provider.dart'; import 'package:immich_mobile/providers/activity.provider.dart';
@ -48,7 +47,7 @@ class LikeActivityActionButton extends ConsumerWidget {
return BaseActionButton( return BaseActionButton(
maxWidth: 60, maxWidth: 60,
iconData: liked != null ? Icons.thumb_up : Icons.thumb_up_off_alt, iconData: liked != null ? Icons.thumb_up : Icons.thumb_up_off_alt,
label: "like".t(context: context), label: context.t.like,
onPressed: () => onTap(liked), onPressed: () => onTap(liked),
iconOnly: iconOnly, iconOnly: iconOnly,
menuItem: menuItem, menuItem: menuItem,
@ -58,11 +57,11 @@ class LikeActivityActionButton extends ConsumerWidget {
// default to empty heart during loading // default to empty heart during loading
loading: () => BaseActionButton( loading: () => BaseActionButton(
iconData: Icons.thumb_up_off_alt, iconData: Icons.thumb_up_off_alt,
label: "like".t(context: context), label: context.t.like,
iconOnly: iconOnly, iconOnly: iconOnly,
menuItem: menuItem, menuItem: menuItem,
), ),
error: (error, stack) => Text('error_saving_image'.tr(args: [error.toString()])), error: (error, stack) => Text(context.t.error_saving_image(error: error.toString())),
); );
} }
} }

View file

@ -1,6 +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/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';
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
@ -16,7 +16,7 @@ class MotionPhotoActionButton extends ConsumerWidget {
return BaseActionButton( return BaseActionButton(
iconData: isPlaying ? Icons.motion_photos_pause_outlined : Icons.play_circle_outline_rounded, iconData: isPlaying ? Icons.motion_photos_pause_outlined : Icons.play_circle_outline_rounded,
label: "play_motion_photo".t(context: context), label: context.t.play_motion_photo,
onPressed: ref.watch(isPlayingMotionVideoProvider.notifier).toggle, onPressed: ref.watch(isPlayingMotionVideoProvider.notifier).toggle,
iconOnly: iconOnly, iconOnly: iconOnly,
menuItem: menuItem, menuItem: menuItem,

View file

@ -7,7 +7,7 @@ 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/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/widgets/album/album_tile.dart'; import 'package:immich_mobile/presentation/widgets/album/album_tile.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
@ -52,7 +52,7 @@ class AppearsInDetails extends ConsumerWidget {
spacing: 12, spacing: 12,
children: [ children: [
SheetTile( SheetTile(
title: 'appears_in'.t(context: context), title: context.t.appears_in,
titleStyle: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary), titleStyle: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
Padding( Padding(

View file

@ -8,7 +8,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/exif.model.dart'; import 'package:immich_mobile/domain/models/exif.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/duration_extensions.dart'; import 'package:immich_mobile/extensions/duration_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/actions/edit_datetime.action.dart'; import 'package:immich_mobile/presentation/actions/edit_datetime.action.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart';
import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
@ -100,7 +100,7 @@ class _SheetAssetDescriptionState extends ConsumerState<_SheetAssetDescription>
ImmichToast.show( ImmichToast.show(
context: context, context: context,
msg: 'exif_bottom_sheet_description_error'.t(context: context), msg: context.t.exif_bottom_sheet_description_error,
toastType: ToastType.error, toastType: ToastType.error,
); );
} }
@ -111,9 +111,9 @@ class _SheetAssetDescriptionState extends ConsumerState<_SheetAssetDescription>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final currentDescription = widget.exif.description ?? ''; final currentDescription = widget.exif.description ?? '';
final hintText = (widget.isEditable ? 'exif_bottom_sheet_description' : 'exif_bottom_sheet_no_description').t( final hintText = widget.isEditable
context: context, ? context.t.exif_bottom_sheet_description
); : context.t.exif_bottom_sheet_no_description;
if (_controller.text != currentDescription && !_descriptionFocus.hasFocus) { if (_controller.text != currentDescription && !_descriptionFocus.hasFocus) {
_controller.text = currentDescription; _controller.text = currentDescription;
} }

View file

@ -6,7 +6,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/exif.model.dart'; import 'package:immich_mobile/domain/models/exif.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/actions/edit_location.action.dart'; import 'package:immich_mobile/presentation/actions/edit_location.action.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart';
import 'package:immich_mobile/widgets/asset_viewer/detail_panel/exif_map.dart'; import 'package:immich_mobile/widgets/asset_viewer/detail_panel/exif_map.dart';
@ -75,7 +75,7 @@ class _LocationDetailsState extends ConsumerState<LocationDetails> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SheetTile( SheetTile(
title: 'location'.t(context: context), title: context.t.location,
titleStyle: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary), titleStyle: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary),
trailing: hasCoordinates && editLocation != null ? const Icon(Icons.edit_location_alt, size: 20) : null, trailing: hasCoordinates && editLocation != null ? const Icon(Icons.edit_location_alt, size: 20) : null,
onTap: editLocation?.onAction, onTap: editLocation?.onAction,
@ -107,7 +107,7 @@ class _LocationDetailsState extends ConsumerState<LocationDetails> {
), ),
if (!hasCoordinates) if (!hasCoordinates)
SheetTile( SheetTile(
title: "add_a_location".t(context: context), title: context.t.add_a_location,
titleStyle: context.textTheme.bodyMedium?.copyWith( titleStyle: context.textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: context.primaryColor, color: context.primaryColor,

View file

@ -7,7 +7,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.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/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/widgets/images/remote_image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart';
import 'package:immich_mobile/presentation/widgets/people/person_edit_name_modal.widget.dart'; import 'package:immich_mobile/presentation/widgets/people/person_edit_name_modal.widget.dart';
import 'package:immich_mobile/providers/infrastructure/people.provider.dart'; import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
@ -52,7 +52,7 @@ class PeopleDetails extends ConsumerWidget {
Padding( Padding(
padding: const EdgeInsets.only(left: 16, top: 16, bottom: 16), padding: const EdgeInsets.only(left: 16, top: 16, bottom: 16),
child: Text( child: Text(
"people".t(context: context), context.t.people,
style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
), ),
@ -89,7 +89,7 @@ class PeopleDetails extends ConsumerWidget {
duration: Durations.short4, duration: Durations.short4,
); );
}, },
error: (error, stack) => Text("error_loading_people".t(context: context), style: context.textTheme.bodyMedium), error: (error, stack) => Text(context.t.errors.failed_to_load_people, style: context.textTheme.bodyMedium),
loading: () => const SizedBox.shrink(), loading: () => const SizedBox.shrink(),
); );
} }
@ -135,7 +135,7 @@ class _Avatar extends StatelessWidget {
GestureDetector( GestureDetector(
onTap: () => onNameTap?.call(), onTap: () => onNameTap?.call(),
child: Text( child: Text(
"add_a_name".t(context: context), context.t.add_a_name,
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor), style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,

View file

@ -4,7 +4,7 @@ import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/exif.model.dart'; import 'package:immich_mobile/domain/models/exif.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/widgets/asset_viewer/rating_bar.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/rating_bar.widget.dart';
import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart'; import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart';
@ -32,7 +32,7 @@ class RatingDetails extends ConsumerWidget {
spacing: 8, spacing: 8,
children: [ children: [
Text( Text(
'rating'.t(context: context), context.t.rating,
style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
RatingBar( RatingBar(

View file

@ -4,7 +4,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/exif.model.dart'; import 'package:immich_mobile/domain/models/exif.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/widgets/asset_viewer/sheet_tile.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart';
import 'package:immich_mobile/repositories/asset_media.repository.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart';
import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:immich_mobile/utils/bytes_units.dart';
@ -27,7 +27,7 @@ class TechnicalDetails extends ConsumerWidget {
return Column( return Column(
children: [ children: [
SheetTile( SheetTile(
title: 'details'.t(context: context), title: context.t.details,
titleStyle: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary), titleStyle: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
_buildFileInfoTile(context, ref, asset, exifInfo), _buildFileInfoTile(context, ref, asset, exifInfo),

View file

@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:math' as math; import 'dart:math' as 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/services.dart'; import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@ -14,6 +13,7 @@ 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/platform_extensions.dart'; import 'package:immich_mobile/extensions/platform_extensions.dart';
import 'package:immich_mobile/extensions/scroll_extensions.dart'; import 'package:immich_mobile/extensions/scroll_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/download_status_floating_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/download_status_floating_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_page.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_page.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_preloader.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_preloader.dart';
@ -210,7 +210,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
SnackBar( SnackBar(
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
content: Text( content: Text(
"local_asset_cast_failed".tr(), context.t.local_asset_cast_failed,
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
), ),
), ),

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/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/providers/asset_viewer/asset_viewer.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
@ -66,7 +66,7 @@ class _MotionButton extends StatelessWidget {
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
CurrentPlatform.isAndroid ? 'motion'.t(context: context) : 'live'.t(context: context), CurrentPlatform.isAndroid ? context.t.motion : context.t.live,
style: const TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500), style: const TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500),
), ),
], ],

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 RatingBar extends StatefulWidget { class RatingBar extends StatefulWidget {
final double initialRating; final double initialRating;
@ -129,10 +129,7 @@ class _RatingBarState extends State<RatingBar> {
}); });
widget.onClearRating?.call(); widget.onClearRating?.call();
}, },
child: Text( child: Text(context.t.rating_clear, style: TextStyle(color: context.themeData.colorScheme.primary)),
'rating_clear'.t(context: context),
style: TextStyle(color: context.themeData.colorScheme.primary),
),
), ),
), ),
], ],

View file

@ -3,7 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.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/haptic_feedback.provider.dart'; import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart';
@ -29,11 +29,7 @@ class SheetTile extends ConsumerWidget {
void copyTitle(BuildContext context, WidgetRef ref) { void copyTitle(BuildContext context, WidgetRef ref) {
unawaited(Clipboard.setData(ClipboardData(text: title))); unawaited(Clipboard.setData(ClipboardData(text: title)));
ImmichToast.show( ImmichToast.show(context: context, msg: context.t.copied_to_clipboard, toastType: ToastType.info);
context: context,
msg: 'copied_to_clipboard'.t(context: context),
toastType: ToastType.info,
);
ref.read(hapticFeedbackProvider.notifier).selectionClick(); ref.read(hapticFeedbackProvider.notifier).selectionClick();
} }

View file

@ -1,12 +1,13 @@
// ignore_for_file: require_trailing_commas // ignore_for_file: require_trailing_commas
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:immich_mobile/domain/models/events.model.dart'; import 'package:immich_mobile/domain/models/events.model.dart';
import 'package:immich_mobile/domain/models/memory.model.dart'; import 'package:immich_mobile/domain/models/memory.model.dart';
import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/domain/utils/event_stream.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:intl/intl.dart';
class DriftMemoryBottomInfo extends StatelessWidget { class DriftMemoryBottomInfo extends StatelessWidget {
final DriftMemory memory; final DriftMemory memory;
@ -36,7 +37,7 @@ class DriftMemoryBottomInfo extends StatelessWidget {
], ],
), ),
Tooltip( Tooltip(
message: 'view_in_timeline'.tr(), message: context.t.view_in_timeline,
child: MaterialButton( child: MaterialButton(
minWidth: 0, minWidth: 0,
onPressed: () async { onPressed: () async {

View file

@ -4,7 +4,7 @@ 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/domain/models/memory.model.dart'; import 'package:immich_mobile/domain/models/memory.model.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/pages/drift_memory.page.dart'; import 'package:immich_mobile/presentation/pages/drift_memory.page.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/haptic_feedback.provider.dart'; import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
@ -53,7 +53,7 @@ class DriftMemoryCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final yearsAgo = DateTime.now().year - memory.data.year; final yearsAgo = DateTime.now().year - memory.data.year;
final title = 'years_ago'.t(context: context, args: {'years': yearsAgo.toString()}); final title = context.t.years_ago(years: yearsAgo);
return Center( return Center(
child: Stack( child: Stack(
children: [ children: [

View file

@ -1,69 +1,69 @@
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 DeleteLocalOnlyDialog extends StatelessWidget { class DeleteLocalOnlyDialog extends StatelessWidget {
final void Function(bool onlyMerged) onDeleteLocal; final void Function(bool onlyMerged) onDeleteLocal;
const DeleteLocalOnlyDialog({super.key, required this.onDeleteLocal}); const DeleteLocalOnlyDialog({super.key, required this.onDeleteLocal});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
void onDeleteBackedUpOnly() { void onDeleteBackedUpOnly() {
context.pop(true); context.pop(true);
onDeleteLocal(true); onDeleteLocal(true);
} }
void onForceDelete() { void onForceDelete() {
context.pop(false); context.pop(false);
onDeleteLocal(false); onDeleteLocal(false);
} }
return AlertDialog( return AlertDialog(
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
title: const Text("delete_dialog_title").tr(), title: Text(context.t.delete_dialog_title),
content: const Text("delete_dialog_alert_local_non_backed_up").tr(), content: Text(context.t.delete_dialog_alert_local_non_backed_up),
actions: [ actions: [
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
height: 48, height: 48,
child: FilledButton( child: FilledButton(
onPressed: () => context.pop(), onPressed: () => context.pop(),
style: FilledButton.styleFrom( style: FilledButton.styleFrom(
backgroundColor: context.colorScheme.surfaceDim, backgroundColor: context.colorScheme.surfaceDim,
foregroundColor: context.primaryColor, foregroundColor: context.primaryColor,
), ),
child: const Text("cancel", style: TextStyle(fontWeight: FontWeight.bold)).tr(), child: Text(context.t.cancel, style: const TextStyle(fontWeight: FontWeight.bold)),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
height: 48, height: 48,
child: FilledButton( child: FilledButton(
onPressed: onDeleteBackedUpOnly, onPressed: onDeleteBackedUpOnly,
style: FilledButton.styleFrom( style: FilledButton.styleFrom(
backgroundColor: context.colorScheme.errorContainer, backgroundColor: context.colorScheme.errorContainer,
foregroundColor: context.colorScheme.onErrorContainer, foregroundColor: context.colorScheme.onErrorContainer,
), ),
child: const Text( child: Text(
"delete_local_dialog_ok_backed_up_only", context.t.delete_local_dialog_ok_backed_up_only,
style: TextStyle(fontWeight: FontWeight.bold), style: const TextStyle(fontWeight: FontWeight.bold),
).tr(), ),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
height: 48, height: 48,
child: FilledButton( child: FilledButton(
onPressed: onForceDelete, onPressed: onForceDelete,
style: FilledButton.styleFrom(backgroundColor: Colors.red[400], foregroundColor: Colors.white), style: FilledButton.styleFrom(backgroundColor: Colors.red[400], foregroundColor: Colors.white),
child: const Text("delete_local_dialog_ok_force", style: TextStyle(fontWeight: FontWeight.bold)).tr(), child: Text(context.t.delete_local_dialog_ok_force, style: const TextStyle(fontWeight: FontWeight.bold)),
), ),
), ),
], ],
); );
} }
} }

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/models/cast/cast_manager_state.dart'; import 'package:immich_mobile/models/cast/cast_manager_state.dart';
import 'package:immich_mobile/providers/cast.provider.dart'; import 'package:immich_mobile/providers/cast.provider.dart';
@ -23,7 +23,7 @@ class CastDialog extends ConsumerWidget {
} }
return AlertDialog( return AlertDialog(
title: const Text("cast", style: TextStyle(fontWeight: FontWeight.bold)).tr(), title: Text(context.t.cast, style: const TextStyle(fontWeight: FontWeight.bold)),
content: SizedBox( content: SizedBox(
width: 250, width: 250,
height: 250, height: 250,
@ -31,13 +31,13 @@ class CastDialog extends ConsumerWidget {
future: ref.watch(castProvider.notifier).getDevices(), future: ref.watch(castProvider.notifier).getDevices(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return Text('error_saving_image'.tr(args: [snapshot.error.toString()])); return Text(context.t.error_saving_image(error: snapshot.error.toString()));
} else if (!snapshot.hasData) { } else if (!snapshot.hasData) {
return const SizedBox(height: 48, child: Center(child: CircularProgressIndicator())); return const SizedBox(height: 48, child: Center(child: CircularProgressIndicator()));
} }
if (snapshot.data!.isEmpty) { if (snapshot.data!.isEmpty) {
return const Text('no_cast_devices_found').tr(); return Text(context.t.no_cast_devices_found);
} }
final devices = snapshot.data!; final devices = snapshot.data!;
@ -47,12 +47,12 @@ class CastDialog extends ConsumerWidget {
final List<dynamic> sectionedList = []; final List<dynamic> sectionedList = [];
if (connected.isNotEmpty) { if (connected.isNotEmpty) {
sectionedList.add("connected_device"); sectionedList.add(context.t.connected_device);
sectionedList.addAll(connected); sectionedList.addAll(connected);
} }
if (others.isNotEmpty) { if (others.isNotEmpty) {
sectionedList.add("discovered_devices"); sectionedList.add(context.t.discovered_devices);
sectionedList.addAll(others); sectionedList.addAll(others);
} }
@ -66,7 +66,7 @@ class CastDialog extends ConsumerWidget {
// It's a section header // It's a section header
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(item, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16)).tr(), child: Text(item, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16)),
); );
} else { } else {
final (deviceName, type, deviceObj) = item as (String, CastDestinationType, dynamic); final (deviceName, type, deviceObj) = item as (String, CastDestinationType, dynamic);
@ -110,16 +110,16 @@ class CastDialog extends ConsumerWidget {
TextButton( TextButton(
onPressed: () => ref.read(castProvider.notifier).disconnect(), onPressed: () => ref.read(castProvider.notifier).disconnect(),
child: Text( child: Text(
"stop_casting", context.t.stop_casting,
style: TextStyle(color: context.colorScheme.secondary, fontWeight: FontWeight.bold), style: TextStyle(color: context.colorScheme.secondary, fontWeight: FontWeight.bold),
).tr(), ),
), ),
TextButton( TextButton(
onPressed: () => context.pop(), onPressed: () => context.pop(),
child: Text( child: Text(
"close", context.t.close,
style: TextStyle(color: context.colorScheme.primary, fontWeight: FontWeight.bold), style: TextStyle(color: context.colorScheme.primary, fontWeight: FontWeight.bold),
).tr(), ),
), ),
], ],
); );

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 MemoryEpilogue extends StatefulWidget { class MemoryEpilogue extends StatefulWidget {
final Function()? onStartOver; final Function()? onStartOver;
@ -45,23 +45,23 @@ class _MemoryEpilogueState extends State<MemoryEpilogue> with TickerProviderStat
), ),
const SizedBox(height: 16.0), const SizedBox(height: 16.0),
Text( Text(
"memories_all_caught_up", context.t.memories_all_caught_up,
style: context.textTheme.headlineMedium?.copyWith(color: Colors.white), style: context.textTheme.headlineMedium?.copyWith(color: Colors.white),
).tr(), ),
const SizedBox(height: 16.0), const SizedBox(height: 16.0),
Text( Text(
"memories_check_back_tomorrow", context.t.memories_check_back_tomorrow,
style: context.textTheme.bodyMedium?.copyWith(color: Colors.white), style: context.textTheme.bodyMedium?.copyWith(color: Colors.white),
).tr(), ),
const SizedBox(height: 16.0), const SizedBox(height: 16.0),
TextButton( TextButton(
onPressed: widget.onStartOver, onPressed: widget.onStartOver,
child: Text( child: Text(
"memories_start_over", context.t.memories_start_over,
style: context.textTheme.displayMedium?.copyWith( style: context.textTheme.displayMedium?.copyWith(
color: context.isDarkTheme ? context.colorScheme.primary : context.colorScheme.inversePrimary, color: context.isDarkTheme ? context.colorScheme.primary : context.colorScheme.inversePrimary,
), ),
).tr(), ),
), ),
], ],
), ),
@ -85,9 +85,9 @@ class _MemoryEpilogueState extends State<MemoryEpilogue> with TickerProviderStat
), ),
), ),
Text( Text(
"memories_swipe_to_close", context.t.memories_swipe_to_close,
style: context.textTheme.bodyMedium?.copyWith(color: Colors.white), style: context.textTheme.bodyMedium?.copyWith(color: Colors.white),
).tr(), ),
], ],
), ),
), ),

View file

@ -3,7 +3,7 @@ import 'dart:async';
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,14 +23,14 @@ class ImageViewerQualitySetting extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SettingGroupTitle( SettingGroupTitle(
title: "photos".t(context: context), title: context.t.photos,
icon: Icons.image_outlined, icon: Icons.image_outlined,
subtitle: "setting_image_viewer_help".t(context: context), subtitle: context.t.setting_image_viewer_help,
), ),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: isOriginal, valueNotifier: isOriginal,
title: "setting_image_viewer_original_title".t(context: context), title: context.t.setting_image_viewer_original_title,
subtitle: "setting_image_viewer_original_subtitle".t(context: context), subtitle: context.t.setting_image_viewer_original_subtitle,
onChanged: (_) => ref.invalidate(appSettingsServiceProvider), onChanged: (_) => ref.invalidate(appSettingsServiceProvider),
), ),
], ],

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/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/widgets/settings/settings_sub_title.dart'; import 'package:immich_mobile/widgets/settings/settings_sub_title.dart';
import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart';
@ -21,11 +21,11 @@ class ImageViewerTapToNavigateSetting extends HookConsumerWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SettingsSubTitle(title: "setting_image_navigation_title".tr()), SettingsSubTitle(title: context.t.setting_image_navigation_title),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: tapToNavigate, valueNotifier: tapToNavigate,
title: "setting_image_navigation_enable_title".tr(), title: context.t.setting_image_navigation_enable_title,
subtitle: "setting_image_navigation_enable_subtitle".tr(), subtitle: context.t.setting_image_navigation_enable_subtitle,
), ),
], ],
); );

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/constants/enums.dart'; import 'package:immich_mobile/constants/enums.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/setting_group_title.dart'; import 'package:immich_mobile/widgets/settings/setting_group_title.dart';
import 'package:immich_mobile/widgets/settings/settings_radio_list_tile.dart'; import 'package:immich_mobile/widgets/settings/settings_radio_list_tile.dart';
@ -39,40 +39,28 @@ class SlideshowSettings extends HookConsumerWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SettingGroupTitle( SettingGroupTitle(title: context.t.slideshow, icon: Icons.slideshow_outlined),
title: 'slideshow'.t(context: context),
icon: Icons.slideshow_outlined,
),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: useRepeat, valueNotifier: useRepeat,
title: "slideshow_repeat".t(context: context), title: context.t.slideshow_repeat,
subtitle: "slideshow_repeat_description".t(context: context), subtitle: context.t.slideshow_repeat_description,
), ),
SettingsSliderListTile( SettingsSliderListTile(
valueNotifier: useDuration, valueNotifier: useDuration,
text: "duration".t(context: context), text: context.t.duration,
minValue: 5, minValue: 5,
noDivisons: 5, noDivisons: 5,
maxValue: 30, maxValue: 30,
), ),
Padding( Padding(
padding: const EdgeInsets.only(top: 20), padding: const EdgeInsets.only(top: 20),
child: SettingsSubTitle(title: 'look'.t(context: context)), child: SettingsSubTitle(title: context.t.look),
), ),
SettingsRadioListTile( SettingsRadioListTile(
groups: [ groups: [
SettingsRadioGroup( SettingsRadioGroup(title: context.t.contain, value: SlideshowLook.contain),
title: 'contain'.t(context: context), SettingsRadioGroup(title: context.t.cover, value: SlideshowLook.cover),
value: SlideshowLook.contain, SettingsRadioGroup(title: context.t.blurred_background, value: SlideshowLook.blurredBackground),
),
SettingsRadioGroup(
title: 'cover'.t(context: context),
value: SlideshowLook.cover,
),
SettingsRadioGroup(
title: 'blurred_background'.t(context: context),
value: SlideshowLook.blurredBackground,
),
], ],
groupBy: useLook.value, groupBy: useLook.value,
onRadioChanged: (value) { onRadioChanged: (value) {
@ -83,24 +71,15 @@ class SlideshowSettings extends HookConsumerWidget {
), ),
Padding( Padding(
padding: const EdgeInsets.only(top: 20), padding: const EdgeInsets.only(top: 20),
child: SettingsSubTitle(title: 'direction'.t(context: context)), child: SettingsSubTitle(title: context.t.direction),
), ),
Padding( Padding(
padding: const EdgeInsets.only(bottom: 32), padding: const EdgeInsets.only(bottom: 32),
child: SettingsRadioListTile( child: SettingsRadioListTile(
groups: [ groups: [
SettingsRadioGroup( SettingsRadioGroup(title: context.t.forward, value: SlideshowDirection.forward),
title: 'forward'.t(context: context), SettingsRadioGroup(title: context.t.backward, value: SlideshowDirection.backward),
value: SlideshowDirection.forward, SettingsRadioGroup(title: context.t.shuffle, value: SlideshowDirection.shuffle),
),
SettingsRadioGroup(
title: 'backward'.t(context: context),
value: SlideshowDirection.backward,
),
SettingsRadioGroup(
title: 'shuffle'.t(context: context),
value: SlideshowDirection.shuffle,
),
], ],
groupBy: useDirection.value, groupBy: useDirection.value,
onRadioChanged: (value) { onRadioChanged: (value) {

View file

@ -3,7 +3,7 @@ import 'dart:async';
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/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';
import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart';
@ -31,24 +31,21 @@ class VideoViewerSettings extends HookConsumerWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SettingGroupTitle( SettingGroupTitle(title: context.t.videos, icon: Icons.video_camera_back_outlined),
title: "videos".t(context: context),
icon: Icons.video_camera_back_outlined,
),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: useAutoPlayVideo, valueNotifier: useAutoPlayVideo,
title: "setting_video_viewer_auto_play_title".t(context: context), title: context.t.setting_video_viewer_auto_play_title,
subtitle: "setting_video_viewer_auto_play_subtitle".t(context: context), subtitle: context.t.setting_video_viewer_auto_play_subtitle,
), ),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: useLoopVideo, valueNotifier: useLoopVideo,
title: "setting_video_viewer_looping_title".t(context: context), title: context.t.setting_video_viewer_looping_title,
subtitle: "loop_videos_description".t(context: context), subtitle: context.t.loop_videos_description,
), ),
SettingsSwitchListTile( SettingsSwitchListTile(
valueNotifier: useOriginalVideo, valueNotifier: useOriginalVideo,
title: "setting_video_viewer_original_video_title".t(context: context), title: context.t.setting_video_viewer_original_video_title,
subtitle: "setting_video_viewer_original_video_subtitle".t(context: context), subtitle: context.t.setting_video_viewer_original_video_subtitle,
), ),
], ],
); );

View file

@ -5,7 +5,6 @@ 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/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/app_settings.provider.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart';
import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart';
@ -45,9 +44,7 @@ class SyncStatusAndActions extends HookConsumerWidget {
return; return;
} }
context.scaffoldMessenger.showSnackBar( context.scaffoldMessenger.showSnackBar(const SnackBar(content: Text('Database file not found')));
SnackBar(content: Text("Database file not found".t(context: context))),
);
return; return;
} }
@ -77,17 +74,13 @@ class SyncStatusAndActions extends HookConsumerWidget {
return; return;
} }
context.scaffoldMessenger.showSnackBar( context.scaffoldMessenger.showSnackBar(const SnackBar(content: Text('Database exported successfully')));
SnackBar(content: Text("Database exported successfully".t(context: context))),
);
} catch (e) { } catch (e) {
if (!context.mounted) { if (!context.mounted) {
return; return;
} }
context.scaffoldMessenger.showSnackBar( context.scaffoldMessenger.showSnackBar(SnackBar(content: Text('Failed to export database: $e')));
SnackBar(content: Text("Failed to export database: $e".t(context: context))),
);
} }
} }
@ -138,10 +131,10 @@ class SyncStatusAndActions extends HookConsumerWidget {
const _SyncStatsCounts(), const _SyncStatsCounts(),
const Divider(height: 10), const Divider(height: 10),
const SizedBox(height: 16), const SizedBox(height: 16),
SettingGroupTitle(title: "jobs".t(context: context)), SettingGroupTitle(title: context.t.jobs),
SettingListTile( SettingListTile(
title: "sync_local".t(context: context), title: context.t.sync_local,
subtitle: "tap_to_run_job".t(context: context), subtitle: context.t.tap_to_run_job,
leading: const Icon(Icons.sync), leading: const Icon(Icons.sync),
trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).localSyncStatus), trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).localSyncStatus),
onTap: () { onTap: () {
@ -149,8 +142,8 @@ class SyncStatusAndActions extends HookConsumerWidget {
}, },
), ),
SettingListTile( SettingListTile(
title: "sync_remote".t(context: context), title: context.t.sync_remote,
subtitle: "tap_to_run_job".t(context: context), subtitle: context.t.tap_to_run_job,
leading: const Icon(Icons.cloud_sync), leading: const Icon(Icons.cloud_sync),
trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).remoteSyncStatus), trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).remoteSyncStatus),
onTap: () { onTap: () {
@ -159,16 +152,16 @@ class SyncStatusAndActions extends HookConsumerWidget {
), ),
if (CurrentPlatform.isIOS && serverVersion.isAtLeast(major: 2, minor: 5)) if (CurrentPlatform.isIOS && serverVersion.isAtLeast(major: 2, minor: 5))
SettingListTile( SettingListTile(
title: "Sync Cloud Ids".t(context: context), title: 'Sync Cloud Ids',
leading: const Icon(Icons.cloud_circle_rounded), leading: const Icon(Icons.cloud_circle_rounded),
subtitle: "tap_to_run_job".t(context: context), subtitle: context.t.tap_to_run_job,
trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).cloudIdSyncStatus), trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).cloudIdSyncStatus),
onTap: ref.watch(backgroundSyncProvider).syncCloudIds, onTap: ref.watch(backgroundSyncProvider).syncCloudIds,
), ),
SettingListTile( SettingListTile(
title: "hash_asset".t(context: context), title: context.t.hash_asset,
leading: const Icon(Icons.tag), leading: const Icon(Icons.tag),
subtitle: "tap_to_run_job".t(context: context), subtitle: context.t.tap_to_run_job,
trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).hashJobStatus), trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).hashJobStatus),
onTap: () { onTap: () {
unawaited(ref.read(backgroundSyncProvider).hashAssets()); unawaited(ref.read(backgroundSyncProvider).hashAssets());
@ -176,27 +169,21 @@ class SyncStatusAndActions extends HookConsumerWidget {
), ),
const Divider(height: 1), const Divider(height: 1),
const SizedBox(height: 16), const SizedBox(height: 16),
SettingGroupTitle(title: "actions".t(context: context)), SettingGroupTitle(title: context.t.actions),
ListTile( ListTile(
title: Text( title: Text(context.t.clear_file_cache, style: const TextStyle(fontWeight: FontWeight.w500)),
"clear_file_cache".t(context: context),
style: const TextStyle(fontWeight: FontWeight.w500),
),
leading: const Icon(Icons.playlist_remove_rounded), leading: const Icon(Icons.playlist_remove_rounded),
onTap: clearFileCache, onTap: clearFileCache,
), ),
ListTile( ListTile(
title: Text( title: Text(context.t.export_database, style: const TextStyle(fontWeight: FontWeight.w500)),
"export_database".t(context: context), subtitle: Text(context.t.export_database_description),
style: const TextStyle(fontWeight: FontWeight.w500),
),
subtitle: Text("export_database_description".t(context: context)),
leading: const Icon(Icons.download), leading: const Icon(Icons.download),
onTap: exportDatabase, onTap: exportDatabase,
), ),
ListTile( ListTile(
title: Text( title: Text(
"reset_sqlite".t(context: context), context.t.reset_sqlite,
style: TextStyle(color: context.colorScheme.error, fontWeight: FontWeight.w500), style: TextStyle(color: context.colorScheme.error, fontWeight: FontWeight.w500),
), ),
leading: Icon(Icons.settings_backup_restore_rounded, color: context.colorScheme.error), leading: Icon(Icons.settings_backup_restore_rounded, color: context.colorScheme.error),
@ -282,7 +269,7 @@ class _SyncStatsCounts extends ConsumerWidget {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SettingGroupTitle(title: "assets".t(context: context)), SettingGroupTitle(title: context.t.assets),
Padding( Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
// 1. Wrap in IntrinsicHeight // 1. Wrap in IntrinsicHeight
@ -295,24 +282,16 @@ class _SyncStatsCounts extends ConsumerWidget {
spacing: 8.0, spacing: 8.0,
children: [ children: [
Expanded( Expanded(
child: EntityCountTile( child: EntityCountTile(label: context.t.local, count: localAssetCount, icon: Icons.smartphone),
label: "local".t(context: context),
count: localAssetCount,
icon: Icons.smartphone,
),
), ),
Expanded( Expanded(
child: EntityCountTile( child: EntityCountTile(label: context.t.remote, count: remoteAssetCount, icon: Icons.cloud),
label: "remote".t(context: context),
count: remoteAssetCount,
icon: Icons.cloud,
),
), ),
], ],
), ),
), ),
), ),
SettingGroupTitle(title: "albums".t(context: context)), SettingGroupTitle(title: context.t.albums),
Padding( Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: IntrinsicHeight( child: IntrinsicHeight(
@ -323,24 +302,16 @@ class _SyncStatsCounts extends ConsumerWidget {
spacing: 8.0, spacing: 8.0,
children: [ children: [
Expanded( Expanded(
child: EntityCountTile( child: EntityCountTile(label: context.t.local, count: localAlbumCount, icon: Icons.smartphone),
label: "local".t(context: context),
count: localAlbumCount,
icon: Icons.smartphone,
),
), ),
Expanded( Expanded(
child: EntityCountTile( child: EntityCountTile(label: context.t.remote, count: remoteAlbumCount, icon: Icons.cloud),
label: "remote".t(context: context),
count: remoteAlbumCount,
icon: Icons.cloud,
),
), ),
], ],
), ),
), ),
), ),
SettingGroupTitle(title: "other".t(context: context)), SettingGroupTitle(title: context.t.other),
Padding( Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: IntrinsicHeight( child: IntrinsicHeight(
@ -351,18 +322,10 @@ class _SyncStatsCounts extends ConsumerWidget {
spacing: 8.0, spacing: 8.0,
children: [ children: [
Expanded( Expanded(
child: EntityCountTile( child: EntityCountTile(label: context.t.memories, count: memoryCount, icon: Icons.calendar_today),
label: "memories".t(context: context),
count: memoryCount,
icon: Icons.calendar_today,
),
), ),
Expanded( Expanded(
child: EntityCountTile( child: EntityCountTile(label: context.t.hashed_assets, count: localHashedCount, icon: Icons.tag),
label: "hashed_assets".t(context: context),
count: localHashedCount,
icon: Icons.tag,
),
), ),
], ],
), ),
@ -371,7 +334,7 @@ class _SyncStatsCounts extends ConsumerWidget {
// To be removed once the experimental feature is stable // To be removed once the experimental feature is stable
if (CurrentPlatform.isAndroid && if (CurrentPlatform.isAndroid &&
appSettingsService.getSetting<bool>(AppSettingsEnum.manageLocalMediaAndroid)) ...[ appSettingsService.getSetting<bool>(AppSettingsEnum.manageLocalMediaAndroid)) ...[
SettingGroupTitle(title: "trash".t(context: context)), SettingGroupTitle(title: context.t.trash),
Consumer( Consumer(
builder: (context, ref, _) { builder: (context, ref, _) {
final counts = ref.watch(trashedAssetsCountProvider); final counts = ref.watch(trashedAssetsCountProvider);
@ -387,17 +350,13 @@ class _SyncStatsCounts extends ConsumerWidget {
children: [ children: [
Expanded( Expanded(
child: EntityCountTile( child: EntityCountTile(
label: "local".t(context: context), label: context.t.local,
count: c.total, count: c.total,
icon: Icons.delete_outline, icon: Icons.delete_outline,
), ),
), ),
Expanded( Expanded(
child: EntityCountTile( child: EntityCountTile(label: context.t.hashed_assets, count: c.hashed, icon: Icons.tag),
label: "hashed_assets".t(context: context),
count: c.hashed,
icon: Icons.tag,
),
), ),
], ],
), ),

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/constants/enums.dart'; import 'package:immich_mobile/constants/enums.dart';
@ -9,12 +8,13 @@ import 'package:immich_mobile/domain/models/album/local_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/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/providers/cleanup.provider.dart'; import 'package:immich_mobile/providers/cleanup.provider.dart';
import 'package:immich_mobile/providers/haptic_feedback.provider.dart'; import 'package:immich_mobile/providers/haptic_feedback.provider.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';
import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:immich_mobile/utils/bytes_units.dart';
import 'package:intl/intl.dart';
import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:wakelock_plus/wakelock_plus.dart';
class FreeUpSpaceSettings extends ConsumerStatefulWidget { class FreeUpSpaceSettings extends ConsumerStatefulWidget {
@ -236,21 +236,21 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
final parts = <String>[]; final parts = <String>[];
if (state.keepMediaType == AssetKeepType.photosOnly) { if (state.keepMediaType == AssetKeepType.photosOnly) {
parts.add('all_photos'.t(context: context)); parts.add(context.t.all_photos);
} else if (state.keepMediaType == AssetKeepType.videosOnly) { } else if (state.keepMediaType == AssetKeepType.videosOnly) {
parts.add('all_videos'.t(context: context)); parts.add(context.t.all_videos);
} }
if (state.keepFavorites) { if (state.keepFavorites) {
parts.add('favorites'.t(context: context)); parts.add(context.t.favorites);
} }
if (state.keepAlbumIds.isNotEmpty) { if (state.keepAlbumIds.isNotEmpty) {
parts.add('keep_albums_count'.t(context: context, args: {'count': state.keepAlbumIds.length.toString()})); parts.add(context.t.keep_albums_count(count: state.keepAlbumIds.length));
} }
if (parts.isEmpty) { if (parts.isEmpty) {
return 'none'.t(context: context); return context.t.none;
} }
return parts.join(', '); return parts.join(', ');
@ -274,7 +274,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
borderRadius: const BorderRadius.all(Radius.circular(12)), borderRadius: const BorderRadius.all(Radius.circular(12)),
border: Border.all(color: context.primaryColor.withValues(alpha: 0.25)), border: Border.all(color: context.primaryColor.withValues(alpha: 0.25)),
), ),
child: Text('free_up_space_description'.t(context: context), style: context.textTheme.bodyMedium), child: Text(context.t.free_up_space_description, style: context.textTheme.bodyMedium),
), ),
), ),
@ -307,7 +307,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
color: hasKeepSettings ? context.colorScheme.primary : context.colorScheme.onSurfaceVariant, color: hasKeepSettings ? context.colorScheme.primary : context.colorScheme.onSurfaceVariant,
), ),
title: Text( title: Text(
'keep_on_device'.t(context: context), context.t.keep_on_device,
style: context.textTheme.titleSmall?.copyWith( style: context.textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: hasKeepSettings ? context.colorScheme.primary : null, color: hasKeepSettings ? context.colorScheme.primary : null,
@ -315,8 +315,8 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
), ),
subtitle: Text( subtitle: Text(
hasKeepSettings hasKeepSettings
? 'keeping'.t(context: context, args: {'items': getKeepSettingsSummary()}) ? context.t.keeping(items: getKeepSettingsSummary())
: 'keep_on_device_hint'.t(context: context), : context.t.keep_on_device_hint,
style: context.textTheme.bodySmall?.copyWith( style: context.textTheme.bodySmall?.copyWith(
color: hasKeepSettings ? context.colorScheme.primary : context.colorScheme.onSurfaceVariant, color: hasKeepSettings ? context.colorScheme.primary : context.colorScheme.onSurfaceVariant,
), ),
@ -327,12 +327,12 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
Text('keep_description'.t(context: context), style: subtitleStyle), Text(context.t.keep_description, style: subtitleStyle),
const SizedBox(height: 4), const SizedBox(height: 4),
SwitchListTile( SwitchListTile(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
title: Text( title: Text(
'keep_favorites'.t(context: context), context.t.keep_favorites,
style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5), style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5),
), ),
@ -352,7 +352,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'always_keep'.t(context: context), context.t.always_keep,
style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5), style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
@ -362,12 +362,12 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
const ButtonSegment(value: AssetKeepType.none, label: Text('')), const ButtonSegment(value: AssetKeepType.none, label: Text('')),
ButtonSegment( ButtonSegment(
value: AssetKeepType.photosOnly, value: AssetKeepType.photosOnly,
label: Text('photos'.t(context: context)), label: Text(context.t.photos),
icon: const Icon(Icons.photo), icon: const Icon(Icons.photo),
), ),
ButtonSegment( ButtonSegment(
value: AssetKeepType.videosOnly, value: AssetKeepType.videosOnly,
label: Text('videos'.t(context: context)), label: Text(context.t.videos),
icon: const Icon(Icons.videocam), icon: const Icon(Icons.videocam),
), ),
], ],
@ -381,8 +381,8 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
state.keepMediaType == AssetKeepType.photosOnly state.keepMediaType == AssetKeepType.photosOnly
? 'always_keep_photos_hint'.t(context: context) ? context.t.always_keep_photos_hint
: 'always_keep_videos_hint'.t(context: context), : context.t.always_keep_videos_hint,
style: context.textTheme.bodySmall?.copyWith( style: context.textTheme.bodySmall?.copyWith(
color: context.colorScheme.onSurfaceVariant, color: context.colorScheme.onSurfaceVariant,
), ),
@ -413,7 +413,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
Step( Step(
stepStyle: styleForState(step1State), stepStyle: styleForState(step1State),
title: Text( title: Text(
'select_cutoff_date'.t(context: context), context.t.select_cutoff_date,
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: step1State == StepState.complete color: step1State == StepState.complete
@ -433,7 +433,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
content: Column( content: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
Text('cutoff_date_description'.t(context: context), style: subtitleStyle), Text(context.t.cutoff_date_description, style: subtitleStyle),
const SizedBox(height: 16), const SizedBox(height: 16),
GridView.count( GridView.count(
shrinkWrap: true, shrinkWrap: true,
@ -445,39 +445,39 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
children: [ children: [
_DatePresetCard( _DatePresetCard(
value: '30', value: '30',
unit: 'cutoff_day'.t(context: context, args: {'count': '30'}), unit: context.t.cutoff_day(count: 30),
onTap: () => _setPresetDate(30), onTap: () => _setPresetDate(30),
isSelected: _isPresetSelected(30), isSelected: _isPresetSelected(30),
), ),
_DatePresetCard( _DatePresetCard(
value: '60', value: '60',
unit: 'cutoff_day'.t(context: context, args: {'count': '60'}), unit: context.t.cutoff_day(count: 60),
onTap: () => _setPresetDate(60), onTap: () => _setPresetDate(60),
isSelected: _isPresetSelected(60), isSelected: _isPresetSelected(60),
), ),
_DatePresetCard( _DatePresetCard(
value: '90', value: '90',
unit: 'cutoff_day'.t(context: context, args: {'count': '90'}), unit: context.t.cutoff_day(count: 90),
onTap: () => _setPresetDate(90), onTap: () => _setPresetDate(90),
isSelected: _isPresetSelected(90), isSelected: _isPresetSelected(90),
), ),
_DatePresetCard( _DatePresetCard(
value: '1', value: '1',
unit: 'cutoff_year'.t(context: context, args: {'count': '1'}), unit: context.t.cutoff_year(count: 1),
onTap: () => _setPresetDate(365), onTap: () => _setPresetDate(365),
isSelected: _isPresetSelected(365), isSelected: _isPresetSelected(365),
), ),
_DatePresetCard( _DatePresetCard(
value: '2', value: '2',
unit: 'cutoff_year'.t(context: context, args: {'count': '2'}), unit: context.t.cutoff_year(count: 2),
onTap: () => _setPresetDate(730), onTap: () => _setPresetDate(730),
isSelected: _isPresetSelected(730), isSelected: _isPresetSelected(730),
), ),
_DatePresetCard( _DatePresetCard(
value: '3', value: '3',
unit: 'cutoff_year'.t(context: context, args: {'count': '3'}), unit: context.t.cutoff_year(count: 3),
onTap: () => _setPresetDate(1095), onTap: () => _setPresetDate(1095),
isSelected: _isPresetSelected(1095), isSelected: _isPresetSelected(1095),
), ),
@ -487,14 +487,14 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
OutlinedButton.icon( OutlinedButton.icon(
onPressed: _selectDate, onPressed: _selectDate,
icon: const Icon(Icons.calendar_today), icon: const Icon(Icons.calendar_today),
label: Text('custom_date'.t(context: context)), label: Text(context.t.custom_date),
style: OutlinedButton.styleFrom(minimumSize: const Size(double.infinity, 48)), style: OutlinedButton.styleFrom(minimumSize: const Size(double.infinity, 48)),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
ElevatedButton.icon( ElevatedButton.icon(
onPressed: hasDate ? _goToScanStep : null, onPressed: hasDate ? _goToScanStep : null,
icon: const Icon(Icons.arrow_forward), icon: const Icon(Icons.arrow_forward),
label: Text('continue'.t(context: context)), label: Text(context.t.continue$),
style: ElevatedButton.styleFrom(minimumSize: const Size(double.infinity, 48)), style: ElevatedButton.styleFrom(minimumSize: const Size(double.infinity, 48)),
), ),
], ],
@ -507,7 +507,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
Step( Step(
stepStyle: styleForState(step2State), stepStyle: styleForState(step2State),
title: Text( title: Text(
'scan'.t(context: context), context.t.scan,
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: step2State == StepState.complete color: step2State == StepState.complete
@ -520,17 +520,11 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
subtitle: _hasScanned subtitle: _hasScanned
? Text( ? Text(
state.totalBytes > 0 state.totalBytes > 0
? 'cleanup_found_assets_with_size'.t( ? context.t.cleanup_found_assets_with_size(
context: context, count: state.assetsToDelete.length,
args: { size: formatBytes(state.totalBytes),
'count': state.assetsToDelete.length.toString(),
'size': formatBytes(state.totalBytes),
},
) )
: 'cleanup_found_assets'.t( : context.t.cleanup_found_assets(count: state.assetsToDelete.length),
context: context,
args: {'count': state.assetsToDelete.length.toString()},
),
style: context.textTheme.bodyMedium?.copyWith( style: context.textTheme.bodyMedium?.copyWith(
color: state.assetsToDelete.isNotEmpty color: state.assetsToDelete.isNotEmpty
? context.colorScheme.primary ? context.colorScheme.primary
@ -541,7 +535,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
: null, : null,
content: Column( content: Column(
children: [ children: [
Text('cleanup_step3_description'.t(context: context), style: subtitleStyle), Text(context.t.cleanup_step3_description, style: subtitleStyle),
if (CurrentPlatform.isIOS) ...[ if (CurrentPlatform.isIOS) ...[
const SizedBox(height: 12), const SizedBox(height: 12),
Container( Container(
@ -556,7 +550,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
child: Text( child: Text(
'cleanup_icloud_shared_albums_excluded'.t(context: context), context.t.cleanup_icloud_shared_albums_excluded,
style: context.textTheme.labelLarge, style: context.textTheme.labelLarge,
), ),
), ),
@ -577,7 +571,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
: ElevatedButton.icon( : ElevatedButton.icon(
onPressed: state.isScanning ? null : _scanAssets, onPressed: state.isScanning ? null : _scanAssets,
icon: const Icon(Icons.search), icon: const Icon(Icons.search),
label: Text(_hasScanned ? 'rescan'.t(context: context) : 'scan'.t(context: context)), label: Text(_hasScanned ? context.t.rescan : context.t.scan),
style: ElevatedButton.styleFrom(minimumSize: const Size(double.infinity, 48)), style: ElevatedButton.styleFrom(minimumSize: const Size(double.infinity, 48)),
), ),
if (_hasScanned && state.assetsToDelete.isEmpty) ...[ if (_hasScanned && state.assetsToDelete.isEmpty) ...[
@ -593,10 +587,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
const Icon(Icons.info, color: Colors.orange), const Icon(Icons.info, color: Colors.orange),
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
child: Text( child: Text(context.t.cleanup_no_assets_found, style: context.textTheme.bodyMedium),
'cleanup_no_assets_found'.t(context: context),
style: context.textTheme.bodyMedium,
),
), ),
], ],
), ),
@ -612,7 +603,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
Step( Step(
stepStyle: styleForState(step3State, isDestructive: true), stepStyle: styleForState(step3State, isDestructive: true),
title: Text( title: Text(
'move_to_device_trash'.t(context: context), context.t.move_to_device_trash,
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: step3State == StepState.disabled color: step3State == StepState.disabled
@ -635,12 +626,9 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'cleanup_step4_summary'.t( context.t.cleanup_step4_summary(
context: context, count: state.assetsToDelete.length,
args: { date: DateFormat.yMMMd().format(state.selectedDate!),
'count': state.assetsToDelete.length.toString(),
'date': DateFormat.yMMMd().format(state.selectedDate!),
},
), ),
style: context.textTheme.labelLarge?.copyWith(fontSize: 15), style: context.textTheme.labelLarge?.copyWith(fontSize: 15),
), ),
@ -652,7 +640,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
OutlinedButton.icon( OutlinedButton.icon(
onPressed: () => _showAssetsPreview(state.assetsToDelete), onPressed: () => _showAssetsPreview(state.assetsToDelete),
icon: const Icon(Icons.preview), icon: const Icon(Icons.preview),
label: Text('preview'.t(context: context)), label: Text(context.t.preview),
style: OutlinedButton.styleFrom(minimumSize: const Size(double.infinity, 48)), style: OutlinedButton.styleFrom(minimumSize: const Size(double.infinity, 48)),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
@ -665,11 +653,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white), child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white),
) )
: const Icon(Icons.delete_forever), : const Icon(Icons.delete_forever),
label: Text( label: Text(state.isDeleting ? context.t.cleanup_deleting : context.t.move_to_device_trash),
state.isDeleting
? 'cleanup_deleting'.t(context: context)
: 'move_to_device_trash'.t(context: context),
),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: context.colorScheme.error, backgroundColor: context.colorScheme.error,
foregroundColor: context.colorScheme.onError, foregroundColor: context.colorScheme.onError,
@ -701,26 +685,20 @@ class _DeleteConfirmationDialog extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text('cleanup_confirm_prompt_title'.t(context: context)), title: Text(context.t.cleanup_confirm_prompt_title),
content: Text( content: Text(
'cleanup_confirm_description'.t( context.t.cleanup_confirm_description(count: assetCount, date: DateFormat.yMMMd().format(cutoffDate)),
context: context,
args: {'count': assetCount.toString(), 'date': DateFormat.yMMMd().format(cutoffDate)},
),
style: context.textTheme.labelLarge?.copyWith(fontSize: 15), style: context.textTheme.labelLarge?.copyWith(fontSize: 15),
), ),
actions: [ actions: [
TextButton( TextButton(onPressed: () => ContextHelper(context).pop(false), child: Text(context.t.cancel)),
onPressed: () => ContextHelper(context).pop(false),
child: Text('cancel'.t(context: context)),
),
ElevatedButton( ElevatedButton(
onPressed: () => ContextHelper(context).pop(true), onPressed: () => ContextHelper(context).pop(true),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: context.colorScheme.error, backgroundColor: context.colorScheme.error,
foregroundColor: context.colorScheme.onError, foregroundColor: context.colorScheme.onError,
), ),
child: Text('confirm'.t(context: context)), child: Text(context.t.confirm),
), ),
], ],
); );
@ -736,29 +714,24 @@ class _DeleteSuccessDialog extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
icon: Icon(Icons.check_circle, color: context.colorScheme.primary, size: 48), icon: Icon(Icons.check_circle, color: context.colorScheme.primary, size: 48),
title: Text('success'.t(context: context)), title: Text(context.t.success),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
'cleanup_deleted_assets'.t(context: context, args: {'count': deletedCount.toString()}), context.t.cleanup_deleted_assets(count: deletedCount),
style: context.textTheme.labelLarge?.copyWith(fontSize: 16), style: context.textTheme.labelLarge?.copyWith(fontSize: 16),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'cleanup_trash_hint'.t(context: context), context.t.cleanup_trash_hint,
style: context.textTheme.labelLarge?.copyWith(fontSize: 16, color: context.primaryColor), style: context.textTheme.labelLarge?.copyWith(fontSize: 16, color: context.primaryColor),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
], ],
), ),
actions: [ actions: [ElevatedButton(onPressed: () => ContextHelper(context).pop(), child: Text(context.t.done))],
ElevatedButton(
onPressed: () => ContextHelper(context).pop(),
child: Text('done'.t(context: context)),
),
],
); );
} }
} }
@ -824,7 +797,7 @@ class _KeepAlbumsSection extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'keep_albums'.t(context: context), context.t.keep_albums,
style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5), style: context.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5),
), ),
@ -834,13 +807,13 @@ class _KeepAlbumsSection extends ConsumerWidget {
child: Padding(padding: EdgeInsets.all(16.0), child: CircularProgressIndicator(strokeWidth: 2)), child: Padding(padding: EdgeInsets.all(16.0), child: CircularProgressIndicator(strokeWidth: 2)),
), ),
error: (error, stack) => Text( error: (error, stack) => Text(
'error_loading_albums'.t(context: context), context.t.error_loading_albums,
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.error), style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.error),
), ),
data: (albums) { data: (albums) {
if (albums.isEmpty) { if (albums.isEmpty) {
return Text( return Text(
'no_albums_found'.t(context: context), context.t.no_albums_found,
style: context.textTheme.bodyMedium?.copyWith( style: context.textTheme.bodyMedium?.copyWith(
color: context.colorScheme.onSurface.withValues(alpha: 0.6), color: context.colorScheme.onSurface.withValues(alpha: 0.6),
), ),
@ -870,7 +843,7 @@ class _KeepAlbumsSection extends ConsumerWidget {
if (albumIds.isNotEmpty) ...[ if (albumIds.isNotEmpty) ...[
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'keep_albums_count'.t(context: context, args: {'count': albumIds.length.toString()}), context.t.keep_albums_count(count: albumIds.length),
style: context.textTheme.bodySmall?.copyWith( style: context.textTheme.bodySmall?.copyWith(
color: context.colorScheme.primary, color: context.colorScheme.primary,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,

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:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart'; import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/auth.provider.dart';
import 'package:immich_mobile/widgets/settings/networking_settings/networking_settings.dart'; import 'package:immich_mobile/widgets/settings/networking_settings/networking_settings.dart';
@ -78,11 +78,11 @@ class EndpointInputState extends ConsumerState<EndpointInput> {
try { try {
if (url == null || url.isEmpty || !Uri.parse(url).isAbsolute) { if (url == null || url.isEmpty || !Uri.parse(url).isAbsolute) {
isInputValid = false; isInputValid = false;
return 'validate_endpoint_error'.tr(); return context.t.validate_endpoint_error;
} }
} catch (_) { } catch (_) {
isInputValid = false; isInputValid = false;
return 'validate_endpoint_error'.tr(); return context.t.validate_endpoint_error;
} }
isInputValid = true; isInputValid = true;

View file

@ -5,7 +5,7 @@ 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/settings_key.dart'; import 'package:immich_mobile/domain/models/settings_key.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/models/auth/auxilary_endpoint.model.dart'; import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/api.provider.dart'; import 'package:immich_mobile/providers/api.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
@ -103,7 +103,7 @@ class ExternalNetworkPreference extends HookConsumerWidget {
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 24), padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 24),
child: Text("external_network_sheet_info".t(context: context), style: context.textTheme.bodyMedium), child: Text(context.t.external_network_sheet_info, style: context.textTheme.bodyMedium),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Divider(color: context.colorScheme.surfaceContainerHighest), Divider(color: context.colorScheme.surfaceContainerHighest),
@ -135,7 +135,7 @@ class ExternalNetworkPreference extends HookConsumerWidget {
height: 48, height: 48,
child: OutlinedButton.icon( child: OutlinedButton.icon(
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
label: Text('add_endpoint'.t(context: context)), label: Text(context.t.add_endpoint),
onPressed: enabled onPressed: enabled
? () { ? () {
entries.value = [ entries.value = [

View file

@ -1,11 +1,10 @@
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/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/auth.provider.dart'; import 'package:immich_mobile/providers/auth.provider.dart';
import 'package:immich_mobile/providers/network.provider.dart'; import 'package:immich_mobile/providers/network.provider.dart';
import 'package:immich_ui/immich_ui.dart'; import 'package:immich_ui/immich_ui.dart';
@ -34,9 +33,12 @@ class LocalNetworkPreference extends HookConsumerWidget {
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
child: Text('cancel'.tr().toUpperCase(), style: const TextStyle(color: Colors.red)), child: Text(context.t.cancel.toUpperCase(), style: const TextStyle(color: Colors.red)),
),
TextButton(
onPressed: () => Navigator.pop(context, controller.text),
child: Text(context.t.save.toUpperCase()),
), ),
TextButton(onPressed: () => Navigator.pop(context, controller.text), child: Text('save'.tr().toUpperCase())),
], ],
), ),
); );
@ -73,7 +75,12 @@ class LocalNetworkPreference extends HookConsumerWidget {
} }
Future<void> handleEditWifiName() async { Future<void> handleEditWifiName() async {
final wifiName = await _showEditDialog(context, "wifi_name".tr(), "your_wifi_name".tr(), wifiNameText.value); final wifiName = await _showEditDialog(
context,
context.t.wifi_name,
context.t.your_wifi_name,
wifiNameText.value,
);
if (wifiName != null) { if (wifiName != null) {
await saveWifiName(wifiName); await saveWifiName(wifiName);
@ -83,7 +90,7 @@ class LocalNetworkPreference extends HookConsumerWidget {
Future<void> handleEditServerEndpoint() async { Future<void> handleEditServerEndpoint() async {
final localEndpoint = await _showEditDialog( final localEndpoint = await _showEditDialog(
context, context,
"server_endpoint".tr(), context.t.server_endpoint,
"http://local-ip:2283", "http://local-ip:2283",
localEndpointText.value, localEndpointText.value,
isUrlField: true, isUrlField: true,
@ -104,7 +111,7 @@ class LocalNetworkPreference extends HookConsumerWidget {
context.showSnackBar( context.showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(
"get_wifiname_error".tr(), context.t.get_wifiname_error,
style: context.textTheme.bodyMedium?.copyWith( style: context.textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: context.colorScheme.onSecondary, color: context.colorScheme.onSecondary,
@ -149,7 +156,7 @@ class LocalNetworkPreference extends HookConsumerWidget {
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 24), padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 24),
child: Text("local_network_sheet_info".tr(), style: context.textTheme.bodyMedium), child: Text(context.t.local_network_sheet_info, style: context.textTheme.bodyMedium),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Divider(color: context.colorScheme.surfaceContainerHighest), Divider(color: context.colorScheme.surfaceContainerHighest),
@ -157,9 +164,9 @@ class LocalNetworkPreference extends HookConsumerWidget {
enabled: enabled, enabled: enabled,
contentPadding: const EdgeInsets.only(left: 24, right: 8), contentPadding: const EdgeInsets.only(left: 24, right: 8),
leading: const Icon(Icons.wifi_rounded), leading: const Icon(Icons.wifi_rounded),
title: Text("wifi_name".tr()), title: Text(context.t.wifi_name),
subtitle: wifiNameText.value.isEmpty subtitle: wifiNameText.value.isEmpty
? Text("enter_wifi_name".tr()) ? Text(context.t.enter_wifi_name)
: Text( : Text(
wifiNameText.value, wifiNameText.value,
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(
@ -177,7 +184,7 @@ class LocalNetworkPreference extends HookConsumerWidget {
enabled: enabled, enabled: enabled,
contentPadding: const EdgeInsets.only(left: 24, right: 8), contentPadding: const EdgeInsets.only(left: 24, right: 8),
leading: const Icon(Icons.lan_rounded), leading: const Icon(Icons.lan_rounded),
title: Text("server_endpoint".t(context: context)), title: Text(context.t.server_endpoint),
subtitle: localEndpointText.value.isEmpty subtitle: localEndpointText.value.isEmpty
? const Text("http://local-ip:2283") ? const Text("http://local-ip:2283")
: Text( : Text(
@ -199,7 +206,7 @@ class LocalNetworkPreference extends HookConsumerWidget {
height: 48, height: 48,
child: OutlinedButton.icon( child: OutlinedButton.icon(
icon: const Icon(Icons.wifi_find_rounded), icon: const Icon(Icons.wifi_find_rounded),
label: Text('use_current_connection'.t(context: context)), label: Text(context.t.use_current_connection),
onPressed: enabled ? autofillCurrentNetwork : null, onPressed: enabled ? autofillCurrentNetwork : null,
), ),
), ),

View file

@ -1,11 +1,10 @@
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/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/models/auth/auxilary_endpoint.model.dart'; import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/providers/network.provider.dart'; import 'package:immich_mobile/providers/network.provider.dart';
@ -39,8 +38,8 @@ class NetworkingSettings extends HookConsumerWidget {
context: context, context: context,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
title: Text("location_permission".tr()), title: Text(context.t.location_permission),
content: Text("location_permission_content".tr()), content: Text(context.t.location_permission_content),
actions: [ actions: [
TextButton( TextButton(
onPressed: () async { onPressed: () async {
@ -52,7 +51,7 @@ class NetworkingSettings extends HookConsumerWidget {
Navigator.pop(context, isGrant); Navigator.pop(context, isGrant);
}, },
child: Text("grant_permission".tr()), child: Text(context.t.grant_permission),
), ),
], ],
); );
@ -69,8 +68,8 @@ class NetworkingSettings extends HookConsumerWidget {
context: context, context: context,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
title: Text("background_location_permission".tr()), title: Text(context.t.background_location_permission),
content: Text("background_location_permission_content".tr()), content: Text(context.t.background_location_permission_content),
actions: [ actions: [
TextButton( TextButton(
onPressed: () async { onPressed: () async {
@ -82,7 +81,7 @@ class NetworkingSettings extends HookConsumerWidget {
Navigator.pop(context, isGrant); Navigator.pop(context, isGrant);
}, },
child: Text("grant_permission".tr()), child: Text(context.t.grant_permission),
), ),
], ],
); );
@ -107,7 +106,7 @@ class NetworkingSettings extends HookConsumerWidget {
children: <Widget>[ children: <Widget>[
const SizedBox(height: 8), const SizedBox(height: 8),
SettingGroupTitle( SettingGroupTitle(
title: "current_server_address".t(context: context), title: context.t.current_server_address,
icon: (currentEndpoint?.startsWith('https') ?? false) ? Icons.https_outlined : Icons.http_outlined, icon: (currentEndpoint?.startsWith('https') ?? false) ? Icons.https_outlined : Icons.http_outlined,
), ),
Padding( Padding(
@ -136,20 +135,14 @@ class NetworkingSettings extends HookConsumerWidget {
SettingsSwitchListTile( SettingsSwitchListTile(
enabled: true, enabled: true,
valueNotifier: featureEnabled, valueNotifier: featureEnabled,
title: "automatic_endpoint_switching_title".tr(), title: context.t.automatic_endpoint_switching_title,
subtitle: "automatic_endpoint_switching_subtitle".tr(), subtitle: context.t.automatic_endpoint_switching_subtitle,
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
SettingGroupTitle( SettingGroupTitle(title: context.t.local_network, icon: Icons.home_outlined),
title: "local_network".t(context: context),
icon: Icons.home_outlined,
),
LocalNetworkPreference(enabled: featureEnabled.value), LocalNetworkPreference(enabled: featureEnabled.value),
const SizedBox(height: 16), const SizedBox(height: 16),
SettingGroupTitle( SettingGroupTitle(title: context.t.external_network, icon: Icons.dns_outlined),
title: "external_network".t(context: context),
icon: Icons.dns_outlined,
),
ExternalNetworkPreference(enabled: featureEnabled.value), ExternalNetworkPreference(enabled: featureEnabled.value),
], ],
); );

View file

@ -1,10 +1,10 @@
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/services.dart'; import 'package:flutter/services.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/platform/network_api.g.dart'; import 'package:immich_mobile/platform/network_api.g.dart';
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
@ -44,12 +44,15 @@ class _SslClientCertSettingsState extends State<SslClientCertSettings> {
contentPadding: const EdgeInsets.symmetric(horizontal: 20), contentPadding: const EdgeInsets.symmetric(horizontal: 20),
horizontalTitleGap: 20, horizontalTitleGap: 20,
isThreeLine: true, isThreeLine: true,
title: Text("client_cert_title".tr(), style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500)), title: Text(
context.t.client_cert_title,
style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500),
),
subtitle: Column( subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"client_cert_subtitle".tr(), context.t.client_cert_subtitle,
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
@ -58,8 +61,8 @@ class _SslClientCertSettingsState extends State<SslClientCertSettings> {
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
ElevatedButton(onPressed: importCert, child: Text("client_cert_import".tr())), ElevatedButton(onPressed: importCert, child: Text(context.t.client_cert_import)),
ElevatedButton(onPressed: !isCertExist ? null : removeCert, child: Text("remove".tr())), ElevatedButton(onPressed: !isCertExist ? null : removeCert, child: Text(context.t.remove)),
], ],
), ),
], ],
@ -79,20 +82,20 @@ class _SslClientCertSettingsState extends State<SslClientCertSettings> {
Future<void> importCert() async { Future<void> importCert() async {
try { try {
final styling = ClientCertPrompt( final styling = ClientCertPrompt(
title: "client_cert_password_title".tr(), title: context.t.client_cert_password_title,
message: "client_cert_password_message".tr(), message: context.t.client_cert_password_message,
cancel: "cancel".tr(), cancel: context.t.cancel,
confirm: "confirm".tr(), confirm: context.t.confirm,
); );
await networkApi.selectCertificate(styling); await networkApi.selectCertificate(styling);
setState(() => isCertExist = true); setState(() => isCertExist = true);
showMessage("client_cert_import_success_msg".tr()); showMessage(StaticTranslations.instance.client_cert_import_success_msg);
} catch (e) { } catch (e) {
if (_isCancellation(e)) { if (_isCancellation(e)) {
return; return;
} }
_log.severe("Error importing client cert", e); _log.severe("Error importing client cert", e);
showMessage("client_cert_invalid_msg".tr()); showMessage(StaticTranslations.instance.client_cert_invalid_msg);
} }
} }
@ -100,13 +103,13 @@ class _SslClientCertSettingsState extends State<SslClientCertSettings> {
try { try {
await networkApi.removeCertificate(); await networkApi.removeCertificate();
setState(() => isCertExist = false); setState(() => isCertExist = false);
showMessage("client_cert_remove_msg".tr()); showMessage(StaticTranslations.instance.client_cert_remove_msg);
} catch (e) { } catch (e) {
if (_isCancellation(e)) { if (_isCancellation(e)) {
return; return;
} }
_log.severe("Error removing client cert", e); _log.severe("Error removing client cert", e);
showMessage("client_cert_invalid_msg".tr()); showMessage(StaticTranslations.instance.client_cert_invalid_msg);
} }
} }