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:
Henry Hiles 2026-06-02 11:53:14 -04:00
commit d2ec5f035b
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
36 changed files with 391 additions and 534 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

Some files were not shown because too many files have changed in this diff Show more