mass migrate to adaptive sheets
This commit is contained in:
parent
ba258c2fcd
commit
9117663c48
13 changed files with 292 additions and 289 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/widgets/sheet_layout.dart";
|
||||
import "package:flutter/services.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
|
|
@ -46,27 +47,13 @@ extension BuildEventOptions on Event {
|
|||
required String action,
|
||||
required Future<void> Function(String reason) onConfirm,
|
||||
}) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => HookBuilder(
|
||||
context.showAdaptiveSheet(
|
||||
(context) => HookBuilder(
|
||||
builder: (context) {
|
||||
final reasonController = useTextEditingController();
|
||||
|
||||
return AlertDialog(
|
||||
return SheetLayout(
|
||||
title: Text(title),
|
||||
content: Column(
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Text(description),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: reasonController,
|
||||
textCapitalization: .sentences,
|
||||
decoration: .new(labelText: "Reason (optional)"),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Navigator.of(context).pop,
|
||||
|
|
@ -82,6 +69,14 @@ extension BuildEventOptions on Event {
|
|||
child: Text(action),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
Text(description),
|
||||
TextField(
|
||||
controller: reasonController,
|
||||
textCapitalization: .sentences,
|
||||
decoration: .new(labelText: "Reason (optional)"),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||
import "package:nexus/widgets/sheet_layout.dart";
|
||||
import "package:flutter_svg/flutter_svg.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:m3e_card_list/m3e_card_list.dart";
|
||||
|
|
@ -10,64 +12,8 @@ extension ShowAboutDialog on BuildContext {
|
|||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
|
||||
if (mounted) {
|
||||
showDialog(
|
||||
context: this,
|
||||
builder: (context) => AlertDialog(
|
||||
content: Column(
|
||||
mainAxisSize: .min,
|
||||
spacing: 16,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 12,
|
||||
children: [
|
||||
SvgPicture.asset("assets/bundled/icon.svg", width: 64),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: .center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
"Nexus",
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
Text(
|
||||
"(${packageInfo.version}+${const String.fromEnvironment("GIT_COMMIT", defaultValue: "dev")})",
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
"A simple and user-friendly Matrix client",
|
||||
overflow: .ellipsis,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
M3ECardColumn(
|
||||
onTap: (index) =>
|
||||
ref.read(LaunchHelper.provider).launchUrl(switch (index) {
|
||||
0 => .https("git.federated.nexus", "nexus/nexus"),
|
||||
_ => .https("liberapay.com", "QuadRadical"),
|
||||
}),
|
||||
children: [
|
||||
ListTile(
|
||||
leading: Icon(Icons.commit),
|
||||
title: Text("Source Code"),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.favorite, color: Colors.pinkAccent),
|
||||
title: Text("Donate"),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
showAdaptiveSheet(
|
||||
(context) => SheetLayout(
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => showLicensePage(context: context),
|
||||
|
|
@ -78,6 +24,65 @@ extension ShowAboutDialog on BuildContext {
|
|||
child: Text("Close"),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: .min,
|
||||
spacing: 16,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 12,
|
||||
children: [
|
||||
SvgPicture.asset("assets/bundled/icon.svg", width: 64),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: .center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
"Nexus",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.headlineMedium,
|
||||
),
|
||||
Text(
|
||||
"(${packageInfo.version}+${const String.fromEnvironment("GIT_COMMIT", defaultValue: "dev")})",
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
"A simple and user-friendly Matrix client",
|
||||
overflow: .ellipsis,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
M3ECardColumn(
|
||||
onTap: (index) =>
|
||||
ref.read(LaunchHelper.provider).launchUrl(switch (index) {
|
||||
0 => .https("git.federated.nexus", "nexus/nexus"),
|
||||
_ => .https("liberapay.com", "QuadRadical"),
|
||||
}),
|
||||
children: [
|
||||
ListTile(
|
||||
leading: Icon(Icons.commit),
|
||||
title: Text("Source Code"),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.favorite, color: Colors.pinkAccent),
|
||||
title: Text("Donate"),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/event.dart";
|
||||
import "package:nexus/controllers/room_summary.dart";
|
||||
|
|
@ -8,7 +9,7 @@ import "package:nexus/helpers/extensions/get_link_info.dart";
|
|||
import "package:nexus/helpers/extensions/show_user_popover.dart";
|
||||
import "package:nexus/models/content/membership.dart";
|
||||
import "package:nexus/models/room_summary.dart";
|
||||
import "package:nexus/widgets/room_summary_dialog.dart";
|
||||
import "package:nexus/widgets/room_summary_sheet.dart";
|
||||
|
||||
class const MentionChip(final String content, final String? roomId, {super.key})
|
||||
extends ConsumerWidget {
|
||||
|
|
@ -58,10 +59,9 @@ class const MentionChip(final String content, final String? roomId, {super.key})
|
|||
|
||||
if (!await ref.focusRoom(summary.roomId, eventRowId) &&
|
||||
context.mounted) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => Consumer(
|
||||
builder: (context, ref, _) => RoomSummaryDialog(
|
||||
context.showAdaptiveSheet(
|
||||
(context) => Consumer(
|
||||
builder: (context, ref, _) => RoomSummarySheet(
|
||||
ref
|
||||
.watch(
|
||||
RoomSummaryController.provider(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||
import "package:nexus/widgets/sheet_layout.dart";
|
||||
import "package:nexus/controllers/invites.dart";
|
||||
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||
import "package:nexus/main.dart";
|
||||
|
|
@ -8,7 +10,7 @@ import "package:nexus/models/content/create.dart";
|
|||
import "package:nexus/models/nav_page.dart";
|
||||
import "package:nexus/models/room_summary.dart";
|
||||
import "package:nexus/widgets/avatar_or_hash.dart";
|
||||
import "package:nexus/widgets/room_summary_dialog.dart";
|
||||
import "package:nexus/widgets/room_summary_sheet.dart";
|
||||
|
||||
class const InvitesList({super.key})
|
||||
extends HookConsumerWidget
|
||||
|
|
@ -33,13 +35,9 @@ class const InvitesList({super.key})
|
|||
final decliningAll = useState(false);
|
||||
|
||||
Future<void> declineAll() async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
final confirmed = await context.showAdaptiveSheet<bool>(
|
||||
(context) => SheetLayout(
|
||||
title: const Text("Decline All Invites"),
|
||||
content: Text(
|
||||
"Are you sure you want to decline all ${invites.length} invites?",
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
|
|
@ -50,6 +48,11 @@ class const InvitesList({super.key})
|
|||
child: const Text("Decline All"),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
Text(
|
||||
"Are you sure you want to decline all ${invites.length} invites?",
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (confirmed != true) return;
|
||||
|
|
@ -103,10 +106,7 @@ class const InviteCard(final RoomSummary invite, {super.key})
|
|||
return Card(
|
||||
clipBehavior: .antiAlias,
|
||||
child: ListTile(
|
||||
onTap: () => showDialog(
|
||||
context: context,
|
||||
builder: (_) => RoomSummaryDialog(invite),
|
||||
),
|
||||
onTap: () => context.showAdaptiveSheet((_) => RoomSummarySheet(invite)),
|
||||
leading: AvatarOrHash(
|
||||
invite.avatarUrl,
|
||||
name,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||
import "package:nexus/widgets/sheet_layout.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:nexus/controllers/room_summary.dart";
|
||||
import "package:nexus/helpers/extensions/get_link_info.dart";
|
||||
import "package:nexus/widgets/room_summary_dialog.dart";
|
||||
import "package:nexus/widgets/room_summary_sheet.dart";
|
||||
|
||||
class const JoinDialog(final WidgetRef ref, {super.key}) extends HookWidget {
|
||||
class const JoinSheet(final WidgetRef ref, {super.key}) extends HookWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final roomAlias = useTextEditingController();
|
||||
|
|
@ -17,16 +19,15 @@ class const JoinDialog(final WidgetRef ref, {super.key}) extends HookWidget {
|
|||
final via = linkInfo?.via ?? const .empty();
|
||||
final roomIdOrAlias = linkInfo?.identifier ?? roomAlias.text;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => Consumer(
|
||||
context.showAdaptiveSheet(
|
||||
(context) => Consumer(
|
||||
builder: (context, ref, _) => switch (ref.watch(
|
||||
RoomSummaryController.provider(
|
||||
.new(roomIdOrAlias: roomIdOrAlias, via: via),
|
||||
),
|
||||
)) {
|
||||
AsyncData(:final value) => RoomSummaryDialog(value, via: via),
|
||||
AsyncError _ || AsyncLoading _ => RoomSummaryDialog(
|
||||
AsyncData(:final value) => RoomSummarySheet(value, via: via),
|
||||
AsyncError _ || AsyncLoading _ => RoomSummarySheet(
|
||||
.new(roomId: roomIdOrAlias),
|
||||
via: via,
|
||||
),
|
||||
|
|
@ -35,25 +36,27 @@ class const JoinDialog(final WidgetRef ref, {super.key}) extends HookWidget {
|
|||
);
|
||||
}
|
||||
|
||||
return AlertDialog(
|
||||
return SheetLayout(
|
||||
title: Text("Join a Room"),
|
||||
content: Column(
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Text("Enter the room alias, Matrix URI, or Matrix.to link."),
|
||||
SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: roomAlias,
|
||||
decoration: .new(hintText: "#room:server.name"),
|
||||
onEditingComplete: onJoin,
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(onPressed: Navigator.of(context).pop, child: Text("Cancel")),
|
||||
TextButton(onPressed: onJoin, child: Text("Join")),
|
||||
],
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Text("Enter the room alias, Matrix URI, or Matrix.to link."),
|
||||
SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: roomAlias,
|
||||
decoration: .new(hintText: "#room:server.name"),
|
||||
onEditingComplete: onJoin,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/widgets/appbar.dart";
|
||||
import "package:nexus/widgets/avatar_or_hash.dart";
|
||||
import "package:nexus/widgets/count_badge.dart";
|
||||
import "package:nexus/widgets/room_menu_button.dart";
|
||||
import "package:nexus/widgets/room_summary_dialog.dart";
|
||||
import "package:nexus/widgets/room_summary_sheet.dart";
|
||||
import "package:nexus/widgets/sidebar.dart";
|
||||
|
||||
final class const RoomAppbar({
|
||||
|
|
@ -28,9 +29,8 @@ final class const RoomAppbar({
|
|||
return Appbar(
|
||||
onTap: room?.metadata == null
|
||||
? null
|
||||
: () => showDialog(
|
||||
context: context,
|
||||
builder: (context) => RoomSummaryDialog(
|
||||
: () => context.showAdaptiveSheet(
|
||||
(context) => RoomSummarySheet(
|
||||
.new(
|
||||
roomId: room!.metadata!.id,
|
||||
joinedMembers:
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import "package:nexus/widgets/start_dm_sheet.dart";
|
|||
import "package:nexus/widgets/divider_widget.dart";
|
||||
import "package:nexus/widgets/error_dialog.dart";
|
||||
import "package:nexus/widgets/pages/settings.dart";
|
||||
import "package:nexus/widgets/join_dialog.dart";
|
||||
import "package:nexus/widgets/join_sheet.dart";
|
||||
import "package:nexus/widgets/room_menu_button.dart";
|
||||
import "package:nexus/controllers/key.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
|
|
@ -157,10 +157,8 @@ class const SpacesRail({super.key}) extends ConsumerWidget {
|
|||
tooltip: "Add a room",
|
||||
itemBuilder: (_) => [
|
||||
PopupMenuItem(
|
||||
onTap: () => showDialog(
|
||||
context: context,
|
||||
builder: (_) => JoinDialog(ref),
|
||||
),
|
||||
onTap: () =>
|
||||
context.showAdaptiveSheet((_) => JoinSheet(ref)),
|
||||
child: const ListTile(
|
||||
title: Text("Join an existing room (or space)"),
|
||||
leading: Icon(Icons.numbers),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||
import "package:nexus/widgets/sheet_layout.dart";
|
||||
import "package:flutter/services.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
|
|
@ -50,9 +52,8 @@ final class const RoomMenuButton(
|
|||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
onTap: () => showDialog(
|
||||
context: context,
|
||||
builder: (context) => HookBuilder(
|
||||
onTap: () => context.showAdaptiveSheet(
|
||||
(context) => HookBuilder(
|
||||
builder: (context) {
|
||||
final userIdController = useTextEditingController();
|
||||
final reasonController = useTextEditingController();
|
||||
|
|
@ -75,35 +76,8 @@ final class const RoomMenuButton(
|
|||
.onError(showError);
|
||||
}
|
||||
|
||||
return AlertDialog(
|
||||
return SheetLayout(
|
||||
title: Text("Invite User"),
|
||||
content: Column(
|
||||
mainAxisSize: .min,
|
||||
spacing: 12,
|
||||
children: [
|
||||
TextField(
|
||||
controller: userIdController,
|
||||
autofocus: true,
|
||||
keyboardType: .emailAddress,
|
||||
onSubmitted: (_) => submit(),
|
||||
decoration: .new(
|
||||
labelText: "User ID",
|
||||
hintText: "@user:example.com",
|
||||
errorText: text.isEmpty || valid
|
||||
? null
|
||||
: "Enter a valid user ID",
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
controller: reasonController,
|
||||
textCapitalization: .sentences,
|
||||
onSubmitted: (_) => submit(),
|
||||
decoration: const .new(
|
||||
labelText: "Invite reason (optional)",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Navigator.of(context).pop,
|
||||
|
|
@ -114,6 +88,29 @@ final class const RoomMenuButton(
|
|||
child: Text("Invite"),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
TextField(
|
||||
controller: userIdController,
|
||||
autofocus: true,
|
||||
keyboardType: .emailAddress,
|
||||
onSubmitted: (_) => submit(),
|
||||
decoration: .new(
|
||||
labelText: "User ID",
|
||||
hintText: "@user:example.com",
|
||||
errorText: text.isEmpty || valid
|
||||
? null
|
||||
: "Enter a valid user ID",
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
controller: reasonController,
|
||||
textCapitalization: .sentences,
|
||||
onSubmitted: (_) => submit(),
|
||||
decoration: const .new(
|
||||
labelText: "Invite reason (optional)",
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
@ -124,13 +121,9 @@ final class const RoomMenuButton(
|
|||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
onTap: () => showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
onTap: () => context.showAdaptiveSheet(
|
||||
(context) => SheetLayout(
|
||||
title: Text("Leave Room"),
|
||||
content: Text(
|
||||
"Are you sure you want to leave \"${room!.metadata?.name ?? "Unnamed Room"}\"?",
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Navigator.of(context).pop,
|
||||
|
|
@ -154,6 +147,11 @@ final class const RoomMenuButton(
|
|||
child: Text("Leave"),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
Text(
|
||||
"Are you sure you want to leave \"${room!.metadata?.name ?? "Unnamed Room"}\"?",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: ListTile(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/widgets/sheet_layout.dart";
|
||||
import "package:nexus/controllers/invites.dart";
|
||||
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||
import "package:nexus/helpers/extensions/join_room.dart";
|
||||
|
|
@ -10,7 +11,7 @@ import "package:nexus/widgets/expandable_image.dart";
|
|||
import "package:nexus/widgets/linkified_text.dart";
|
||||
import "package:nexus/models/room_summary.dart";
|
||||
|
||||
class const RoomSummaryDialog(
|
||||
class const RoomSummarySheet(
|
||||
final RoomSummary summary, {
|
||||
final IList<String>? via,
|
||||
super.key,
|
||||
|
|
@ -21,10 +22,7 @@ class const RoomSummaryDialog(
|
|||
final isInvite = summary.membership == .invite;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return AlertDialog(
|
||||
constraints: .loose(.fromWidth(400)),
|
||||
scrollable: true,
|
||||
contentPadding: EdgeInsets.all(24).copyWith(top: 8),
|
||||
return SheetLayout(
|
||||
title: Row(
|
||||
spacing: 12,
|
||||
mainAxisSize: .min,
|
||||
|
|
@ -48,56 +46,6 @@ class const RoomSummaryDialog(
|
|||
),
|
||||
],
|
||||
),
|
||||
content: Column(
|
||||
children: [
|
||||
if (summary.invitedBy case final invitedBy?)
|
||||
ListTile(
|
||||
leading: AvatarOrHash(
|
||||
summary.inviterProfile?.avatarUrl,
|
||||
summary.inviterProfile?.displayName ?? invitedBy.localpart,
|
||||
),
|
||||
title: Text(
|
||||
"${summary.isDirect ? "Direct message from" : "Invited by"} ${summary.inviterProfile?.displayName ?? invitedBy.localpart}",
|
||||
),
|
||||
subtitle: SelectableText(invitedBy),
|
||||
),
|
||||
if (summary.inviteReason case final reason?)
|
||||
ListTile(
|
||||
titleAlignment: ListTileTitleAlignment.titleHeight,
|
||||
leading: const Icon(Icons.format_quote),
|
||||
title: const Text("Invite reason"),
|
||||
subtitle: SelectableText(reason),
|
||||
),
|
||||
// Invite state never includes the member count
|
||||
if (summary.joinedMembers != null || !isInvite)
|
||||
ListTile(
|
||||
title: Text(
|
||||
"${summary.joinedMembers ?? "Unknown number of"} members",
|
||||
),
|
||||
leading: Icon(Icons.people),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
summary.canonicalAlias == null ? "Room ID" : "Canonical Alias",
|
||||
),
|
||||
subtitle: SelectableText(summary.canonicalAlias ?? summary.roomId),
|
||||
leading: Icon(Icons.numbers),
|
||||
),
|
||||
if (summary.topic != null)
|
||||
ListTile(
|
||||
title: Text("Topic"),
|
||||
subtitle: LinkifiedText(summary.topic!),
|
||||
leading: Icon(Icons.info),
|
||||
),
|
||||
if (summary.encryption != null)
|
||||
ListTile(title: Text("Encrypted"), leading: Icon(Icons.lock)),
|
||||
if (summary.worldReadable == true)
|
||||
ListTile(
|
||||
title: Text("Anyone can read room history"),
|
||||
leading: Icon(Icons.public),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(onPressed: Navigator.of(context).pop, child: Text("Cancel")),
|
||||
if (isInvite) ...[
|
||||
|
|
@ -146,6 +94,60 @@ class const RoomSummaryDialog(
|
|||
child: Text("Join"),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
if (summary.invitedBy case final invitedBy?)
|
||||
ListTile(
|
||||
leading: AvatarOrHash(
|
||||
summary.inviterProfile?.avatarUrl,
|
||||
summary.inviterProfile?.displayName ?? invitedBy.localpart,
|
||||
),
|
||||
title: Text(
|
||||
"${summary.isDirect ? "Direct message from" : "Invited by"} ${summary.inviterProfile?.displayName ?? invitedBy.localpart}",
|
||||
),
|
||||
subtitle: SelectableText(invitedBy),
|
||||
),
|
||||
if (summary.inviteReason case final reason?)
|
||||
ListTile(
|
||||
titleAlignment: ListTileTitleAlignment.titleHeight,
|
||||
leading: const Icon(Icons.format_quote),
|
||||
title: const Text("Invite reason"),
|
||||
subtitle: SelectableText(reason),
|
||||
),
|
||||
// Invite state never includes the member count
|
||||
if (summary.joinedMembers != null || !isInvite)
|
||||
ListTile(
|
||||
title: Text(
|
||||
"${summary.joinedMembers ?? "Unknown number of"} members",
|
||||
),
|
||||
leading: Icon(Icons.people),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
summary.canonicalAlias == null ? "Room ID" : "Canonical Alias",
|
||||
),
|
||||
subtitle: SelectableText(
|
||||
summary.canonicalAlias ?? summary.roomId,
|
||||
),
|
||||
leading: Icon(Icons.numbers),
|
||||
),
|
||||
if (summary.topic != null)
|
||||
ListTile(
|
||||
title: Text("Topic"),
|
||||
subtitle: LinkifiedText(summary.topic!),
|
||||
leading: Icon(Icons.info),
|
||||
),
|
||||
if (summary.encryption != null)
|
||||
ListTile(title: Text("Encrypted"), leading: Icon(Icons.lock)),
|
||||
if (summary.worldReadable == true)
|
||||
ListTile(
|
||||
title: Text("Anyone can read room history"),
|
||||
leading: Icon(Icons.public),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/widgets/settings/radio_dialog.dart";
|
||||
import "package:nexus/widgets/settings/radio_sheet.dart";
|
||||
|
||||
final class const DialogListTile<T>({
|
||||
required final T? initialValue,
|
||||
|
|
@ -26,9 +27,8 @@ final class const DialogListTile<T>({
|
|||
),
|
||||
child: ListTile(
|
||||
enabled: onChanged != null,
|
||||
onTap: () => showDialog(
|
||||
context: context,
|
||||
builder: (context) => RadioDialog<T>(
|
||||
onTap: () => context.showAdaptiveSheet(
|
||||
(context) => RadioSheet<T>(
|
||||
title: title,
|
||||
getName: getName,
|
||||
onChanged: onChanged == null
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/widgets/sheet_layout.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
|
||||
final class const RadioDialog<T>({
|
||||
final class const RadioSheet<T>({
|
||||
required final T? value,
|
||||
required final String title,
|
||||
required final List<T> options,
|
||||
|
|
@ -12,26 +13,8 @@ final class const RadioDialog<T>({
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mutValue = useState<T?>(null);
|
||||
return AlertDialog(
|
||||
return SheetLayout(
|
||||
title: Text(title),
|
||||
content: RadioGroup<T>(
|
||||
groupValue: mutValue.value ?? value,
|
||||
onChanged: (value) => mutValue.value = value ?? mutValue.value,
|
||||
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: options
|
||||
.map(
|
||||
(option) => RadioListTile<T>(
|
||||
enabled: onChanged != null,
|
||||
value: option,
|
||||
title: Text(getName(option)),
|
||||
dense: true,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(onPressed: Navigator.of(context).pop, child: Text("Cancel")),
|
||||
if (onChanged != null)
|
||||
|
|
@ -43,6 +26,26 @@ final class const RadioDialog<T>({
|
|||
child: Text("OK"),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
RadioGroup<T>(
|
||||
groupValue: mutValue.value ?? value,
|
||||
onChanged: (value) => mutValue.value = value ?? mutValue.value,
|
||||
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: options
|
||||
.map(
|
||||
(option) => RadioListTile<T>(
|
||||
enabled: onChanged != null,
|
||||
value: option,
|
||||
title: Text(getName(option)),
|
||||
dense: true,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import "package:material_ui/material_ui.dart";
|
||||
|
||||
class const SheetLayout({
|
||||
required final Widget title,
|
||||
final Widget? title,
|
||||
required final List<Widget> children,
|
||||
required final List<Widget> actions,
|
||||
super.key,
|
||||
|
|
@ -16,10 +16,11 @@ class const SheetLayout({
|
|||
crossAxisAlignment: .stretch,
|
||||
spacing: 12,
|
||||
children: [
|
||||
DefaultTextStyle(
|
||||
style: Theme.of(context).textTheme.headlineSmall!,
|
||||
child: title,
|
||||
),
|
||||
if (title case final title?)
|
||||
DefaultTextStyle(
|
||||
style: Theme.of(context).textTheme.headlineSmall!,
|
||||
child: title,
|
||||
),
|
||||
...children,
|
||||
Row(mainAxisAlignment: .end, spacing: 8, children: actions),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import "package:collection/collection.dart";
|
||||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/widgets/sheet_layout.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:intl/intl.dart";
|
||||
|
|
@ -35,54 +36,51 @@ final class const UserBottomSheet(
|
|||
);
|
||||
final client = ref.read(ClientController.provider.notifier);
|
||||
|
||||
void showMembershipDialog(MembershipAction action) => showDialog(
|
||||
context: context,
|
||||
builder: (context) => HookBuilder(
|
||||
builder: (context) {
|
||||
final actionReasonController = useTextEditingController();
|
||||
return AlertDialog(
|
||||
title: Text("${toBeginningOfSentenceCase(action.name)} $userId"),
|
||||
content: Column(
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Text("Are you sure you want to ${action.name} $userId?"),
|
||||
SizedBox(height: 12),
|
||||
TextField(
|
||||
textCapitalization: .sentences,
|
||||
controller: actionReasonController,
|
||||
decoration: .new(
|
||||
labelText: "Reason for ${action.name} (optional)",
|
||||
),
|
||||
void showMembershipDialog(MembershipAction action) =>
|
||||
context.showAdaptiveSheet(
|
||||
(context) => HookBuilder(
|
||||
builder: (context) {
|
||||
final actionReasonController = useTextEditingController();
|
||||
return SheetLayout(
|
||||
title: Text(
|
||||
"${toBeginningOfSentenceCase(action.name)} $userId",
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Navigator.of(context).pop,
|
||||
child: Text("Cancel"),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
client
|
||||
.setMembership(
|
||||
.new(
|
||||
userId: userId,
|
||||
roomId: roomId!,
|
||||
action: action,
|
||||
reason: actionReasonController.text,
|
||||
),
|
||||
)
|
||||
.onError(showError);
|
||||
},
|
||||
child: Text(toBeginningOfSentenceCase(action.name)),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Navigator.of(context).pop,
|
||||
child: Text("Cancel"),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
client
|
||||
.setMembership(
|
||||
.new(
|
||||
userId: userId,
|
||||
roomId: roomId!,
|
||||
action: action,
|
||||
reason: actionReasonController.text,
|
||||
),
|
||||
)
|
||||
.onError(showError);
|
||||
},
|
||||
child: Text(toBeginningOfSentenceCase(action.name)),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
Text("Are you sure you want to ${action.name} $userId?"),
|
||||
TextField(
|
||||
textCapitalization: .sentences,
|
||||
controller: actionReasonController,
|
||||
decoration: .new(
|
||||
labelText: "Reason for ${action.name} (optional)",
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
|
|
|
|||
Loading…
Reference in a new issue