fix(desktop): hydrate Focus Assist on mount; thread-aware toast quick reply
CI / Build & Quality Checks (push) Canceled after 0s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Secret scan (gitleaks) (push) Canceled after 0s
CI / Docker image build & smoke test (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s
CI / Build & Quality Checks (push) Canceled after 0s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Secret scan (gitleaks) (push) Canceled after 0s
CI / Docker image build & smoke test (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s
- useTauriFocusAssist queries the new `get_focus_assist` command on mount. The native poll's first reading is emitted during app setup, before the page listens, and the atom resets on every reload — so with Focus Assist already on, notifications leaked until the OS state flipped (cinny-desktop #15). - The toast quick reply takes the real `threadId` from the notification data and replies inside the thread (cinny-desktop #17). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f5ee3c0d0e
commit
3b6de2fdac
@@ -1,6 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { focusAssistActiveAtom } from '../state/focusAssist';
|
||||
import { useTauriEvent } from './useTauri';
|
||||
import { tauriInvoke, useTauriEvent } from './useTauri';
|
||||
|
||||
/** Detail shape of the `focus-assist-changed` event emitted by the native side. */
|
||||
type FocusAssistChangedDetail = {
|
||||
@@ -21,4 +22,16 @@ export function useTauriFocusAssist(): void {
|
||||
useTauriEvent<FocusAssistChangedDetail>('focus-assist-changed', ({ active }) =>
|
||||
setFocusAssist(active),
|
||||
);
|
||||
|
||||
// Hydrate on mount. The native poll only emits on a transition, and its first
|
||||
// reading lands during app setup before this page is listening — so with Focus
|
||||
// Assist already on at launch (or after a reload) notifications leaked until
|
||||
// the OS state next flipped (cinny-desktop #15). `null` = no reading yet.
|
||||
useEffect(() => {
|
||||
tauriInvoke()?.('get_focus_assist')
|
||||
.then((active) => {
|
||||
if (typeof active === 'boolean') setFocusAssist(active);
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}, [setFocusAssist]);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ interface ActivateDetail {
|
||||
/** Payload of the `lotus-notification-reply` event (the inline reply box). */
|
||||
interface ReplyDetail {
|
||||
roomId?: string;
|
||||
/** Set for a thread notification: the reply goes into that thread. */
|
||||
threadId?: string;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
@@ -36,12 +38,14 @@ export function useTauriToastActions(): void {
|
||||
if (path) navigate(path);
|
||||
});
|
||||
|
||||
useTauriEvent<ReplyDetail>('lotus-notification-reply', ({ roomId, text }) => {
|
||||
useTauriEvent<ReplyDetail>('lotus-notification-reply', ({ roomId, threadId, text }) => {
|
||||
// `roomId` is the real room id carried in the notification data, never the
|
||||
// coalescing tag (`room:thread`, `lotus-invites`) — cinny-desktop #17.
|
||||
if (!roomId || !text) return;
|
||||
// #79 — a quick-reply failure (offline, no send permission, etc.) used to
|
||||
// be swallowed with no feedback, leaving the user believing it was sent.
|
||||
// Surface it via the in-app error toast instead.
|
||||
mx.sendMessage(roomId, { msgtype: MsgType.Text, body: text }).catch(() => {
|
||||
mx.sendMessage(roomId, threadId ?? null, { msgtype: MsgType.Text, body: text }).catch(() => {
|
||||
setToast(
|
||||
createErrorToast(
|
||||
'Your quick reply could not be sent. Please try again.',
|
||||
|
||||
Reference in New Issue
Block a user