diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart
index 877ddf428..9ddaa4fce 100644
--- a/lib/pages/chat/events/html_message.dart
+++ b/lib/pages/chat/events/html_message.dart
@@ -26,6 +26,30 @@ import 'package:fluffychat/widgets/matrix.dart';
import 'package:fluffychat/widgets/mxc_image.dart';
import '../../../utils/url_launcher.dart';
+class _TokenPosition {
+ final PangeaToken token;
+ final int startIndex;
+ final int endIndex;
+
+ _TokenPosition({
+ required this.token,
+ required this.startIndex,
+ required this.endIndex,
+ });
+}
+
+class _MessageChunk {
+ final int startIndex;
+ final int endIndex;
+ final String text;
+
+ _MessageChunk({
+ required this.startIndex,
+ required this.endIndex,
+ required this.text,
+ });
+}
+
class HtmlMessage extends StatelessWidget {
final String html;
final Room room;
@@ -229,7 +253,59 @@ class HtmlMessage extends StatelessWidget {
]);
}
- return result.join();
+ for (int i = 0; i < result.length; i++) {
+ final tag = result[i];
+ if (blockHtmlTags.contains(tag.htmlTagName) ||
+ fullLineHtmlTag.contains(tag.htmlTagName)) {
+ result[i] = ", ";
+ }
+ }
+
+ if (pangeaMessageEvent?.textDirection == TextDirection.rtl) {
+ final inverted = _invertTags(result);
+ return inverted.join().trim();
+ }
+ return result.join().trim();
+ }
+
+ List _invertTags(List tags) {
+ final List<(String, int)> stack = [];
+ final List<(int, int)> invertedTags = [];
+ for (int i = 0; i < tags.length; i++) {
+ final tag = tags[i];
+ if (!tag.contains('<') || tag.contains("
+ element.$1.htmlTagName == tag.htmlTagName &&
+ !element.$1.contains(""),
+ );
+ }
+
+ if (match != -1) {
+ // If the tag is already in the stack, we remove it
+ final (matchTag, matchIndex) = stack.removeAt(match);
+ invertedTags.add((matchIndex, i));
+ } else {
+ // If the tag is not in the stack, we add it
+ stack.insert(0, (tag, i));
+ }
+ }
+
+ for (final (start, end) in invertedTags) {
+ final startTag = tags[start];
+ final endTag = tags[end];
+
+ tags[start] = endTag;
+ tags[end] = startTag;
+ }
+
+ final inverted = tags.reversed.toList();
+ return inverted;
}
// Pangea#
@@ -377,6 +453,7 @@ class HtmlMessage extends StatelessWidget {
? () => onClick?.call(token)
: null,
child: RichText(
+ textDirection: pangeaMessageEvent?.textDirection,
text: TextSpan(
children: [
LinkifySpan(
@@ -1008,3 +1085,8 @@ extension on String {
extension on dom.Element {
dom.Element get rootElement => parent?.rootElement ?? this;
}
+
+extension on String {
+ String get htmlTagName =>
+ replaceAll('<', '').replaceAll('>', '').replaceAll('/', '').split(' ')[0];
+}
diff --git a/lib/pangea/events/event_wrappers/pangea_message_event.dart b/lib/pangea/events/event_wrappers/pangea_message_event.dart
index 0f01f2655..f6f7e6b91 100644
--- a/lib/pangea/events/event_wrappers/pangea_message_event.dart
+++ b/lib/pangea/events/event_wrappers/pangea_message_event.dart
@@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:developer';
+import 'dart:ui';
import 'package:flutter/foundation.dart';
@@ -18,6 +19,7 @@ import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/events/models/representation_content_model.dart';
import 'package:fluffychat/pangea/events/models/stt_translation_model.dart';
import 'package:fluffychat/pangea/events/models/tokens_event_content_model.dart';
+import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart';
import 'package:fluffychat/pangea/morphs/morph_features_enum.dart';
import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart';
import 'package:fluffychat/pangea/spaces/models/space_model.dart';
@@ -768,4 +770,9 @@ class PangeaMessageEvent {
tag: tag,
);
}
+
+ TextDirection get textDirection =>
+ PLanguageStore.rtlLanguageCodes.contains(messageDisplayLangCode)
+ ? TextDirection.rtl
+ : TextDirection.ltr;
}
diff --git a/lib/pangea/learning_settings/models/language_model.dart b/lib/pangea/learning_settings/models/language_model.dart
index 4029b9507..5e62e312e 100644
--- a/lib/pangea/learning_settings/models/language_model.dart
+++ b/lib/pangea/learning_settings/models/language_model.dart
@@ -1,21 +1,26 @@
import 'package:flutter/material.dart';
+import 'package:collection/collection.dart';
+
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart';
import 'package:fluffychat/pangea/learning_settings/enums/l2_support_enum.dart';
+import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart';
class LanguageModel {
final String langCode;
final String displayName;
final String script;
final L2SupportEnum l2Support;
+ final TextDirection? _textDirection;
LanguageModel({
required this.langCode,
required this.displayName,
this.script = LanguageKeys.unknownLanguage,
this.l2Support = L2SupportEnum.na,
- });
+ TextDirection? textDirection,
+ }) : _textDirection = textDirection;
factory LanguageModel.fromJson(json) {
final String code = json['language_code'] ??
@@ -31,6 +36,11 @@ class LanguageModel {
? L2SupportEnum.na.fromStorageString(json['l2_support'])
: L2SupportEnum.na,
script: json['script'] ?? LanguageKeys.unknownLanguage,
+ textDirection: json['text_direction'] != null
+ ? TextDirection.values.firstWhereOrNull(
+ (e) => e.name == json['text_direction'],
+ )
+ : null,
);
}
@@ -39,6 +49,7 @@ class LanguageModel {
'language_name': displayName,
'script': script,
'l2_support': l2Support.storageString,
+ 'text_direction': textDirection.name,
};
bool get l2 => l2Support != L2SupportEnum.na;
@@ -73,6 +84,16 @@ class LanguageModel {
String get langCodeShort => langCode.split('-').first;
+ TextDirection get _defaultTextDirection {
+ return PLanguageStore.rtlLanguageCodes.contains(langCodeShort)
+ ? TextDirection.rtl
+ : TextDirection.ltr;
+ }
+
+ TextDirection get textDirection {
+ return _textDirection ?? _defaultTextDirection;
+ }
+
@override
bool operator ==(Object other) {
if (other is LanguageModel) {
diff --git a/lib/pangea/learning_settings/utils/p_language_store.dart b/lib/pangea/learning_settings/utils/p_language_store.dart
index ed66d2bf9..075912e75 100644
--- a/lib/pangea/learning_settings/utils/p_language_store.dart
+++ b/lib/pangea/learning_settings/utils/p_language_store.dart
@@ -107,4 +107,19 @@ class PLanguageStore {
}
return null;
}
+
+ static final List rtlLanguageCodes = [
+ 'ar',
+ 'arc',
+ 'dv',
+ 'fa',
+ 'ha',
+ 'he',
+ 'khw',
+ 'ks',
+ 'ku',
+ 'ps',
+ 'ur',
+ 'yi',
+ ];
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 2e67fdca8..6045a6386 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -6,7 +6,7 @@ description: Learn a language while texting your friends.
# Pangea#
publish_to: none
# On version bump also increase the build number for F-Droid
-version: 4.1.10+2
+version: 4.1.12+2
environment:
sdk: ">=3.0.0 <4.0.0"
@@ -168,8 +168,8 @@ flutter:
# #Pangea
# uncomment this to enable mobile builds
# causes error with github actions
- # - .env
- # - assets/.env
+ - .env
+ - assets/.env
- assets/pangea/
- assets/pangea/bot_faces/
# Pangea#