From cbc4ddb2d0339626b97227d93fcce52ba873f768 Mon Sep 17 00:00:00 2001 From: Salastil Date: Sat, 22 Aug 2026 23:17:28 -0400 Subject: [PATCH] Reduce status to Online and Idle, and stop tracking the packed tarball Do Not Disturb is gone from the picker, along with what it needed: the notifier's account-status tracking and main's watching of the account list, which existed only to enforce it with the window closed. Status is now purely per account, so choosing one no longer reaches across the others. moho-0.1.0.tgz was committed - 19.5MB of npm pack output, a build artifact regenerable at any time. Untracked, and *.tgz ignored so the next `npm pack` does not put it back. The .presence-dot.dnd style stays: that renders other people's Discord status in the friends list, where DND is a value they really can have. --- .gitignore | 2 ++ nobilis | 2 +- src/main/index.ts | 10 +------ src/main/notifications.ts | 13 --------- src/renderer/src/components/UserFooter.tsx | 31 +++++----------------- src/renderer/src/state/store.ts | 2 +- src/shared/wire.ts | 2 +- 7 files changed, 13 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index ab8f822..1243e29 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ node_modules/ /out/ /dist/ +# npm pack output - a build artifact, regenerable with `npm pack` +*.tgz *.log *.tsbuildinfo diff --git a/nobilis b/nobilis index 94e801f..e6b8244 160000 --- a/nobilis +++ b/nobilis @@ -1 +1 @@ -Subproject commit 94e801f0247e1821eefdb305e40050eb80b14295 +Subproject commit e6b824462734ef40211d65dd1f067a45f7692905 diff --git a/src/main/index.ts b/src/main/index.ts index ad457b4..aef0620 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -221,15 +221,7 @@ function applyHotkey(accelerator: string): void { function wireIpc(): void { ipcMain.handle(IPC.rpc, async (_e, method: string, params: Record) => { try { - const result = await client.request(method, params) - // Main needs each account's status to enforce Do Not Disturb, and the - // renderer already asks for the account list whenever it changes - - // watching the answer keeps the two in step without a second channel or - // a poll of its own. - if (method === 'listAccounts' && Array.isArray(result)) { - notifier.trackAccounts(result as { id: string; status?: string }[]) - } - return { ok: true, result } + return { ok: true, result: await client.request(method, params) } } catch (err) { // Surfaced as a value rather than a rejection so the renderer sees // nobilis's own error text (which is often the actionable part - "account diff --git a/src/main/notifications.ts b/src/main/notifications.ts index e969395..0441c86 100644 --- a/src/main/notifications.ts +++ b/src/main/notifications.ts @@ -35,8 +35,6 @@ export class Notifier { /** Source path -> transcoded PNG, so a repeat sender is converted once. */ private transcoded = new Map() - /** Accounts currently set to Do Not Disturb. */ - private dndAccounts = new Set() constructor( private prefs: Prefs, @@ -46,11 +44,6 @@ export class Notifier { private renderer: () => WebContents | null = () => null ) {} - /** Mirrors each account's status, so DND can be enforced here. */ - trackAccounts(accounts: { id: string; status?: string }[]): void { - this.dndAccounts = new Set(accounts.filter((a) => a.status === 'dnd').map((a) => a.id)) - } - trackBuffer(buffer: ChatBuffer, removed: boolean): void { if (removed) this.buffers.delete(buffer.id) else this.buffers.set(buffer.id, buffer) @@ -67,12 +60,6 @@ export class Notifier { * all; see isMuted for why. */ private isMuted(accountId: string, bufferId: string): boolean { - // Do Not Disturb is a statement about the person rather than any one - // connection, so it silences every account regardless of which one it was - // set from. Held in main so it keeps working with the window closed, - // which is the whole point of the setting. - if (this.dndAccounts.size > 0) return true - const muted = this.prefs.get('mutedBuffers', []) if (muted.includes(bufferId)) return true diff --git a/src/renderer/src/components/UserFooter.tsx b/src/renderer/src/components/UserFooter.tsx index ea4d957..c43397a 100644 --- a/src/renderer/src/components/UserFooter.tsx +++ b/src/renderer/src/components/UserFooter.tsx @@ -1,6 +1,6 @@ import { ContextMenu, useContextMenu } from './ContextMenu' import { Icon, MaskIcon } from './Icon' -import { useChat, useStore } from '../state/hooks' +import { useStore } from '../state/hooks' import { nickColor, resolveMediaUrl, serviceIcon } from '../lib/util' import type { Account } from '../../../shared/wire' @@ -9,33 +9,22 @@ import type { Account } from '../../../shared/wire' * channel list - and the way to change how you are presenting. * * Per account rather than global because that is what the underlying status - * is: each protocol carries its own, and only Do Not Disturb reaches across - * all of them (by silencing notifications, which is this app's own doing - * rather than anything a server is told). + * is: each protocol carries its own. */ -export type Status = 'online' | 'idle' | 'dnd' +export type Status = 'online' | 'idle' -const STATUSES: { id: Status; label: string; glyph: string; note?: string }[] = [ +const STATUSES: { id: Status; label: string; glyph: string }[] = [ { id: 'online', label: 'Online', glyph: 'circle' }, - { id: 'idle', label: 'Idle', glyph: 'dark_mode' }, - { - id: 'dnd', - label: 'Do Not Disturb', - glyph: 'do_not_disturb_on', - note: 'Silences notifications everywhere' - } + { id: 'idle', label: 'Idle', glyph: 'dark_mode' } ] export function statusColor(status: string): string { - if (status === 'idle') return 'var(--warning)' - if (status === 'dnd') return 'var(--error)' - return 'var(--success)' + return status === 'idle' ? 'var(--warning)' : 'var(--success)' } export function UserFooter({ account }: { account?: Account }): JSX.Element { const store = useStore() - const accounts = useChat((s) => s.accounts) const { menu, open, close } = useContextMenu() // With no account selected there is nobody to show, but the footer still @@ -46,13 +35,7 @@ export function UserFooter({ account }: { account?: Account }): JSX.Element { const service = serviceIcon(account.service) const name = account.displayName || account.id - const setStatus = (next: Status): void => { - // DND is a statement about the person, not the connection, so it goes to - // every account at once. The others are per-account, matching where the - // user set them from. - const targets = next === 'dnd' || status === 'dnd' ? accounts : [account] - for (const a of targets) void store.setAccountStatus(a.id, next) - } + const setStatus = (next: Status): void => void store.setAccountStatus(account.id, next) return ( <> diff --git a/src/renderer/src/state/store.ts b/src/renderer/src/state/store.ts index 7f57a15..8ddfed9 100644 --- a/src/renderer/src/state/store.ts +++ b/src/renderer/src/state/store.ts @@ -256,7 +256,7 @@ export class ChatStore { * disconnected account or a protocol with no presence concept the answer is * no - showing it as set anyway would be a lie. */ - async setAccountStatus(accountId: string, status: 'online' | 'idle' | 'dnd'): Promise { + async setAccountStatus(accountId: string, status: 'online' | 'idle'): Promise { try { await window.moho.rpc('setAccountStatus', { accountId, status }) await this.refreshAccounts() diff --git a/src/shared/wire.ts b/src/shared/wire.ts index d0ac63f..8e861ab 100644 --- a/src/shared/wire.ts +++ b/src/shared/wire.ts @@ -6,7 +6,7 @@ export interface Account { service: 'irc' | 'discord' | 'sockchat' | 'matrix' | 'jabber' | 'slack' displayName: string /** - * How the user is presenting: "online" | "idle" | "dnd". Distinct from + * How the user is presenting: "online" | "idle". Distinct from * `state`, which is whether the connection is up. */ status?: string