import clsx from "clsx"; import { z } from "zod"; import { useState, useEffect, useRef } from "react"; import { Link } from "react-router-dom"; import { invoke } from "@tauri-apps/api/tauri"; import { getVersion } from "@tauri-apps/api/app"; import { Button } from "@/components/ui/button"; import { ArrowLeft, Github, Globe, History, Save } from "lucide-react"; import { Input } from "@/components/ui/input"; import { Config, PlatformInfo } from "@/types"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { useToast } from "@/hooks/use-toast"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { getPlatformInfo } from "@/lib/platform-utils"; const DEFAULT_PORT = 3030; const settingsFormSchema = z.object({ port: z.number().min(3000, { message: "Port must be greater than 3000" }).max(3999, { message: "Port must be less than 3999" }), }) export default function SettingsPage() { const { toast } = useToast(); const [platformInfo, setPlatformInfo] = useState(null); const [appConfig, setAppConfig] = useState(null); const [appVersion, setAppVersion] = useState(null); const [isFormDirty, setIsFormDirty] = useState(false); const saveButtonRef = useRef(null); const settingsForm = useForm>({ resolver: zodResolver(settingsFormSchema), defaultValues: { port: DEFAULT_PORT, }, }); useEffect(() => { const subscription = settingsForm.watch((value) => { if (appConfig) { setIsFormDirty(value.port !== appConfig.port); } }); return () => subscription.unsubscribe(); }, [settingsForm, appConfig]); useEffect(() => { const getConfig = async () => { const config: Config = await invoke("get_config"); if (config) { setAppConfig(config); settingsForm.reset({ port: config.port }); } } getConfig().catch(console.error); }, [settingsForm]); useEffect(() => { getPlatformInfo().then(setPlatformInfo).catch(console.error); const getAppVersion = async () => { const version = await getVersion(); setAppVersion(version); } getAppVersion().catch(console.error); }, []) const updateConfig = async () => { try { const updatedConfig: Config = await invoke("update_config", { newConfig: { port: Number(settingsForm.getValues().port) } }); setAppConfig(updatedConfig); setIsFormDirty(false); toast({ title: "Settings updated" }); } catch (error) { console.error("Failed to update config:", error); toast({ title: "Failed to update settings", variant: "destructive" }); } } const resetConfig = async () => { try { const config: Config = await invoke("reset_config"); setAppConfig(config); settingsForm.reset({ port: config.port }); setIsFormDirty(false); toast({ title: "Using default settings" }); } catch (error) { console.error("Failed to reset config:", error); toast({ title: "Failed to reset settings", variant: "destructive" }); } } const isUsingDefaultConfig = appConfig?.port === DEFAULT_PORT; return (

Settings

{isUsingDefaultConfig ? "using default settings" : "reset to default"}

{isFormDirty ? "save changes" : "no changes to save"}

( Port { const value = e.target.value; field.onChange(value ? Number(value) : DEFAULT_PORT); }} onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); } }} /> The port to use for the websocket server )} />

PytubePP Helper | v{appVersion}-beta

© {new Date().getFullYear()} - MIT License - Made with ❤️ by Subhamoy

); }