refactor: Reimplement flutter matrix html locally

This commit is contained in:
Krille 2023-05-17 12:26:59 +02:00
parent 8faba7bdf2
commit 102f3bba8e
No known key found for this signature in database
9 changed files with 433 additions and 293 deletions

View File

@ -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<String> 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<String> 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<StyledElement, InlineSpan> 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<String> get supportedTags => {'code'};
@override
InlineSpan build(
ExtensionContext context,
Map<StyledElement, InlineSpan> 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<String> 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<StyledElement, InlineSpan> 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<String> 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<StyledElement, InlineSpan> 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<QueryPublicRoomsResponse>(
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,
),
),
],
),
),
),
);
}
}

View File

@ -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(),
);
},
);

View File

@ -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: <Widget>[

View File

@ -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(),
);
},
),

View File

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

View File

@ -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<String>('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

View File

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

View File

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

View File

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