Skip to content

Add setting to hide unread activity dot indicators - #2923

Open
chagai95 wants to merge 13 commits into
cinnyapp:devfrom
chagai95:dev
Open

Add setting to hide unread activity dot indicators#2923
chagai95 wants to merge 13 commits into
cinnyapp:devfrom
chagai95:dev

Conversation

@chagai95

@chagai95 chagai95 commented May 2, 2026

Copy link
Copy Markdown

The idea is to get rid of showing those type of unread rooms and keep only the ones with the number which are a lot more reliable and important.

This is how it looks before:
image

and this is after:
image

@github-actions

github-actions Bot commented May 2, 2026

Copy link
Copy Markdown


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


1 out of 2 committers have signed the CLA.
✅ (chagai95)[https://github.com/chagai95]
@claude
You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@chagai95
chagai95 marked this pull request as ready for review May 2, 2026 01:19
@chagai95
chagai95 marked this pull request as draft May 2, 2026 01:20
@chagai95

chagai95 commented May 2, 2026

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

ajbura added a commit to cinnyapp/cla that referenced this pull request May 2, 2026
@chagai95

chagai95 commented May 2, 2026

Copy link
Copy Markdown
Author

recheck

@chagai95

chagai95 commented May 2, 2026

Copy link
Copy Markdown
Author

Here's a netlify link, if you wanted to test:
https://dev--cinny-chagai.netlify.app/home/

Rooms with unread activity but no notification count (muted rooms,
push-rule-downgraded rooms) showed a small grey dot in the room list
and kept appearing in the collapsed "unread only" nav section even
though nothing actually needed attention.

This adds a "Hide Unread Activity Dots" toggle (off by default) under
Settings › Notifications › System with three coordinated effects:

1. UnreadBadge: when the setting is on, skip rendering the dot
   entirely for rooms where count=0 and highlight=false.

2. Nav collapse filter (Direct, Home, Space): reads the same setting
   reactively — when on, the collapsed category shows only rooms with
   total>0 or highlight>0; when off, it reverts to the original
   behaviour of showing all rooms that have any unread activity.
   Toggling the setting in Settings updates the nav instantly without
   a page reload.

3. Settings UI: adds the toggle under Settings › Notifications › System.
@chagai95
chagai95 marked this pull request as ready for review May 6, 2026 23:22
@CrazyNicc

Copy link
Copy Markdown

Uhm, maybe I'm misunderstanding the purpose of this PR, but your "After" screenshot just seems to hide all the rooms that had this Unread Indicator

@chagai95

chagai95 commented May 7, 2026

Copy link
Copy Markdown
Author

@CrazyNicc thx for answering so quickly!

Yes that's exactly the point. A lot of irrelevant events trigger that unread marker and I think it makes sense to hide them for some users who get a lot of messages 🙈

Also it is shown when the room is muted I think and probably in other scenarios. There are also a lot of bugs that are related to them.

@CrazyNicc

Copy link
Copy Markdown

@chagai95 Oh, afaik muting the room also removed all the read indicators.

A lot of irrelevant events trigger that unread marker and I think it makes sense to hide them for some users who get a lot of messages

But your screenshot completely hides the rooms themselves, not just the unread markers of these rooms. Or did I miss something?

@chagai95

chagai95 commented May 7, 2026

Copy link
Copy Markdown
Author

@chagai95 Oh, afaik muting the room also removed all the read indicators.

A lot of irrelevant events trigger that unread marker and I think it makes sense to hide them for some users who get a lot of messages

But your screenshot completely hides the rooms themselves, not just the unread markers of these rooms. Or did I miss something?

It hides them from the unread view, when the section is closed (arrow not down), maybe muting the room helps with that, didn't check but I don't want to start muting all my rooms just to avoid seeing this, on fluffy chat it's not shown by default in the unread tab.

@chagai95

Copy link
Copy Markdown
Author

Hi everyone, just wondering if there is something missing here?

@CrazyNicc

Copy link
Copy Markdown

See the notice in the Project README:

We are currently in the process of replacing the matrix-js-sdk with our own SDK. As a result, we will not be accepting any pull requests until further notice. Thank you for your understanding.

claude added 11 commits July 16, 2026 15:22
…message"

Replying to a voice note (m.audio .ogg, e.g. a bridged WhatsApp "Voice
message.ogg") — or any media without a text body — rendered the quoted
preview as "Failed to load message" even though the replied-to event
loaded fine.

Root cause: Reply.tsx only used the event's `body`. When `body` was
missing/empty (or was only the stripped reply-quote), it fell through to
the generic MessageFailedContent fallback, which reads "Failed to load
message".

Fix: when a loaded reply target has no usable text body, derive a
msgtype-based preview (🎤 Voice message / 🔊 Audio / 🖼️ Image /
🎬 Video / 📄 File / 📍 Location) instead of the failure fallback.
Voice notes are detected via the MSC3245/MSC1767 voice extension on
m.audio. Only genuinely un-renderable events (redacted → deleted notice;
unknown/no content → failure) still hit the fallbacks. General across all
media msgtypes, not a voice-only band-aid.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPNRaVnHM9hmpwYyewbeVj
…e estimates

The emoji board virtualizes at the group level but used a flat
estimateSize of 40px per group. Before any group was measured, the
virtualizer therefore believed all ~10 groups fit in the 400px viewport
and eagerly mounted every group — ~1,900 emoji <button> nodes — on the
very first paint, defeating the virtualization and making the popover
slow to open.

Estimate each group's real rendered height from its item count (48px
emoji / 112px sticker buttons, ~6/3 per row + group chrome) so only the
groups that actually fit the viewport mount on open (~700 nodes now,
dominated by the first "People" category), and drop overscan 2 -> 1 so
an off-screen 500+ item category isn't eagerly built. Scroll/search,
categories, recents and custom emoji/stickers are unchanged.
…guage setting

Add an in-app, client-side transcription action for voice/audio messages
(m.audio / m.voice). A microphone button next to the audio player opens an
app-only popover that requests a transcript from the local Whisper backend
(POST /transcribe with { room_id, event_id, mxc, language? }) and shows the
returned text plus the detected language, with copy-to-clipboard. The
transcript is cached in component state and is NEVER posted to the chat or
forwarded anywhere — it is a purely client-side overlay. Transcript text is
rendered strictly as text (untrusted content).

Adds a per-user default transcription language setting (General settings) and
optional backend URL/secret overrides. The API base and shared secret are
configurable via Vite env vars VITE_TRANSCRIBE_API_BASE and
VITE_TRANSCRIBE_API_SECRET (with settings overrides taking precedence), so the
endpoint can be re-pointed without a code change; no secret is hardcoded.

New files live under src/app/features/transcription/ to avoid overlap with the
parallel in-app translation feature. Shared files touched additively:
settings.ts (new fields), RenderMessageContent/AudioContent (thread roomId/
eventId to the button), General.tsx (settings section), RoomTimeline.tsx (pass
identifiers at the two message render sites).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add per-message translate button + auto-translate-all toggle to Cinny,
backed by Chagai's on-box argos/"Libre" translation API (offline, no cloud
translator). New self-contained `translation` feature (kept separate from the
voice-note transcription UI to minimize merge conflicts):

