diff options
| author | xXJSONDeruloXx <danielhimebauch@gmail.com> | 2025-07-16 17:11:00 -0400 |
|---|---|---|
| committer | xXJSONDeruloXx <danielhimebauch@gmail.com> | 2025-07-16 17:11:00 -0400 |
| commit | 2811ba4e29cd27b5893fba676278f29b155068cb (patch) | |
| tree | 5eaab7f419b277196ed4c22939ce0ea74555f4ce /src | |
| parent | 44393f6e126c3dff196283a2079162e3eb9245a2 (diff) | |
| download | decky-lsfg-vk-2811ba4e29cd27b5893fba676278f29b155068cb.tar.gz decky-lsfg-vk-2811ba4e29cd27b5893fba676278f29b155068cb.zip | |
non modal updater
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/lsfgApi.ts | 21 | ||||
| -rw-r--r-- | src/components/Content.tsx | 4 | ||||
| -rw-r--r-- | src/components/PluginUpdateChecker.tsx | 187 | ||||
| -rw-r--r-- | src/components/index.ts | 1 |
4 files changed, 213 insertions, 0 deletions
diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts index 2e7964c..f7363c1 100644 --- a/src/api/lsfgApi.ts +++ b/src/api/lsfgApi.ts @@ -49,6 +49,23 @@ export interface ConfigSchemaResult { defaults: ConfigurationData; } +export interface UpdateCheckResult { + success: boolean; + update_available: boolean; + current_version: string; + latest_version: string; + release_notes: string; + release_date: string; + download_url: string; + error?: string; +} + +export interface UpdateDownloadResult { + success: boolean; + download_path?: string; + error?: string; +} + // API functions export const installLsfgVk = callable<[], InstallationResult>("install_lsfg_vk"); export const uninstallLsfgVk = callable<[], InstallationResult>("uninstall_lsfg_vk"); @@ -68,3 +85,7 @@ export const updateLsfgConfigFromObject = async (config: ConfigurationData): Pro const args = ConfigurationManager.createArgsFromConfig(config); return updateLsfgConfig(...args as [boolean, number, number, boolean, boolean, boolean, boolean, number]); }; + +// Self-updater API functions +export const checkForPluginUpdate = callable<[], UpdateCheckResult>("check_for_plugin_update"); +export const downloadPluginUpdate = callable<[string], UpdateDownloadResult>("download_plugin_update"); diff --git a/src/components/Content.tsx b/src/components/Content.tsx index ba651d4..ea3f3c1 100644 --- a/src/components/Content.tsx +++ b/src/components/Content.tsx @@ -8,6 +8,7 @@ import { ConfigurationSection } from "./ConfigurationSection"; import { UsageInstructions } from "./UsageInstructions"; import { WikiButton } from "./WikiButton"; import { ClipboardButton } from "./ClipboardButton"; +import { PluginUpdateChecker } from "./PluginUpdateChecker"; import { ConfigurationData } from "../config/configSchema"; export function Content() { @@ -77,6 +78,9 @@ export function Content() { <WikiButton /> <ClipboardButton /> + + {/* Plugin Update Checker */} + <PluginUpdateChecker /> </PanelSection> ); } diff --git a/src/components/PluginUpdateChecker.tsx b/src/components/PluginUpdateChecker.tsx new file mode 100644 index 0000000..0028a79 --- /dev/null +++ b/src/components/PluginUpdateChecker.tsx @@ -0,0 +1,187 @@ +import React, { useState, useEffect } from 'react'; +import { + ButtonItem, + PanelSection +} from '@decky/ui'; +import { checkForPluginUpdate, downloadPluginUpdate, UpdateCheckResult, UpdateDownloadResult } from '../api/lsfgApi'; + +interface PluginUpdateCheckerProps { + // Add any props if needed +} + +interface UpdateInfo { + updateAvailable: boolean; + currentVersion: string; + latestVersion: string; + releaseNotes: string; + releaseDate: string; + downloadUrl: string; +} + +export const PluginUpdateChecker: React.FC<PluginUpdateCheckerProps> = () => { + const [checkingUpdate, setCheckingUpdate] = useState(false); + const [downloadingUpdate, setDownloadingUpdate] = useState(false); + const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null); + const [updateError, setUpdateError] = useState<string | null>(null); + const [downloadResult, setDownloadResult] = useState<UpdateDownloadResult | null>(null); + + // Auto-hide error messages after 5 seconds + useEffect(() => { + if (updateError) { + const timer = setTimeout(() => { + setUpdateError(null); + }, 5000); + return () => clearTimeout(timer); + } + return undefined; + }, [updateError]); + + const handleCheckForUpdate = async () => { + setCheckingUpdate(true); + setUpdateError(null); + setUpdateInfo(null); + setDownloadResult(null); // Clear previous download result + + try { + const result: UpdateCheckResult = await checkForPluginUpdate(); + + if (result.success) { + setUpdateInfo({ + updateAvailable: result.update_available, + currentVersion: result.current_version, + latestVersion: result.latest_version, + releaseNotes: result.release_notes, + releaseDate: result.release_date, + downloadUrl: result.download_url + }); + + // Simple console log instead of toast since showToast may not be available + if (result.update_available) { + console.log("Update available!", `Version ${result.latest_version} is now available.`); + } else { + console.log("Up to date!", "You have the latest version installed."); + } + } else { + setUpdateError(result.error || "Failed to check for updates"); + } + } catch (error) { + setUpdateError(`Error checking for updates: ${error}`); + } finally { + setCheckingUpdate(false); + } + }; + + const handleDownloadUpdate = async () => { + if (!updateInfo?.downloadUrl) return; + + setDownloadingUpdate(true); + setUpdateError(null); + setDownloadResult(null); + + try { + const result: UpdateDownloadResult = await downloadPluginUpdate(updateInfo.downloadUrl); + + if (result.success) { + setDownloadResult(result); + console.log("✓ Download complete!", `Plugin downloaded to ${result.download_path}`); + } else { + setUpdateError(result.error || "Failed to download update"); + } + } catch (error) { + setUpdateError(`Error downloading update: ${error}`); + } finally { + setDownloadingUpdate(false); + } + }; + + const getStatusMessage = () => { + if (!updateInfo) return null; + + if (updateInfo.updateAvailable) { + if (downloadResult?.success) { + return ( + <div style={{ color: 'lightgreen', marginTop: '5px' }}> + ✓ v{updateInfo.latestVersion} downloaded - ready to install + </div> + ); + } else { + return ( + <div style={{ color: 'orange', marginTop: '5px' }}> + Update available: v{updateInfo.latestVersion} + </div> + ); + } + } else { + return ( + <div style={{ color: 'lightgreen', marginTop: '5px' }}> + Up to date (v{updateInfo.currentVersion}) + </div> + ); + } + }; + + return ( + <PanelSection title="Plugin Updates"> + <ButtonItem + layout="below" + onClick={handleCheckForUpdate} + disabled={checkingUpdate} + description={getStatusMessage()} + > + {checkingUpdate ? 'Checking for updates...' : 'Check for Updates'} + </ButtonItem> + + {updateInfo && updateInfo.updateAvailable && !downloadResult?.success && ( + <ButtonItem + layout="below" + onClick={handleDownloadUpdate} + disabled={downloadingUpdate} + description={`Download version ${updateInfo.latestVersion}`} + > + {downloadingUpdate ? 'Downloading...' : 'Download Update'} + </ButtonItem> + )} + + {downloadResult?.success && ( + <div style={{ + marginTop: '10px', + padding: '10px', + backgroundColor: 'rgba(0, 255, 0, 0.1)', + borderRadius: '4px', + border: '1px solid rgba(0, 255, 0, 0.3)' + }}> + <div style={{ color: 'lightgreen', fontWeight: 'bold', marginBottom: '5px' }}> + ✓ Download Complete! + </div> + <div style={{ fontSize: '12px', marginBottom: '10px' }}> + File saved to: {downloadResult.download_path} + </div> + <div style={{ fontSize: '12px' }}> + <strong>Installation Instructions:</strong> + <ol style={{ paddingLeft: '20px', marginTop: '5px' }}> + <li>Go to Decky Loader settings</li> + <li>Click "Developer" tab</li> + <li>Click "Uninstall" next to "Lossless Scaling"</li> + <li>Click "Install from ZIP"</li> + <li>Select the downloaded file</li> + <li>Restart Steam or reload plugins</li> + </ol> + </div> + </div> + )} + + {updateError && ( + <div style={{ + color: 'red', + marginTop: '10px', + padding: '8px', + backgroundColor: 'rgba(255, 0, 0, 0.1)', + borderRadius: '4px', + fontSize: '12px' + }}> + {updateError} + </div> + )} + </PanelSection> + ); +}; diff --git a/src/components/index.ts b/src/components/index.ts index 7304ca9..d26159d 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -5,3 +5,4 @@ export { ConfigurationSection } from "./ConfigurationSection"; export { UsageInstructions } from "./UsageInstructions"; export { WikiButton } from "./WikiButton"; export { ClipboardButton } from "./ClipboardButton"; +export { PluginUpdateChecker } from "./PluginUpdateChecker"; |
