mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-21 15:41:15 +00:00
feat(desktop): add a chat backdrop on/off toggle
The faint statue backdrop behind the transcript was only switchable via the DEV-only leva panel. Add a persisted Appearance toggle (default on) so users can hide it; the Backdrop simply skips rendering when off.
This commit is contained in:
parent
7e84d2b5a4
commit
1813d3046c
8 changed files with 56 additions and 1 deletions
|
|
@ -12,6 +12,7 @@ import { Check, Download, Loader2, Palette, Trash2 } from '@/lib/icons'
|
|||
import { selectableCardClass } from '@/lib/selectable-card'
|
||||
import { normalize } from '@/lib/text'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { $backdrop, setBackdrop } from '@/store/backdrop'
|
||||
import { $embedAllowed, $embedMode, clearEmbedAllowed, type EmbedMode, setEmbedMode } from '@/store/embed-consent'
|
||||
import { $activeGatewayProfile, $profiles, normalizeProfileKey } from '@/store/profile'
|
||||
import { $toolViewMode, setToolViewMode } from '@/store/tool-view'
|
||||
|
|
@ -248,6 +249,7 @@ export function AppearanceSettings() {
|
|||
const embedMode = useStore($embedMode)
|
||||
const embedAllowed = useStore($embedAllowed)
|
||||
const translucency = useStore($translucency)
|
||||
const backdrop = useStore($backdrop)
|
||||
const installs = useStore($marketplaceInstalls)
|
||||
const profiles = useStore($profiles)
|
||||
const activeProfileKey = normalizeProfileKey(useStore($activeGatewayProfile))
|
||||
|
|
@ -451,6 +453,24 @@ export function AppearanceSettings() {
|
|||
title={a.translucencyTitle}
|
||||
/>
|
||||
|
||||
<ListRow
|
||||
action={
|
||||
<SegmentedControl
|
||||
onChange={id => {
|
||||
triggerHaptic('selection')
|
||||
setBackdrop(id === 'on')
|
||||
}}
|
||||
options={[
|
||||
{ id: 'off', label: t.common.off },
|
||||
{ id: 'on', label: t.common.on }
|
||||
]}
|
||||
value={backdrop ? 'on' : 'off'}
|
||||
/>
|
||||
}
|
||||
description={a.backdropDesc}
|
||||
title={a.backdropTitle}
|
||||
/>
|
||||
|
||||
<ListRow
|
||||
action={
|
||||
<SegmentedControl
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { useStore } from '@nanostores/react'
|
||||
import { Leva, useControls } from 'leva'
|
||||
import { type CSSProperties, useEffect, useState } from 'react'
|
||||
|
||||
import { $backdrop } from '@/store/backdrop'
|
||||
|
||||
const BLEND_MODES = [
|
||||
'normal',
|
||||
'multiply',
|
||||
|
|
@ -25,6 +28,7 @@ const assetPath = (path: string) => `${import.meta.env.BASE_URL}${path.replace(/
|
|||
|
||||
export function Backdrop() {
|
||||
const [controlsOpen, setControlsOpen] = useState(false)
|
||||
const on = useStore($backdrop)
|
||||
|
||||
useEffect(() => {
|
||||
if (!import.meta.env.DEV) {
|
||||
|
|
@ -87,7 +91,7 @@ export function Backdrop() {
|
|||
<>
|
||||
<Leva collapsed hidden={!import.meta.env.DEV || !controlsOpen} titleBar={{ title: 'backdrop', drag: true }} />
|
||||
|
||||
{statue.enabled && (
|
||||
{on && statue.enabled && (
|
||||
<div
|
||||
aria-hidden
|
||||
className="pointer-events-none absolute inset-0 z-2"
|
||||
|
|
|
|||
|
|
@ -392,6 +392,8 @@ export const en: Translations = {
|
|||
`Scales text and controls across the whole app. Cmd/Ctrl with +, - and 0 also works. Current: ${percent}%.`,
|
||||
translucencyTitle: 'Window Translucency',
|
||||
translucencyDesc: 'See your desktop through the whole window. macOS and Windows only.',
|
||||
backdropTitle: 'Chat Backdrop',
|
||||
backdropDesc: 'The faint statue image behind the conversation.',
|
||||
embedsTitle: 'Inline Embeds',
|
||||
embedsDesc:
|
||||
'Rich previews load from third-party sites (YouTube, X, …). Ask shows a placeholder until you allow each one; Always loads them automatically; Off keeps plain links.',
|
||||
|
|
|
|||
|
|
@ -297,6 +297,8 @@ export const ja = defineLocale({
|
|||
`アプリ全体の文字と UI を拡大縮小します。Cmd/Ctrl と +、-、0 でも変更できます。現在: ${percent}%`,
|
||||
translucencyTitle: 'ウィンドウの透過',
|
||||
translucencyDesc: 'ウィンドウ全体を透過させてデスクトップを表示します。macOS と Windows のみ。',
|
||||
backdropTitle: 'チャット背景',
|
||||
backdropDesc: '会話の背後に表示される淡い彫像の画像。',
|
||||
embedsTitle: 'インライン埋め込み',
|
||||
embedsDesc:
|
||||
'リッチプレビューは第三者サイト(YouTube、X など)から読み込まれます。確認は許可するまでプレースホルダーを表示し、常には自動で読み込み、オフはリンクのままにします。',
|
||||
|
|
|
|||
|
|
@ -311,6 +311,8 @@ export interface Translations {
|
|||
uiScaleDesc: (percent: number) => string
|
||||
translucencyTitle: string
|
||||
translucencyDesc: string
|
||||
backdropTitle: string
|
||||
backdropDesc: string
|
||||
embedsTitle: string
|
||||
embedsDesc: string
|
||||
embedsAsk: string
|
||||
|
|
|
|||
|
|
@ -290,6 +290,8 @@ export const zhHant = defineLocale({
|
|||
`縮放整個應用程式的文字與介面。也可使用 Cmd/Ctrl 加 +、- 或 0 調整。目前:${percent}%`,
|
||||
translucencyTitle: '視窗透明',
|
||||
translucencyDesc: '讓整個視窗透出桌面。僅支援 macOS 與 Windows。',
|
||||
backdropTitle: '聊天背景',
|
||||
backdropDesc: '對話後方那張淡淡的雕像圖片。',
|
||||
embedsTitle: '內嵌預覽',
|
||||
embedsDesc:
|
||||
'豐富預覽會從第三方網站(YouTube、X 等)載入。詢問會在你允許前顯示佔位符;一律會自動載入;關閉則保留純連結。',
|
||||
|
|
|
|||
|
|
@ -381,6 +381,8 @@ export const zh: Translations = {
|
|||
`缩放整个应用的文字和界面。也可使用 Cmd/Ctrl 加 +、- 或 0 调整。当前:${percent}%`,
|
||||
translucencyTitle: '窗口透明',
|
||||
translucencyDesc: '让整个窗口透出桌面。仅支持 macOS 和 Windows。',
|
||||
backdropTitle: '聊天背景',
|
||||
backdropDesc: '对话后方那张淡淡的雕像图片。',
|
||||
embedsTitle: '内嵌预览',
|
||||
embedsDesc:
|
||||
'富预览会从第三方网站(YouTube、X 等)加载。询问会在你允许前显示占位符;总是会自动加载;关闭则保留纯链接。',
|
||||
|
|
|
|||
21
apps/desktop/src/store/backdrop.ts
Normal file
21
apps/desktop/src/store/backdrop.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Chat backdrop image (the faint statue behind the transcript). One boolean,
|
||||
* on by default. Purely presentational renderer state — the `Backdrop`
|
||||
* component just skips rendering when it's off.
|
||||
*/
|
||||
|
||||
import { atom } from 'nanostores'
|
||||
|
||||
import { persistBoolean, storedBoolean } from '@/lib/storage'
|
||||
|
||||
const KEY = 'hermes.desktop.backdrop.v1'
|
||||
|
||||
export const $backdrop = atom<boolean>(typeof window === 'undefined' ? true : storedBoolean(KEY, true))
|
||||
|
||||
export function setBackdrop(on: boolean): void {
|
||||
$backdrop.set(on)
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
$backdrop.subscribe(on => persistBoolean(KEY, on))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue