CI / Build & Quality Checks (pull_request) Successful in 3m13s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 13s
CI / Playwright smoke (e2e) (pull_request) Successful in 18m14s
On desktops with no tray host (stock GNOME), "Keep running in the tray" hid the window with no icon to bring it back. Ask the desktop app (has_tray_host); without a tray, say so, focus "Quit when I close the window", and offer "Keep running in the background" as the secondary choice. Older desktop builds keep the current dialog. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
161 lines
5.7 KiB
TypeScript
161 lines
5.7 KiB
TypeScript
import React, { useCallback, useEffect, useState } from 'react';
|
|
import FocusTrap from 'focus-trap-react';
|
|
import {
|
|
Box,
|
|
Button,
|
|
Checkbox,
|
|
Dialog,
|
|
Header,
|
|
Overlay,
|
|
OverlayBackdrop,
|
|
OverlayCenter,
|
|
Text,
|
|
config,
|
|
} from 'folds';
|
|
import { invokeTauri, isTauri, tauriInvoke, useTauriEvent } from '../hooks/useTauri';
|
|
import { useModalStyle } from '../hooks/useModalStyle';
|
|
|
|
/**
|
|
* cinny-desktop #5: the first time the window is closed, ask whether Lotus Chat
|
|
* should keep running in the tray (calls, messages, notifications) or quit —
|
|
* and, in the same moment, whether it should start when you sign in. Asked
|
|
* once; changeable in Settings → General. The native side sends
|
|
* `lotus-close-requested` only while the choice is still "ask", and never
|
|
* during a call (a call always goes to the tray).
|
|
*/
|
|
export function CloseBehaviorPrompt() {
|
|
const [open, setOpen] = useState(false);
|
|
const [launchOnLogin, setLaunchOnLogin] = useState(false);
|
|
// [cinny-desktop #37] Stock GNOME has no tray host: "keep running in the
|
|
// tray" would hide the window with no icon to bring it back. Older desktop
|
|
// builds lack the command; assume a tray then (the old behaviour).
|
|
const [hasTray, setHasTray] = useState(true);
|
|
const modalStyle = useModalStyle(420);
|
|
|
|
// Tells the native side we're listening (see get_close_behavior).
|
|
useEffect(() => {
|
|
if (!isTauri()) return;
|
|
tauriInvoke()?.('get_close_behavior').catch(() => undefined);
|
|
}, []);
|
|
|
|
useTauriEvent('lotus-close-requested', () => {
|
|
const ask = tauriInvoke()?.('has_tray_host');
|
|
if (!ask) {
|
|
setOpen(true);
|
|
return;
|
|
}
|
|
ask
|
|
.then((v) => setHasTray(v !== false))
|
|
.catch(() => setHasTray(true))
|
|
.finally(() => setOpen(true));
|
|
});
|
|
|
|
const choose = useCallback(
|
|
(value: 'tray' | 'quit') => {
|
|
if (launchOnLogin) invokeTauri('plugin:autostart|enable');
|
|
setOpen(false);
|
|
invokeTauri('resolve_close_request', { value });
|
|
},
|
|
[launchOnLogin],
|
|
);
|
|
|
|
if (!open) return null;
|
|
return (
|
|
<Overlay open backdrop={<OverlayBackdrop />}>
|
|
<OverlayCenter>
|
|
<FocusTrap
|
|
focusTrapOptions={{
|
|
initialFocus: hasTray ? '#close-behavior-keep' : '#close-behavior-quit',
|
|
// Dismissing without choosing keeps the window open; the next close
|
|
// asks again.
|
|
onDeactivate: () => setOpen(false),
|
|
clickOutsideDeactivates: true,
|
|
}}
|
|
>
|
|
<Dialog
|
|
variant="Surface"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="close-behavior-title"
|
|
aria-describedby="close-behavior-body"
|
|
style={modalStyle}
|
|
>
|
|
<Header
|
|
style={{
|
|
padding: `0 ${config.space.S400}`,
|
|
borderBottomWidth: config.borderWidth.B300,
|
|
}}
|
|
variant="Surface"
|
|
size="500"
|
|
>
|
|
<Text as="h2" size="H4" id="close-behavior-title">
|
|
Keep Lotus Chat running?
|
|
</Text>
|
|
</Header>
|
|
<Box style={{ padding: config.space.S400 }} direction="Column" gap="400">
|
|
<Text priority="400" id="close-behavior-body">
|
|
{hasTray
|
|
? 'Lotus Chat can keep running in the system tray when you close this window, so messages, notifications and calls still reach you. Open it again from the tray icon.'
|
|
: "Your desktop doesn't show tray icons, so if Lotus Chat keeps running after you close this window, the only way back is to launch it again."}
|
|
</Text>
|
|
<Box as="label" alignItems="Center" gap="200" style={{ cursor: 'pointer' }}>
|
|
<Checkbox
|
|
size="300"
|
|
variant="Primary"
|
|
checked={launchOnLogin}
|
|
onClick={(e: React.MouseEvent<HTMLInputElement>) =>
|
|
setLaunchOnLogin(e.currentTarget.checked)
|
|
}
|
|
/>
|
|
<Text size="T300">Start Lotus Chat when I sign in to my computer</Text>
|
|
</Box>
|
|
<Box direction="Column" gap="200">
|
|
{hasTray ? (
|
|
<>
|
|
<Button
|
|
id="close-behavior-keep"
|
|
variant="Primary"
|
|
onClick={() => choose('tray')}
|
|
>
|
|
<Text size="B400">Keep running in the tray</Text>
|
|
</Button>
|
|
<Button
|
|
id="close-behavior-quit"
|
|
variant="Secondary"
|
|
fill="Soft"
|
|
onClick={() => choose('quit')}
|
|
>
|
|
<Text size="B400">Quit when I close the window</Text>
|
|
</Button>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Button
|
|
id="close-behavior-quit"
|
|
variant="Primary"
|
|
onClick={() => choose('quit')}
|
|
>
|
|
<Text size="B400">Quit when I close the window</Text>
|
|
</Button>
|
|
<Button
|
|
id="close-behavior-keep"
|
|
variant="Secondary"
|
|
fill="Soft"
|
|
onClick={() => choose('tray')}
|
|
>
|
|
<Text size="B400">Keep running in the background</Text>
|
|
</Button>
|
|
</>
|
|
)}
|
|
</Box>
|
|
<Text size="T200" priority="300">
|
|
You can change this in Settings → General.
|
|
</Text>
|
|
</Box>
|
|
</Dialog>
|
|
</FocusTrap>
|
|
</OverlayCenter>
|
|
</Overlay>
|
|
);
|
|
}
|