Files
im0o 8eb98e2e9a 设置页重做:配置文件下载上传、内核参数、资源、免责声明
配置每次落盘都打顶层 patchbay: 标记(盐加版本的哈希)。内核忽略未知
顶层键(yaml.Unmarshal 没开严格模式,config/config.go:612)。刻意不对
内容做哈希:本项目只接管部分段落,手改其余段落是正常用法,内容哈希
会把合法手改判成无效。上传配置时靠标记分流:有标记的确认后替换,
没有的用更重的措辞确认导入;两者都走 config-store 完整保护链路
(新端点 POST /api/config/import)。自动备份列表从界面撤下,改成
下载当前配置 + 拖放上传。

内核参数一组编辑五个老式顶层端口和 keep-alive-interval(config.go:444,
整数秒),走带基准指纹的保存链路。资源一组接 POST /configs/geo
(同步接口,透传给了 300 秒超时)。测速地址成为本地偏好,延迟测试
读它;prefs 模块顶层的浏览器全局加了存在性守卫——api.ts 开始引用
prefs,而 bun test 环境没有 localStorage。

退出登录挪到侧栏底部;密度设置从设置页撤下(侧栏按钮还在);
免责声明和关于做成子页(左上角返回),登录页输入框下加同一份
免责声明的弹层入口。
2026-08-12 01:01:33 +08:00

67 lines
2.3 KiB
TypeScript

/**
* 界面偏好,存在 localStorage 里。
*
* 密度:工具栏和导航是只显示图标,还是图标加文字。
* 默认是「完整」——这个工具是隔一阵子才动一次的,纯图标对偶尔来一次的人不友好;
* 想收拢的人用侧栏底部的按钮切。
*
* 主题:跟随系统、浅色、深色。默认跟随系统。
*
* localStorage 和 document 都加了存在性守卫:api.ts 引用这里(测速地址),
* 而 api.ts 被 bun test 环境里跑的模块间接引用——那里没有浏览器全局,
* 模块顶层直接碰它们会把整个测试文件炸掉。
*/
import { ref, watch } from 'vue'
const storage = typeof localStorage === 'undefined' ? null : localStorage
export type Density = 'full' | 'compact'
const KEY = 'patchbay.density'
const stored = storage?.getItem(KEY)
export const density = ref<Density>(stored === 'compact' ? 'compact' : 'full')
watch(density, (value) => {
storage?.setItem(KEY, value)
})
export function toggleDensity(): void {
density.value = density.value === 'full' ? 'compact' : 'full'
}
/** 测延迟用的目标地址。204 空响应的端点最合适,默认值全球都有部署。 */
export const DEFAULT_TEST_URL = 'https://www.gstatic.com/generate_204'
const TEST_URL_KEY = 'patchbay.test-url'
export const testUrl = ref(storage?.getItem(TEST_URL_KEY) || DEFAULT_TEST_URL)
watch(testUrl, (value) => {
if (value.trim() === '' || value === DEFAULT_TEST_URL) storage?.removeItem(TEST_URL_KEY)
else storage?.setItem(TEST_URL_KEY, value.trim())
})
export type Theme = 'system' | 'light' | 'dark'
const THEME_KEY = 'patchbay.theme'
const storedTheme = storage?.getItem(THEME_KEY)
export const theme = ref<Theme>(
storedTheme === 'light' || storedTheme === 'dark' ? storedTheme : 'system',
)
// 显式选了浅色或深色就在 <html> 上标出来:tokens.css 里 :root[data-theme=…] 的权重
// 高于 :root 和媒体查询里的 :root,压过系统偏好。跟随系统则不加标记,交回给媒体查询,
// 这样系统主题切换时界面仍然跟着变。
watch(
theme,
(value) => {
storage?.setItem(THEME_KEY, value)
if (typeof document === 'undefined') return
if (value === 'system') document.documentElement.removeAttribute('data-theme')
else document.documentElement.setAttribute('data-theme', value)
},
{ immediate: true },
)