make user bottom sheet scrollable
This commit is contained in:
parent
ec30adc0e3
commit
a61cac130b
2 changed files with 148 additions and 156 deletions
|
|
@ -7,6 +7,7 @@ import "package:m3e_card_list/m3e_card_list.dart";
|
||||||
import "package:nexus/controllers/members_by_status.dart";
|
import "package:nexus/controllers/members_by_status.dart";
|
||||||
import "package:nexus/controllers/members_grouped.dart";
|
import "package:nexus/controllers/members_grouped.dart";
|
||||||
import "package:nexus/helpers/extensions/get_localpart.dart";
|
import "package:nexus/helpers/extensions/get_localpart.dart";
|
||||||
|
import "package:nexus/helpers/extensions/show_user_popover.dart";
|
||||||
import "package:nexus/helpers/extensions/string_to_color.dart";
|
import "package:nexus/helpers/extensions/string_to_color.dart";
|
||||||
import "package:nexus/models/content/membership.dart";
|
import "package:nexus/models/content/membership.dart";
|
||||||
import "package:nexus/models/membership_status.dart";
|
import "package:nexus/models/membership_status.dart";
|
||||||
|
|
@ -14,7 +15,6 @@ import "package:nexus/widgets/avatar_or_hash.dart";
|
||||||
import "package:nexus/widgets/divider_text.dart";
|
import "package:nexus/widgets/divider_text.dart";
|
||||||
import "package:nexus/widgets/error_dialog.dart";
|
import "package:nexus/widgets/error_dialog.dart";
|
||||||
import "package:nexus/widgets/loading.dart";
|
import "package:nexus/widgets/loading.dart";
|
||||||
import "package:nexus/widgets/user_bottom_sheet.dart";
|
|
||||||
|
|
||||||
class const MemberList(final String roomId, {super.key})
|
class const MemberList(final String roomId, {super.key})
|
||||||
extends HookConsumerWidget {
|
extends HookConsumerWidget {
|
||||||
|
|
@ -140,20 +140,10 @@ class const MemberList(final String roomId, {super.key})
|
||||||
final member = members[index];
|
final member = members[index];
|
||||||
if (member.content
|
if (member.content
|
||||||
case MembershipContent content) {
|
case MembershipContent content) {
|
||||||
showModalBottomSheet(
|
context.showUserPopover(
|
||||||
constraints: .loose(
|
content,
|
||||||
.new(
|
member.stateKey!,
|
||||||
500,
|
roomId: roomId,
|
||||||
(context.size?.height ?? 1000) - 80,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
isScrollControlled: true,
|
|
||||||
context: context,
|
|
||||||
builder: (context) => UserBottomSheet(
|
|
||||||
content,
|
|
||||||
member.stateKey!,
|
|
||||||
roomId: roomId,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -79,176 +79,178 @@ final class const UserBottomSheet(
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: .all(42),
|
padding: .all(42),
|
||||||
child: Column(
|
child: SingleChildScrollView(
|
||||||
spacing: 4,
|
child: Column(
|
||||||
mainAxisSize: .min,
|
spacing: 4,
|
||||||
crossAxisAlignment: .center,
|
mainAxisSize: .min,
|
||||||
children: [
|
crossAxisAlignment: .center,
|
||||||
Row(
|
children: [
|
||||||
mainAxisAlignment: .end,
|
|
||||||
children: [
|
|
||||||
M3EButton(
|
|
||||||
onPressed: Navigator.of(context).pop,
|
|
||||||
child: Icon(Icons.close),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 18),
|
|
||||||
|
|
||||||
ExpandableImage(
|
|
||||||
member.avatarUrl == null ? null : .new(mxc: member.avatarUrl!),
|
|
||||||
child: AvatarOrHash(
|
|
||||||
member.avatarUrl,
|
|
||||||
member.displayName ?? userId.localpart,
|
|
||||||
height: 200,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 8),
|
|
||||||
|
|
||||||
SelectableText(
|
|
||||||
member.displayName ?? userId.localpart,
|
|
||||||
style: textTheme.headlineLarge,
|
|
||||||
textAlign: .center,
|
|
||||||
),
|
|
||||||
SelectableText(
|
|
||||||
userId,
|
|
||||||
textAlign: .center,
|
|
||||||
style: textTheme.titleSmall?.copyWith(
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
ref
|
|
||||||
.watch(ProfileController.provider(userId))
|
|
||||||
.betterWhen(
|
|
||||||
loading: () => Text(""),
|
|
||||||
data: (profileResponse) => Column(
|
|
||||||
children: [
|
|
||||||
if (profileResponse.profile.timezone == null &&
|
|
||||||
profileResponse.profile.pronouns.isEmpty)
|
|
||||||
Text(""),
|
|
||||||
Wrap(
|
|
||||||
crossAxisAlignment: .center,
|
|
||||||
alignment: .center,
|
|
||||||
spacing: 4,
|
|
||||||
runSpacing: 4,
|
|
||||||
children: [
|
|
||||||
...profileResponse.profile.pronouns
|
|
||||||
.where(
|
|
||||||
// TODO: Check system language (l10n)
|
|
||||||
(pronoun) => pronoun.language == "en",
|
|
||||||
)
|
|
||||||
.mapIndexed(
|
|
||||||
(index, pronoun) => [
|
|
||||||
if (index != 0)
|
|
||||||
Icon(
|
|
||||||
Icons.circle,
|
|
||||||
size: 4,
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
pronoun.summary,
|
|
||||||
textAlign: .center,
|
|
||||||
style: textTheme.titleSmall?.copyWith(
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.flattened,
|
|
||||||
|
|
||||||
if (profileResponse.profile.timezone != null) ...[
|
|
||||||
if (profileResponse.profile.pronouns.isNotEmpty)
|
|
||||||
SizedBox(
|
|
||||||
height: 16,
|
|
||||||
child: VerticalDivider(
|
|
||||||
thickness: 1.5,
|
|
||||||
width: 4,
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
profileResponse.profile.timezone!,
|
|
||||||
textAlign: .center,
|
|
||||||
style: textTheme.titleSmall?.copyWith(
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 8),
|
|
||||||
if (userId != ref.watch(ClientStateController.provider)?.userId &&
|
|
||||||
roomId != null) ...[
|
|
||||||
Row(
|
Row(
|
||||||
|
mainAxisAlignment: .end,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
M3EButton(
|
||||||
child: M3EButton.icon(
|
onPressed: Navigator.of(context).pop,
|
||||||
onPressed: null,
|
child: Icon(Icons.close),
|
||||||
shape: .square,
|
|
||||||
style: .tonal,
|
|
||||||
icon: Icon(Icons.message),
|
|
||||||
label: Text("Message"),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
SizedBox(height: 18),
|
||||||
|
|
||||||
if (ref.watch(
|
ExpandableImage(
|
||||||
PowerLevelController.provider(
|
member.avatarUrl == null ? null : .new(mxc: member.avatarUrl!),
|
||||||
.membershipAction(
|
child: AvatarOrHash(
|
||||||
action: .kick,
|
member.avatarUrl,
|
||||||
roomId: roomId!,
|
member.displayName ?? userId.localpart,
|
||||||
targetUser: userId,
|
height: 200,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
))
|
),
|
||||||
Padding(
|
|
||||||
padding: .only(top: 4),
|
SizedBox(height: 8),
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
SelectableText(
|
||||||
spacing: 8,
|
member.displayName ?? userId.localpart,
|
||||||
children: [
|
style: textTheme.headlineLarge,
|
||||||
if (member.status == .join || member.status == .invite)
|
textAlign: .center,
|
||||||
|
),
|
||||||
|
SelectableText(
|
||||||
|
userId,
|
||||||
|
textAlign: .center,
|
||||||
|
style: textTheme.titleSmall?.copyWith(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
ref
|
||||||
|
.watch(ProfileController.provider(userId))
|
||||||
|
.betterWhen(
|
||||||
|
loading: () => Text(""),
|
||||||
|
data: (profileResponse) => Column(
|
||||||
|
children: [
|
||||||
|
if (profileResponse.profile.timezone == null &&
|
||||||
|
profileResponse.profile.pronouns.isEmpty)
|
||||||
|
Text(""),
|
||||||
|
Wrap(
|
||||||
|
crossAxisAlignment: .center,
|
||||||
|
alignment: .center,
|
||||||
|
spacing: 4,
|
||||||
|
runSpacing: 4,
|
||||||
|
children: [
|
||||||
|
...profileResponse.profile.pronouns
|
||||||
|
.where(
|
||||||
|
// TODO: Check system language (l10n)
|
||||||
|
(pronoun) => pronoun.language == "en",
|
||||||
|
)
|
||||||
|
.mapIndexed(
|
||||||
|
(index, pronoun) => [
|
||||||
|
if (index != 0)
|
||||||
|
Icon(
|
||||||
|
Icons.circle,
|
||||||
|
size: 4,
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
pronoun.summary,
|
||||||
|
textAlign: .center,
|
||||||
|
style: textTheme.titleSmall?.copyWith(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.flattened,
|
||||||
|
|
||||||
|
if (profileResponse.profile.timezone != null) ...[
|
||||||
|
if (profileResponse.profile.pronouns.isNotEmpty)
|
||||||
|
SizedBox(
|
||||||
|
height: 16,
|
||||||
|
child: VerticalDivider(
|
||||||
|
thickness: 1.5,
|
||||||
|
width: 4,
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
profileResponse.profile.timezone!,
|
||||||
|
textAlign: .center,
|
||||||
|
style: textTheme.titleSmall?.copyWith(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 8),
|
||||||
|
if (userId != ref.watch(ClientStateController.provider)?.userId &&
|
||||||
|
roomId != null) ...[
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: M3EButton.icon(
|
||||||
|
onPressed: null,
|
||||||
|
shape: .square,
|
||||||
|
style: .tonal,
|
||||||
|
icon: Icon(Icons.message),
|
||||||
|
label: Text("Message"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
if (ref.watch(
|
||||||
|
PowerLevelController.provider(
|
||||||
|
.membershipAction(
|
||||||
|
action: .kick,
|
||||||
|
roomId: roomId!,
|
||||||
|
targetUser: userId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
Padding(
|
||||||
|
padding: .only(top: 4),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
if (member.status == .join || member.status == .invite)
|
||||||
|
M3EButton.icon(
|
||||||
|
onPressed: () => showMembershipDialog(.kick),
|
||||||
|
shape: .square,
|
||||||
|
icon: Icon(Icons.sports_martial_arts),
|
||||||
|
label: Text("Kick"),
|
||||||
|
decoration: .new(
|
||||||
|
backgroundColor: WidgetStatePropertyAll(
|
||||||
|
theme.colorScheme.error,
|
||||||
|
),
|
||||||
|
foregroundColor: WidgetStatePropertyAll(
|
||||||
|
theme.colorScheme.onError,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
M3EButton.icon(
|
M3EButton.icon(
|
||||||
onPressed: () => showMembershipDialog(.kick),
|
onPressed: () => showMembershipDialog(.ban),
|
||||||
shape: .square,
|
shape: .square,
|
||||||
icon: Icon(Icons.sports_martial_arts),
|
icon: Icon(Icons.gavel),
|
||||||
label: Text("Kick"),
|
label: Text("Ban"),
|
||||||
decoration: .new(
|
decoration: .new(
|
||||||
backgroundColor: WidgetStatePropertyAll(
|
backgroundColor: WidgetStatePropertyAll(
|
||||||
theme.colorScheme.error,
|
theme.colorScheme.errorContainer,
|
||||||
),
|
),
|
||||||
foregroundColor: WidgetStatePropertyAll(
|
foregroundColor: WidgetStatePropertyAll(
|
||||||
theme.colorScheme.onError,
|
theme.colorScheme.onErrorContainer,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
].map((e) => Expanded(child: e)).toList(),
|
||||||
M3EButton.icon(
|
),
|
||||||
onPressed: () => showMembershipDialog(.ban),
|
|
||||||
shape: .square,
|
|
||||||
icon: Icon(Icons.gavel),
|
|
||||||
label: Text("Ban"),
|
|
||||||
decoration: .new(
|
|
||||||
backgroundColor: WidgetStatePropertyAll(
|
|
||||||
theme.colorScheme.errorContainer,
|
|
||||||
),
|
|
||||||
foregroundColor: WidgetStatePropertyAll(
|
|
||||||
theme.colorScheme.onErrorContainer,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
].map((e) => Expanded(child: e)).toList(),
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue