feat(wizard): redesign environment step - upscaling options

- Replace FSR Version with flexible Upscaler Type + Version
- Add new upscaler options: AMD FSR, NVIDIA DLSS, Intel XeSS, Lossless Scaling FG, Other
- Expand Frame Gen options: lsfg, other
- Add Estimated Battery Life field (minutes)
- Add Custom / Modified System toggle
- Update review step with new summary rows
- Update submit body with new fields
This commit is contained in:
2026-04-27 07:24:23 +08:00
parent bcc0382001
commit 4943f24fd4
3 changed files with 104 additions and 32 deletions
+84 -11
View File
@@ -2,28 +2,35 @@
import { useEffect, useRef, useState, useCallback } from "react"
import { motion, AnimatePresence } from "motion/react"
import { Terminal, ChevronDown, Loader2 } from "lucide-react"
import { Terminal, ChevronDown, Loader2, ToggleLeft, ToggleRight } from "lucide-react"
import { api } from "@/lib/eden"
const FSR_OPTIONS = [
export const UPSCALER_TYPE_OPTIONS = [
{ value: "none", label: "None" },
{ value: "fsr1", label: "FSR 1" },
{ value: "fsr2", label: "FSR 2" },
{ value: "fsr3", label: "FSR 3" },
{ value: "fsr", label: "AMD FSR" },
{ value: "dlss", label: "NVIDIA DLSS" },
{ value: "xess", label: "Intel XeSS" },
{ value: "lsfg", label: "Lossless Scaling FG" },
{ value: "other", label: "Other" },
] as const
const FRAME_GEN_OPTIONS = [
export const FRAME_GEN_OPTIONS = [
{ value: "none", label: "None" },
{ value: "fsr_fg", label: "FSR Frame Generation" },
{ value: "dlss_fg", label: "DLSS Frame Generation" },
{ value: "lsfg", label: "Lossless Scaling FG" },
{ value: "other", label: "Other" },
] as const
export interface EnvironmentData {
protonVersion?: string
osVersion?: string
fsrVersion?: string
upscalerType?: string
upscalerVersion?: string
frameGenMethod?: string
launchOptions?: string
estimatedBatteryMin?: number
customSystem?: boolean
}
interface EnvironmentStepProps {
@@ -184,14 +191,14 @@ export function EnvironmentStep({ value, onChange }: EnvironmentStepProps) {
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div className="space-y-1.5">
<label className="text-xs font-medium text-text/60">FSR Version</label>
<label className="text-xs font-medium text-text/60">Upscaler Type</label>
<div className="relative">
<select
value={value.fsrVersion ?? "none"}
onChange={(e) => update("fsrVersion", e.target.value)}
value={value.upscalerType ?? "none"}
onChange={(e) => update("upscalerType", e.target.value)}
className="w-full appearance-none px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors cursor-pointer"
>
{FSR_OPTIONS.map((opt) => (
{UPSCALER_TYPE_OPTIONS.map((opt) => (
<option key={opt.value} value={opt.value}>
{opt.label}
</option>
@@ -201,6 +208,21 @@ export function EnvironmentStep({ value, onChange }: EnvironmentStepProps) {
</div>
</div>
{value.upscalerType && value.upscalerType !== "none" && (
<div className="space-y-1.5">
<label className="text-xs font-medium text-text/60">Upscaler Version</label>
<input
type="text"
value={value.upscalerVersion ?? ""}
onChange={(e) => update("upscalerVersion", e.target.value)}
placeholder="e.g. 3.1"
className="w-full px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors"
/>
</div>
)}
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div className="space-y-1.5">
<label className="text-xs font-medium text-text/60">Frame Gen Method</label>
<div className="relative">
@@ -233,6 +255,57 @@ export function EnvironmentStep({ value, onChange }: EnvironmentStepProps) {
Steam launch options or environment variables used.
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 pt-2">
<div className="space-y-1.5">
<label className="text-xs font-medium text-text/60">
Estimated Battery Life (minutes)
</label>
<input
type="number"
min={1}
step={1}
value={value.estimatedBatteryMin ?? ""}
onChange={(e) => {
const val = e.target.value
onChange({
...value,
estimatedBatteryMin: val === "" ? undefined : Number(val),
})
}}
placeholder="e.g. 90"
className="w-full px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors"
/>
<p className="text-xs text-text/40">
Approximate battery life in minutes while playing this game.
</p>
</div>
<div className="space-y-1.5">
<label className="text-xs font-medium text-text/60">
Custom / Modified System
</label>
<div className="flex items-center gap-3 py-3">
<button
type="button"
onClick={() => onChange({ ...value, customSystem: !value.customSystem })}
className={`flex items-center gap-2 text-sm cursor-pointer transition-colors ${
value.customSystem ? "text-primary" : "text-text/40"
}`}
>
{value.customSystem ? (
<ToggleRight className="h-5 w-5" />
) : (
<ToggleLeft className="h-5 w-5" />
)}
{value.customSystem ? "Yes" : "No"}
</button>
<span className="text-xs text-text/40">
Check if using custom firmware, OS, or mods that affect performance.
</span>
</div>
</div>
</div>
</div>
)
}
+15 -19
View File
@@ -6,6 +6,7 @@ import { TiptapEditor } from "@/components/tiptap-editor"
import type { SettingCategory } from "@/components/wizard/settings-editor"
import type { PerformanceData } from "./performance-step"
import type { EnvironmentData } from "./environment-step"
import { UPSCALER_TYPE_OPTIONS, FRAME_GEN_OPTIONS } from "./environment-step"
export interface ReviewData {
hardwareSlug: string
@@ -57,25 +58,18 @@ export function ReviewStep({
}: ReviewStepProps) {
const { hardwareName, performance, environment, settings } = data
const fsrLabel =
environment.fsrVersion === "none"
? "None"
: environment.fsrVersion === "fsr1"
? "FSR 1"
: environment.fsrVersion === "fsr2"
? "FSR 2"
: environment.fsrVersion === "fsr3"
? "FSR 3"
: "Not set"
const upscalerLabel = (() => {
if (!data.environment.upscalerType || data.environment.upscalerType === "none") return "None"
const opt = UPSCALER_TYPE_OPTIONS.find(o => o.value === data.environment.upscalerType)
const base = opt?.label ?? data.environment.upscalerType
return data.environment.upscalerVersion ? `${base} ${data.environment.upscalerVersion}` : base
})()
const frameGenLabel =
environment.frameGenMethod === "none"
? "None"
: environment.frameGenMethod === "fsr_fg"
? "FSR Frame Generation"
: environment.frameGenMethod === "dlss_fg"
? "DLSS Frame Generation"
: "Not set"
const frameGenLabel = (() => {
if (!environment.frameGenMethod || environment.frameGenMethod === "none") return "None"
const opt = FRAME_GEN_OPTIONS.find(o => o.value === environment.frameGenMethod)
return opt?.label ?? environment.frameGenMethod
})()
return (
<div className="space-y-6">
@@ -112,8 +106,10 @@ export function ReviewStep({
<SectionHeader icon={Terminal} label="Environment" />
<SummaryRow label="Proton Version" value={environment.protonVersion || "Not set"} />
<SummaryRow label="OS Version" value={environment.osVersion || "Not set"} />
<SummaryRow label="FSR Version" value={fsrLabel} />
<SummaryRow label="Upscaler" value={upscalerLabel} />
<SummaryRow label="Frame Gen" value={frameGenLabel} />
<SummaryRow label="Estimated Battery" value={environment.estimatedBatteryMin ? `${environment.estimatedBatteryMin} min` : "Not set"} />
<SummaryRow label="Custom System" value={environment.customSystem ? "Yes" : "No"} />
{environment.launchOptions && (
<SummaryRow
label="Launch Options"