Remove flutter chat #26
5 changed files with 172 additions and 6 deletions
text message rendering
commit
cb20cb38fd
|
|
@ -27,7 +27,9 @@ class PowerLevelController extends Notifier<bool> {
|
||||||
final content = event?.content is PowerLevelsContent
|
final content = event?.content is PowerLevelsContent
|
||||||
? event!.content
|
? event!.content
|
||||||
: PowerLevelsContent();
|
: PowerLevelsContent();
|
||||||
final user = ref.watch(ClientStateController.provider)?.userId;
|
final user = ref.watch(
|
||||||
|
ClientStateController.provider.select((value) => value?.userId),
|
||||||
|
);
|
||||||
if (user == null || content is! PowerLevelsContent) return false;
|
if (user == null || content is! PowerLevelsContent) return false;
|
||||||
|
|
||||||
int powerLevelOf(String userId) =>
|
int powerLevelOf(String userId) =>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ part "membership.g.dart";
|
||||||
@freezed
|
@freezed
|
||||||
abstract class MembershipContent extends Content with _$MembershipContent {
|
abstract class MembershipContent extends Content with _$MembershipContent {
|
||||||
MembershipContent._();
|
MembershipContent._();
|
||||||
|
|
||||||
factory MembershipContent({
|
factory MembershipContent({
|
||||||
@JsonKey(name: "displayname") required String? displayName,
|
@JsonKey(name: "displayname") required String? displayName,
|
||||||
@JsonKey(name: "membership") required MembershipStatus status,
|
@JsonKey(name: "membership") required MembershipStatus status,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ part "power_levels.g.dart";
|
||||||
@freezed
|
@freezed
|
||||||
abstract class PowerLevelsContent extends Content with _$PowerLevelsContent {
|
abstract class PowerLevelsContent extends Content with _$PowerLevelsContent {
|
||||||
PowerLevelsContent._();
|
PowerLevelsContent._();
|
||||||
|
|
||||||
factory PowerLevelsContent({
|
factory PowerLevelsContent({
|
||||||
@Default(IMap.empty()) IMap<String, int> events,
|
@Default(IMap.empty()) IMap<String, int> events,
|
||||||
@Default(IMap.empty()) IMap<String, int> users,
|
@Default(IMap.empty()) IMap<String, int> users,
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,26 @@
|
||||||
|
import "package:cross_cache/cross_cache.dart";
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
import "package:nexus/controllers/client_state_controller.dart";
|
||||||
|
import "package:nexus/controllers/cross_cache_controller.dart";
|
||||||
|
import "package:nexus/controllers/url_preview_controller.dart";
|
||||||
|
import "package:nexus/helpers/extensions/better_when.dart";
|
||||||
|
import "package:nexus/helpers/extensions/get_headers.dart";
|
||||||
|
import "package:nexus/helpers/launch_helper.dart";
|
||||||
import "package:nexus/models/content/avatar.dart";
|
import "package:nexus/models/content/avatar.dart";
|
||||||
|
import "package:nexus/models/content/content.dart";
|
||||||
import "package:nexus/models/content/message.dart";
|
import "package:nexus/models/content/message.dart";
|
||||||
import "package:nexus/models/event.dart";
|
import "package:nexus/models/event.dart";
|
||||||
|
import "package:nexus/widgets/chat_page/html/html.dart";
|
||||||
|
import "package:nexus/widgets/chat_page/html/quoted.dart";
|
||||||
import "package:nexus/widgets/chat_page/lazy_loading/message_avatar.dart";
|
import "package:nexus/widgets/chat_page/lazy_loading/message_avatar.dart";
|
||||||
import "package:nexus/widgets/chat_page/lazy_loading/message_displayname.dart";
|
import "package:nexus/widgets/chat_page/lazy_loading/message_displayname.dart";
|
||||||
|
import "package:nexus/widgets/link_preview.dart";
|
||||||
import "package:timeago/timeago.dart";
|
import "package:timeago/timeago.dart";
|
||||||
|
import "package:flutter_linkify/flutter_linkify.dart";
|
||||||
|
|
||||||
class EventText extends StatelessWidget {
|
class EventText extends ConsumerWidget {
|
||||||
final Event event;
|
final Event event;
|
||||||
final bool textOnly;
|
final bool textOnly;
|
||||||
final bool isGrouped;
|
final bool isGrouped;
|
||||||
|
|
@ -25,8 +38,10 @@ class EventText extends StatelessWidget {
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
final colorScheme = theme.colorScheme;
|
||||||
|
|
||||||
final timestamp = Tooltip(
|
final timestamp = Tooltip(
|
||||||
message: event.timestamp.toString(),
|
message: event.timestamp.toString(),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|
@ -55,7 +70,97 @@ class EventText extends StatelessWidget {
|
||||||
Expanded(child: timestamp),
|
Expanded(child: timestamp),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Text("data"),
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color:
|
||||||
|
ref.watch(
|
||||||
|
ClientStateController.provider.select(
|
||||||
|
(value) => value?.userId,
|
||||||
|
),
|
||||||
|
) ==
|
||||||
|
event.sender
|
||||||
|
? (event.eventId.startsWith("~")
|
||||||
|
? colorScheme.onPrimary
|
||||||
|
: colorScheme.primaryContainer)
|
||||||
|
: colorScheme.surfaceContainer,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// Quoted( // TODO: Show replies
|
||||||
|
// EventText(replyEvent textOnly: true, maxLines: 1,)
|
||||||
|
// ),
|
||||||
|
switch (event.content) {
|
||||||
|
Content(:final parseError?) => SelectableText(
|
||||||
|
"An error occurred while parsing this message:\n$parseError",
|
||||||
|
style: TextStyle(color: colorScheme.error),
|
||||||
|
),
|
||||||
|
TextMessageContent(
|
||||||
|
:final body,
|
||||||
|
:final formattedBody,
|
||||||
|
:final format,
|
||||||
|
) =>
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
format == "org.matrix.custom.html"
|
||||||
|
? Html(
|
||||||
|
textStyle:
|
||||||
|
event.localContent?.bigEmoji == true
|
||||||
|
? TextStyle(fontSize: 32)
|
||||||
|
: null,
|
||||||
|
formattedBody!.replaceAllMapped(
|
||||||
|
RegExp(
|
||||||
|
"(<a\\b[^>]*>.*?<\\/a>)|(\\bhttps?:\\/\\/[^\\s<]+)",
|
||||||
|
caseSensitive: false,
|
||||||
|
dotAll: true,
|
||||||
|
),
|
||||||
|
(m) {
|
||||||
|
// If it's already an <a> tag, leave it unchanged
|
||||||
|
if (m.group(1) != null) {
|
||||||
|
return m.group(1)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, wrap the bare URL
|
||||||
|
final url = m.group(2)!;
|
||||||
|
return "<a href=\"$url\">$url</a>";
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Linkify(
|
||||||
|
text: body,
|
||||||
|
options: LinkifyOptions(
|
||||||
|
humanize: false,
|
||||||
|
),
|
||||||
|
onOpen: (link) => ref
|
||||||
|
.watch(LaunchHelper.provider)
|
||||||
|
.launchUrl(Uri.parse(link.url)),
|
||||||
|
linkStyle: TextStyle(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (event.lastEditRowId != null)
|
||||||
|
Text(
|
||||||
|
"(edited)",
|
||||||
|
style: theme.textTheme.labelSmall,
|
||||||
|
),
|
||||||
|
if (RegExp(
|
||||||
|
r'''https?://[^\s"'<>]+''',
|
||||||
|
).allMatches(body).firstOrNull?.group(0)
|
||||||
|
case final link?)
|
||||||
|
LinkPreview(link),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
_ => SizedBox.shrink(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
61
lib/widgets/link_preview.dart
Normal file
61
lib/widgets/link_preview.dart
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
import "package:cross_cache/cross_cache.dart";
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
import "package:nexus/controllers/cross_cache_controller.dart";
|
||||||
|
import "package:nexus/controllers/url_preview_controller.dart";
|
||||||
|
import "package:nexus/helpers/extensions/better_when.dart";
|
||||||
|
import "package:nexus/helpers/extensions/get_headers.dart";
|
||||||
|
import "package:nexus/helpers/launch_helper.dart";
|
||||||
|
|
||||||
|
class LinkPreview extends ConsumerWidget {
|
||||||
|
final String link;
|
||||||
|
const LinkPreview(this.link, {super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) => ref
|
||||||
|
.watch(UrlPreviewController.provider(link))
|
||||||
|
.betterWhen(
|
||||||
|
data: (preview) => preview == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: InkWell(
|
||||||
|
onTap: () =>
|
||||||
|
ref.watch(LaunchHelper.provider).launchUrl(Uri.parse(link)),
|
||||||
|
child: Card(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (preview.title != null)
|
||||||
|
Text(
|
||||||
|
preview.title!,
|
||||||
|
style: Theme.of(context).textTheme.labelLarge,
|
||||||
|
),
|
||||||
|
if (preview.description != null)
|
||||||
|
Text(preview.description!),
|
||||||
|
if (preview.imageUrl != null)
|
||||||
|
Image(
|
||||||
|
errorBuilder: (_, _, _) => SizedBox.shrink(),
|
||||||
|
width: preview.width,
|
||||||
|
height: preview.height,
|
||||||
|
image: CachedNetworkImage(
|
||||||
|
preview.imageUrl!,
|
||||||
|
ref.watch(CrossCacheController.provider),
|
||||||
|
headers: ref.headers,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// text: link,
|
||||||
|
// backgroundColor: isSentByMe
|
||||||
|
// ? colorScheme.inversePrimary
|
||||||
|
// : colorScheme.surfaceContainerLow,
|
||||||
|
// outsidePadding: EdgeInsets.only(top: 4),
|
||||||
|
// insidePadding: EdgeInsets.symmetric(
|
||||||
|
// vertical: 8,
|
||||||
|
// horizontal: 16,
|
||||||
|
// ),
|
||||||
|
// linkPreviewData: preview,
|
||||||
|
// onLinkPreviewDataFetched: (_) => null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue