treewide: use dot shorthands where possible
Now this feature is stable, we should use it. I might have missed some usecases, but these can be added in future commits.
This commit is contained in:
parent
6281c1d13a
commit
d2ec5f035b
67 changed files with 391 additions and 534 deletions
|
|
@ -18,11 +18,11 @@ class Appbar extends StatelessWidget implements PreferredSizeWidget {
|
|||
this.backgroundColor,
|
||||
this.scrolledUnderElevation,
|
||||
this.leading,
|
||||
this.actions = const IList.empty(),
|
||||
this.actions = const .empty(),
|
||||
});
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
Size get preferredSize => const .fromHeight(kToolbarHeight);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -42,7 +42,7 @@ class Appbar extends StatelessWidget implements PreferredSizeWidget {
|
|||
leading: InkWell(onTap: onTap, child: leading),
|
||||
backgroundColor: backgroundColor,
|
||||
scrolledUnderElevation: scrolledUnderElevation,
|
||||
actionsPadding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
actionsPadding: const .symmetric(horizontal: 8),
|
||||
title: InkWell(
|
||||
onTap: onTap,
|
||||
child: IgnorePointer(child: title),
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class AvatarOrHash extends ConsumerWidget {
|
|||
smallSize: 12,
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular((height - 8) / 2.5)),
|
||||
borderRadius: .all(.circular((height - 8) / 2.5)),
|
||||
child: SizedBox(
|
||||
width: height,
|
||||
height: height,
|
||||
|
|
@ -60,7 +60,7 @@ class AvatarOrHash extends ConsumerWidget {
|
|||
ref.watch(CrossCacheController.provider),
|
||||
headers: ref.headers,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
fit: .cover,
|
||||
loadingBuilder: (_, child, loadingProgress) =>
|
||||
loadingProgress == null ? child : box,
|
||||
errorBuilder: (_, _, _) => box,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import "package:flutter_hooks/flutter_hooks.dart";
|
|||
import "package:fluttertagger/fluttertagger.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:nexus/controllers/power_level_controller.dart";
|
||||
import "package:nexus/models/configs/power_level_config.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/relation_type.dart";
|
||||
import "package:nexus/widgets/composer/mention_overlay.dart";
|
||||
|
|
@ -42,7 +40,7 @@ class Composer extends HookConsumerWidget {
|
|||
final shouldMention = useState(true);
|
||||
final query = useState("");
|
||||
|
||||
if (relationType == RelationType.edit && controller.value.text.isEmpty) {
|
||||
if (relationType == .edit && controller.value.text.isEmpty) {
|
||||
controller.value.text = relatedEvent?.localContent?.editSource ?? "";
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +49,7 @@ class Composer extends HookConsumerWidget {
|
|||
onSend(
|
||||
controller.value.formattedText,
|
||||
shouldMention: shouldMention.value,
|
||||
tags: controller.value.tags.toIList(),
|
||||
tags: .new(controller.value.tags),
|
||||
);
|
||||
|
||||
onDismiss();
|
||||
|
|
@ -60,13 +58,13 @@ class Composer extends HookConsumerWidget {
|
|||
|
||||
final style = TextStyle(
|
||||
color: theme.colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: .bold,
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsetsGeometry.all(12),
|
||||
padding: .all(12),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
borderRadius: .all(.circular(12)),
|
||||
child: Column(
|
||||
children: [
|
||||
RelationPreview(
|
||||
|
|
@ -79,17 +77,14 @@ class Composer extends HookConsumerWidget {
|
|||
),
|
||||
Container(
|
||||
color: theme.colorScheme.surfaceContainerHighest,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
padding: .symmetric(horizontal: 8),
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment: .center,
|
||||
children:
|
||||
ref.watch(
|
||||
PowerLevelController.provider(
|
||||
PowerLevelConfig(
|
||||
eventType: EventType.message,
|
||||
roomId: roomId,
|
||||
),
|
||||
.new(eventType: .message, roomId: roomId),
|
||||
),
|
||||
)
|
||||
? [
|
||||
|
|
@ -124,7 +119,7 @@ class Composer extends HookConsumerWidget {
|
|||
),
|
||||
Expanded(
|
||||
child: FlutterTagger(
|
||||
triggerStrategy: TriggerStrategy.eager,
|
||||
triggerStrategy: .eager,
|
||||
overlay: MentionOverlay(
|
||||
roomId,
|
||||
query: query.value,
|
||||
|
|
@ -144,16 +139,16 @@ class Composer extends HookConsumerWidget {
|
|||
maxLines: 12,
|
||||
minLines: 1,
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
decoration: .new(
|
||||
hintText: "Your message here...",
|
||||
border: InputBorder.none,
|
||||
border: .none,
|
||||
),
|
||||
controller: controller.value,
|
||||
key: key,
|
||||
onSubmitted: (_) => send(),
|
||||
// Don't defocus on submit
|
||||
onEditingComplete: () {},
|
||||
textInputAction: TextInputAction.done,
|
||||
textInputAction: .done,
|
||||
focusNode: node,
|
||||
),
|
||||
),
|
||||
|
|
@ -167,10 +162,7 @@ class Composer extends HookConsumerWidget {
|
|||
: [
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsetsGeometry.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 12,
|
||||
),
|
||||
padding: .symmetric(horizontal: 8, vertical: 12),
|
||||
child: Text(
|
||||
"You don't have permission to send messages in this room...",
|
||||
),
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@ import "package:nexus/controllers/rooms_controller.dart";
|
|||
import "package:nexus/controllers/via_controller.dart";
|
||||
import "package:nexus/helpers/extensions/better_when.dart";
|
||||
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||
import "package:nexus/models/configs/members_by_status_config.dart";
|
||||
import "package:nexus/models/content/membership.dart";
|
||||
import "package:nexus/models/membership_status.dart";
|
||||
import "package:nexus/widgets/avatar_or_hash.dart";
|
||||
import "package:nexus/widgets/loading.dart";
|
||||
|
||||
|
|
@ -29,21 +27,18 @@ class MentionOverlay extends ConsumerWidget {
|
|||
final rooms = ref.watch(RoomsController.provider);
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(8),
|
||||
padding: .all(8),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
borderRadius: .all(.circular(12)),
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
padding: EdgeInsets.all(8),
|
||||
padding: .all(8),
|
||||
child: switch (triggerCharacter) {
|
||||
"@" =>
|
||||
ref
|
||||
.watch(
|
||||
MembersByStatusController.provider(
|
||||
MembersByStatusConfig(
|
||||
roomId: roomId,
|
||||
status: MembershipStatus.join,
|
||||
),
|
||||
.new(roomId: roomId, status: .join),
|
||||
),
|
||||
)
|
||||
.betterWhen(
|
||||
|
|
|
|||
|
|
@ -27,38 +27,34 @@ class RelationPreview extends ConsumerWidget {
|
|||
|
||||
return Container(
|
||||
color: theme.colorScheme.surfaceContainerHigh,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
padding: .symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
if (relationType == RelationType.edit)
|
||||
Text(
|
||||
"Editing message:",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (relationType == .edit)
|
||||
Text("Editing message:", style: .new(fontWeight: .bold)),
|
||||
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
padding: .symmetric(vertical: 8),
|
||||
child: EventPreview(relatedEvent!),
|
||||
),
|
||||
),
|
||||
|
||||
if (relationType == RelationType.reply)
|
||||
if (relationType == .reply)
|
||||
TextButton(
|
||||
onPressed: toggleShouldMention,
|
||||
child: Text(
|
||||
shouldMention ? "@On" : "@Off",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w900,
|
||||
fontWeight: .w900,
|
||||
color: shouldMention ? null : Theme.of(context).disabledColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
IconButton(
|
||||
tooltip:
|
||||
"Cancel ${relationType == RelationType.edit ? "edit" : "reply"}",
|
||||
tooltip: "Cancel ${relationType == .edit ? "edit" : "reply"}",
|
||||
onPressed: onDismiss,
|
||||
icon: const Icon(Icons.close),
|
||||
iconSize: 20,
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ class DividerText extends StatelessWidget {
|
|||
child: Divider(color: Theme.of(context).colorScheme.onSurface),
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: constraints.maxWidth - 32),
|
||||
constraints: .new(maxWidth: constraints.maxWidth - 32),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
padding: const .all(8),
|
||||
child: Text(text, style: Theme.of(context).textTheme.labelLarge),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -20,14 +20,14 @@ class EmojiPickerButton extends HookConsumerWidget {
|
|||
Widget build(_, WidgetRef ref) => IconButton(
|
||||
onPressed: () async {
|
||||
onPressed?.call();
|
||||
final controller = this.controller ?? TextEditingController();
|
||||
final controller = this.controller ?? .new();
|
||||
|
||||
final emojis = await ref.watch(EmojiController.provider.future);
|
||||
if (context.mounted) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => EmojiKeyboardView(
|
||||
config: EmojiViewConfig(
|
||||
config: .new(
|
||||
showRecentTab: false,
|
||||
customCategories: emojis.$1.unlock,
|
||||
customKeywords: emojis.$2.unlock,
|
||||
|
|
@ -37,7 +37,8 @@ class EmojiPickerButton extends HookConsumerWidget {
|
|||
textController: controller
|
||||
..addListener(() {
|
||||
// Without this, there will sometimes be a debugLocked is not true error sometimes
|
||||
Future.delayed(Duration.zero, () {
|
||||
// It might be preferable to use a microtask instead of a `Future.delayed`.
|
||||
Future.delayed(.zero, () {
|
||||
if (context.mounted) Navigator.of(context).pop();
|
||||
});
|
||||
onSelection?.call(controller.text);
|
||||
|
|
|
|||
|
|
@ -12,16 +12,16 @@ class EventPreview extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) => IgnorePointer(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 4),
|
||||
padding: .symmetric(vertical: 4),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisSize: .min,
|
||||
spacing: 12,
|
||||
children: [
|
||||
if (event.content is MessageContent) MessageAvatar(event),
|
||||
|
||||
Flexible(
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
crossAxisAlignment: .center,
|
||||
spacing: 8,
|
||||
runSpacing: 2,
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -20,14 +20,12 @@ class ExpandableImage extends ConsumerWidget {
|
|||
builder: (_) => LayoutBuilder(
|
||||
builder: (context, constraints) => Dialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
insetPadding: EdgeInsets.all(constraints.maxWidth / 100),
|
||||
insetPadding: .all(constraints.maxWidth / 100),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: min(constraints.maxWidth, 1000),
|
||||
),
|
||||
constraints: .new(minWidth: min(constraints.maxWidth, 1000)),
|
||||
child: InteractiveViewer(
|
||||
child: Image(
|
||||
fit: BoxFit.contain,
|
||||
fit: .contain,
|
||||
errorBuilder: (_, error, stackTrace) => ErrorDialog(
|
||||
"Loading failed for $source\nError: $error",
|
||||
stackTrace,
|
||||
|
|
|
|||
|
|
@ -15,11 +15,7 @@ class FileCard extends StatelessWidget {
|
|||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.file_copy),
|
||||
title: Text(
|
||||
filename ?? "file",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
title: Text(filename ?? "file", maxLines: 1, overflow: .ellipsis),
|
||||
subtitle: info?.size == null ? null : Text(info!.size!.sizeAsString),
|
||||
// TODO: Downloading files
|
||||
trailing: IconButton(onPressed: null, icon: Icon(Icons.download)),
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ class FlashWrapper extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) => ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
borderRadius: .all(.circular(12)),
|
||||
child: AnimatedContainer(
|
||||
padding: isFlashing ? EdgeInsets.all(8) : EdgeInsets.all(0),
|
||||
padding: isFlashing ? .all(8) : .all(0),
|
||||
color: isFlashing
|
||||
? Theme.of(context).colorScheme.onSurface.withAlpha(50)
|
||||
: Colors.transparent,
|
||||
duration: Duration(milliseconds: 250),
|
||||
duration: .new(milliseconds: 250),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -55,14 +55,12 @@ class FormTextInput extends StatelessWidget {
|
|||
maxLines: maxLines,
|
||||
maxLength: maxLength,
|
||||
inputFormatters: formatters,
|
||||
textCapitalization: capitalize
|
||||
? TextCapitalization.sentences
|
||||
: TextCapitalization.none,
|
||||
textCapitalization: capitalize ? .sentences : .none,
|
||||
initialValue: initialValue,
|
||||
autocorrect: autocorrect,
|
||||
obscureText: obscure,
|
||||
onTap: onTap,
|
||||
decoration: InputDecoration(
|
||||
decoration: .new(
|
||||
labelText: title,
|
||||
border: border ?? (outlined ? null : const UnderlineInputBorder()),
|
||||
suffixIcon: trailing,
|
||||
|
|
|
|||
|
|
@ -11,20 +11,20 @@ class CodeBlock extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||
borderRadius: .all(.circular(16)),
|
||||
child: ColoredBox(
|
||||
color: theme.colorScheme.surfaceContainerHighest,
|
||||
child: IntrinsicWidth(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment: .spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
padding: .symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
lang.substring(0, min(lang.length, 15)),
|
||||
style: TextStyle(fontFamily: "monospace"),
|
||||
style: .new(fontFamily: "monospace"),
|
||||
),
|
||||
),
|
||||
TextButton.icon(
|
||||
|
|
@ -37,13 +37,13 @@ class CodeBlock extends StatelessWidget {
|
|||
ColoredBox(
|
||||
color: theme.colorScheme.surfaceContainerHigh,
|
||||
child: Container(
|
||||
constraints: BoxConstraints(minWidth: 250),
|
||||
padding: EdgeInsets.all(8),
|
||||
constraints: .new(minWidth: 250),
|
||||
padding: .all(8),
|
||||
child: SelectableText(
|
||||
code,
|
||||
minLines: 1,
|
||||
maxLines: 99,
|
||||
style: TextStyle(fontFamily: "monospace"),
|
||||
style: .new(fontFamily: "monospace"),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -86,9 +86,7 @@ class Html extends ConsumerWidget {
|
|||
),
|
||||
errorBuilder: (_, error, _) => Text(
|
||||
"Image Failed to Load",
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
style: .new(color: Theme.of(context).colorScheme.error),
|
||||
),
|
||||
height: height.toDouble(),
|
||||
width: width?.toDouble(),
|
||||
|
|
@ -146,15 +144,14 @@ class Html extends ConsumerWidget {
|
|||
element.attributes
|
||||
.mapTo<MapEntry<String, String>?>(
|
||||
(key, value) => switch (key) {
|
||||
"data-mx-color" => MapEntry("color", value),
|
||||
"data-mx-bg-color" => MapEntry("background-color", value),
|
||||
"data-mx-color" => .new("color", value),
|
||||
"data-mx-bg-color" => .new("background-color", value),
|
||||
_ => null,
|
||||
},
|
||||
)
|
||||
.nonNulls,
|
||||
),
|
||||
},
|
||||
onTapUrl: (url) =>
|
||||
ref.watch(LaunchHelper.provider).launchUrl(Uri.parse(url)),
|
||||
onTapUrl: (url) => ref.watch(LaunchHelper.provider).launchUrl(.parse(url)),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
|
|||
import "package:nexus/controllers/user_controller.dart";
|
||||
import "package:nexus/helpers/extensions/link_to_mention.dart";
|
||||
import "package:nexus/helpers/extensions/show_user_popover.dart";
|
||||
import "package:nexus/models/configs/user_config.dart";
|
||||
|
||||
class MentionChip extends ConsumerWidget {
|
||||
final String? roomId;
|
||||
|
|
@ -16,9 +15,7 @@ class MentionChip extends ConsumerWidget {
|
|||
final membership = mention?.startsWith("@") == true
|
||||
? ref
|
||||
.watch(
|
||||
UserController.provider(
|
||||
UserConfig(roomId: roomId, userId: mention!),
|
||||
),
|
||||
UserController.provider(.new(roomId: roomId, userId: mention!)),
|
||||
)
|
||||
.whenOrNull(data: (data) => data)
|
||||
: null;
|
||||
|
|
@ -41,8 +38,8 @@ class MentionChip extends ConsumerWidget {
|
|||
label: Text(
|
||||
(membership == null ? null : "@${membership.displayName}") ??
|
||||
mention,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
style: .new(
|
||||
fontWeight: .bold,
|
||||
color: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ class Quoted extends StatelessWidget {
|
|||
Widget build(BuildContext context) => Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
left: BorderSide(width: 4, color: Theme.of(context).dividerColor),
|
||||
left: .new(width: 4, color: Theme.of(context).dividerColor),
|
||||
),
|
||||
),
|
||||
child: Padding(padding: EdgeInsets.only(left: 8), child: child),
|
||||
child: Padding(padding: .only(left: 8), child: child),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,15 +13,15 @@ class SpoilerText extends HookWidget {
|
|||
return InkWell(
|
||||
onTap: () => revealed.value = !revealed.value,
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 100),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
||||
duration: const .new(milliseconds: 100),
|
||||
padding: const .symmetric(horizontal: 4, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: revealed.value ? Colors.transparent : Colors.blueGrey,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
borderRadius: .circular(4),
|
||||
),
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(color: revealed.value ? null : Colors.transparent),
|
||||
style: .new(color: revealed.value ? null : Colors.transparent),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import "package:collection/collection.dart";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
|
|
@ -7,7 +6,6 @@ import "package:nexus/controllers/client_controller.dart";
|
|||
import "package:nexus/controllers/key_controller.dart";
|
||||
import "package:nexus/controllers/spaces_controller.dart";
|
||||
import "package:nexus/helpers/extensions/link_to_mention.dart";
|
||||
import "package:nexus/models/requests/join_room_request.dart";
|
||||
import "package:nexus/widgets/form_text_input.dart";
|
||||
|
||||
class JoinDialog extends HookWidget {
|
||||
|
|
@ -20,8 +18,8 @@ class JoinDialog extends HookWidget {
|
|||
return AlertDialog(
|
||||
title: Text("Join a Room"),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Text("Enter the room alias, Matrix URI, or Matrix.to link."),
|
||||
SizedBox(height: 12),
|
||||
|
|
@ -45,7 +43,7 @@ class JoinDialog extends HookWidget {
|
|||
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
||||
|
||||
final snackbar = scaffoldMessenger.showSnackBar(
|
||||
SnackBar(
|
||||
.new(
|
||||
content: Text("Joining room $roomIdOrAlias."),
|
||||
duration: Duration(days: 999),
|
||||
),
|
||||
|
|
@ -55,9 +53,9 @@ class JoinDialog extends HookWidget {
|
|||
final id = await ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.joinRoom(
|
||||
JoinRoomRequest(
|
||||
.new(
|
||||
roomIdOrAlias: roomIdOrAlias,
|
||||
via: IList(
|
||||
via: .new(
|
||||
Uri.tryParse(
|
||||
roomAlias.text.replaceAll("/#", ""),
|
||||
)?.queryParametersAll["via"] ??
|
||||
|
|
@ -69,9 +67,9 @@ class JoinDialog extends HookWidget {
|
|||
snackbar.close();
|
||||
|
||||
scaffoldMessenger.showSnackBar(
|
||||
SnackBar(
|
||||
.new(
|
||||
content: Text("Room $roomIdOrAlias successfully joined."),
|
||||
action: SnackBarAction(
|
||||
action: .new(
|
||||
label: "Open",
|
||||
onPressed: () async {
|
||||
final spaces = ref.watch(SpacesController.provider);
|
||||
|
|
@ -113,13 +111,13 @@ class JoinDialog extends HookWidget {
|
|||
snackbar.close();
|
||||
if (context.mounted) {
|
||||
scaffoldMessenger.showSnackBar(
|
||||
SnackBar(
|
||||
.new(
|
||||
backgroundColor: Theme.of(
|
||||
context,
|
||||
).colorScheme.errorContainer,
|
||||
content: Text(
|
||||
error.toString(),
|
||||
style: TextStyle(
|
||||
style: .new(
|
||||
color: Theme.of(context).colorScheme.onErrorContainer,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -18,52 +18,46 @@ class MessageDisplayname extends ConsumerWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) =>
|
||||
switch (ref.watch(AuthorController.provider(event))) {
|
||||
AsyncData(:final value) || AsyncLoading(:final value?) => InkWell(
|
||||
onTapUp: clickable
|
||||
? (details) => context.showUserPopover(
|
||||
value,
|
||||
event.sender,
|
||||
roomId: event.roomId,
|
||||
globalPosition: details.globalPosition,
|
||||
)
|
||||
: null,
|
||||
child: Wrap(
|
||||
spacing: 4,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
value.displayName ?? event.sender.localpart,
|
||||
style:
|
||||
style ??
|
||||
TextStyle(
|
||||
color: event.sender.colorHash,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Widget build(BuildContext context, WidgetRef ref) => switch (ref.watch(
|
||||
AuthorController.provider(event),
|
||||
)) {
|
||||
AsyncData(:final value) || AsyncLoading(:final value?) => InkWell(
|
||||
onTapUp: clickable
|
||||
? (details) => context.showUserPopover(
|
||||
value,
|
||||
event.sender,
|
||||
roomId: event.roomId,
|
||||
globalPosition: details.globalPosition,
|
||||
)
|
||||
: null,
|
||||
child: Wrap(
|
||||
spacing: 4,
|
||||
crossAxisAlignment: .center,
|
||||
children: [
|
||||
Text(
|
||||
value.displayName ?? event.sender.localpart,
|
||||
style:
|
||||
style ?? .new(color: event.sender.colorHash, fontWeight: .bold),
|
||||
maxLines: 1,
|
||||
overflow: .ellipsis,
|
||||
),
|
||||
|
||||
if (event.pmp != null)
|
||||
Text(
|
||||
"(via ${event.sender})",
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: event.sender.colorHash,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_ => Text(
|
||||
event.sender.localpart,
|
||||
style: TextStyle(
|
||||
color: event.sender.colorHash,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
};
|
||||
if (event.pmp != null)
|
||||
Text(
|
||||
"(via ${event.sender})",
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: event.sender.colorHash,
|
||||
fontWeight: .bold,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: .ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_ => Text(
|
||||
event.sender.localpart,
|
||||
style: .new(color: event.sender.colorHash, fontWeight: .bold),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ class LinkifiedText extends ConsumerWidget {
|
|||
text: text,
|
||||
maxLines: maxLines,
|
||||
style: style,
|
||||
options: LinkifyOptions(humanize: false),
|
||||
options: .new(humanize: false),
|
||||
onOpen: (link) =>
|
||||
ref.watch(LaunchHelper.provider).launchUrl(Uri.parse(link.url)),
|
||||
linkStyle: TextStyle(color: Theme.of(context).colorScheme.primary),
|
||||
overflow: maxLines == null ? null : TextOverflow.ellipsis,
|
||||
ref.watch(LaunchHelper.provider).launchUrl(.parse(link.url)),
|
||||
linkStyle: .new(color: Theme.of(context).colorScheme.primary),
|
||||
overflow: maxLines == null ? null : .ellipsis,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class Loading extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) => Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
padding: .all(16),
|
||||
child: SizedBox(height: height, child: CircularProgressIndicator()),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import "package:nexus/controllers/members_by_status_controller.dart";
|
|||
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||
import "package:nexus/helpers/extensions/show_user_popover.dart";
|
||||
import "package:nexus/helpers/extensions/string_to_color.dart";
|
||||
import "package:nexus/models/configs/members_by_status_config.dart";
|
||||
import "package:nexus/models/content/membership.dart";
|
||||
import "package:nexus/models/membership_status.dart";
|
||||
import "package:nexus/widgets/avatar_or_hash.dart";
|
||||
|
|
@ -21,7 +20,7 @@ class MemberList extends HookConsumerWidget {
|
|||
final status = useState(MembershipStatus.join);
|
||||
final membersProvider = ref.watch(
|
||||
MembersByStatusController.provider(
|
||||
MembersByStatusConfig(roomId: roomId, status: status.value),
|
||||
.new(roomId: roomId, status: status.value),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
@ -33,7 +32,7 @@ class MemberList extends HookConsumerWidget {
|
|||
scrolledUnderElevation: 0,
|
||||
leading: Icon(Icons.people),
|
||||
title: Text("Members"),
|
||||
actionsPadding: EdgeInsets.only(right: 4),
|
||||
actionsPadding: .only(right: 4),
|
||||
actions: [
|
||||
if (Scaffold.of(context).hasEndDrawer)
|
||||
IconButton(
|
||||
|
|
@ -44,24 +43,24 @@ class MemberList extends HookConsumerWidget {
|
|||
],
|
||||
),
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
alignment: .center,
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
FilterChip(
|
||||
label: Text("Joined"),
|
||||
onSelected: (value) => status.value = MembershipStatus.join,
|
||||
selected: status.value == MembershipStatus.join,
|
||||
onSelected: (value) => status.value = .join,
|
||||
selected: status.value == .join,
|
||||
),
|
||||
FilterChip(
|
||||
label: Text("Invited"),
|
||||
onSelected: (value) => status.value = MembershipStatus.invite,
|
||||
selected: status.value == MembershipStatus.invite,
|
||||
onSelected: (value) => status.value = .invite,
|
||||
selected: status.value == .invite,
|
||||
),
|
||||
FilterChip(
|
||||
label: Text("Banned"),
|
||||
onSelected: (value) => status.value = MembershipStatus.ban,
|
||||
selected: status.value == MembershipStatus.ban,
|
||||
onSelected: (value) => status.value = .ban,
|
||||
selected: status.value == .ban,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -93,15 +92,15 @@ class MemberList extends HookConsumerWidget {
|
|||
),
|
||||
title: Text(
|
||||
displayName ?? member.stateKey!.localpart,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
overflow: .ellipsis,
|
||||
style: .new(
|
||||
color: member.stateKey!.colorHash,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: .bold,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
member.stateKey!,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow: .ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class MessageImage extends ConsumerWidget {
|
|||
Widget build(BuildContext context, WidgetRef ref) => ExpandableImage(
|
||||
url.toString(),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
borderRadius: .all(.circular(8)),
|
||||
child: Image(
|
||||
image: CachedNetworkImage(
|
||||
url.toString(),
|
||||
|
|
@ -47,7 +47,7 @@ class MessageImage extends ConsumerWidget {
|
|||
errorBuilder: (context, error, stackTrace) => Center(
|
||||
child: Text(
|
||||
"Image Failed to Load",
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.error),
|
||||
style: .new(color: Theme.of(context).colorScheme.error),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ class AudioPlayer extends HookConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final player = useMemoized(
|
||||
() => Player(
|
||||
configuration: PlayerConfiguration(bufferSize: 128 * 1024 * 1024),
|
||||
),
|
||||
() => Player(configuration: .new(bufferSize: 128 * 1024 * 1024)),
|
||||
);
|
||||
|
||||
final playing = useState(false);
|
||||
|
|
@ -66,7 +64,7 @@ class AudioPlayer extends HookConsumerWidget {
|
|||
child: Card(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
child: Padding(
|
||||
padding: EdgeInsetsGeometry.only(left: 8, right: 16),
|
||||
padding: .only(left: 8, right: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
|
|
@ -88,7 +86,7 @@ class AudioPlayer extends HookConsumerWidget {
|
|||
: duration.value.inMilliseconds.toDouble(),
|
||||
value: position.value.inMilliseconds.toDouble(),
|
||||
onChanged: (value) =>
|
||||
player.seek(Duration(milliseconds: value.toInt())),
|
||||
player.seek(.new(milliseconds: value.toInt())),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ class VideoPlayer extends HookConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final player = useMemoized(
|
||||
() => Player(
|
||||
configuration: PlayerConfiguration(bufferSize: 128 * 1024 * 1024),
|
||||
),
|
||||
() => Player(configuration: .new(bufferSize: 128 * 1024 * 1024)),
|
||||
);
|
||||
final controller = useMemoized(() => VideoController(player));
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import "package:nexus/controllers/reactions_controller.dart";
|
|||
import "package:nexus/controllers/room_chat_controller.dart";
|
||||
import "package:nexus/helpers/extensions/get_headers.dart";
|
||||
import "package:nexus/helpers/extensions/mxc_to_https.dart";
|
||||
import "package:nexus/models/configs/reactions_config.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/widgets/error_dialog.dart";
|
||||
import "package:nexus/main.dart";
|
||||
|
|
@ -24,7 +23,7 @@ class ReactionRow extends ConsumerWidget {
|
|||
|
||||
return switch (ref.watch(
|
||||
ReactionsController.provider(
|
||||
ReactionsConfig(roomId: event.roomId, eventRowId: event.rowId),
|
||||
.new(roomId: event.roomId, eventRowId: event.rowId),
|
||||
),
|
||||
)) {
|
||||
AsyncData(value: final IMap<String, IList<String>>? reactors) ||
|
||||
|
|
@ -47,7 +46,7 @@ class ReactionRow extends ConsumerWidget {
|
|||
showCheckmark: false,
|
||||
selected: selected,
|
||||
label: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisSize: .min,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Flexible(
|
||||
|
|
@ -64,15 +63,9 @@ class ReactionRow extends ConsumerWidget {
|
|||
ref.watch(CrossCacheController.provider),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
reaction,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
count.toString(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
: Text(reaction, overflow: .ellipsis),
|
||||
),
|
||||
Text(count.toString(), overflow: .ellipsis),
|
||||
],
|
||||
),
|
||||
onSelected: enabled.value
|
||||
|
|
|
|||
|
|
@ -64,12 +64,11 @@ class EventRenderer extends ConsumerWidget {
|
|||
textOnly: textOnly,
|
||||
),
|
||||
|
||||
MembershipContent content =>
|
||||
event.previousContent is MembershipContent &&
|
||||
(event.previousContent as MembershipContent).status ==
|
||||
content.status
|
||||
? null
|
||||
: MembershipRenderer(event),
|
||||
MembershipContent content => switch (event.previousContent) {
|
||||
MembershipContent(:final status) =>
|
||||
status == content.status ? null : MembershipRenderer(event),
|
||||
_ => null,
|
||||
},
|
||||
|
||||
AvatarContent() => GenericEventRenderer(Icons.interests, [
|
||||
MessageDisplayname(event),
|
||||
|
|
@ -101,10 +100,10 @@ class EventRenderer extends ConsumerWidget {
|
|||
MessageDisplayname(event),
|
||||
Text(
|
||||
"changed the room's history visibility to ${switch (historyVisibility) {
|
||||
HistoryVisibility.invited => "since invited",
|
||||
HistoryVisibility.joined => "since joined",
|
||||
HistoryVisibility.shared => "all history visible (shared)",
|
||||
HistoryVisibility.worldReadable => "all history visible (world readable)",
|
||||
.invited => "since invited",
|
||||
.joined => "since joined",
|
||||
.shared => "all history visible (shared)",
|
||||
.worldReadable => "all history visible (world readable)",
|
||||
}}",
|
||||
),
|
||||
]),
|
||||
|
|
@ -158,7 +157,7 @@ class EventRenderer extends ConsumerWidget {
|
|||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
if (child != null) ...[
|
||||
if (textOnly)
|
||||
|
|
@ -168,7 +167,7 @@ class EventRenderer extends ConsumerWidget {
|
|||
onSecondaryTapUp: contextMenuCallback,
|
||||
onLongPressStart: contextMenuCallback,
|
||||
child: Padding(
|
||||
padding: isGrouped ? EdgeInsets.zero : EdgeInsets.only(top: 8),
|
||||
padding: isGrouped ? .zero : .only(top: 8),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
|
|
@ -183,12 +182,7 @@ class EventRenderer extends ConsumerWidget {
|
|||
color: theme.colorScheme.error,
|
||||
),
|
||||
),
|
||||
].map(
|
||||
(child) => Padding(
|
||||
padding: EdgeInsetsGeometry.only(left: 4),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
].map((child) => Padding(padding: .only(left: 4), child: child)),
|
||||
],
|
||||
] else if (textOnly)
|
||||
Text("Unknown event type", style: errorStyle),
|
||||
|
|
|
|||
|
|
@ -7,14 +7,11 @@ class GenericEventRenderer extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) => Padding(
|
||||
padding: EdgeInsets.only(bottom: 8),
|
||||
padding: .only(bottom: 8),
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Icon(icon),
|
||||
),
|
||||
Padding(padding: .symmetric(horizontal: 4), child: Icon(icon)),
|
||||
Expanded(child: Wrap(spacing: 4, children: children)),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import "package:nexus/helpers/extensions/show_user_popover.dart";
|
|||
import "package:nexus/helpers/extensions/string_to_color.dart";
|
||||
import "package:nexus/models/content/membership.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/membership_status.dart";
|
||||
import "package:nexus/widgets/lazy_loading/message_displayname.dart";
|
||||
import "package:nexus/widgets/renderers/generic_event.dart";
|
||||
|
||||
|
|
@ -29,24 +28,21 @@ class MembershipRenderer extends StatelessWidget {
|
|||
globalPosition: details.globalPosition,
|
||||
),
|
||||
child: Text(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow: .ellipsis,
|
||||
content.displayName ?? event.stateKey!.localpart,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
color: event.sender.colorHash,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: .new(color: event.sender.colorHash, fontWeight: .bold),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow: .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",
|
||||
.invite => "was invited to",
|
||||
.join => "joined",
|
||||
.leave => event.sender == event.stateKey ? "left" : (event.unsigned["prev_content"]?["membership"] == "ban" ? "was unbanned from" : "was kicked from"),
|
||||
.ban => "was banned from",
|
||||
.knock => "asked to join",
|
||||
}} the room${event.sender == event.stateKey ? "" : " by "}",
|
||||
),
|
||||
if (event.sender != event.stateKey) MessageDisplayname(event),
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import "package:nexus/models/content/encrypted.dart";
|
|||
import "package:nexus/models/content/message.dart";
|
||||
import "package:nexus/models/content/sticker.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/requests/get_event_request.dart";
|
||||
import "package:nexus/widgets/file_card.dart";
|
||||
import "package:nexus/widgets/html/html.dart";
|
||||
import "package:nexus/widgets/lazy_loading/message_avatar.dart";
|
||||
|
|
@ -49,19 +48,19 @@ class MessageRenderer extends ConsumerWidget {
|
|||
child: Text(
|
||||
format(event.timestamp),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow: .ellipsis,
|
||||
style: theme.textTheme.labelSmall?.copyWith(color: Colors.grey),
|
||||
),
|
||||
);
|
||||
|
||||
final textStyle = TextStyle(
|
||||
fontSize: event.localContent?.bigEmoji == true ? 32 : null,
|
||||
fontStyle: event.content is EmoteMessageContent ? FontStyle.italic : null,
|
||||
fontStyle: event.content is EmoteMessageContent ? .italic : null,
|
||||
);
|
||||
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: .start,
|
||||
mainAxisSize: .min,
|
||||
spacing: 8,
|
||||
children: [
|
||||
if (!textOnly)
|
||||
|
|
@ -72,7 +71,7 @@ class MessageRenderer extends ConsumerWidget {
|
|||
Flexible(
|
||||
child: Column(
|
||||
spacing: 4,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
if (!isGrouped && !textOnly)
|
||||
Row(
|
||||
|
|
@ -83,7 +82,7 @@ class MessageRenderer extends ConsumerWidget {
|
|||
],
|
||||
),
|
||||
Card(
|
||||
margin: textOnly ? EdgeInsets.zero : EdgeInsets.only(bottom: 4),
|
||||
margin: textOnly ? .zero : .only(bottom: 4),
|
||||
color: textOnly
|
||||
? Colors.transparent
|
||||
: ref.watch(
|
||||
|
|
@ -99,24 +98,21 @@ class MessageRenderer extends ConsumerWidget {
|
|||
elevation: textOnly ? 0 : null,
|
||||
|
||||
child: Padding(
|
||||
padding: textOnly ? EdgeInsets.zero : EdgeInsets.all(12),
|
||||
padding: textOnly ? .zero : .all(12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
if (!textOnly && event.replyTo != null)
|
||||
Card(
|
||||
margin: EdgeInsets.only(bottom: 8),
|
||||
margin: .only(bottom: 8),
|
||||
color: theme.colorScheme.surfaceContainerHigh,
|
||||
child: InkWell(
|
||||
onTap: onTapReply,
|
||||
child: Padding(
|
||||
padding: EdgeInsetsGeometry.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 12,
|
||||
),
|
||||
padding: .symmetric(vertical: 8, horizontal: 12),
|
||||
child: switch (ref.watch(
|
||||
EventController.provider(
|
||||
GetEventRequest(
|
||||
.new(
|
||||
roomId: event.roomId,
|
||||
eventId: event.replyTo!,
|
||||
),
|
||||
|
|
@ -145,12 +141,10 @@ class MessageRenderer extends ConsumerWidget {
|
|||
? Text(
|
||||
body,
|
||||
maxLines: maxLines,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow: .ellipsis,
|
||||
)
|
||||
: ConstrainedBox(
|
||||
constraints: BoxConstraints.loose(
|
||||
Size.square(200),
|
||||
),
|
||||
constraints: .loose(.square(200)),
|
||||
child: MessageImage(
|
||||
url.mxcToHttps(
|
||||
ref.watch(
|
||||
|
|
@ -199,9 +193,9 @@ class MessageRenderer extends ConsumerWidget {
|
|||
:final formattedBody,
|
||||
:final format,
|
||||
) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
format == MessageFormat.html && !textOnly
|
||||
format == .html && !textOnly
|
||||
? Html(
|
||||
roomId: event.roomId,
|
||||
textStyle: textStyle,
|
||||
|
|
@ -243,9 +237,7 @@ class MessageRenderer extends ConsumerWidget {
|
|||
),
|
||||
)) {
|
||||
final url? => ConstrainedBox(
|
||||
constraints: BoxConstraints.loose(
|
||||
Size.square(500),
|
||||
),
|
||||
constraints: .loose(.square(500)),
|
||||
child: switch (event.content) {
|
||||
VideoMessageContent(:final info) =>
|
||||
VideoPlayer(url, info),
|
||||
|
|
@ -286,7 +278,7 @@ class MessageRenderer extends ConsumerWidget {
|
|||
),
|
||||
MessageContent(:final body) => Row(
|
||||
spacing: 8,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisSize: .min,
|
||||
children: [
|
||||
Text("Unknown message type:", style: errorStyle),
|
||||
Text(body),
|
||||
|
|
|
|||
|
|
@ -38,17 +38,17 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
|
|||
: () => showDialog(
|
||||
context: context,
|
||||
builder: (context) => Dialog(
|
||||
constraints: BoxConstraints.loose(Size.fromWidth(400)),
|
||||
constraints: .loose(.fromWidth(400)),
|
||||
child: Padding(
|
||||
padding: EdgeInsetsGeometry.all(24),
|
||||
padding: .all(24),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 12,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisSize: .min,
|
||||
children: [
|
||||
if (room.metadata?.avatar != null)
|
||||
ExpandableImage(
|
||||
|
|
@ -71,7 +71,7 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
|
|||
Expanded(
|
||||
child: Text(
|
||||
room.metadata?.name ?? "Unnamed Room",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow: .ellipsis,
|
||||
maxLines: 3,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
|
|
@ -105,18 +105,18 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
|
|||
title: room == null
|
||||
? null
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Text(
|
||||
room.metadata?.name ?? "Unnamed Room",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow: .ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
if (room.metadata?.topic?.isNotEmpty == true)
|
||||
Text(
|
||||
room.metadata!.topic!,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow: .ellipsis,
|
||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -12,11 +12,9 @@ import "package:nexus/controllers/rooms_controller.dart";
|
|||
import "package:nexus/controllers/room_chat_controller.dart";
|
||||
import "package:nexus/controllers/via_controller.dart";
|
||||
import "package:nexus/models/configs/power_level_config.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/message.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/relation_type.dart";
|
||||
import "package:nexus/models/requests/report_request.dart";
|
||||
import "package:nexus/widgets/composer/composer.dart";
|
||||
import "package:nexus/widgets/emoji_picker_button.dart";
|
||||
import "package:nexus/widgets/renderers/event.dart";
|
||||
|
|
@ -102,8 +100,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
|
||||
final composerNode = useFocusNode(
|
||||
onKeyEvent: (_, event) {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.escape) {
|
||||
if (event is KeyDownEvent && event.logicalKey == .escape) {
|
||||
relatedEvent.value = null;
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
|
|
@ -118,7 +115,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
return [
|
||||
if (ref.watch(
|
||||
PowerLevelController.provider(
|
||||
PowerLevelConfig(eventType: EventType.reaction, roomId: roomId),
|
||||
.new(eventType: .reaction, roomId: roomId),
|
||||
),
|
||||
))
|
||||
PopupMenuItem(
|
||||
|
|
@ -134,7 +131,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
value["m.recent_emoji"]
|
||||
?.content["recent_emoji"] ??
|
||||
[],
|
||||
).map((entry) => entry["emoji"]),
|
||||
).map((entry) => entry["emoji"]).toIList(),
|
||||
),
|
||||
),
|
||||
"👍",
|
||||
|
|
@ -167,13 +164,13 @@ class RoomChat extends HookConsumerWidget {
|
|||
),
|
||||
if (ref.watch(
|
||||
PowerLevelController.provider(
|
||||
PowerLevelConfig(eventType: EventType.message, roomId: roomId),
|
||||
PowerLevelConfig(eventType: .message, roomId: roomId),
|
||||
),
|
||||
))
|
||||
PopupMenuItem(
|
||||
onTap: () {
|
||||
relatedEvent.value = event;
|
||||
relationType.value = RelationType.reply;
|
||||
relationType.value = .reply;
|
||||
composerNode.requestFocus();
|
||||
},
|
||||
child: ListTile(leading: Icon(Icons.reply), title: Text("Reply")),
|
||||
|
|
@ -182,7 +179,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
PopupMenuItem(
|
||||
onTap: () {
|
||||
relatedEvent.value = event;
|
||||
relationType.value = RelationType.edit;
|
||||
relationType.value = .edit;
|
||||
composerNode.requestFocus();
|
||||
},
|
||||
child: ListTile(leading: Icon(Icons.edit), title: Text("Edit")),
|
||||
|
|
@ -207,10 +204,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
),
|
||||
if (ref.watch(
|
||||
PowerLevelController.provider(
|
||||
PowerLevelConfig.redaction(
|
||||
targetUser: event.sender,
|
||||
roomId: roomId,
|
||||
),
|
||||
.redaction(targetUser: event.sender, roomId: roomId),
|
||||
),
|
||||
))
|
||||
PopupMenuItem(
|
||||
|
|
@ -222,8 +216,8 @@ class RoomChat extends HookConsumerWidget {
|
|||
return AlertDialog(
|
||||
title: Text("Delete Message"),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Text(
|
||||
"Are you sure you want to delete this message? This can not be reversed.",
|
||||
|
|
@ -261,7 +255,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
),
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.delete, color: danger),
|
||||
title: Text("Delete", style: TextStyle(color: danger)),
|
||||
title: Text("Delete", style: .new(color: danger)),
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
|
|
@ -273,8 +267,8 @@ class RoomChat extends HookConsumerWidget {
|
|||
return AlertDialog(
|
||||
title: Text("Report"),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Text(
|
||||
"Report this event to your server administrators, who can take action like banning this server or room.",
|
||||
|
|
@ -297,7 +291,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
TextButton(
|
||||
onPressed: () {
|
||||
client.reportEvent(
|
||||
ReportRequest(
|
||||
.new(
|
||||
roomId: roomId,
|
||||
eventId: event.eventId,
|
||||
reason: reasonController.text.isEmpty
|
||||
|
|
@ -316,7 +310,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
),
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.report, color: danger),
|
||||
title: Text("Report", style: TextStyle(color: danger)),
|
||||
title: Text("Report", style: .new(color: danger)),
|
||||
),
|
||||
),
|
||||
].toIList();
|
||||
|
|
@ -341,7 +335,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
children: [
|
||||
Positioned.fill(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
padding: .symmetric(horizontal: 12),
|
||||
child: switch (controllerData) {
|
||||
AsyncData(:final value) ||
|
||||
AsyncLoading(:final value?) => CustomScrollView(
|
||||
|
|
@ -349,9 +343,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
controller: scrollController,
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsetsGeometry.only(
|
||||
bottom: composerSize.value,
|
||||
),
|
||||
padding: .only(bottom: composerSize.value),
|
||||
),
|
||||
|
||||
SuperSliverList.builder(
|
||||
|
|
@ -371,19 +363,15 @@ class RoomChat extends HookConsumerWidget {
|
|||
),
|
||||
scrollController: scrollController,
|
||||
alignment: 0.5,
|
||||
duration: (_) =>
|
||||
Duration(milliseconds: 700),
|
||||
duration: (_) => .new(milliseconds: 700),
|
||||
curve: (_) => Curves.easeInOut,
|
||||
);
|
||||
flashingEvent.value = replyId;
|
||||
await Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() {
|
||||
if (flashingEvent.value == replyId) {
|
||||
flashingEvent.value = null;
|
||||
}
|
||||
},
|
||||
);
|
||||
await Future.delayed(.new(seconds: 1), () {
|
||||
if (flashingEvent.value == replyId) {
|
||||
flashingEvent.value = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
getEventOptions: getEventOptions,
|
||||
isGrouped:
|
||||
|
|
@ -403,7 +391,7 @@ class RoomChat extends HookConsumerWidget {
|
|||
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 36),
|
||||
padding: .symmetric(vertical: 36),
|
||||
child: Center(
|
||||
child: controllerData is AsyncLoading
|
||||
? Loading()
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class RoomMenu extends ConsumerWidget {
|
|||
final vias = ref.watch(ViaController.provider(room!));
|
||||
|
||||
await Clipboard.setData(
|
||||
ClipboardData(
|
||||
.new(
|
||||
text:
|
||||
"matrix:roomid/${room!.metadata?.id.substring(1)}$vias)",
|
||||
),
|
||||
|
|
@ -63,7 +63,7 @@ class RoomMenu extends ConsumerWidget {
|
|||
Navigator.of(context).pop();
|
||||
final snackbar = ScaffoldMessenger.of(context)
|
||||
.showSnackBar(
|
||||
SnackBar(
|
||||
.new(
|
||||
content: Text("Leaving room..."),
|
||||
duration: Duration(days: 1),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -74,14 +74,14 @@ class Sidebar extends HookConsumerWidget {
|
|||
),
|
||||
),
|
||||
label: Text(space.title),
|
||||
padding: EdgeInsets.only(top: 4),
|
||||
padding: .only(top: 4),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
selectedIndex: selectedIndex,
|
||||
trailingAtBottom: true,
|
||||
trailing: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
padding: .symmetric(vertical: 16),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
|
|
@ -136,10 +136,7 @@ class Sidebar extends HookConsumerWidget {
|
|||
|
||||
selectedSpace.title,
|
||||
),
|
||||
title: Text(
|
||||
selectedSpace.title,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
title: Text(selectedSpace.title, overflow: .ellipsis),
|
||||
backgroundColor: Colors.transparent,
|
||||
actions: [
|
||||
RoomMenu(
|
||||
|
|
|
|||
|
|
@ -13,25 +13,24 @@ class UrlPreview extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) => ConstrainedBox(
|
||||
constraints: BoxConstraints.loose(Size.fromWidth(400)),
|
||||
constraints: .loose(.fromWidth(400)),
|
||||
child: ref
|
||||
.watch(UrlPreviewController.provider(link))
|
||||
.betterWhen(
|
||||
data: (preview) => preview == null
|
||||
? SizedBox.shrink()
|
||||
: InkWell(
|
||||
onTap: () => ref
|
||||
.watch(LaunchHelper.provider)
|
||||
.launchUrl(Uri.parse(link)),
|
||||
onTap: () =>
|
||||
ref.watch(LaunchHelper.provider).launchUrl(.parse(link)),
|
||||
child: Card(
|
||||
margin: EdgeInsets.symmetric(vertical: 4),
|
||||
margin: .symmetric(vertical: 4),
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.surfaceContainerHighest,
|
||||
child: Padding(
|
||||
padding: EdgeInsetsGeometry.all(16),
|
||||
padding: .all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: .start,
|
||||
spacing: 4,
|
||||
children: [
|
||||
if (preview.title != null)
|
||||
|
|
@ -45,9 +44,7 @@ class UrlPreview extends ConsumerWidget {
|
|||
],
|
||||
if (preview.imageUrl != null)
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(8),
|
||||
),
|
||||
borderRadius: .all(.circular(8)),
|
||||
child: Image(
|
||||
errorBuilder: (_, _, _) => SizedBox.shrink(),
|
||||
width: preview.width,
|
||||
|
|
@ -56,7 +53,7 @@ class UrlPreview extends ConsumerWidget {
|
|||
ref.watch(CrossCacheController.provider),
|
||||
headers: ref.headers,
|
||||
),
|
||||
fit: BoxFit.fitWidth,
|
||||
fit: .fitWidth,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -9,11 +9,8 @@ import "package:nexus/controllers/profile_controller.dart";
|
|||
import "package:nexus/helpers/extensions/better_when.dart";
|
||||
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||
import "package:nexus/helpers/extensions/mxc_to_https.dart";
|
||||
import "package:nexus/models/configs/power_level_config.dart";
|
||||
import "package:nexus/models/content/membership.dart";
|
||||
import "package:nexus/models/membership_status.dart";
|
||||
import "package:nexus/models/requests/membership_action.dart";
|
||||
import "package:nexus/models/requests/set_membership_request.dart";
|
||||
import "package:nexus/widgets/avatar_or_hash.dart";
|
||||
import "package:nexus/main.dart";
|
||||
import "package:nexus/widgets/expandable_image.dart";
|
||||
|
|
@ -39,8 +36,8 @@ class UserPopover extends ConsumerWidget {
|
|||
return AlertDialog(
|
||||
title: Text("${toBeginningOfSentenceCase(action.name)} $userId"),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Text("Are you sure you want to ${action.name} $userId?"),
|
||||
SizedBox(height: 12),
|
||||
|
|
@ -62,7 +59,7 @@ class UserPopover extends ConsumerWidget {
|
|||
Navigator.of(context).pop();
|
||||
client
|
||||
.setMembership(
|
||||
SetMembershipRequest(
|
||||
.new(
|
||||
userId: userId,
|
||||
roomId: roomId!,
|
||||
action: action,
|
||||
|
|
@ -80,20 +77,18 @@ class UserPopover extends ConsumerWidget {
|
|||
);
|
||||
|
||||
final actionButton = ButtonStyle(
|
||||
padding: WidgetStatePropertyAll(
|
||||
EdgeInsets.symmetric(horizontal: 24, vertical: 18),
|
||||
),
|
||||
padding: WidgetStatePropertyAll(.symmetric(horizontal: 24, vertical: 18)),
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
RoundedRectangleBorder(borderRadius: .circular(8)),
|
||||
),
|
||||
);
|
||||
|
||||
return Column(
|
||||
spacing: 16,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
crossAxisAlignment: .stretch,
|
||||
children: [
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
alignment: .center,
|
||||
spacing: 16,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
|
|
@ -126,7 +121,7 @@ class UserPopover extends ConsumerWidget {
|
|||
.betterWhen(
|
||||
loading: SizedBox.shrink,
|
||||
data: (profile) => Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
alignment: .center,
|
||||
spacing: 4,
|
||||
runSpacing: 4,
|
||||
children: [
|
||||
|
|
@ -135,7 +130,7 @@ class UserPopover extends ConsumerWidget {
|
|||
))
|
||||
Chip(
|
||||
label: Text(pronoun.summary),
|
||||
labelStyle: TextStyle(
|
||||
labelStyle: .new(
|
||||
color: theme.colorScheme.onPrimary,
|
||||
),
|
||||
color: WidgetStatePropertyAll(
|
||||
|
|
@ -145,7 +140,7 @@ class UserPopover extends ConsumerWidget {
|
|||
if (profile.timezone != null)
|
||||
Chip(
|
||||
label: Text(profile.timezone!),
|
||||
labelStyle: TextStyle(
|
||||
labelStyle: .new(
|
||||
color: theme.colorScheme.onPrimary,
|
||||
),
|
||||
color: WidgetStatePropertyAll(
|
||||
|
|
@ -162,7 +157,7 @@ class UserPopover extends ConsumerWidget {
|
|||
if (userId != ref.watch(ClientStateController.provider)?.userId &&
|
||||
roomId != null)
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
alignment: .center,
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
|
|
@ -175,17 +170,17 @@ class UserPopover extends ConsumerWidget {
|
|||
|
||||
if (ref.watch(
|
||||
PowerLevelController.provider(
|
||||
PowerLevelConfig.membershipAction(
|
||||
action: MembershipAction.kick,
|
||||
.membershipAction(
|
||||
action: .kick,
|
||||
roomId: roomId!,
|
||||
targetUser: userId,
|
||||
),
|
||||
),
|
||||
) &&
|
||||
member.status == MembershipStatus.join ||
|
||||
member.status == MembershipStatus.invite)
|
||||
member.status == .join ||
|
||||
member.status == .invite)
|
||||
FilledButton.icon(
|
||||
onPressed: () => showMembershipDialog(MembershipAction.kick),
|
||||
onPressed: () => showMembershipDialog(.kick),
|
||||
label: Text("Kick"),
|
||||
style: actionButton.copyWith(
|
||||
backgroundColor: WidgetStatePropertyAll(
|
||||
|
|
@ -199,23 +194,19 @@ class UserPopover extends ConsumerWidget {
|
|||
),
|
||||
if (ref.watch(
|
||||
PowerLevelController.provider(
|
||||
PowerLevelConfig.membershipAction(
|
||||
.membershipAction(
|
||||
roomId: roomId!,
|
||||
action: MembershipAction.ban,
|
||||
action: .ban,
|
||||
targetUser: userId,
|
||||
),
|
||||
),
|
||||
))
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => showMembershipDialog(
|
||||
member.status == MembershipStatus.ban
|
||||
? MembershipAction.unban
|
||||
: MembershipAction.ban,
|
||||
member.status == .ban ? .unban : .ban,
|
||||
),
|
||||
icon: Icon(Icons.gavel),
|
||||
label: Text(
|
||||
member.status == MembershipStatus.ban ? "Unban" : "Ban",
|
||||
),
|
||||
label: Text(member.status == .ban ? "Unban" : "Ban"),
|
||||
style: actionButton.copyWith(
|
||||
backgroundColor: WidgetStatePropertyAll(
|
||||
theme.colorScheme.errorContainer,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue