Move to Flutter 3.47, use the improvements that come with this (#64)

Reviewed-on: #64
This commit is contained in:
Henry Hiles 2026-08-22 13:04:33 -04:00 committed by Henry Hiles
commit 077044ec19
157 changed files with 1366 additions and 1457 deletions

View file

@ -1,28 +1,20 @@
import "dart:io";
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/settings.dart";
import "package:window_manager/window_manager.dart";
class Appbar extends ConsumerWidget implements PreferredSizeWidget {
final Widget? leading;
final Widget? title;
final Color? backgroundColor;
final double? scrolledUnderElevation;
final IList<Widget> actions;
final VoidCallback? onTap;
const Appbar({
super.key,
this.title,
this.onTap,
this.backgroundColor,
this.scrolledUnderElevation,
this.leading,
this.actions = const .empty(),
});
final class const Appbar({
final Widget? leading,
final Widget? title,
final Color? backgroundColor,
final double? scrolledUnderElevation,
final IList<Widget> actions = const .empty(),
final VoidCallback? onTap,
super.key,
}) extends ConsumerWidget implements PreferredSizeWidget {
@override
Size get preferredSize => const .fromHeight(kToolbarHeight);

View file

@ -1,21 +1,15 @@
import "package:color_hash/color_hash.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/helpers/mxc_image.dart";
class AvatarOrHash extends ConsumerWidget {
final Uri? avatar;
final String title;
final Widget? fallback;
final double height;
const AvatarOrHash(
this.avatar,
this.title, {
this.fallback,
this.height = 24,
super.key,
});
final class const AvatarOrHash(
final Uri? avatar,
final String title, {
final Widget? fallback,
final double height = 24,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final box = ColoredBox(

View file

@ -1,7 +1,8 @@
import "dart:io";
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:file_selector/file_selector.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter/services.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:fluttertagger/fluttertagger.dart";
@ -17,28 +18,20 @@ import "package:nexus/widgets/composer/relation_preview.dart";
import "package:nexus/widgets/emoji_picker_button.dart";
import "package:nexus/main.dart";
class Composer extends HookConsumerWidget {
final String roomId;
final Event? relatedEvent;
final RelationType relationType;
final VoidCallback onDismiss;
final FocusNode? node;
final Future<void> Function(
class const Composer(
final String roomId, {
required final Event? relatedEvent,
required final RelationType relationType,
required final VoidCallback onDismiss,
required final Future<void> Function(
String text, {
required bool shouldMention,
required IList<Tag> tags,
})
onSend;
const Composer(
this.roomId, {
required this.relatedEvent,
required this.relationType,
required this.onDismiss,
required this.onSend,
this.node,
super.key,
});
onSend,
final FocusNode? node,
super.key,
}) extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context);
@ -143,9 +136,8 @@ class Composer extends HookConsumerWidget {
),
onTap: () async => ref
.watch(
AttachmentController.provider(
roomId,
).notifier,
AttachmentController.provider(roomId)
.notifier,
)
.add(
(await ref
@ -163,9 +155,8 @@ class Composer extends HookConsumerWidget {
),
onTap: () async => ref
.watch(
AttachmentController.provider(
roomId,
).notifier,
AttachmentController.provider(roomId)
.notifier,
)
.add(
(await ref
@ -179,9 +170,8 @@ class Composer extends HookConsumerWidget {
PopupMenuItem(
onTap: () async => ref
.watch(
AttachmentController.provider(
roomId,
).notifier,
AttachmentController.provider(roomId)
.notifier,
)
.add((await openFile())!)
.onError(showError),

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/members_by_status.dart";
import "package:nexus/controllers/rooms.dart";
@ -9,19 +9,14 @@ import "package:nexus/models/content/membership.dart";
import "package:nexus/widgets/avatar_or_hash.dart";
import "package:nexus/widgets/loading.dart";
class MentionOverlay extends ConsumerWidget {
final String? triggerCharacter;
final String query;
final String roomId;
final void Function({required String id, required String name}) addTag;
const MentionOverlay(
this.roomId, {
required this.query,
required this.addTag,
required this.triggerCharacter,
super.key,
});
class const MentionOverlay(
final String roomId, {
required final String query,
required final void Function({required String id, required String name})
addTag,
required final String? triggerCharacter,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final rooms = ref.watch(RoomsController.provider);

View file

@ -1,25 +1,17 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/models/event.dart";
import "package:nexus/models/relation_type.dart";
import "package:nexus/widgets/event_preview.dart";
class RelationPreview extends ConsumerWidget {
final Event? relatedEvent;
final RelationType relationType;
final VoidCallback onDismiss;
final bool shouldMention;
final VoidCallback toggleShouldMention;
const RelationPreview(
this.relatedEvent, {
required this.relationType,
required this.onDismiss,
required this.shouldMention,
required this.toggleShouldMention,
super.key,
});
class const RelationPreview(
final Event? relatedEvent, {
required final RelationType relationType,
required final VoidCallback onDismiss,
required final bool shouldMention,
required final VoidCallback toggleShouldMention,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
if (relatedEvent == null) return SizedBox.shrink();

View file

@ -1,11 +1,8 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:nexus/widgets/divider_widget.dart";
class DividerText extends StatelessWidget {
final String text;
const DividerText(this.text, {super.key});
final class const DividerText(final String text, {super.key})
extends StatelessWidget {
@override
Widget build(BuildContext context) =>
DividerWidget(Text(text, style: Theme.of(context).textTheme.labelLarge));

View file

@ -1,9 +1,7 @@
import "package:flutter/material.dart";
class DividerWidget extends StatelessWidget {
final Widget widget;
const DividerWidget(this.widget, {super.key});
import "package:material_ui/material_ui.dart";
final class const DividerWidget(final Widget widget, {super.key})
extends StatelessWidget {
@override
Widget build(BuildContext context) => LayoutBuilder(
builder: (_, constraints) => Row(

View file

@ -1,21 +1,15 @@
import "package:emoji_text_field/emoji_text_field.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/emoji.dart";
class EmojiPickerButton extends HookConsumerWidget {
final TextEditingController? controller;
final void Function(String emoji)? onSelection;
final VoidCallback? onPressed;
final BuildContext context;
const EmojiPickerButton({
this.controller,
this.onPressed,
this.onSelection,
required this.context,
super.key,
});
final class const EmojiPickerButton({
required final BuildContext context,
final TextEditingController? controller,
final void Function(String emoji)? onSelection,
final VoidCallback? onPressed,
super.key,
}) extends HookConsumerWidget {
@override
Widget build(_, WidgetRef ref) => IconButton(
onPressed: () async {

View file

@ -1,13 +1,13 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:flutter_riverpod/misc.dart";
class ErrorDialog extends ConsumerWidget {
final Object error;
final StackTrace? stackTrace;
final ProviderOrFamily? provider;
const ErrorDialog(this.error, this.stackTrace, {this.provider, super.key});
final class const ErrorDialog(
final Object error,
final StackTrace? stackTrace, {
final ProviderOrFamily? provider,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return AlertDialog(

View file

@ -1,14 +1,12 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.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});
class const EventPreview(final Event event, {super.key})
extends StatelessWidget {
@override
Widget build(BuildContext context) => IgnorePointer(
child: Padding(

View file

@ -1,15 +1,15 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:m3e_buttons/m3e_buttons.dart";
import "package:nexus/helpers/mxc_image.dart";
import "package:nexus/models/requests/download_media.dart";
import "package:nexus/widgets/error_dialog.dart";
class ExpandableImage extends ConsumerWidget {
final Widget child;
final DownloadMediaRequest? request;
const ExpandableImage(this.request, {required this.child, super.key});
final class const ExpandableImage(
final DownloadMediaRequest? request, {
required final Widget child,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) => InkWell(
onTap: request == null

View file

@ -1,13 +1,13 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:nexus/helpers/extensions/size_to_string.dart";
import "package:nexus/models/info/file.dart";
class FileCard extends StatelessWidget {
final Uri uri;
final FileInfo? info;
final String? filename;
const FileCard(this.uri, this.info, {this.filename, super.key});
final class const FileCard(
final Uri uri,
final FileInfo? info, {
final String? filename,
super.key,
}) extends StatelessWidget {
@override
Widget build(BuildContext context) => SizedBox(
width: 320,

View file

@ -1,10 +1,10 @@
import "package:flutter/material.dart";
class HighlightWrapper extends StatelessWidget {
final Widget child;
final bool isHighlighted;
const HighlightWrapper(this.child, {this.isHighlighted = false, super.key});
import "package:material_ui/material_ui.dart";
final class const HighlightWrapper(
final Widget child, {
final bool isHighlighted = false,
super.key,
}) extends StatelessWidget {
@override
Widget build(BuildContext context) => ClipRRect(
borderRadius: .all(.circular(12)),

View file

@ -1,12 +1,12 @@
import "dart:math";
import "package:flutter/material.dart";
class CodeBlock extends StatelessWidget {
final String code;
final String lang;
const CodeBlock(this.code, {required this.lang, super.key});
import "package:material_ui/material_ui.dart";
class const CodeBlock(
final String code, {
required final String lang,
super.key,
}) extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);

View file

@ -1,5 +1,5 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart";
import "package:nexus/helpers/extensions/link_to_mention.dart";
@ -11,12 +11,12 @@ import "package:nexus/widgets/html/spoiler_text.dart";
import "package:nexus/widgets/html/code_block.dart";
import "package:nexus/widgets/html/quoted.dart";
class Html extends ConsumerWidget {
final String html;
final String? roomId;
final TextStyle? textStyle;
const Html(this.html, {this.roomId, this.textStyle, super.key});
class const Html(
final String html, {
final String? roomId,
final TextStyle? textStyle,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) => HtmlWidget(
html,
@ -28,7 +28,7 @@ class Html extends ConsumerWidget {
}
if (element.attributes.keys.contains("data-mx-spoiler")) {
return InlineCustomWidget(child: SpoilerText(text: element.text));
return InlineCustomWidget(child: SpoilerText(element.text));
}
final height =

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/room_summary.dart";
import "package:nexus/controllers/user.dart";
@ -7,11 +7,8 @@ import "package:nexus/helpers/extensions/show_user_popover.dart";
import "package:nexus/models/content/membership.dart";
import "package:nexus/models/room_summary.dart";
class MentionChip extends ConsumerWidget {
final String? roomId;
final String content;
const MentionChip(this.content, this.roomId, {super.key});
class const MentionChip(final String content, final String? roomId, {super.key})
extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final mention = content.mention;

View file

@ -1,9 +1,6 @@
import "package:flutter/material.dart";
class Quoted extends StatelessWidget {
final Widget child;
const Quoted(this.child, {super.key});
import "package:material_ui/material_ui.dart";
class const Quoted(final Widget child, {super.key}) extends StatelessWidget {
@override
Widget build(BuildContext context) => Container(
decoration: BoxDecoration(

View file

@ -1,11 +1,7 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_hooks/flutter_hooks.dart";
class SpoilerText extends HookWidget {
final String text;
const SpoilerText({super.key, required this.text});
class const SpoilerText(final String text, {super.key}) extends HookWidget {
@override
Widget build(BuildContext context) {
final revealed = useState(false);

View file

@ -1,5 +1,5 @@
import "package:collection/collection.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/client.dart";
@ -7,10 +7,7 @@ import "package:nexus/controllers/key.dart";
import "package:nexus/controllers/spaces.dart";
import "package:nexus/helpers/extensions/link_to_mention.dart";
class JoinDialog extends HookWidget {
final WidgetRef ref;
const JoinDialog(this.ref, {super.key});
class const JoinDialog(final WidgetRef ref, {super.key}) extends HookWidget {
@override
Widget build(BuildContext context) {
final roomAlias = useTextEditingController();
@ -53,9 +50,8 @@ class JoinDialog extends HookWidget {
.new(
roomIdOrAlias: roomIdOrAlias,
via: .new(
Uri.tryParse(
roomAlias.text.replaceAll("/#", ""),
)?.queryParametersAll["via"] ??
Uri.tryParse(roomAlias.text.replaceAll("/#", ""))
?.queryParametersAll["via"] ??
[],
),
),
@ -76,9 +72,8 @@ class JoinDialog extends HookWidget {
await ref
.watch(
KeyController.provider(
KeyController.spaceKey,
).notifier,
KeyController.provider(KeyController.spaceKey)
.notifier,
)
.set(
space?.id ??
@ -100,9 +95,8 @@ class JoinDialog extends HookWidget {
if (space == null) {
await ref
.watch(
KeyController.provider(
KeyController.roomKey,
).notifier,
KeyController.provider(KeyController.roomKey)
.notifier,
)
.set(id);
}
@ -115,9 +109,9 @@ class JoinDialog extends HookWidget {
if (context.mounted) {
scaffoldMessenger.showSnackBar(
.new(
backgroundColor: Theme.of(
context,
).colorScheme.errorContainer,
backgroundColor: Theme.of(context)
.colorScheme
.errorContainer,
content: Text(
error.toString(),
style: .new(

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/author.dart";
import "package:nexus/helpers/extensions/get_localpart.dart";
@ -6,11 +6,11 @@ import "package:nexus/helpers/extensions/show_user_popover.dart";
import "package:nexus/models/event.dart";
import "package:nexus/widgets/avatar_or_hash.dart";
class MessageAvatar extends ConsumerWidget {
final Event event;
final double height;
const MessageAvatar(this.event, {this.height = 24, super.key});
class const MessageAvatar(
final Event event, {
final double height = 24,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) => switch (ref.watch(
AuthorController.provider(event),

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/author.dart";
import "package:nexus/helpers/extensions/get_localpart.dart";
@ -6,17 +6,12 @@ import "package:nexus/helpers/extensions/show_user_popover.dart";
import "package:nexus/helpers/extensions/string_to_color.dart";
import "package:nexus/models/event.dart";
class MessageDisplayname extends ConsumerWidget {
final Event event;
final TextStyle? style;
final bool clickable;
const MessageDisplayname(
this.event, {
this.clickable = true,
this.style,
super.key,
});
class const MessageDisplayname(
final Event event, {
final TextStyle? style,
final bool clickable = true,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) => switch (ref.watch(
AuthorController.provider(event),
@ -40,14 +35,11 @@ class MessageDisplayname extends ConsumerWidget {
maxLines: 1,
overflow: .ellipsis,
),
if (event.pmp != null)
Text(
"(via ${event.sender})",
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: event.sender.colorHash,
fontWeight: .bold,
),
style: Theme.of(context).textTheme.labelSmall
?.copyWith(color: event.sender.colorHash, fontWeight: .bold),
maxLines: 1,
overflow: .ellipsis,
),

View file

@ -1,14 +1,14 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_linkify/flutter_linkify.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/helpers/launch_helper.dart";
class LinkifiedText extends ConsumerWidget {
final String text;
final int? maxLines;
final TextStyle? style;
const LinkifiedText(this.text, {this.maxLines, this.style, super.key});
final class const LinkifiedText(
final String text, {
final int? maxLines,
final TextStyle? style,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) => Linkify(
text: text,

View file

@ -1,9 +1,6 @@
import "package:flutter/material.dart";
class Loading extends StatelessWidget {
final double? height;
const Loading({this.height, super.key});
import "package:material_ui/material_ui.dart";
class const Loading({super.key, final double? height}) extends StatelessWidget {
@override
Widget build(BuildContext context) => Center(
child: Padding(

View file

@ -1,5 +1,5 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:m3e_buttons/m3e_buttons.dart";
@ -16,10 +16,8 @@ import "package:nexus/widgets/error_dialog.dart";
import "package:nexus/widgets/loading.dart";
import "package:nexus/widgets/user_bottom_sheet.dart";
class MemberList extends HookConsumerWidget {
final String roomId;
const MemberList(this.roomId, {super.key});
class const MemberList(final String roomId, {super.key})
extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final statusIndex = useState(0);
@ -96,9 +94,9 @@ class MemberList extends HookConsumerWidget {
),
SliverM3ECardList(
padding: .all(4),
color: Theme.of(
context,
).colorScheme.surfaceContainerHigh,
color: Theme.of(context)
.colorScheme
.surfaceContainerHigh,
margin: .symmetric(horizontal: 12, vertical: 4),
itemCount: members.length,
itemBuilder: (context, index) =>

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_blurhash/flutter_blurhash.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/helpers/mxc_image.dart";
@ -7,12 +7,12 @@ import "package:nexus/models/requests/download_media.dart";
import "package:nexus/widgets/expandable_image.dart";
import "package:nexus/widgets/loading.dart";
class MessageImage extends ConsumerWidget {
final Uri url;
final i.ImageInfo? info;
final bool encrypted;
const MessageImage(this.url, {this.info, required this.encrypted, super.key});
final class const MessageImage(
final Uri url, {
final i.ImageInfo? info,
required final bool encrypted,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final request = DownloadMediaRequest(mxc: url, encrypted: encrypted);

View file

@ -1,5 +1,5 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/pinned_events.dart";
import "package:nexus/models/event.dart";
@ -7,17 +7,12 @@ import "package:nexus/widgets/error_dialog.dart";
import "package:nexus/widgets/loading.dart";
import "package:nexus/widgets/renderers/event.dart";
class PinnedEventsDrawer extends HookConsumerWidget {
final String roomId;
final IList<PopupMenuEntry> Function(Event event) getEventOptions;
final Future<void> Function(String eventId) jumpToId;
const PinnedEventsDrawer(
this.roomId, {
required this.getEventOptions,
required this.jumpToId,
super.key,
});
final class const PinnedEventsDrawer(
final String roomId, {
required final IList<PopupMenuEntry> Function(Event event) getEventOptions,
required final Future<void> Function(String eventId) jumpToId,
super.key,
}) extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final pinsProvider = ref.watch(PinnedEventsController.provider(roomId));

View file

@ -1,18 +1,18 @@
import "dart:async";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:media_kit/media_kit.dart";
import "package:nexus/controllers/client.dart";
import "package:nexus/models/info/audio.dart";
class AudioPlayer extends HookConsumerWidget {
final Uri uri;
final AudioInfo? info;
final bool encrypted;
const AudioPlayer(this.uri, this.info, {this.encrypted = false, super.key});
class const AudioPlayer(
final Uri uri,
final AudioInfo? info, {
final bool encrypted = false,
super.key,
}) extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final player = useMemoized(

View file

@ -1,5 +1,6 @@
import "dart:async";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/client.dart";
import "package:nexus/models/info/video.dart";
@ -7,12 +8,12 @@ import "package:flutter_hooks/flutter_hooks.dart";
import "package:media_kit/media_kit.dart";
import "package:media_kit_video/media_kit_video.dart";
class VideoPlayer extends HookConsumerWidget {
final VideoInfo? info;
final Uri uri;
final bool encrypted;
const VideoPlayer(this.uri, this.info, {this.encrypted = false, super.key});
class const VideoPlayer(
final Uri uri,
final VideoInfo? info, {
final bool encrypted = false,
super.key,
}) extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final player = useMemoized(

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client_state.dart";
@ -10,10 +10,7 @@ import "package:nexus/widgets/error_dialog.dart";
import "package:nexus/main.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart";
class ReactionRow extends ConsumerWidget {
final Event event;
const ReactionRow(this.event, {super.key});
class const ReactionRow(final Event event, {super.key}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final clientState = ref.watch(ClientStateController.provider);
@ -67,9 +64,8 @@ class ReactionRow extends ConsumerWidget {
enabled.value = false;
try {
final controller = ref.watch(
RoomChatController.provider(
event.roomId,
).notifier,
RoomChatController.provider(event.roomId)
.notifier,
);
if (selected) {

View file

@ -1,5 +1,5 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/helpers/extensions/show_context_menu.dart";
@ -25,23 +25,15 @@ import "package:nexus/widgets/reaction_row.dart";
import "package:nexus/widgets/renderers/membership.dart";
import "package:nexus/widgets/renderers/generic_event.dart";
class EventRenderer extends HookConsumerWidget {
final Event event;
final bool textOnly;
final bool isGrouped;
final int? maxLines;
final VoidCallback? onTapReply;
final IList<PopupMenuEntry> Function(Event event)? getEventOptions;
const EventRenderer(
this.event, {
this.onTapReply,
this.textOnly = false,
this.isGrouped = false,
this.maxLines,
this.getEventOptions,
super.key,
});
class const EventRenderer(
final Event event, {
final bool textOnly = false,
final bool isGrouped = false,
final int? maxLines,
final VoidCallback? onTapReply,
final IList<PopupMenuEntry> Function(Event event)? getEventOptions,
super.key,
}) extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context);
@ -202,9 +194,8 @@ class EventRenderer extends HookConsumerWidget {
onSecondaryTapUp: contextMenuCallback,
onLongPressStart: contextMenuCallback,
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 8,
).copyWith(top: isGrouped ? 0 : 8),
padding: EdgeInsets.symmetric(horizontal: 8)
.copyWith(top: isGrouped ? 0 : 8),
child: child,
),
),

View file

@ -1,10 +1,10 @@
import "package:flutter/material.dart";
class GenericEventRenderer extends StatelessWidget {
final IconData icon;
final List<Widget> children;
const GenericEventRenderer(this.icon, this.children, {super.key});
import "package:material_ui/material_ui.dart";
class const GenericEventRenderer(
final IconData icon,
final List<Widget> children, {
super.key,
}) extends StatelessWidget {
@override
Widget build(BuildContext context) => Padding(
padding: .symmetric(vertical: 4),

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.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";
@ -7,10 +7,8 @@ import "package:nexus/models/event.dart";
import "package:nexus/widgets/lazy_loading/message_displayname.dart";
import "package:nexus/widgets/renderers/generic_event.dart";
class MembershipRenderer extends StatelessWidget {
final Event event;
const MembershipRenderer(this.event, {super.key});
class const MembershipRenderer(final Event event, {super.key})
extends StatelessWidget {
@override
Widget build(BuildContext context) {
assert(

View file

@ -1,5 +1,5 @@
import "package:collection/collection.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:linkify/linkify.dart";
import "package:nexus/controllers/client_state.dart";
@ -21,21 +21,14 @@ import "package:nexus/widgets/event_preview.dart";
import "package:nexus/widgets/players/video.dart";
import "package:nexus/widgets/players/audio.dart";
class MessageRenderer extends ConsumerWidget {
final Event event;
final bool textOnly;
final bool isGrouped;
final int? maxLines;
final VoidCallback? onTapReply;
const MessageRenderer(
this.event, {
this.onTapReply,
this.textOnly = false,
this.isGrouped = false,
this.maxLines,
super.key,
});
class const MessageRenderer(
final Event event, {
final VoidCallback? onTapReply,
final bool textOnly = false,
final bool isGrouped = false,
final int? maxLines,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context);

View file

@ -1,4 +1,4 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/rooms.dart";
import "package:nexus/widgets/appbar.dart";
@ -7,21 +7,14 @@ import "package:nexus/widgets/expandable_image.dart";
import "package:nexus/widgets/linkified_text.dart";
import "package:nexus/widgets/room_menu.dart";
class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
final bool isDesktop;
final void Function(BuildContext context)? onOpenMemberList;
final void Function()? onOpenPinnedMessagesList;
final void Function() onOpenDrawer;
final String? roomId;
const RoomAppbar({
required this.roomId,
required this.isDesktop,
required this.onOpenDrawer,
this.onOpenMemberList,
this.onOpenPinnedMessagesList,
super.key,
});
final class const RoomAppbar({
required final String? roomId,
required final bool isDesktop,
required final void Function() onOpenDrawer,
final void Function(BuildContext context)? onOpenMemberList,
final void Function()? onOpenPinnedMessagesList,
super.key,
}) extends ConsumerWidget implements PreferredSizeWidget {
@override
Size get preferredSize => AppBar().preferredSize;
@ -67,9 +60,9 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
room.metadata?.name ?? "Unnamed Room",
overflow: .ellipsis,
maxLines: 3,
style: Theme.of(
context,
).textTheme.headlineSmall,
style: Theme.of(context)
.textTheme
.headlineSmall,
),
),
],
@ -79,9 +72,9 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
room.metadata!.topic!,
style: Theme.of(context).textTheme.bodyLarge
?.copyWith(
color: Theme.of(
context,
).colorScheme.onSurfaceVariant,
color: Theme.of(context)
.colorScheme
.onSurfaceVariant,
),
),
],

View file

@ -1,5 +1,5 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter/services.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
@ -28,17 +28,12 @@ import "package:nexus/main.dart";
import "package:nexus/widgets/loading.dart";
import "package:super_sliver_list/super_sliver_list.dart";
class RoomChat extends HookConsumerWidget {
final bool isDesktop;
final bool showMembersByDefault;
final String? roomId;
const RoomChat({
required this.roomId,
required this.isDesktop,
required this.showMembersByDefault,
super.key,
});
final class const RoomChat({
required final String? roomId,
required final bool isDesktop,
required final bool showMembersByDefault,
super.key,
}) extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final relatedEvent = useState<Event?>(null);
@ -127,9 +122,8 @@ class RoomChat extends HookConsumerWidget {
}, [scrollController.hasClients]);
useEffect(() {
if (controllerData case AsyncData(
:final value?,
) when scrollController.hasClients) {
if (controllerData case AsyncData(:final value?)
when scrollController.hasClients) {
if (topEventBeforeLoad.value != null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (scrollController.hasClients) {

View file

@ -1,16 +1,16 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter/services.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client.dart";
import "package:nexus/controllers/via.dart";
import "package:nexus/models/room.dart";
class RoomMenu extends ConsumerWidget {
final Room? room;
final IList<Room> children;
const RoomMenu(this.room, {this.children = const IList.empty(), super.key});
final class const RoomMenu(
final Room? room, {
final IList<Room> children = const IList.empty(),
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final danger = Theme.of(context).colorScheme.error;

View file

@ -1,28 +1,18 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/widgets/settings/radio_dialog.dart";
class DialogListTile<T> extends ConsumerWidget {
final T? initialValue;
final String title;
final Widget? subtitle;
final List<T> options;
final bool required;
final Icon icon;
final void Function(T value)? onChanged;
final String Function(T option) getName;
const DialogListTile({
super.key,
required this.icon,
required this.title,
required this.initialValue,
required this.options,
required this.onChanged,
required this.getName,
this.subtitle,
this.required = true,
});
final class const DialogListTile<T>({
required final T? initialValue,
required final Icon icon,
required final String title,
required final List<T> options,
required final void Function(T value)? onChanged,
required final String Function(T option) getName,
final Widget? subtitle,
final bool required = true,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) => FormField(
validator: (value) =>

View file

@ -1,21 +1,14 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_hooks/flutter_hooks.dart";
class RadioDialog<T> extends HookWidget {
final T? value;
final String title;
final List<T> options;
final void Function(T value)? onChanged;
final String Function(T option) getName;
const RadioDialog({
super.key,
required this.title,
required this.value,
required this.options,
required this.onChanged,
required this.getName,
});
final class const RadioDialog<T>({
required final T? value,
required final String title,
required final List<T> options,
required final void Function(T value)? onChanged,
required final String Function(T option) getName,
super.key,
}) extends HookWidget {
@override
Widget build(BuildContext context) {
final mutValue = useState<T?>(null);

View file

@ -1,6 +1,6 @@
import "package:collection/collection.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:navigation_rail_m3e/navigation_rail_m3e.dart";
import "package:nexus/controllers/key.dart";
@ -12,10 +12,8 @@ import "package:nexus/widgets/divider_widget.dart";
import "package:nexus/widgets/join_dialog.dart";
import "package:nexus/widgets/room_menu.dart";
class Sidebar extends HookConsumerWidget {
final bool isDesktop;
const Sidebar({required this.isDesktop, super.key});
class const Sidebar({required final bool isDesktop, super.key})
extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final selectedSpaceProvider = KeyController.provider(

View file

@ -1,14 +1,11 @@
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/url_preview.dart";
import "package:nexus/helpers/extensions/better_when.dart";
import "package:nexus/helpers/launch_helper.dart";
import "package:nexus/helpers/mxc_image.dart";
class UrlPreview extends ConsumerWidget {
final Uri link;
const UrlPreview(this.link, {super.key});
class const UrlPreview(final Uri link, {super.key}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) => ConstrainedBox(
constraints: .loose(.fromWidth(400)),
@ -21,9 +18,9 @@ class UrlPreview extends ConsumerWidget {
onTap: () => ref.watch(LaunchHelper.provider).launchUrl(link),
child: Card(
margin: .symmetric(vertical: 4),
color: Theme.of(
context,
).colorScheme.surfaceContainerHighest,
color: Theme.of(context)
.colorScheme
.surfaceContainerHighest,
child: Padding(
padding: .all(16),
child: Column(

View file

@ -1,5 +1,5 @@
import "package:collection/collection.dart";
import "package:flutter/material.dart";
import "package:material_ui/material_ui.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:intl/intl.dart";
@ -16,12 +16,12 @@ import "package:nexus/widgets/avatar_or_hash.dart";
import "package:nexus/main.dart";
import "package:nexus/widgets/expandable_image.dart";
class UserBottomSheet extends ConsumerWidget {
final MembershipContent member;
final String userId;
final String? roomId;
const UserBottomSheet(this.member, this.userId, {this.roomId, super.key});
final class const UserBottomSheet(
final MembershipContent member,
final String userId, {
final String? roomId,
super.key,
}) extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context);