mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
chore: migrate mobile translations accessor (5) (#30672)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
parent
a8b3b30aba
commit
675408b003
41 changed files with 268 additions and 372 deletions
|
|
@ -97,6 +97,18 @@ dart_code_metrics:
|
|||
exclude-paths:
|
||||
- 'lib/utils/debug_print.dart'
|
||||
severity: perf
|
||||
- name: tr
|
||||
description: 'Use context.t.<key> or StaticTranslations.instance.<key> instead of tr().'
|
||||
- type: String
|
||||
entries:
|
||||
- name: tr
|
||||
description: 'Use context.t.<key> or StaticTranslations.instance.<key> instead of String.tr().'
|
||||
- name: plural
|
||||
description: 'Use the generated plural accessor instead of String.plural().'
|
||||
- type: Text
|
||||
entries:
|
||||
- name: tr
|
||||
description: 'Use Text(context.t.<key>) instead of Text(<key>).tr().'
|
||||
# All rules from "recommended" preset
|
||||
# Show potential errors
|
||||
# - avoid-cascade-after-if-null
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
import '../test_utils/general_helper.dart';
|
||||
|
||||
|
|
@ -7,45 +7,32 @@ void main() async {
|
|||
await ImmichTestHelper.initialize();
|
||||
|
||||
group("Login input validation test", () {
|
||||
immichWidgetTest("Test leading/trailing whitespace",
|
||||
(tester, helper) async {
|
||||
immichWidgetTest("Test leading/trailing whitespace", (tester, helper) async {
|
||||
await helper.loginHelper.waitForLoginScreen();
|
||||
await helper.loginHelper.acknowledgeNewServerVersion();
|
||||
|
||||
await helper.loginHelper.enterCredentials(
|
||||
email: " demo@immich.app",
|
||||
);
|
||||
await helper.loginHelper.enterCredentials(email: " demo@immich.app");
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 300));
|
||||
|
||||
expect(
|
||||
find.text("login_form_err_leading_whitespace".tr()),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.text(StaticTranslations.instance.login_form_err_leading_whitespace), findsOneWidget);
|
||||
|
||||
await helper.loginHelper.enterCredentials(
|
||||
email: "demo@immich.app ",
|
||||
);
|
||||
await helper.loginHelper.enterCredentials(email: "demo@immich.app ");
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 300));
|
||||
|
||||
expect(
|
||||
find.text("login_form_err_trailing_whitespace".tr()),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.text(StaticTranslations.instance.login_form_err_trailing_whitespace), findsOneWidget);
|
||||
});
|
||||
|
||||
immichWidgetTest("Test invalid email", (tester, helper) async {
|
||||
await helper.loginHelper.waitForLoginScreen();
|
||||
await helper.loginHelper.acknowledgeNewServerVersion();
|
||||
|
||||
await helper.loginHelper.enterCredentials(
|
||||
email: "demo.immich.app",
|
||||
);
|
||||
await helper.loginHelper.enterCredentials(email: "demo.immich.app");
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 300));
|
||||
|
||||
expect(find.text("login_form_err_invalid_email".tr()), findsOneWidget);
|
||||
expect(find.text(StaticTranslations.instance.login_form_err_invalid_email), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
import 'general_helper.dart';
|
||||
|
||||
|
|
@ -23,11 +23,7 @@ class ImmichTestLoginHelper {
|
|||
return true;
|
||||
}
|
||||
|
||||
Future<void> enterCredentials({
|
||||
String server = "",
|
||||
String email = "",
|
||||
String password = "",
|
||||
}) async {
|
||||
Future<void> enterCredentials({String server = "", String email = "", String password = ""}) async {
|
||||
final loginForms = find.byType(TextFormField);
|
||||
|
||||
await tester.enterText(loginForms.at(0), email);
|
||||
|
|
@ -44,49 +40,30 @@ class ImmichTestLoginHelper {
|
|||
}
|
||||
|
||||
Future<void> enterCredentialsOf(LoginCredentials credentials) async {
|
||||
await enterCredentials(
|
||||
server: credentials.server,
|
||||
email: credentials.email,
|
||||
password: credentials.password,
|
||||
);
|
||||
await enterCredentials(server: credentials.server, email: credentials.email, password: credentials.password);
|
||||
}
|
||||
|
||||
Future<void> pressLoginButton() async {
|
||||
await pumpUntilFound(
|
||||
tester,
|
||||
find.textContaining("login_form_button_text".tr()),
|
||||
);
|
||||
final button = find.textContaining("login_form_button_text".tr());
|
||||
await pumpUntilFound(tester, find.textContaining(StaticTranslations.instance.login));
|
||||
final button = find.textContaining(StaticTranslations.instance.login);
|
||||
await tester.tap(button);
|
||||
}
|
||||
|
||||
Future<void> assertLoginSuccess() async {
|
||||
await pumpUntilFound(tester, find.text("home_page_building_timeline".tr()));
|
||||
await pumpUntilFound(tester, find.text(StaticTranslations.instance.home_page_building_timeline));
|
||||
}
|
||||
|
||||
Future<void> assertLoginFailed() async {
|
||||
await pumpUntilFound(tester, find.text("login_form_failed_login".tr()));
|
||||
await pumpUntilFound(tester, find.text(StaticTranslations.instance.login_form_failed_login));
|
||||
}
|
||||
}
|
||||
|
||||
enum LoginCredentials {
|
||||
testInstance(
|
||||
"https://flutter-int-test.preview.immich.app",
|
||||
"demo@immich.app",
|
||||
"demo",
|
||||
),
|
||||
testInstance("https://flutter-int-test.preview.immich.app", "demo@immich.app", "demo"),
|
||||
|
||||
testInstanceButWithWrongPassword(
|
||||
"https://flutter-int-test.preview.immich.app",
|
||||
"demo@immich.app",
|
||||
"wrong",
|
||||
),
|
||||
testInstanceButWithWrongPassword("https://flutter-int-test.preview.immich.app", "demo@immich.app", "wrong"),
|
||||
|
||||
wrongInstanceUrl(
|
||||
"https://does-not-exist.preview.immich.app",
|
||||
"demo@immich.app",
|
||||
"demo",
|
||||
);
|
||||
wrongInstanceUrl("https://does-not-exist.preview.immich.app", "demo@immich.app", "demo");
|
||||
|
||||
const LoginCredentials(this.server, this.email, this.password);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,40 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/utils/semver.dart';
|
||||
|
||||
class FeatureHighlight {
|
||||
enum FeatureHighlight {
|
||||
shareQuality(image: 'assets/feature_message/share_quality.webp'),
|
||||
slideshow(image: 'assets/feature_message/slideshow.webp'),
|
||||
recentlyAdded(image: 'assets/feature_message/recently_added.webp'),
|
||||
ocr(image: 'assets/feature_message/ocr.webp'),
|
||||
openInImmich(image: 'assets/feature_message/open_in_immich.webp', platform: [.android]),
|
||||
uploadToAlbum();
|
||||
|
||||
/// Asset path of the feature screenshot, or null to show a placeholder.
|
||||
final String? image;
|
||||
final String titleKey;
|
||||
final String bodyKey;
|
||||
final List<TargetPlatform> platform;
|
||||
|
||||
const FeatureHighlight({
|
||||
this.image,
|
||||
required this.titleKey,
|
||||
required this.bodyKey,
|
||||
this.platform = const [.iOS, .android],
|
||||
});
|
||||
const FeatureHighlight({this.image, this.platform = const [.iOS, .android]});
|
||||
|
||||
bool get isVisibleOnCurrentPlatform => platform.contains(defaultTargetPlatform);
|
||||
|
||||
String title(Translations t) => switch (this) {
|
||||
FeatureHighlight.shareQuality => t.share_quality_title,
|
||||
FeatureHighlight.slideshow => t.slideshow_title,
|
||||
FeatureHighlight.recentlyAdded => t.recently_added_title,
|
||||
FeatureHighlight.ocr => t.ocr_title,
|
||||
FeatureHighlight.openInImmich => t.open_in_immich_title,
|
||||
FeatureHighlight.uploadToAlbum => t.upload_to_album_title,
|
||||
};
|
||||
|
||||
String body(Translations t) => switch (this) {
|
||||
FeatureHighlight.shareQuality => t.share_quality_body,
|
||||
FeatureHighlight.slideshow => t.slideshow_body,
|
||||
FeatureHighlight.recentlyAdded => t.recently_added_body,
|
||||
FeatureHighlight.ocr => t.ocr_body,
|
||||
FeatureHighlight.openInImmich => t.open_in_immich_body,
|
||||
FeatureHighlight.uploadToAlbum => t.upload_to_album_body,
|
||||
};
|
||||
}
|
||||
|
||||
/// The release this batch of highlights was authored for. Content-defined:
|
||||
|
|
@ -24,31 +43,4 @@ const featureMessageRelease = SemVer(major: 3, minor: 0, patch: 0);
|
|||
|
||||
/// Highlights relevant to the current platform.
|
||||
List<FeatureHighlight> get visibleFeatureMessageHighlights =>
|
||||
featureMessageHighlights.where((h) => h.isVisibleOnCurrentPlatform).toList();
|
||||
|
||||
const List<FeatureHighlight> featureMessageHighlights = [
|
||||
FeatureHighlight(
|
||||
image: 'assets/feature_message/share_quality.webp',
|
||||
titleKey: 'share_quality_title',
|
||||
bodyKey: 'share_quality_body',
|
||||
),
|
||||
FeatureHighlight(
|
||||
image: 'assets/feature_message/slideshow.webp',
|
||||
titleKey: 'slideshow_title',
|
||||
bodyKey: 'slideshow_body',
|
||||
),
|
||||
FeatureHighlight(
|
||||
image: 'assets/feature_message/recently_added.webp',
|
||||
titleKey: 'recently_added_title',
|
||||
bodyKey: 'recently_added_body',
|
||||
),
|
||||
|
||||
FeatureHighlight(image: 'assets/feature_message/ocr.webp', titleKey: 'ocr_title', bodyKey: 'ocr_body'),
|
||||
FeatureHighlight(
|
||||
image: 'assets/feature_message/open_in_immich.webp',
|
||||
titleKey: 'open_in_immich_title',
|
||||
bodyKey: 'open_in_immich_body',
|
||||
platform: [.android],
|
||||
),
|
||||
FeatureHighlight(titleKey: 'upload_to_album_title', bodyKey: 'upload_to_album_body'),
|
||||
];
|
||||
FeatureHighlight.values.where((h) => h.isVisibleOnCurrentPlatform).toList();
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class FeatureMessageService {
|
|||
|
||||
bool shouldShow() {
|
||||
final seen = _settingsRepository.appConfig.featureMessage.seenRelease;
|
||||
return featureMessageHighlights.isNotEmpty && featureMessageRelease > seen;
|
||||
return visibleFeatureMessageHighlights.isNotEmpty && featureMessageRelease > seen;
|
||||
}
|
||||
|
||||
Future<void> markSeen() => _settingsRepository.write(SettingsKey.featureMessageSeenRelease, featureMessageRelease);
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/utils/debug_print.dart';
|
||||
import 'package:intl/message_format.dart';
|
||||
|
||||
extension StringTranslateExtension on String {
|
||||
String t({BuildContext? context, Map<String, Object>? args}) {
|
||||
return _translateHelper(context, this, args);
|
||||
}
|
||||
}
|
||||
|
||||
extension TextTranslateExtension on Text {
|
||||
Text t({BuildContext? context, Map<String, Object>? args}) {
|
||||
return Text(
|
||||
_translateHelper(context, data ?? '', args),
|
||||
key: key,
|
||||
style: style,
|
||||
strutStyle: strutStyle,
|
||||
textAlign: textAlign,
|
||||
textDirection: textDirection,
|
||||
locale: locale,
|
||||
softWrap: softWrap,
|
||||
overflow: overflow,
|
||||
textScaler: textScaler,
|
||||
maxLines: maxLines,
|
||||
semanticsLabel: semanticsLabel,
|
||||
textWidthBasis: textWidthBasis,
|
||||
textHeightBehavior: textHeightBehavior,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _translateHelper(BuildContext? context, String key, [Map<String, Object>? args]) {
|
||||
if (key.isEmpty) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
final translatedMessage = key.tr(context: context);
|
||||
return args != null
|
||||
? MessageFormat(translatedMessage, locale: Intl.defaultLocale ?? 'en').format(args)
|
||||
: translatedMessage;
|
||||
} catch (e) {
|
||||
dPrint(() => 'Translation failed for key "$key". Error: $e');
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
|
@ -427,8 +427,8 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
|||
return showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) => ConfirmDialog(
|
||||
title: "delete_shared_link_dialog_title",
|
||||
content: "confirm_delete_shared_link",
|
||||
title: context.t.delete_shared_link_dialog_title,
|
||||
content: context.t.confirm_delete_shared_link,
|
||||
onOk: () async {
|
||||
await ref.read(sharedLinkServiceProvider).deleteSharedLink(existingLink!.id);
|
||||
ref.invalidate(sharedLinksStateProvider);
|
||||
|
|
|
|||
|
|
@ -127,8 +127,11 @@ class DeleteAction extends AssetActionBuilder {
|
|||
final assetService = ref.read(assetServiceProvider);
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (_) =>
|
||||
const ConfirmDialog(title: 'delete_dialog_title', content: 'delete_dialog_alert', ok: 'delete_permanently'),
|
||||
builder: (_) => ConfirmDialog(
|
||||
title: context.t.delete_dialog_title,
|
||||
content: context.t.delete_dialog_alert,
|
||||
ok: context.t.delete_permanently,
|
||||
),
|
||||
);
|
||||
if (confirmed != true || !context.mounted) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ class CleanupPreviewPage extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('cleanup_preview_title'.t(context: context, args: {'count': assets.length.toString()})),
|
||||
title: Text(context.t.cleanup_preview_title(count: assets.length)),
|
||||
centerTitle: true,
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import 'package:auto_route/auto_route.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.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/pages/common/download_panel.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/download.provider.dart';
|
||||
|
||||
|
|
@ -21,10 +21,7 @@ class DownloadInfoPage extends ConsumerWidget {
|
|||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("download".t(context: context)),
|
||||
actions: const [],
|
||||
),
|
||||
appBar: AppBar(title: Text(context.t.download), actions: const []),
|
||||
body: ListView.builder(
|
||||
physics: const ClampingScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
|
|
@ -49,7 +46,7 @@ class DownloadInfoPage extends ConsumerWidget {
|
|||
},
|
||||
style: OutlinedButton.styleFrom(side: BorderSide(color: context.colorScheme.primary)),
|
||||
child: Text(
|
||||
'clear_all'.t(context: context),
|
||||
context.t.clear_all,
|
||||
style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
|
|
@ -28,10 +28,7 @@ class DriftFavoritePage extends StatelessWidget {
|
|||
}),
|
||||
],
|
||||
child: Timeline(
|
||||
appBar: MesmerizingSliverAppBar(
|
||||
title: 'favorites'.t(context: context),
|
||||
icon: Icons.favorite_outline,
|
||||
),
|
||||
appBar: MesmerizingSliverAppBar(title: context.t.favorites, icon: Icons.favorite_outline),
|
||||
bottomSheet: const FavoriteBottomSheet(),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/pages/common/large_leading_tile.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
|
|
@ -62,10 +62,10 @@ class _PlaceSliverAppBar extends HookWidget {
|
|||
onTapOutside: (_) => searchFocusNode.unfocus(),
|
||||
onChanged: (value) => search.value = value,
|
||||
filled: true,
|
||||
hintText: 'filter_places'.t(context: context),
|
||||
hintText: context.t.filter_places,
|
||||
autofocus: true,
|
||||
)
|
||||
: Text('places'.t(context: context)),
|
||||
: Text(context.t.places),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(search.value != null ? Icons.close : Icons.search),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/widgets.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/timeline/timeline.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
|
|
@ -26,7 +26,7 @@ class DriftRecentlyAddedPage extends StatelessWidget {
|
|||
return timelineService;
|
||||
}),
|
||||
],
|
||||
child: Timeline(appBar: MesmerizingSliverAppBar(title: 'recently_added'.t())),
|
||||
child: Timeline(appBar: MesmerizingSliverAppBar(title: context.t.recently_added)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/widgets.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/timeline/timeline.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
|
|
@ -26,7 +26,7 @@ class DriftRecentlyTakenPage extends StatelessWidget {
|
|||
return timelineService;
|
||||
}),
|
||||
],
|
||||
child: Timeline(appBar: MesmerizingSliverAppBar(title: 'recently_taken'.t())),
|
||||
child: Timeline(appBar: MesmerizingSliverAppBar(title: context.t.recently_taken)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import 'package:immich_mobile/domain/models/config/slideshow_config.dart';
|
|||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/scroll_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/pages/common/settings.page.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||
|
|
@ -411,7 +411,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
|
|||
children: [
|
||||
AppBar(
|
||||
backgroundColor: context.scaffoldBackgroundColor,
|
||||
title: Text("slideshow".t(context: context)),
|
||||
title: Text(context.t.slideshow),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: _paused ? _play : _pause,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
|
@ -9,6 +8,7 @@ import 'package:immich_mobile/domain/models/album/album.model.dart';
|
|||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/remote_album.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
|
|
@ -86,7 +86,7 @@ class DriftUserSelectionPage extends HookConsumerWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'suggestions'.tr(),
|
||||
context.t.suggestions,
|
||||
style: const TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
|
|
@ -118,7 +118,7 @@ class DriftUserSelectionPage extends HookConsumerWidget {
|
|||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('invite_to_album').tr(),
|
||||
title: Text(context.t.invite_to_album),
|
||||
elevation: 0,
|
||||
centerTitle: false,
|
||||
leading: IconButton(
|
||||
|
|
@ -130,7 +130,7 @@ class DriftUserSelectionPage extends HookConsumerWidget {
|
|||
actions: [
|
||||
TextButton(
|
||||
onPressed: sharedUsersList.value.isEmpty ? null : () => addNewUsersHandler(),
|
||||
child: const Text("add", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(),
|
||||
child: Text(context.t.add, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/widgets.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/timeline/timeline.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
|
|
@ -26,7 +26,7 @@ class DriftVideoPage extends StatelessWidget {
|
|||
return timelineService;
|
||||
}),
|
||||
],
|
||||
child: Timeline(appBar: MesmerizingSliverAppBar(title: 'videos'.t())),
|
||||
child: Timeline(appBar: MesmerizingSliverAppBar(title: context.t.videos)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||
import 'package:immich_mobile/constants/aspect_ratios.dart';
|
||||
import 'package:immich_mobile/domain/models/asset_edit.model.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/pages/edit/editor.provider.dart';
|
||||
import 'package:immich_mobile/providers/theme.provider.dart';
|
||||
import 'package:immich_mobile/theme/theme_data.dart';
|
||||
|
|
@ -63,14 +64,14 @@ class _DriftEditImagePageState extends ConsumerState<DriftEditImagePage> with Ti
|
|||
return;
|
||||
}
|
||||
|
||||
ImmichToast.show(context: context, msg: 'success'.tr(), toastType: ToastType.success);
|
||||
ImmichToast.show(context: context, msg: context.t.success, toastType: ToastType.success);
|
||||
Navigator.of(context).pop();
|
||||
} catch (e) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImmichToast.show(context: context, msg: 'error_title'.tr(), toastType: ToastType.error);
|
||||
ImmichToast.show(context: context, msg: context.t.error_title, toastType: ToastType.error);
|
||||
} finally {
|
||||
ref.read(editorStateProvider.notifier).setIsEditing(false);
|
||||
}
|
||||
|
|
@ -80,17 +81,17 @@ class _DriftEditImagePageState extends ConsumerState<DriftEditImagePage> with Ti
|
|||
return showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('editor_discard_edits_title'.tr()),
|
||||
content: Text('editor_discard_edits_prompt'.tr()),
|
||||
title: Text(context.t.editor_discard_edits_title),
|
||||
content: Text(context.t.editor_discard_edits_prompt),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
style: ButtonStyle(
|
||||
foregroundColor: WidgetStateProperty.all(context.themeData.colorScheme.onSurfaceVariant),
|
||||
),
|
||||
child: Text('cancel'.tr()),
|
||||
child: Text(context.t.cancel),
|
||||
),
|
||||
TextButton(onPressed: () => Navigator.of(context).pop(true), child: Text('confirm'.tr())),
|
||||
TextButton(onPressed: () => Navigator.of(context).pop(true), child: Text(context.t.confirm)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
@ -116,7 +117,7 @@ class _DriftEditImagePageState extends ConsumerState<DriftEditImagePage> with Ti
|
|||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.black,
|
||||
title: Text("edit".tr()),
|
||||
title: Text(context.t.edit),
|
||||
leading: ImmichCloseButton(onPressed: () => Navigator.of(context).maybePop()),
|
||||
actions: [_SaveEditsButton(onSave: _saveEditedImage)],
|
||||
),
|
||||
|
|
@ -336,7 +337,7 @@ class _ResetEditsButton extends ConsumerWidget {
|
|||
final editorNotifier = ref.watch(editorStateProvider.notifier);
|
||||
|
||||
return ImmichTextButton(
|
||||
labelText: 'reset'.tr(),
|
||||
labelText: context.t.reset,
|
||||
onPressed: editorNotifier.resetEdits,
|
||||
variant: ImmichVariant.ghost,
|
||||
expanded: false,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/domain/models/feature_message.model.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
|
|
@ -60,10 +59,10 @@ class _HighlightCard extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(highlight.titleKey.tr(), style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600)),
|
||||
Text(highlight.title(context.t), style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600)),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
highlight.bodyKey.tr(),
|
||||
highlight.body(context.t),
|
||||
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceVariant),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import 'dart:async';
|
|||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:crop_image/crop_image.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:image_picker/image_picker.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/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
|
|
@ -93,7 +93,7 @@ class _ProfilePictureCropPageState extends ConsumerState<ProfilePictureCropPage>
|
|||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'profile_picture_set'.tr(),
|
||||
msg: context.t.profile_picture_set,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
toastType: ToastType.success,
|
||||
);
|
||||
|
|
@ -102,7 +102,7 @@ class _ProfilePictureCropPageState extends ConsumerState<ProfilePictureCropPage>
|
|||
} else {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'errors.unable_to_set_profile_picture'.tr(),
|
||||
msg: context.t.errors.unable_to_set_profile_picture,
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
|
|
@ -114,7 +114,7 @@ class _ProfilePictureCropPageState extends ConsumerState<ProfilePictureCropPage>
|
|||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'errors.unable_to_set_profile_picture'.tr(),
|
||||
msg: context.t.errors.unable_to_set_profile_picture,
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
|
|
@ -135,7 +135,7 @@ class _ProfilePictureCropPageState extends ConsumerState<ProfilePictureCropPage>
|
|||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: context.scaffoldBackgroundColor,
|
||||
title: Text("set_profile_picture".tr()),
|
||||
title: Text(context.t.set_profile_picture),
|
||||
leading: _isLoading ? null : const ImmichCloseButton(),
|
||||
actions: [
|
||||
if (_isLoading)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import 'package:immich_mobile/domain/models/tag.model.dart';
|
|||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.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/search/search_filter.model.dart';
|
||||
import 'package:immich_mobile/presentation/pages/search/paginated_search.provider.dart';
|
||||
|
|
@ -48,9 +47,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
serverFeatures.smartSearch ? TextSearchType.context : TextSearchType.filename,
|
||||
);
|
||||
final searchHintText = useState<String>(
|
||||
serverFeatures.smartSearch
|
||||
? 'sunrise_on_the_beach'.t(context: context)
|
||||
: 'file_name_or_extension'.t(context: context),
|
||||
serverFeatures.smartSearch ? context.t.sunrise_on_the_beach : context.t.file_name_or_extension,
|
||||
);
|
||||
final textSearchController = useTextEditingController();
|
||||
final filter = useState<SearchFilter>(
|
||||
|
|
@ -142,7 +139,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
}
|
||||
|
||||
void handleApply() {
|
||||
final label = people.map((e) => e.name != '' ? e.name : 'no_name'.t(context: context)).join(', ');
|
||||
final label = people.map((e) => e.name != '' ? e.name : context.t.no_name).join(', ');
|
||||
peopleCurrentFilterWidget.value = label.isNotEmpty ? Text(label, style: context.textTheme.labelLarge) : null;
|
||||
search(filter.value.copyWith(people: people));
|
||||
}
|
||||
|
|
@ -154,7 +151,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
child: FractionallySizedBox(
|
||||
heightFactor: 0.8,
|
||||
child: FilterBottomSheetScaffold(
|
||||
title: 'search_filter_people_title'.t(context: context),
|
||||
title: context.t.search_filter_people_title,
|
||||
expanded: true,
|
||||
onSearch: handleApply,
|
||||
onClear: handleClear,
|
||||
|
|
@ -191,7 +188,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
child: FractionallySizedBox(
|
||||
heightFactor: 0.8,
|
||||
child: FilterBottomSheetScaffold(
|
||||
title: 'search_filter_tags_title'.t(context: context),
|
||||
title: context.t.search_filter_tags_title,
|
||||
expanded: true,
|
||||
onSearch: handleApply,
|
||||
onClear: handleClear,
|
||||
|
|
@ -232,7 +229,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
child: FilterBottomSheetScaffold(
|
||||
title: 'search_filter_location_title'.t(context: context),
|
||||
title: context.t.search_filter_location_title,
|
||||
onSearch: handleApply,
|
||||
onClear: handleClear,
|
||||
child: Padding(
|
||||
|
|
@ -277,7 +274,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
child: FilterBottomSheetScaffold(
|
||||
title: 'search_filter_camera_title'.t(context: context),
|
||||
title: context.t.search_filter_camera_title,
|
||||
onSearch: handleApply,
|
||||
onClear: handleClear,
|
||||
child: Padding(
|
||||
|
|
@ -333,14 +330,14 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
lastDate: lastDate,
|
||||
currentDate: DateTime.now(),
|
||||
initialDateRange: dateRange,
|
||||
helpText: 'search_filter_date_title'.t(context: context),
|
||||
cancelText: 'cancel'.t(context: context),
|
||||
confirmText: 'select'.t(context: context),
|
||||
saveText: 'save'.t(context: context),
|
||||
errorFormatText: 'invalid_date_format'.t(context: context),
|
||||
errorInvalidText: 'invalid_date'.t(context: context),
|
||||
fieldStartHintText: 'start_date'.t(context: context),
|
||||
fieldEndHintText: 'end_date'.t(context: context),
|
||||
helpText: context.t.search_filter_date_title,
|
||||
cancelText: context.t.cancel,
|
||||
confirmText: context.t.select,
|
||||
saveText: context.t.save,
|
||||
errorFormatText: context.t.invalid_date_format,
|
||||
errorInvalidText: context.t.invalid_date,
|
||||
fieldStartHintText: context.t.start_date,
|
||||
fieldEndHintText: context.t.end_date,
|
||||
initialEntryMode: DatePickerEntryMode.calendar,
|
||||
keyboardType: TextInputType.text,
|
||||
);
|
||||
|
|
@ -357,7 +354,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
showFilterBottomSheet(
|
||||
context: context,
|
||||
child: FilterBottomSheetScaffold(
|
||||
title: "pick_date_range".tr(),
|
||||
title: context.t.pick_date_range,
|
||||
expanded: true,
|
||||
onClear: () => datePicked(null),
|
||||
child: QuickDatePicker(
|
||||
|
|
@ -392,7 +389,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
void handleApply() {
|
||||
mediaTypeCurrentFilterWidget.value = mediaType != AssetType.other
|
||||
? Text(
|
||||
mediaType == AssetType.image ? 'image'.t(context: context) : 'video'.t(context: context),
|
||||
mediaType == AssetType.image ? context.t.image : context.t.video,
|
||||
style: context.textTheme.labelLarge,
|
||||
)
|
||||
: null;
|
||||
|
|
@ -403,7 +400,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
showFilterBottomSheet(
|
||||
context: context,
|
||||
child: FilterBottomSheetScaffold(
|
||||
title: 'search_filter_media_type_title'.t(context: context),
|
||||
title: context.t.search_filter_media_type_title,
|
||||
onSearch: handleApply,
|
||||
onClear: handleClear,
|
||||
child: MediaTypePicker(onSelect: handleOnSelected, filter: filter.value.mediaType),
|
||||
|
|
@ -427,10 +424,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
|
||||
void handleApply() {
|
||||
ratingCurrentFilterWidget.value = rating.rating.isSome
|
||||
? Text(
|
||||
'rating_count'.t(args: {'count': rating.rating.unwrapOrNull ?? 0}),
|
||||
style: context.textTheme.labelLarge,
|
||||
)
|
||||
? Text(context.t.rating_count(count: rating.rating.unwrapOrNull ?? 0), style: context.textTheme.labelLarge)
|
||||
: null;
|
||||
search(filter.value.copyWith(rating: rating));
|
||||
}
|
||||
|
|
@ -440,7 +434,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
context: context,
|
||||
isScrollControlled: true,
|
||||
child: FilterBottomSheetScaffold(
|
||||
title: 'rating'.t(context: context),
|
||||
title: context.t.rating,
|
||||
onSearch: handleApply,
|
||||
onClear: handleClear,
|
||||
child: StarRatingPicker(onSelect: handleOnSelected, filter: filter.value.rating),
|
||||
|
|
@ -472,9 +466,9 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
|
||||
void handleApply() {
|
||||
final filterText = [
|
||||
if (display.isNotInAlbum) 'search_filter_display_option_not_in_album'.t(context: context),
|
||||
if (display.isArchive) 'archive'.t(context: context),
|
||||
if (display.isFavorite) 'favorite'.t(context: context),
|
||||
if (display.isNotInAlbum) context.t.search_filter_display_option_not_in_album,
|
||||
if (display.isArchive) context.t.archive,
|
||||
if (display.isFavorite) context.t.favorite,
|
||||
];
|
||||
displayOptionCurrentFilterWidget.value = filterText.isNotEmpty
|
||||
? Text(filterText.join(', '), style: context.textTheme.labelLarge)
|
||||
|
|
@ -486,7 +480,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
showFilterBottomSheet(
|
||||
context: context,
|
||||
child: FilterBottomSheetScaffold(
|
||||
title: 'display_options'.t(context: context),
|
||||
title: context.t.display_options,
|
||||
onSearch: handleApply,
|
||||
onClear: handleClear,
|
||||
child: DisplayOptionPicker(onSelect: handleOnSelect, filter: filter.value.display),
|
||||
|
|
@ -534,7 +528,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
}
|
||||
},
|
||||
icon: const Icon(Icons.more_vert_rounded),
|
||||
tooltip: 'show_text_search_menu'.tr(),
|
||||
tooltip: context.t.show_text_search_menu,
|
||||
);
|
||||
},
|
||||
menuChildren: [
|
||||
|
|
@ -544,7 +538,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
child: ListTile(
|
||||
leading: const Icon(Icons.image_search_rounded),
|
||||
title: Text(
|
||||
'search_by_context'.t(context: context),
|
||||
context.t.search_by_context,
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: textSearchType.value == TextSearchType.context ? context.colorScheme.primary : null,
|
||||
|
|
@ -555,7 +549,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
),
|
||||
onPressed: () {
|
||||
textSearchType.value = TextSearchType.context;
|
||||
searchHintText.value = 'sunrise_on_the_beach'.t(context: context);
|
||||
searchHintText.value = context.t.sunrise_on_the_beach;
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
@ -563,7 +557,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
child: ListTile(
|
||||
leading: const Icon(Icons.abc_rounded),
|
||||
title: Text(
|
||||
'search_filter_filename'.t(context: context),
|
||||
context.t.search_filter_filename,
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: textSearchType.value == TextSearchType.filename ? context.colorScheme.primary : null,
|
||||
|
|
@ -574,14 +568,14 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
),
|
||||
onPressed: () {
|
||||
textSearchType.value = TextSearchType.filename;
|
||||
searchHintText.value = 'file_name_or_extension'.t(context: context);
|
||||
searchHintText.value = context.t.file_name_or_extension;
|
||||
},
|
||||
),
|
||||
MenuItemButton(
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.text_snippet_outlined),
|
||||
title: Text(
|
||||
'search_by_description'.t(context: context),
|
||||
context.t.search_by_description,
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: textSearchType.value == TextSearchType.description ? context.colorScheme.primary : null,
|
||||
|
|
@ -592,7 +586,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
),
|
||||
onPressed: () {
|
||||
textSearchType.value = TextSearchType.description;
|
||||
searchHintText.value = 'search_by_description_example'.t(context: context);
|
||||
searchHintText.value = context.t.search_by_description_example;
|
||||
},
|
||||
),
|
||||
FeatureCheck(
|
||||
|
|
@ -601,7 +595,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
child: ListTile(
|
||||
leading: const Icon(Icons.document_scanner_outlined),
|
||||
title: Text(
|
||||
'search_by_ocr'.t(context: context),
|
||||
context.t.search_by_ocr,
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: textSearchType.value == TextSearchType.ocr ? context.colorScheme.primary : null,
|
||||
|
|
@ -612,7 +606,7 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
),
|
||||
onPressed: () {
|
||||
textSearchType.value = TextSearchType.ocr;
|
||||
searchHintText.value = 'search_by_ocr_example'.t(context: context);
|
||||
searchHintText.value = context.t.search_by_ocr_example;
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
@ -663,52 +657,52 @@ class DriftSearchPage extends HookConsumerWidget {
|
|||
SearchFilterChip(
|
||||
icon: Icons.people_alt_outlined,
|
||||
onTap: showPeoplePicker,
|
||||
label: 'people'.t(context: context),
|
||||
label: context.t.people,
|
||||
currentFilter: peopleCurrentFilterWidget.value,
|
||||
),
|
||||
SearchFilterChip(
|
||||
icon: Icons.location_on_outlined,
|
||||
onTap: showLocationPicker,
|
||||
label: 'search_filter_location'.t(context: context),
|
||||
label: context.t.search_filter_location,
|
||||
currentFilter: locationCurrentFilterWidget.value,
|
||||
),
|
||||
if (userPreferences.valueOrNull?.tagsEnabled ?? false)
|
||||
SearchFilterChip(
|
||||
icon: Icons.sell_outlined,
|
||||
onTap: showTagPicker,
|
||||
label: 'tags'.t(context: context),
|
||||
label: context.t.tags,
|
||||
currentFilter: tagCurrentFilterWidget.value,
|
||||
),
|
||||
SearchFilterChip(
|
||||
icon: Icons.camera_alt_outlined,
|
||||
onTap: showCameraPicker,
|
||||
label: 'camera'.t(context: context),
|
||||
label: context.t.camera,
|
||||
currentFilter: cameraCurrentFilterWidget.value,
|
||||
),
|
||||
SearchFilterChip(
|
||||
icon: Icons.date_range_outlined,
|
||||
onTap: showQuickDatePicker,
|
||||
label: 'search_filter_date'.t(context: context),
|
||||
label: context.t.search_filter_date,
|
||||
currentFilter: dateRangeCurrentFilterWidget.value,
|
||||
),
|
||||
SearchFilterChip(
|
||||
key: const Key('media_type_chip'),
|
||||
icon: Icons.video_collection_outlined,
|
||||
onTap: showMediaTypePicker,
|
||||
label: 'search_filter_media_type'.t(context: context),
|
||||
label: context.t.search_filter_media_type,
|
||||
currentFilter: mediaTypeCurrentFilterWidget.value,
|
||||
),
|
||||
if (userPreferences.valueOrNull?.ratingsEnabled ?? false)
|
||||
SearchFilterChip(
|
||||
icon: Icons.star_outline_rounded,
|
||||
onTap: showStarRatingPicker,
|
||||
label: 'search_filter_star_rating'.t(context: context),
|
||||
label: context.t.search_filter_star_rating,
|
||||
currentFilter: ratingCurrentFilterWidget.value,
|
||||
),
|
||||
SearchFilterChip(
|
||||
icon: Icons.display_settings_outlined,
|
||||
onTap: showDisplayOptionPicker,
|
||||
label: 'search_filter_display_options'.t(context: context),
|
||||
label: context.t.search_filter_display_options,
|
||||
currentFilter: displayOptionCurrentFilterWidget.value,
|
||||
),
|
||||
],
|
||||
|
|
@ -772,7 +766,7 @@ class _SearchResultGrid extends ConsumerWidget {
|
|||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'search_no_more_result'.t(context: context),
|
||||
context.t.search_no_more_result,
|
||||
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceVariant),
|
||||
),
|
||||
),
|
||||
|
|
@ -837,7 +831,7 @@ class _SearchNoResults extends StatelessWidget {
|
|||
Icon(Icons.search_off_rounded, size: 72, color: context.colorScheme.onSurfaceVariant),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
'search_no_result'.t(context: context),
|
||||
context.t.search_no_result,
|
||||
textAlign: TextAlign.center,
|
||||
style: context.textTheme.bodyLarge?.copyWith(color: context.colorScheme.onSurfaceVariant),
|
||||
),
|
||||
|
|
@ -865,9 +859,7 @@ class _SearchSuggestions extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Center(
|
||||
child: Text('search_page_search_photos_videos'.t(context: context), style: context.textTheme.labelLarge),
|
||||
),
|
||||
Center(child: Text(context.t.search_page_search_photos_videos, style: context.textTheme.labelLarge)),
|
||||
const SizedBox(height: 32),
|
||||
const Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: _QuickLinkList()),
|
||||
],
|
||||
|
|
@ -900,7 +892,7 @@ class _QuickLinkList extends StatelessWidget {
|
|||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
_QuickLink(
|
||||
title: 'recently_taken'.t(context: context),
|
||||
title: context.t.recently_taken,
|
||||
icon: Icons.schedule_outlined,
|
||||
isTop: true,
|
||||
onTap: () => context.pushRoute(const DriftRecentlyTakenRoute()),
|
||||
|
|
@ -911,12 +903,12 @@ class _QuickLinkList extends StatelessWidget {
|
|||
onTap: () => context.pushRoute(const DriftRecentlyAddedRoute()),
|
||||
),
|
||||
_QuickLink(
|
||||
title: 'videos'.t(context: context),
|
||||
title: context.t.videos,
|
||||
icon: Icons.play_circle_outline_rounded,
|
||||
onTap: () => context.pushRoute(const DriftVideoRoute()),
|
||||
),
|
||||
_QuickLink(
|
||||
title: 'favorites'.t(context: context),
|
||||
title: context.t.favorites,
|
||||
icon: Icons.favorite_border_rounded,
|
||||
isBottom: true,
|
||||
onTap: () => context.pushRoute(const DriftFavoriteRoute()),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:hooks_riverpod/hooks_riverpod.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/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/archive.action.dart';
|
||||
import 'package:immich_mobile/presentation/actions/asset_debug.action.dart';
|
||||
|
|
@ -43,28 +43,25 @@ class FavoriteBottomSheet extends ConsumerWidget {
|
|||
}
|
||||
|
||||
if (selectedAssets.length != remoteAssets.length) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'add_to_album_bottom_sheet_some_local_assets'.t(context: context),
|
||||
);
|
||||
ImmichToast.show(context: context, msg: context.t.add_to_album_bottom_sheet_some_local_assets);
|
||||
}
|
||||
|
||||
// Only report the failure when nothing was added; if some succeeded we show "added".
|
||||
if (result.added > 0) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'add_to_album_bottom_sheet_added'.t(args: {"album": album.name}),
|
||||
msg: context.t.add_to_album_bottom_sheet_added(album: album.name),
|
||||
);
|
||||
} else if (result.failed > 0) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'assets_cannot_be_added_to_album_count'.t(context: context, args: {'count': result.failed}),
|
||||
msg: context.t.assets_cannot_be_added_to_album_count(count: result.failed),
|
||||
toastType: ToastType.error,
|
||||
);
|
||||
} else {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'add_to_album_bottom_sheet_already_exists'.t(args: {"album": album.name}),
|
||||
msg: context.t.add_to_album_bottom_sheet_already_exists(album: album.name),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.widget.dart';
|
||||
import 'package:immich_mobile/presentation/actions/archive.action.dart';
|
||||
import 'package:immich_mobile/presentation/actions/asset_debug.action.dart';
|
||||
|
|
@ -54,14 +54,14 @@ class _GeneralBottomSheetState extends ConsumerState<GeneralBottomSheet> {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: result.count == 0
|
||||
? 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name})
|
||||
: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}),
|
||||
? context.t.add_to_album_bottom_sheet_already_exists(album: album.name)
|
||||
: context.t.add_to_album_bottom_sheet_added(album: album.name),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.widget.dart';
|
||||
import 'package:immich_mobile/presentation/actions/asset_debug.action.dart';
|
||||
import 'package:immich_mobile/presentation/actions/download.action.dart';
|
||||
|
|
@ -44,15 +44,15 @@ class _PartnerDetailBottomSheetState extends ConsumerState<PartnerDetailBottomSh
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: result.count == 0
|
||||
? 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name})
|
||||
: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}),
|
||||
? context.t.add_to_album_bottom_sheet_already_exists(album: album.name)
|
||||
: context.t.add_to_album_bottom_sheet_added(album: album.name),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/domain/models/feature_message.model.dart';
|
||||
|
|
@ -263,12 +262,12 @@ class _FeaturePage extends StatelessWidget {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
highlight.titleKey.tr(),
|
||||
highlight.title(context.t),
|
||||
style: context.textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w700, fontSize: 24),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
highlight.bodyKey.tr(),
|
||||
highlight.body(context.t),
|
||||
style: context.textTheme.bodyLarge?.copyWith(color: scheme.onSurfaceVariant, height: 1.4),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
sealed class DateFilterInputModel {
|
||||
DateTimeRange<DateTime> asDateTimeRange();
|
||||
|
|
@ -13,12 +13,9 @@ sealed class DateFilterInputModel {
|
|||
if (date.end.difference(date.start).inHours < 24) {
|
||||
return DateFormat.yMMMd().format(date.start.toLocal());
|
||||
} else {
|
||||
return 'search_filter_date_interval'.t(
|
||||
context: context,
|
||||
args: {
|
||||
"start": DateFormat.yMMMd().format(date.start.toLocal()),
|
||||
"end": DateFormat.yMMMd().format(date.end.toLocal()),
|
||||
},
|
||||
return context.t.search_filter_date_interval(
|
||||
start: DateFormat.yMMMd().format(date.start.toLocal()),
|
||||
end: DateFormat.yMMMd().format(date.end.toLocal()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +35,7 @@ class RecentMonthRangeFilter extends DateFilterInputModel {
|
|||
|
||||
@override
|
||||
String asHumanReadable(BuildContext context) {
|
||||
return 'last_months'.t(context: context, args: {"count": monthDelta.toString()});
|
||||
return context.t.last_months(count: monthDelta);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +59,7 @@ class YearFilter extends DateFilterInputModel {
|
|||
|
||||
@override
|
||||
String asHumanReadable(BuildContext context) {
|
||||
return 'in_year'.tr(namedArgs: {"year": year.toString()});
|
||||
return context.t.in_year(year: year);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,14 +118,13 @@ class QuickDatePicker extends HookWidget {
|
|||
return null;
|
||||
}
|
||||
|
||||
Text _monthLabel(BuildContext context, int monthsFromNow) =>
|
||||
const Text('last_months').t(context: context, args: {"count": monthsFromNow.toString()});
|
||||
Text _monthLabel(BuildContext context, int monthsFromNow) => Text(context.t.last_months(count: monthsFromNow));
|
||||
|
||||
Widget _yearPicker(BuildContext context) {
|
||||
final size = MediaQuery.of(context).size;
|
||||
return Row(
|
||||
children: [
|
||||
const Text("in_year_selector").tr(),
|
||||
Text(context.t.in_year_selector),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(
|
||||
child: DropdownMenu(
|
||||
|
|
@ -158,7 +154,7 @@ class QuickDatePicker extends HookWidget {
|
|||
child: IgnorePointer(
|
||||
ignoring: true,
|
||||
child: RadioListTile(
|
||||
title: const Text('pick_custom_range').tr(),
|
||||
title: Text(context.t.pick_custom_range),
|
||||
subtitle: hasPreviousInput ? Text(currentInput!.asHumanReadable(context)) : null,
|
||||
secondary: hasPreviousInput ? const Icon(Icons.edit) : null,
|
||||
value: _QuickPickerType.custom,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
|
||||
|
||||
class DismissibleActivity extends StatelessWidget {
|
||||
|
|
@ -23,9 +24,9 @@ class DismissibleActivity extends StatelessWidget {
|
|||
context: context,
|
||||
builder: (context) => ConfirmDialog(
|
||||
onOk: () {},
|
||||
title: "shared_album_activity_remove_title",
|
||||
content: "shared_album_activity_remove_content",
|
||||
ok: "delete",
|
||||
title: context.t.shared_album_activity_remove_title,
|
||||
content: context.t.shared_album_activity_remove_content,
|
||||
ok: context.t.delete,
|
||||
),
|
||||
)
|
||||
: Future.value(false),
|
||||
|
|
|
|||
|
|
@ -122,9 +122,9 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return ConfirmDialog(
|
||||
title: "app_bar_signout_dialog_title",
|
||||
content: "app_bar_signout_dialog_content",
|
||||
ok: "yes",
|
||||
title: context.t.app_bar_signout_dialog_title,
|
||||
content: context.t.app_bar_signout_dialog_content,
|
||||
ok: context.t.yes,
|
||||
onOk: () async {
|
||||
isLoggingOut.value = true;
|
||||
await ref.read(authProvider.notifier).logout().whenComplete(() => isLoggingOut.value = false);
|
||||
|
|
|
|||
|
|
@ -1,22 +1,15 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
class ConfirmDialog extends StatelessWidget {
|
||||
final Function? onOk;
|
||||
final String title;
|
||||
final String content;
|
||||
final String cancel;
|
||||
final String ok;
|
||||
final String? cancel;
|
||||
final String? ok;
|
||||
|
||||
const ConfirmDialog({
|
||||
super.key,
|
||||
this.onOk,
|
||||
required this.title,
|
||||
required this.content,
|
||||
this.cancel = "cancel",
|
||||
this.ok = "backup_controller_page_background_battery_info_ok",
|
||||
});
|
||||
const ConfirmDialog({super.key, this.onOk, required this.title, required this.content, this.cancel, this.ok});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -27,22 +20,22 @@ class ConfirmDialog extends StatelessWidget {
|
|||
|
||||
return AlertDialog(
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||
title: Text(title).tr(),
|
||||
content: Text(content).tr(),
|
||||
title: Text(title),
|
||||
content: Text(content),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(false),
|
||||
child: Text(
|
||||
cancel,
|
||||
cancel ?? context.t.cancel,
|
||||
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: onOkPressed,
|
||||
child: Text(
|
||||
ok,
|
||||
ok ?? context.t.backup_controller_page_background_battery_info_ok,
|
||||
style: TextStyle(color: context.colorScheme.error, fontWeight: FontWeight.bold),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/websocket.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
|
|
@ -29,13 +29,13 @@ class ChangePasswordForm extends HookConsumerWidget {
|
|||
alignment: WrapAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'change_password'.tr(),
|
||||
context.t.change_password,
|
||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: context.primaryColor),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 24.0),
|
||||
child: Text(
|
||||
'change_password_form_description'.tr(namedArgs: {'name': authState.name}),
|
||||
context.t.change_password_form_description(name: authState.name),
|
||||
style: TextStyle(fontSize: 14, color: context.colorScheme.onSurface, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
|
|
@ -62,7 +62,7 @@ class ChangePasswordForm extends HookConsumerWidget {
|
|||
if (!isSuccess && context.mounted) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "login_password_changed_error".tr(),
|
||||
msg: context.t.login_password_changed_error,
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.TOP,
|
||||
);
|
||||
|
|
@ -82,7 +82,7 @@ class ChangePasswordForm extends HookConsumerWidget {
|
|||
AutoRouter.of(context).back();
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "login_password_changed_success".tr(),
|
||||
msg: context.t.login_password_changed_success,
|
||||
toastType: ToastType.success,
|
||||
gravity: ToastGravity.TOP,
|
||||
);
|
||||
|
|
@ -92,7 +92,7 @@ class ChangePasswordForm extends HookConsumerWidget {
|
|||
TextButton.icon(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => AutoRouter.of(context).back(),
|
||||
label: const Text('back').tr(),
|
||||
label: Text(context.t.back),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -116,9 +116,9 @@ class PasswordInput extends StatelessWidget {
|
|||
obscureText: true,
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'change_password_form_new_password'.tr(),
|
||||
labelText: context.t.change_password_form_new_password,
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: 'change_password_form_new_password'.tr(),
|
||||
hintText: context.t.change_password_form_new_password,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -132,7 +132,7 @@ class ConfirmPasswordInput extends StatelessWidget {
|
|||
|
||||
String? _validateInput(String? email) {
|
||||
if (confirmController.value != originalController.value) {
|
||||
return 'change_password_form_password_mismatch'.tr();
|
||||
return StaticTranslations.instance.change_password_form_password_mismatch;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -143,8 +143,8 @@ class ConfirmPasswordInput extends StatelessWidget {
|
|||
obscureText: true,
|
||||
controller: confirmController,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'change_password_form_confirm_password'.tr(),
|
||||
hintText: 'change_password_form_reenter_new_password'.tr(),
|
||||
labelText: context.t.change_password_form_confirm_password,
|
||||
hintText: context.t.change_password_form_reenter_new_password,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
validator: _validateInput,
|
||||
|
|
@ -166,7 +166,7 @@ class ChangePasswordButton extends StatelessWidget {
|
|||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 25),
|
||||
),
|
||||
onPressed: onPressed,
|
||||
child: Text('change_password'.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||
child: Text(context.t.change_password, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import 'dart:math';
|
|||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||
|
|
@ -14,7 +13,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
|
|
@ -43,20 +42,21 @@ class LoginForm extends HookConsumerWidget {
|
|||
|
||||
final log = Logger('LoginForm');
|
||||
|
||||
String? _validateUrl(String? url) => normalizeAndValidateServerUrl(url) ? null : 'login_form_err_invalid_url'.tr();
|
||||
String? _validateUrl(String? url) =>
|
||||
normalizeAndValidateServerUrl(url) ? null : StaticTranslations.instance.login_form_err_invalid_url;
|
||||
|
||||
String? _validateEmail(String? email) {
|
||||
if (email == null || email == '') {
|
||||
return null;
|
||||
}
|
||||
if (email.endsWith(' ')) {
|
||||
return 'login_form_err_trailing_whitespace'.tr();
|
||||
return StaticTranslations.instance.login_form_err_trailing_whitespace;
|
||||
}
|
||||
if (email.startsWith(' ')) {
|
||||
return 'login_form_err_leading_whitespace'.tr();
|
||||
return StaticTranslations.instance.login_form_err_leading_whitespace;
|
||||
}
|
||||
if (email.contains(' ') || !email.contains('@')) {
|
||||
return 'login_form_err_invalid_email'.tr();
|
||||
return StaticTranslations.instance.login_form_err_invalid_email;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ class LoginForm extends HookConsumerWidget {
|
|||
|
||||
// Guard empty URL
|
||||
if (serverUrl.isEmpty) {
|
||||
ImmichToast.show(context: context, msg: "login_form_server_empty".tr(), toastType: ToastType.error);
|
||||
ImmichToast.show(context: context, msg: context.t.login_form_server_empty, toastType: ToastType.error);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -127,7 +127,7 @@ class LoginForm extends HookConsumerWidget {
|
|||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: e.message ?? 'login_form_api_exception'.tr(),
|
||||
msg: e.message ?? context.t.login_form_api_exception,
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.TOP,
|
||||
);
|
||||
|
|
@ -140,7 +140,7 @@ class LoginForm extends HookConsumerWidget {
|
|||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'login_form_handshake_exception'.tr(),
|
||||
msg: context.t.login_form_handshake_exception,
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.TOP,
|
||||
);
|
||||
|
|
@ -153,7 +153,7 @@ class LoginForm extends HookConsumerWidget {
|
|||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'login_form_server_error'.tr(),
|
||||
msg: context.t.login_form_server_error,
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.TOP,
|
||||
);
|
||||
|
|
@ -210,15 +210,15 @@ class LoginForm extends HookConsumerWidget {
|
|||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||
elevation: 5,
|
||||
title: Text(
|
||||
'manage_media_access_title',
|
||||
context.t.manage_media_access_title,
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: context.primaryColor),
|
||||
).tr(),
|
||||
),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: [
|
||||
const Text('manage_media_access_subtitle', style: TextStyle(fontSize: 14)).tr(),
|
||||
Text(context.t.manage_media_access_subtitle, style: const TextStyle(fontSize: 14)),
|
||||
const SizedBox(height: 4),
|
||||
const Text('manage_media_access_rationale', style: TextStyle(fontSize: 12)).tr(),
|
||||
Text(context.t.manage_media_access_rationale, style: const TextStyle(fontSize: 12)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -226,7 +226,7 @@ class LoginForm extends HookConsumerWidget {
|
|||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(
|
||||
'cancel'.tr(),
|
||||
context.t.cancel,
|
||||
style: TextStyle(fontWeight: FontWeight.w600, color: context.primaryColor),
|
||||
),
|
||||
),
|
||||
|
|
@ -236,7 +236,7 @@ class LoginForm extends HookConsumerWidget {
|
|||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(
|
||||
'manage_media_access_settings'.tr(),
|
||||
context.t.manage_media_access_settings,
|
||||
style: TextStyle(fontWeight: FontWeight.w600, color: context.primaryColor),
|
||||
),
|
||||
),
|
||||
|
|
@ -290,7 +290,7 @@ class LoginForm extends HookConsumerWidget {
|
|||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "login_form_failed_login".tr(),
|
||||
msg: context.t.login_form_failed_login,
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.TOP,
|
||||
);
|
||||
|
|
@ -348,7 +348,7 @@ class LoginForm extends HookConsumerWidget {
|
|||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "login_form_failed_get_oauth_server_config".tr(),
|
||||
msg: context.t.login_form_failed_get_oauth_server_config,
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.TOP,
|
||||
);
|
||||
|
|
@ -404,7 +404,7 @@ class LoginForm extends HookConsumerWidget {
|
|||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "login_form_failed_get_oauth_server_disable".tr(),
|
||||
msg: context.t.login_form_failed_get_oauth_server_disable,
|
||||
toastType: ToastType.info,
|
||||
gravity: ToastGravity.TOP,
|
||||
);
|
||||
|
|
@ -451,19 +451,19 @@ class LoginForm extends HookConsumerWidget {
|
|||
children: [
|
||||
ImmichForm(
|
||||
onSubmit: getServerAuthSettings,
|
||||
submitText: 'next'.t(context: context),
|
||||
submitText: context.t.next,
|
||||
submitIcon: Icons.arrow_forward_rounded,
|
||||
builder: (_, form) => ImmichURLInput(
|
||||
controller: serverEndpointController,
|
||||
label: 'login_form_endpoint_url'.t(context: context),
|
||||
hintText: 'login_form_endpoint_hint'.t(context: context),
|
||||
label: context.t.login_form_endpoint_url,
|
||||
hintText: context.t.login_form_endpoint_hint,
|
||||
validator: _validateUrl,
|
||||
keyboardAction: .next,
|
||||
onSubmit: (_) => form.submit(),
|
||||
),
|
||||
),
|
||||
ImmichTextButton(
|
||||
labelText: 'settings'.t(context: context),
|
||||
labelText: context.t.settings,
|
||||
icon: Icons.settings,
|
||||
variant: ImmichVariant.ghost,
|
||||
onPressed: () => context.pushRoute(const SettingsRoute()),
|
||||
|
|
@ -488,15 +488,15 @@ class LoginForm extends HookConsumerWidget {
|
|||
if (isPasswordLoginEnable.value)
|
||||
ImmichForm(
|
||||
onSubmit: login,
|
||||
submitText: 'login'.t(context: context),
|
||||
submitText: context.t.login,
|
||||
submitIcon: Icons.login_rounded,
|
||||
builder: (context, form) => Column(
|
||||
spacing: ImmichSpacing.md,
|
||||
children: [
|
||||
ImmichTextInput(
|
||||
controller: emailController,
|
||||
label: 'email'.t(context: context),
|
||||
hintText: 'login_form_email_hint'.t(context: context),
|
||||
label: context.t.email,
|
||||
hintText: context.t.login_form_email_hint,
|
||||
validator: _validateEmail,
|
||||
keyboardAction: TextInputAction.next,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
|
|
@ -506,8 +506,8 @@ class LoginForm extends HookConsumerWidget {
|
|||
ImmichPasswordInput(
|
||||
controller: passwordController,
|
||||
focusNode: passwordFocusNode,
|
||||
label: 'password'.t(context: context),
|
||||
hintText: 'login_form_password_hint'.t(context: context),
|
||||
label: context.t.password,
|
||||
hintText: context.t.login_form_password_hint,
|
||||
keyboardAction: TextInputAction.go,
|
||||
onSubmit: (_) => form.submit(),
|
||||
),
|
||||
|
|
@ -526,10 +526,9 @@ class LoginForm extends HookConsumerWidget {
|
|||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
if (!isOauthEnable.value && !isPasswordLoginEnable.value)
|
||||
Center(child: const Text('login_disabled').tr()),
|
||||
if (!isOauthEnable.value && !isPasswordLoginEnable.value) Center(child: Text(context.t.login_disabled)),
|
||||
ImmichTextButton(
|
||||
labelText: 'back'.t(context: context),
|
||||
labelText: context.t.back,
|
||||
icon: Icons.arrow_back,
|
||||
variant: ImmichVariant.ghost,
|
||||
onPressed: () => serverEndpoint.value = null,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/widgets/forms/pin_input.dart';
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ class PinRegistrationForm extends HookConsumerWidget {
|
|||
SizedBox(
|
||||
width: context.width * 0.7,
|
||||
child: Text(
|
||||
'setup_pin_code'.tr(),
|
||||
context.t.setup_pin_code,
|
||||
style: context.textTheme.labelLarge!.copyWith(fontSize: 24),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
|
|
@ -66,7 +66,7 @@ class PinRegistrationForm extends HookConsumerWidget {
|
|||
SizedBox(
|
||||
width: context.width * 0.8,
|
||||
child: Text(
|
||||
'new_pin_code_subtitle'.tr(),
|
||||
context.t.new_pin_code_subtitle,
|
||||
style: context.textTheme.bodyLarge!.copyWith(fontSize: 16),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
|
|
@ -74,7 +74,7 @@ class PinRegistrationForm extends HookConsumerWidget {
|
|||
const SizedBox(height: 32),
|
||||
PinInput(
|
||||
controller: newPinCodeController,
|
||||
label: 'new_pin_code'.tr(),
|
||||
label: context.t.new_pin_code,
|
||||
length: 6,
|
||||
autoFocus: true,
|
||||
hasError: hasError.value,
|
||||
|
|
@ -87,7 +87,7 @@ class PinRegistrationForm extends HookConsumerWidget {
|
|||
const SizedBox(height: 32),
|
||||
PinInput(
|
||||
controller: confirmPinCodeController,
|
||||
label: 'confirm_new_pin_code'.tr(),
|
||||
label: context.t.confirm_new_pin_code,
|
||||
length: 6,
|
||||
hasError: hasError.value,
|
||||
onChanged: (input) {
|
||||
|
|
@ -102,7 +102,7 @@ class PinRegistrationForm extends HookConsumerWidget {
|
|||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ElevatedButton(onPressed: createNewPinCode, child: Text('create'.tr())),
|
||||
child: ElevatedButton(onPressed: createNewPinCode, child: Text(context.t.create)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/widgets/forms/pin_input.dart';
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ class PinVerificationForm extends HookConsumerWidget {
|
|||
SizedBox(
|
||||
width: context.width * 0.7,
|
||||
child: Text(
|
||||
description ?? 'enter_your_pin_code_subtitle'.tr(),
|
||||
description ?? context.t.enter_your_pin_code_subtitle,
|
||||
style: context.textTheme.labelLarge!.copyWith(fontSize: 18),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/search/search_filter.model.dart';
|
||||
import 'package:immich_mobile/providers/search/search_filter.provider.dart';
|
||||
import 'package:immich_mobile/widgets/search/search_filter/common/dropdown.dart';
|
||||
|
|
@ -37,7 +37,7 @@ class CameraPicker extends HookConsumerWidget {
|
|||
AsyncData(:final value) => value.map((e) => DropdownMenuEntry(value: e, label: e)).toList(),
|
||||
_ => [],
|
||||
},
|
||||
label: const Text('make').tr(),
|
||||
label: Text(context.t.make),
|
||||
controller: makeTextController,
|
||||
leadingIcon: const Icon(Icons.photo_camera_rounded),
|
||||
onSelected: (value) {
|
||||
|
|
@ -56,7 +56,7 @@ class CameraPicker extends HookConsumerWidget {
|
|||
AsyncData(:final value) => value.map((e) => DropdownMenuEntry(value: e, label: e)).toList(),
|
||||
_ => [],
|
||||
},
|
||||
label: const Text('model').tr(),
|
||||
label: Text(context.t.model),
|
||||
controller: modelTextController,
|
||||
leadingIcon: const Icon(Icons.camera),
|
||||
onSelected: (value) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/search/search_filter.model.dart';
|
||||
|
||||
enum DisplayOption { notInAlbum, favorite, archive }
|
||||
|
|
@ -23,7 +23,7 @@ class DisplayOptionPicker extends HookWidget {
|
|||
shrinkWrap: true,
|
||||
children: [
|
||||
CheckboxListTile(
|
||||
title: const Text('search_filter_display_option_not_in_album').tr(),
|
||||
title: Text(context.t.search_filter_display_option_not_in_album),
|
||||
value: options.value[DisplayOption.notInAlbum],
|
||||
onChanged: (bool? value) {
|
||||
options.value = {...options.value, DisplayOption.notInAlbum: value!};
|
||||
|
|
@ -31,7 +31,7 @@ class DisplayOptionPicker extends HookWidget {
|
|||
},
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: const Text('favorite').tr(),
|
||||
title: Text(context.t.favorite),
|
||||
value: options.value[DisplayOption.favorite],
|
||||
onChanged: (value) {
|
||||
options.value = {...options.value, DisplayOption.favorite: value!};
|
||||
|
|
@ -39,7 +39,7 @@ class DisplayOptionPicker extends HookWidget {
|
|||
},
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: const Text('archive').tr(),
|
||||
title: Text(context.t.archive),
|
||||
value: options.value[DisplayOption.archive],
|
||||
onChanged: (value) {
|
||||
options.value = {...options.value, DisplayOption.archive: value!};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
class FilterBottomSheetScaffold extends StatelessWidget {
|
||||
const FilterBottomSheetScaffold({
|
||||
|
|
@ -46,7 +46,7 @@ class FilterBottomSheetScaffold extends StatelessWidget {
|
|||
onClear();
|
||||
context.pop();
|
||||
},
|
||||
child: const Text('clear').tr(),
|
||||
child: Text(context.t.clear),
|
||||
),
|
||||
if (onSearch != null) const SizedBox(width: 8),
|
||||
if (onSearch != null)
|
||||
|
|
@ -56,7 +56,7 @@ class FilterBottomSheetScaffold extends StatelessWidget {
|
|||
onSearch!();
|
||||
context.pop();
|
||||
},
|
||||
child: const Text('search_filter_apply').tr(),
|
||||
child: Text(context.t.search_filter_apply),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/search/search_filter.model.dart';
|
||||
import 'package:immich_mobile/providers/search/search_filter.provider.dart';
|
||||
import 'package:immich_mobile/widgets/search/search_filter/common/dropdown.dart';
|
||||
|
|
@ -61,7 +61,7 @@ class LocationPicker extends HookConsumerWidget {
|
|||
AsyncData(:final value) => value.map((e) => DropdownMenuEntry(value: e, label: e)).toList(),
|
||||
_ => [],
|
||||
},
|
||||
label: const Text('country').tr(),
|
||||
label: Text(context.t.country),
|
||||
controller: countryTextController,
|
||||
onSelected: (value) {
|
||||
if (value.toString() == selectedCountry.value) {
|
||||
|
|
@ -80,7 +80,7 @@ class LocationPicker extends HookConsumerWidget {
|
|||
AsyncData(:final value) => value.map((e) => DropdownMenuEntry(value: e, label: e)).toList(),
|
||||
_ => [],
|
||||
},
|
||||
label: const Text('state').tr(),
|
||||
label: Text(context.t.state),
|
||||
controller: stateTextController,
|
||||
onSelected: (value) {
|
||||
if (value.toString() == selectedState.value) {
|
||||
|
|
@ -98,7 +98,7 @@ class LocationPicker extends HookConsumerWidget {
|
|||
AsyncData(:final value) => value.map((e) => DropdownMenuEntry(value: e, label: e)).toList(),
|
||||
_ => [],
|
||||
},
|
||||
label: const Text('city').tr(),
|
||||
label: Text(context.t.city),
|
||||
controller: cityTextController,
|
||||
onSelected: (value) {
|
||||
selectedCity.value = value.toString();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
class MediaTypePicker extends HookWidget {
|
||||
const MediaTypePicker({super.key, required this.onSelect, this.filter});
|
||||
|
|
@ -21,9 +21,9 @@ class MediaTypePicker extends HookWidget {
|
|||
groupValue: selectedMediaType.value,
|
||||
child: Column(
|
||||
children: [
|
||||
RadioListTile(key: const Key("all"), title: const Text("all").tr(), value: AssetType.other),
|
||||
RadioListTile(key: const Key("image"), title: const Text("image").tr(), value: AssetType.image),
|
||||
RadioListTile(key: const Key("video"), title: const Text("video").tr(), value: AssetType.video),
|
||||
RadioListTile(key: const Key("all"), title: Text(context.t.all), value: AssetType.other),
|
||||
RadioListTile(key: const Key("image"), title: Text(context.t.image), value: AssetType.image),
|
||||
RadioListTile(key: const Key("video"), title: Text(context.t.video), value: AssetType.video),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/search/search_filter.model.dart';
|
||||
import 'package:immich_mobile/utils/option.dart';
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ class StarRatingPicker extends HookWidget {
|
|||
6,
|
||||
(index) => RadioListTile<int>(
|
||||
key: Key("star_$index"),
|
||||
title: Text('rating_count'.t(args: {'count': index})),
|
||||
title: Text(context.t.rating_count(count: index)),
|
||||
value: index,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
class SearchRowTitle extends StatelessWidget {
|
||||
const SearchRowTitle({super.key, required this.onViewAllPressed, required this.title});
|
||||
|
|
@ -17,9 +17,9 @@ class SearchRowTitle extends StatelessWidget {
|
|||
TextButton(
|
||||
onPressed: onViewAllPressed,
|
||||
child: Text(
|
||||
'search_page_view_all_button',
|
||||
context.t.search_page_view_all_button,
|
||||
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -173,8 +173,8 @@ class SharedLinkItem extends ConsumerWidget {
|
|||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) => ConfirmDialog(
|
||||
title: "delete_shared_link_dialog_title",
|
||||
content: "confirm_delete_shared_link",
|
||||
title: context.t.delete_shared_link_dialog_title,
|
||||
content: context.t.confirm_delete_shared_link,
|
||||
onOk: () {},
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue