Files
shadcn-slint/web/src/pages/Settings.tsx
2026-01-30 12:56:00 +08:00

253 lines
7.5 KiB
TypeScript

import {ScrollableBody, ContentHeader, Container} from "@/components/app-content.tsx";
import {BadgeCheckIcon, SettingsIcon} from "lucide-react";
import {Item, ItemActions, ItemContent, ItemMedia, ItemTitle} from "@/components/ui/item.tsx";
import {Switch} from "@/components/ui/switch.tsx";
import {Button} from "@/components/ui/button.tsx";
import {TunConfigModal} from "@/components/settings/tun-config-modal.tsx";
import {useState} from "react";
import {TunConfig} from "@/lib/types.ts";
export function Settings() {
const [tunModalOpen, setTunModalOpen] = useState(false);
// 示例 TUN 配置数据
const [tunConfig, setTunConfig] = useState<TunConfig>({
enable: false,
stack: 'system',
dnsHijack: ['0.0.0.0:53'],
autoRoute: true,
autoDetectInterface: true,
mtu: 9000,
});
const handleSaveTunConfig = (newConfig: TunConfig) => {
setTunConfig(newConfig);
// TODO: 这里应该调用 Tauri 命令保存配置到后端
console.log('保存 TUN 配置:', newConfig);
};
const config = {
auto_route: false,
device: "",
dns_hijack: [],
enable: false,
mtu: 0,
stack: 'System',
strict_route: false
}
if (!config) {
return (
<ScrollableBody>
<ContentHeader>Settings</ContentHeader>
<div className="p-4">Loading...</div>
</ScrollableBody>
);
}
return (
<ScrollableBody>
<ContentHeader>Settings</ContentHeader>
<Container className={'py-2 px-4'}>
<span>App </span>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span></span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Switch/>
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span></span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Switch/>
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span>Clash </span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Switch/>
</ItemActions>
</Item>
</Container>
<Container className={'py-2 px-4 mt-2'}>
<span>Clash </span>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle className="flex items-center gap-1.5">
<span></span>
<Button
size={'icon-sm'}
variant={'ghost'}
onClick={() => setTunModalOpen(true)}
className="h-5 w-5 p-0"
>
<SettingsIcon className="size-3.5 text-muted-foreground hover:text-foreground transition-colors" />
</Button>
</ItemTitle>
</ItemContent>
<ItemActions>
<Switch
checked={tunConfig.enable}
onCheckedChange={(checked) => {
setTunConfig({ ...tunConfig, enable: checked });
}}
/>
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span></span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Switch/>
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span>Ipv6</span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Switch/>
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span></span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Switch/>
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span></span>
</ItemTitle>
</ItemContent>
<ItemActions>
INFO
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span></span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Button size={'icon-sm'} variant={'link'}>7890</Button>
</ItemActions>
</Item>
</Container>
<Container>
<span></span>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span>App </span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Button size={'icon-sm'} variant={'link'}>7890</Button>
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span>App </span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Button size={'icon-sm'} variant={'link'}>7890</Button>
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span></span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Button size={'icon-sm'} variant={'link'}>7890</Button>
</ItemActions>
</Item>
<Item className={'py-2 px-0'} variant="default" size="sm">
<ItemMedia>
<BadgeCheckIcon className="size-5"/>
</ItemMedia>
<ItemContent>
<ItemTitle>
<span>App </span>
</ItemTitle>
</ItemContent>
<ItemActions>
<Button size={'icon-sm'} variant={'link'}>7890</Button>
</ItemActions>
</Item>
</Container>
<TunConfigModal
open={tunModalOpen}
onOpenChange={setTunModalOpen}
config={tunConfig}
onSave={handleSaveTunConfig}
/>
</ScrollableBody>
);
}