Add Decky branch switcher and updater to error boundary (#775)

* Add Decky branch switcher and updater to error boundary

* Linting fixup

* Update DeckyErrorBoundary.tsx

Allow for plugins to trigger new behavior.

* Lint fixup
This commit is contained in:
marios
2025-06-29 21:36:48 +03:00
committed by GitHub
parent 078a9cf33d
commit 414493eed2
2 changed files with 83 additions and 1 deletions
+1 -1
View File
@@ -7,4 +7,4 @@ export default {
tabWidth: 2, tabWidth: 2,
endOfLine: 'auto', endOfLine: 'auto',
plugins: [importSort], plugins: [importSort],
} };
@@ -4,6 +4,8 @@ import { FunctionComponent, useEffect, useReducer, useState } from 'react';
import { uninstallPlugin } from '../plugin'; import { uninstallPlugin } from '../plugin';
import { VerInfo, doRestart, doShutdown } from '../updater'; import { VerInfo, doRestart, doShutdown } from '../updater';
import { ValveReactErrorInfo, getLikelyErrorSourceFromValveReactError } from '../utils/errors'; import { ValveReactErrorInfo, getLikelyErrorSourceFromValveReactError } from '../utils/errors';
import { useSetting } from '../utils/hooks/useSetting';
import { UpdateBranch } from './settings/pages/general/BranchSelect';
interface DeckyErrorBoundaryProps { interface DeckyErrorBoundaryProps {
error: ValveReactErrorInfo; error: ValveReactErrorInfo;
@@ -37,6 +39,27 @@ const DeckyErrorBoundary: FunctionComponent<DeckyErrorBoundaryProps> = ({ error,
if (!shouldReportToValve) DeckyPluginLoader.errorBoundaryHook.temporarilyDisableReporting(); if (!shouldReportToValve) DeckyPluginLoader.errorBoundaryHook.temporarilyDisableReporting();
DeckyPluginLoader.updateVersion().then(setVersionInfo); DeckyPluginLoader.updateVersion().then(setVersionInfo);
}, []); }, []);
const [selectedBranch, setSelectedBranch] = useSetting<UpdateBranch>('branch', UpdateBranch.Stable);
const [isChecking, setIsChecking] = useState<boolean>(false);
const [updateProgress, setUpdateProgress] = useState<number>(-1);
const [versionToUpdateTo, setSetVersionToUpdateTo] = useState<string>('');
useEffect(() => {
const a = DeckyBackend.addEventListener('updater/update_download_percentage', (percentage) => {
setUpdateProgress(percentage);
});
const b = DeckyBackend.addEventListener('updater/finish_download', () => {
setUpdateProgress(-2);
});
return () => {
DeckyBackend.removeEventListener('updater/update_download_percentage', a);
DeckyBackend.removeEventListener('updater/finish_download', b);
};
}, []);
return ( return (
<> <>
<style> <style>
@@ -149,6 +172,65 @@ const DeckyErrorBoundary: FunctionComponent<DeckyErrorBoundaryProps> = ({ error,
</button> </button>
</div> </div>
)} )}
{
<div style={{ display: 'block', marginBottom: '5px' }}>
{updateProgress > -1
? 'Update in progress... ' + updateProgress + '%'
: updateProgress == -2
? 'Update complete. Restarting...'
: 'Changing your Decky Loader branch and/or \n checking for updates might help!\n'}
{updateProgress == -1 && (
<div style={{ height: '30px' }}>
<select
style={{ height: '100%' }}
onChange={async (e) => {
const branch = parseInt(e.target.value);
setSelectedBranch(branch);
setSetVersionToUpdateTo('');
}}
>
<option value="0" selected={selectedBranch == UpdateBranch.Stable}>
Stable
</option>
<option value="1" selected={selectedBranch == UpdateBranch.Prerelease}>
Pre-Release
</option>
<option value="2" selected={selectedBranch == UpdateBranch.Testing}>
Testing
</option>
</select>
<button
style={{ height: '100%' }}
disabled={updateProgress != -1 || isChecking}
onClick={async () => {
if (versionToUpdateTo == '') {
setIsChecking(true);
const versionInfo = (await DeckyBackend.callable(
'updater/check_for_updates',
)()) as unknown as VerInfo;
setIsChecking(false);
if (versionInfo?.remote && versionInfo?.remote?.tag_name != versionInfo?.current) {
setSetVersionToUpdateTo(versionInfo.remote.tag_name);
} else {
setSetVersionToUpdateTo('');
}
} else {
DeckyBackend.callable('updater/do_update')();
setUpdateProgress(0);
}
}}
>
{' '}
{isChecking
? 'Checking for updates...'
: versionToUpdateTo != ''
? 'Update to ' + versionToUpdateTo
: 'Check for updates'}
</button>
</div>
)}
</div>
}
{wasCausedByPlugin && ( {wasCausedByPlugin && (
<div style={{ display: 'block', marginBottom: '5px' }}> <div style={{ display: 'block', marginBottom: '5px' }}>
{'\n'} {'\n'}