feat(chat): mute conversations (Q10)

Per-conversation mute toggle in the thread header. Muted conversations (tracked
by cid in settings, so it persists) are skipped by chatUnreadCount(), so they
neither raise the nav-item unread badge nor the new-message toast — the toast now
gates on a chatUnreadCount() delta across ingest, which already skips muted cids,
so mute is respected for free. "Block" (rejecting a peer's inbound memos) is a
larger ingest-filter change and is intentionally left out of this pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-16 16:48:57 -05:00
parent fecc9015fb
commit 24c661f743
4 changed files with 40 additions and 4 deletions

View File

@@ -11,6 +11,7 @@
#include "../../chat/chat_service.h"
#include "../../util/i18n.h"
#include "../../util/platform.h" // getConfigDir + writeFileAtomically — conversation export (Q11)
#include "../../config/settings.h" // per-conversation mute (Q10)
#include "../material/colors.h"
#include "../material/color_theme.h" // WithAlpha
#include "../material/type.h"
@@ -431,6 +432,13 @@ void RenderChatTab(App* app)
else
Notifications::instance().error(TR("chat_export_failed"));
}
// Mute toggle — muted conversations don't badge or toast (Q10). Persisted to settings.
ImGui::SameLine();
const bool muted = app->settings() && app->settings()->isChatMuted(sel->cid);
if (ImGui::SmallButton(muted ? TR("chat_unmute") : TR("chat_mute")) && app->settings()) {
app->settings()->setChatMuted(sel->cid, !muted);
app->settings()->save();
}
}
ImGui::Separator();