This commit is contained in:
Thibault Deckers 2023-03-24 17:29:50 +01:00
parent 25dc291ba4
commit e8893f7f07
54 changed files with 207 additions and 191 deletions

View file

@ -9,7 +9,7 @@ import 'package:aves/ref/mime_types.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves/services/metadata/svg_metadata_service.dart';
import 'package:aves/theme/colors.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/viewer/info/metadata/metadata_dir.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
@ -115,7 +115,7 @@ extension ExtraAvesEntryInfo on AvesEntry {
final dirName = [
'Stream ${index.toString().padLeft(indexDigits, '0')}',
typeText,
].join(Constants.separator);
].join(AText.separator);
final formattedStreamTags = VideoMetadataFormatter.formatInfo(stream);
if (formattedStreamTags.isNotEmpty) {
final color = colors.fromString(typeText);

View file

@ -3,6 +3,8 @@ import 'dart:ui';
import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/ref/mime_types.dart';
import 'package:aves/ref/unicode.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/utils/android_file_utils.dart';
extension ExtraAvesEntryProps on AvesEntry {
@ -81,15 +83,12 @@ extension ExtraAvesEntryProps on AvesEntry {
bool get canRemoveMetadata => MimeTypes.canRemoveMetadata(mimeType);
static const ratioSeparator = '\u2236';
static const resolutionSeparator = ' \u00D7 ';
bool get isSized => width > 0 && height > 0;
String get resolutionText {
final ws = width;
final hs = height;
return isRotated ? '$hs$resolutionSeparator$ws' : '$ws$resolutionSeparator$hs';
return isRotated ? '$hs${AText.resolutionSeparator}$ws' : '$ws${AText.resolutionSeparator}$hs';
}
String get aspectRatioText {
@ -97,9 +96,9 @@ extension ExtraAvesEntryProps on AvesEntry {
final gcd = width.gcd(height);
final w = width ~/ gcd;
final h = height ~/ gcd;
return isRotated ? '$h$ratioSeparator$w' : '$w$ratioSeparator$h';
return isRotated ? '$h${Unicode.ratio}$w' : '$w${Unicode.ratio}$h';
} else {
return '?$ratioSeparator?';
return '?${Unicode.ratio}?';
}
}

View file

@ -5,7 +5,6 @@ import 'package:aves/model/settings/enums/coordinate_format.dart';
import 'package:aves/model/settings/enums/enums.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/aves_app.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves_map/aves_map.dart';
import 'package:flutter/material.dart';
@ -61,7 +60,7 @@ class CoordinateFilter extends CollectionFilter {
bool get exclusiveProp => false;
@override
String get universalLabel => _formatBounds(lookupAppLocalizations(AvesApp.supportedLocales.first), CoordinateFormat.decimal);
String get universalLabel => _formatBounds(lookupAppLocalizations(AppLocalizations.supportedLocales.first), CoordinateFormat.decimal);
@override
String getLabel(BuildContext context) => _formatBounds(context.l10n, context.read<Settings>().coordinateFormat);

View file

@ -1,4 +1,5 @@
import 'package:aves/model/filters/filters.dart';
import 'package:aves/ref/unicode.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/widgets.dart';
@ -67,7 +68,7 @@ class RatingFilter extends CollectionFilter {
case 0:
return context.l10n.filterNoRatingLabel;
default:
return '\u2B50' * rating;
return Unicode.whiteMediumStar * rating;
}
}
}

View file

@ -1,11 +1,11 @@
import 'package:flutter/painting.dart';
import 'dart:ui';
class BrandColors {
static const Color adobeAfterEffects = Color(0xFF9A9AFF);
static const Color adobeIllustrator = Color(0xFFFF9B00);
static const Color adobePhotoshop = Color(0xFF2DAAFF);
static const Color android = Color(0xFF3DDC84);
static const Color flutter = Color(0xFF47D1FD);
static const adobeAfterEffects = Color(0xFF9A9AFF);
static const adobeIllustrator = Color(0xFFFF9B00);
static const adobePhotoshop = Color(0xFF2DAAFF);
static const android = Color(0xFF3DDC84);
static const flutter = Color(0xFF47D1FD);
static Color? get(String text) {
switch (text.toLowerCase()) {

15
lib/ref/poi.dart Normal file
View file

@ -0,0 +1,15 @@
import 'package:latlong2/latlong.dart';
class PointsOfInterest {
static final pointNemo = LatLng(-48.876667, -123.393333);
static final wonders = [
LatLng(29.979167, 31.134167),
LatLng(36.451000, 28.223615),
LatLng(32.5355, 44.4275),
LatLng(31.213889, 29.885556),
LatLng(37.0379, 27.4241),
LatLng(37.637861, 21.63),
LatLng(37.949722, 27.363889),
];
}

9
lib/ref/unicode.dart Normal file
View file

@ -0,0 +1,9 @@
// cf Flutter's `foundation/unicode.dart` for bidi related characters
class Unicode {
static const noBreakSpace = '\u00A0';
static const multiplicationSign = '\u00D7'; // ×
static const emDash = '\u2014'; //
static const bullet = '\u2022'; //
static const ratio = '\u2236'; //
static const whiteMediumStar = '\u2B50'; //
}

View file

@ -1,6 +1,6 @@
import 'package:aves/model/entry/entry.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/text.dart';
import 'package:flutter/services.dart';
abstract class EmbeddedDataService {
@ -42,7 +42,7 @@ class PlatformEmbeddedDataService implements EmbeddedDataService {
'mimeType': entry.mimeType,
'uri': entry.uri,
'sizeBytes': entry.sizeBytes,
'displayName': ['${entry.bestTitle}', dataUri].join(Constants.separator),
'displayName': ['${entry.bestTitle}', dataUri].join(AText.separator),
'dataUri': dataUri,
});
if (result != null) return result as Map;
@ -59,7 +59,7 @@ class PlatformEmbeddedDataService implements EmbeddedDataService {
'mimeType': entry.mimeType,
'uri': entry.uri,
'sizeBytes': entry.sizeBytes,
'displayName': ['${entry.bestTitle}', 'Image'].join(Constants.separator),
'displayName': ['${entry.bestTitle}', 'Image'].join(AText.separator),
});
if (result != null) return result as Map;
} on PlatformException catch (e, stack) {
@ -75,7 +75,7 @@ class PlatformEmbeddedDataService implements EmbeddedDataService {
'mimeType': entry.mimeType,
'uri': entry.uri,
'sizeBytes': entry.sizeBytes,
'displayName': ['${entry.bestTitle}', 'Video'].join(Constants.separator),
'displayName': ['${entry.bestTitle}', 'Video'].join(AText.separator),
});
if (result != null) return result as Map;
} on PlatformException catch (e, stack) {
@ -89,7 +89,7 @@ class PlatformEmbeddedDataService implements EmbeddedDataService {
try {
final result = await _platform.invokeMethod('extractVideoEmbeddedPicture', <String, dynamic>{
'uri': entry.uri,
'displayName': ['${entry.bestTitle}', 'Cover'].join(Constants.separator),
'displayName': ['${entry.bestTitle}', 'Cover'].join(AText.separator),
});
if (result != null) return result as Map;
} on PlatformException catch (e, stack) {
@ -105,7 +105,7 @@ class PlatformEmbeddedDataService implements EmbeddedDataService {
'mimeType': entry.mimeType,
'uri': entry.uri,
'sizeBytes': entry.sizeBytes,
'displayName': ['${entry.bestTitle}', '$props'].join(Constants.separator),
'displayName': ['${entry.bestTitle}', '$props'].join(AText.separator),
'propPath': props,
'propMimeType': propMimeType,
});

View file

@ -33,6 +33,10 @@ class AvesColorsProvider extends StatelessWidget {
}
abstract class AvesColorsData {
static const defaultAccent = Colors.indigoAccent;
static const _neutralOnDark = Colors.white;
static const _neutralOnLight = Color(0xAA000000);
Color get neutral;
Color fromHue(double hue);
@ -71,9 +75,6 @@ abstract class AvesColorsData {
void clearAppColor(String album) => _appColors.remove(album);
static const Color _neutralOnDark = Colors.white;
static const Color _neutralOnLight = Color(0xAA000000);
// mime
Color get image => fromHue(243);

View file

@ -1,4 +1,4 @@
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/text.dart';
import 'package:intl/intl.dart';
String formatDay(DateTime date, String locale) => DateFormat.yMMMd(locale).format(date);
@ -8,7 +8,7 @@ String formatTime(DateTime date, String locale, bool use24hour) => (use24hour ?
String formatDateTime(DateTime date, String locale, bool use24hour) => [
formatDay(date, locale),
formatTime(date, locale, use24hour),
].join(Constants.separator);
].join(AText.separator);
String formatFriendlyDuration(Duration d) {
final seconds = (d.inSeconds.remainder(Duration.secondsPerMinute)).toString().padLeft(2, '0');

22
lib/theme/styles.dart Normal file
View file

@ -0,0 +1,22 @@
import 'dart:ui';
import 'package:flutter/widgets.dart';
class AStyles {
// as of Flutter v2.8.0, overflowing `Text` miscalculates height and some text (e.g. 'Å') is clipped
// so we give it a `strutStyle` with a slightly larger height
static const overflowStrut = StrutStyle(height: 1.3);
static const knownTitleText = TextStyle(
fontSize: 20,
fontWeight: FontWeight.w300,
fontFeatures: [FontFeature.enable('smcp')],
);
static TextStyle unknownTitleText = knownTitleText;
static void updateStylesForLocale(Locale locale) {
final smcp = locale.languageCode != 'el';
unknownTitleText = smcp ? knownTitleText : knownTitleText.copyWith(fontFeatures: []);
}
}

7
lib/theme/text.dart Normal file
View file

@ -0,0 +1,7 @@
import 'package:aves/ref/unicode.dart';
class AText {
static const separator = ' ${Unicode.bullet} ';
static const resolutionSeparator = ' ${Unicode.multiplicationSign} ';
static const valueNotAvailable = Unicode.emDash;
}

View file

@ -7,8 +7,6 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Themes {
static const defaultAccent = Colors.indigoAccent;
static const _tooltipTheme = TooltipThemeData(
verticalOffset: 32,
);

8
lib/utils/colors.dart Normal file
View file

@ -0,0 +1,8 @@
import 'dart:ui';
class ColorUtils {
// `Color(0x00FFFFFF)` is different from `Color(0x00000000)` (or `Colors.transparent`)
// when used in gradients or lerping to it
static const transparentWhite = Color(0x00FFFFFF);
static const transparentBlack = Color(0x00000000);
}

View file

@ -1,7 +1,4 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart';
import 'package:permission_handler/permission_handler.dart';
class Constants {
@ -12,32 +9,8 @@ class Constants {
Permission.videos,
];
static const separator = '';
// `Color(0x00FFFFFF)` is different from `Color(0x00000000)` (or `Colors.transparent`)
// when used in gradients or lerping to it
static const transparentWhite = Color(0x00FFFFFF);
static const transparentBlack = Colors.transparent;
// as of Flutter v2.8.0, overflowing `Text` miscalculates height and some text (e.g. 'Å') is clipped
// so we give it a `strutStyle` with a slightly larger height
static const overflowStrutStyle = StrutStyle(height: 1.3);
static const double colorPickerRadius = 16;
static const knownTitleTextStyle = TextStyle(
fontSize: 20,
fontWeight: FontWeight.w300,
fontFeatures: [FontFeature.enable('smcp')],
);
static TextStyle unknownTitleTextStyle = knownTitleTextStyle;
static void updateStylesForLocale(Locale locale) {
final smcp = locale.languageCode != 'el';
unknownTitleTextStyle = smcp ? knownTitleTextStyle : knownTitleTextStyle.copyWith(fontFeatures: []);
}
static const embossShadows = [
Shadow(
color: Colors.black,
@ -50,30 +23,5 @@ class Constants {
Color(0xffeaecc6),
];
// Bidi fun, cf https://www.unicode.org/reports/tr9/
// First Strong Isolate
static const fsi = '\u2068';
// Pop Directional Isolate
static const pdi = '\u2069';
static const zwsp = '\u200B';
static const overlayUnknown = ''; // em dash
static final pointNemo = LatLng(-48.876667, -123.393333);
static final wonders = [
LatLng(29.979167, 31.134167),
LatLng(36.451000, 28.223615),
LatLng(32.5355, 44.4275),
LatLng(31.213889, 29.885556),
LatLng(37.0379, 27.4241),
LatLng(37.637861, 21.63),
LatLng(37.949722, 27.363889),
];
static const int infoGroupMaxValueLength = 140;
static const String avesGithub = 'https://github.com/deckerst/aves';
}

View file

@ -1,7 +1,6 @@
import 'dart:ui';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/about/policy_page.dart';
import 'package:aves/widgets/common/basic/link_chip.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
@ -10,6 +9,8 @@ import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
class AppReference extends StatefulWidget {
static const avesGithub = 'https://github.com/deckerst/aves';
const AppReference({super.key});
@override
@ -79,7 +80,7 @@ class _AppReferenceState extends State<AppReference> {
size: 24,
),
text: 'GitHub',
urlString: Constants.avesGithub,
urlString: AppReference.avesGithub,
),
LinkChip(
leading: const Icon(
@ -87,7 +88,7 @@ class _AppReferenceState extends State<AppReference> {
size: 22,
),
text: l10n.aboutLinkLicense,
urlString: '${Constants.avesGithub}/blob/main/LICENSE',
urlString: '${AppReference.avesGithub}/blob/main/LICENSE',
),
LinkChip(
leading: const Icon(

View file

@ -10,7 +10,8 @@ import 'package:aves/ref/mime_types.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves/theme/colors.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/about/app_ref.dart';
import 'package:aves/widgets/aves_app.dart';
import 'package:aves/widgets/common/action_mixins/feedback.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
@ -34,7 +35,7 @@ class _BugReportState extends State<BugReport> with FeedbackMixin {
late Future<String> _infoLoader;
bool _showInstructions = false;
static const bugReportUrl = '${Constants.avesGithub}/issues/new?labels=type%3Abug&template=bug_report.md';
static const bugReportUrl = '${AppReference.avesGithub}/issues/new?labels=type%3Abug&template=bug_report.md';
@override
void initState() {
@ -60,7 +61,7 @@ class _BugReportState extends State<BugReport> with FeedbackMixin {
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
alignment: AlignmentDirectional.centerStart,
child: Text(l10n.aboutBugSectionTitle, style: Constants.knownTitleTextStyle),
child: Text(l10n.aboutBugSectionTitle, style: AStyles.knownTitleText),
),
),
body: Padding(

View file

@ -2,7 +2,7 @@ import 'package:aves/app_flavor.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/ref/brand_colors.dart';
import 'package:aves/theme/colors.dart';
import 'package:aves/utils/dependencies.dart';
import 'package:aves/model/dependencies.dart';
import 'package:aves/widgets/about/title.dart';
import 'package:aves/widgets/about/tv_license_page.dart';
import 'package:aves/widgets/common/basic/link_chip.dart';

View file

@ -1,5 +1,5 @@
import 'package:aves/model/settings/settings.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:flutter/material.dart';
class AboutSectionTitle extends StatelessWidget {
@ -15,7 +15,7 @@ class AboutSectionTitle extends StatelessWidget {
Widget child = Container(
alignment: AlignmentDirectional.centerStart,
constraints: const BoxConstraints(minHeight: kMinInteractiveDimension),
child: Text(text, style: Constants.knownTitleTextStyle),
child: Text(text, style: AStyles.knownTitleText),
);
if (settings.useTvLayout) {

View file

@ -1,6 +1,6 @@
import 'dart:math';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/about/title.dart';
import 'package:aves/widgets/common/basic/text/change_highlight.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
@ -154,7 +154,7 @@ class _RandomTextSpanHighlighterState extends State<_RandomTextSpanHighlighter>
TextSpan(
children: [
...widget.spans.expandIndexed((i, v) => [
if (i != 0) const TextSpan(text: Constants.separator),
if (i != 0) const TextSpan(text: AText.separator),
TextSpan(text: v, style: i == _highlightedIndex ? _animatedStyle.value : _baseStyle),
])
],

View file

@ -22,9 +22,9 @@ import 'package:aves/services/common/services.dart';
import 'package:aves/theme/colors.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/themes.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/utils/debouncer.dart';
import 'package:aves/widgets/collection/collection_grid.dart';
import 'package:aves/widgets/collection/collection_page.dart';
@ -224,12 +224,12 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
final themeBrightness = s.item2;
final enableDynamicColor = s.item3;
Constants.updateStylesForLocale(settings.appliedLocale);
AStyles.updateStylesForLocale(settings.appliedLocale);
return FutureBuilder<CorePalette?>(
future: _dynamicColorPaletteLoader,
builder: (context, snapshot) {
const defaultAccent = Themes.defaultAccent;
const defaultAccent = AvesColorsData.defaultAccent;
Color lightAccent = defaultAccent, darkAccent = defaultAccent;
if (enableDynamicColor) {
// `DynamicColorBuilder` from package `dynamic_color` provides light/dark

View file

@ -4,8 +4,9 @@ import 'package:aves/model/settings/enums/coordinate_format.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/format.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/utils/collection_utils.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/utils/file_utils.dart';
import 'package:aves/widgets/collection/grid/list_details_theme.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
@ -59,7 +60,7 @@ class EntryListDetails extends StatelessWidget {
children: spans,
),
style: style,
strutStyle: Constants.overflowStrutStyle,
strutStyle: AStyles.overflowStrut,
softWrap: false,
overflow: TextOverflow.fade,
);
@ -79,10 +80,10 @@ class EntryListDetails extends StatelessWidget {
final locale = context.l10n.localeName;
final use24hour = context.select<MediaQueryData, bool>((v) => v.alwaysUse24HourFormat);
final date = entry.bestDate;
final dateText = date != null ? formatDateTime(date, locale, use24hour) : Constants.overlayUnknown;
final dateText = date != null ? formatDateTime(date, locale, use24hour) : AText.valueNotAvailable;
final size = entry.burstEntries?.map((v) => v.sizeBytes).sum ?? entry.sizeBytes;
final sizeText = size != null ? formatFileSize(locale, size) : Constants.overlayUnknown;
final sizeText = size != null ? formatFileSize(locale, size) : AText.valueNotAvailable;
return _buildRow(
[

View file

@ -1,5 +1,5 @@
import 'package:aves/theme/format.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
@ -43,7 +43,7 @@ class EntryListDetailsTheme extends StatelessWidget {
TextSpan(text: formatDateTime(DateTime.now(), locale, use24hour), style: captionStyle),
textDirection: TextDirection.ltr,
textScaleFactor: textScaleFactor,
strutStyle: Constants.overflowStrutStyle,
strutStyle: AStyles.overflowStrut,
)..layout(const BoxConstraints(), parentUsesSize: true))
.getMaxIntrinsicHeight(double.infinity);

View file

@ -2,7 +2,7 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
import 'package:flutter/material.dart';
@ -34,7 +34,7 @@ class TitledExpandableFilterRow extends StatelessWidget {
Widget header = Text(
title,
style: Constants.knownTitleTextStyle,
style: AStyles.knownTitleText,
);
void toggle() => expandedNotifier.value = isExpanded ? null : title;
if (settings.useTvLayout) {

View file

@ -3,7 +3,7 @@ import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/source/section_keys.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/grid/sections/list_layout.dart';
import 'package:flutter/material.dart';
@ -85,7 +85,7 @@ class SectionHeader<T> extends StatelessWidget {
),
TextSpan(
text: title,
style: Constants.unknownTitleTextStyle,
style: AStyles.unknownTitleText,
),
if (trailing != null)
WidgetSpan(
@ -141,7 +141,7 @@ class SectionHeader<T> extends StatelessWidget {
if (hasTrailing) TextSpan(text: '\u200A' * 17),
TextSpan(
text: title,
style: Constants.unknownTitleTextStyle,
style: AStyles.unknownTitleText,
),
],
),

View file

@ -1,6 +1,6 @@
import 'package:aves/model/source/enums/enums.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/utils/colors.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:flutter/material.dart';
@ -123,12 +123,12 @@ class _OverlayBackgroundState extends State<_OverlayBackground> {
gradient: RadialGradient(
colors: isDark
? const [
Constants.transparentBlack,
Constants.transparentBlack,
ColorUtils.transparentBlack,
ColorUtils.transparentBlack,
]
: const [
Constants.transparentWhite,
Constants.transparentWhite,
ColorUtils.transparentWhite,
ColorUtils.transparentWhite,
],
),
);

View file

@ -1,5 +1,5 @@
import 'package:aves/theme/durations.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/utils/colors.dart';
import 'package:aves/widgets/common/grid/sections/mosaic/scale_grid.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:flutter/material.dart';
@ -110,7 +110,7 @@ class _OverlayBackgroundState extends State<_OverlayBackground> {
color: isDark ? Colors.black87 : const Color(0xDDFFFFFF),
)
: BoxDecoration(
color: isDark ? Constants.transparentBlack : Constants.transparentWhite,
color: isDark ? ColorUtils.transparentBlack : ColorUtils.transparentWhite,
);
}
}

View file

@ -9,10 +9,10 @@ import 'package:aves/model/entry/sort.dart';
import 'package:aves/model/settings/enums/l10n.dart';
import 'package:aves/model/settings/enums/map_style.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/ref/poi.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/utils/math_utils.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
@ -331,7 +331,7 @@ class _GeoMapState extends State<GeoMap> {
// fallback to default center
var center = settings.mapDefaultCenter;
if (center == null) {
center = Constants.wonders[Random().nextInt(Constants.wonders.length)];
center = PointsOfInterest.wonders[Random().nextInt(PointsOfInterest.wonders.length)];
WidgetsBinding.instance.addPostFrameCallback((_) => settings.mapDefaultCenter = center);
}
bounds = ZoomedBounds.fromPoints(

View file

@ -1,11 +1,11 @@
import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/entry/extensions/props.dart';
import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/metadata/enums/length_unit.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/ref/mime_types.dart';
import 'package:aves/services/media/media_edit_service.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/theme/themes.dart';
import 'package:aves/utils/mime_utils.dart';
import 'package:aves/widgets/common/basic/text_dropdown_button.dart';
@ -149,7 +149,7 @@ class _ConvertEntryDialogState extends State<ConvertEntryDialog> {
),
),
const SizedBox(width: 8),
const Text(ExtraAvesEntryProps.resolutionSeparator),
const Text(AText.resolutionSeparator),
const SizedBox(width: 8),
Expanded(
child: TextField(

View file

@ -6,10 +6,10 @@ import 'package:aves/model/metadata/enums/location_edit_action.dart';
import 'package:aves/model/settings/enums/coordinate_format.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/ref/poi.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/theme/themes.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/basic/text_dropdown_button.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/fx/transitions.dart';
@ -250,7 +250,7 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
controller: _latitudeController,
decoration: InputDecoration(
labelText: l10n.editEntryLocationDialogLatitude,
hintText: coordinateFormatter.format(Constants.pointNemo.latitude),
hintText: coordinateFormatter.format(PointsOfInterest.pointNemo.latitude),
),
onChanged: (_) => _validate(),
),
@ -258,7 +258,7 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
controller: _longitudeController,
decoration: InputDecoration(
labelText: l10n.editEntryLocationDialogLongitude,
hintText: coordinateFormatter.format(Constants.pointNemo.longitude),
hintText: coordinateFormatter.format(PointsOfInterest.pointNemo.longitude),
),
onChanged: (_) => _validate(),
),

View file

@ -2,9 +2,9 @@ import 'dart:io';
import 'package:aves/model/entry/entry.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/dialogs/aves_dialog.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class RenameEntryDialog extends StatefulWidget {
@ -43,7 +43,7 @@ class _RenameEntryDialogState extends State<RenameEntryDialog> {
@override
Widget build(BuildContext context) {
final isRtl = context.isRtl;
final extensionSuffixText = '${Constants.fsi}${entry.extension}${Constants.pdi}';
final extensionSuffixText = '${Unicode.FSI}${entry.extension}${Unicode.PDI}';
return AvesDialog(
content: TextField(
controller: _nameController,

View file

@ -5,7 +5,7 @@ import 'package:aves/model/naming_pattern.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/collection/collection_grid.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
@ -117,7 +117,7 @@ class _RenameEntrySetPageState extends State<RenameEntrySetPage> {
padding: const EdgeInsets.all(16),
child: Text(
l10n.renameEntrySetPagePreviewSectionTitle,
style: Constants.knownTitleTextStyle,
style: AStyles.knownTitleText,
),
),
Expanded(

View file

@ -8,7 +8,8 @@ import 'package:aves/services/common/services.dart';
import 'package:aves/services/geocoding_service.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/utils/debouncer.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
@ -267,8 +268,8 @@ class _AddressRowState extends State<_AddressRow> {
valueListenable: _addressLineNotifier,
builder: (context, addressLine, child) {
return Text(
addressLine ?? Constants.overlayUnknown,
strutStyle: Constants.overflowStrutStyle,
addressLine ?? AText.valueNotAvailable,
strutStyle: AStyles.overflowStrut,
softWrap: false,
overflow: TextOverflow.fade,
maxLines: 1,
@ -317,8 +318,8 @@ class _CoordinateRow extends StatelessWidget {
const SizedBox(width: _LocationInfo.iconPadding),
Expanded(
child: Text(
location != null ? settings.coordinateFormat.format(context.l10n, location!) : Constants.overlayUnknown,
strutStyle: Constants.overflowStrutStyle,
location != null ? settings.coordinateFormat.format(context.l10n, location!) : AText.valueNotAvailable,
strutStyle: AStyles.overflowStrut,
softWrap: false,
overflow: TextOverflow.fade,
maxLines: 1,

View file

@ -1,6 +1,6 @@
import 'package:aves/model/entry/extensions/props.dart';
import 'package:aves/ref/languages.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/theme/themes.dart';
import 'package:aves/widgets/common/basic/text_dropdown_button.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
@ -117,7 +117,7 @@ class _VideoStreamSelectionDialogState extends State<VideoStreamSelectionDialog>
final w = stream.width;
final h = stream.height;
if (w != null && h != null) {
return '$common$w${ExtraAvesEntryProps.resolutionSeparator}$h';
return '$common$w${AText.resolutionSeparator}$h';
}
}
return common;

View file

@ -12,8 +12,8 @@ import 'package:aves/model/source/tag.dart';
import 'package:aves/model/vaults/vaults.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
import 'package:aves/widgets/common/thumbnail/image.dart';
@ -214,7 +214,7 @@ class CoveredFilterChip<T extends CollectionFilter> extends StatelessWidget {
),
),
Text(
locked ? Constants.overlayUnknown : numberFormat.format(source.count(filter)),
locked ? AText.valueNotAvailable : numberFormat.format(source.count(filter)),
style: TextStyle(
color: _detailColor(context),
fontSize: fontSize,

View file

@ -4,8 +4,9 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/source/collection_source.dart';
import 'package:aves/theme/format.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/utils/file_utils.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/fx/borders.dart';
@ -87,7 +88,7 @@ class FilterListDetails<T extends CollectionFilter> extends StatelessWidget {
final locale = context.l10n.localeName;
final use24hour = context.select<MediaQueryData, bool>((v) => v.alwaysUse24HourFormat);
final date = entry?.bestDate;
final dateText = date != null ? formatDateTime(date, locale, use24hour) : Constants.overlayUnknown;
final dateText = date != null ? formatDateTime(date, locale, use24hour) : AText.valueNotAvailable;
Widget leading = const Icon(AIcons.date);
if (hasTitleLeading) {
@ -106,7 +107,7 @@ class FilterListDetails<T extends CollectionFilter> extends StatelessWidget {
child: Text(
dateText,
style: detailsTheme.captionStyle,
strutStyle: Constants.overflowStrutStyle,
strutStyle: AStyles.overflowStrut,
softWrap: false,
overflow: TextOverflow.fade,
),
@ -157,7 +158,7 @@ class FilterListDetails<T extends CollectionFilter> extends StatelessWidget {
Text(
'${l10n.itemCount(source.count(filter))}${formatFileSize(locale, source.size(filter))}',
style: detailsTheme.captionStyle,
strutStyle: Constants.overflowStrutStyle,
strutStyle: AStyles.overflowStrut,
softWrap: false,
overflow: TextOverflow.fade,
),

View file

@ -1,7 +1,7 @@
import 'dart:math';
import 'package:aves/theme/format.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
import 'package:flutter/material.dart';
@ -49,7 +49,7 @@ class FilterListDetailsTheme extends StatelessWidget {
TextSpan(text: formatDateTime(DateTime.now(), locale, use24hour), style: captionStyle),
textDirection: TextDirection.ltr,
textScaleFactor: textScaleFactor,
strutStyle: Constants.overflowStrutStyle,
strutStyle: AStyles.overflowStrut,
)..layout(const BoxConstraints(), parentUsesSize: true))
.getMaxIntrinsicHeight(double.infinity);

View file

@ -6,7 +6,8 @@ import 'package:aves/services/common/services.dart';
import 'package:aves/services/geocoding_service.dart';
import 'package:aves/theme/format.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves_map/aves_map.dart';
import 'package:flutter/material.dart';
@ -118,13 +119,13 @@ class _AddressRowState extends State<_AddressRow> {
builder: (context, addressLine, child) {
final location = addressLine ??
(entry == null
? Constants.overlayUnknown
? AText.valueNotAvailable
: entry.hasAddress
? entry.shortAddress
: settings.coordinateFormat.format(context.l10n, entry.latLng!));
return Text(
location,
strutStyle: Constants.overflowStrutStyle,
strutStyle: AStyles.overflowStrut,
softWrap: false,
overflow: TextOverflow.fade,
maxLines: 1,
@ -170,7 +171,7 @@ class _DateRow extends StatelessWidget {
final use24hour = context.select<MediaQueryData, bool>((v) => v.alwaysUse24HourFormat);
final date = entry?.bestDate;
final dateText = date != null ? formatDateTime(date, locale, use24hour) : Constants.overlayUnknown;
final dateText = date != null ? formatDateTime(date, locale, use24hour) : AText.valueNotAvailable;
return Row(
children: [
const SizedBox(width: MapInfoRow.iconPadding),
@ -179,7 +180,7 @@ class _DateRow extends StatelessWidget {
Expanded(
child: Text(
dateText,
strutStyle: Constants.overflowStrutStyle,
strutStyle: AStyles.overflowStrut,
softWrap: false,
overflow: TextOverflow.fade,
maxLines: 1,

View file

@ -2,9 +2,8 @@ import 'dart:async';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves_utils/aves_utils.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
@ -13,6 +12,7 @@ import 'package:aves/widgets/settings/common/quick_actions/action_panel.dart';
import 'package:aves/widgets/settings/common/quick_actions/available_actions.dart';
import 'package:aves/widgets/settings/common/quick_actions/placeholder.dart';
import 'package:aves/widgets/settings/common/quick_actions/quick_actions.dart';
import 'package:aves_utils/aves_utils.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@ -163,7 +163,7 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
padding: const EdgeInsets.only(left: 16, top: 16, right: 16),
child: Text(
context.l10n.settingsViewerQuickActionEditorDisplayedButtonsSectionTitle,
style: Constants.knownTitleTextStyle,
style: AStyles.knownTitleText,
),
),
ValueListenableBuilder<bool>(
@ -240,7 +240,7 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
context.l10n.settingsViewerQuickActionEditorAvailableButtonsSectionTitle,
style: Constants.knownTitleTextStyle,
style: AStyles.knownTitleText,
),
),
ValueListenableBuilder<bool>(

View file

@ -1,6 +1,6 @@
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/utils/time_utils.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/aves_caption.dart';
@ -179,7 +179,7 @@ class SettingsMultiSelectionListTile<T> extends StatelessWidget {
}
return ListTile(
title: titleWidget,
subtitle: AvesCaption(current.isEmpty ? noneSubtitle : current.map((v) => getName(context, v)).join(Constants.separator)),
subtitle: AvesCaption(current.isEmpty ? noneSubtitle : current.map((v) => getName(context, v)).join(AText.separator)),
onTap: () => showSelectionDialog<List<T>>(
context: context,
builder: (context) => AvesMultiSelectionDialog<T>(

View file

@ -4,9 +4,9 @@ import 'package:aves/model/settings/enums/coordinate_format.dart';
import 'package:aves/model/settings/enums/enums.dart';
import 'package:aves/model/settings/enums/l10n.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/ref/poi.dart';
import 'package:aves/theme/colors.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/settings/common/tile_leading.dart';
import 'package:aves/widgets/settings/common/tiles.dart';
@ -56,7 +56,7 @@ class SettingsTileLanguageCoordinateFormat extends SettingsTile {
onSelection: (v) => settings.coordinateFormat = v,
tileTitle: title(context),
dialogTitle: context.l10n.settingsCoordinateFormatDialogTitle,
optionSubtitleBuilder: (value) => value.format(context.l10n, Constants.pointNemo),
optionSubtitleBuilder: (value) => value.format(context.l10n, PointsOfInterest.pointNemo),
);
}

View file

@ -5,7 +5,6 @@ import 'package:aves/services/common/services.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
@ -183,7 +182,7 @@ class _FilePickerPageState extends State<FilePickerPage> {
Widget _buildContentLine(BuildContext context, FileSystemEntity content) {
return ListTile(
leading: const Icon(AIcons.folder),
title: Text('${Constants.fsi}${pContext.split(content.path).last}${Constants.pdi}'),
title: Text('${Unicode.FSI}${pContext.split(content.path).last}${Unicode.PDI}'),
onTap: () {
_goTo(content.path);
setState(() {});

View file

@ -12,7 +12,7 @@ import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/model/source/collection_source.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/collection/collection_page.dart';
import 'package:aves/widgets/common/action_mixins/feedback.dart';
import 'package:aves/widgets/common/action_mixins/vault_aware.dart';
@ -285,7 +285,7 @@ class _StatsPageState extends State<StatsPage> with FeedbackMixin, VaultAwareMix
: null;
Widget header = Text(
title,
style: Constants.knownTitleTextStyle,
style: AStyles.knownTitleText,
);
if (settings.useTvLayout) {
header = Container(

View file

@ -1,7 +1,7 @@
import 'dart:math';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
@ -75,7 +75,7 @@ class InfoRowGroup extends StatefulWidget {
final linkColor = Theme.of(context).colorScheme.primary;
final style = InfoRowGroup.valueStyle.copyWith(color: linkColor, decoration: TextDecoration.underline);
return [TextSpan(text: '${Constants.fsi}$value${Constants.pdi}', style: style, recognizer: recognizer)];
return [TextSpan(text: '${Unicode.FSI}$value${Unicode.PDI}', style: style, recognizer: recognizer)];
};
}
}
@ -164,7 +164,7 @@ class _InfoRowGroupState extends State<InfoRowGroup> {
// so that layout of the spans follows the directionality of the locale
// (e.g. keys on the right for RTL locale, whatever the key intrinsic directionality)
// and each span respects the directionality of its inner text only
String _buildTextValue(String value) => '${Constants.fsi}$value${Constants.pdi}';
String _buildTextValue(String value) => '${Unicode.FSI}$value${Unicode.PDI}';
}
typedef InfoValueSpanBuilder = List<InlineSpan> Function(BuildContext context, String key, String value);

View file

@ -2,7 +2,8 @@ import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/entry/extensions/props.dart';
import 'package:aves/theme/format.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/viewer/multipage/controller.dart';
import 'package:aves/widgets/viewer/overlay/details/details.dart';
@ -26,7 +27,7 @@ class OverlayDateRow extends StatelessWidget {
final use24hour = context.select<MediaQueryData, bool>((v) => v.alwaysUse24HourFormat);
final date = entry.bestDate;
final dateText = date != null ? formatDateTime(date, locale, use24hour) : Constants.overlayUnknown;
final dateText = date != null ? formatDateTime(date, locale, use24hour) : AText.valueNotAvailable;
final resolutionText = entry.isSvg
? entry.aspectRatioText
: entry.isSized
@ -37,8 +38,8 @@ class OverlayDateRow extends StatelessWidget {
children: [
DecoratedIcon(AIcons.date, size: ViewerDetailOverlayContent.iconSize, shadows: ViewerDetailOverlayContent.shadows(context)),
const SizedBox(width: ViewerDetailOverlayContent.iconPadding),
Expanded(flex: 3, child: Text(dateText, strutStyle: Constants.overflowStrutStyle)),
Expanded(flex: 2, child: Text(resolutionText, strutStyle: Constants.overflowStrutStyle)),
Expanded(flex: 3, child: Text(dateText, strutStyle: AStyles.overflowStrut)),
Expanded(flex: 2, child: Text(resolutionText, strutStyle: AStyles.overflowStrut)),
],
);
}

View file

@ -1,5 +1,5 @@
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/viewer/overlay/details/details.dart';
import 'package:decorated_icon/decorated_icon.dart';
import 'package:flutter/material.dart';
@ -31,7 +31,7 @@ class OverlayDescriptionRow extends StatelessWidget {
TextSpan(text: description),
],
),
strutStyle: Constants.overflowStrutStyle,
strutStyle: AStyles.overflowStrut,
);
}
}

View file

@ -3,7 +3,7 @@ import 'package:aves/model/entry/extensions/location.dart';
import 'package:aves/model/settings/enums/coordinate_format.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/viewer/overlay/details/details.dart';
import 'package:decorated_icon/decorated_icon.dart';
@ -34,7 +34,7 @@ class OverlayLocationRow extends AnimatedWidget {
children: [
DecoratedIcon(AIcons.location, size: ViewerDetailOverlayContent.iconSize, shadows: ViewerDetailOverlayContent.shadows(context)),
const SizedBox(width: ViewerDetailOverlayContent.iconPadding),
Expanded(child: Text(location, strutStyle: Constants.overflowStrutStyle)),
Expanded(child: Text(location, strutStyle: AStyles.overflowStrut)),
],
);
}

View file

@ -1,7 +1,9 @@
import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/multipage.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/viewer/multipage/controller.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class OverlayPositionTitleRow extends StatelessWidget {
@ -26,9 +28,9 @@ class OverlayPositionTitleRow extends StatelessWidget {
[
if (collectionPosition != null) collectionPosition,
if (pagePosition != null) pagePosition,
if (title != null) '${Constants.fsi}$title${Constants.pdi}',
].join(Constants.separator),
strutStyle: Constants.overflowStrutStyle);
if (title != null) '${Unicode.FSI}$title${Unicode.PDI}',
].join(AText.separator),
strutStyle: AStyles.overflowStrut);
if (multiPageController == null) return toText();

View file

@ -1,6 +1,7 @@
import 'package:aves/model/entry/entry.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/viewer/overlay/details/details.dart';
import 'package:collection/collection.dart';
@ -40,7 +41,7 @@ class OverlayRatingTagsRow extends AnimatedWidget {
children: [
TextSpan(text: ratingString),
if (hasTags) ...[
if (ratingString.isNotEmpty) const TextSpan(text: Constants.separator),
if (ratingString.isNotEmpty) const TextSpan(text: AText.separator),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Padding(
@ -52,11 +53,11 @@ class OverlayRatingTagsRow extends AnimatedWidget {
),
),
),
TextSpan(text: tags.join(Constants.separator)),
TextSpan(text: tags.join(AText.separator)),
]
],
),
strutStyle: Constants.overflowStrutStyle,
strutStyle: AStyles.overflowStrut,
);
}
}

View file

@ -1,6 +1,7 @@
import 'package:aves/model/metadata/overlay.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/viewer/overlay/details/details.dart';
import 'package:decorated_icon/decorated_icon.dart';
@ -20,22 +21,22 @@ class OverlayShootingRow extends StatelessWidget {
final locale = context.l10n.localeName;
final aperture = details.aperture;
final apertureText = aperture != null ? 'ƒ/${NumberFormat('0.0', locale).format(aperture)}' : Constants.overlayUnknown;
final apertureText = aperture != null ? 'ƒ/${NumberFormat('0.0', locale).format(aperture)}' : AText.valueNotAvailable;
final focalLength = details.focalLength;
final focalLengthText = focalLength != null ? context.l10n.focalLength(NumberFormat('0.#', locale).format(focalLength)) : Constants.overlayUnknown;
final focalLengthText = focalLength != null ? context.l10n.focalLength(NumberFormat('0.#', locale).format(focalLength)) : AText.valueNotAvailable;
final iso = details.iso;
final isoText = iso != null ? 'ISO$iso' : Constants.overlayUnknown;
final isoText = iso != null ? 'ISO$iso' : AText.valueNotAvailable;
return Row(
children: [
DecoratedIcon(AIcons.shooting, size: ViewerDetailOverlayContent.iconSize, shadows: ViewerDetailOverlayContent.shadows(context)),
const SizedBox(width: ViewerDetailOverlayContent.iconPadding),
Expanded(child: Text(apertureText, strutStyle: Constants.overflowStrutStyle)),
Expanded(child: Text(details.exposureTime ?? Constants.overlayUnknown, strutStyle: Constants.overflowStrutStyle)),
Expanded(child: Text(focalLengthText, strutStyle: Constants.overflowStrutStyle)),
Expanded(child: Text(isoText, strutStyle: Constants.overflowStrutStyle)),
Expanded(child: Text(apertureText, strutStyle: AStyles.overflowStrut)),
Expanded(child: Text(details.exposureTime ?? AText.valueNotAvailable, strutStyle: AStyles.overflowStrut)),
Expanded(child: Text(focalLengthText, strutStyle: AStyles.overflowStrut)),
Expanded(child: Text(isoText, strutStyle: AStyles.overflowStrut)),
],
);
}

View file

@ -2,7 +2,7 @@ import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/selection.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/common/basic/text/animated_diff.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
@ -50,7 +50,7 @@ class SelectionButton extends StatelessWidget {
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Text(Constants.separator),
child: Text(AText.separator),
),
Selector<Selection<AvesEntry>, bool>(
selector: (context, selection) => selection.isSelected({mainEntry}),

View file

@ -1,3 +1,4 @@
import 'package:aves/ref/unicode.dart';
import 'package:aves/widgets/viewer/visual/video/subtitle/line.dart';
import 'package:aves/widgets/viewer/visual/video/subtitle/span.dart';
import 'package:aves/widgets/viewer/visual/video/subtitle/style.dart';
@ -39,8 +40,6 @@ class AssParser {
// e.g. m 937.5 472.67 b 937.5 472.67 937.25 501.25 960 501.5 960 501.5 937.5 500.33 937.5 529.83
static final pathPattern = RegExp(r'([mnlbspc])([.\s\d]+)');
static const noBreakSpace = '\u00A0';
// Parse text with ASS style overrides
// cf https://aegi.vmoe.info/docs/3.0/ASS_Tags/
// e.g. `And I'm like, "We can't {\i1}not{\i0} see it."`
@ -389,7 +388,7 @@ class AssParser {
);
}
static String _replaceChars(String text) => text.replaceAll(r'\h', noBreakSpace).replaceAll(r'\N', '\n').trim();
static String _replaceChars(String text) => text.replaceAll(r'\h', Unicode.noBreakSpace).replaceAll(r'\N', '\n').trim();
static int? _parseAlpha(String param) {
final match = alphaPattern.firstMatch(param);

View file

@ -3,7 +3,7 @@ import 'package:aves/model/settings/defaults.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/about/policy_page.dart';
import 'package:aves/widgets/common/basic/link_chip.dart';
import 'package:aves/widgets/common/basic/markdown_container.dart';
@ -174,7 +174,7 @@ class _WelcomePageState extends State<WelcomePage> {
value: settings.isInstalledAppAccessAllowed,
onChanged: (v) => setState(() => settings.isInstalledAppAccessAllowed = v),
title: Text(l10n.settingsAllowInstalledAppAccess),
subtitle: Text([l10n.welcomeOptional, l10n.settingsAllowInstalledAppAccessSubtitle].join(Constants.separator)),
subtitle: Text([l10n.welcomeOptional, l10n.settingsAllowInstalledAppAccessSubtitle].join(AText.separator)),
contentPadding: contentPadding,
),
if (canEnableErrorReporting)