From 102f3bba8e3efc5a6b894f0d8365431609454d90 Mon Sep 17 00:00:00 2001 From: Krille Date: Wed, 17 May 2023 12:26:59 +0200 Subject: [PATCH] refactor: Reimplement flutter matrix html locally --- lib/pages/chat/events/html_message.dart | 417 +++++++++++++----- lib/pages/chat/events/message_content.dart | 26 +- lib/pages/chat/events/reply_content.dart | 59 +-- lib/pages/chat/pinned_events.dart | 12 +- lib/pages/chat_details/chat_details_view.dart | 13 +- lib/pages/story/story_view.dart | 12 +- lib/widgets/public_room_bottom_sheet.dart | 12 +- pubspec.lock | 158 ++++--- pubspec.yaml | 17 +- 9 files changed, 433 insertions(+), 293 deletions(-) diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index 06f27a6d..adc691c7 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -1,31 +1,26 @@ import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:flutter_matrix_html/flutter_html.dart'; +import 'package:collection/collection.dart'; +import 'package:flutter_highlighter/flutter_highlighter.dart'; +import 'package:flutter_highlighter/themes/shades-of-purple.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_math_fork/flutter_math.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import '../../../config/app_config.dart'; -import '../../../config/setting_keys.dart'; -import '../../../utils/matrix_sdk_extensions/matrix_locals.dart'; +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/widgets/avatar.dart'; import '../../../utils/url_launcher.dart'; class HtmlMessage extends StatelessWidget { final String html; - final int? maxLines; final Room room; - final TextStyle? defaultTextStyle; - final TextStyle? linkStyle; - final double? emoteSize; + final Color? textColor; const HtmlMessage({ Key? key, required this.html, - this.maxLines, required this.room, - this.defaultTextStyle, - this.linkStyle, - this.emoteSize, + this.textColor, }) : super(key: key); @override @@ -46,101 +41,315 @@ class HtmlMessage extends StatelessWidget { '', ); + final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; + // there is no need to pre-validate the html, as we validate it while rendering - - final matrix = Matrix.of(context); - - final themeData = Theme.of(context); return Html( data: renderHtml, - defaultTextStyle: defaultTextStyle, - emoteSize: emoteSize, - linkStyle: linkStyle ?? - themeData.textTheme.bodyMedium!.copyWith( - color: themeData.colorScheme.secondary, - decoration: TextDecoration.underline, - decorationColor: themeData.colorScheme.secondary, - ), - shrinkToFit: true, - maxLines: maxLines, - onLinkTap: (url) => UrlLauncher(context, url).launchUrl(), - onPillTap: (url) => UrlLauncher(context, url).launchUrl(), - getMxcUrl: ( - String mxc, - double? width, - double? height, { - bool? animated = false, - }) { - final ratio = MediaQuery.of(context).devicePixelRatio; - return Uri.parse(mxc) - .getThumbnail( - matrix.client, - width: (width ?? 800) * ratio, - height: (height ?? 800) * ratio, - method: ThumbnailMethod.scale, - animated: AppConfig.autoplayImages ? animated : false, - ) - .toString(); + style: { + '*': Style( + color: textColor, + margin: Margins.all(0), + fontSize: FontSize(fontSize), + ), + 'a': Style(color: textColor?.withAlpha(150)), + 'h1': Style(fontSize: FontSize(fontSize * 3)), + 'h2': Style(fontSize: FontSize(fontSize * 2.5)), + 'h3': Style(fontSize: FontSize(fontSize * 2)), + 'h4': Style(fontSize: FontSize(fontSize * 1.75)), + 'h5': Style(fontSize: FontSize(fontSize * 1.5)), + 'h6': Style(fontSize: FontSize(fontSize * 1.25)), + // Otherwise list tiles are all in the same row$$ + 'li': Style(display: Display.block), }, - onImageTap: (url) => UrlLauncher(context, url).launchUrl(), - setCodeLanguage: (String key, String value) async { - await matrix.store.setItem('${SettingKeys.codeLanguage}.$key', value); - }, - getCodeLanguage: (String key) async { - return await matrix.store.getItem('${SettingKeys.codeLanguage}.$key'); - }, - getPillInfo: (String url) async { - final identityParts = url.parseIdentifierIntoParts(); - final identifier = identityParts?.primaryIdentifier; - if (identifier == null) { - return {}; - } - if (identifier.sigil == '@') { - // we have a user pill - final user = room.getState('m.room.member', identifier); - if (user != null) { - return user.content; - } - // there might still be a profile... - final profile = await room.client.getProfileFromUserId(identifier); - return { - 'displayname': profile.displayName, - 'avatar_url': profile.avatarUrl.toString(), - }; - } - if (identifier.sigil == '#') { - // we have an alias pill - for (final r in room.client.rooms) { - final state = r.getState('m.room.canonical_alias'); - if (state != null && - ((state.content['alias'] is String && - state.content['alias'] == identifier) || - (state.content['alt_aliases'] is List && - state.content['alt_aliases'].contains(identifier)))) { - // we have a room! - return { - 'displayname': - r.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), - 'avatar_url': r.getState('m.room.avatar')?.content['url'], - }; - } - } - return {}; - } - if (identifier.sigil == '!') { - // we have a room ID pill - final r = room.client.getRoomById(identifier); - if (r == null) { - return {}; - } - return { - 'displayname': - r.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), - 'avatar_url': r.getState('m.room.avatar')?.content['url'], - }; - } - return {}; + extensions: [ + UserPillExtension(context, room), + RoomPillExtension(context, room.client), + CodeExtension(fontSize: fontSize), + MatrixMathExtension( + style: TextStyle(fontSize: fontSize, color: textColor), + ), + ], + onLinkTap: (url, _, __) => UrlLauncher(context, url).launchUrl(), + onlyRenderTheseTags: const { + ...allowedHtmlTags, + // Needed to make it work properly + 'body', + 'html', }, + shrinkWrap: true, + ); + } + + /// Keep in sync with: https://spec.matrix.org/v1.6/client-server-api/#mroommessage-msgtypes + static const Set allowedHtmlTags = { + 'font', + 'del', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'blockquote', + 'p', + 'a', + 'ul', + 'ol', + 'sup', + 'sub', + 'li', + 'b', + 'i', + 'u', + 'strong', + 'em', + 'strike', + 'code', + 'hr', + 'br', + 'div', + 'table', + 'thead', + 'tbody', + 'tr', + 'th', + 'td', + 'caption', + 'pre', + 'span', + 'img', + 'details', + 'summary' + }; +} + +class MatrixMathExtension extends HtmlExtension { + final TextStyle? style; + + MatrixMathExtension({this.style}); + @override + Set get supportedTags => {'div'}; + + @override + bool matches(ExtensionContext context) { + if (context.elementName != 'div') return false; + final mathData = context.element?.attributes['data-mx-maths']; + return mathData != null; + } + + @override + InlineSpan build( + ExtensionContext context, + Map Function() parseChildren, + ) { + final data = context.element?.attributes['data-mx-maths'] ?? ''; + return WidgetSpan( + child: Math.tex( + data, + textStyle: style, + onErrorFallback: (e) { + Logs().d('Flutter math parse error', e); + return Text( + data, + style: style, + ); + }, + ), + ); + } +} + +class CodeExtension extends HtmlExtension { + final double fontSize; + + CodeExtension({required this.fontSize}); + @override + Set get supportedTags => {'code'}; + + @override + InlineSpan build( + ExtensionContext context, + Map Function() parseChildren, + ) => + WidgetSpan( + child: Material( + clipBehavior: Clip.hardEdge, + borderRadius: BorderRadius.circular(4), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: HighlightView( + context.element?.text ?? '', + language: context.element?.className + .split(' ') + .singleWhereOrNull( + (className) => className.startsWith('language-'), + ) + ?.split('language-') + .last ?? + 'md', + theme: shadesOfPurpleTheme, + padding: const EdgeInsets.all(6), + textStyle: TextStyle(fontSize: fontSize), + ), + ), + ), + ); +} + +class UserPillExtension extends HtmlExtension { + final Room room; + final BuildContext context; + + UserPillExtension(this.context, this.room); + @override + Set get supportedTags => {'a'}; + + @override + bool matches(ExtensionContext context) { + if (context.elementName != 'a') return false; + final href = context.element?.attributes['href']; + if (href == null) return false; + final uri = Uri.tryParse(href); + if (uri == null || uri.host != 'matrix.to') return false; + final userId = uri.fragment.split('/').last; + if (userId.sigil != '@') return false; + return true; + } + + @override + InlineSpan build( + ExtensionContext context, + Map Function() parseChildren, + ) { + final href = context.element!.attributes['href']!; + final uri = Uri.parse(href); + final userId = uri.fragment.split('/').last; + final user = room.unsafeGetUserFromMemoryOrFallback(userId); + return WidgetSpan( + child: MatrixPill( + name: user.calcDisplayname(), + avatar: user.avatarUrl, + uri: href, + outerContext: this.context, + ), + ); + } +} + +class RoomPillExtension extends HtmlExtension { + final Client client; + final BuildContext context; + + RoomPillExtension(this.context, this.client); + @override + Set get supportedTags => {'a'}; + + @override + bool matches(ExtensionContext context) { + if (context.elementName != 'a') return false; + final href = context.element?.attributes['href']; + if (href == null) return false; + final uri = Uri.tryParse(href); + if (uri == null || uri.host != 'matrix.to') return false; + final roomId = Uri.decodeComponent(uri.fragment.split('/').last); + if (!{'#', '!'}.contains(roomId.sigil)) return false; + return true; + } + + @override + InlineSpan build( + ExtensionContext context, + Map Function() parseChildren, + ) { + final href = context.element!.attributes['href']!; + final uri = Uri.parse(href); + final roomId = Uri.decodeComponent(uri.fragment.split('/').last); + + final room = roomId.sigil == '!' + ? client.getRoomById(roomId) + : client.getRoomByAlias(roomId); + if (room != null) { + return WidgetSpan( + child: MatrixPill( + name: room.getLocalizedDisplayname(), + avatar: room.avatar, + uri: href, + outerContext: this.context, + ), + ); + } + + return WidgetSpan( + child: FutureBuilder( + future: client.queryPublicRooms( + server: roomId.domain, + filter: PublicRoomQueryFilter( + genericSearchTerm: roomId, + ), + ), + builder: (context, snapshot) { + final room = snapshot.data; + return MatrixPill( + name: room?.chunk.singleOrNull?.name ?? roomId, + avatar: room?.chunk.singleOrNull?.avatarUrl, + uri: href, + outerContext: this.context, + ); + }, + ), + ); + } +} + +class MatrixPill extends StatelessWidget { + final String name; + final BuildContext outerContext; + final Uri? avatar; + final String uri; + + const MatrixPill({ + super.key, + required this.name, + required this.outerContext, + this.avatar, + required this.uri, + }); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: UrlLauncher(outerContext, uri).launchUrl, + child: Material( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppConfig.borderRadius), + side: BorderSide( + color: Theme.of(outerContext).colorScheme.onPrimaryContainer, + width: 0.5, + ), + ), + color: Theme.of(outerContext).colorScheme.primaryContainer, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 6.0), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Avatar( + mxContent: avatar, + name: name, + size: 16, + ), + const SizedBox(width: 6), + Text( + name, + style: TextStyle( + color: Theme.of(outerContext).colorScheme.onPrimaryContainer, + ), + ), + ], + ), + ), + ), ); } } diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index 843a7355..3186a029 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:matrix/matrix.dart'; -import 'package:matrix_link_text/link_text.dart'; import 'package:fluffychat/pages/chat/events/video_player.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; @@ -150,23 +150,10 @@ class MessageContent extends StatelessWidget { if (event.messageType == MessageTypes.Emote) { html = '* $html'; } - final bigEmotes = event.onlyEmotes && - event.numberEmotes > 0 && - event.numberEmotes <= 10; return HtmlMessage( html: html, - defaultTextStyle: TextStyle( - color: textColor, - fontSize: bigEmotes ? fontSize * 3 : fontSize, - ), - linkStyle: TextStyle( - color: textColor.withAlpha(150), - fontSize: bigEmotes ? fontSize * 3 : fontSize, - decoration: TextDecoration.underline, - decorationColor: textColor.withAlpha(150), - ), + textColor: textColor, room: event.room, - emoteSize: bigEmotes ? fontSize * 3 : fontSize * 1.5, ); } // else we fall through to the normal message rendering @@ -242,13 +229,13 @@ class MessageContent extends StatelessWidget { hideReply: true, ), builder: (context, snapshot) { - return LinkText( + return Linkify( text: snapshot.data ?? event.calcLocalizedBodyFallback( MatrixLocals(L10n.of(context)!), hideReply: true, ), - textStyle: TextStyle( + style: TextStyle( color: textColor, fontSize: bigEmotes ? fontSize * 3 : fontSize, decoration: @@ -260,10 +247,7 @@ class MessageContent extends StatelessWidget { decoration: TextDecoration.underline, decorationColor: textColor.withAlpha(150), ), - beforeLaunch: (url) { - UrlLauncher(context, url.toString()).launchUrl(); - return false; - }, + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ); }, ); diff --git a/lib/pages/chat/events/reply_content.dart b/lib/pages/chat/events/reply_content.dart index 26c47218..6de2e592 100644 --- a/lib/pages/chat/events/reply_content.dart +++ b/lib/pages/chat/events/reply_content.dart @@ -5,7 +5,6 @@ import 'package:matrix/matrix.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import '../../../config/app_config.dart'; -import 'html_message.dart'; class ReplyContent extends StatelessWidget { final Event replyEvent; @@ -26,47 +25,23 @@ class ReplyContent extends StatelessWidget { final displayEvent = timeline != null ? replyEvent.getDisplayEvent(timeline) : replyEvent; final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; - if (AppConfig.renderHtml && - [EventTypes.Message, EventTypes.Encrypted] - .contains(displayEvent.type) && - [MessageTypes.Text, MessageTypes.Notice, MessageTypes.Emote] - .contains(displayEvent.messageType) && - !displayEvent.redacted && - displayEvent.content['format'] == 'org.matrix.custom.html' && - displayEvent.content['formatted_body'] is String) { - String? html = displayEvent.content['formatted_body']; - if (displayEvent.messageType == MessageTypes.Emote) { - html = '* $html'; - } - replyBody = HtmlMessage( - html: html!, - defaultTextStyle: TextStyle( - color: ownMessage - ? Theme.of(context).colorScheme.onPrimary - : Theme.of(context).colorScheme.onBackground, - fontSize: fontSize, - ), - maxLines: 1, - room: displayEvent.room, - emoteSize: fontSize * 1.5, - ); - } else { - replyBody = Text( - displayEvent.calcLocalizedBodyFallback( - MatrixLocals(L10n.of(context)!), - withSenderNamePrefix: false, - hideReply: true, - ), - overflow: TextOverflow.ellipsis, - maxLines: 1, - style: TextStyle( - color: ownMessage - ? Theme.of(context).colorScheme.onPrimary - : Theme.of(context).colorScheme.onBackground, - fontSize: fontSize, - ), - ); - } + + replyBody = Text( + displayEvent.calcLocalizedBodyFallback( + MatrixLocals(L10n.of(context)!), + withSenderNamePrefix: false, + hideReply: true, + ), + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: TextStyle( + color: ownMessage + ? Theme.of(context).colorScheme.onPrimary + : Theme.of(context).colorScheme.onBackground, + fontSize: fontSize, + ), + ); + return Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/pages/chat/pinned_events.dart b/lib/pages/chat/pinned_events.dart index a38d950e..88373d07 100644 --- a/lib/pages/chat/pinned_events.dart +++ b/lib/pages/chat/pinned_events.dart @@ -4,8 +4,8 @@ import 'package:flutter/material.dart'; import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:matrix/matrix.dart'; -import 'package:matrix_link_text/link_text.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/chat/chat.dart'; @@ -101,7 +101,7 @@ class PinnedEvents extends StatelessWidget { hideReply: true, ), builder: (context, snapshot) { - return LinkText( + return Linkify( text: snapshot.data ?? event.calcLocalizedBodyFallback( MatrixLocals(L10n.of(context)!), @@ -109,7 +109,7 @@ class PinnedEvents extends StatelessWidget { hideReply: true, ), maxLines: 2, - textStyle: TextStyle( + style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant, overflow: TextOverflow.ellipsis, @@ -126,10 +126,8 @@ class PinnedEvents extends StatelessWidget { decorationColor: Theme.of(context).colorScheme.onSurfaceVariant, ), - beforeLaunch: (url) { - UrlLauncher(context, url.toString()).launchUrl(); - return false; - }, + onOpen: (url) => + UrlLauncher(context, url.url).launchUrl(), ); }, ), diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index 2f33e84a..8889e877 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:matrix/matrix.dart'; -import 'package:matrix_link_text/link_text.dart'; import 'package:vrouter/vrouter.dart'; import 'package:fluffychat/config/app_config.dart'; @@ -125,13 +125,13 @@ class ChatDetailsView extends StatelessWidget { padding: const EdgeInsets.symmetric( horizontal: 16.0, ), - child: LinkText( + child: Linkify( text: room.topic.isEmpty ? L10n.of(context)!.addGroupDescription : room.topic, linkStyle: const TextStyle(color: Colors.blueAccent), - textStyle: TextStyle( + style: TextStyle( fontSize: 14, color: Theme.of(context) .textTheme @@ -142,11 +142,8 @@ class ChatDetailsView extends StatelessWidget { .bodyMedium! .color, ), - beforeLaunch: (url) { - UrlLauncher(context, url.toString()) - .launchUrl(); - return false; - }, + onOpen: (url) => + UrlLauncher(context, url.url).launchUrl(), ), ), const SizedBox(height: 8), diff --git a/lib/pages/story/story_view.dart b/lib/pages/story/story_view.dart index 40aae425..26af6686 100644 --- a/lib/pages/story/story_view.dart +++ b/lib/pages/story/story_view.dart @@ -3,8 +3,8 @@ import 'package:flutter/services.dart'; import 'package:flutter_blurhash/flutter_blurhash.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:matrix/matrix.dart'; -import 'package:matrix_link_text/link_text.dart'; import 'package:video_player/video_player.dart'; import 'package:fluffychat/config/app_config.dart'; @@ -273,15 +273,13 @@ class StoryView extends StatelessWidget { controller.storyThemeData.alignmentY.toDouble() / 100, ), child: SafeArea( - child: LinkText( + child: Linkify( text: controller.loadingMode ? L10n.of(context)!.loadingPleaseWait : event.content.tryGet('body') ?? '', textAlign: TextAlign.center, - beforeLaunch: (url) { - UrlLauncher(context, url.toString()).launchUrl(); - return false; - }, + onOpen: (url) => + UrlLauncher(context, url.url).launchUrl(), linkStyle: TextStyle( fontSize: 24, color: Colors.blue.shade50, @@ -291,7 +289,7 @@ class StoryView extends StatelessWidget { ? null : textShadows, ), - textStyle: TextStyle( + style: TextStyle( fontSize: 24, color: Colors.white, shadows: event.messageType == MessageTypes.Text diff --git a/lib/widgets/public_room_bottom_sheet.dart b/lib/widgets/public_room_bottom_sheet.dart index 832f33bf..12a910b8 100644 --- a/lib/widgets/public_room_bottom_sheet.dart +++ b/lib/widgets/public_room_bottom_sheet.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:matrix/matrix.dart'; -import 'package:matrix_link_text/link_text.dart'; import 'package:vrouter/vrouter.dart'; import 'package:fluffychat/utils/url_launcher.dart'; @@ -153,17 +153,15 @@ class PublicRoomBottomSheet extends StatelessWidget { color: Theme.of(context).colorScheme.secondary, ), ), - subtitle: LinkText( + subtitle: Linkify( text: profile!.topic!, linkStyle: const TextStyle(color: Colors.blueAccent), - textStyle: TextStyle( + style: TextStyle( fontSize: 14, color: Theme.of(context).textTheme.bodyMedium!.color, ), - beforeLaunch: (url) { - UrlLauncher(context, url.toString()).launchUrl(); - return false; - }, + onOpen: (url) => + UrlLauncher(context, url.url).launchUrl(), ), ), ], diff --git a/pubspec.lock b/pubspec.lock index 05c1fd57..b41e0e33 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -113,30 +113,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" - cached_network_image: - dependency: transitive - description: - name: cached_network_image - sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 - url: "https://pub.dev" - source: hosted - version: "3.2.3" - cached_network_image_platform_interface: - dependency: transitive - description: - name: cached_network_image_platform_interface - sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 - url: "https://pub.dev" - source: hosted - version: "2.0.0" - cached_network_image_web: - dependency: transitive - description: - name: cached_network_image_web - sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 - url: "https://pub.dev" - source: hosted - version: "1.0.2" callkeep: dependency: "direct main" description: @@ -467,14 +443,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.10.0" - flutter_highlight: - dependency: transitive + flutter_highlighter: + dependency: "direct main" description: - name: flutter_highlight - sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c" + name: flutter_highlighter + sha256: "93173afd47a9ada53f3176371755e7ea4a1065362763976d06d6adfb4d946e10" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.1.1" + flutter_html: + dependency: "direct main" + description: + name: flutter_html + sha256: "850c07bc6c1ed060d3eb3e88469a598260a13eb45d8978b197c1348e0a2b101f" + url: "https://pub.dev" + source: hosted + version: "3.0.0-beta.1" flutter_keyboard_visibility: dependency: transitive description: @@ -523,6 +507,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + flutter_linkify: + dependency: "direct main" + description: + name: flutter_linkify + sha256: "74669e06a8f358fee4512b4320c0b80e51cffc496607931de68d28f099254073" + url: "https://pub.dev" + source: hosted + version: "6.0.0" flutter_lints: dependency: "direct dev" description: @@ -569,22 +561,13 @@ packages: source: hosted version: "3.1.0" flutter_math_fork: - dependency: "direct overridden" - description: - name: flutter_math_fork - sha256: "012ca684618b74286ab84fcc2f0e8d66b03ad623b8f79aea738f6b9c287f432c" - url: "https://pub.dev" - source: hosted - version: "0.7.0" - flutter_matrix_html: dependency: "direct main" description: - path: "." - ref: "krille/fix-trying-modify-unmodifiable-list" - resolved-ref: "97ab2982ff0429167436e15c3ae3c1b23d630c05" - url: "https://github.com/Sorunome/flutter_matrix_html.git" - source: git - version: "1.1.0" + name: flutter_math_fork + sha256: a143a3a89131b578043ecbdb5e759c1033a1b3e9174f5cd1b979d93f4a7fb41c + url: "https://pub.dev" + source: hosted + version: "0.7.1" flutter_native_splash: dependency: "direct dev" description: @@ -678,10 +661,10 @@ packages: dependency: transitive description: name: flutter_svg - sha256: "6ff9fa12892ae074092de2fa6a9938fb21dbabfdaa2ff57dc697ff912fc8d4b2" + sha256: f991fdb1533c3caeee0cdc14b04f50f0c3916f0dbcbc05237ccbe4e3c6b93f3f url: "https://pub.dev" source: hosted - version: "1.1.6" + version: "2.0.5" flutter_test: dependency: "direct dev" description: flutter @@ -801,14 +784,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.9" - highlight: + highlighter: dependency: transitive description: - name: highlight - sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" + name: highlighter + sha256: "92180c72b9da8758e1acf39a45aa305a97dcfe2fdc8f3d1d2947c23f2772bfbc" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.1.1" hive: dependency: "direct main" description: @@ -829,10 +812,10 @@ packages: dependency: transitive description: name: html - sha256: "79d498e6d6761925a34ee5ea8fa6dfef38607781d2fa91e37523474282af55cb" + sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" url: "https://pub.dev" source: hosted - version: "0.15.2" + version: "0.15.3" html_unescape: dependency: transitive description: @@ -934,14 +917,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.18.0" - isolate: - dependency: transitive - description: - name: isolate - sha256: "3554ab10fdeec965d27e0074c913ccb2229887633da080d2b35a6322da14938b" - url: "https://pub.dev" - source: hosted - version: "2.1.1" js: dependency: transitive description: @@ -1007,6 +982,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.8.1" + linkify: + dependency: transitive + description: + name: linkify + sha256: "4139ea77f4651ab9c315b577da2dd108d9aa0bd84b5d03d33323f1970c645832" + url: "https://pub.dev" + source: hosted + version: "5.0.0" lints: dependency: transitive description: @@ -1015,6 +998,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + list_counter: + dependency: transitive + description: + name: list_counter + sha256: c447ae3dfcd1c55f0152867090e67e219d42fe6d4f2807db4bbe8b8d69912237 + url: "https://pub.dev" + source: hosted + version: "1.0.2" lists: dependency: transitive description: @@ -1071,15 +1062,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.0" - matrix_link_text: - dependency: "direct main" - description: - path: "." - ref: "9b4d5c28dc602c17757d0eb689aafffe02719f26" - resolved-ref: "9b4d5c28dc602c17757d0eb689aafffe02719f26" - url: "https://github.com/TheOneWithTheBraid/matrix_link_text.git" - source: git - version: "1.1.0" meta: dependency: transitive description: @@ -1152,14 +1134,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.0" - octo_image: - dependency: transitive - description: - name: octo_image - sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" - url: "https://pub.dev" - source: hosted - version: "1.0.2" olm: dependency: transitive description: @@ -1200,14 +1174,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" - path_drawing: - dependency: transitive - description: - name: path_drawing - sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 - url: "https://pub.dev" - source: hosted - version: "1.0.1" path_parsing: dependency: transitive description: @@ -1933,6 +1899,30 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.7" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: ea8d3fc7b2e0f35de38a7465063ecfcf03d8217f7962aa2a6717132cb5d43a79 + url: "https://pub.dev" + source: hosted + version: "1.1.5" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: a5eaa5d19e123ad4f61c3718ca1ed921c4e6254238d9145f82aa214955d9aced + url: "https://pub.dev" + source: hosted + version: "1.1.5" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "15edc42f7eaa478ce854eaf1fbb9062a899c0e4e56e775dd73b7f4709c97c4ca" + url: "https://pub.dev" + source: hosted + version: "1.1.5" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3a098239..33d004df 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,11 +33,14 @@ dependencies: flutter_blurhash: ^0.7.0 flutter_cache_manager: ^3.3.0 flutter_foreground_task: ^3.10.0 + flutter_highlighter: ^0.1.1 + flutter_html: ^3.0.0-beta.1 + flutter_linkify: ^6.0.0 flutter_local_notifications: ^12.0.2 flutter_localizations: sdk: flutter flutter_map: ^3.1.0 - flutter_matrix_html: ^1.1.0 + flutter_math_fork: ^0.7.1 flutter_olm: ^1.2.0 flutter_openssl_crypto: ^0.1.0 flutter_ringtone_player: ^3.1.1 @@ -59,7 +62,6 @@ dependencies: latlong2: ^0.8.1 matrix: ^0.20.1 matrix_homeserver_recommendations: ^0.3.0 - matrix_link_text: ^1.0.2 native_imaging: ^0.1.0 package_info_plus: ^4.0.0 path_provider: ^2.0.9 @@ -143,12 +145,6 @@ msix_config: install_certificate: false dependency_overrides: - # null safety - flutter_math_fork: ">=0.7.0" - flutter_matrix_html: - git: - url: https://github.com/Sorunome/flutter_matrix_html.git - ref: krille/fix-trying-modify-unmodifiable-list # fake secure storage plugin for Windows # See: https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15161 flutter_secure_storage_windows: @@ -165,11 +161,6 @@ dependency_overrides: git: url: https://github.com/TheOneWithTheBraid/keyboard_shortcuts.git ref: null-safety - # https://github.com/Sorunome/matrix_link_text/pull/2 - matrix_link_text: - git: - url: https://github.com/TheOneWithTheBraid/matrix_link_text.git - ref: 9b4d5c28dc602c17757d0eb689aafffe02719f26 # blocked upgrade of package_info_plus for null safety # https://github.com/creativecreatorormaybenot/wakelock/pull/203 wakelock_windows: