general fixups, plus adding colors for names
This commit is contained in:
parent
ccd8513cde
commit
cff580dee2
14 changed files with 196 additions and 122 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import "dart:async";
|
import "dart:async";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/user_controller.dart";
|
import "package:nexus/controllers/user_controller.dart";
|
||||||
|
import "package:nexus/models/configs/user_config.dart";
|
||||||
import "package:nexus/models/content/membership.dart";
|
import "package:nexus/models/content/membership.dart";
|
||||||
import "package:nexus/models/event.dart";
|
import "package:nexus/models/event.dart";
|
||||||
|
|
||||||
|
|
@ -11,7 +12,9 @@ class AuthorController extends AsyncNotifier<MembershipContent> {
|
||||||
@override
|
@override
|
||||||
Future<MembershipContent> build() async {
|
Future<MembershipContent> build() async {
|
||||||
final member = await ref.watch(
|
final member = await ref.watch(
|
||||||
UserController.provider(event.sender).future,
|
UserController.provider(
|
||||||
|
UserConfig(roomId: event.roomId, userId: event.sender),
|
||||||
|
).future,
|
||||||
);
|
);
|
||||||
|
|
||||||
return MembershipContent(
|
return MembershipContent(
|
||||||
|
|
|
||||||
|
|
@ -4,25 +4,44 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/members_controller.dart";
|
import "package:nexus/controllers/members_controller.dart";
|
||||||
import "package:nexus/controllers/profile_controller.dart";
|
import "package:nexus/controllers/profile_controller.dart";
|
||||||
import "package:nexus/helpers/extensions/get_localpart.dart";
|
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||||
|
import "package:nexus/models/configs/user_config.dart";
|
||||||
import "package:nexus/models/content/membership.dart";
|
import "package:nexus/models/content/membership.dart";
|
||||||
import "package:nexus/models/membership_status.dart";
|
import "package:nexus/models/membership_status.dart";
|
||||||
|
|
||||||
class UserController extends AsyncNotifier<MembershipContent> {
|
class UserController extends AsyncNotifier<MembershipContent> {
|
||||||
final String userId;
|
final UserConfig config;
|
||||||
UserController(this.userId);
|
UserController(this.config);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MembershipContent> build() async {
|
Future<MembershipContent> build() async {
|
||||||
final profile = await ref.watch(ProfileController.provider(userId).future);
|
final member = config.roomId == null
|
||||||
|
? null
|
||||||
|
: await ref.watch(
|
||||||
|
MembersController.provider(config.roomId!).selectAsync(
|
||||||
|
(value) => value.firstWhereOrNull(
|
||||||
|
(membership) => membership.stateKey == config.userId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (member?.content case final MembershipContent content) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
final profile = await ref.watch(
|
||||||
|
ProfileController.provider(config.userId).future,
|
||||||
|
);
|
||||||
return MembershipContent(
|
return MembershipContent(
|
||||||
status: MembershipStatus.leave,
|
status: MembershipStatus.leave,
|
||||||
avatarUrl: profile.avatarUrl,
|
avatarUrl: profile.avatarUrl,
|
||||||
displayName: profile.displayName ?? userId.localpart,
|
displayName: profile.displayName ?? config.userId.localpart,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
AsyncNotifierProvider.family<UserController, MembershipContent, String>(
|
AsyncNotifierProvider.family<
|
||||||
UserController.new,
|
UserController,
|
||||||
);
|
MembershipContent,
|
||||||
|
UserConfig
|
||||||
|
>(UserController.new);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@ void main() async {
|
||||||
await windowManager.setMinimumSize(Size.square(500));
|
await windowManager.setMinimumSize(Size.square(500));
|
||||||
}
|
}
|
||||||
|
|
||||||
FlutterError.onError = (FlutterErrorDetails details) =>
|
// FlutterError.onError = (FlutterErrorDetails details) =>
|
||||||
showError(details.exception.toString(), details.stack);
|
// showError(details.exception.toString(), details.stack);
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
|
|
|
||||||
12
lib/models/configs/user_config.dart
Normal file
12
lib/models/configs/user_config.dart
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import "package:freezed_annotation/freezed_annotation.dart";
|
||||||
|
part "user_config.freezed.dart";
|
||||||
|
part "user_config.g.dart";
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class UserConfig with _$UserConfig {
|
||||||
|
const factory UserConfig({required String? roomId, required String userId}) =
|
||||||
|
_UserConfig;
|
||||||
|
|
||||||
|
factory UserConfig.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$UserConfigFromJson(json);
|
||||||
|
}
|
||||||
|
|
@ -2,9 +2,7 @@ import "package:flutter/material.dart";
|
||||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||||
import "package:nexus/models/event.dart";
|
import "package:nexus/models/event.dart";
|
||||||
import "package:nexus/models/relation_type.dart";
|
import "package:nexus/models/relation_type.dart";
|
||||||
import "package:nexus/widgets/renderers/event.dart";
|
import "package:nexus/widgets/event_preview.dart";
|
||||||
import "package:nexus/widgets/lazy_loading/message_avatar.dart";
|
|
||||||
import "package:nexus/widgets/lazy_loading/message_displayname.dart";
|
|
||||||
|
|
||||||
class RelationPreview extends ConsumerWidget {
|
class RelationPreview extends ConsumerWidget {
|
||||||
final Event? relatedEvent;
|
final Event? relatedEvent;
|
||||||
|
|
@ -29,7 +27,7 @@ class RelationPreview extends ConsumerWidget {
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
color: theme.colorScheme.surfaceContainerHigh,
|
color: theme.colorScheme.surfaceContainerHigh,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: Row(
|
child: Row(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -39,30 +37,10 @@ class RelationPreview extends ConsumerWidget {
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
|
|
||||||
MessageAvatar(relatedEvent!),
|
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Padding(
|
||||||
spacing: 8,
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
children: [
|
child: EventPreview(relatedEvent!),
|
||||||
Flexible(
|
|
||||||
child: MessageDisplayname(
|
|
||||||
relatedEvent!,
|
|
||||||
style: theme.textTheme.labelMedium?.copyWith(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: IgnorePointer(
|
|
||||||
child: EventRenderer(
|
|
||||||
relatedEvent!,
|
|
||||||
textOnly: true,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
|
||||||
36
lib/widgets/event_preview.dart
Normal file
36
lib/widgets/event_preview.dart
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
import "package:nexus/models/content/message.dart";
|
||||||
|
import "package:nexus/models/event.dart";
|
||||||
|
import "package:nexus/widgets/lazy_loading/message_avatar.dart";
|
||||||
|
import "package:nexus/widgets/lazy_loading/message_displayname.dart";
|
||||||
|
import "package:nexus/widgets/renderers/event.dart";
|
||||||
|
|
||||||
|
class EventPreview extends StatelessWidget {
|
||||||
|
final Event event;
|
||||||
|
const EventPreview(this.event, {super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => IgnorePointer(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 4),
|
||||||
|
child: Row(
|
||||||
|
spacing: 12,
|
||||||
|
children: [
|
||||||
|
if (event.content is MessageContent) MessageAvatar(event),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: Wrap(
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
|
spacing: 4,
|
||||||
|
runSpacing: 2,
|
||||||
|
children: [
|
||||||
|
if (event.content is MessageContent) MessageDisplayname(event),
|
||||||
|
EventRenderer(event, textOnly: true, maxLines: 1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -17,8 +17,9 @@ import "package:nexus/widgets/html/quoted.dart";
|
||||||
|
|
||||||
class Html extends ConsumerWidget {
|
class Html extends ConsumerWidget {
|
||||||
final String html;
|
final String html;
|
||||||
|
final String? roomId;
|
||||||
final TextStyle? textStyle;
|
final TextStyle? textStyle;
|
||||||
const Html(this.html, {this.textStyle, super.key});
|
const Html(this.html, {this.roomId, this.textStyle, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) => HtmlWidget(
|
Widget build(BuildContext context, WidgetRef ref) => HtmlWidget(
|
||||||
|
|
@ -59,13 +60,15 @@ class Html extends ConsumerWidget {
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
"blockquote" => Quoted(Html(element.innerHtml)),
|
"blockquote" => Quoted(
|
||||||
|
Html(element.innerHtml, textStyle: textStyle, roomId: roomId),
|
||||||
|
),
|
||||||
|
|
||||||
"a" =>
|
"a" =>
|
||||||
element.attributes["href"]?.mention == null
|
element.attributes["href"]?.mention == null
|
||||||
? null
|
? null
|
||||||
: InlineCustomWidget(
|
: InlineCustomWidget(
|
||||||
child: MentionChip(element.attributes["href"]!),
|
child: MentionChip(element.attributes["href"]!, roomId),
|
||||||
),
|
),
|
||||||
|
|
||||||
"img" =>
|
"img" =>
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,23 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/user_controller.dart";
|
import "package:nexus/controllers/user_controller.dart";
|
||||||
import "package:nexus/helpers/extensions/link_to_mention.dart";
|
import "package:nexus/helpers/extensions/link_to_mention.dart";
|
||||||
import "package:nexus/helpers/extensions/show_user_popover.dart";
|
import "package:nexus/helpers/extensions/show_user_popover.dart";
|
||||||
|
import "package:nexus/models/configs/user_config.dart";
|
||||||
|
|
||||||
class MentionChip extends ConsumerWidget {
|
class MentionChip extends ConsumerWidget {
|
||||||
|
final String? roomId;
|
||||||
final String content;
|
final String content;
|
||||||
const MentionChip(this.content, {super.key});
|
const MentionChip(this.content, this.roomId, {super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final mention = content.mention;
|
final mention = content.mention;
|
||||||
final membership = mention?.startsWith("@") == true
|
final membership = mention?.startsWith("@") == true
|
||||||
? ref
|
? ref
|
||||||
.watch(UserController.provider(mention!))
|
.watch(
|
||||||
|
UserController.provider(
|
||||||
|
UserConfig(roomId: roomId, userId: mention!),
|
||||||
|
),
|
||||||
|
)
|
||||||
.whenOrNull(data: (data) => data)
|
.whenOrNull(data: (data) => data)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import "package:nexus/widgets/avatar_or_hash.dart";
|
||||||
class MessageAvatar extends ConsumerWidget {
|
class MessageAvatar extends ConsumerWidget {
|
||||||
final Event event;
|
final Event event;
|
||||||
final double height;
|
final double height;
|
||||||
const MessageAvatar(this.event, {this.height = 16, super.key});
|
const MessageAvatar(this.event, {this.height = 24, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) => ref
|
Widget build(BuildContext context, WidgetRef ref) => ref
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "package:color_hash/color_hash.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/author_controller.dart";
|
import "package:nexus/controllers/author_controller.dart";
|
||||||
|
|
@ -31,7 +32,17 @@ class MessageDisplayname extends ConsumerWidget {
|
||||||
: null,
|
: null,
|
||||||
child: Text(
|
child: Text(
|
||||||
"${membership.displayName ?? event.sender.localpart}${event.pmp == null ? "" : " (via ${event.sender})"}",
|
"${membership.displayName ?? event.sender.localpart}${event.pmp == null ? "" : " (via ${event.sender})"}",
|
||||||
style: style,
|
style:
|
||||||
|
style ??
|
||||||
|
TextStyle(
|
||||||
|
color: ColorHash(
|
||||||
|
event.sender,
|
||||||
|
lightness: .7,
|
||||||
|
saturation: .7,
|
||||||
|
).color,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
|
import "package:color_hash/color_hash.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_hooks/flutter_hooks.dart";
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||||
import "package:nexus/controllers/members_by_status_controller.dart";
|
import "package:nexus/controllers/members_by_status_controller.dart";
|
||||||
import "package:nexus/helpers/extensions/better_when.dart";
|
|
||||||
import "package:nexus/helpers/extensions/get_localpart.dart";
|
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||||
import "package:nexus/helpers/extensions/show_user_popover.dart";
|
import "package:nexus/helpers/extensions/show_user_popover.dart";
|
||||||
import "package:nexus/models/configs/members_by_status_config.dart";
|
import "package:nexus/models/configs/members_by_status_config.dart";
|
||||||
import "package:nexus/models/content/membership.dart";
|
import "package:nexus/models/content/membership.dart";
|
||||||
import "package:nexus/models/membership_status.dart";
|
import "package:nexus/models/membership_status.dart";
|
||||||
import "package:nexus/widgets/avatar_or_hash.dart";
|
import "package:nexus/widgets/avatar_or_hash.dart";
|
||||||
|
import "package:nexus/widgets/error_dialog.dart";
|
||||||
|
import "package:nexus/widgets/loading.dart";
|
||||||
|
|
||||||
class MemberList extends HookConsumerWidget {
|
class MemberList extends HookConsumerWidget {
|
||||||
final String roomId;
|
final String roomId;
|
||||||
|
|
@ -63,10 +65,14 @@ class MemberList extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
membersProvider.betterWhen(
|
switch (membersProvider) {
|
||||||
data: (members) => Expanded(
|
AsyncError(:final error, :final stackTrace) => ErrorDialog(
|
||||||
|
error,
|
||||||
|
stackTrace,
|
||||||
|
),
|
||||||
|
AsyncData(:final value) || AsyncLoading(:final value?) => Expanded(
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: members
|
children: value
|
||||||
.map(
|
.map(
|
||||||
(member) => switch (member.content) {
|
(member) => switch (member.content) {
|
||||||
MembershipContent(
|
MembershipContent(
|
||||||
|
|
@ -87,6 +93,14 @@ class MemberList extends HookConsumerWidget {
|
||||||
title: Text(
|
title: Text(
|
||||||
displayName ?? member.stateKey!.localpart,
|
displayName ?? member.stateKey!.localpart,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorHash(
|
||||||
|
member.stateKey!,
|
||||||
|
lightness: .7,
|
||||||
|
saturation: .8,
|
||||||
|
).color,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
member.stateKey!,
|
member.stateKey!,
|
||||||
|
|
@ -100,7 +114,8 @@ class MemberList extends HookConsumerWidget {
|
||||||
.toList(),
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
AsyncLoading _ => Loading(),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import "package:nexus/models/content/membership.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/models/requests/get_event_request.dart";
|
import "package:nexus/models/requests/get_event_request.dart";
|
||||||
|
import "package:nexus/widgets/event_preview.dart";
|
||||||
import "package:nexus/widgets/expandable_image.dart";
|
import "package:nexus/widgets/expandable_image.dart";
|
||||||
import "package:nexus/widgets/html/html.dart";
|
import "package:nexus/widgets/html/html.dart";
|
||||||
import "package:nexus/widgets/lazy_loading/message_avatar.dart";
|
import "package:nexus/widgets/lazy_loading/message_avatar.dart";
|
||||||
|
|
@ -59,6 +60,8 @@ class EventRenderer extends ConsumerWidget {
|
||||||
message: event.timestamp.toString(),
|
message: event.timestamp.toString(),
|
||||||
child: Text(
|
child: Text(
|
||||||
format(event.timestamp),
|
format(event.timestamp),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
style: theme.textTheme.labelSmall?.copyWith(color: Colors.grey),
|
style: theme.textTheme.labelSmall?.copyWith(color: Colors.grey),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -83,6 +86,7 @@ class EventRenderer extends ConsumerWidget {
|
||||||
),
|
),
|
||||||
MessageContent() || EncryptedContent() => Row(
|
MessageContent() || EncryptedContent() => Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
if (!textOnly)
|
if (!textOnly)
|
||||||
|
|
@ -90,7 +94,7 @@ class EventRenderer extends ConsumerWidget {
|
||||||
SizedBox(width: 40)
|
SizedBox(width: 40)
|
||||||
else
|
else
|
||||||
MessageAvatar(event, height: 40),
|
MessageAvatar(event, height: 40),
|
||||||
Expanded(
|
Flexible(
|
||||||
child: Column(
|
child: Column(
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|
@ -99,16 +103,14 @@ class EventRenderer extends ConsumerWidget {
|
||||||
Row(
|
Row(
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(child: MessageDisplayname(event)),
|
||||||
child: MessageDisplayname(
|
Flexible(flex: 0, child: timestamp),
|
||||||
event,
|
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Flexible(child: timestamp),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Card(
|
Card(
|
||||||
|
margin: textOnly
|
||||||
|
? EdgeInsets.zero
|
||||||
|
: EdgeInsets.only(bottom: 4),
|
||||||
color: textOnly
|
color: textOnly
|
||||||
? Colors.transparent
|
? Colors.transparent
|
||||||
: ref.watch(
|
: ref.watch(
|
||||||
|
|
@ -152,32 +154,7 @@ class EventRenderer extends ConsumerWidget {
|
||||||
AsyncData(:final value?) ||
|
AsyncData(:final value?) ||
|
||||||
AsyncLoading(
|
AsyncLoading(
|
||||||
:final value?,
|
:final value?,
|
||||||
) => IgnorePointer(
|
) => EventPreview(value),
|
||||||
child: Row(
|
|
||||||
spacing: 8,
|
|
||||||
children: [
|
|
||||||
MessageAvatar(value, height: 24),
|
|
||||||
Flexible(
|
|
||||||
child: MessageDisplayname(
|
|
||||||
value,
|
|
||||||
style: TextStyle(
|
|
||||||
color: theme
|
|
||||||
.colorScheme
|
|
||||||
.primary,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: EventRenderer(
|
|
||||||
value,
|
|
||||||
textOnly: true,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
AsyncError _ => Text(
|
AsyncError _ => Text(
|
||||||
"An error occurred while fetching the reply",
|
"An error occurred while fetching the reply",
|
||||||
style: errorStyle,
|
style: errorStyle,
|
||||||
|
|
@ -233,6 +210,7 @@ class EventRenderer extends ConsumerWidget {
|
||||||
children: [
|
children: [
|
||||||
format == MessageFormat.html && !textOnly
|
format == MessageFormat.html && !textOnly
|
||||||
? Html(
|
? Html(
|
||||||
|
roomId: event.roomId,
|
||||||
textStyle: textStyle,
|
textStyle: textStyle,
|
||||||
formattedBody!.replaceAllMapped(
|
formattedBody!.replaceAllMapped(
|
||||||
RegExp(
|
RegExp(
|
||||||
|
|
@ -291,7 +269,7 @@ class EventRenderer extends ConsumerWidget {
|
||||||
)) {
|
)) {
|
||||||
final url? => ConstrainedBox(
|
final url? => ConstrainedBox(
|
||||||
constraints: BoxConstraints.loose(
|
constraints: BoxConstraints.loose(
|
||||||
Size.fromWidth(500),
|
Size.square(500),
|
||||||
),
|
),
|
||||||
child: switch (event.content) {
|
child: switch (event.content) {
|
||||||
VideoMessageContent(
|
VideoMessageContent(
|
||||||
|
|
@ -425,14 +403,8 @@ class EventRenderer extends ConsumerWidget {
|
||||||
padding: EdgeInsets.symmetric(horizontal: 4),
|
padding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
child: Icon(Icons.numbers),
|
child: Icon(Icons.numbers),
|
||||||
),
|
),
|
||||||
MessageDisplayname(
|
Flexible(child: MessageDisplayname(event)),
|
||||||
event,
|
Expanded(child: Text("changed the room avatar")),
|
||||||
style: TextStyle(
|
|
||||||
color: theme.colorScheme.primary,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text("changed the room avatar"),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
_ => null,
|
_ => null,
|
||||||
|
|
|
||||||
|
|
@ -19,43 +19,54 @@ class MembershipRenderer extends StatelessWidget {
|
||||||
|
|
||||||
return switch (event.content) {
|
return switch (event.content) {
|
||||||
MembershipContent content => Row(
|
MembershipContent content => Row(
|
||||||
spacing: 4,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 4),
|
padding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
child: Icon(Icons.people),
|
child: Icon(Icons.people),
|
||||||
),
|
),
|
||||||
InkWell(
|
Expanded(
|
||||||
onTapUp: (details) => context.showUserPopover(
|
child: Wrap(
|
||||||
content,
|
spacing: 4,
|
||||||
event.stateKey!,
|
children: [
|
||||||
globalPosition: details.globalPosition,
|
InkWell(
|
||||||
),
|
onTapUp: (details) => context.showUserPopover(
|
||||||
child: Text(
|
content,
|
||||||
content.displayName ?? event.stateKey!.localpart,
|
event.stateKey!,
|
||||||
style: TextStyle(
|
globalPosition: details.globalPosition,
|
||||||
color: Theme.of(context).colorScheme.primary,
|
),
|
||||||
fontWeight: FontWeight.bold,
|
child: Text(
|
||||||
),
|
overflow: TextOverflow.ellipsis,
|
||||||
|
content.displayName ?? event.stateKey!.localpart,
|
||||||
|
maxLines: 1,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
"${switch (content.status) {
|
||||||
|
MembershipStatus.invite => "was invited to",
|
||||||
|
MembershipStatus.join => "joined",
|
||||||
|
MembershipStatus.leave => event.sender == event.stateKey ? "left" : (event.unsigned["prev_content"]?["membership"] == "ban" ? "was unbanned from" : "was kicked from"),
|
||||||
|
MembershipStatus.ban => "was banned from",
|
||||||
|
MembershipStatus.knock => "asked to join",
|
||||||
|
}} the room${content.reason == null ? "" : "because ${content.reason}"}${event.sender == event.stateKey ? "" : " by "}",
|
||||||
|
),
|
||||||
|
if (event.sender != event.stateKey)
|
||||||
|
MessageDisplayname(
|
||||||
|
event,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
|
||||||
"${switch (content.status) {
|
|
||||||
MembershipStatus.invite => "was invited to",
|
|
||||||
MembershipStatus.join => "joined",
|
|
||||||
MembershipStatus.leave => event.sender == event.stateKey ? "left" : (event.unsigned["prev_content"]?["membership"] == "ban" ? "was unbanned from" : "was kicked from"),
|
|
||||||
MembershipStatus.ban => "was banned from",
|
|
||||||
MembershipStatus.knock => "asked to join",
|
|
||||||
}} the room${content.reason == null ? "" : "because ${content.reason}"}${event.sender == event.stateKey ? "" : " by "}",
|
|
||||||
),
|
|
||||||
if (event.sender != event.stateKey)
|
|
||||||
MessageDisplayname(
|
|
||||||
event,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
_ => SizedBox.shrink(),
|
_ => SizedBox.shrink(),
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
|
boxy:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: boxy
|
||||||
|
sha256: "42ccafe13b2893878042acc5b7e2446025328e11a3197b0bb78db42ff76aa3f0"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.0"
|
||||||
build:
|
build:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue