Skip to content

feat(messaging): emoji reactions with custom-emoji image resolution#111

Merged
krazyjakee merged 4 commits into
masterfrom
feat/message-reactions-emoji
Jun 11, 2026
Merged

feat(messaging): emoji reactions with custom-emoji image resolution#111
krazyjakee merged 4 commits into
masterfrom
feat/message-reactions-emoji

Conversation

@krazyjakee

Copy link
Copy Markdown
Contributor

Summary

  • Adds emoji reactions to message rows: reaction pills, a reaction picker button, and a "who reacted" dialog (_ReactButton, _ReactionPill, _ReactorsDialog).
  • Resolves custom-emoji reaction images from the space's emoji catalog by id (using the authoritative image_url), falling back to the bare CDN path, so animated/custom emoji render correctly. Unicode reactions render without an image.
  • Emoji management now prefers emoji.imageUrl and uses the gif/png format based on emoji.animated.
  • Fixes channel-mute detection in the channel context menu to read channel_id from the structured mutes list rather than stringifying whole entries.

Why

Reaction rendering previously used a bare CDN emoji URL that didn't account for custom/animated emoji or the space path segment, so custom reactions wouldn't display. This wires reactions through the space emoji catalog for correct images.

Notes for reviewers

  • flutter analyze --no-fatal-infos is clean on all four changed files.
  • _MuteButton is defined in accord_home_message_row.dart but appears unused — flagging in case it should be wired up or removed in a follow-up.

Test plan

  • React to a message with a unicode emoji — pill shows the glyph and count.
  • React with a custom/animated space emoji — pill shows the correct image.
  • Long-press / right-click a reaction pill — reactors dialog lists who reacted.
  • Mute a channel, reopen its context menu — mute state reflects correctly.

🤖 Generated with Claude Code

krazyjakee and others added 2 commits June 11, 2026 12:20
Adds reaction pills, a reaction picker, and a reactors dialog to message
rows, and resolves custom-emoji reaction images from the space's emoji
catalog (falling back to the bare CDN path) so animated/custom emoji
render correctly. Also fixes channel-mute detection to read channel_id
from the structured mutes list.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The reaction & mute work landed both in accord_home_message_row.dart and
in the dedicated part files (accord_home_mute_button.dart /
accord_home_reactions.dart) that refactor #108 had already extracted,
producing duplicate_definition compile errors. Remove the stale copies
from accord_home_message_row.dart and port the two bug fixes into the
canonical part files:

- mute-state read: parse channel_id out of the listMutes objects instead
  of stringifying the whole map (was always falsey, so muted state never
  showed).
- custom-emoji reactions: resolve the image URL from the space emoji
  catalog (image_url with space segment + real extension) rather than the
  bare AccordCDN.emoji(id) path, which 404'd.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@krazyjakee

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up commit (0f75d518) that makes this branch compile and adds two fixes:

Build fix — duplicate definitions. The reaction/mute widgets were defined both in accord_home_message_row.dart and in the dedicated part files (accord_home_mute_button.dart / accord_home_reactions.dart) that refactor #108 had already extracted, causing duplicate_definition errors (_MuteButton, _MuteButtonState, _NotifAction, _ReactButton, _ReactionPill, _ReactorsDialog). Removed the stale copies from accord_home_message_row.dart and ported the fixes into the canonical part files.

Bug fixes ported into the canonical files:

  • Mute state never reflected: listMutes returns objects {user_id, channel_id, created_at}, but the client stringified each whole map (e.toString()) instead of reading channel_id, so the muted check was always false. Now parses channel_id.
  • Custom-emoji reactions/management showed broken images: the client built <cdn>/emojis/<id>.png, but the server serves <cdn>/emojis/<space_id>/<id>.<ext>. Now uses the server-provided image_url (resolved via the space emoji catalog for reactions), matching the emoji picker / message-markup pattern.

flutter analyze --no-fatal-infos is clean and all 186 tests pass.

… add tests

