discourse/plugins/chat/app
Rafael dos Santos Silva b0873d3ecd
FEATURE: Restore web push quick reply for chat messages (#39614)
**Previously**, the "Reply" action on chat web push notifications was
silently broken — the service worker's chat URL regex stopped matching
when chat routes moved to `/chat/c/:slug/:id`, and the chat-specific
code lived in core with no thread support, URL encoding, or error
handling.

**In this update**, generalize the core service worker into a
plugin-extensible action registry, move chat reply handling into the
chat plugin with proper thread/encoding/fallback support, and convert
single-emoji replies into reactions on the source message (falling back
to a regular message post on any failure).

## Architecture

Core (`app/views/static/service-worker.js.erb`) now exposes:

```js
self.registerNotificationActionHandler(action, handler);
```

Push payloads can carry `actions` (Web Notifications API format) and
`action_data` (an arbitrary object surfaced to the handler at
`event.notification.data.actionData`). The click handler dispatches by
`event.action` name and falls back to the existing focus-or-open
behavior when no handler matches or a handler throws.

`PushNotificationPusher` forwards `actions` / `action_data` when
present.

The chat plugin owns its own service worker
(`plugins/chat/assets/javascripts/service-worker.js`), registered via
`register_service_worker`. It registers a `chat-reply` handler that:

1. Fetches a CSRF token.
2. If the reply is a single emoji grapheme (detected via
`Intl.Segmenter`, with a `\p{Extended_Pictographic}` regex fallback),
`PUT`s to `/chat/:channel_id/react/:message_id`.
3. Otherwise — or if the reaction request fails — `POST`s to
`/chat/:channel_id` with proper `URLSearchParams` encoding and the
source `thread_id` if present.
4. If everything fails, opens the channel so the user can retype.

`Chat::Notifier.push_notification_reply_action(chat_message, user)`
builds the payload in the user's locale with `channel_id`, `message_id`,
and optional `thread_id`.

`Chat::MessageReactor#react!` resolves raw Unicode via
`Emoji.unicode_replacements[emoji] || emoji` before validation, so
smartwatch quick-reply chips (which send raw Unicode like `👍🏽` or ZWJ
sequences) just work. Existing shortcode callers are unaffected.

## Why this matters

Smartwatch notification UIs expose a single "reply" affordance with
canned chips that include short text and emoji. The user can't choose
between "send as message" and "react"; they tap a chip and a string
comes through. Treating a single-grapheme pictographic reply as a
reaction matches user intent on the watch UX without any new product
surface.

## Test plan

- [ ] On a chat-enabled site, subscribe to web push notifications.
- [ ] Have another user post a message that mentions you, or a watched
channel message.
- [ ] On the resulting OS notification, confirm a "Reply" action button
appears.
- [ ] Type a text reply and submit — verify it posts as a message in the
right channel/thread.
- [ ] Submit a single emoji (e.g. 👍 or 👍🏽 with skin tone) — verify it
lands as a reaction on the source message instead of posting a message.
- [ ] Submit a ZWJ sequence (e.g. 👨‍👩‍👧) — verify it lands as a reaction
(or falls back to message post if not in the emoji DB).
- [ ] Sign out / let session expire and submit a reply — verify the
channel opens as a fallback rather than silently failing.
- [ ] Watch via Wear OS / watchOS quick-reply chips and confirm the same
behavior end-to-end.
2026-04-29 12:36:03 -03:00
..
controllers/chat SECURITY: Respect group visibility in category chatables when accessed by a moderator 2026-03-31 15:12:45 +01:00
jobs FEATURE: Restore web push quick reply for chat messages (#39614) 2026-04-29 12:36:03 -03:00
models PERF: speed up chat channel and thread unread queries (#39398) 2026-04-22 14:57:56 +10:00
queries/chat PERF: speed up chat channel and thread unread queries (#39398) 2026-04-22 14:57:56 +10:00
serializers/chat DEV: Apply consistent N+1 fix pattern to ThreadOriginalMessageSerializer (#38667) 2026-03-17 14:17:58 -05:00
services/chat SECURITY: Harden chat DM channel creation and expansion 2026-03-31 15:12:45 +01:00
validators/chat FEATURE: Add setting to prevent anonymous users from using chat (#31842) 2025-03-21 13:32:52 +03:00
views PERF: fix performance of chat email notifications 2024-06-10 14:25:06 +02:00