fix(plugin): dropdown data prop, always show guide, add config export/import
This commit is contained in:
@@ -414,3 +414,37 @@ benchmark_percentiles=97,AVG,1,0.1
|
|||||||
return {"valid": False, "error": f"Network error: {str(e.reason)}"}
|
return {"valid": False, "error": f"Network error: {str(e.reason)}"}
|
||||||
except Exception as e:
|
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 = [
|
const UPSCALER_OPTIONS = [
|
||||||
{ label: "None", value: "none" },
|
{ label: "None", data: "none" },
|
||||||
{ label: "FSR", value: "fsr" },
|
{ label: "FSR", data: "fsr" },
|
||||||
{ label: "DLSS", value: "dlss" },
|
{ label: "DLSS", data: "dlss" },
|
||||||
{ label: "XeSS", value: "xess" },
|
{ label: "XeSS", data: "xess" },
|
||||||
{ label: "LSFG", value: "lsfg" },
|
{ label: "LSFG", data: "lsfg" },
|
||||||
{ label: "Other", value: "other" },
|
{ label: "Other", data: "other" },
|
||||||
]
|
]
|
||||||
|
|
||||||
const FRAME_GEN_OPTIONS = [
|
const FRAME_GEN_OPTIONS = [
|
||||||
{ label: "None", value: "none" },
|
{ label: "None", data: "none" },
|
||||||
{ label: "FSR FG", value: "fsr_fg" },
|
{ label: "FSR FG", data: "fsr_fg" },
|
||||||
{ label: "DLSS FG", value: "dlss_fg" },
|
{ label: "DLSS FG", data: "dlss_fg" },
|
||||||
{ label: "LSFG", value: "lsfg" },
|
{ label: "LSFG", data: "lsfg" },
|
||||||
{ label: "Other", value: "other" },
|
{ label: "Other", data: "other" },
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function SessionForm({
|
export default function SessionForm({
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ import {
|
|||||||
FaTimes,
|
FaTimes,
|
||||||
FaDownload,
|
FaDownload,
|
||||||
FaCog,
|
FaCog,
|
||||||
|
FaFileExport,
|
||||||
|
FaFileImport,
|
||||||
} from "react-icons/fa"
|
} from "react-icons/fa"
|
||||||
import type { PluginSettings } from "../lib/store"
|
import type { PluginSettings } from "../lib/store"
|
||||||
import { KNOWN_HARDWARE_SLUGS } from "@deckyvault/shared"
|
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 {
|
interface SettingsPanelProps {
|
||||||
settings: PluginSettings
|
settings: PluginSettings
|
||||||
@@ -26,8 +28,8 @@ interface SettingsPanelProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const HARDWARE_OPTIONS = [
|
const HARDWARE_OPTIONS = [
|
||||||
{ label: "Auto-detect", value: "" },
|
{ label: "Auto-detect", data: "" },
|
||||||
...KNOWN_HARDWARE_SLUGS.map((slug) => ({ label: slug, value: slug })),
|
...KNOWN_HARDWARE_SLUGS.map((slug) => ({ label: slug, data: slug })),
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function SettingsPanel({
|
export default function SettingsPanel({
|
||||||
@@ -42,8 +44,8 @@ export default function SettingsPanel({
|
|||||||
path: string
|
path: string
|
||||||
version: string
|
version: string
|
||||||
}>({ checked: false, installed: false, path: "", version: "" })
|
}>({ checked: false, installed: false, path: "", version: "" })
|
||||||
const [showMangohudGuide, setShowMangohudGuide] = useState(false)
|
|
||||||
const [configWritten, setConfigWritten] = useState(false)
|
const [configWritten, setConfigWritten] = useState(false)
|
||||||
|
const [configStatus, setConfigStatus] = useState<{ message: string; isError: boolean } | null>(null)
|
||||||
|
|
||||||
async function handleTestKey() {
|
async function handleTestKey() {
|
||||||
if (!settings.apiKey) {
|
if (!settings.apiKey) {
|
||||||
@@ -78,6 +80,30 @@ export default function SettingsPanel({
|
|||||||
setConfigWritten(result.success)
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* ── API Key ─────────────────────────────────────────────── */}
|
{/* ── API Key ─────────────────────────────────────────────── */}
|
||||||
@@ -152,6 +178,40 @@ export default function SettingsPanel({
|
|||||||
</PanelSectionRow>
|
</PanelSectionRow>
|
||||||
</PanelSection>
|
</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 ──────────────────────────────────────── */}
|
{/* ── MangoHud Setup ──────────────────────────────────────── */}
|
||||||
<PanelSection title="MangoHud Setup">
|
<PanelSection title="MangoHud Setup">
|
||||||
<PanelSectionRow>
|
<PanelSectionRow>
|
||||||
@@ -204,13 +264,6 @@ export default function SettingsPanel({
|
|||||||
</PanelSectionRow>
|
</PanelSectionRow>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<PanelSectionRow>
|
|
||||||
<ButtonItem layout="below" onClick={() => setShowMangohudGuide(!showMangohudGuide)}>
|
|
||||||
{showMangohudGuide ? "Hide Guide" : "Show Installation Guide"}
|
|
||||||
</ButtonItem>
|
|
||||||
</PanelSectionRow>
|
|
||||||
|
|
||||||
{showMangohudGuide && (
|
|
||||||
<PanelSectionRow>
|
<PanelSectionRow>
|
||||||
<div className={staticClasses.Text} style={{ fontSize: "12px", padding: "8px", lineHeight: "1.6" }}>
|
<div className={staticClasses.Text} style={{ fontSize: "12px", padding: "8px", lineHeight: "1.6" }}>
|
||||||
<strong>Steam Deck (SteamOS):</strong>
|
<strong>Steam Deck (SteamOS):</strong>
|
||||||
@@ -251,7 +304,6 @@ export default function SettingsPanel({
|
|||||||
• Not attaching? Try adding <code>mangohud %command%</code> to Steam launch options explicitly.
|
• Not attaching? Try adding <code>mangohud %command%</code> to Steam launch options explicitly.
|
||||||
</div>
|
</div>
|
||||||
</PanelSectionRow>
|
</PanelSectionRow>
|
||||||
)}
|
|
||||||
</PanelSection>
|
</PanelSection>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -74,3 +74,26 @@ export const testApiKey = callable<[apiKey: string, baseUrl?: string], {
|
|||||||
valid: boolean
|
valid: boolean
|
||||||
error?: string
|
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")
|
||||||
Reference in New Issue
Block a user