From 059e852ed184570217513e72f841a224c0d6a9f1 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 10 Dec 2023 23:28:17 +0100 Subject: [PATCH] rtl fixes --- lib/widgets/about/bug_report.dart | 2 ++ lib/widgets/aves_app.dart | 1 - .../common/grid/sections/mosaic/row.dart | 15 ++++++++---- .../selection_dialogs/multi_selection.dart | 2 +- lib/widgets/home_widget.dart | 4 ++-- lib/widgets/settings/language/locales.dart | 1 + .../settings/thumbnails/thumbnails.dart | 3 ++- .../settings/video/subtitle_sample.dart | 4 ++-- lib/widgets/viewer/info/basic_section.dart | 2 +- lib/widgets/viewer/info/common.dart | 24 ++++++++++++++----- 10 files changed, 39 insertions(+), 19 deletions(-) diff --git a/lib/widgets/about/bug_report.dart b/lib/widgets/about/bug_report.dart index 3c8276b15..671b3e0b6 100644 --- a/lib/widgets/about/bug_report.dart +++ b/lib/widgets/about/bug_report.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:io'; +import 'dart:ui' as ui; import 'package:aves/app_flavor.dart'; import 'package:aves/flutter_version.dart'; @@ -98,6 +99,7 @@ class _BugReportState extends State with FeedbackMixin { // as of Flutter v3.0.0, `SelectableText` does not allow passing the `scrollController` child: SelectableText( info, + textDirection: ui.TextDirection.ltr, style: Theme.of(context).textTheme.bodySmall, ), ), diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index ce9f8ccf7..84a02fff5 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -58,7 +58,6 @@ class AvesApp extends StatefulWidget { // temporary exclude locales not ready yet for prime time // `ckb`: add `flutter_ckb_localization` and necessary app localization delegates when ready static final _unsupportedLocales = { - 'ar', // Arabic 'bn', // Bengali 'ckb', // Kurdish (Central) 'fa', // Persian diff --git a/lib/widgets/common/grid/sections/mosaic/row.dart b/lib/widgets/common/grid/sections/mosaic/row.dart index 2cf0aa829..119840515 100644 --- a/lib/widgets/common/grid/sections/mosaic/row.dart +++ b/lib/widgets/common/grid/sections/mosaic/row.dart @@ -113,17 +113,22 @@ class RenderMosaicGridRow extends RenderBox with ContainerRenderObjectMixin extends State settings.collectionBurstPatterns = v, tileTitle: title(context), noneSubtitle: context.l10n.settingsCollectionBurstPatternsNone, - optionSubtitleBuilder: BurstPatterns.getExample, + optionSubtitleBuilder: (value) => '${Unicode.FSI}${BurstPatterns.getExample(value)}${Unicode.PDI}', ); } diff --git a/lib/widgets/settings/video/subtitle_sample.dart b/lib/widgets/settings/video/subtitle_sample.dart index 40879e56a..a7ffad64a 100644 --- a/lib/widgets/settings/video/subtitle_sample.dart +++ b/lib/widgets/settings/video/subtitle_sample.dart @@ -33,8 +33,8 @@ class SubtitleSample extends StatelessWidget { return Container( decoration: BoxDecoration( gradient: const LinearGradient( - begin: Alignment.bottomLeft, - end: Alignment.topRight, + begin: AlignmentDirectional.bottomStart, + end: AlignmentDirectional.topEnd, colors: AColors.boraBoraGradient, ), border: AvesBorder.border(context), diff --git a/lib/widgets/viewer/info/basic_section.dart b/lib/widgets/viewer/info/basic_section.dart index f3420fc6a..fa7c58a23 100644 --- a/lib/widgets/viewer/info/basic_section.dart +++ b/lib/widgets/viewer/info/basic_section.dart @@ -360,7 +360,7 @@ class _BasicInfoState extends State<_BasicInfo> { WidgetSpan( alignment: PlaceholderAlignment.middle, child: Padding( - padding: const EdgeInsetsDirectional.only(end: 4), + padding: const EdgeInsetsDirectional.only(start: 2, end: 4), child: ConstrainedBox( // use constraints instead of sizing `Image`, // so that it can collapse when handling an empty image diff --git a/lib/widgets/viewer/info/common.dart b/lib/widgets/viewer/info/common.dart index cf10ebcf9..8c9d706df 100644 --- a/lib/widgets/viewer/info/common.dart +++ b/lib/widgets/viewer/info/common.dart @@ -116,20 +116,32 @@ class _InfoRowGroupState extends State { (kv) { final key = kv.key; final value = kv.value; - final spanBuilder = spanBuilders[key] ?? _buildTextValueSpans; + final customSpanBuilder = spanBuilders[key]; + final spanBuilder = customSpanBuilder ?? _buildTextValueSpans; final thisSpaceSize = max(0.0, (baseValueX - keySizes[key]!)) + InfoRowGroup.keyValuePadding; - final textScaleFactor = textScaler.scale(thisSpaceSize) / thisSpaceSize; - return [ - TextSpan(text: _buildTextValue(key), style: _keyStyle), - WidgetSpan( + InlineSpan paddingSpan; + if (customSpanBuilder != null) { + // add padding using hair spaces instead of a straightforward `SizedBox` in a `WidgetSpan`, + // because ordering of multiple `WidgetSpan`s (e.g. with owner app icon) in Bidi context is tricky + final baseSpaceWidth = _getSpanWidth(TextSpan(text: '\u200A' * 100, style: _keyStyle), textScaler); + final spaceCount = (100 * thisSpaceSize / baseSpaceWidth).round(); + paddingSpan = TextSpan(text: '\u200A' * spaceCount); + } else { + final textScaleFactor = textScaler.scale(thisSpaceSize) / thisSpaceSize; + paddingSpan = WidgetSpan( child: SizedBox( width: thisSpaceSize / textScaleFactor, // as of Flutter v3.0.0, the underline decoration from the following `TextSpan` // is applied to the `WidgetSpan` too, so we add a dummy `Text` as a workaround child: const Text(''), ), - ), + ); + } + + return [ + TextSpan(text: _buildTextValue(key), style: _keyStyle), + paddingSpan, ...spanBuilder(context, key, value), if (key != lastKey) const TextSpan(text: '\n'), ];