rtl fixes
This commit is contained in:
parent
273ec45a28
commit
059e852ed1
10 changed files with 39 additions and 19 deletions
|
@ -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,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
class SupportedLocales {
|
||||
static const languagesByLanguageCode = {
|
||||
'ar': 'العربية',
|
||||
'be': 'Беларуская мова',
|
||||
'cs': 'Čeština',
|
||||
'de': 'Deutsch',
|
||||
|
|
|
@ -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}',
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'),
|
||||
];
|
||||
|
|
Loading…
Reference in a new issue