summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxXJSONDeruloXx <danielhimebauch@gmail.com>2025-07-22 11:41:49 -0400
committerxXJSONDeruloXx <danielhimebauch@gmail.com>2025-07-22 11:41:49 -0400
commitdfe4c033dd1922a63c8393ab467e9aa58fa757e4 (patch)
treee6e518f4becdf0edd1e5f6fefd060b5c9060f010
parentc02343e68874efd57c2e312cb6b7e4f02222e43a (diff)
downloaddecky-lsfg-vk-dfe4c033dd1922a63c8393ab467e9aa58fa757e4.tar.gz
decky-lsfg-vk-dfe4c033dd1922a63c8393ab467e9aa58fa757e4.zip
refactor: update configuration handling to use object-based API
-rw-r--r--justfile7
-rw-r--r--py_modules/lsfg_vk/configuration.py2
-rw-r--r--py_modules/lsfg_vk/plugin.py40
-rw-r--r--scripts/generate_ts_schema.py135
-rw-r--r--src/api/lsfgApi.ts11
-rw-r--r--src/components/ConfigurationSection.tsx26
-rw-r--r--src/config/configSchema.ts23
7 files changed, 183 insertions, 61 deletions
diff --git a/justfile b/justfile
index 9923416..054c113 100644
--- a/justfile
+++ b/justfile
@@ -1,8 +1,11 @@
default:
- echo "Available recipes: build, test, clean"
+ echo "Available recipes: build, test, clean, generate-schema"
+
+generate-schema:
+ python3 scripts/generate_ts_schema.py
build:
- sudo rm -rf node_modules && .vscode/build.sh
+ python3 scripts/generate_ts_schema.py && sudo rm -rf node_modules && .vscode/build.sh
test:
scp "out/Lossless Scaling.zip" deck@192.168.0.6:~/Desktop
diff --git a/py_modules/lsfg_vk/configuration.py b/py_modules/lsfg_vk/configuration.py
index 82982e5..68ff577 100644
--- a/py_modules/lsfg_vk/configuration.py
+++ b/py_modules/lsfg_vk/configuration.py
@@ -222,7 +222,7 @@ class ConfigurationService(BaseService):
if config.get("mangohud_workaround", False):
lines.append("export MANGOHUD=1")
- lines.append("export MANGOHUD_CONFIG=alpha=0.01,background_alpha=0.01")
+ lines.append("export MANGOHUD_CONFIG=alpha=0.001,background_alpha=0.001")
if config.get("disable_vkbasalt", False):
lines.append("export DISABLE_VKBASALT=1")
diff --git a/py_modules/lsfg_vk/plugin.py b/py_modules/lsfg_vk/plugin.py
index 7deed71..d126d84 100644
--- a/py_modules/lsfg_vk/plugin.py
+++ b/py_modules/lsfg_vk/plugin.py
@@ -184,36 +184,30 @@ class Plugin:
"defaults": ConfigurationManager.get_defaults()
}
- async def update_lsfg_config(self, dll: str, multiplier: int, flow_scale: float,
- performance_mode: bool, hdr_mode: bool,
- experimental_present_mode: str = "fifo",
- dxvk_frame_rate: int = 0,
- enable_wow64: bool = False,
- disable_steamdeck_mode: bool = False,
- mangohud_workaround: bool = False,
- disable_vkbasalt: bool = False) -> Dict[str, Any]:
- """Update lsfg TOML configuration
+ async def update_lsfg_config(self, config: Dict[str, Any]) -> Dict[str, Any]:
+ """Update lsfg TOML configuration using object-based API
Args:
- dll: Path to Lossless.dll
- multiplier: LSFG multiplier value
- flow_scale: LSFG flow scale value
- performance_mode: Whether to enable performance mode
- hdr_mode: Whether to enable HDR mode
- experimental_present_mode: Experimental Vulkan present mode override
- dxvk_frame_rate: Frame rate cap for DirectX games, before frame multiplier (0 = disabled)
- enable_wow64: Whether to enable PROTON_USE_WOW64=1 for 32-bit games
- disable_steamdeck_mode: Whether to disable Steam Deck mode
- mangohud_workaround: Whether to enable MangoHud workaround with transparent overlay
- disable_vkbasalt: Whether to disable vkBasalt layer
+ config: Configuration data dictionary containing all settings
Returns:
ConfigurationResponse dict with success status
"""
+ # Validate and extract configuration from the config dict
+ validated_config = ConfigurationManager.validate_config(config)
+
return self.configuration_service.update_config(
- dll, multiplier, flow_scale, performance_mode, hdr_mode,
- experimental_present_mode, dxvk_frame_rate, enable_wow64, disable_steamdeck_mode,
- mangohud_workaround, disable_vkbasalt
+ dll=validated_config["dll"],
+ multiplier=validated_config["multiplier"],
+ flow_scale=validated_config["flow_scale"],
+ performance_mode=validated_config["performance_mode"],
+ hdr_mode=validated_config["hdr_mode"],
+ experimental_present_mode=validated_config["experimental_present_mode"],
+ dxvk_frame_rate=validated_config["dxvk_frame_rate"],
+ enable_wow64=validated_config["enable_wow64"],
+ disable_steamdeck_mode=validated_config["disable_steamdeck_mode"],
+ mangohud_workaround=validated_config["mangohud_workaround"],
+ disable_vkbasalt=validated_config["disable_vkbasalt"]
)
async def update_dll_path(self, dll_path: str) -> Dict[str, Any]:
diff --git a/scripts/generate_ts_schema.py b/scripts/generate_ts_schema.py
new file mode 100644
index 0000000..dcdddf2
--- /dev/null
+++ b/scripts/generate_ts_schema.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python3
+"""
+Generate TypeScript schema from Python shared_config.py
+
+This script reads the canonical schema from shared_config.py and generates
+the corresponding TypeScript files, ensuring single source of truth.
+"""
+
+import sys
+from pathlib import Path
+
+# Add project root to path to import shared_config
+project_root = Path(__file__).parent.parent
+sys.path.insert(0, str(project_root))
+
+from shared_config import CONFIG_SCHEMA_DEF, ConfigFieldType
+
+
+def generate_typescript_schema():
+ """Generate generatedConfigSchema.ts from Python schema"""
+
+ # Generate enum
+ enum_lines = [
+ "// src/config/generatedConfigSchema.ts",
+ "// Configuration field type enum - matches Python",
+ "export enum ConfigFieldType {",
+ " BOOLEAN = \"boolean\",",
+ " INTEGER = \"integer\",",
+ " FLOAT = \"float\",",
+ " STRING = \"string\"",
+ "}",
+ "",
+ "// Configuration field definition",
+ "export interface ConfigField {",
+ " name: string;",
+ " fieldType: ConfigFieldType;",
+ " default: boolean | number | string;",
+ " description: string;",
+ "}",
+ "",
+ "// Configuration schema - auto-generated from Python",
+ "export const CONFIG_SCHEMA: Record<string, ConfigField> = {"
+ ]
+
+ # Generate schema entries
+ schema_entries = []
+ interface_fields = []
+ defaults_fields = []
+ field_types = []
+
+ for field_name, field_def in CONFIG_SCHEMA_DEF.items():
+ # Schema entry
+ default_value = field_def["default"]
+ if isinstance(default_value, str):
+ default_str = f'"{default_value}"'
+ elif isinstance(default_value, bool):
+ default_str = "true" if default_value else "false"
+ else:
+ default_str = str(default_value)
+
+ schema_entries.append(f' {field_name}: {{')
+ schema_entries.append(f' name: "{field_def["name"]}",')
+ schema_entries.append(f' fieldType: ConfigFieldType.{field_def["fieldType"].upper()},')
+ schema_entries.append(f' default: {default_str},')
+ schema_entries.append(f' description: "{field_def["description"]}"')
+ schema_entries.append(' },')
+
+ # Interface field
+ if field_def["fieldType"] == ConfigFieldType.BOOLEAN:
+ ts_type = "boolean"
+ elif field_def["fieldType"] == ConfigFieldType.INTEGER:
+ ts_type = "number"
+ elif field_def["fieldType"] == ConfigFieldType.FLOAT:
+ ts_type = "number"
+ elif field_def["fieldType"] == ConfigFieldType.STRING:
+ ts_type = "string"
+ else:
+ ts_type = "any"
+
+ interface_fields.append(f' {field_name}: {ts_type};')
+ defaults_fields.append(f' {field_name}: {default_str},')
+ field_types.append(f' {field_name}: ConfigFieldType.{field_def["fieldType"].upper()},')
+
+ # Complete the file
+ all_lines = enum_lines + schema_entries + [
+ "};",
+ "",
+ "// Type-safe configuration data structure",
+ "export interface ConfigurationData {",
+ ] + interface_fields + [
+ "}",
+ "",
+ "// Helper functions",
+ "export function getFieldNames(): string[] {",
+ " return Object.keys(CONFIG_SCHEMA);",
+ "}",
+ "",
+ "export function getDefaults(): ConfigurationData {",
+ " return {",
+ ] + defaults_fields + [
+ " };",
+ "}",
+ "",
+ "export function getFieldTypes(): Record<string, ConfigFieldType> {",
+ " return {",
+ ] + field_types + [
+ " };",
+ "}",
+ "",
+ ""
+ ]
+
+ return "\n".join(all_lines)
+
+
+def main():
+ """Main function to generate TypeScript schema"""
+ try:
+ # Generate the TypeScript content
+ ts_content = generate_typescript_schema()
+
+ # Write to the target file
+ target_file = project_root / "src" / "config" / "generatedConfigSchema.ts"
+ target_file.write_text(ts_content)
+
+ print(f"✅ Generated {target_file} from shared_config.py")
+ print(f" Fields: {len(CONFIG_SCHEMA_DEF)}")
+
+ except Exception as e:
+ print(f"❌ Error generating TypeScript schema: {e}")
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts
index 0b221e9..8d14da6 100644
--- a/src/api/lsfgApi.ts
+++ b/src/api/lsfgApi.ts
@@ -1,5 +1,5 @@
import { callable } from "@decky/api";
-import { ConfigurationData, ConfigurationManager } from "../config/configSchema";
+import { ConfigurationData } from "../config/configSchema";
// Type definitions for API responses
export interface InstallationResult {
@@ -99,16 +99,15 @@ export const getLaunchOption = callable<[], LaunchOptionResult>("get_launch_opti
export const getConfigFileContent = callable<[], FileContentResult>("get_config_file_content");
export const getLaunchScriptContent = callable<[], FileContentResult>("get_launch_script_content");
-// Updated config function using centralized configuration
+// Updated config function using object-based configuration (single source of truth)
export const updateLsfgConfig = callable<
- [string, number, number, boolean, boolean, string, number, boolean, boolean, boolean, boolean],
+ [ConfigurationData],
ConfigUpdateResult
>("update_lsfg_config");
-// Helper function to create config update from configuration object
+// Legacy helper function for backward compatibility
export const updateLsfgConfigFromObject = async (config: ConfigurationData): Promise<ConfigUpdateResult> => {
- const args = ConfigurationManager.createArgsFromConfig(config);
- return updateLsfgConfig(...args as [string, number, number, boolean, boolean, string, number, boolean, boolean, boolean, boolean]);
+ return updateLsfgConfig(config);
};
// Self-updater API functions
diff --git a/src/components/ConfigurationSection.tsx b/src/components/ConfigurationSection.tsx
index 26099e7..1c0d2b2 100644
--- a/src/components/ConfigurationSection.tsx
+++ b/src/components/ConfigurationSection.tsx
@@ -112,16 +112,26 @@ export function ConfigurationSection({
<PanelSectionRow>
<div
style={{
- fontSize: "14px",
- fontWeight: "bold",
- marginTop: "16px",
- marginBottom: "8px",
- borderBottom: "1px solid rgba(255, 255, 255, 0.2)",
- paddingBottom: "4px",
- color: "white"
+ fontSize: "14px",
+ fontWeight: "bold",
+ marginTop: "16px",
+ marginBottom: "2px",
+ borderBottom: "1px solid rgba(255, 255, 255, 0.2)",
+ paddingBottom: "2px",
+ color: "white"
+ }}
+ >
+ Environment Variables
+ </div>
+ <div
+ style={{
+ fontSize: "12px",
+ color: "#cccccc",
+ marginTop: "2px",
+ marginBottom: "8px"
}}
>
- Environment Variables (Requires re-launch)
+ Must be toggled before game start or restart game to take effect
</div>
</PanelSectionRow>
diff --git a/src/config/configSchema.ts b/src/config/configSchema.ts
index 979d3c9..fdf6212 100644
--- a/src/config/configSchema.ts
+++ b/src/config/configSchema.ts
@@ -8,6 +8,7 @@
import { callable } from "@decky/api";
import type { ConfigurationData } from './generatedConfigSchema';
import { getDefaults } from './generatedConfigSchema';
+import { updateLsfgConfig } from "../api/lsfgApi";
// Re-export all auto-generated configuration constants
export {
@@ -30,7 +31,6 @@ export class ConfigurationManager {
// Callable methods for backend communication
private getConfiguration = callable<[], { success: boolean; data?: ConfigurationData; error?: string }>("get_configuration");
- private setConfiguration = callable<[{ config_data: ConfigurationData }], { success: boolean; error?: string }>("set_configuration");
private resetConfiguration = callable<[], { success: boolean; data?: ConfigurationData; error?: string }>("reset_configuration");
private constructor() {}
@@ -50,25 +50,6 @@ export class ConfigurationManager {
}
/**
- * Create args array from config object for lsfg API calls
- */
- static createArgsFromConfig(config: ConfigurationData): [string, number, number, boolean, boolean, string, number, boolean, boolean, boolean, boolean] {
- return [
- config.dll,
- config.multiplier,
- config.flow_scale,
- config.performance_mode,
- config.hdr_mode,
- config.experimental_present_mode,
- config.dxvk_frame_rate,
- config.enable_wow64,
- config.disable_steamdeck_mode,
- config.mangohud_workaround,
- config.disable_vkbasalt
- ];
- }
-
- /**
* Load configuration from backend
*/
async loadConfig(): Promise<ConfigurationData> {
@@ -91,7 +72,7 @@ export class ConfigurationManager {
*/
async saveConfig(config: ConfigurationData): Promise<void> {
try {
- const result = await this.setConfiguration({ config_data: config });
+ const result = await updateLsfgConfig(config);
if (result.success) {
this._config = config;
} else {