Files
ztab/app/src/config/settingsPresets.ts
yinsx d025691180 1
2026-01-29 11:28:01 +08:00

201 lines
4.8 KiB
TypeScript

import { layoutConfig } from './layout';
export type SearchProvider = {
id: 'baidu' | 'bing' | 'google' | 'zhihu';
label: string;
url: string;
placeholder: string;
};
export const searchProviders: SearchProvider[] = [
{
id: 'baidu',
label: '百度',
url: 'https://www.baidu.com/s?wd=',
placeholder: '百度一下',
},
{
id: 'bing',
label: '必应',
url: 'https://www.bing.com/search?q=',
placeholder: '搜索必应',
},
{
id: 'google',
label: '谷歌',
url: 'https://www.google.com/search?q=',
placeholder: '搜索谷歌',
},
{
id: 'zhihu',
label: '知乎',
url: 'https://www.zhihu.com/search?q=',
placeholder: '知乎搜索',
},
];
export type SearchProviderId = SearchProvider['id'];
export const getSearchProvider = (id?: string) =>
searchProviders.find(item => item.id === id) ?? searchProviders[0];
export type ThemePreset = {
id: 'default' | 'warm' | 'sea' | 'forest';
label: string;
overlay: string;
image: string;
};
export const themePresets: ThemePreset[] = [
{
id: 'default',
label: '默认',
overlay: 'none',
image: "url('/bg.png')",
},
{
id: 'warm',
label: '暖阳',
overlay: 'linear-gradient(135deg, rgba(255, 185, 110, 0.32), rgba(255, 221, 149, 0.14))',
image: "url('/bg.png')",
},
{
id: 'sea',
label: '海盐',
overlay: 'linear-gradient(135deg, rgba(88, 200, 255, 0.3), rgba(183, 240, 255, 0.14))',
image: "url('/bg.png')",
},
{
id: 'forest',
label: '松林',
overlay: 'linear-gradient(135deg, rgba(96, 198, 137, 0.28), rgba(217, 247, 201, 0.12))',
image: "url('/bg.png')",
},
];
export type ThemePresetId = ThemePreset['id'];
export const getThemePreset = (id?: string) =>
themePresets.find(item => item.id === id) ?? themePresets[0];
const clamp = (value: number, min: number) => (value < min ? min : value);
const clampRange = (value: number, min: number, max: number) =>
Math.min(Math.max(value, min), max);
export type LayoutDensityPreset = {
value: number;
label: string;
cellSize: number;
gap: number;
};
const baseGrid = layoutConfig.grid;
const baseIcon = layoutConfig.icon;
export const layoutDensityPresets: LayoutDensityPreset[] = [
{
value: 1,
label: '宽松',
cellSize: baseGrid.cellSize + 16,
gap: baseGrid.gap + 10,
},
{
value: 2,
label: '标准',
cellSize: baseGrid.cellSize,
gap: baseGrid.gap,
},
{
value: 3,
label: '紧凑',
cellSize: clamp(baseGrid.cellSize - 18, 76),
gap: clamp(baseGrid.gap - 6, 8),
},
{
value: 4,
label: '更紧凑',
cellSize: clamp(baseGrid.cellSize - 32, 64),
gap: clamp(baseGrid.gap - 10, 4),
},
];
export const layoutDensityRange = {
min: 1,
max: 4,
step: 0.1,
default: 2,
};
export const getLayoutDensityPreset = (value?: number) => {
const normalized = clampRange(
typeof value === 'number' ? value : layoutDensityRange.default,
layoutDensityRange.min,
layoutDensityRange.max
);
const lower = Math.floor(normalized);
const upper = Math.ceil(normalized);
if (lower === upper) {
return layoutDensityPresets[lower - 1] ?? layoutDensityPresets[1];
}
const lowerPreset = layoutDensityPresets[lower - 1] ?? layoutDensityPresets[0];
const upperPreset = layoutDensityPresets[upper - 1] ??
layoutDensityPresets[layoutDensityPresets.length - 1];
const t = (normalized - lower) / (upper - lower);
return {
value: normalized,
label: t < 0.5 ? lowerPreset.label : upperPreset.label,
cellSize: Math.round(lowerPreset.cellSize + (upperPreset.cellSize - lowerPreset.cellSize) * t),
gap: Math.round(lowerPreset.gap + (upperPreset.gap - lowerPreset.gap) * t),
};
};
export const iconDensityRange = {
min: 0,
max: 50,
step: 1,
default: 25,
};
const iconDensityScaleRange = {
loose: 2,
dense: 0,
};
export const getIconDensityScale = (value?: number) => {
const normalized = clampRange(
typeof value === 'number' ? value : iconDensityRange.default,
iconDensityRange.min,
iconDensityRange.max
);
const ease = (t: number) => Math.pow(t, 0.5);
if (normalized === iconDensityRange.default) {
return 1;
}
if (normalized < iconDensityRange.default) {
// Smaller slider value = denser布局
const t = (iconDensityRange.default - normalized) /
(iconDensityRange.default - iconDensityRange.min);
return 1 - ease(t) * (1 - iconDensityScaleRange.dense);
}
const t = (normalized - iconDensityRange.default) /
(iconDensityRange.max - iconDensityRange.default);
return 1 + ease(t) * (iconDensityScaleRange.loose - 1);
};
export const iconSizeRange = {
min: 70,
max: 100,
step: 1,
default: Math.round(
((baseGrid.cellSize - baseIcon.padding * 2) / baseGrid.cellSize) * 100
),
};
export const iconRadiusRange = {
min: 0,
max: 24,
step: 1,
default: baseIcon.radius,
};