fix message bubble alignment

This commit is contained in:
Henry Hiles 2026-07-14 20:17:00 -04:00
commit b48e9457b8
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
2 changed files with 88 additions and 84 deletions

View file

@ -21,93 +21,98 @@ class ReactionRow extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final clientState = ref.watch(ClientStateController.provider); final clientState = ref.watch(ClientStateController.provider);
return switch (ref.watch( return Padding(
ReactionsController.provider( padding: .only(top: 4),
.new(roomId: event.roomId, eventRowId: event.rowId), child: switch (ref.watch(
), ReactionsController.provider(
)) { .new(roomId: event.roomId, eventRowId: event.rowId),
AsyncData(value: final IMap<String, IList<String>>? reactors) || ),
AsyncLoading(value: final reactors) => Wrap( )) {
spacing: 4, AsyncData(value: final IMap<String, IList<String>>? reactors) ||
runSpacing: 4, AsyncLoading(value: final reactors) => Wrap(
children: event.reactions spacing: 4,
.where((_, value) => value != 0) runSpacing: 4,
.mapTo( children: event.reactions
(reaction, count) => HookBuilder( .where((_, value) => value != 0)
builder: (context) { .mapTo(
final enabled = useState(true); (reaction, count) => HookBuilder(
builder: (context) {
final enabled = useState(true);
final selected = final selected =
reactors?[reaction]?.contains(clientState!.userId) ?? reactors?[reaction]?.contains(clientState!.userId) ??
false; false;
return Tooltip( return Tooltip(
message: reactors?[reaction]?.join(", ") ?? "", message: reactors?[reaction]?.join(", ") ?? "",
child: ChoiceChip( child: ChoiceChip(
showCheckmark: false, showCheckmark: false,
selected: selected, selected: selected,
label: Row( label: Row(
mainAxisSize: .min, mainAxisSize: .min,
spacing: 8, spacing: 8,
children: [ children: [
Flexible( Flexible(
child: reaction.startsWith("mxc://") child: reaction.startsWith("mxc://")
? Image( ? Image(
height: 20, height: 20,
image: CachedNetworkImage( image: CachedNetworkImage(
headers: ref.headers, headers: ref.headers,
Uri.parse(reaction) Uri.parse(reaction)
.mxcToHttps( .mxcToHttps(
clientState!.homeserverUrl!, clientState!.homeserverUrl!,
) )
.toString(), .toString(),
ref.watch(CrossCacheController.provider), ref.watch(
), CrossCacheController.provider,
) ),
: Text(reaction, overflow: .ellipsis), ),
), )
Text(count.toString(), overflow: .ellipsis), : Text(reaction, overflow: .ellipsis),
], ),
), Text(count.toString(), overflow: .ellipsis),
onSelected: enabled.value ],
? (value) async { ),
enabled.value = false; onSelected: enabled.value
try { ? (value) async {
final controller = ref.watch( enabled.value = false;
RoomChatController.provider( try {
event.roomId, final controller = ref.watch(
).notifier, RoomChatController.provider(
); event.roomId,
).notifier,
);
if (selected) { if (selected) {
await controller await controller
.removeReaction( .removeReaction(
reaction, reaction,
event, event,
clientState!.userId!, clientState!.userId!,
) )
.onError(showError); .onError(showError);
} else { } else {
await controller await controller
.sendReaction(reaction, event) .sendReaction(reaction, event)
.onError(showError); .onError(showError);
}
} finally {
enabled.value = true;
} }
} finally {
enabled.value = true;
} }
} : null,
: null, ),
), );
); },
}, ),
), )
) .toList(),
.toList(), ),
),
AsyncError(:final error, :final stackTrace) => ErrorDialog( AsyncError(:final error, :final stackTrace) => ErrorDialog(
error, error,
stackTrace, stackTrace,
), ),
}; },
);
} }
} }

View file

@ -271,7 +271,6 @@ class MessageRenderer extends ConsumerWidget {
case final UrlElement link?) case final UrlElement link?)
UrlPreview(link.url), UrlPreview(link.url),
SizedBox(height: 4),
ReactionRow(event), ReactionRow(event),
], ],
], ],