Originally created by: kristofferR
A review of fMess (toanbku/fmess, MIT) turned up behavior Carrier lacked and no issue tracked:
- After sleep, Messenger notified about every message it caught up on, including ones already read on the phone.
- Messenger's in-page sounds showed up in macOS Now Playing, kept playing during Do Not Disturb and Pause, and a message could ring twice: Messenger's sound plus Carrier's system notification sound.
- Hide Avatars still let sender and group pictures into notifications.
- The panes couldn't be resized, encrypted chats opened slowly, and a few rough edges remained: selectable app chrome, grey scroll-bar tracks, a gradient flash in themed chats, and a slow WebKit layout for full-size post images.
What changed
Notifications and sounds
- Messenger's notification is skipped for a message over 2 minutes old by Facebook's server clock, or one whose conversation is already read past it. If the check fails or is slow, the notification is shown.
SoundPlayer one-shots play through Web Audio. The context suspends between sounds and is created behind the existing idle gate (#232, [#234]). Ringtones and other media are untouched. If Web Audio fails, the element plays as before.
- All of Messenger's sounds are silent during Messenger's Do Not Disturb, Carrier's Pause and Mute. Calls still ring.
- A message rings once:
- While Carrier is unfocused and its notification sound is on, Messenger's sound is skipped.
- When Messenger's sound has just played for a conversation, the native notification for that conversation is delivered silently. The page can only take the sound away (
silent in carrier:notify), never add it.
- Hide Avatars is enforced on the Rust delivery path: no sender or group pictures in notifications on any platform. Message photos stay unless Hide Preview drops them.
Layout and reading
- Drag the edge of the chat list or details pane to resize it, and double-click it to reset. The widths are sent through
carrier:pane-widths, validated and clamped in Rust, saved in settings and pushed back on every page load, since Facebook clears unknown localStorage on Mac. "Reset all settings" resets them too.
- The newest 40 messages of the 12 most recent end-to-end encrypted chats are preloaded from the local store, the same call Messenger makes when you press a chat row. This sends nothing to Facebook and opens no chat, so no seen receipts and no notifications. It pauses during rate-limit episodes, recovery and offline. Plain chats are left out because preloading them would request messages from Facebook's servers.
Polish
- On chat routes the app chrome can't be selected, and Select All outside a text field selects nothing. Message text, dialogs and fields stay selectable.
- macOS draws overlay scroll bars:
AppleShowScrollBars=WhenScrolling in Carrier's own defaults. Where Windows or Linux draws classic bars, they're hidden and a thin passive indicator floats over the scrolling pane.
- In gradient-themed chats, outgoing bubbles paint the gradient themselves, so a fast scroll no longer flashes it. This works alongside the existing seam fix and Carrier themes.
img[height="100%"][width="100%"] in chats uses height: auto. fMess measured about 4 s per layout for these images in shared-post previews.
- Trackpad pinch zooms photos in Carrier's zoom overlay on macOS. Wheel zoom follows a gentler curve.
- Escape cancels a voice clip being recorded or replayed, unless a dialog, menu or the overlay is open.
Code adapted from fMess carries its MIT notice.
Testing
bun run check, cargo fmt, cargo clippy --all-targets -D warnings (Linux, plus cross-checks for aarch64-apple-darwin and x86_64-pc-windows-msvc) and cargo test --lib.
- Live on Linux (WebKitGTK) and macOS 27 diagnostics builds, through a dev-only MCP probe (
__carrier_mcp_fmess_probe__, counts and geometry only):
- Pane edges are found (details on the correct side), drag, persist to
settings.json, survive a relaunch, and reset on double-click.
- Chrome is unselectable, message text selectable, and Select All with nothing focused selects nothing.
- macOS gets
AppleShowScrollBars=WhenScrolling. Both engines report overlay scroll bars, which are only thinned.
- The gradient fix applies in a gradient-themed chat.
- Read-ahead preloads the 12 most recent encrypted chats on both platforms, with no notifications and no change in unread state.
- Messenger's message sound plays through Web Audio and its
<audio> element never plays. On macOS, Carrier no longer registers with Now Playing. That needed the elements muted too: a WKWebView test app showed that, after a user gesture, WebKit offers a loaded, unmuted, never-played <audio> as Now Playing as soon as any other playback starts.
- Still to try by hand: trackpad pinch in the zoom overlay, Escape while recording a voice clip, and a real message for single-ring and Hide Avatars notifications.
Ref [#349]
Summary by CodeRabbit
- New Features
- Resize Messenger’s conversation list and details panes by dragging their edges; double-click an edge to restore its default width. Pane widths are saved.
- Zoom images and videos with wheel, pinch, or double-click gestures.
- Press Escape to cancel a voice clip when no other dialog or viewer is using the key.
- Encrypted chats can have recent messages preloaded without opening the chats or marking messages as seen.
- Chat bubbles display the gradient background, and classic scrollbars show a scroll-position indicator.
- Improvements
- Notifications avoid duplicate sounds and suppress stale alerts; avatar visibility is handled separately from message previews.
- Select All no longer selects the entire Messenger page when focus is outside an editable field.
Originally posted by: coderabbitai[bot]
Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.
Originally posted by: chatgpt-codex-connector[bot]
Codex Review Summary: ✅ Completed
This comment shows the latest Codex review activity on this pull request. | Review | Status | Commit | Review trigger | | --- | --- | --- | --- | | 📝 **Code Review** | ✅ **Completed** <relative-time datetime="2026-11-08T09:05:17.411563Z">2026-11-08T09:05:17.411563Z</relative-time> | `7a8a2af` | Manual request |ℹ️ About Codex in GitHub
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review" or "@codex security review". Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.
Originally posted by: chatgpt-codex-connector[bot]
Codex Review: Didn't find any major issues. What shall we delve into next?
Reviewed commit:
23fd1371e1ℹ️ About Codex in GitHub
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Originally posted by: coderabbitai[bot]
<picture>
</picture>
Walkthrough
The pull request adds Messenger features for sound and notification handling, pane resizing, encrypted-chat read-ahead, media zoom, voice-clip Escape handling, and chat presentation. It also adds Tauri persistence and window updates for pane widths, plus a bridge probe for feature state and actions. **Changes: Sound and notification handling** |Layer / File(s)|Summary| |:---|:---| |**Messenger sound routing**
`inject/src/messenger/lib/messenger-sounds.ts`, `inject/src/messenger/features/messenger-sounds.ts`, `inject/src/messenger/features/facebook-modules.ts`, `inject/src/messenger/lib/messenger-sounds.test.ts`|Sound modules apply message-sound policy and route eligible non-looping audio through Web Audio, with native playback fallback.| |**Old-message detection and stale state**
`inject/src/messenger/lib/page-notifications.ts`, `inject/src/messenger/lib/page-notifications.test.ts`|Message timestamps and read watermarks identify old notifications. The page message index records stale IDs and exposes stale-tag checks.| |**Notification delivery and sound state**
`inject/src/messenger/features/notifications.ts`, `src-tauri/src/notifications.rs`|Native notification payloads carry silent state, stale page notifications follow the suppression path, and avatar visibility is handled separately from preview visibility.| **Pane resizing and persistence** |Layer / File(s)|Summary| |:---|:---| |**Pane width rules**
`inject/src/messenger/lib/pane-resize.ts`, `inject/src/messenger/lib/pane-resize.test.ts`, `inject/src/types.d.ts`|Pane width values are sanitized and bounded. Helpers calculate resize edges, drag widths, limits, and CSS; tests cover these calculations.| |**Resize interaction**
`inject/src/messenger/features/pane-resize.ts`, `inject/src/messenger/lib/pane-gradient.browser.test.ts`|The page applies stored widths, supports pointer dragging and double-click resets, and emits changed widths. Browser tests cover drag termination and gradient detection.| |**Persisting and distributing widths**
`src-tauri/src/pane_widths.rs`, `src-tauri/src/settings.rs`, `src-tauri/src/commands.rs`, `src-tauri/src/lib.rs`, `src-tauri/src/window.rs`|Tauri stores pane widths, preserves them during ordinary settings saves, and pushes updates to Messenger windows.| **Encrypted chat read-ahead** |Layer / File(s)|Summary| |:---|:---| |**Thread selection and timing**
`inject/src/messenger/lib/read-ahead.ts`, `inject/src/messenger/lib/read-ahead.test.ts`|Selection filters eligible encrypted inbox threads and excludes the open thread and duplicates. Timing helpers enforce result limits and minimum gaps.| |**Preload scheduling and execution**
`inject/src/messenger/features/read-ahead.ts`|The initializer checks runtime conditions, loads Messenger APIs, preloads selected threads with timeouts, and schedules runs after startup and activity events.| **Media viewer zoom** |Layer / File(s)|Summary| |:---|:---| |**Zoom math and boundaries**
`inject/src/messenger/lib/media-zoom.ts`, `inject/src/messenger/lib/media-zoom.test.ts`|Shared utilities convert wheel input to scale factors and keep a selected point anchored within scale limits.| |**Viewer zoom controls**
`inject/src/messenger/features/media-viewer.ts`|The viewer delegates wheel and double-click zoom to shared utilities, tracks Ctrl state, and adds WebKit gesture entry, updates, and exit behavior.| **Voice-clip Escape handling** |Layer / File(s)|Summary| |:---|:---| |**Escape eligibility and cancel icon**
`inject/src/messenger/lib/composer-keys.ts`, `inject/src/messenger/lib/composer-keys.test.ts`|Helpers identify the voice-clip cancel icon and define the conditions for handling Escape.| |**Capture-phase cancel action**
`inject/src/messenger/features/composer-keys.ts`|The document capture handler checks for a visible cancel button and clicks it when Escape is eligible.| **Chat presentation and selection** |Layer / File(s)|Summary| |:---|:---| |**Outgoing bubble gradient**
`inject/src/messenger/lib/chat-gradient.ts`, `inject/src/messenger/lib/chat-gradient.test.ts`, `inject/src/messenger/features/chat-gradient.ts`|The feature discovers outgoing bubble classes from accessible stylesheets and applies generated gradient CSS.| |**Selection and scrollbar behavior**
`inject/src/messenger/features/selection.ts`, `inject/src/messenger/lib/scrollbars.ts`, `inject/src/messenger/lib/scrollbars.test.ts`, `inject/src/messenger/features/scrollbars.ts`, `src-tauri/inject/messenger.css`|The page tracks Messenger paths for selection controls, measures scrollbar style, and positions a scroll indicator. CSS styles selection, scrollbars, the indicator, and fully sized main-pane images.| |**Feature registration and platform setup**
`inject/src/messenger/index.ts`, `src-tauri/src/macos/mod.rs`, `src-tauri/src/macos/scrollbars.rs`, `src-tauri/src/lib.rs`|Messenger registers the new feature initializers, and macOS startup requests overlay scrollbars before creating webviews.| **Messenger feature probe** |Layer / File(s)|Summary| |:---|:---| |**Probe command and actions**
`src-tauri/inject/mcp-bridge.js`|The bridge dispatches the optional probe command and returns feature diagnostics or action results, including errors from rejected asynchronous actions.| **Estimated code review effort:** 4 (Complex) | ~60 minutes **Change:** Feature **Possibly related issues** - [[kristofferR/Carrier#349](https://github.com/kristofferR/Carrier/issues/349)](https://github.com/kristofferR/Carrier/issues/349): The PR changes Messenger sound handling and duplicate message rings, which match the tracker’s notification behavior. - [[kristofferR/Carrier#437](https://github.com/kristofferR/Carrier/issues/437)](https://github.com/kristofferR/Carrier/issues/437): The PR changes sound behavior related to one sound per message, Do Not Disturb, and Messenger’s sound setting. **Possibly related PRs** - [[kristofferR/Carrier#378](https://github.com/kristofferR/Carrier/issues/378)](https://github.com/kristofferR/Carrier/pull/378): This PR provides the `notificationsGloballyMuted` contract used by the new Messenger sound and notification logic.
Pre-merge checks: <picture>
</picture> 3 · <picture>
</picture> 2
<picture>
<picture>
</picture> Passed checks: 3 passed
| Check name | Status | Explanation | | :------------------------ | :--------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Title check |  | The title "feat: notification, sound and layout improvements from the fMess review" matches the changeset. The diff covers notification suppression for old news and silent delivery, Web Audio routing … | | Linked Issues check |  | Check skipped because no linked issues were found for this pull request. | | Out of Scope Changes check |  | Check skipped because no linked issues were found for this pull request. |
Full details: Title check
**Explanation** The title "feat: notification, sound and layout improvements from the fMess review" matches the changeset. The diff covers notification suppression for old news and silent delivery, Web Audio routing for Messenger sounds, pane resizing, read-ahead, scrollbars, gradient handling, and Escape handling for voice clips. The title names the three main areas but omits read-ahead, scrollbars, and the Escape change. It also includes the phrase 'from the fMess review', which describes the source of the work rather than the change itself. The title is broad, but it is related to the changeset and is not misleading.
Full details: Docstring Coverage
**Explanation** Docstring coverage is 58.18% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 55 functions across 38 files. **Resolution** Write docstrings for the functions missing them to satisfy the coverage threshold.
Full details: Description check
**Explanation** The description covers the change in substantial detail: notification and sound behavior, pane resizing, encrypted-chat read-ahead, layout and polish items, and the fMess MIT attribution. It also lists the checks run and the live verification done. It does not follow the repository template, which requires a '## Summary' heading, an 'AI models used' field, and an optional reasoning-levels field. The author never states whether AI helped write the code or PR text, so the required AI-models field is missing. The description also does not say that the test plan is partly unfinished beyond a short list of manual checks. **Resolution** Add the template's required sections: a '## Summary' heading that wraps the problem and change text, and an 'AI models used:' line. State the models and versions used to create or edit code, tests, or PR text, or write 'None' if no AI was used. Optionally add the 'Reasoning levels' line, or write 'Reasoning levels: Unavailable (not exposed by tool)' if AI was used and the tool does not expose it.
Finishing Touches
Generate docstrings
- [ ] Commit to this branch - [ ] Create a new PR
Generate unit tests (beta)
- [ ] Commit to this branch - [ ] Create a new PR
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Share
- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)
Related
Commit: [a49771]
Originally posted by: coderabbitai[bot]
Action not completed
Review rate limited. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.
Originally posted by: chatgpt-codex-connector[bot]
Codex Review: Didn't find any major issues. Hooray!
Reviewed commit:
0c7ee99810ℹ️ About Codex in GitHub
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Originally posted by: chatgpt-codex-connector[bot]
Codex Review: Didn't find any major issues. Nice work!
Reviewed commit:
d3af5ee09bℹ️ About Codex in GitHub
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Originally posted by: chatgpt-codex-connector[bot]
Codex Review: Didn't find any major issues. More of your lovely PRs please.
Reviewed commit:
59445cfcc9ℹ️ About Codex in GitHub
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Originally posted by: chatgpt-codex-connector[bot]
Codex Review: Didn't find any major issues. Swish!
Reviewed commit:
a49771be2cℹ️ About Codex in GitHub
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Originally posted by: coderabbitai[bot]
Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.
Originally posted by: kristofferR
@coderabbitai review
Originally posted by: coderabbitai[bot]
Action not completed
Review rate limited. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.
Originally posted by: chatgpt-codex-connector[bot]
Codex Review: Didn't find any major issues. Nice work!
Reviewed commit:
7a8a2af9beℹ️ About Codex in GitHub
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Ticket changed by: kristofferR