From 81977ea4d894f961e09349d01d3c858a77d3467c Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 20 Dec 2023 14:21:06 +0100 Subject: [PATCH] fixed text / strut styles --- lib/theme/styles.dart | 4 ---- lib/widgets/about/translators.dart | 1 - lib/widgets/collection/grid/list_details.dart | 2 -- .../collection/grid/list_details_theme.dart | 18 ++++++++++++------ .../common/basic/text/animated_diff.dart | 19 ++++++++++++++----- lib/widgets/common/grid/header.dart | 12 +++++++++--- .../identity/buttons/captioned_button.dart | 10 +++++++--- .../pick_dialogs/location_pick_page.dart | 3 --- .../filter_grids/common/list_details.dart | 3 --- .../common/list_details_theme.dart | 8 ++++---- lib/widgets/map/address_row.dart | 2 -- lib/widgets/map/date_row.dart | 2 -- lib/widgets/viewer/overlay/details/date.dart | 5 ++--- .../viewer/overlay/details/description.dart | 2 -- .../viewer/overlay/details/location.dart | 3 +-- .../overlay/details/position_title.dart | 13 ++++++------- .../viewer/overlay/details/rating_tags.dart | 2 -- .../viewer/overlay/details/shooting.dart | 9 ++++----- 18 files changed, 59 insertions(+), 59 deletions(-) diff --git a/lib/theme/styles.dart b/lib/theme/styles.dart index bd8b584f2..6cacf0b53 100644 --- a/lib/theme/styles.dart +++ b/lib/theme/styles.dart @@ -3,10 +3,6 @@ import 'dart:ui'; import 'package:flutter/painting.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, diff --git a/lib/widgets/about/translators.dart b/lib/widgets/about/translators.dart index b69e2288a..e3056be10 100644 --- a/lib/widgets/about/translators.dart +++ b/lib/widgets/about/translators.dart @@ -112,7 +112,6 @@ class _RandomTextSpanHighlighterState extends State<_RandomTextSpanHighlighter> ]) ], ), - strutStyle: const StrutStyle(height: 1.5, forceStrutHeight: true), ); } } diff --git a/lib/widgets/collection/grid/list_details.dart b/lib/widgets/collection/grid/list_details.dart index 45a1a86ec..8b3c9790e 100644 --- a/lib/widgets/collection/grid/list_details.dart +++ b/lib/widgets/collection/grid/list_details.dart @@ -4,7 +4,6 @@ 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/file_utils.dart'; @@ -60,7 +59,6 @@ class EntryListDetails extends StatelessWidget { children: spans, ), style: style, - strutStyle: AStyles.overflowStrut, softWrap: false, overflow: TextOverflow.fade, ); diff --git a/lib/widgets/collection/grid/list_details_theme.dart b/lib/widgets/collection/grid/list_details_theme.dart index 38fe2b901..2fc551f8b 100644 --- a/lib/widgets/collection/grid/list_details_theme.dart +++ b/lib/widgets/collection/grid/list_details_theme.dart @@ -1,5 +1,4 @@ import 'package:aves/theme/format.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'; @@ -29,11 +28,16 @@ class EntryListDetailsTheme extends StatelessWidget { final textScaler = mq.textScaler; final textTheme = Theme.of(context).textTheme; - final titleStyle = textTheme.bodyMedium!; - final captionStyle = textTheme.bodySmall!; + // specify `height` for accurate paragraph height measurement + final defaultTextHeight = DefaultTextStyle.of(context).style.height; + final titleStyle = textTheme.bodyMedium!.copyWith(height: defaultTextHeight); + final captionStyle = textTheme.bodySmall!.copyWith(height: defaultTextHeight); final titleLineHeightParagraph = RenderParagraph( - TextSpan(text: 'Fake Title', style: titleStyle), + TextSpan( + text: 'Fake Title', + style: titleStyle, + ), textDirection: TextDirection.ltr, textScaler: textScaler, )..layout(const BoxConstraints(), parentUsesSize: true); @@ -41,10 +45,12 @@ class EntryListDetailsTheme extends StatelessWidget { titleLineHeightParagraph.dispose(); final captionLineHeightParagraph = RenderParagraph( - TextSpan(text: formatDateTime(DateTime.now(), locale, use24hour), style: captionStyle), + TextSpan( + text: formatDateTime(DateTime.now(), locale, use24hour), + style: captionStyle, + ), textDirection: TextDirection.ltr, textScaler: textScaler, - strutStyle: AStyles.overflowStrut, )..layout(const BoxConstraints(), parentUsesSize: true); final captionLineHeight = captionLineHeightParagraph.getMaxIntrinsicHeight(double.infinity); diff --git a/lib/widgets/common/basic/text/animated_diff.dart b/lib/widgets/common/basic/text/animated_diff.dart index 213a2a58e..a76726e25 100644 --- a/lib/widgets/common/basic/text/animated_diff.dart +++ b/lib/widgets/common/basic/text/animated_diff.dart @@ -29,6 +29,14 @@ class _AnimatedDiffTextState extends State with SingleTickerPr late final Animation _animation; final List<_TextDiff> _diffs = []; + TextStyle get _textStyle { + final style = widget.textStyle ?? const TextStyle(); + // specify `height` for accurate paragraph height measurement + return style.copyWith(height: style.height ?? DefaultTextStyle.of(context).style.height); + } + + StrutStyle? get _strutStyle => widget.strutStyle; + @override void initState() { super.initState(); @@ -101,24 +109,25 @@ class _AnimatedDiffTextState extends State with SingleTickerPr child: Text( text, key: Key(text), + style: _textStyle, ), ), ), ); }).toList(), ), - strutStyle: widget.strutStyle, + strutStyle: _strutStyle, ); }, ); } - Size textSize(String text) { + Size _textSize(String text) { final paragraph = RenderParagraph( - TextSpan(text: text, style: widget.textStyle), + TextSpan(text: text, style: _textStyle), textDirection: Directionality.of(context), textScaler: MediaQuery.textScalerOf(context), - strutStyle: widget.strutStyle, + strutStyle: _strutStyle, )..layout(const BoxConstraints(), parentUsesSize: true); final width = paragraph.getMaxIntrinsicWidth(double.infinity); final height = paragraph.getMaxIntrinsicHeight(double.infinity); @@ -140,7 +149,7 @@ class _AnimatedDiffTextState extends State with SingleTickerPr ..clear() ..addAll(d.map((diff) { final text = diff.text; - final size = textSize(text); + final size = _textSize(text); return switch (diff.operation) { Operation.delete => (text, null, size, Size.zero), Operation.insert => (null, text, Size.zero, size), diff --git a/lib/widgets/common/grid/header.dart b/lib/widgets/common/grid/header.dart index 376df39e6..b1efa5884 100644 --- a/lib/widgets/common/grid/header.dart +++ b/lib/widgets/common/grid/header.dart @@ -68,7 +68,7 @@ class SectionHeader extends StatelessWidget { sectionKey: sectionKey, browsingBuilder: leading != null ? (context) => Container( - padding: const EdgeInsetsDirectional.only(end: 8, bottom: 4), + padding: const EdgeInsetsDirectional.only(end: 8), width: leadingSize.width, height: leadingSize.height, child: leading, @@ -80,7 +80,7 @@ class SectionHeader extends StatelessWidget { ), TextSpan( text: title, - style: AStyles.unknownTitleText, + style: _headerTextStyle(context), ), if (trailing != null) WidgetSpan( @@ -152,7 +152,7 @@ class SectionHeader extends StatelessWidget { if (hasTrailing) TextSpan(text: '\u200A' * 17), TextSpan( text: title, - style: AStyles.unknownTitleText, + style: _headerTextStyle(context), ), ], ), @@ -163,6 +163,12 @@ class SectionHeader extends StatelessWidget { paragraph.dispose(); return height; } + + static TextStyle _headerTextStyle(BuildContext context) { + // specify `height` for accurate paragraph height measurement + final defaultTextHeight = DefaultTextStyle.of(context).style.height; + return AStyles.unknownTitleText.copyWith(height: defaultTextHeight); + } } class _SectionSelectableLeading extends StatelessWidget { diff --git a/lib/widgets/common/identity/buttons/captioned_button.dart b/lib/widgets/common/identity/buttons/captioned_button.dart index 72d4fdebf..a3cda2caf 100644 --- a/lib/widgets/common/identity/buttons/captioned_button.dart +++ b/lib/widgets/common/identity/buttons/captioned_button.dart @@ -39,7 +39,7 @@ class CaptionedButton extends StatefulWidget { var height = width; if (showCaption) { final paragraph = RenderParagraph( - TextSpan(text: text, style: CaptionedButtonText.textStyle(context)), + TextSpan(text: text, style: CaptionedButtonText._textStyle(context)), textDirection: TextDirection.ltr, textScaler: MediaQuery.textScalerOf(context), maxLines: CaptionedButtonText.maxLines, @@ -112,7 +112,7 @@ class _CaptionedButtonState extends State { child: ValueListenableBuilder( valueListenable: _focusedNotifier, builder: (context, focused, child) { - final style = CaptionedButtonText.textStyle(context); + final style = CaptionedButtonText._textStyle(context); return AnimatedDefaultTextStyle( style: focused ? style.copyWith( @@ -176,5 +176,9 @@ class CaptionedButtonText extends StatelessWidget { ); } - static TextStyle textStyle(BuildContext context) => Theme.of(context).textTheme.bodySmall!; + static TextStyle _textStyle(BuildContext context) { + // specify `height` for accurate paragraph height measurement + final defaultTextHeight = DefaultTextStyle.of(context).style.height; + return Theme.of(context).textTheme.bodySmall!.copyWith(height: defaultTextHeight); + } } diff --git a/lib/widgets/dialogs/pick_dialogs/location_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/location_pick_page.dart index af859416c..4c8d13d1e 100644 --- a/lib/widgets/dialogs/pick_dialogs/location_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/location_pick_page.dart @@ -8,7 +8,6 @@ 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/theme/styles.dart'; import 'package:aves/theme/text.dart'; import 'package:aves/utils/debouncer.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; @@ -280,7 +279,6 @@ class _AddressRowState extends State<_AddressRow> { builder: (context, addressLine, child) { return Text( addressLine ?? AText.valueNotAvailable, - strutStyle: AStyles.overflowStrut, softWrap: false, overflow: TextOverflow.fade, maxLines: 1, @@ -331,7 +329,6 @@ class _CoordinateRow extends StatelessWidget { Expanded( child: Text( location != null ? settings.coordinateFormat.format(context, location!) : AText.valueNotAvailable, - strutStyle: AStyles.overflowStrut, softWrap: false, overflow: TextOverflow.fade, maxLines: 1, diff --git a/lib/widgets/filter_grids/common/list_details.dart b/lib/widgets/filter_grids/common/list_details.dart index ea43c32ea..955ff70fb 100644 --- a/lib/widgets/filter_grids/common/list_details.dart +++ b/lib/widgets/filter_grids/common/list_details.dart @@ -4,7 +4,6 @@ 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/file_utils.dart'; @@ -107,7 +106,6 @@ class FilterListDetails extends StatelessWidget { child: Text( dateText, style: detailsTheme.captionStyle, - strutStyle: AStyles.overflowStrut, softWrap: false, overflow: TextOverflow.fade, ), @@ -158,7 +156,6 @@ class FilterListDetails extends StatelessWidget { Text( '${l10n.itemCount(source.count(filter))} • ${formatFileSize(locale, source.size(filter))}', style: detailsTheme.captionStyle, - strutStyle: AStyles.overflowStrut, softWrap: false, overflow: TextOverflow.fade, ), diff --git a/lib/widgets/filter_grids/common/list_details_theme.dart b/lib/widgets/filter_grids/common/list_details_theme.dart index 049f91c73..dbf1b3a8a 100644 --- a/lib/widgets/filter_grids/common/list_details_theme.dart +++ b/lib/widgets/filter_grids/common/list_details_theme.dart @@ -1,7 +1,6 @@ import 'dart:math'; import 'package:aves/theme/format.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'; @@ -34,8 +33,10 @@ class FilterListDetailsTheme extends StatelessWidget { final textTheme = Theme.of(context).textTheme; final titleStyleBase = textTheme.bodyMedium!; - final titleStyle = titleStyleBase.copyWith(fontSize: textScaler.scale(titleStyleBase.fontSize!)); - final captionStyle = textTheme.bodySmall!; + // specify `height` for accurate paragraph height measurement + final defaultTextHeight = DefaultTextStyle.of(context).style.height; + final titleStyle = titleStyleBase.copyWith(fontSize: textScaler.scale(titleStyleBase.fontSize!), height: defaultTextHeight); + final captionStyle = textTheme.bodySmall!.copyWith(height: defaultTextHeight); final titleIconSize = textScaler.scale(AvesFilterChip.iconSize); final titleLineHeightParagraph = RenderParagraph( @@ -50,7 +51,6 @@ class FilterListDetailsTheme extends StatelessWidget { TextSpan(text: formatDateTime(DateTime.now(), locale, use24hour), style: captionStyle), textDirection: TextDirection.ltr, textScaler: textScaler, - strutStyle: AStyles.overflowStrut, )..layout(const BoxConstraints(), parentUsesSize: true); final captionLineHeight = captionLineHeightParagraph.getMaxIntrinsicHeight(double.infinity); captionLineHeightParagraph.dispose(); diff --git a/lib/widgets/map/address_row.dart b/lib/widgets/map/address_row.dart index 6c760d9e5..252b6c5d2 100644 --- a/lib/widgets/map/address_row.dart +++ b/lib/widgets/map/address_row.dart @@ -5,7 +5,6 @@ import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/services/geocoding_service.dart'; import 'package:aves/theme/icons.dart'; -import 'package:aves/theme/styles.dart'; import 'package:aves/theme/text.dart'; import 'package:flutter/material.dart'; @@ -78,7 +77,6 @@ class _MapAddressRowState extends State { TextSpan(text: location), ], ), - strutStyle: AStyles.overflowStrut, softWrap: false, overflow: TextOverflow.fade, maxLines: 1, diff --git a/lib/widgets/map/date_row.dart b/lib/widgets/map/date_row.dart index 33e5893ca..e663afcb0 100644 --- a/lib/widgets/map/date_row.dart +++ b/lib/widgets/map/date_row.dart @@ -1,7 +1,6 @@ import 'package:aves/model/entry/entry.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/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/map/info_row.dart'; @@ -35,7 +34,6 @@ class MapDateRow extends StatelessWidget { TextSpan(text: dateText), ], ), - strutStyle: AStyles.overflowStrut, softWrap: false, overflow: TextOverflow.fade, maxLines: 1, diff --git a/lib/widgets/viewer/overlay/details/date.dart b/lib/widgets/viewer/overlay/details/date.dart index e6e77fb55..480ce4c2e 100644 --- a/lib/widgets/viewer/overlay/details/date.dart +++ b/lib/widgets/viewer/overlay/details/date.dart @@ -2,7 +2,6 @@ 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/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'; @@ -37,8 +36,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: AStyles.overflowStrut)), - Expanded(flex: 2, child: Text(resolutionText, strutStyle: AStyles.overflowStrut)), + Expanded(flex: 3, child: Text(dateText)), + Expanded(flex: 2, child: Text(resolutionText)), ], ); } diff --git a/lib/widgets/viewer/overlay/details/description.dart b/lib/widgets/viewer/overlay/details/description.dart index 171ecde5e..18e6da347 100644 --- a/lib/widgets/viewer/overlay/details/description.dart +++ b/lib/widgets/viewer/overlay/details/description.dart @@ -1,5 +1,4 @@ import 'package:aves/theme/icons.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 +30,6 @@ class OverlayDescriptionRow extends StatelessWidget { TextSpan(text: description), ], ), - strutStyle: AStyles.overflowStrut, ); } } diff --git a/lib/widgets/viewer/overlay/details/location.dart b/lib/widgets/viewer/overlay/details/location.dart index 12b7126be..4df7b891c 100644 --- a/lib/widgets/viewer/overlay/details/location.dart +++ b/lib/widgets/viewer/overlay/details/location.dart @@ -3,7 +3,6 @@ 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/theme/styles.dart'; import 'package:aves/theme/text.dart'; import 'package:aves/widgets/viewer/overlay/details/details.dart'; import 'package:decorated_icon/decorated_icon.dart'; @@ -33,7 +32,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 ?? AText.valueNotAvailable, strutStyle: AStyles.overflowStrut)), + Expanded(child: Text(location ?? AText.valueNotAvailable)), ], ); } diff --git a/lib/widgets/viewer/overlay/details/position_title.dart b/lib/widgets/viewer/overlay/details/position_title.dart index 167594b8b..346f66dd3 100644 --- a/lib/widgets/viewer/overlay/details/position_title.dart +++ b/lib/widgets/viewer/overlay/details/position_title.dart @@ -1,6 +1,5 @@ import 'package:aves/model/entry/entry.dart'; import 'package:aves/model/multipage.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'; @@ -25,12 +24,12 @@ class OverlayPositionTitleRow extends StatelessWidget { @override Widget build(BuildContext context) { Text toText({String? pagePosition}) => Text( - [ - if (collectionPosition != null) collectionPosition, - if (pagePosition != null) pagePosition, - if (title != null) '${Unicode.FSI}$title${Unicode.PDI}', - ].join(AText.separator), - strutStyle: AStyles.overflowStrut); + [ + if (collectionPosition != null) collectionPosition, + if (pagePosition != null) pagePosition, + if (title != null) '${Unicode.FSI}$title${Unicode.PDI}', + ].join(AText.separator), + ); if (multiPageController == null) return toText(); diff --git a/lib/widgets/viewer/overlay/details/rating_tags.dart b/lib/widgets/viewer/overlay/details/rating_tags.dart index f2b92c0d0..e777b9841 100644 --- a/lib/widgets/viewer/overlay/details/rating_tags.dart +++ b/lib/widgets/viewer/overlay/details/rating_tags.dart @@ -1,6 +1,5 @@ import 'package:aves/model/entry/entry.dart'; import 'package:aves/theme/icons.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'; @@ -57,7 +56,6 @@ class OverlayRatingTagsRow extends AnimatedWidget { ] ], ), - strutStyle: AStyles.overflowStrut, ); } } diff --git a/lib/widgets/viewer/overlay/details/shooting.dart b/lib/widgets/viewer/overlay/details/shooting.dart index 567e652be..94ea6f260 100644 --- a/lib/widgets/viewer/overlay/details/shooting.dart +++ b/lib/widgets/viewer/overlay/details/shooting.dart @@ -1,6 +1,5 @@ import 'package:aves/model/metadata/overlay.dart'; import 'package:aves/theme/icons.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'; @@ -33,10 +32,10 @@ class OverlayShootingRow extends StatelessWidget { children: [ DecoratedIcon(AIcons.shooting, size: ViewerDetailOverlayContent.iconSize, shadows: ViewerDetailOverlayContent.shadows(context)), const SizedBox(width: ViewerDetailOverlayContent.iconPadding), - 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)), + Expanded(child: Text(apertureText)), + Expanded(child: Text(details.exposureTime ?? AText.valueNotAvailable)), + Expanded(child: Text(focalLengthText)), + Expanded(child: Text(isoText)), ], ); }