summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParty Wumpus <48649272+PartyWumpus@users.noreply.github.com>2024-03-01 23:07:51 +0000
committerParty Wumpus <48649272+PartyWumpus@users.noreply.github.com>2024-03-01 23:07:51 +0000
commit11b743a79285d458bf7ef31ac6f1c62ed46d7b86 (patch)
treee4bcc54bd54a8ae9f2275e57127ff90ed8b7acc9
parent637e3c566e3aee04c57de008a0a0a8b5e95b447f (diff)
downloaddecky-loader-11b743a79285d458bf7ef31ac6f1c62ed46d7b86.tar.gz
decky-loader-11b743a79285d458bf7ef31ac6f1c62ed46d7b86.zip
Add loading bar to testing page and make downloading more robust
-rw-r--r--backend/decky_loader/updater.py24
-rw-r--r--backend/locales/en-US.json4
-rw-r--r--frontend/src/components/settings/pages/general/Updater.tsx7
-rw-r--r--frontend/src/components/settings/pages/testing/index.tsx29
-rw-r--r--frontend/src/plugin-loader.tsx3
5 files changed, 51 insertions, 16 deletions
diff --git a/backend/decky_loader/updater.py b/backend/decky_loader/updater.py
index 268ab240..1957c59d 100644
--- a/backend/decky_loader/updater.py
+++ b/backend/decky_loader/updater.py
@@ -137,27 +137,30 @@ class Updater:
pass
await sleep(60 * 60 * 6) # 6 hours
- async def download_decky_binary(self, download_url: str, version: str, is_zip: bool = False):
+ async def download_decky_binary(self, download_url: str, version: str, is_zip: bool = False, size_in_bytes: int | None = None):
download_filename = "PluginLoader" if ON_LINUX else "PluginLoader.exe"
download_temp_filename = download_filename + ".new"
tab = await get_gamepadui_tab()
await tab.open_websocket()
+ if size_in_bytes == None:
+ size_in_bytes = 26214400 # 25MiB, a reasonable overestimate (19.6MiB as of 2024/02/25)
+
async with ClientSession() as web:
logger.debug("Downloading binary")
async with web.request("GET", download_url, ssl=helpers.get_ssl_context(), allow_redirects=True) as res:
- total = int(res.headers.get('content-length', 0))
+ total = int(res.headers.get('content-length', size_in_bytes))
+ if total == 0: total = 1
with open(path.join(getcwd(), download_temp_filename), "wb") as out:
progress = 0
raw = 0
async for c in res.content.iter_chunked(512):
out.write(c)
- if total != 0:
- raw += len(c)
- new_progress = round((raw / total) * 100)
- if progress != new_progress:
- self.context.loop.create_task(self.context.ws.emit("updater/update_download_percentage", new_progress))
- progress = new_progress
+ raw += len(c)
+ new_progress = round((raw / total) * 100)
+ if progress != new_progress:
+ self.context.loop.create_task(self.context.ws.emit("updater/update_download_percentage", new_progress))
+ progress = new_progress
with open(path.join(getcwd(), ".loader.version"), "w", encoding="utf-8") as out:
out.write(version)
@@ -277,9 +280,10 @@ class Updater:
#If the request found at least one artifact to download...
if int(jresp['total_count']) != 0:
# this assumes that the artifact we want is the first one!
- down_link = f"https://nightly.link/SteamDeckHomebrew/decky-loader/actions/artifacts/{jresp['artifacts'][0]['id']}.zip"
+ artifact = jresp['artifacts'][0]
+ down_link = f"https://nightly.link/SteamDeckHomebrew/decky-loader/actions/artifacts/{artifact['id']}.zip"
#Then fetch it and restart itself
- await self.download_decky_binary(down_link, f'PR-{pr_id}' , True)
+ await self.download_decky_binary(down_link, f'PR-{pr_id}', is_zip=True, size_in_bytes=artifact.get('size_in_bytes',None))
else:
logger.error("workflow run not found", str(works))
raise Exception("Workflow run not found.")
diff --git a/backend/locales/en-US.json b/backend/locales/en-US.json
index fe544dea..e1e0b9ea 100644
--- a/backend/locales/en-US.json
+++ b/backend/locales/en-US.json
@@ -267,6 +267,8 @@
"Testing": {
"download": "Download",
"header": "The following versions of Decky Loader are built from open third-party Pull Requests. The Decky Loader team has not verified their functionality or security, and they may be outdated.",
- "loading": "Loading open Pull Requests..."
+ "loading": "Loading open Pull Requests...",
+ "error": "Error Installing PR",
+ "start_download_toast": "Downloading PR #{{id}}"
}
}
diff --git a/frontend/src/components/settings/pages/general/Updater.tsx b/frontend/src/components/settings/pages/general/Updater.tsx
index 3c7e53f1..9fcc2dd3 100644
--- a/frontend/src/components/settings/pages/general/Updater.tsx
+++ b/frontend/src/components/settings/pages/general/Updater.tsx
@@ -66,7 +66,7 @@ function PatchNotesModal({ versionInfo, closeModal }: { versionInfo: VerInfo | n
}
export default function UpdaterSettings() {
- const { isLoaderUpdating, setIsLoaderUpdating, versionInfo, setVersionInfo } = useDeckyState();
+ const { isLoaderUpdating, versionInfo, setVersionInfo } = useDeckyState();
const [checkingForUpdates, setCheckingForUpdates] = useState<boolean>(false);
const [updateProgress, setUpdateProgress] = useState<number>(-1);
@@ -77,7 +77,6 @@ export default function UpdaterSettings() {
useEffect(() => {
const a = DeckyBackend.addEventListener('updater/update_download_percentage', (percentage) => {
setUpdateProgress(percentage);
- setIsLoaderUpdating(true);
});
const b = DeckyBackend.addEventListener('updater/finish_download', () => {
@@ -86,8 +85,8 @@ export default function UpdaterSettings() {
});
return () => {
- DeckyBackend.removeEventListener('frontend/update_download_percentage', a);
- DeckyBackend.removeEventListener('frontend/finish_download', b);
+ DeckyBackend.removeEventListener('updater/update_download_percentage', a);
+ DeckyBackend.removeEventListener('updater/finish_download', b);
};
}, []);
diff --git a/frontend/src/components/settings/pages/testing/index.tsx b/frontend/src/components/settings/pages/testing/index.tsx
index 4fe0f240..2467f3c5 100644
--- a/frontend/src/components/settings/pages/testing/index.tsx
+++ b/frontend/src/components/settings/pages/testing/index.tsx
@@ -5,6 +5,7 @@ import {
Field,
Focusable,
Navigation,
+ ProgressBar,
SteamSpinner,
} from 'decky-frontend-lib';
import { useEffect, useState } from 'react';
@@ -26,8 +27,11 @@ const downloadTestingVersion = DeckyBackend.callable<[pr_id: number, sha: string
export default function TestingVersionList() {
const { t } = useTranslation();
+
const [testingVersions, setTestingVersions] = useState<TestingVersion[]>([]);
const [loading, setLoading] = useState<boolean>(true);
+ const [updateProgress, setUpdateProgress] = useState<number | null>(null);
+ const [reloading, setReloading] = useState<boolean>(false);
useEffect(() => {
(async () => {
@@ -36,6 +40,21 @@ export default function TestingVersionList() {
})();
}, []);
+ useEffect(() => {
+ const a = DeckyBackend.addEventListener('updater/update_download_percentage', (percentage) => {
+ setUpdateProgress(percentage);
+ });
+
+ const b = DeckyBackend.addEventListener('updater/finish_download', () => {
+ setReloading(true);
+ });
+
+ return () => {
+ DeckyBackend.removeEventListener('updater/update_download_percentage', a);
+ DeckyBackend.removeEventListener('updater/finish_download', b);
+ };
+ }, []);
+
if (loading) {
return (
<>
@@ -54,6 +73,7 @@ export default function TestingVersionList() {
return (
<DialogBody>
+ {updateProgress !== null && <ProgressBar nProgress={updateProgress} indeterminate={reloading} />}
<DialogControlsSection>
<h4>{t('Testing.header')}</h4>
<ul style={{ listStyleType: 'none', padding: '0' }}>
@@ -71,11 +91,18 @@ export default function TestingVersionList() {
<DialogButton
style={{ height: '40px', minWidth: '60px', marginRight: '10px' }}
onClick={async () => {
+ DeckyPluginLoader.toaster.toast({
+ title: t('Testing.start_download_toast', { id: version.id }),
+ body: null,
+ });
try {
await downloadTestingVersion(version.id, version.head_sha);
} catch (e) {
if (e instanceof Error) {
- DeckyPluginLoader.toaster.toast({ title: 'Error Installing PR', body: e.message });
+ DeckyPluginLoader.toaster.toast({
+ title: t('Testing.error'),
+ body: `${e.name}: ${e.message}`,
+ });
}
}
setSetting('branch', UpdateBranch.Testing);
diff --git a/frontend/src/plugin-loader.tsx b/frontend/src/plugin-loader.tsx
index d9b1211e..7a87253f 100644
--- a/frontend/src/plugin-loader.tsx
+++ b/frontend/src/plugin-loader.tsx
@@ -78,6 +78,9 @@ class PluginLoader extends Logger {
'loader/add_multiple_plugins_install_prompt',
this.addMultiplePluginsInstallPrompt.bind(this),
);
+ DeckyBackend.addEventListener('updater/update_download_percentage', () => {
+ this.deckyState.setIsLoaderUpdating(true);
+ });
this.tabsHook.init();