mirror of
https://github.com/upscayl/upscayl.git
synced 2026-04-25 03:00:05 -04:00
Add language validation
This commit is contained in:
145
renderer/components/main-content/onboarding-dialog.tsx
Normal file
145
renderer/components/main-content/onboarding-dialog.tsx
Normal file
@@ -0,0 +1,145 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "../ui/dialog";
|
||||
|
||||
type OnboardingStep = {
|
||||
title: string;
|
||||
description: string;
|
||||
type: "info" | "settings";
|
||||
settings?: {
|
||||
type: "switch" | "input";
|
||||
label: string;
|
||||
key: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
const onboardingSteps: OnboardingStep[] = [
|
||||
{
|
||||
title: "Welcome to Upscayl 🎉",
|
||||
description: "Let's get you started with a few quick steps.",
|
||||
type: "info",
|
||||
},
|
||||
{
|
||||
title: "Choose Your Preferences",
|
||||
description: "Configure your initial settings.",
|
||||
type: "settings",
|
||||
settings: [
|
||||
{
|
||||
type: "switch",
|
||||
label: "Enable automatic updates",
|
||||
key: "autoUpdate",
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
label: "Default output folder",
|
||||
key: "outputFolder",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "You're All Set!",
|
||||
description: "You can now start upscaling your images.",
|
||||
type: "info",
|
||||
},
|
||||
];
|
||||
|
||||
export function OnboardingDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
}: {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
}) {
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [settings, setSettings] = useState<Record<string, any>>({});
|
||||
|
||||
const currentStepData = onboardingSteps[currentStep];
|
||||
const isLastStep = currentStep === onboardingSteps.length - 1;
|
||||
const isFirstStep = currentStep === 0;
|
||||
|
||||
const handleNext = () => {
|
||||
if (isLastStep) {
|
||||
onOpenChange(false);
|
||||
// Here you can handle saving the settings
|
||||
console.log("Final settings:", settings);
|
||||
} else {
|
||||
setCurrentStep((prev) => prev + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSettingChange = (key: string, value: any) => {
|
||||
setSettings((prev) => ({ ...prev, [key]: value }));
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="flex h-[80%] w-full max-w-[80%] flex-col items-center justify-center">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-center text-4xl">
|
||||
{currentStepData.title}
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-center text-lg">
|
||||
{currentStepData.description}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
{currentStepData.type === "settings" && currentStepData.settings && (
|
||||
<div className="grid gap-4 py-4">
|
||||
{currentStepData.settings.map((setting) => (
|
||||
<div
|
||||
key={setting.key}
|
||||
className="grid grid-cols-2 items-center gap-4"
|
||||
>
|
||||
<label htmlFor={setting.key} className="text-right">
|
||||
{setting.label}
|
||||
</label>
|
||||
{setting.type === "switch" && (
|
||||
<input
|
||||
type="checkbox"
|
||||
className="toggle"
|
||||
defaultChecked
|
||||
id={setting.key}
|
||||
checked={settings[setting.key] || false}
|
||||
onChange={(e) =>
|
||||
handleSettingChange(setting.key, e.target.checked)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{setting.type === "input" && (
|
||||
<input
|
||||
className="input input-bordered"
|
||||
id={setting.key}
|
||||
value={settings[setting.key] || ""}
|
||||
onChange={(e) =>
|
||||
handleSettingChange(setting.key, e.target.value)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<DialogFooter>
|
||||
<button onClick={handleNext} className="btn btn-secondary">
|
||||
{isLastStep ? "Get Started" : "Next"}
|
||||
</button>
|
||||
{!isFirstStep && (
|
||||
<button
|
||||
onClick={() => setCurrentStep((prev) => prev - 1)}
|
||||
className="btn btn-primary"
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
)}
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -17,18 +17,15 @@ import { selectedModelIdAtom } from "@/atoms/user-settings-atom";
|
||||
import { customModelIdsAtom } from "@/atoms/models-list-atom";
|
||||
import useTranslation from "@/components/hooks/use-translation";
|
||||
|
||||
export default function SelectModel() {
|
||||
const SelectModelDialog = () => {
|
||||
const t = useTranslation();
|
||||
const [selectedModelId, setSelectedModelId] = useAtom(selectedModelIdAtom);
|
||||
console.log("🚀 => selectedModelId:", selectedModelId);
|
||||
|
||||
const customModelIds = useAtomValue(customModelIdsAtom);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [zoomedModel, setZoomedModel] = useState<ModelId | null>(null);
|
||||
|
||||
const handleModelSelect = (model: ModelId | string) => {
|
||||
console.log("🚀 => model:", model);
|
||||
|
||||
setSelectedModelId(model);
|
||||
setOpen(false);
|
||||
};
|
||||
@@ -160,4 +157,6 @@ export default function SelectModel() {
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SelectModelDialog;
|
||||
@@ -16,7 +16,7 @@ import { ELECTRON_COMMANDS } from "@common/electron-commands";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { translationAtom } from "@/atoms/translations-atom";
|
||||
import { SelectImageScale } from "../settings-tab/select-image-scale";
|
||||
import SelectModel from "./select-model";
|
||||
import SelectModelDialog from "./select-model-dialog";
|
||||
import { ImageFormat } from "@/lib/valid-formats";
|
||||
|
||||
interface IProps {
|
||||
@@ -156,7 +156,7 @@ function UpscaylSteps({
|
||||
<p className="step-heading">{t("APP.MODEL_SELECTION.TITLE")}</p>
|
||||
<p className="mb-2 text-sm">{t("APP.MODEL_SELECTION.DESCRIPTION")}</p>
|
||||
|
||||
<SelectModel />
|
||||
<SelectModelDialog />
|
||||
</div>
|
||||
|
||||
{!batchMode && (
|
||||
|
||||
@@ -20,6 +20,7 @@ import getDirectoryFromPath from "@common/get-directory-from-path";
|
||||
import { FEATURE_FLAGS } from "@common/feature-flags";
|
||||
import { ImageFormat, VALID_IMAGE_FORMATS } from "@/lib/valid-formats";
|
||||
import { initCustomModels } from "@/components/hooks/use-custom-models";
|
||||
import { OnboardingDialog } from "@/components/main-content/onboarding-dialog";
|
||||
|
||||
const Home = () => {
|
||||
const t = useAtomValue(translationAtom);
|
||||
@@ -310,6 +311,7 @@ const Home = () => {
|
||||
doubleUpscaylCounter={doubleUpscaylCounter}
|
||||
setDimensions={setDimensions}
|
||||
/>
|
||||
<OnboardingDialog open={false} onOpenChange={() => {}} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user