allow sending emoji/stickers from emote packs

This commit is contained in:
Henry Hiles 2026-10-23 18:16:45 -04:00
commit 3754bc2feb
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
2 changed files with 701 additions and 74 deletions

View file

@ -18,6 +18,7 @@ import "package:nexus/models/content/message.dart";
import "package:nexus/models/event.dart";
import "package:nexus/models/relation_type.dart";
import "package:nexus/widgets/emoji_picker.dart";
import "package:nexus/widgets/mxc_emoji.dart";
import "package:nexus/main.dart";
extension BuildEventOptions on Event {
@ -97,6 +98,8 @@ extension BuildEventOptions on Event {
mainAxisAlignment: isDesktop ? .center : .spaceEvenly,
children: [
...{
// Custom emoji are sent without their shortcode, as only
// their mxc URL is recorded
...ref
.read(RecentEmojiController.provider)
.map((entry) => entry.emoji),
@ -109,10 +112,15 @@ extension BuildEventOptions on Event {
.take(isDesktop ? 3 : 5)
.map(
(emoji) => IconButton(
icon: Text(
emoji,
style: .new(fontSize: isDesktop ? null : 18),
),
icon: emoji.startsWith("mxc://")
? SizedBox.square(
dimension: isDesktop ? 18 : 24,
child: MxcEmoji(Uri.parse(emoji)),
)
: Text(
emoji,
style: .new(fontSize: isDesktop ? null : 18),
),
onPressed: () async {
Navigator.of(context).pop();
await ref
@ -134,12 +142,13 @@ extension BuildEventOptions on Event {
context.showAdaptiveSheet(
(context) => EmojiPicker(
roomId: roomId,
allowFreeText: true,
onSelection: (emoji) {
onSelection: (emoji, {shortcode}) {
Navigator.of(context).pop();
ref
.read(notifier)
.sendReaction(emoji, this)
.sendReaction(emoji, this, shortcode: shortcode)
.onError(showError);
},
),

View file

@ -0,0 +1,29 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:material_emoji_picker/material_emoji_picker.dart";
import "package:nexus/models/content/image_pack.dart";
import "package:nexus/models/image_pack.dart";
import "package:nexus/widgets/mxc_emoji.dart";
extension ImagePackEmoji on ImagePack {
EmojiCategory? get emojiCategory => _category(emoticons);
EmojiCategory? get stickerCategory => _category(stickers);
EmojiCategory? _category(IMap<String, PackImage> images) => images.isEmpty
? null
: .new(
icon: MxcEmoji(avatar ?? images.values.first.url),
name: name,
emojis: images
.mapTo(
(shortcode, image) => Emoji(
widget: MxcEmoji(image.url, label: shortcode),
value: image.url.toString(),
aliases: .new([shortcode]),
description: image.body ?? shortcode,
tags: const .empty(),
data: image,
),
)
.toIList(),
);
}