rtl fixes

This commit is contained in:
Thibault Deckers 2023-12-10 23:28:17 +01:00
parent 273ec45a28
commit 059e852ed1
10 changed files with 39 additions and 19 deletions

View file

@ -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<BugReport> 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,
),
),

View file

@ -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

View file

@ -113,17 +113,22 @@ class RenderMosaicGridRow extends RenderBox with ContainerRenderObjectMixin<Rend
final thumbnailHeight = rowLayout.height - spacing;
size = Size(constraints.maxWidth, rowLayout.height);
final flipMainAxis = textDirection == TextDirection.rtl;
final sign = (flipMainAxis ? -1.0 : 1.0);
var i = 0;
var offset = Offset(flipMainAxis ? size.width - rowLayout.itemWidths[i] : 0, 0);
double offsetX = flipMainAxis ? size.width : 0;
while (child != null) {
final thumbnailWidth = rowLayout.itemWidths[i];
final childConstraints = BoxConstraints.tight(Size(thumbnailWidth, thumbnailHeight));
child.layout(childConstraints, parentUsesSize: false);
final childParentData = child.parentData! as _GridRowParentData;
childParentData.offset = offset;
final dx = sign * (thumbnailWidth + spacing);
offset += Offset(dx, 0);
if (flipMainAxis) {
offsetX -= thumbnailWidth;
}
childParentData.offset = Offset(offsetX, 0);
if (flipMainAxis) {
offsetX -= spacing;
} else {
offsetX += thumbnailWidth + spacing;
}
child = childParentData.nextSibling;
i++;
}

View file

@ -64,7 +64,7 @@ class _AvesMultiSelectionDialogState<T> extends State<AvesMultiSelectionDialog<T
setState(() {});
},
title: Align(
alignment: Alignment.centerLeft,
alignment: AlignmentDirectional.centerStart,
child: Text(title),
),
subtitle: subtitle != null

View file

@ -15,8 +15,8 @@ class HomeWidgetPainter {
final double devicePixelRatio;
static const backgroundGradient = LinearGradient(
begin: Alignment.bottomLeft,
end: Alignment.topRight,
begin: AlignmentDirectional.bottomStart,
end: AlignmentDirectional.topEnd,
colors: AColors.boraBoraGradient,
);

View file

@ -3,6 +3,7 @@
class SupportedLocales {
static const languagesByLanguageCode = {
'ar': 'العربية',
'be': 'Беларуская мова',
'cs': 'Čeština',
'de': 'Deutsch',

View file

@ -8,6 +8,7 @@ import 'package:aves/widgets/settings/common/tiles.dart';
import 'package:aves/widgets/settings/settings_definition.dart';
import 'package:aves/widgets/settings/thumbnails/collection_actions_editor_page.dart';
import 'package:aves/widgets/settings/thumbnails/overlay.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -68,6 +69,6 @@ class SettingsTileBurstPatterns extends SettingsTile {
onSelection: (v) => settings.collectionBurstPatterns = v,
tileTitle: title(context),
noneSubtitle: context.l10n.settingsCollectionBurstPatternsNone,
optionSubtitleBuilder: BurstPatterns.getExample,
optionSubtitleBuilder: (value) => '${Unicode.FSI}${BurstPatterns.getExample(value)}${Unicode.PDI}',
);
}

View file

@ -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),

View file

@ -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

View file

@ -116,20 +116,32 @@ class _InfoRowGroupState extends State<InfoRowGroup> {
(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'),
];