fix(plugin): dropdown data prop, always show guide, add config export/import

This commit is contained in:
2026-06-28 17:43:36 +08:00
parent 4b7efd3c5c
commit 3196812c0d
4 changed files with 172 additions and 63 deletions
+35 -1
View File
@@ -413,4 +413,38 @@ benchmark_percentiles=97,AVG,1,0.1
except urllib.error.URLError as e:
return {"valid": False, "error": f"Network error: {str(e.reason)}"}
except Exception as e:
return {"valid": False, "error": str(e)}
return {"valid": False, "error": str(e)}
async def export_config(self, settings: dict) -> dict:
"""RPC: Export current settings to Downloads/deckyvault-config.json.
Returns {success: bool, path?: str, error?: str}."""
try:
home = os.path.expanduser("~")
config_path = os.path.join(home, "Downloads", "deckyvault-config.json")
with open(config_path, 'w') as f:
json.dump(settings, f, indent=2)
return {"success": True, "path": config_path}
except Exception as e:
return {"success": False, "error": str(e)}
async def import_config(self) -> dict:
"""RPC: Import settings from the latest deckyvault-config.json in Downloads.
Returns {success: bool, settings?: dict, error?: str}."""
try:
home = os.path.expanduser("~")
config_path = os.path.join(home, "Downloads", "deckyvault-config.json")
if not os.path.exists(config_path):
return {"success": False, "error": "No deckyvault-config.json found in Downloads"}
with open(config_path, 'r') as f:
settings = json.load(f)
return {
"success": True,
"settings": {
"apiKey": settings.get("apiKey", ""),
"exportPath": settings.get("exportPath", "/home/deck/Downloads"),
"baseUrl": settings.get("baseUrl", "https://deckyvault.xyz"),
"hardwareSlug": settings.get("hardwareSlug", None),
}
}
except Exception as e:
return {"success": False, "error": str(e)}
@@ -29,20 +29,20 @@ interface SessionFormProps {
}
const UPSCALER_OPTIONS = [
{ label: "None", value: "none" },
{ label: "FSR", value: "fsr" },
{ label: "DLSS", value: "dlss" },
{ label: "XeSS", value: "xess" },
{ label: "LSFG", value: "lsfg" },
{ label: "Other", value: "other" },
{ label: "None", data: "none" },
{ label: "FSR", data: "fsr" },
{ label: "DLSS", data: "dlss" },
{ label: "XeSS", data: "xess" },
{ label: "LSFG", data: "lsfg" },
{ label: "Other", data: "other" },
]
const FRAME_GEN_OPTIONS = [
{ label: "None", value: "none" },
{ label: "FSR FG", value: "fsr_fg" },
{ label: "DLSS FG", value: "dlss_fg" },
{ label: "LSFG", value: "lsfg" },
{ label: "Other", value: "other" },
{ label: "None", data: "none" },
{ label: "FSR FG", data: "fsr_fg" },
{ label: "DLSS FG", data: "dlss_fg" },
{ label: "LSFG", data: "lsfg" },
{ label: "Other", data: "other" },
]
export default function SessionForm({
@@ -12,10 +12,12 @@ import {
FaTimes,
FaDownload,
FaCog,
FaFileExport,
FaFileImport,
} from "react-icons/fa"
import type { PluginSettings } from "../lib/store"
import { KNOWN_HARDWARE_SLUGS } from "@deckyvault/shared"
import { testApiKey, checkMangohud, writeMangohudConfig, getMangohudConfig } from "../lib/api"
import { testApiKey, checkMangohud, writeMangohudConfig, exportConfig, importConfig } from "../lib/api"
interface SettingsPanelProps {
settings: PluginSettings
@@ -26,8 +28,8 @@ interface SettingsPanelProps {
}
const HARDWARE_OPTIONS = [
{ label: "Auto-detect", value: "" },
...KNOWN_HARDWARE_SLUGS.map((slug) => ({ label: slug, value: slug })),
{ label: "Auto-detect", data: "" },
...KNOWN_HARDWARE_SLUGS.map((slug) => ({ label: slug, data: slug })),
]
export default function SettingsPanel({
@@ -42,8 +44,8 @@ export default function SettingsPanel({
path: string
version: string
}>({ checked: false, installed: false, path: "", version: "" })
const [showMangohudGuide, setShowMangohudGuide] = useState(false)
const [configWritten, setConfigWritten] = useState(false)
const [configStatus, setConfigStatus] = useState<{ message: string; isError: boolean } | null>(null)
async function handleTestKey() {
if (!settings.apiKey) {
@@ -78,6 +80,30 @@ export default function SettingsPanel({
setConfigWritten(result.success)
}
async function handleExportConfig() {
setConfigStatus(null)
const result = await exportConfig(settings)
if (result.success) {
setConfigStatus({ message: `Config saved to ${result.path}`, isError: false })
} else {
setConfigStatus({ message: result.error || "Export failed", isError: true })
}
}
async function handleImportConfig() {
setConfigStatus(null)
const result = await importConfig()
if (result.success && result.settings) {
onUpdateSetting("apiKey", result.settings.apiKey || "")
onUpdateSetting("exportPath", result.settings.exportPath || "/home/deck/Downloads")
onUpdateSetting("baseUrl", result.settings.baseUrl || "https://deckyvault.xyz")
onUpdateSetting("hardwareSlug", result.settings.hardwareSlug || null)
setConfigStatus({ message: "Config imported from Downloads", isError: false })
} else {
setConfigStatus({ message: result.error || "No config file found in Downloads", isError: true })
}
}
return (
<>
{/* ── API Key ─────────────────────────────────────────────── */}
@@ -152,6 +178,40 @@ export default function SettingsPanel({
</PanelSectionRow>
</PanelSection>
{/* ── Config Export/Import ────────────────────────────────── */}
<PanelSection title="Configuration">
<PanelSectionRow>
<ButtonItem layout="below" onClick={handleExportConfig}>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<FaFileExport />
Export Config to Downloads
</div>
</ButtonItem>
</PanelSectionRow>
<PanelSectionRow>
<ButtonItem layout="below" onClick={handleImportConfig}>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<FaFileImport />
Import Config from Downloads
</div>
</ButtonItem>
</PanelSectionRow>
{configStatus && (
<PanelSectionRow>
<div
className={staticClasses.Text}
style={{
fontSize: "12px",
padding: "4px 0",
color: configStatus.isError ? "#e74c3c" : "#2ecc71",
}}
>
{configStatus.isError ? <FaTimes /> : <FaCheck />} {configStatus.message}
</div>
</PanelSectionRow>
)}
</PanelSection>
{/* ── MangoHud Setup ──────────────────────────────────────── */}
<PanelSection title="MangoHud Setup">
<PanelSectionRow>
@@ -205,53 +265,45 @@ export default function SettingsPanel({
)}
<PanelSectionRow>
<ButtonItem layout="below" onClick={() => setShowMangohudGuide(!showMangohudGuide)}>
{showMangohudGuide ? "Hide Guide" : "Show Installation Guide"}
</ButtonItem>
<div className={staticClasses.Text} style={{ fontSize: "12px", padding: "8px", lineHeight: "1.6" }}>
<strong>Steam Deck (SteamOS):</strong>
<br />
MangoHud is pre-installed. Enable it per-game by adding
<code style={{ display: "block", margin: "4px 0", padding: "4px", background: "rgba(255,255,255,0.1)" }}>
mangohud %command%
</code>
to the game's Steam launch options (right-click game Properties Launch Options).
<br /><br />
<strong>Other Linux handhelds</strong> (ROG Ally, Legion Go):
<br />
Install via package manager:
<code style={{ display: "block", margin: "4px 0", padding: "4px", background: "rgba(255,255,255,0.1)" }}>
sudo apt install mangohud
</code>
or Flatpak:
<code style={{ display: "block", margin: "4px 0", padding: "4px", background: "rgba(255,255,255,0.1)" }}>
flatpak install flathub org.freedesktop.Platform.VulkanLayer.MangoHud
</code>
<br /><br />
<strong>Manual build:</strong>
<br />
See{" "}
<a href="https://github.com/flightlessmango/MangoHud" style={{ color: "#66c0f4" }}>
github.com/flightlessmango/MangoHud
</a>
<br /><br />
<strong>Troubleshooting:</strong>
<br />
Log file empty? Check MangoHud is enabled for the game and the config was written.
<br />
Wrong path? Ensure the plugin can write to /tmp/.
<br />
Not attaching? Try adding <code>mangohud %command%</code> to Steam launch options explicitly.
</div>
</PanelSectionRow>
{showMangohudGuide && (
<PanelSectionRow>
<div className={staticClasses.Text} style={{ fontSize: "12px", padding: "8px", lineHeight: "1.6" }}>
<strong>Steam Deck (SteamOS):</strong>
<br />
MangoHud is pre-installed. Enable it per-game by adding
<code style={{ display: "block", margin: "4px 0", padding: "4px", background: "rgba(255,255,255,0.1)" }}>
mangohud %command%
</code>
to the game's Steam launch options (right-click game Properties Launch Options).
<br /><br />
<strong>Other Linux handhelds</strong> (ROG Ally, Legion Go):
<br />
Install via package manager:
<code style={{ display: "block", margin: "4px 0", padding: "4px", background: "rgba(255,255,255,0.1)" }}>
sudo apt install mangohud
</code>
or Flatpak:
<code style={{ display: "block", margin: "4px 0", padding: "4px", background: "rgba(255,255,255,0.1)" }}>
flatpak install flathub org.freedesktop.Platform.VulkanLayer.MangoHud
</code>
<br /><br />
<strong>Manual build:</strong>
<br />
See{" "}
<a href="https://github.com/flightlessmango/MangoHud" style={{ color: "#66c0f4" }}>
github.com/flightlessmango/MangoHud
</a>
<br /><br />
<strong>Troubleshooting:</strong>
<br />
Log file empty? Check MangoHud is enabled for the game and the config was written.
<br />
Wrong path? Ensure the plugin can write to /tmp/.
<br />
Not attaching? Try adding <code>mangohud %command%</code> to Steam launch options explicitly.
</div>
</PanelSectionRow>
)}
</PanelSection>
</>
)
+24 -1
View File
@@ -73,4 +73,27 @@ export const uploadToDeckyvault = callable<[
export const testApiKey = callable<[apiKey: string, baseUrl?: string], {
valid: boolean
error?: string
}>("test_api_key")
}>("test_api_key")
// ── Config Export/Import ────────────────────────────────────────
export const exportConfig = callable<[settings: {
apiKey: string
exportPath: string
baseUrl: string
hardwareSlug: string | null
}], {
success: boolean
path?: string
error?: string
}>("export_config")
export const importConfig = callable<[], {
success: boolean
settings?: {
apiKey: string
exportPath: string
baseUrl: string
hardwareSlug: string | null
}
error?: string
}>("import_config")