l10n: typography fixes for arabic/persian
This commit is contained in:
parent
ea53420c17
commit
dd6258d8ac
18 changed files with 108 additions and 53 deletions
3
devtools_options.yaml
Normal file
3
devtools_options.yaml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
description: This file stores settings for Dart & Flutter DevTools.
|
||||||
|
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||||
|
extensions:
|
|
@ -11,6 +11,7 @@ import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/theme/text.dart';
|
import 'package:aves/theme/text.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/utils/time_utils.dart';
|
import 'package:aves/utils/time_utils.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
extension ExtraAvesEntryProps on AvesEntry {
|
extension ExtraAvesEntryProps on AvesEntry {
|
||||||
bool get isValid => !isMissingAtPath && sizeBytes != 0 && width > 0 && height > 0;
|
bool get isValid => !isMissingAtPath && sizeBytes != 0 && width > 0 && height > 0;
|
||||||
|
@ -51,9 +52,10 @@ extension ExtraAvesEntryProps on AvesEntry {
|
||||||
|
|
||||||
// text
|
// text
|
||||||
|
|
||||||
String get resolutionText {
|
String getResolutionText(String locale) {
|
||||||
final ws = width;
|
final numberFormat = NumberFormat('0', locale);
|
||||||
final hs = height;
|
final ws = numberFormat.format(width);
|
||||||
|
final hs = numberFormat.format(height);
|
||||||
return isRotated ? '$hs${AText.resolutionSeparator}$ws' : '$ws${AText.resolutionSeparator}$hs';
|
return isRotated ? '$hs${AText.resolutionSeparator}$ws' : '$ws${AText.resolutionSeparator}$hs';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,11 @@ extension ExtraCoordinateFormat on CoordinateFormat {
|
||||||
final min = minDecimal.toInt();
|
final min = minDecimal.toInt();
|
||||||
final sec = (minDecimal - min) * 60;
|
final sec = (minDecimal - min) * 60;
|
||||||
|
|
||||||
var minText = NumberFormat('0' * (minuteSecondPadding ? 2 : 1), locale).format(min);
|
final degText = NumberFormat('0', locale).format(deg);
|
||||||
var secText = NumberFormat('${'0' * (minuteSecondPadding ? 2 : 1)}${secondDecimals > 0 ? '.${'0' * secondDecimals}' : ''}', locale).format(sec);
|
final minText = NumberFormat('0' * (minuteSecondPadding ? 2 : 1), locale).format(min);
|
||||||
|
final secText = NumberFormat('${'0' * (minuteSecondPadding ? 2 : 1)}${secondDecimals > 0 ? '.${'0' * secondDecimals}' : ''}', locale).format(sec);
|
||||||
|
|
||||||
return '$deg° $minText′ $secText″';
|
return '$degText° $minText′ $secText″';
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<String> _toDecimal(AppLocalizations l10n, LatLng latLng) {
|
static List<String> _toDecimal(AppLocalizations l10n, LatLng latLng) {
|
||||||
|
|
|
@ -45,3 +45,13 @@ bool shouldUseNativeDigits(Locale? countrifiedLocale) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool canHaveLetterSpacing(String locale) {
|
||||||
|
switch (locale) {
|
||||||
|
case 'ar':
|
||||||
|
case 'fa':
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
import 'package:aves/model/device.dart';
|
import 'package:aves/model/device.dart';
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/about/policy_page.dart';
|
import 'package:aves/widgets/about/policy_page.dart';
|
||||||
import 'package:aves/widgets/common/basic/link_chip.dart';
|
import 'package:aves/widgets/common/basic/link_chip.dart';
|
||||||
|
@ -10,13 +10,6 @@ import 'package:flutter/material.dart';
|
||||||
class AppReference extends StatelessWidget {
|
class AppReference extends StatelessWidget {
|
||||||
static const avesGithub = 'https://github.com/deckerst/aves';
|
static const avesGithub = 'https://github.com/deckerst/aves';
|
||||||
|
|
||||||
static const _appTitleStyle = TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.normal,
|
|
||||||
letterSpacing: 1.0,
|
|
||||||
fontFeatures: [FontFeature.enable('smcp')],
|
|
||||||
);
|
|
||||||
|
|
||||||
const AppReference({super.key});
|
const AppReference({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -38,27 +31,35 @@ class AppReference extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAvesLine(BuildContext context) {
|
Widget _buildAvesLine(BuildContext context) {
|
||||||
|
final locale = context.l10n.localeName;
|
||||||
final textScaler = MediaQuery.textScalerOf(context);
|
final textScaler = MediaQuery.textScalerOf(context);
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
AvesLogo(
|
AvesLogo(
|
||||||
size: textScaler.scale(_appTitleStyle.fontSize!) * 1.3,
|
size: textScaler.scale(_getAppTitleStyle(locale).fontSize!) * 1.3,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
Text(
|
||||||
context.l10n.appName,
|
context.l10n.appName,
|
||||||
style: _appTitleStyle,
|
style: _getAppTitleStyle(locale),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
Text(
|
||||||
device.packageVersion,
|
device.packageVersion,
|
||||||
style: _appTitleStyle,
|
style: _getAppTitleStyle(locale),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextStyle _getAppTitleStyle(String locale) => TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
letterSpacing: canHaveLetterSpacing(locale) ? 1 : 0,
|
||||||
|
fontFeatures: const [FontFeature.enable('smcp')],
|
||||||
|
);
|
||||||
|
|
||||||
static List<Widget> buildLinks(BuildContext context) {
|
static List<Widget> buildLinks(BuildContext context) {
|
||||||
final l10n = context.l10n;
|
final l10n = context.l10n;
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -122,6 +122,9 @@ class _BugReportState extends State<BugReport> with FeedbackMixin {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildStep(int step, String text, String buttonText, VoidCallback onPressed) {
|
Widget _buildStep(int step, String text, String buttonText, VoidCallback onPressed) {
|
||||||
|
final locale = context.l10n.localeName;
|
||||||
|
final numberFormat = NumberFormat.decimalPattern(locale);
|
||||||
|
|
||||||
final isMonochrome = settings.themeColorMode == AvesThemeColorMode.monochrome;
|
final isMonochrome = settings.themeColorMode == AvesThemeColorMode.monochrome;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||||
|
@ -136,7 +139,7 @@ class _BugReportState extends State<BugReport> with FeedbackMixin {
|
||||||
)),
|
)),
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: Text('$step'),
|
child: Text(numberFormat.format(step)),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(child: Text(text)),
|
Expanded(child: Text(text)),
|
||||||
|
|
|
@ -218,6 +218,9 @@ class _ReportOverlayState<T> extends State<ReportOverlay<T>> with SingleTickerPr
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final locale = context.l10n.localeName;
|
||||||
|
final percentFormat = NumberFormat.percentPattern(locale);
|
||||||
|
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final colorScheme = theme.colorScheme;
|
final colorScheme = theme.colorScheme;
|
||||||
final progressColor = colorScheme.primary;
|
final progressColor = colorScheme.primary;
|
||||||
|
@ -230,7 +233,6 @@ class _ReportOverlayState<T> extends State<ReportOverlay<T>> with SingleTickerPr
|
||||||
final processedCount = processed.length.toDouble();
|
final processedCount = processed.length.toDouble();
|
||||||
final total = widget.itemCount;
|
final total = widget.itemCount;
|
||||||
final percent = total == null || total == 0 ? 0.0 : min(1.0, processedCount / total);
|
final percent = total == null || total == 0 ? 0.0 : min(1.0, processedCount / total);
|
||||||
final percentFormat = NumberFormat.percentPattern();
|
|
||||||
return FadeTransition(
|
return FadeTransition(
|
||||||
opacity: _animation,
|
opacity: _animation,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
|
@ -351,6 +353,9 @@ class _FeedbackMessageState extends State<_FeedbackMessage> with SingleTickerPro
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final locale = context.l10n.localeName;
|
||||||
|
final numberFormat = NumberFormat('0', locale);
|
||||||
|
|
||||||
final textScaler = MediaQuery.textScalerOf(context);
|
final textScaler = MediaQuery.textScalerOf(context);
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final colorScheme = theme.colorScheme;
|
final colorScheme = theme.colorScheme;
|
||||||
|
@ -388,7 +393,7 @@ class _FeedbackMessageState extends State<_FeedbackMessage> with SingleTickerPro
|
||||||
// because we cannot use the app context theme here
|
// because we cannot use the app context theme here
|
||||||
foreground: widget.progressColor,
|
foreground: widget.progressColor,
|
||||||
center: ChangeHighlightText(
|
center: ChangeHighlightText(
|
||||||
'${(remainingDurationMillis / 1000).ceil()}',
|
numberFormat.format((remainingDurationMillis / 1000).ceil()),
|
||||||
style: contentTextStyle.copyWith(
|
style: contentTextStyle.copyWith(
|
||||||
shadows: [
|
shadows: [
|
||||||
Shadow(
|
Shadow(
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/theme/colors.dart';
|
import 'package:aves/theme/colors.dart';
|
||||||
import 'package:aves/theme/themes.dart';
|
import 'package:aves/theme/themes.dart';
|
||||||
import 'package:aves/widgets/common/basic/text/outlined.dart';
|
import 'package:aves/widgets/common/basic/text/outlined.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/extensions/theme.dart';
|
import 'package:aves/widgets/common/extensions/theme.dart';
|
||||||
import 'package:aves/widgets/common/fx/highlight_decoration.dart';
|
import 'package:aves/widgets/common/fx/highlight_decoration.dart';
|
||||||
import 'package:aves_model/aves_model.dart';
|
import 'package:aves_model/aves_model.dart';
|
||||||
|
@ -40,7 +41,7 @@ class HighlightTitle extends StatelessWidget {
|
||||||
final style = TextStyle(
|
final style = TextStyle(
|
||||||
shadows: shadows(context),
|
shadows: shadows(context),
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
letterSpacing: 1.0,
|
letterSpacing: canHaveLetterSpacing(context.l10n.localeName) ? 1 : 0,
|
||||||
fontFeatures: const [FontFeature.enable('smcp')],
|
fontFeatures: const [FontFeature.enable('smcp')],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -146,9 +146,11 @@ class _GeoMapState extends State<GeoMap> {
|
||||||
selector: (context, s) => s.mapStyle,
|
selector: (context, s) => s.mapStyle,
|
||||||
builder: (context, mapStyle, child) {
|
builder: (context, mapStyle, child) {
|
||||||
final isHeavy = ExtraEntryMapStyle.isHeavy(mapStyle);
|
final isHeavy = ExtraEntryMapStyle.isHeavy(mapStyle);
|
||||||
|
final locale = context.l10n.localeName;
|
||||||
Widget _buildMarkerWidget(MarkerKey<AvesEntry> key) => ImageMarker(
|
Widget _buildMarkerWidget(MarkerKey<AvesEntry> key) => ImageMarker(
|
||||||
key: key,
|
key: key,
|
||||||
count: key.count,
|
count: key.count,
|
||||||
|
locale: locale,
|
||||||
buildThumbnailImage: (extent) => ThumbnailImage(
|
buildThumbnailImage: (extent) => ThumbnailImage(
|
||||||
entry: key.entry,
|
entry: key.entry,
|
||||||
extent: extent,
|
extent: extent,
|
||||||
|
@ -482,9 +484,11 @@ class _GeoMapState extends State<GeoMap> {
|
||||||
} else {
|
} else {
|
||||||
markerEntry = geoEntry.entry!;
|
markerEntry = geoEntry.entry!;
|
||||||
}
|
}
|
||||||
|
final locale = context.l10n.localeName;
|
||||||
final markerLocation = LatLng(geoEntry.latitude!, geoEntry.longitude!);
|
final markerLocation = LatLng(geoEntry.latitude!, geoEntry.longitude!);
|
||||||
Widget markerBuilder(BuildContext context) => ImageMarker(
|
Widget markerBuilder(BuildContext context) => ImageMarker(
|
||||||
count: geoEntry.pointsSize,
|
count: geoEntry.pointsSize,
|
||||||
|
locale: locale,
|
||||||
drawArrow: false,
|
drawArrow: false,
|
||||||
buildThumbnailImage: (extent) => ThumbnailImage(
|
buildThumbnailImage: (extent) => ThumbnailImage(
|
||||||
entry: markerEntry,
|
entry: markerEntry,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
import 'package:aves/model/filters/album.dart';
|
import 'package:aves/model/filters/album.dart';
|
||||||
import 'package:aves/model/filters/trash.dart';
|
import 'package:aves/model/filters/trash.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
|
@ -8,6 +7,7 @@ import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/model/source/location/country.dart';
|
import 'package:aves/model/source/location/country.dart';
|
||||||
import 'package:aves/model/source/location/place.dart';
|
import 'package:aves/model/source/location/place.dart';
|
||||||
import 'package:aves/model/source/tag.dart';
|
import 'package:aves/model/source/tag.dart';
|
||||||
|
import 'package:aves/ref/locales.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
|
@ -111,6 +111,9 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHeader(BuildContext context) {
|
Widget _buildHeader(BuildContext context) {
|
||||||
|
final l10n = context.l10n;
|
||||||
|
final locale = l10n.localeName;
|
||||||
|
|
||||||
Future<void> goTo(String routeName, WidgetBuilder pageBuilder) async {
|
Future<void> goTo(String routeName, WidgetBuilder pageBuilder) async {
|
||||||
Navigator.maybeOf(context)?.pop();
|
Navigator.maybeOf(context)?.pop();
|
||||||
await Future.delayed(ADurations.drawerTransitionAnimation);
|
await Future.delayed(ADurations.drawerTransitionAnimation);
|
||||||
|
@ -145,13 +148,13 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
OutlinedText(
|
OutlinedText(
|
||||||
textSpans: [
|
textSpans: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: context.l10n.appName,
|
text: l10n.appName,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 38,
|
fontSize: 38,
|
||||||
fontWeight: FontWeight.w300,
|
fontWeight: FontWeight.w300,
|
||||||
letterSpacing: 1.0,
|
letterSpacing: canHaveLetterSpacing(locale) ? 1 : 0,
|
||||||
fontFeatures: [FontFeature.enable('smcp')],
|
fontFeatures: const [FontFeature.enable('smcp')],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -177,7 +180,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
onPressed: () => goTo(AboutPage.routeName, (_) => const AboutPage()),
|
onPressed: () => goTo(AboutPage.routeName, (_) => const AboutPage()),
|
||||||
style: drawerButtonStyle,
|
style: drawerButtonStyle,
|
||||||
icon: const Icon(AIcons.info),
|
icon: const Icon(AIcons.info),
|
||||||
label: Text(context.l10n.drawerAboutButton),
|
label: Text(l10n.drawerAboutButton),
|
||||||
),
|
),
|
||||||
OutlinedButton.icon(
|
OutlinedButton.icon(
|
||||||
// key is expected by test driver
|
// key is expected by test driver
|
||||||
|
@ -185,7 +188,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
onPressed: () => goTo(SettingsPage.routeName, (_) => const SettingsPage()),
|
onPressed: () => goTo(SettingsPage.routeName, (_) => const SettingsPage()),
|
||||||
style: drawerButtonStyle,
|
style: drawerButtonStyle,
|
||||||
icon: const Icon(AIcons.settings),
|
icon: const Icon(AIcons.settings),
|
||||||
label: Text(context.l10n.drawerSettingsButton),
|
label: Text(l10n.drawerSettingsButton),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'package:aves/model/settings/enums/home_page.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
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/ref/locales.dart';
|
||||||
import 'package:aves/widgets/about/about_page.dart';
|
import 'package:aves/widgets/about/about_page.dart';
|
||||||
import 'package:aves/widgets/collection/collection_page.dart';
|
import 'package:aves/widgets/collection/collection_page.dart';
|
||||||
import 'package:aves/widgets/common/basic/insets.dart';
|
import 'package:aves/widgets/common/basic/insets.dart';
|
||||||
|
@ -90,6 +91,9 @@ class _TvRailState extends State<TvRail> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final l10n = context.l10n;
|
||||||
|
final locale = l10n.localeName;
|
||||||
|
|
||||||
final navEntries = _getNavEntries(context);
|
final navEntries = _getNavEntries(context);
|
||||||
return DirectionalSafeArea(
|
return DirectionalSafeArea(
|
||||||
end: false,
|
end: false,
|
||||||
|
@ -103,13 +107,13 @@ class _TvRailState extends State<TvRail> {
|
||||||
logo,
|
logo,
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Text(
|
Text(
|
||||||
context.l10n.appName,
|
l10n.appName,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 32,
|
fontSize: 32,
|
||||||
fontWeight: FontWeight.w300,
|
fontWeight: FontWeight.w300,
|
||||||
letterSpacing: 1.0,
|
letterSpacing: canHaveLetterSpacing(locale) ? 1 : 0,
|
||||||
fontFeatures: [FontFeature.enable('smcp')],
|
fontFeatures: const [FontFeature.enable('smcp')],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
import 'package:aves/theme/styles.dart';
|
import 'package:aves/theme/styles.dart';
|
||||||
import 'package:aves/theme/themes.dart';
|
import 'package:aves/theme/themes.dart';
|
||||||
import 'package:aves/widgets/common/basic/text/outlined.dart';
|
import 'package:aves/widgets/common/basic/text/outlined.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/extensions/theme.dart';
|
import 'package:aves/widgets/common/extensions/theme.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class LinearPercentIndicatorText extends StatelessWidget {
|
class LinearPercentIndicatorText extends StatelessWidget {
|
||||||
final double percent;
|
final double percent;
|
||||||
final percentFormat = NumberFormat.percentPattern();
|
|
||||||
|
|
||||||
LinearPercentIndicatorText({
|
const LinearPercentIndicatorText({
|
||||||
super.key,
|
super.key,
|
||||||
required this.percent,
|
required this.percent,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final locale = context.l10n.localeName;
|
||||||
|
final percentFormat = NumberFormat.percentPattern(locale);
|
||||||
|
|
||||||
return OutlinedText(
|
return OutlinedText(
|
||||||
textSpans: [
|
textSpans: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
|
|
|
@ -32,6 +32,7 @@ import 'package:aves_model/aves_model.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class BasicSection extends StatefulWidget {
|
class BasicSection extends StatefulWidget {
|
||||||
|
@ -277,15 +278,6 @@ class _BasicInfoState extends State<_BasicInfo> {
|
||||||
|
|
||||||
AvesEntry get entry => widget.entry;
|
AvesEntry get entry => widget.entry;
|
||||||
|
|
||||||
int get megaPixels => (entry.width * entry.height / 1000000).round();
|
|
||||||
|
|
||||||
// guess whether this is a photo, according to file type
|
|
||||||
bool get isPhoto => [MimeTypes.heic, MimeTypes.heif, MimeTypes.jpeg, MimeTypes.tiff].contains(entry.mimeType) || entry.isRaw;
|
|
||||||
|
|
||||||
bool get showMegaPixels => isPhoto && megaPixels > 0;
|
|
||||||
|
|
||||||
String get rasterResolutionText => '${entry.resolutionText}${showMegaPixels ? ' • $megaPixels MP' : ''}';
|
|
||||||
|
|
||||||
static const ownerPackageNamePropKey = 'owner_package_name';
|
static const ownerPackageNamePropKey = 'owner_package_name';
|
||||||
static const iconSize = 20.0;
|
static const iconSize = 20.0;
|
||||||
|
|
||||||
|
@ -331,7 +323,7 @@ class _BasicInfoState extends State<_BasicInfo> {
|
||||||
l10n.viewerInfoLabelTitle: title,
|
l10n.viewerInfoLabelTitle: title,
|
||||||
l10n.viewerInfoLabelDate: dateText,
|
l10n.viewerInfoLabelDate: dateText,
|
||||||
if (entry.isVideo) ..._buildVideoRows(context),
|
if (entry.isVideo) ..._buildVideoRows(context),
|
||||||
if (showResolution) l10n.viewerInfoLabelResolution: context.applyDirectionality(rasterResolutionText),
|
if (showResolution) l10n.viewerInfoLabelResolution: context.applyDirectionality(getRasterResolutionText(locale)),
|
||||||
l10n.viewerInfoLabelSize: context.applyDirectionality(sizeText),
|
l10n.viewerInfoLabelSize: context.applyDirectionality(sizeText),
|
||||||
if (!entry.trashed) l10n.viewerInfoLabelUri: entry.uri,
|
if (!entry.trashed) l10n.viewerInfoLabelUri: entry.uri,
|
||||||
if (path != null) l10n.viewerInfoLabelPath: path,
|
if (path != null) l10n.viewerInfoLabelPath: path,
|
||||||
|
@ -384,4 +376,20 @@ class _BasicInfoState extends State<_BasicInfo> {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getRasterResolutionText(String locale) {
|
||||||
|
var s = entry.getResolutionText(locale);
|
||||||
|
|
||||||
|
// guess whether this is a photo, according to file type
|
||||||
|
final isPhoto = [MimeTypes.heic, MimeTypes.heif, MimeTypes.jpeg, MimeTypes.tiff].contains(entry.mimeType) || entry.isRaw;
|
||||||
|
if (isPhoto) {
|
||||||
|
final numberFormat = NumberFormat('0', locale);
|
||||||
|
final megaPixels = (entry.width * entry.height / 1000000).round();
|
||||||
|
if (megaPixels > 0) {
|
||||||
|
s += ' • ${numberFormat.format(megaPixels)} MP';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,9 +69,12 @@ class _ColorSectionSliverState extends State<ColorSectionSliver> {
|
||||||
children: [
|
children: [
|
||||||
ColorIndicator(value: v.color),
|
ColorIndicator(value: v.color),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
SelectableText(
|
Directionality(
|
||||||
'#${v.color.hex}',
|
textDirection: TextDirection.ltr,
|
||||||
style: const TextStyle(fontFamily: 'monospace'),
|
child: SelectableText(
|
||||||
|
'#${v.color.hex}',
|
||||||
|
style: const TextStyle(fontFamily: 'monospace'),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -29,7 +29,7 @@ class OverlayDateRow extends StatelessWidget {
|
||||||
final resolutionText = entry.isSvg
|
final resolutionText = entry.isSvg
|
||||||
? entry.aspectRatioText
|
? entry.aspectRatioText
|
||||||
: entry.isSized
|
: entry.isSized
|
||||||
? entry.resolutionText
|
? entry.getResolutionText(locale)
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
|
|
|
@ -4,10 +4,12 @@ import 'package:collection/collection.dart';
|
||||||
import 'package:custom_rounded_rectangle_border/custom_rounded_rectangle_border.dart';
|
import 'package:custom_rounded_rectangle_border/custom_rounded_rectangle_border.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_map/flutter_map.dart';
|
import 'package:flutter_map/flutter_map.dart';
|
||||||
|
import 'package:intl/intl.dart' as intl;
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
|
|
||||||
class ImageMarker extends StatelessWidget {
|
class ImageMarker extends StatelessWidget {
|
||||||
final int? count;
|
final int? count;
|
||||||
|
final intl.NumberFormat numberFormat;
|
||||||
final bool drawArrow;
|
final bool drawArrow;
|
||||||
final Widget Function(double extent) buildThumbnailImage;
|
final Widget Function(double extent) buildThumbnailImage;
|
||||||
|
|
||||||
|
@ -20,12 +22,13 @@ class ImageMarker extends StatelessWidget {
|
||||||
static const innerRadius = Radius.circular(outerBorderRadiusDim - outerBorderWidth);
|
static const innerRadius = Radius.circular(outerBorderRadiusDim - outerBorderWidth);
|
||||||
static const innerBorderRadius = BorderRadius.all(innerRadius);
|
static const innerBorderRadius = BorderRadius.all(innerRadius);
|
||||||
|
|
||||||
const ImageMarker({
|
ImageMarker({
|
||||||
super.key,
|
super.key,
|
||||||
required this.count,
|
required this.count,
|
||||||
|
required String locale,
|
||||||
this.drawArrow = true,
|
this.drawArrow = true,
|
||||||
required this.buildThumbnailImage,
|
required this.buildThumbnailImage,
|
||||||
});
|
}) : numberFormat = intl.NumberFormat.decimalPattern(locale);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -107,7 +110,7 @@ class ImageMarker extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'$count',
|
numberFormat.format(count),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: theme.colorScheme.onPrimary,
|
color: theme.colorScheme.onPrimary,
|
||||||
|
|
|
@ -102,7 +102,7 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
version: "4.0.2"
|
||||||
intl:
|
intl:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: intl
|
name: intl
|
||||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||||
|
|
|
@ -15,6 +15,7 @@ dependencies:
|
||||||
equatable:
|
equatable:
|
||||||
fluster:
|
fluster:
|
||||||
flutter_map:
|
flutter_map:
|
||||||
|
intl:
|
||||||
latlong2:
|
latlong2:
|
||||||
provider:
|
provider:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue