[2.x] feat: realtime extender API + per-extension integrations + notification toasts - #4473
Merged
Conversation
…fication toasts Introduces a `Realtime` extender so each bundled extension wires its own realtime behaviour without realtime having hardcoded knowledge of them. **flarum/realtime** - New `Realtime` PHP extender: `onPublicChannelEvent`, `onUserChannelEvent`, `registerModelEndpoint` — extensions declare their own push handlers and payload model mappings. - `RealtimeRegistry` collects extender registrations; `EventSubscriber` dispatches them. - `Generator` endpoint/resource maps are now open — `Notification` added as a core entry; extensions add their own via `registerModelEndpoint`. - Deleted hardcoded `NewActivity` push classes (Dialog, Discussion, Post). - `SendFlaggedJob` no longer deletes flags as a side-effect; flags extension owns that logic. - `SendNotificationsJob` now looks up the `Notification` record and sends it (not the recipient `User`) so the JS receives a proper notification payload. - JS: new `Realtime` extender class for extension-side channel event wiring. - JS: `RealtimeState` for sharing channel-ready callbacks. - JS: `NotificationToast` component + `NotificationToastState` — realtime notifications show as auto-dismissing toasts (top-right, 5 s) reusing the standard `NotificationType` component, with discussion context header. - LESS: toast + typing-indicator styles. **flarum/flags** - Registers its own realtime push via `Realtime` extender (flagged event). - JS: `extendRealtime` wires flag stream update on incoming flag events. **flarum/likes** - Registers its own realtime push via `Realtime` extender. - JS converted to TypeScript; `extendRealtime` wires like count update. **flarum/lock** - Registers its own realtime push via `Realtime` extender. - JS converted to TypeScript; `extendRealtime` wires lock state update. **flarum/messages** - Registers its own realtime push via `Realtime` extender. - JS: `extendRealtime` wires inline message delivery (`state.push`) and typing indicator; uses `ext:` prefix for cross-extension `extend()` calls. - `DialogMessageResource` gains a Show endpoint (needed for payload generation). - `extend.php` de-duplicated (Show endpoint lives in resource class). **flarum/core** - `NotificationResource` gains a Show endpoint (authenticated, scoped to actor) so the payload generator can fetch a single notification.
…esource Show endpoint
…nto im/realtime-extender-refactor
…mework into im/realtime-extender-refactor
- Generator::retrieve(): add is_string() guard before instanceof to fix PHPStan error (map keys are int|string, instanceof requires string) - Improve TypeScript type coverage from 76% → 80%: replace `this: any` property assignments with arrow functions so inner callbacks are typed; add explicit return types and typed parameters to DiscussionList/NewActivity, Discussion/NewActivity, and Discussion/TypingIndicator
imorland
added a commit
to flarum/docs
that referenced
this pull request
Mar 20, 2026
Documents the Realtime PHP and JS extender API introduced in flarum/framework#4473. Covers: - broadcastModelEvent / broadcastDialogEvent / broadcastFlagEvent - registerModelEndpoint for custom model types - JS RealtimeExtend extender (onDiscussionStreamEvent, onUserChannelEvent, onPublicChannelEvent, onBothChannelsEvent) - Direct channel access via RealtimeState - Complete likes integration as a real-world example - Security model (permission-gated payload generation + channel auth)
3 tasks
imorland
marked this pull request as ready for review
March 20, 2026 23:57
imorland
added a commit
to flarum/docs
that referenced
this pull request
Mar 21, 2026
Documents the Realtime PHP and JS extender API introduced in flarum/framework#4473. Covers: - broadcastModelEvent / broadcastDialogEvent / broadcastFlagEvent - registerModelEndpoint for custom model types - JS RealtimeExtend extender (onDiscussionStreamEvent, onUserChannelEvent, onPublicChannelEvent, onBothChannelsEvent) - Direct channel access via RealtimeState - Complete likes integration as a real-world example - Security model (permission-gated payload generation + channel auth)
imorland
added a commit
that referenced
this pull request
Mar 21, 2026
These were generated by the TS build during the realtime refactor (#4473) but never committed — the build bot only updates already-tracked files. This seeds the dist-typings so future PRs are bundled automatically.
This was referenced Jun 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
RealtimePHP + JS extender so bundled extensions wire their own realtime behaviour;flarum/realtimehas no hardcoded knowledge of other extensionsflarum/flags,flarum/likes,flarum/lock, andflarum/messagesrespectivelyNotificationTypecomponent with discussion contextflarum/messages(push not reload) and typing indicator teardownNotificationResource::Showendpoint andNotificationtoGeneratorendpoint map so notification payloads are generated correctlyNewActivitypush classes fromflarum/realtimeTest plan
user_id = actor->idscope in both DB query and API resource