The PR added _ReactButton, _ReactionPill, _ReactorsDialog, _MuteButton, and
_NotifAction to accord_home_message_row.dart, but identical/older definitions
of the first three already existed in accord_home_reactions.dart (same `part of`
library → compile-time duplicate class error).

- Move all reaction/notification widgets to accord_home_reactions.dart (their
  natural home); remove duplicates from accord_home_message_row.dart.
- Update _ReactionPill in accord_home_reactions.dart to use the new `imageUrl`
  parameter (was `cdnUrl`) matching the improved PR design.
- Extract _ReactorTile to eliminate the double accordAvatarUrl() call per user.
- Fix wrong docstring on _MuteButton (previously read "Opens the full emoji
  picker to add a reaction to the message").
- Remove redundant `final emojiUrl = imageUrl;` alias in _ReactionPill.build().
- Wrap long _reactionEmojiUrl line to stay within 80 cols.
- Add test/features/messaging/emoji_utils_test.dart covering parseEmojiToken,
  resolveEmojiGlyph, and the mute-list channel_id extraction logic.

https://claude.ai/code/session_01MVhELbGUNvFDcBX2MkRs8r

Copy link
Copy Markdown
Contributor Author

Review findings and fixes (commit 298bd3b)

Findings ranked by severity:


🔴 CRITICAL — Duplicate class definitions (compile error)

_ReactButton, _ReactionPill, and _ReactorsDialog were added to accord_home_message_row.dart by this PR, but identical/older definitions of all three already existed in accord_home_reactions.dart. Both files are part of 'accord_home.dart', so the same class name in two part files is a compile-time duplicate-definition error — the app would not build.

Fix: Moved all reaction/notification widgets to accord_home_reactions.dart (their natural home) and removed the duplicate definitions from accord_home_message_row.dart. The improved _ReactionPill with imageUrl (from this PR) replaced the old cdnUrl-based version in the reactions file.


🟠 HIGH — Wrong docstring on _MuteButton

The doc-comment on _MuteButton began with:

/// Opens the full emoji picker to add a reaction to the message.
/// A bell toggle in the channel header …

The first line describes _ReactButton, not _MuteButton — a stale line accidentally left from a copy-paste. Fixed by removing it.


🟡 MEDIUM — accord_home_message_row.dart over 1000 lines

After the PR the file reached 1234 lines. Resolved as a side-effect of fix #1 (moving the widgets to the reactions file brings it back to 837 lines).


🟡 MEDIUM — Double accordAvatarUrl() call per reactor

In _ReactorsDialogState.build(), accordAvatarUrl(user, cdnUrl) was called twice per user — once for the null check and once to get the actual value. Fixed by extracting a _ReactorTile widget that stores the URL in a local variable.


🟢 LOW — Redundant emojiUrl alias in _ReactionPill

final emojiUrl = imageUrl;  // pointless rename

emojiUrl was used in exactly the same way imageUrl would be. Fixed by removing the alias and using imageUrl! directly.


🟢 LOW — Line too long in _reactionEmojiUrl

final id = rawId ?? parseEmojiToken(reaction.emoji['name']?.toString() ?? '').id;

Wrapped to two lines to stay within 80 columns.


🔵 TEST COVERAGE — New test file added

test/features/messaging/emoji_utils_test.dart — covers:

  • parseEmojiToken: name/id splitting, colon-wrapped shortcodes, non-numeric suffixes, empty input
  • resolveEmojiGlyph: known shortcode → glyph, passthrough unicode, colon-stripped lookup, unknown fallback
  • Mute-list channel_id extraction logic (mirrors the parsing in channel_context_menu.dart and _MuteButtonState._load)

Generated by Claude Code

…part

The mute-button widgets were accidentally appended to accord_home_reactions.dart,
duplicating the definitions already in accord_home_mute_button.dart and failing
analyze with duplicate_definition. Keep only the canonical copies.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@krazyjakee krazyjakee merged commit 1fa85f2 into master Jun 11, 2026
5 checks passed
@krazyjakee krazyjakee deleted the feat/message-reactions-emoji branch June 11, 2026 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants