#960 l10n: use dates with western arabic numerals for maghreb arabic locales
This commit is contained in:
parent
5db31476fe
commit
007c917dca
16 changed files with 153 additions and 33 deletions
|
@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file.
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- opening app from launcher always show home page
|
- opening app from launcher always show home page
|
||||||
|
- use dates with western arabic numerals for maghreb arabic locales
|
||||||
- upgraded Flutter to stable v3.19.4
|
- upgraded Flutter to stable v3.19.4
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:aves/model/entry/entry.dart';
|
||||||
import 'package:aves/model/entry/extensions/catalog.dart';
|
import 'package:aves/model/entry/extensions/catalog.dart';
|
||||||
import 'package:aves/model/entry/extensions/props.dart';
|
import 'package:aves/model/entry/extensions/props.dart';
|
||||||
import 'package:aves/model/metadata/date_modifier.dart';
|
import 'package:aves/model/metadata/date_modifier.dart';
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/ref/metadata/exif.dart';
|
import 'package:aves/ref/metadata/exif.dart';
|
||||||
import 'package:aves/ref/metadata/iptc.dart';
|
import 'package:aves/ref/metadata/iptc.dart';
|
||||||
import 'package:aves/ref/metadata/xmp.dart';
|
import 'package:aves/ref/metadata/xmp.dart';
|
||||||
|
@ -121,7 +122,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry {
|
||||||
if (latLng != null && latLng != removalLocation) {
|
if (latLng != null && latLng != removalLocation) {
|
||||||
final latitude = latLng.latitude;
|
final latitude = latLng.latitude;
|
||||||
final longitude = latLng.longitude;
|
final longitude = latLng.longitude;
|
||||||
const locale = 'en_US';
|
const locale = asciiLocale;
|
||||||
final isoLat = '${latitude >= 0 ? '+' : '-'}${NumberFormat('00.0000', locale).format(latitude.abs())}';
|
final isoLat = '${latitude >= 0 ? '+' : '-'}${NumberFormat('00.0000', locale).format(latitude.abs())}';
|
||||||
final isoLon = '${longitude >= 0 ? '+' : '-'}${NumberFormat('000.0000', locale).format(longitude.abs())}';
|
final isoLon = '${longitude >= 0 ? '+' : '-'}${NumberFormat('000.0000', locale).format(longitude.abs())}';
|
||||||
iso6709String = '$isoLat$isoLon/';
|
iso6709String = '$isoLat$isoLon/';
|
||||||
|
|
|
@ -20,6 +20,7 @@ class NamingPattern {
|
||||||
factory NamingPattern.from({
|
factory NamingPattern.from({
|
||||||
required String userPattern,
|
required String userPattern,
|
||||||
required int entryCount,
|
required int entryCount,
|
||||||
|
required String locale,
|
||||||
}) {
|
}) {
|
||||||
final processors = <NamingProcessor>[];
|
final processors = <NamingProcessor>[];
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ class NamingPattern {
|
||||||
switch (processorKey) {
|
switch (processorKey) {
|
||||||
case DateNamingProcessor.key:
|
case DateNamingProcessor.key:
|
||||||
if (processorOptions != null) {
|
if (processorOptions != null) {
|
||||||
processors.add(DateNamingProcessor(processorOptions.trim()));
|
processors.add(DateNamingProcessor(processorOptions.trim(), locale));
|
||||||
}
|
}
|
||||||
case TagsNamingProcessor.key:
|
case TagsNamingProcessor.key:
|
||||||
processors.add(TagsNamingProcessor(processorOptions?.trim() ?? ''));
|
processors.add(TagsNamingProcessor(processorOptions?.trim() ?? ''));
|
||||||
|
@ -156,7 +157,7 @@ class DateNamingProcessor extends NamingProcessor {
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [format.pattern];
|
List<Object?> get props => [format.pattern];
|
||||||
|
|
||||||
DateNamingProcessor(String pattern) : format = DateFormat(pattern);
|
DateNamingProcessor(String pattern, String locale) : format = DateFormat(pattern, locale);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? process(AvesEntry entry, int index, Map<String, dynamic> fieldValues) {
|
String? process(AvesEntry entry, int index, Map<String, dynamic> fieldValues) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ mixin AppSettings on SettingsAccess {
|
||||||
].join(localeSeparator);
|
].join(localeSeparator);
|
||||||
}
|
}
|
||||||
set(SettingKeys.localeKey, tag);
|
set(SettingKeys.localeKey, tag);
|
||||||
_appliedLocale = null;
|
resetAppliedLocale();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Locale> _systemLocalesFallback = [];
|
List<Locale> _systemLocalesFallback = [];
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'package:aves/model/video/profiles/aac.dart';
|
||||||
import 'package:aves/model/video/profiles/h264.dart';
|
import 'package:aves/model/video/profiles/h264.dart';
|
||||||
import 'package:aves/model/video/profiles/hevc.dart';
|
import 'package:aves/model/video/profiles/hevc.dart';
|
||||||
import 'package:aves/ref/languages.dart';
|
import 'package:aves/ref/languages.dart';
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/ref/mime_types.dart';
|
import 'package:aves/ref/mime_types.dart';
|
||||||
import 'package:aves/ref/mp4.dart';
|
import 'package:aves/ref/mp4.dart';
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
|
@ -453,7 +454,7 @@ class VideoMetadataFormatter {
|
||||||
|
|
||||||
static String _formatFilesize(dynamic value) {
|
static String _formatFilesize(dynamic value) {
|
||||||
final size = value is int ? value : int.tryParse(value);
|
final size = value is int ? value : int.tryParse(value);
|
||||||
return size != null ? formatFileSize('en_US', size) : value;
|
return size != null ? formatFileSize(asciiLocale, size) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String _formatLanguage(String value) {
|
static String _formatLanguage(String value) {
|
||||||
|
|
47
lib/ref/locales.dart
Normal file
47
lib/ref/locales.dart
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
const String asciiLocale = 'en_US';
|
||||||
|
|
||||||
|
// cf https://en.wikipedia.org/wiki/Eastern_Arabic_numerals
|
||||||
|
bool shouldUseNativeDigits(Locale? countrifiedLocale) {
|
||||||
|
switch (countrifiedLocale?.toString()) {
|
||||||
|
// Maghreb
|
||||||
|
case 'ar_DZ': // Algeria
|
||||||
|
case 'ar_EH': // Western Sahara
|
||||||
|
case 'ar_LY': // Libya
|
||||||
|
case 'ar_MA': // Morocco
|
||||||
|
case 'ar_MR': // Mauritania
|
||||||
|
case 'ar_TN': // Tunisia
|
||||||
|
return false;
|
||||||
|
// Mashriq
|
||||||
|
case 'ar_AE': // United Arab Emirates
|
||||||
|
case 'ar_BH': // Bahrain
|
||||||
|
case 'ar_EG': // Egypt
|
||||||
|
case 'ar_IQ': // Iraq
|
||||||
|
case 'ar_JO': // Jordan
|
||||||
|
case 'ar_KW': // Kuwait
|
||||||
|
case 'ar_LB': // Lebanon
|
||||||
|
case 'ar_OM': // Oman
|
||||||
|
case 'ar_PS': // Palestinian Territories
|
||||||
|
case 'ar_QA': // Qatar
|
||||||
|
case 'ar_SA': // Saudi Arabia
|
||||||
|
case 'ar_SD': // Sudan
|
||||||
|
case 'ar_SS': // South Sudan
|
||||||
|
case 'ar_SY': // Syria
|
||||||
|
case 'ar_YE': // Yemen
|
||||||
|
return true;
|
||||||
|
// Horn of Africa
|
||||||
|
case 'ar_DJ': // Djibouti
|
||||||
|
case 'ar_ER': // Eritrea
|
||||||
|
case 'ar_KM': // Comoros
|
||||||
|
case 'ar_SO': // Somalia
|
||||||
|
return true;
|
||||||
|
// others
|
||||||
|
case 'ar_IL': // Israel
|
||||||
|
case 'ar_TD': // Chad
|
||||||
|
return true;
|
||||||
|
case null:
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/ref/metadata/xmp.dart';
|
import 'package:aves/ref/metadata/xmp.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:xml/xml.dart';
|
import 'package:xml/xml.dart';
|
||||||
|
@ -60,7 +61,7 @@ class XMP {
|
||||||
return '${offsetMinutes.isNegative ? '-' : '+'}${h.toString().padLeft(2, '0')}:${m.toString().padLeft(2, '0')}';
|
return '${offsetMinutes.isNegative ? '-' : '+'}${h.toString().padLeft(2, '0')}:${m.toString().padLeft(2, '0')}';
|
||||||
}
|
}
|
||||||
|
|
||||||
static String toXmpDate(DateTime date) => '${DateFormat('yyyy-MM-ddTHH:mm:ss').format(date)}${_xmpTimeZoneDesignator(date)}';
|
static String toXmpDate(DateTime date) => '${DateFormat('yyyy-MM-ddTHH:mm:ss', asciiLocale).format(date)}${_xmpTimeZoneDesignator(date)}';
|
||||||
|
|
||||||
static String? getString(
|
static String? getString(
|
||||||
List<XmlNode> nodes,
|
List<XmlNode> nodes,
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'package:aves/app_flavor.dart';
|
||||||
import 'package:aves/flutter_version.dart';
|
import 'package:aves/flutter_version.dart';
|
||||||
import 'package:aves/model/device.dart';
|
import 'package:aves/model/device.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/ref/mime_types.dart';
|
import 'package:aves/ref/mime_types.dart';
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/theme/colors.dart';
|
import 'package:aves/theme/colors.dart';
|
||||||
|
@ -176,7 +177,7 @@ class _BugReportState extends State<BugReport> with FeedbackMixin {
|
||||||
final result = await Process.run('logcat', ['-d']);
|
final result = await Process.run('logcat', ['-d']);
|
||||||
final logs = result.stdout;
|
final logs = result.stdout;
|
||||||
final success = await storageService.createFile(
|
final success = await storageService.createFile(
|
||||||
'aves-logs-${DateFormat('yyyyMMdd_HHmmss').format(DateTime.now())}.txt',
|
'aves-logs-${DateFormat('yyyyMMdd_HHmmss', asciiLocale).format(DateTime.now())}.txt',
|
||||||
MimeTypes.plainText,
|
MimeTypes.plainText,
|
||||||
Uint8List.fromList(utf8.encode(logs)),
|
Uint8List.fromList(utf8.encode(logs)),
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,6 +16,7 @@ import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/model/source/media_store_source.dart';
|
import 'package:aves/model/source/media_store_source.dart';
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/services/accessibility_service.dart';
|
import 'package:aves/services/accessibility_service.dart';
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/theme/colors.dart';
|
import 'package:aves/theme/colors.dart';
|
||||||
|
@ -37,12 +38,14 @@ import 'package:aves/widgets/navigation/tv_rail.dart';
|
||||||
import 'package:aves/widgets/welcome_page.dart';
|
import 'package:aves/widgets/welcome_page.dart';
|
||||||
import 'package:aves_model/aves_model.dart';
|
import 'package:aves_model/aves_model.dart';
|
||||||
import 'package:aves_utils/aves_utils.dart';
|
import 'package:aves_utils/aves_utils.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:dynamic_color/dynamic_color.dart';
|
import 'package:dynamic_color/dynamic_color.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_localization_nn/flutter_localization_nn.dart';
|
import 'package:flutter_localization_nn/flutter_localization_nn.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
import 'package:overlay_support/overlay_support.dart';
|
import 'package:overlay_support/overlay_support.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:screen_brightness/screen_brightness.dart';
|
import 'package:screen_brightness/screen_brightness.dart';
|
||||||
|
@ -158,6 +161,7 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||||
final ValueNotifier<PageTransitionsBuilder> _pageTransitionsBuilderNotifier = ValueNotifier(defaultPageTransitionsBuilder);
|
final ValueNotifier<PageTransitionsBuilder> _pageTransitionsBuilderNotifier = ValueNotifier(defaultPageTransitionsBuilder);
|
||||||
final ValueNotifier<TvMediaQueryModifier?> _tvMediaQueryModifierNotifier = ValueNotifier(null);
|
final ValueNotifier<TvMediaQueryModifier?> _tvMediaQueryModifierNotifier = ValueNotifier(null);
|
||||||
final ValueNotifier<AppMode> _appModeNotifier = ValueNotifier(AppMode.main);
|
final ValueNotifier<AppMode> _appModeNotifier = ValueNotifier(AppMode.main);
|
||||||
|
final ValueNotifier<LocaleOverrides> _localeOverridesNotifier = ValueNotifier(LocaleOverrides.none);
|
||||||
|
|
||||||
// observers are not registered when using the same list object with different items
|
// observers are not registered when using the same list object with different items
|
||||||
// the list itself needs to be reassigned
|
// the list itself needs to be reassigned
|
||||||
|
@ -217,6 +221,7 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||||
Provider<TvRailController>.value(value: _tvRailController),
|
Provider<TvRailController>.value(value: _tvRailController),
|
||||||
DurationsProvider(),
|
DurationsProvider(),
|
||||||
HighlightInfoProvider(),
|
HighlightInfoProvider(),
|
||||||
|
ListenableProvider<ValueNotifier<LocaleOverrides>>.value(value: _localeOverridesNotifier),
|
||||||
],
|
],
|
||||||
child: OverlaySupport(
|
child: OverlaySupport(
|
||||||
child: FutureBuilder<void>(
|
child: FutureBuilder<void>(
|
||||||
|
@ -239,9 +244,6 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||||
),
|
),
|
||||||
builder: (context, s, child) {
|
builder: (context, s, child) {
|
||||||
final (settingsLocale, themeBrightness, enableDynamicColor) = s;
|
final (settingsLocale, themeBrightness, enableDynamicColor) = s;
|
||||||
|
|
||||||
AStyles.updateStylesForLocale(settings.appliedLocale);
|
|
||||||
|
|
||||||
return DynamicColorBuilder(
|
return DynamicColorBuilder(
|
||||||
builder: (lightScheme, darkScheme) {
|
builder: (lightScheme, darkScheme) {
|
||||||
const defaultAccent = AvesColorsData.defaultAccent;
|
const defaultAccent = AvesColorsData.defaultAccent;
|
||||||
|
@ -411,6 +413,33 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeLocales(List<Locale>? locales) {
|
||||||
|
_applyLocale();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _applyLocale() {
|
||||||
|
settings.resetAppliedLocale();
|
||||||
|
|
||||||
|
final appliedLocale = settings.appliedLocale;
|
||||||
|
AStyles.updateStylesForLocale(appliedLocale);
|
||||||
|
|
||||||
|
Locale? countrifiedLocale;
|
||||||
|
if (appliedLocale.countryCode == null) {
|
||||||
|
final languageCode = appliedLocale.languageCode;
|
||||||
|
countrifiedLocale = WidgetsBinding.instance.platformDispatcher.locales.firstWhereOrNull((v) => v.languageCode == languageCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appliedLocale.languageCode == 'ar') {
|
||||||
|
final useNativeDigits = shouldUseNativeDigits(countrifiedLocale);
|
||||||
|
DateFormat.useNativeDigitsByDefaultFor(appliedLocale.toString(), useNativeDigits);
|
||||||
|
DateFormat.useNativeDigitsByDefaultFor(countrifiedLocale.toString(), useNativeDigits);
|
||||||
|
}
|
||||||
|
_localeOverridesNotifier.value = LocaleOverrides(
|
||||||
|
countrifiedLocale: countrifiedLocale,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _getFirstPage({Map? intentData}) => settings.hasAcceptedTerms ? HomePage(intentData: intentData) : const WelcomePage();
|
Widget _getFirstPage({Map? intentData}) => settings.hasAcceptedTerms ? HomePage(intentData: intentData) : const WelcomePage();
|
||||||
|
|
||||||
Size? _getScreenSize(BuildContext context) {
|
Size? _getScreenSize(BuildContext context) {
|
||||||
|
@ -504,7 +533,7 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _monitorSettings() {
|
void _monitorSettings() {
|
||||||
void applyIsInstalledAppAccessAllowed() {
|
void _applyIsInstalledAppAccessAllowed() {
|
||||||
if (settings.isInstalledAppAccessAllowed) {
|
if (settings.isInstalledAppAccessAllowed) {
|
||||||
appInventory.initAppNames();
|
appInventory.initAppNames();
|
||||||
} else {
|
} else {
|
||||||
|
@ -512,9 +541,9 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyDisplayRefreshRateMode() => settings.displayRefreshRateMode.apply();
|
void _applyDisplayRefreshRateMode() => settings.displayRefreshRateMode.apply();
|
||||||
|
|
||||||
void applyMaxBrightness() {
|
void _applyMaxBrightness() {
|
||||||
switch (settings.maxBrightness) {
|
switch (settings.maxBrightness) {
|
||||||
case MaxBrightness.never:
|
case MaxBrightness.never:
|
||||||
case MaxBrightness.viewerOnly:
|
case MaxBrightness.viewerOnly:
|
||||||
|
@ -524,9 +553,9 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyKeepScreenOn() => settings.keepScreenOn.apply();
|
void _applyKeepScreenOn() => settings.keepScreenOn.apply();
|
||||||
|
|
||||||
void applyIsRotationLocked() {
|
void _applyIsRotationLocked() {
|
||||||
if (!settings.isRotationLocked && !settings.useTvLayout) {
|
if (!settings.isRotationLocked && !settings.useTvLayout) {
|
||||||
windowService.requestOrientation();
|
windowService.requestOrientation();
|
||||||
}
|
}
|
||||||
|
@ -545,20 +574,22 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||||
|
|
||||||
final settingStream = settings.updateStream;
|
final settingStream = settings.updateStream;
|
||||||
// app
|
// app
|
||||||
settingStream.where((event) => event.key == SettingKeys.isInstalledAppAccessAllowedKey).listen((_) => applyIsInstalledAppAccessAllowed());
|
settingStream.where((event) => event.key == SettingKeys.isInstalledAppAccessAllowedKey).listen((_) => _applyIsInstalledAppAccessAllowed());
|
||||||
|
settingStream.where((event) => event.key == SettingKeys.localeKey).listen((_) => _applyLocale());
|
||||||
// display
|
// display
|
||||||
settingStream.where((event) => event.key == SettingKeys.displayRefreshRateModeKey).listen((_) => applyDisplayRefreshRateMode());
|
settingStream.where((event) => event.key == SettingKeys.displayRefreshRateModeKey).listen((_) => _applyDisplayRefreshRateMode());
|
||||||
settingStream.where((event) => event.key == SettingKeys.maxBrightnessKey).listen((_) => applyMaxBrightness());
|
settingStream.where((event) => event.key == SettingKeys.maxBrightnessKey).listen((_) => _applyMaxBrightness());
|
||||||
settingStream.where((event) => event.key == SettingKeys.forceTvLayoutKey).listen((_) => applyForceTvLayout());
|
settingStream.where((event) => event.key == SettingKeys.forceTvLayoutKey).listen((_) => applyForceTvLayout());
|
||||||
// navigation
|
// navigation
|
||||||
settingStream.where((event) => event.key == SettingKeys.keepScreenOnKey).listen((_) => applyKeepScreenOn());
|
settingStream.where((event) => event.key == SettingKeys.keepScreenOnKey).listen((_) => _applyKeepScreenOn());
|
||||||
// platform settings
|
// platform settings
|
||||||
settingStream.where((event) => event.key == SettingKeys.platformAccelerometerRotationKey).listen((_) => applyIsRotationLocked());
|
settingStream.where((event) => event.key == SettingKeys.platformAccelerometerRotationKey).listen((_) => _applyIsRotationLocked());
|
||||||
|
|
||||||
applyDisplayRefreshRateMode();
|
_applyLocale();
|
||||||
applyMaxBrightness();
|
_applyDisplayRefreshRateMode();
|
||||||
applyKeepScreenOn();
|
_applyMaxBrightness();
|
||||||
applyIsRotationLocked();
|
_applyKeepScreenOn();
|
||||||
|
_applyIsRotationLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _setupErrorReporting() async {
|
Future<void> _setupErrorReporting() async {
|
||||||
|
@ -632,3 +663,18 @@ class AvesScrollBehavior extends MaterialScrollBehavior {
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef TvMediaQueryModifier = MediaQueryData Function(MediaQueryData);
|
typedef TvMediaQueryModifier = MediaQueryData Function(MediaQueryData);
|
||||||
|
|
||||||
|
class LocaleOverrides extends Equatable {
|
||||||
|
final Locale? countrifiedLocale;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [countrifiedLocale];
|
||||||
|
|
||||||
|
const LocaleOverrides({
|
||||||
|
required this.countrifiedLocale,
|
||||||
|
});
|
||||||
|
|
||||||
|
static const LocaleOverrides none = LocaleOverrides(
|
||||||
|
countrifiedLocale: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -672,8 +672,8 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> with Widge
|
||||||
final newest = firstKey.date;
|
final newest = firstKey.date;
|
||||||
final oldest = lastKey.date;
|
final oldest = lastKey.date;
|
||||||
if (newest != null && oldest != null) {
|
if (newest != null && oldest != null) {
|
||||||
final localeName = context.l10n.localeName;
|
final locale = context.l10n.localeName;
|
||||||
final dateFormat = (newest.difference(oldest).inDays).abs() > 365 ? DateFormat.y(localeName) : DateFormat.MMM(localeName);
|
final dateFormat = (newest.difference(oldest).inDays).abs() > 365 ? DateFormat.y(locale) : DateFormat.MMM(locale);
|
||||||
String? lastLabel;
|
String? lastLabel;
|
||||||
sectionLayouts.forEach((section) {
|
sectionLayouts.forEach((section) {
|
||||||
final date = (section.sectionKey as EntryDateSectionKey).date;
|
final date = (section.sectionKey as EntryDateSectionKey).date;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/utils/file_utils.dart';
|
import 'package:aves/utils/file_utils.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
||||||
|
@ -15,6 +16,8 @@ class _DebugCacheSectionState extends State<DebugCacheSection> with AutomaticKee
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
|
|
||||||
|
final currentSizeBytes = formatFileSize(asciiLocale, imageCache.currentSizeBytes);
|
||||||
|
final maxSizeBytes = formatFileSize(asciiLocale, imageCache.maximumSizeBytes);
|
||||||
return AvesExpansionTile(
|
return AvesExpansionTile(
|
||||||
title: 'Cache',
|
title: 'Cache',
|
||||||
children: [
|
children: [
|
||||||
|
@ -25,7 +28,7 @@ class _DebugCacheSectionState extends State<DebugCacheSection> with AutomaticKee
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('Image cache:\n\t${imageCache.currentSize}/${imageCache.maximumSize} items\n\t${formatFileSize('en_US', imageCache.currentSizeBytes)}/${formatFileSize('en_US', imageCache.maximumSizeBytes)}'),
|
child: Text('Image cache:\n\t${imageCache.currentSize}/${imageCache.maximumSize} items\n\t$currentSizeBytes/$maxSizeBytes'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:aves/model/metadata/trash.dart';
|
||||||
import 'package:aves/model/vaults/details.dart';
|
import 'package:aves/model/vaults/details.dart';
|
||||||
import 'package:aves/model/vaults/vaults.dart';
|
import 'package:aves/model/vaults/vaults.dart';
|
||||||
import 'package:aves/model/video_playback.dart';
|
import 'package:aves/model/video_playback.dart';
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/utils/file_utils.dart';
|
import 'package:aves/utils/file_utils.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
||||||
|
@ -65,7 +66,7 @@ class _DebugAppDatabaseSectionState extends State<DebugAppDatabaseSection> with
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('DB file size: ${formatFileSize('en_US', snapshot.data!)}'),
|
child: Text('DB file size: ${formatFileSize(asciiLocale, snapshot.data!)}'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/utils/file_utils.dart';
|
import 'package:aves/utils/file_utils.dart';
|
||||||
|
@ -47,7 +48,7 @@ class _DebugStorageSectionState extends State<DebugStorageSection> with Automati
|
||||||
'isPrimary': '${v.isPrimary}',
|
'isPrimary': '${v.isPrimary}',
|
||||||
'isRemovable': '${v.isRemovable}',
|
'isRemovable': '${v.isRemovable}',
|
||||||
'state': v.state,
|
'state': v.state,
|
||||||
if (freeSpace != null) 'freeSpace': formatFileSize('en_US', freeSpace),
|
if (freeSpace != null) 'freeSpace': formatFileSize(asciiLocale, freeSpace),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -38,6 +38,7 @@ class RenameEntrySetPage extends StatefulWidget {
|
||||||
class _RenameEntrySetPageState extends State<RenameEntrySetPage> {
|
class _RenameEntrySetPageState extends State<RenameEntrySetPage> {
|
||||||
final TextEditingController _patternTextController = TextEditingController();
|
final TextEditingController _patternTextController = TextEditingController();
|
||||||
final ValueNotifier<NamingPattern> _namingPatternNotifier = ValueNotifier<NamingPattern>(const NamingPattern([]));
|
final ValueNotifier<NamingPattern> _namingPatternNotifier = ValueNotifier<NamingPattern>(const NamingPattern([]));
|
||||||
|
late final String locale;
|
||||||
|
|
||||||
static const int previewMax = 10;
|
static const int previewMax = 10;
|
||||||
static const double thumbnailExtent = 48;
|
static const double thumbnailExtent = 48;
|
||||||
|
@ -51,7 +52,11 @@ class _RenameEntrySetPageState extends State<RenameEntrySetPage> {
|
||||||
super.initState();
|
super.initState();
|
||||||
_patternTextController.text = settings.entryRenamingPattern;
|
_patternTextController.text = settings.entryRenamingPattern;
|
||||||
_patternTextController.addListener(_onUserPatternChanged);
|
_patternTextController.addListener(_onUserPatternChanged);
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
locale = context.l10n.localeName;
|
||||||
_onUserPatternChanged();
|
_onUserPatternChanged();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -229,6 +234,7 @@ class _RenameEntrySetPageState extends State<RenameEntrySetPage> {
|
||||||
_namingPatternNotifier.value = NamingPattern.from(
|
_namingPatternNotifier.value = NamingPattern.from(
|
||||||
userPattern: _patternTextController.text,
|
userPattern: _patternTextController.text,
|
||||||
entryCount: entryCount,
|
entryCount: entryCount,
|
||||||
|
locale: locale,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'dart:typed_data';
|
||||||
import 'package:aves/model/settings/enums/accessibility_animations.dart';
|
import 'package:aves/model/settings/enums/accessibility_animations.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/ref/mime_types.dart';
|
import 'package:aves/ref/mime_types.dart';
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
|
@ -117,7 +118,7 @@ class _SettingsMobilePageState extends State<SettingsMobilePage> with FeedbackMi
|
||||||
final allJsonString = jsonEncode(allMap);
|
final allJsonString = jsonEncode(allMap);
|
||||||
|
|
||||||
final success = await storageService.createFile(
|
final success = await storageService.createFile(
|
||||||
'aves-settings-${DateFormat('yyyyMMdd_HHmmss').format(DateTime.now())}.json',
|
'aves-settings-${DateFormat('yyyyMMdd_HHmmss', asciiLocale).format(DateTime.now())}.json',
|
||||||
MimeTypes.json,
|
MimeTypes.json,
|
||||||
Uint8List.fromList(utf8.encode(allJsonString)),
|
Uint8List.fromList(utf8.encode(allJsonString)),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
import 'package:aves/model/naming_pattern.dart';
|
import 'package:aves/model/naming_pattern.dart';
|
||||||
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
setUpAll(() async {
|
||||||
|
await initializeDateFormatting();
|
||||||
|
});
|
||||||
|
|
||||||
test('mixed processors', () {
|
test('mixed processors', () {
|
||||||
const entryCount = 42;
|
const entryCount = 42;
|
||||||
|
const locale = 'en';
|
||||||
expect(
|
expect(
|
||||||
NamingPattern.from(
|
NamingPattern.from(
|
||||||
userPattern: 'pure literal',
|
userPattern: 'pure literal',
|
||||||
entryCount: entryCount,
|
entryCount: entryCount,
|
||||||
|
locale: locale,
|
||||||
).processors,
|
).processors,
|
||||||
[
|
[
|
||||||
const LiteralNamingProcessor('pure literal'),
|
const LiteralNamingProcessor('pure literal'),
|
||||||
|
@ -17,10 +24,11 @@ void main() {
|
||||||
NamingPattern.from(
|
NamingPattern.from(
|
||||||
userPattern: 'prefix<date,yyyy-MM-ddTHH:mm:ss>suffix',
|
userPattern: 'prefix<date,yyyy-MM-ddTHH:mm:ss>suffix',
|
||||||
entryCount: entryCount,
|
entryCount: entryCount,
|
||||||
|
locale: locale,
|
||||||
).processors,
|
).processors,
|
||||||
[
|
[
|
||||||
const LiteralNamingProcessor('prefix'),
|
const LiteralNamingProcessor('prefix'),
|
||||||
DateNamingProcessor('yyyy-MM-ddTHH:mm:ss'),
|
DateNamingProcessor('yyyy-MM-ddTHH:mm:ss', locale),
|
||||||
const LiteralNamingProcessor('suffix'),
|
const LiteralNamingProcessor('suffix'),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -28,9 +36,10 @@ void main() {
|
||||||
NamingPattern.from(
|
NamingPattern.from(
|
||||||
userPattern: '<date,yyyy-MM-ddTHH:mm:ss> <name>',
|
userPattern: '<date,yyyy-MM-ddTHH:mm:ss> <name>',
|
||||||
entryCount: entryCount,
|
entryCount: entryCount,
|
||||||
|
locale: locale,
|
||||||
).processors,
|
).processors,
|
||||||
[
|
[
|
||||||
DateNamingProcessor('yyyy-MM-ddTHH:mm:ss'),
|
DateNamingProcessor('yyyy-MM-ddTHH:mm:ss', locale),
|
||||||
const LiteralNamingProcessor(' '),
|
const LiteralNamingProcessor(' '),
|
||||||
const NameNamingProcessor(),
|
const NameNamingProcessor(),
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue