treewide: small refactors
This commit is contained in:
parent
9117663c48
commit
8d944831f5
10 changed files with 63 additions and 63 deletions
|
|
@ -41,7 +41,7 @@ extension BuildEventOptions on Event {
|
||||||
.read(PinnedIdsController.provider(roomId))
|
.read(PinnedIdsController.provider(roomId))
|
||||||
.contains(eventId);
|
.contains(eventId);
|
||||||
|
|
||||||
void showReasonDialog({
|
void showReasonSheet({
|
||||||
required String title,
|
required String title,
|
||||||
required String description,
|
required String description,
|
||||||
required String action,
|
required String action,
|
||||||
|
|
@ -235,7 +235,7 @@ extension BuildEventOptions on Event {
|
||||||
) &&
|
) &&
|
||||||
!eventId.isFake)
|
!eventId.isFake)
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () => showReasonDialog(
|
onTap: () => showReasonSheet(
|
||||||
title: "Delete Message",
|
title: "Delete Message",
|
||||||
description:
|
description:
|
||||||
"Are you sure you want to delete this message? "
|
"Are you sure you want to delete this message? "
|
||||||
|
|
@ -260,7 +260,7 @@ extension BuildEventOptions on Event {
|
||||||
),
|
),
|
||||||
|
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () => showReasonDialog(
|
onTap: () => showReasonSheet(
|
||||||
title: "Report",
|
title: "Report",
|
||||||
description:
|
description:
|
||||||
"Report this event to your server administrators, "
|
"Report this event to your server administrators, "
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
extension GetLocalpart on String {
|
extension GetLocalpart on String {
|
||||||
String get localpart => length > 1 ? substring(1).split(":").first : "?";
|
String get localpart => length > 1 ? substring(1).split(":").first : "?";
|
||||||
|
|
||||||
|
/// Whether this looks like a valid Matrix user ID, e.g. `@user:example.com`.
|
||||||
|
bool get isValidUserId => RegExp(r"^@[^:\s]+:[^\s]+$").hasMatch(this);
|
||||||
|
|
||||||
String? get serverName {
|
String? get serverName {
|
||||||
final index = indexOf(":");
|
final index = indexOf(":");
|
||||||
return index == -1 ? null : substring(index + 1);
|
return index == -1 ? null : substring(index + 1);
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import "package:m3e_card_list/m3e_card_list.dart";
|
||||||
import "package:nexus/helpers/launch_helper.dart";
|
import "package:nexus/helpers/launch_helper.dart";
|
||||||
import "package:package_info_plus/package_info_plus.dart";
|
import "package:package_info_plus/package_info_plus.dart";
|
||||||
|
|
||||||
extension ShowAboutDialog on BuildContext {
|
extension ShowAboutSheet on BuildContext {
|
||||||
Future<void> showAboutDialog(WidgetRef ref) async {
|
Future<void> showAboutSheet(WidgetRef ref) async {
|
||||||
final packageInfo = await PackageInfo.fromPlatform();
|
final packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
28
lib/helpers/extensions/show_error_snack_bar.dart
Normal file
28
lib/helpers/extensions/show_error_snack_bar.dart
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import "package:material_ui/material_ui.dart";
|
||||||
|
|
||||||
|
extension ShowErrorSnackBar on ScaffoldMessengerState {
|
||||||
|
/// Shows [message] in a snackbar styled as an error.
|
||||||
|
ScaffoldFeatureController<SnackBar, SnackBarClosedReason> showErrorSnackBar(
|
||||||
|
String message, {
|
||||||
|
({String label, VoidCallback onPressed})? action,
|
||||||
|
}) {
|
||||||
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
|
return showSnackBar(
|
||||||
|
.new(
|
||||||
|
backgroundColor: colorScheme.errorContainer,
|
||||||
|
content: Text(
|
||||||
|
message,
|
||||||
|
style: .new(color: colorScheme.onErrorContainer),
|
||||||
|
),
|
||||||
|
action: action == null
|
||||||
|
? null
|
||||||
|
: .new(
|
||||||
|
label: action.label,
|
||||||
|
onPressed: action.onPressed,
|
||||||
|
textColor: colorScheme.onErrorContainer,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import "package:material_ui/material_ui.dart";
|
import "package:material_ui/material_ui.dart";
|
||||||
|
import "package:nexus/helpers/extensions/show_error_snack_bar.dart";
|
||||||
|
|
||||||
extension WithProgressSnackbar on BuildContext {
|
extension WithProgressSnackbar on BuildContext {
|
||||||
/// Shows [progress] in a snackbar while [action] runs, and shows any error
|
/// Shows [progress] in a snackbar while [action] runs, and shows any error
|
||||||
|
|
@ -10,8 +11,6 @@ extension WithProgressSnackbar on BuildContext {
|
||||||
Future<T> Function() action,
|
Future<T> Function() action,
|
||||||
) async {
|
) async {
|
||||||
final messenger = ScaffoldMessenger.of(this);
|
final messenger = ScaffoldMessenger.of(this);
|
||||||
final colorScheme = Theme.of(this).colorScheme;
|
|
||||||
|
|
||||||
final snackbar = messenger.showSnackBar(
|
final snackbar = messenger.showSnackBar(
|
||||||
.new(content: Text(progress), duration: const .new(days: 1)),
|
.new(content: Text(progress), duration: const .new(days: 1)),
|
||||||
);
|
);
|
||||||
|
|
@ -19,15 +18,7 @@ extension WithProgressSnackbar on BuildContext {
|
||||||
try {
|
try {
|
||||||
return await action();
|
return await action();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
messenger.showSnackBar(
|
messenger.showErrorSnackBar(error.toString());
|
||||||
.new(
|
|
||||||
backgroundColor: colorScheme.errorContainer,
|
|
||||||
content: Text(
|
|
||||||
error.toString(),
|
|
||||||
style: .new(color: colorScheme.onErrorContainer),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||||
import "package:nexus/controllers/auth_url.dart";
|
import "package:nexus/controllers/auth_url.dart";
|
||||||
import "package:nexus/controllers/client.dart";
|
import "package:nexus/controllers/client.dart";
|
||||||
import "package:nexus/controllers/client_id.dart";
|
import "package:nexus/controllers/client_id.dart";
|
||||||
|
import "package:nexus/helpers/extensions/show_error_snack_bar.dart";
|
||||||
import "package:nexus/helpers/launch_helper.dart";
|
import "package:nexus/helpers/launch_helper.dart";
|
||||||
import "package:nexus/main.dart";
|
import "package:nexus/main.dart";
|
||||||
import "package:nexus/models/gomuks_exception.dart";
|
import "package:nexus/models/gomuks_exception.dart";
|
||||||
|
|
@ -27,14 +28,8 @@ class const SelectServerPage({super.key}) extends HookConsumerWidget {
|
||||||
|
|
||||||
Future<void> setHomeserver(Uri? newHomeserver) async {
|
Future<void> setHomeserver(Uri? newHomeserver) async {
|
||||||
if (newHomeserver == null) {
|
if (newHomeserver == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showErrorSnackBar(
|
||||||
SnackBar(
|
|
||||||
content: Text(
|
|
||||||
"Failed to parse homeserver URL. Are you sure you typed it correctly?",
|
"Failed to parse homeserver URL. Are you sure you typed it correctly?",
|
||||||
style: .new(color: theme.colorScheme.onErrorContainer),
|
|
||||||
),
|
|
||||||
backgroundColor: theme.colorScheme.errorContainer,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
|
@ -58,14 +53,8 @@ class const SelectServerPage({super.key}) extends HookConsumerWidget {
|
||||||
} on GomuksException catch (error) {
|
} on GomuksException catch (error) {
|
||||||
if (error.errorCode != "M_UNRECOGNIZED") rethrow;
|
if (error.errorCode != "M_UNRECOGNIZED") rethrow;
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showErrorSnackBar(
|
||||||
SnackBar(
|
|
||||||
content: Text(
|
|
||||||
"${url.host} doesn't support OAuth login, which Nexus requires. Try a different homeserver, or ask your homeserver's admin to enable OAuth.",
|
"${url.host} doesn't support OAuth login, which Nexus requires. Try a different homeserver, or ask your homeserver's admin to enable OAuth.",
|
||||||
style: .new(color: theme.colorScheme.onErrorContainer),
|
|
||||||
),
|
|
||||||
backgroundColor: theme.colorScheme.errorContainer,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -109,18 +98,11 @@ class const SelectServerPage({super.key}) extends HookConsumerWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newUrl == null) {
|
if (newUrl == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showErrorSnackBar(
|
||||||
SnackBar(
|
|
||||||
content: Text(
|
|
||||||
"Homeserver verification failed.",
|
"Homeserver verification failed.",
|
||||||
style: .new(color: theme.colorScheme.onErrorContainer),
|
action: (
|
||||||
),
|
|
||||||
action: SnackBarAction(
|
|
||||||
onPressed: () => tryLogin(newHomeserver!).onError(showError),
|
|
||||||
label: "Attempt log in anyways",
|
label: "Attempt log in anyways",
|
||||||
textColor: theme.colorScheme.onErrorContainer,
|
onPressed: () => tryLogin(newHomeserver!).onError(showError),
|
||||||
),
|
|
||||||
backgroundColor: theme.colorScheme.errorContainer,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import "package:m3e_card_list/m3e_card_list.dart";
|
||||||
import "package:navigation_rail_m3e/navigation_rail_m3e.dart";
|
import "package:navigation_rail_m3e/navigation_rail_m3e.dart";
|
||||||
import "package:nexus/controllers/settings_sections.dart";
|
import "package:nexus/controllers/settings_sections.dart";
|
||||||
import "package:nexus/helpers/extensions/better_when.dart";
|
import "package:nexus/helpers/extensions/better_when.dart";
|
||||||
import "package:nexus/helpers/extensions/show_about_dialog.dart";
|
import "package:nexus/helpers/extensions/show_about_sheet.dart";
|
||||||
import "package:nexus/widgets/pages/settings_category.dart";
|
import "package:nexus/widgets/pages/settings_category.dart";
|
||||||
import "package:nexus/widgets/divider_text.dart";
|
import "package:nexus/widgets/divider_text.dart";
|
||||||
import "package:nexus/widgets/highlight_wrapper.dart";
|
import "package:nexus/widgets/highlight_wrapper.dart";
|
||||||
|
|
@ -106,7 +106,7 @@ class const SettingsPage({super.key}) extends ConsumerWidget {
|
||||||
actionsPadding: .symmetric(horizontal: 12),
|
actionsPadding: .symmetric(horizontal: 12),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => context.showAboutDialog(ref),
|
onPressed: () => context.showAboutSheet(ref),
|
||||||
icon: Icon(Icons.info_outline),
|
icon: Icon(Icons.info_outline),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:material_ui/material_ui.dart";
|
import "package:material_ui/material_ui.dart";
|
||||||
|
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||||
|
import "package:nexus/helpers/extensions/with_progress_snackbar.dart";
|
||||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||||
import "package:nexus/widgets/sheet_layout.dart";
|
import "package:nexus/widgets/sheet_layout.dart";
|
||||||
import "package:flutter/services.dart";
|
import "package:flutter/services.dart";
|
||||||
|
|
@ -58,7 +60,7 @@ final class const RoomMenuButton(
|
||||||
final userIdController = useTextEditingController();
|
final userIdController = useTextEditingController();
|
||||||
final reasonController = useTextEditingController();
|
final reasonController = useTextEditingController();
|
||||||
final text = useValueListenable(userIdController).text.trim();
|
final text = useValueListenable(userIdController).text.trim();
|
||||||
final valid = RegExp(r"^@[^:\s]+:[^\s]+$").hasMatch(text);
|
final valid = text.isValidUserId;
|
||||||
|
|
||||||
void submit() {
|
void submit() {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
|
|
@ -130,19 +132,12 @@ final class const RoomMenuButton(
|
||||||
child: Text("Cancel"),
|
child: Text("Cancel"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
context.withProgressSnackbar(
|
||||||
final snackbar = ScaffoldMessenger.of(context)
|
"Leaving room...",
|
||||||
.showSnackBar(
|
() => client.leaveRoom(room!.metadata!.id),
|
||||||
.new(
|
|
||||||
content: Text("Leaving room..."),
|
|
||||||
duration: Duration(days: 1),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
await client
|
Navigator.of(context).pop();
|
||||||
.leaveRoom(room!.metadata!.id)
|
|
||||||
.onError(showError)
|
|
||||||
.whenComplete(snackbar.close);
|
|
||||||
},
|
},
|
||||||
child: Text("Leave"),
|
child: Text("Leave"),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import "package:flutter_hooks/flutter_hooks.dart";
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
import "package:material_ui/material_ui.dart";
|
import "package:material_ui/material_ui.dart";
|
||||||
|
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||||
import "package:nexus/helpers/extensions/create_room.dart";
|
import "package:nexus/helpers/extensions/create_room.dart";
|
||||||
import "package:nexus/widgets/sheet_layout.dart";
|
import "package:nexus/widgets/sheet_layout.dart";
|
||||||
|
|
||||||
|
|
@ -12,7 +13,7 @@ class const StartDmSheet({final String? userId, final String? name, super.key})
|
||||||
final userIdController = useTextEditingController();
|
final userIdController = useTextEditingController();
|
||||||
final text = useValueListenable(userIdController).text.trim();
|
final text = useValueListenable(userIdController).text.trim();
|
||||||
final target = userId ?? text;
|
final target = userId ?? text;
|
||||||
final valid = RegExp(r"^@[^:\s]+:[^\s]+$").hasMatch(target);
|
final valid = target.isValidUserId;
|
||||||
final encrypted = useState(true);
|
final encrypted = useState(true);
|
||||||
final reasonController = useTextEditingController();
|
final reasonController = useTextEditingController();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ final class const UserBottomSheet(
|
||||||
);
|
);
|
||||||
final client = ref.read(ClientController.provider.notifier);
|
final client = ref.read(ClientController.provider.notifier);
|
||||||
|
|
||||||
void showMembershipDialog(MembershipAction action) =>
|
void showMembershipSheet(MembershipAction action) =>
|
||||||
context.showAdaptiveSheet(
|
context.showAdaptiveSheet(
|
||||||
(context) => HookBuilder(
|
(context) => HookBuilder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
|
|
@ -229,7 +229,7 @@ final class const UserBottomSheet(
|
||||||
children: [
|
children: [
|
||||||
if (member.status == .join || member.status == .invite)
|
if (member.status == .join || member.status == .invite)
|
||||||
M3EButton.icon(
|
M3EButton.icon(
|
||||||
onPressed: () => showMembershipDialog(.kick),
|
onPressed: () => showMembershipSheet(.kick),
|
||||||
shape: .square,
|
shape: .square,
|
||||||
icon: Icon(Icons.sports_martial_arts),
|
icon: Icon(Icons.sports_martial_arts),
|
||||||
label: Text("Kick"),
|
label: Text("Kick"),
|
||||||
|
|
@ -244,7 +244,7 @@ final class const UserBottomSheet(
|
||||||
),
|
),
|
||||||
|
|
||||||
M3EButton.icon(
|
M3EButton.icon(
|
||||||
onPressed: () => showMembershipDialog(.ban),
|
onPressed: () => showMembershipSheet(.ban),
|
||||||
shape: .square,
|
shape: .square,
|
||||||
icon: Icon(Icons.gavel),
|
icon: Icon(Icons.gavel),
|
||||||
label: Text("Ban"),
|
label: Text("Ban"),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue