fix(desktop): add a HUD layout reset control
A persisted tall/narrow size has no way out on Linux. Put a reset next to Exit HUD so the default size (and position, where the compositor allows it) is one click away. Co-authored-by: Shawn Wang <32839114+enwaiax@users.noreply.github.com>
This commit is contained in:
committed by
brooklyn!
parent
b595fcd5e1
commit
d467da9100
@@ -72,6 +72,7 @@ describe('HUD mode', () => {
|
||||
expect(screen.getByLabelText('Voice dictation')).toBeTruthy()
|
||||
expect(screen.getByLabelText('Read replies aloud')).toBeTruthy()
|
||||
expect(screen.queryByLabelText('Exit HUD mode')).toBeNull()
|
||||
expect(screen.queryByLabelText('Reset HUD size and position')).toBeNull()
|
||||
expect(screen.queryByLabelText('Voice')).toBeNull()
|
||||
})
|
||||
|
||||
@@ -80,6 +81,7 @@ describe('HUD mode', () => {
|
||||
renderControls()
|
||||
|
||||
expect(screen.getByLabelText('Voice')).toBeTruthy()
|
||||
expect(screen.getByLabelText('Reset HUD size and position')).toBeTruthy()
|
||||
expect(screen.getByLabelText('Exit HUD mode')).toBeTruthy()
|
||||
|
||||
// Folded away, not duplicated — the whole point is the row's width back.
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useI18n } from '@/i18n'
|
||||
import { triggerHaptic } from '@/lib/haptics'
|
||||
import { AudioLines, Ear, EarOff, iconSize, Layers3, Loader2, Square, Volume2, VolumeX } from '@/lib/icons'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { $hudMode, closeHud } from '@/store/hud'
|
||||
import { $hudMode, closeHud, resetHudLayout } from '@/store/hud'
|
||||
import { $wakeWord, toggleWakeWord } from '@/store/wake-word'
|
||||
|
||||
import { ACTIVE_ICON_BTN, GHOST_ICON_BTN, PRIMARY_ICON_BTN } from './control-classes'
|
||||
@@ -173,27 +173,41 @@ export function ComposerControls({
|
||||
the surface, paid for in every state, for a control that is invisible
|
||||
until hovered. Here it costs no reserved space and sits with the other
|
||||
things you can press. */}
|
||||
{hudMode ? <ExitHudButton /> : null}
|
||||
{hudMode ? <HudWindowButtons /> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function ExitHudButton() {
|
||||
function HudWindowButtons() {
|
||||
const { t } = useI18n()
|
||||
|
||||
return (
|
||||
<Tip label={t.titlebar.exitHud}>
|
||||
<Button
|
||||
aria-label={t.titlebar.exitHud}
|
||||
className={cn(GHOST_ICON_BTN, 'p-0')}
|
||||
onClick={closeHud}
|
||||
size="icon"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
>
|
||||
<Codicon name="screen-normal" size="0.875rem" />
|
||||
</Button>
|
||||
</Tip>
|
||||
<>
|
||||
<Tip label={t.titlebar.resetHudLayout}>
|
||||
<Button
|
||||
aria-label={t.titlebar.resetHudLayout}
|
||||
className={cn(GHOST_ICON_BTN, 'p-0')}
|
||||
onClick={resetHudLayout}
|
||||
size="icon"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
>
|
||||
<Codicon name="discard" size="0.875rem" />
|
||||
</Button>
|
||||
</Tip>
|
||||
<Tip label={t.titlebar.exitHud}>
|
||||
<Button
|
||||
aria-label={t.titlebar.exitHud}
|
||||
className={cn(GHOST_ICON_BTN, 'p-0')}
|
||||
onClick={closeHud}
|
||||
size="icon"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
>
|
||||
<Codicon name="screen-normal" size="0.875rem" />
|
||||
</Button>
|
||||
</Tip>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -218,6 +218,7 @@ export const ar = defineLocale({
|
||||
openStarmap: 'فتح خريطة الذاكرة',
|
||||
enterHud: 'وضع HUD',
|
||||
exitHud: 'إنهاء وضع HUD',
|
||||
resetHudLayout: 'إعادة تعيين حجم HUD وموضعه',
|
||||
layoutEditor: 'محرر التخطيط',
|
||||
layoutEditorTitle: modifier => `محرر التخطيط — انقر مع ${modifier} لإعادة ضبط التخطيط`
|
||||
},
|
||||
|
||||
@@ -251,6 +251,7 @@ export const en: Translations = {
|
||||
openStarmap: 'Open memory graph',
|
||||
enterHud: 'HUD mode',
|
||||
exitHud: 'Exit HUD mode',
|
||||
resetHudLayout: 'Reset HUD size and position',
|
||||
layoutEditor: 'Layout editor',
|
||||
layoutEditorTitle: mod => `Layout editor — ${mod}-click resets the layout`
|
||||
},
|
||||
|
||||
@@ -249,7 +249,8 @@ export const ja = defineLocale({
|
||||
muteHaptics: '触覚フィードバックをオフ',
|
||||
unmuteHaptics: '触覚フィードバックをオン',
|
||||
openSettings: '設定を開く',
|
||||
openStarmap: 'メモリグラフを開く'
|
||||
openStarmap: 'メモリグラフを開く',
|
||||
resetHudLayout: 'HUD のサイズと位置をリセット'
|
||||
},
|
||||
|
||||
language: {
|
||||
|
||||
@@ -287,6 +287,7 @@ export interface Translations {
|
||||
openStarmap: string
|
||||
enterHud: string
|
||||
exitHud: string
|
||||
resetHudLayout: string
|
||||
layoutEditor: string
|
||||
layoutEditorTitle: (modifier: string) => string
|
||||
}
|
||||
|
||||
@@ -241,7 +241,8 @@ export const zhHant = defineLocale({
|
||||
muteHaptics: '靜音觸感回饋',
|
||||
unmuteHaptics: '開啟觸感回饋',
|
||||
openSettings: '開啟設定',
|
||||
openStarmap: '開啟記憶圖譜'
|
||||
openStarmap: '開啟記憶圖譜',
|
||||
resetHudLayout: '重設 HUD 大小和位置'
|
||||
},
|
||||
|
||||
language: {
|
||||
|
||||
@@ -244,6 +244,7 @@ export const zh: Translations = {
|
||||
openStarmap: '打开记忆图谱',
|
||||
enterHud: 'HUD 模式',
|
||||
exitHud: '退出 HUD 模式',
|
||||
resetHudLayout: '重置 HUD 大小和位置',
|
||||
layoutEditor: '布局编辑器',
|
||||
layoutEditorTitle: mod => `布局编辑器 — ${mod} 点击重置布局`
|
||||
},
|
||||
|
||||
@@ -4,16 +4,17 @@ import { $activeGatewayProfile } from '@/store/profile'
|
||||
import { $sessions } from '@/store/session'
|
||||
import type { SessionInfo } from '@/types/hermes'
|
||||
|
||||
import { $hudActive, $hudSession, openHud } from './hud'
|
||||
import { $hudActive, $hudSession, openHud, resetHudLayout } from './hud'
|
||||
|
||||
const desktopWindow = window as unknown as { hermesDesktop?: Window['hermesDesktop'] }
|
||||
const initialHermesDesktop = desktopWindow.hermesDesktop
|
||||
|
||||
const open = vi.fn().mockResolvedValue({ ok: true })
|
||||
const resetLayout = vi.fn().mockResolvedValue({ ok: true })
|
||||
|
||||
function installBridge() {
|
||||
desktopWindow.hermesDesktop = {
|
||||
hud: { open }
|
||||
hud: { open, resetLayout }
|
||||
} as unknown as Window['hermesDesktop']
|
||||
}
|
||||
|
||||
@@ -23,6 +24,7 @@ function session(overrides: Partial<SessionInfo>): SessionInfo {
|
||||
|
||||
beforeEach(() => {
|
||||
open.mockClear()
|
||||
resetLayout.mockClear()
|
||||
installBridge()
|
||||
$hudActive.set(false)
|
||||
$hudSession.set(null)
|
||||
@@ -38,6 +40,14 @@ afterEach(() => {
|
||||
}
|
||||
})
|
||||
|
||||
describe('resetHudLayout', () => {
|
||||
it('uses the native HUD recovery capability', () => {
|
||||
resetHudLayout()
|
||||
|
||||
expect(resetLayout).toHaveBeenCalledOnce()
|
||||
})
|
||||
})
|
||||
|
||||
describe('openHud profile targeting (#82285)', () => {
|
||||
it('carries the session-stamped profile when the target belongs to another profile', () => {
|
||||
$sessions.set([session({ id: 'abc', profile: 'work' })])
|
||||
|
||||
@@ -87,6 +87,11 @@ export function closeHud(): void {
|
||||
|
||||
export const toggleHud = (sessionId?: null | string) => ($hudActive.get() ? closeHud() : openHud(sessionId))
|
||||
|
||||
/** Restore the HUD's persisted geometry to its display-aware default. */
|
||||
export function resetHudLayout(): void {
|
||||
void window.hermesDesktop?.hud?.resetLayout?.()
|
||||
}
|
||||
|
||||
/** Tell main which session this HUD is on. Main holds it (the HUD's renderer
|
||||
* doesn't outlive the window) and hands it back in the close broadcast so the
|
||||
* app window knows what to re-home onto. */
|
||||
|
||||
Reference in New Issue
Block a user