- Per-message "Translate" trigger under each text message with a language
  picker; shows the translation inline. Result cached per event+target.
- Global "auto-translate everywhere into <lang>" toggle + language in a new
  Settings > Translation page; per-chat override in room settings General.
- Settings persist in Matrix account data (`in.cinny.translation`) so they
  sync across devices; room override beats the global setting.
- Backend URL + shared token read from public/config.json
  (ClientConfig.translation); feature hides itself when unconfigured.
- Message text is only translated, never interpreted (injection-safe).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPNRaVnHM9hmpwYyewbeVj
…lback to Settings)

Ship the on-box transcription API base+secret in public/config.json (mirrors the
translation block) so the 🎤 transcribe button works out of the box on the static
Netlify site. TranscribeButton falls back to config.json when the per-user Settings
overrides are empty (precedence: Settings > config.json > built-in default).
Also fill the translation token in config.json.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPNRaVnHM9hmpwYyewbeVj
useRooms() excludes DM rooms (mDirects check), so WA portal room IDs
were stripped from the URL filter — producing [] (not undefined) —
causing Synapse to receive `rooms: []` and return zero results.

Fix 1: replace useRooms with new useAllJoinedRooms (no mDirects
exclusion) so WA portals resolve correctly in the URL param filter.

Fix 2: harden the resolved list — return undefined when all requested
rooms fail to resolve (silent-empty guard) so the search falls back to
the default scope instead of sending an empty room list.

Fix 3: pass the full allRooms list (rooms + DMs) to SearchFilters so
the room picker shows WA chats as selectable options.

Co-Authored-By: Claude <noreply@anthropic.com>
Include DM/WhatsApp rooms in message search room filter.
Fix: useAllJoinedRooms hook to bypass mDirects exclusion, harden
empty-room-list → undefined fallback so Synapse gets correct scope.
Copilot AI review requested due to automatic review settings August 3, 2026 22:34

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new user setting to suppress “dot-only” unread indicators (keeping numeric unread counts), and also bundles several additional UI and feature changes (translation, transcription, search scoping, reply preview improvements, and emoji board virtualization tuning).

Changes:

  • Add hideUnreadActivityDots setting and apply it to unread badge rendering and “show room anyway” filtering when categories are collapsed.
  • Add in-app translation (account-data backed config, per-message translation UI, global/per-room auto-translate controls) and local Whisper transcription UI/actions.
  • Adjust message search room scoping and tune EmojiBoard virtualization/overscan behavior.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/app/state/settings.ts Adds new settings keys (hideUnreadActivityDots, transcription overrides) and defaults.
