make user sheets popovers on desktop

This commit is contained in:
Henry Hiles 2026-10-15 10:25:20 -04:00
commit ce5c7b972b
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
6 changed files with 122 additions and 44 deletions

View file

@ -104,36 +104,45 @@ class const MemberList(final String roomId, {super.key})
itemBuilder: (context, index) =>
switch (members[index].content) {
MembershipContent(
:final avatarUrl,
:final displayName,
) =>
ListTile(
title: Text(
displayName ??
members[index]
.stateKey!
.localpart,
overflow: .ellipsis,
style: .new(
color: members[index]
.stateKey!
.colorHash,
fontWeight: .bold,
),
),
subtitle: Text(
members[index].stateKey!,
overflow: .ellipsis,
),
leading: Transform.translate(
offset: .new(0, 2),
child: AvatarOrHash(
avatarUrl,
dimension: 40,
:final avatarUrl,
:final displayName,
) &&
final content =>
Builder(
builder: (context) => ListTile(
onTap: () =>
context.showUserPopover(
content,
members[index].stateKey!,
roomId: roomId,
),
title: Text(
displayName ??
members[index]
.stateKey!
.localpart,
overflow: .ellipsis,
style: .new(
color: members[index]
.stateKey!
.colorHash,
fontWeight: .bold,
),
),
subtitle: Text(
members[index].stateKey!,
overflow: .ellipsis,
),
leading: Transform.translate(
offset: .new(0, 2),
child: AvatarOrHash(
avatarUrl,
dimension: 40,
displayName ??
members[index]
.stateKey!
.localpart,
),
),
),
),
@ -141,17 +150,6 @@ class const MemberList(final String roomId, {super.key})
"Member content was not MembershipContent",
),
},
onTap: (index) {
final member = members[index];
if (member.content
case MembershipContent content) {
context.showUserPopover(
content,
member.stateKey!,
roomId: roomId,
);
}
},
),
];
}).toList(),

View file

@ -0,0 +1,33 @@
import "dart:math";
import "package:material_ui/material_ui.dart";
/// Positions a popover below [anchor], or above it if there isn't room below,
/// keeping it fully on screen.
class const PopoverLayout(final Rect anchor) extends SingleChildLayoutDelegate {
static const margin = 8.0;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) =>
constraints.loosen().deflate(const .all(margin));
@override
Offset getPositionForChild(Size size, Size childSize) {
final fitsBelow = anchor.bottom + childSize.height + margin <= size.height;
return .new(
anchor.left.clamp(
margin,
max(margin, size.width - childSize.width - margin),
),
(fitsBelow ? anchor.bottom : anchor.top - childSize.height).clamp(
margin,
max(margin, size.height - childSize.height - margin),
),
);
}
@override
bool shouldRelayout(PopoverLayout oldDelegate) =>
oldDelegate.anchor != anchor;
}