From 9889aae2feefa7d057befdcc3e16e7f7f5562b9e Mon Sep 17 00:00:00 2001 From: Andriy Kushnir Date: Mon, 1 Dec 2025 09:20:15 +0200 Subject: [PATCH 1/7] Fix regression after new linter rules --- test/command_hint_test.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/command_hint_test.dart b/test/command_hint_test.dart index 68812be5f..84f558635 100644 --- a/test/command_hint_test.dart +++ b/test/command_hint_test.dart @@ -8,8 +8,7 @@ import 'utils/test_client.dart'; void main() async { test('Check for missing /command hints', () async { final translated = - jsonDecode(File('lib/l10n/intl_en.arb').readAsStringSync()) - .keys + jsonDecode(File('lib/l10n/intl_en.arb').readAsStringSync()).keys .where((String k) => k.startsWith('commandHint_')) .map((k) => k.replaceFirst('commandHint_', '')); final commands = (await prepareTestClient()).commands.keys; From 903f7c7d1584164f033fe4413a385c28949fae6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Mon, 1 Dec 2025 14:44:29 +0100 Subject: [PATCH 2/7] fix: Render not permitted html tags as text instead of hiding --- lib/pages/chat/events/html_message.dart | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index 3f82806b5..fcf1dd2c4 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -156,8 +156,8 @@ class HtmlMessage extends StatelessWidget { // We must not render elements nested more than 100 elements deep: if (depth >= 100) return const TextSpan(); - // This is a text node, so we render it as text: - if (node is! dom.Element) { + // This is a text node or not permitted node, so we render it as text: + if (node is! dom.Element || !allowedHtmlTags.contains(node.localName)) { var text = node.text ?? ''; // Single linebreak nodes between Elements are ignored: if (text == '\n') text = ''; @@ -170,9 +170,6 @@ class HtmlMessage extends StatelessWidget { ); } - // We must not render tags which are not in the allow list: - if (!allowedHtmlTags.contains(node.localName)) return const TextSpan(); - switch (node.localName) { case 'br': return const TextSpan(text: '\n'); From 3b181291cc91a536ea2b418171f184cf83bb9dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Mon, 1 Dec 2025 14:44:37 +0100 Subject: [PATCH 3/7] fix: Do not render html in unformatted messages --- lib/pages/chat/events/message_content.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index 792c63814..5cfd55c28 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -241,7 +241,7 @@ class MessageContent extends StatelessWidget { } var html = AppSettings.renderHtml.value && event.isRichMessage ? event.formattedText - : event.body; + : event.body.replaceAll('<', '<').replaceAll('>', '>'); if (event.messageType == MessageTypes.Emote) { html = '* $html'; } From 86a73f9909b35abcbdaefded2aceee29c149cf2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Tue, 2 Dec 2025 09:20:32 +0100 Subject: [PATCH 4/7] chore: Follow up html tag rendering --- lib/pages/chat/events/html_message.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index fcf1dd2c4..f6cb99003 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -86,10 +86,10 @@ class HtmlMessage extends StatelessWidget { 'rt', 'html', 'body', - // Workaround for https://github.com/krille-chan/fluffychat/issues/507 - 'tg-forward', }; + static const Set ignoredHtmlTags = {'mx-reply'}; + /// We add line breaks before these tags: static const Set blockHtmlTags = { 'p', @@ -170,6 +170,8 @@ class HtmlMessage extends StatelessWidget { ); } + if (ignoredHtmlTags.contains(node.localName)) return const TextSpan(); + switch (node.localName) { case 'br': return const TextSpan(text: '\n'); From 89a167dc5713b9a50d71e9514da2f8e08f42ff8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Tue, 2 Dec 2025 11:06:41 +0100 Subject: [PATCH 5/7] chore: Follow up html rendering --- lib/pages/chat/events/html_message.dart | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index f6cb99003..51defb5f5 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -156,6 +156,11 @@ class HtmlMessage extends StatelessWidget { // We must not render elements nested more than 100 elements deep: if (depth >= 100) return const TextSpan(); + if (node is dom.Element && + ignoredHtmlTags.contains(node.localName?.toLowerCase())) { + return const TextSpan(); + } + // This is a text node or not permitted node, so we render it as text: if (node is! dom.Element || !allowedHtmlTags.contains(node.localName)) { var text = node.text ?? ''; @@ -170,8 +175,6 @@ class HtmlMessage extends StatelessWidget { ); } - if (ignoredHtmlTags.contains(node.localName)) return const TextSpan(); - switch (node.localName) { case 'br': return const TextSpan(text: '\n'); @@ -260,13 +263,15 @@ class HtmlMessage extends StatelessWidget { child: Text.rich( TextSpan( children: [ - if (node.parent?.localName == 'ul') - const TextSpan(text: '• '), - if (node.parent?.localName == 'ol') - TextSpan( - text: - '${(node.parent?.nodes.whereType().toList().indexOf(node) ?? 0) + (int.tryParse(node.parent?.attributes['start'] ?? '1') ?? 1)}. ', - ), + if (!isCheckbox) ...[ + if (node.parent?.localName == 'ul') + const TextSpan(text: '• '), + if (node.parent?.localName == 'ol') + TextSpan( + text: + '${(node.parent?.nodes.whereType().toList().indexOf(node) ?? 0) + (int.tryParse(node.parent?.attributes['start'] ?? '1') ?? 1)}. ', + ), + ], if (node.className == 'task-list-item') WidgetSpan( child: Padding( From 5c7520fd73c139d7753f6be362fc3db89f06873d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Tue, 2 Dec 2025 14:47:49 +0100 Subject: [PATCH 6/7] chore: Use license_checker from pub again --- pubspec.lock | 11 +++++------ pubspec.yaml | 4 +--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 00e5f83d2..a5a5b4931 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1015,12 +1015,11 @@ packages: license_checker: dependency: "direct dev" description: - path: "." - ref: HEAD - resolved-ref: "38a65ff5b4b65db092b11dad999081388f75ece8" - url: "https://github.com/krille-chan/license_checker.git" - source: git - version: "1.6.0" + name: license_checker + sha256: "8a35b6946e50811e070ac6fe4717ee431cd1a334e080df2116956b54b0bb0d0f" + url: "https://pub.dev" + source: hosted + version: "1.6.2" linkify: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 202ca1edb..6a4bcc44a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -92,9 +92,7 @@ dev_dependencies: import_sorter: ^4.6.0 integration_test: sdk: flutter - # Waiting for https://github.com/rufman/license_checker/pull/47 - license_checker: - git: https://github.com/krille-chan/license_checker.git + license_checker: ^1.6.2 translations_cleaner: ^0.0.5 import_sorter: From 037393c5983c9dcbf5654e103b8fafd9317edefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Wed, 3 Dec 2025 08:09:08 +0100 Subject: [PATCH 7/7] chore: Override sqlcipher license --- licenses.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/licenses.yaml b/licenses.yaml index c10273e32..fe53d876b 100644 --- a/licenses.yaml +++ b/licenses.yaml @@ -27,6 +27,7 @@ packageLicenseOverride: platform_detect: Apache-2.0 rxdart: Apache-2.0 flutter_new_badger: MIT + sqlcipher_flutter_libs: MIT # flutter's internal packages flutter_driver: BSD-3-Clause