Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions apps/desktop/src/app/settings/appearance-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion apps/desktop/src/components/Backdrop.tsx
Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -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) {
Expand Down Expand Up @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.',
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ export const ja = defineLocale({
`アプリ全体の文字と UI を拡大縮小します。Cmd/Ctrl と +、-、0 でも変更できます。現在: ${percent}%`,
translucencyTitle: 'ウィンドウの透過',
translucencyDesc: 'ウィンドウ全体を透過させてデスクトップを表示します。macOS と Windows のみ。',
backdropTitle: 'チャット背景',
backdropDesc: '会話の背後に表示される淡い彫像の画像。',
embedsTitle: 'インライン埋め込み',
embedsDesc:
'リッチプレビューは第三者サイト(YouTube、X など)から読み込まれます。確認は許可するまでプレースホルダーを表示し、常には自動で読み込み、オフはリンクのままにします。',
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/i18n/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/i18n/zh-hant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ export const zhHant = defineLocale({
`縮放整個應用程式的文字與介面。也可使用 Cmd/Ctrl 加 +、- 或 0 調整。目前:${percent}%`,
translucencyTitle: '視窗透明',
translucencyDesc: '讓整個視窗透出桌面。僅支援 macOS 與 Windows。',
backdropTitle: '聊天背景',
backdropDesc: '對話後方那張淡淡的雕像圖片。',
embedsTitle: '內嵌預覽',
embedsDesc:
'豐富預覽會從第三方網站(YouTube、X 等)載入。詢問會在你允許前顯示佔位符;一律會自動載入;關閉則保留純連結。',
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ export const zh: Translations = {
`缩放整个应用的文字和界面。也可使用 Cmd/Ctrl 加 +、- 或 0 调整。当前:${percent}%`,
translucencyTitle: '窗口透明',
translucencyDesc: '让整个窗口透出桌面。仅支持 macOS 和 Windows。',
backdropTitle: '聊天背景',
backdropDesc: '对话后方那张淡淡的雕像图片。',
embedsTitle: '内嵌预览',
embedsDesc:
'富预览会从第三方网站(YouTube、X 等)加载。询问会在你允许前显示占位符;总是会自动加载;关闭则保留纯链接。',
Expand Down
14 changes: 14 additions & 0 deletions apps/desktop/src/store/backdrop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { atom } from 'nanostores'

import { persistBoolean, storedBoolean } from '@/lib/storage'

const KEY = 'hermes.desktop.backdrop.v1'

/** Whether the faint statue image renders behind the chat transcript. */
export const $backdrop = atom(storedBoolean(KEY, true))

$backdrop.subscribe(on => persistBoolean(KEY, on))

export function setBackdrop(on: boolean) {
$backdrop.set(on)
}
Loading