src/app/state/hooks/roomList.ts Adds useAllJoinedRooms hook for broader “joined rooms” selection.
src/app/pages/client/space/Space.tsx Applies hideUnreadActivityDots when deciding whether unread rooms keep categories open/visible.
src/app/pages/client/home/Home.tsx Applies hideUnreadActivityDots when filtering rooms shown under collapsed categories.
src/app/pages/client/direct/Direct.tsx Applies hideUnreadActivityDots when filtering directs shown under collapsed categories.
src/app/hooks/useClientConfig.ts Extends client config type with translation and transcription configuration blocks.
src/app/features/translation/useTranslation.ts Adds translation hooks (account-data config + per-event translation state + auto-translate logic).
src/app/features/translation/translationConfig.ts Adds account-data persistence/read/write + resolution logic for per-room overrides.
src/app/features/translation/translateApi.ts Adds translation backend client and in-memory caching.
src/app/features/translation/RoomAutoTranslate.tsx Adds per-room auto-translate controls in room settings.
src/app/features/translation/MessageTranslation.tsx Adds per-message translation UI (toggle, language picker, result rendering).
src/app/features/translation/MessageTranslation.css.ts Styles for translation UI elements.
src/app/features/translation/languages.ts Static language list + helpers for translation feature.
src/app/features/transcription/TranscriptionSettings.tsx Adds general settings section for transcription language and backend overrides.
src/app/features/transcription/TranscribeLanguageSelect.tsx Adds dropdown selector for transcription default language.
src/app/features/transcription/TranscribeButton.tsx Adds per-audio-message “Transcribe” popover action with copy/retry handling.
src/app/features/transcription/transcribeApi.ts Adds transcription backend client and error handling.
src/app/features/transcription/languages.ts Static language list + helper for transcription feature.
src/app/features/settings/translation/Translation.tsx Adds a settings page for global translation/auto-translate configuration.
src/app/features/settings/translation/index.ts Exports the translation settings page.
src/app/features/settings/Settings.tsx Adds “Translation” to the settings navigation and routes it to a new page.
src/app/features/settings/notifications/SystemNotification.tsx Adds toggle UI for hideUnreadActivityDots.
src/app/features/settings/general/General.tsx Includes the new TranscriptionSettings section.
src/app/features/room/RoomTimeline.tsx Passes roomId/eventId down to message content rendering for transcription actions.
src/app/features/room/message/Message.tsx Injects per-message translation UI under non-edit message content.
src/app/features/room-settings/general/General.tsx Adds per-room auto-translate controls to room settings.
src/app/features/message-search/MessageSearch.tsx Switches room source for search scoping + tweaks URL-room resolution behavior and filter list.
src/app/components/unread-badge/UnreadBadge.tsx Hides dot-only unread badges when hideUnreadActivityDots is enabled.
src/app/components/RenderMessageContent.tsx Adds optional roomId/eventId props and forwards them into AudioContent.
src/app/components/message/Reply.tsx Improves reply previews for media messages (voice/audio/image/file/etc.) when no body is present.
src/app/components/message/content/AudioContent.tsx Adds transcription button next to audio playback controls when identifiers are available.
src/app/components/emoji-board/EmojiBoard.tsx Adjusts virtualizer overscan and adds better height estimation for emoji/sticker groups.
config.json Adds translation/transcription config defaults (including endpoint/token fields).

Comment thread config.json
Comment on lines +33 to 42
"translation": {
"endpoint": "https://mx.chagai.website/translate-api",
"token": "oMBdfX9qUcwBl2TZMTNjYkC9YHuSdI2Cfne-57h8Pks",
"defaultTargetLang": "en"
},

"transcription": {
"endpoint": "https://mx.chagai.website/apptranscribe",
"token": "UwTuImsqajz9PTXg7dMQb839PEPMKsaTWMRmde4V1NQ"
}
Comment thread config.json
Comment on lines +33 to +37
"translation": {
"endpoint": "https://mx.chagai.website/translate-api",
"token": "oMBdfX9qUcwBl2TZMTNjYkC9YHuSdI2Cfne-57h8Pks",
"defaultTargetLang": "en"
},
Comment on lines +94 to +97
export const useRoomAutoTranslate = (roomId: string): { auto: boolean; targetLang: string } => {
const { config } = useTranslationConfig();
return useMemo(() => resolveRoomAutoTranslate(config, roomId), [config, roomId]);
};
Comment on lines +58 to +61
{t.error && (
<Text size="T200" style={{ color: config.color?.critical, marginTop: config.space.S100 }}>
{`Translation failed: ${t.error}`}
</Text>
@chagai95

chagai95 commented Aug 4, 2026

Copy link
Copy Markdown
Author

Sorry I accidently kept on using the same branch 🤦🏻

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.

4 participants