Updater for decky-loader (#117)

* Add an updater in settings for decky-loader

* add chmod

* remove junk comments
This commit is contained in:
AAGaming
2022-07-14 22:51:55 -04:00
committed by GitHub
parent 05d11cfff0
commit 8c8cf180fa
12 changed files with 353 additions and 111 deletions
+2
View File
@@ -27,6 +27,7 @@ from browser import PluginBrowser
from injector import inject_to_tab, tab_has_global_var from injector import inject_to_tab, tab_has_global_var
from loader import Loader from loader import Loader
from utilities import Utilities from utilities import Utilities
from updater import Updater
logger = getLogger("Main") logger = getLogger("Main")
@@ -47,6 +48,7 @@ class PluginManager:
self.plugin_loader = Loader(self.web_app, CONFIG["plugin_path"], self.loop, CONFIG["live_reload"]) self.plugin_loader = Loader(self.web_app, CONFIG["plugin_path"], self.loop, CONFIG["live_reload"])
self.plugin_browser = PluginBrowser(CONFIG["plugin_path"], self.web_app) self.plugin_browser = PluginBrowser(CONFIG["plugin_path"], self.web_app)
self.utilities = Utilities(self) self.utilities = Utilities(self)
self.updater = Updater(self)
jinja_setup(self.web_app) jinja_setup(self.web_app)
self.web_app.on_startup.append(self.inject_javascript) self.web_app.on_startup.append(self.inject_javascript)
+113
View File
@@ -0,0 +1,113 @@
import uuid
from logging import getLogger
from json.decoder import JSONDecodeError
from asyncio import sleep
from aiohttp import ClientSession, web
from injector import inject_to_tab, get_tab
from os import getcwd, path
from subprocess import call
import helpers
logger = getLogger("Updater")
class Updater:
def __init__(self, context) -> None:
self.context = context
self.updater_methods = {
"get_version": self.get_version,
"do_update": self.do_update,
"do_restart": self.do_restart
}
self.remoteVer = None
try:
with open(path.join(getcwd(), ".loader.version"), 'r') as version_file:
self.localVer = version_file.readline().replace("\n", "")
except:
self.localVer = False
if context:
context.web_app.add_routes([
web.post("/updater/{method_name}", self._handle_server_method_call)
])
context.loop.create_task(self.version_reloader())
async def _handle_server_method_call(self, request):
method_name = request.match_info["method_name"]
try:
args = await request.json()
except JSONDecodeError:
args = {}
res = {}
try:
r = await self.updater_methods[method_name](**args)
res["result"] = r
res["success"] = True
except Exception as e:
res["result"] = str(e)
res["success"] = False
return web.json_response(res)
async def get_version(self):
if self.localVer:
return {
"current": self.localVer,
"remote": self.remoteVer,
"updatable": self.remoteVer != None
}
else:
return {"current": "unknown", "updatable": False}
async def version_reloader(self):
while True:
try:
async with ClientSession() as web:
async with web.request("GET", "https://api.github.com/repos/SteamDeckHomebrew/decky-loader/releases", ssl=helpers.get_ssl_context()) as res:
remoteVersions = await res.json()
self.remoteVer = next(filter(lambda ver: ver["prerelease"] and ver["tag_name"].startswith("v") and ver["tag_name"].endswith("-pre"), remoteVersions), None)
logger.info("Updated remote version information")
except:
pass
await sleep(60 * 60) # 1 hour
async def do_update(self):
version = self.remoteVer["tag_name"]
#TODO don't hardcode this
download_url = self.remoteVer["assets"][0]["browser_download_url"]
tab = await get_tab("SP")
await tab.open_websocket()
async with ClientSession() as web:
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))
with open(path.join(getcwd(), "PluginLoader"), "wb") as out:
progress = 0
raw = 0
async for c in res.content.iter_chunked(512):
out.write(c)
raw += len(c)
new_progress = round((raw / total) * 100)
if progress != new_progress:
if new_progress - progress>= 2:
self.context.loop.create_task(tab.evaluate_js(f"window.DeckyUpdater.updateProgress({progress})", False, False))
progress = new_progress
with open(path.join(getcwd(), ".loader.version"), "w") as out:
out.write(version)
call(['chmod', '+x', path.join(getcwd(), "PluginLoader")])
logger.info("Updated loader installation.")
await tab.evaluate_js("window.DeckyUpdater.finish()", False, False)
await tab.client.close()
async def do_restart(self):
call(["systemctl", "daemon-reload"])
call(["systemctl", "restart", "plugin_loader"])
exit(0)
+8 -4
View File
@@ -12,10 +12,14 @@ sudo -u deck mkdir -p ${HOMEBREW_FOLDER}/services
sudo -u deck mkdir -p ${HOMEBREW_FOLDER}/plugins sudo -u deck mkdir -p ${HOMEBREW_FOLDER}/plugins
# Download latest release and install it # Download latest release and install it
DOWNLOADURL="$(curl -s 'https://api.github.com/repos/SteamDeckHomebrew/decky-loader/releases' | jq -r "first(.[] | select(.prerelease == "true"))" | jq -r ".assets[].browser_download_url")" RELEASES="$(curl -s 'https://api.github.com/repos/SteamDeckHomebrew/decky-loader/releases')"
RELEASE="$($RELEASES | jq -r "first(.[] | select(.prerelease == "true"))")"
VERSION="$($RELEASE | jq -r ".tag_name")"
DOWNLOADURL="$($RELEASE | jq -r ".assets[].browser_download_url")"
# printf "DOWNLOADURL=$DOWNLOADURL\n" # printf "DOWNLOADURL=$DOWNLOADURL\n"
curl -L $DOWNLOADURL --output ${HOMEBREW_FOLDER}/services/PluginLoader curl -L $DOWNLOADURL --output ${HOMEBREW_FOLDER}/services/PluginLoader
chmod +x ${HOMEBREW_FOLDER}/services/PluginLoader chmod +x ${HOMEBREW_FOLDER}/services/PluginLoader
echo $VERSION > ${HOMEBREW_FOLDER}/services/.loader.version
systemctl --user stop plugin_loader 2> /dev/null systemctl --user stop plugin_loader 2> /dev/null
systemctl --user disable plugin_loader 2> /dev/null systemctl --user disable plugin_loader 2> /dev/null
@@ -30,9 +34,9 @@ Description=SteamDeck Plugin Loader
Type=simple Type=simple
User=root User=root
Restart=always Restart=always
ExecStart=/home/deck/homebrew/services/PluginLoader ExecStart=${HOMEBREW_FOLDER}/services/PluginLoader
WorkingDirectory=/home/deck/homebrew/services WorkingDirectory=${HOMEBREW_FOLDER}/services
Environment=PLUGIN_PATH=/home/deck/homebrew/plugins Environment=PLUGIN_PATH=${HOMEBREW_FOLDER}/plugins
Environment=LOG_LEVEL=DEBUG Environment=LOG_LEVEL=DEBUG
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
+2 -2
View File
@@ -26,7 +26,7 @@
"prettier-plugin-import-sort": "^0.0.7", "prettier-plugin-import-sort": "^0.0.7",
"react": "16.14.0", "react": "16.14.0",
"react-dom": "16.14.0", "react-dom": "16.14.0",
"rollup": "^2.75.7", "rollup": "^2.76.0",
"tslib": "^2.4.0", "tslib": "^2.4.0",
"typescript": "^4.7.4" "typescript": "^4.7.4"
}, },
@@ -37,7 +37,7 @@
} }
}, },
"dependencies": { "dependencies": {
"decky-frontend-lib": "^1.0.2", "decky-frontend-lib": "^1.2.1",
"react-icons": "^4.4.0" "react-icons": "^4.4.0"
} }
} }
+100 -100
View File
@@ -9,7 +9,7 @@ specifiers:
'@types/react': 16.14.0 '@types/react': 16.14.0
'@types/react-router': 5.1.18 '@types/react-router': 5.1.18
'@types/webpack': ^5.28.0 '@types/webpack': ^5.28.0
decky-frontend-lib: ^1.0.2 decky-frontend-lib: ^1.2.1
husky: ^8.0.1 husky: ^8.0.1
import-sort-style-module: ^6.0.0 import-sort-style-module: ^6.0.0
inquirer: ^8.2.4 inquirer: ^8.2.4
@@ -18,20 +18,20 @@ specifiers:
react: 16.14.0 react: 16.14.0
react-dom: 16.14.0 react-dom: 16.14.0
react-icons: ^4.4.0 react-icons: ^4.4.0
rollup: ^2.75.7 rollup: ^2.76.0
tslib: ^2.4.0 tslib: ^2.4.0
typescript: ^4.7.4 typescript: ^4.7.4
dependencies: dependencies:
decky-frontend-lib: 1.0.2 decky-frontend-lib: 1.2.1
react-icons: 4.4.0_react@16.14.0 react-icons: 4.4.0_react@16.14.0
devDependencies: devDependencies:
'@rollup/plugin-commonjs': 21.1.0_rollup@2.75.7 '@rollup/plugin-commonjs': 21.1.0_rollup@2.76.0
'@rollup/plugin-json': 4.1.0_rollup@2.75.7 '@rollup/plugin-json': 4.1.0_rollup@2.76.0
'@rollup/plugin-node-resolve': 13.3.0_rollup@2.75.7 '@rollup/plugin-node-resolve': 13.3.0_rollup@2.76.0
'@rollup/plugin-replace': 4.0.0_rollup@2.75.7 '@rollup/plugin-replace': 4.0.0_rollup@2.76.0
'@rollup/plugin-typescript': 8.3.3_g4qkabtmybowem44p7ts7jnbqm '@rollup/plugin-typescript': 8.3.3_mrkdcqv53wzt2ybukxlrvz47fu
'@types/react': 16.14.0 '@types/react': 16.14.0
'@types/react-router': 5.1.18 '@types/react-router': 5.1.18
'@types/webpack': 5.28.0 '@types/webpack': 5.28.0
@@ -42,7 +42,7 @@ devDependencies:
prettier-plugin-import-sort: 0.0.7_prettier@2.7.1 prettier-plugin-import-sort: 0.0.7_prettier@2.7.1
react: 16.14.0 react: 16.14.0
react-dom: 16.14.0_react@16.14.0 react-dom: 16.14.0_react@16.14.0
rollup: 2.75.7 rollup: 2.76.0
tslib: 2.4.0 tslib: 2.4.0
typescript: 4.7.4 typescript: 4.7.4
@@ -63,8 +63,8 @@ packages:
'@babel/highlight': 7.18.6 '@babel/highlight': 7.18.6
dev: true dev: true
/@babel/compat-data/7.18.6: /@babel/compat-data/7.18.8:
resolution: {integrity: sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ==} resolution: {integrity: sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
@@ -76,12 +76,12 @@ packages:
'@babel/code-frame': 7.18.6 '@babel/code-frame': 7.18.6
'@babel/generator': 7.18.7 '@babel/generator': 7.18.7
'@babel/helper-compilation-targets': 7.18.6_@babel+core@7.18.6 '@babel/helper-compilation-targets': 7.18.6_@babel+core@7.18.6
'@babel/helper-module-transforms': 7.18.6 '@babel/helper-module-transforms': 7.18.8
'@babel/helpers': 7.18.6 '@babel/helpers': 7.18.6
'@babel/parser': 7.18.6 '@babel/parser': 7.18.8
'@babel/template': 7.18.6 '@babel/template': 7.18.6
'@babel/traverse': 7.18.6 '@babel/traverse': 7.18.8
'@babel/types': 7.18.7 '@babel/types': 7.18.8
convert-source-map: 1.8.0 convert-source-map: 1.8.0
debug: 4.3.4 debug: 4.3.4
gensync: 1.0.0-beta.2 gensync: 1.0.0-beta.2
@@ -95,7 +95,7 @@ packages:
resolution: {integrity: sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==} resolution: {integrity: sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.7 '@babel/types': 7.18.8
'@jridgewell/gen-mapping': 0.3.2 '@jridgewell/gen-mapping': 0.3.2
jsesc: 2.5.2 jsesc: 2.5.2
dev: true dev: true
@@ -106,10 +106,10 @@ packages:
peerDependencies: peerDependencies:
'@babel/core': ^7.0.0 '@babel/core': ^7.0.0
dependencies: dependencies:
'@babel/compat-data': 7.18.6 '@babel/compat-data': 7.18.8
'@babel/core': 7.18.6 '@babel/core': 7.18.6
'@babel/helper-validator-option': 7.18.6 '@babel/helper-validator-option': 7.18.6
browserslist: 4.21.1 browserslist: 4.21.2
semver: 6.3.0 semver: 6.3.0
dev: true dev: true
@@ -123,25 +123,25 @@ packages:
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/template': 7.18.6 '@babel/template': 7.18.6
'@babel/types': 7.18.7 '@babel/types': 7.18.8
dev: true dev: true
/@babel/helper-hoist-variables/7.18.6: /@babel/helper-hoist-variables/7.18.6:
resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.7 '@babel/types': 7.18.8
dev: true dev: true
/@babel/helper-module-imports/7.18.6: /@babel/helper-module-imports/7.18.6:
resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.7 '@babel/types': 7.18.8
dev: true dev: true
/@babel/helper-module-transforms/7.18.6: /@babel/helper-module-transforms/7.18.8:
resolution: {integrity: sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==} resolution: {integrity: sha512-che3jvZwIcZxrwh63VfnFTUzcAM9v/lznYkkRxIBGMPt1SudOKHAEec0SIRCfiuIzTcF7VGj/CaTT6gY4eWxvA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/helper-environment-visitor': 7.18.6 '@babel/helper-environment-visitor': 7.18.6
@@ -150,8 +150,8 @@ packages:
'@babel/helper-split-export-declaration': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6
'@babel/helper-validator-identifier': 7.18.6 '@babel/helper-validator-identifier': 7.18.6
'@babel/template': 7.18.6 '@babel/template': 7.18.6
'@babel/traverse': 7.18.6 '@babel/traverse': 7.18.8
'@babel/types': 7.18.7 '@babel/types': 7.18.8
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
@@ -160,14 +160,14 @@ packages:
resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==} resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.7 '@babel/types': 7.18.8
dev: true dev: true
/@babel/helper-split-export-declaration/7.18.6: /@babel/helper-split-export-declaration/7.18.6:
resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.7 '@babel/types': 7.18.8
dev: true dev: true
/@babel/helper-validator-identifier/7.18.6: /@babel/helper-validator-identifier/7.18.6:
@@ -185,8 +185,8 @@ packages:
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/template': 7.18.6 '@babel/template': 7.18.6
'@babel/traverse': 7.18.6 '@babel/traverse': 7.18.8
'@babel/types': 7.18.7 '@babel/types': 7.18.8
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
@@ -200,12 +200,12 @@ packages:
js-tokens: 4.0.0 js-tokens: 4.0.0
dev: true dev: true
/@babel/parser/7.18.6: /@babel/parser/7.18.8:
resolution: {integrity: sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw==} resolution: {integrity: sha512-RSKRfYX20dyH+elbJK2uqAkVyucL+xXzhqlMD5/ZXx+dAAwpyB7HsvnHe/ZUGOF+xLr5Wx9/JoXVTj6BQE2/oA==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
hasBin: true hasBin: true
dependencies: dependencies:
'@babel/types': 7.18.7 '@babel/types': 7.18.8
dev: true dev: true
/@babel/template/7.18.6: /@babel/template/7.18.6:
@@ -213,12 +213,12 @@ packages:
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/code-frame': 7.18.6 '@babel/code-frame': 7.18.6
'@babel/parser': 7.18.6 '@babel/parser': 7.18.8
'@babel/types': 7.18.7 '@babel/types': 7.18.8
dev: true dev: true
/@babel/traverse/7.18.6: /@babel/traverse/7.18.8:
resolution: {integrity: sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==} resolution: {integrity: sha512-UNg/AcSySJYR/+mIcJQDCv00T+AqRO7j/ZEJLzpaYtgM48rMg5MnkJgyNqkzo88+p4tfRvZJCEiwwfG6h4jkRg==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/code-frame': 7.18.6 '@babel/code-frame': 7.18.6
@@ -227,16 +227,16 @@ packages:
'@babel/helper-function-name': 7.18.6 '@babel/helper-function-name': 7.18.6
'@babel/helper-hoist-variables': 7.18.6 '@babel/helper-hoist-variables': 7.18.6
'@babel/helper-split-export-declaration': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6
'@babel/parser': 7.18.6 '@babel/parser': 7.18.8
'@babel/types': 7.18.7 '@babel/types': 7.18.8
debug: 4.3.4 debug: 4.3.4
globals: 11.12.0 globals: 11.12.0
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/@babel/types/7.18.7: /@babel/types/7.18.8:
resolution: {integrity: sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==} resolution: {integrity: sha512-qwpdsmraq0aJ3osLJRApsc2ouSJCdnMeZwB0DhbtHAtRpZNZCdlbRnHIgcRKzdE1g0iOGg644fzjOBcdOz9cPw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/helper-validator-identifier': 7.18.6 '@babel/helper-validator-identifier': 7.18.6
@@ -260,8 +260,8 @@ packages:
'@jridgewell/trace-mapping': 0.3.14 '@jridgewell/trace-mapping': 0.3.14
dev: true dev: true
/@jridgewell/resolve-uri/3.0.8: /@jridgewell/resolve-uri/3.1.0:
resolution: {integrity: sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==} resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
dev: true dev: true
@@ -284,61 +284,61 @@ packages:
/@jridgewell/trace-mapping/0.3.14: /@jridgewell/trace-mapping/0.3.14:
resolution: {integrity: sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==} resolution: {integrity: sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==}
dependencies: dependencies:
'@jridgewell/resolve-uri': 3.0.8 '@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.14 '@jridgewell/sourcemap-codec': 1.4.14
dev: true dev: true
/@rollup/plugin-commonjs/21.1.0_rollup@2.75.7: /@rollup/plugin-commonjs/21.1.0_rollup@2.76.0:
resolution: {integrity: sha512-6ZtHx3VHIp2ReNNDxHjuUml6ur+WcQ28N1yHgCQwsbNkQg2suhxGMDQGJOn/KuDxKtd1xuZP5xSTwBA4GQ8hbA==} resolution: {integrity: sha512-6ZtHx3VHIp2ReNNDxHjuUml6ur+WcQ28N1yHgCQwsbNkQg2suhxGMDQGJOn/KuDxKtd1xuZP5xSTwBA4GQ8hbA==}
engines: {node: '>= 8.0.0'} engines: {node: '>= 8.0.0'}
peerDependencies: peerDependencies:
rollup: ^2.38.3 rollup: ^2.38.3
dependencies: dependencies:
'@rollup/pluginutils': 3.1.0_rollup@2.75.7 '@rollup/pluginutils': 3.1.0_rollup@2.76.0
commondir: 1.0.1 commondir: 1.0.1
estree-walker: 2.0.2 estree-walker: 2.0.2
glob: 7.2.3 glob: 7.2.3
is-reference: 1.2.1 is-reference: 1.2.1
magic-string: 0.25.9 magic-string: 0.25.9
resolve: 1.22.1 resolve: 1.22.1
rollup: 2.75.7 rollup: 2.76.0
dev: true dev: true
/@rollup/plugin-json/4.1.0_rollup@2.75.7: /@rollup/plugin-json/4.1.0_rollup@2.76.0:
resolution: {integrity: sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==} resolution: {integrity: sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==}
peerDependencies: peerDependencies:
rollup: ^1.20.0 || ^2.0.0 rollup: ^1.20.0 || ^2.0.0
dependencies: dependencies:
'@rollup/pluginutils': 3.1.0_rollup@2.75.7 '@rollup/pluginutils': 3.1.0_rollup@2.76.0
rollup: 2.75.7 rollup: 2.76.0
dev: true dev: true
/@rollup/plugin-node-resolve/13.3.0_rollup@2.75.7: /@rollup/plugin-node-resolve/13.3.0_rollup@2.76.0:
resolution: {integrity: sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==} resolution: {integrity: sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
peerDependencies: peerDependencies:
rollup: ^2.42.0 rollup: ^2.42.0
dependencies: dependencies:
'@rollup/pluginutils': 3.1.0_rollup@2.75.7 '@rollup/pluginutils': 3.1.0_rollup@2.76.0
'@types/resolve': 1.17.1 '@types/resolve': 1.17.1
deepmerge: 4.2.2 deepmerge: 4.2.2
is-builtin-module: 3.1.0 is-builtin-module: 3.1.0
is-module: 1.0.0 is-module: 1.0.0
resolve: 1.22.1 resolve: 1.22.1
rollup: 2.75.7 rollup: 2.76.0
dev: true dev: true
/@rollup/plugin-replace/4.0.0_rollup@2.75.7: /@rollup/plugin-replace/4.0.0_rollup@2.76.0:
resolution: {integrity: sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==} resolution: {integrity: sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==}
peerDependencies: peerDependencies:
rollup: ^1.20.0 || ^2.0.0 rollup: ^1.20.0 || ^2.0.0
dependencies: dependencies:
'@rollup/pluginutils': 3.1.0_rollup@2.75.7 '@rollup/pluginutils': 3.1.0_rollup@2.76.0
magic-string: 0.25.9 magic-string: 0.25.9
rollup: 2.75.7 rollup: 2.76.0
dev: true dev: true
/@rollup/plugin-typescript/8.3.3_g4qkabtmybowem44p7ts7jnbqm: /@rollup/plugin-typescript/8.3.3_mrkdcqv53wzt2ybukxlrvz47fu:
resolution: {integrity: sha512-55L9SyiYu3r/JtqdjhwcwaECXP7JeJ9h1Sg1VWRJKIutla2MdZQodTgcCNybXLMCnqpNLEhS2vGENww98L1npg==} resolution: {integrity: sha512-55L9SyiYu3r/JtqdjhwcwaECXP7JeJ9h1Sg1VWRJKIutla2MdZQodTgcCNybXLMCnqpNLEhS2vGENww98L1npg==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
peerDependencies: peerDependencies:
@@ -349,14 +349,14 @@ packages:
tslib: tslib:
optional: true optional: true
dependencies: dependencies:
'@rollup/pluginutils': 3.1.0_rollup@2.75.7 '@rollup/pluginutils': 3.1.0_rollup@2.76.0
resolve: 1.22.1 resolve: 1.22.1
rollup: 2.75.7 rollup: 2.76.0
tslib: 2.4.0 tslib: 2.4.0
typescript: 4.7.4 typescript: 4.7.4
dev: true dev: true
/@rollup/pluginutils/3.1.0_rollup@2.75.7: /@rollup/pluginutils/3.1.0_rollup@2.76.0:
resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
engines: {node: '>= 8.0.0'} engines: {node: '>= 8.0.0'}
peerDependencies: peerDependencies:
@@ -365,18 +365,18 @@ packages:
'@types/estree': 0.0.39 '@types/estree': 0.0.39
estree-walker: 1.0.1 estree-walker: 1.0.1
picomatch: 2.3.1 picomatch: 2.3.1
rollup: 2.75.7 rollup: 2.76.0
dev: true dev: true
/@types/eslint-scope/3.7.4: /@types/eslint-scope/3.7.4:
resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==}
dependencies: dependencies:
'@types/eslint': 8.4.3 '@types/eslint': 8.4.5
'@types/estree': 0.0.51 '@types/estree': 0.0.51
dev: true dev: true
/@types/eslint/8.4.3: /@types/eslint/8.4.5:
resolution: {integrity: sha512-YP1S7YJRMPs+7KZKDb9G63n8YejIwW9BALq7a5j2+H4yl6iOv9CB29edho+cuFRrvmJbbaH2yiVChKLJVysDGw==} resolution: {integrity: sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==}
dependencies: dependencies:
'@types/estree': 0.0.51 '@types/estree': 0.0.51
'@types/json-schema': 7.0.11 '@types/json-schema': 7.0.11
@@ -390,8 +390,8 @@ packages:
resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==}
dev: true dev: true
/@types/estree/0.0.52: /@types/estree/1.0.0:
resolution: {integrity: sha512-BZWrtCU0bMVAIliIV+HJO1f1PR41M7NKjfxrFJwwhKI1KwhwOxYw1SXg9ao+CIMt774nFuGiG6eU+udtbEI9oQ==} resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==}
dev: true dev: true
/@types/history/4.7.11: /@types/history/4.7.11:
@@ -402,8 +402,8 @@ packages:
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
dev: true dev: true
/@types/node/18.0.0: /@types/node/18.0.4:
resolution: {integrity: sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==} resolution: {integrity: sha512-M0+G6V0Y4YV8cqzHssZpaNCqvYwlCiulmm0PwpNLF55r/+cT8Ol42CHRU1SEaYFH2rTwiiE1aYg/2g2rrtGdPA==}
dev: true dev: true
/@types/prop-types/15.7.5: /@types/prop-types/15.7.5:
@@ -427,13 +427,13 @@ packages:
/@types/resolve/1.17.1: /@types/resolve/1.17.1:
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
dependencies: dependencies:
'@types/node': 18.0.0 '@types/node': 18.0.4
dev: true dev: true
/@types/webpack/5.28.0: /@types/webpack/5.28.0:
resolution: {integrity: sha512-8cP0CzcxUiFuA9xGJkfeVpqmWTk9nx6CWwamRGCj95ph1SmlRRk9KlCZ6avhCbZd4L68LvYT6l1kpdEnQXrF8w==} resolution: {integrity: sha512-8cP0CzcxUiFuA9xGJkfeVpqmWTk9nx6CWwamRGCj95ph1SmlRRk9KlCZ6avhCbZd4L68LvYT6l1kpdEnQXrF8w==}
dependencies: dependencies:
'@types/node': 18.0.0 '@types/node': 18.0.4
tapable: 2.2.1 tapable: 2.2.1
webpack: 5.73.0 webpack: 5.73.0
transitivePeerDependencies: transitivePeerDependencies:
@@ -643,15 +643,15 @@ packages:
concat-map: 0.0.1 concat-map: 0.0.1
dev: true dev: true
/browserslist/4.21.1: /browserslist/4.21.2:
resolution: {integrity: sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==} resolution: {integrity: sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true hasBin: true
dependencies: dependencies:
caniuse-lite: 1.0.30001361 caniuse-lite: 1.0.30001366
electron-to-chromium: 1.4.174 electron-to-chromium: 1.4.189
node-releases: 2.0.5 node-releases: 2.0.6
update-browserslist-db: 1.0.4_browserslist@4.21.1 update-browserslist-db: 1.0.4_browserslist@4.21.2
dev: true dev: true
/buffer-from/1.1.2: /buffer-from/1.1.2:
@@ -689,8 +689,8 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/caniuse-lite/1.0.30001361: /caniuse-lite/1.0.30001366:
resolution: {integrity: sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ==} resolution: {integrity: sha512-yy7XLWCubDobokgzudpkKux8e0UOOnLHE6mlNJBzT3lZJz6s5atSEzjoL+fsCPkI0G8MP5uVdDx1ur/fXEWkZA==}
dev: true dev: true
/chalk/2.4.2: /chalk/2.4.2:
@@ -771,7 +771,7 @@ packages:
dev: true dev: true
/concat-map/0.0.1: /concat-map/0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
dev: true dev: true
/convert-source-map/1.8.0: /convert-source-map/1.8.0:
@@ -806,8 +806,8 @@ packages:
ms: 2.1.2 ms: 2.1.2
dev: true dev: true
/decky-frontend-lib/1.0.2: /decky-frontend-lib/1.2.1:
resolution: {integrity: sha512-l2Fq1oKkZdi2W4Qq+EXWgwOynWgANLTSFHcHrbJwCimTJ75uPlvrtsulnh5PlIovydM6iC+NyjAbW/qsVXWeLg==} resolution: {integrity: sha512-aJmjOSMwQN9LTquYaMhSqW+FhmKLRgLb75JkcGRWKuIe8rjDfwwbAB/ckJseIC8UMzPKhspvcznfxyp+c72B5Q==}
dev: false dev: false
/deepmerge/4.2.2: /deepmerge/4.2.2:
@@ -826,8 +826,8 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true dev: true
/electron-to-chromium/1.4.174: /electron-to-chromium/1.4.189:
resolution: {integrity: sha512-JER+w+9MV2MBVFOXxP036bLlNOnzbYAWrWU8sNUwoOO69T3w4564WhM5H5atd8VVS8U4vpi0i0kdoYzm1NPQgQ==} resolution: {integrity: sha512-dQ6Zn4ll2NofGtxPXaDfY2laIa6NyCQdqXYHdwH90GJQW0LpJJib0ZU/ERtbb0XkBEmUD2eJtagbOie3pdMiPg==}
dev: true dev: true
/emoji-regex/8.0.0: /emoji-regex/8.0.0:
@@ -1038,9 +1038,9 @@ packages:
resolution: {integrity: sha512-NyShTiNhTh4Vy7kJUVe6CuvOaQAzzfSIT72wtp3CzGjz8bHjNj59DCAjncuviicmDOgVAgmLuSh1WMcLYAMWGg==} resolution: {integrity: sha512-NyShTiNhTh4Vy7kJUVe6CuvOaQAzzfSIT72wtp3CzGjz8bHjNj59DCAjncuviicmDOgVAgmLuSh1WMcLYAMWGg==}
dependencies: dependencies:
'@babel/core': 7.18.6 '@babel/core': 7.18.6
'@babel/parser': 7.18.6 '@babel/parser': 7.18.8
'@babel/traverse': 7.18.6 '@babel/traverse': 7.18.8
'@babel/types': 7.18.7 '@babel/types': 7.18.8
find-line-column: 0.5.2 find-line-column: 0.5.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -1099,7 +1099,7 @@ packages:
mute-stream: 0.0.8 mute-stream: 0.0.8
ora: 5.4.1 ora: 5.4.1
run-async: 2.4.1 run-async: 2.4.1
rxjs: 7.5.5 rxjs: 7.5.6
string-width: 4.2.3 string-width: 4.2.3
strip-ansi: 6.0.1 strip-ansi: 6.0.1
through: 2.3.8 through: 2.3.8
@@ -1145,7 +1145,7 @@ packages:
/is-reference/1.2.1: /is-reference/1.2.1:
resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
dependencies: dependencies:
'@types/estree': 0.0.52 '@types/estree': 1.0.0
dev: true dev: true
/is-unicode-supported/0.1.0: /is-unicode-supported/0.1.0:
@@ -1157,7 +1157,7 @@ packages:
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
engines: {node: '>= 10.13.0'} engines: {node: '>= 10.13.0'}
dependencies: dependencies:
'@types/node': 18.0.0 '@types/node': 18.0.4
merge-stream: 2.0.0 merge-stream: 2.0.0
supports-color: 8.1.1 supports-color: 8.1.1
dev: true dev: true
@@ -1265,8 +1265,8 @@ packages:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
dev: true dev: true
/node-releases/2.0.5: /node-releases/2.0.6:
resolution: {integrity: sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==} resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==}
dev: true dev: true
/object-assign/4.1.1: /object-assign/4.1.1:
@@ -1437,8 +1437,8 @@ packages:
signal-exit: 3.0.7 signal-exit: 3.0.7
dev: true dev: true
/rollup/2.75.7: /rollup/2.76.0:
resolution: {integrity: sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==} resolution: {integrity: sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
hasBin: true hasBin: true
optionalDependencies: optionalDependencies:
@@ -1450,8 +1450,8 @@ packages:
engines: {node: '>=0.12.0'} engines: {node: '>=0.12.0'}
dev: true dev: true
/rxjs/7.5.5: /rxjs/7.5.6:
resolution: {integrity: sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==} resolution: {integrity: sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==}
dependencies: dependencies:
tslib: 2.4.0 tslib: 2.4.0
dev: true dev: true
@@ -1592,12 +1592,12 @@ packages:
jest-worker: 27.5.1 jest-worker: 27.5.1
schema-utils: 3.1.1 schema-utils: 3.1.1
serialize-javascript: 6.0.0 serialize-javascript: 6.0.0
terser: 5.14.1 terser: 5.14.2
webpack: 5.73.0 webpack: 5.73.0
dev: true dev: true
/terser/5.14.1: /terser/5.14.2:
resolution: {integrity: sha512-+ahUAE+iheqBTDxXhTisdA8hgvbEG1hHOQ9xmNjeUJSoi6DU/gMrKNcfZjHkyY6Alnuyc+ikYJaxxfHkT3+WuQ==} resolution: {integrity: sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==}
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true hasBin: true
dependencies: dependencies:
@@ -1644,13 +1644,13 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/update-browserslist-db/1.0.4_browserslist@4.21.1: /update-browserslist-db/1.0.4_browserslist@4.21.2:
resolution: {integrity: sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==} resolution: {integrity: sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
browserslist: '>= 4.21.0' browserslist: '>= 4.21.0'
dependencies: dependencies:
browserslist: 4.21.1 browserslist: 4.21.2
escalade: 3.1.1 escalade: 3.1.1
picocolors: 1.0.0 picocolors: 1.0.0
dev: true dev: true
@@ -1701,7 +1701,7 @@ packages:
'@webassemblyjs/wasm-parser': 1.11.1 '@webassemblyjs/wasm-parser': 1.11.1
acorn: 8.7.1 acorn: 8.7.1
acorn-import-assertions: 1.8.0_acorn@8.7.1 acorn-import-assertions: 1.8.0_acorn@8.7.1
browserslist: 4.21.1 browserslist: 4.21.2
chrome-trace-event: 1.0.3 chrome-trace-event: 1.0.3
enhanced-resolve: 5.10.0 enhanced-resolve: 5.10.0
es-module-lexer: 0.9.3 es-module-lexer: 0.9.3
+2 -2
View File
@@ -1,7 +1,7 @@
import { SidebarNavigation } from 'decky-frontend-lib'; import { SidebarNavigation } from 'decky-frontend-lib';
import GeneralSettings from './pages/GeneralSettings'; import GeneralSettings from './pages/general';
import PluginList from './pages/PluginList'; import PluginList from './pages/plugin_list';
export default function SettingsPage() { export default function SettingsPage() {
return ( return (
@@ -0,0 +1,86 @@
import { DialogButton, Field, ProgressBarWithInfo, Spinner, sleep } from 'decky-frontend-lib';
import { useEffect, useState } from 'react';
import { FaArrowDown } from 'react-icons/fa';
import { callUpdaterMethod, finishUpdate } from '../../../../updater';
interface VerInfo {
current: string;
remote: {
assets: {
browser_download_url: string;
created_at: string;
}[];
name: string;
body: string;
prerelease: boolean;
published_at: string;
tag_name: string;
} | null;
updatable: boolean;
}
export default function UpdaterSettings() {
const [versionInfo, setVersionInfo] = useState<VerInfo | null>(null);
const [updateProgress, setUpdateProgress] = useState<number>(-1);
const [reloading, setReloading] = useState<boolean>(false);
useEffect(() => {
(async () => {
const res = (await callUpdaterMethod('get_version')) as { result: VerInfo };
setVersionInfo(res.result);
})();
}, []);
return (
<Field
label="Updates"
description={
versionInfo && (
<span style={{ whiteSpace: 'pre-line' }}>{`Current version: ${versionInfo.current}\n${
versionInfo.updatable ? `Latest version: ${versionInfo.remote?.tag_name}` : ''
}`}</span>
)
}
icon={
!versionInfo ? (
<Spinner style={{ width: '1em', height: 20, display: 'block' }} />
) : (
<FaArrowDown style={{ display: 'block' }} />
)
}
>
{updateProgress == -1 ? (
<DialogButton
disabled={
!versionInfo?.updatable || !versionInfo?.remote || versionInfo.remote.tag_name == versionInfo.current
}
onClick={async () => {
window.DeckyUpdater = {
updateProgress: (i) => {
setUpdateProgress(i);
},
finish: async () => {
setUpdateProgress(0);
setReloading(true);
await finishUpdate();
},
};
setUpdateProgress(0);
callUpdaterMethod('do_update');
}}
>
Update
</DialogButton>
) : (
<ProgressBarWithInfo
layout="inline"
bottomSeparator={false}
nProgress={updateProgress}
nTransitionSec={0.01}
indeterminate={reloading}
sOperationText={reloading ? 'Reloading' : 'Updating'}
/>
)}
</Field>
);
}
@@ -2,7 +2,8 @@ import { DialogButton, Field, TextField } from 'decky-frontend-lib';
import { useState } from 'react'; import { useState } from 'react';
import { FaShapes } from 'react-icons/fa'; import { FaShapes } from 'react-icons/fa';
import { installFromURL } from '../../store/Store'; import { installFromURL } from '../../../store/Store';
import UpdaterSettings from './Updater';
export default function GeneralSettings() { export default function GeneralSettings() {
const [pluginURL, setPluginURL] = useState(''); const [pluginURL, setPluginURL] = useState('');
@@ -18,12 +19,15 @@ export default function GeneralSettings() {
onChange={(e) => setChecked(e)} onChange={(e) => setChecked(e)}
/> />
</Field> */} </Field> */}
<UpdaterSettings />
<Field <Field
label="Manual plugin install" label="Manual plugin install"
description={<TextField label={'URL'} value={pluginURL} onChange={(e) => setPluginURL(e?.target.value)} />} description={<TextField label={'URL'} value={pluginURL} onChange={(e) => setPluginURL(e?.target.value)} />}
icon={<FaShapes style={{ display: 'block' }} />} icon={<FaShapes style={{ display: 'block' }} />}
> >
<DialogButton onClick={() => installFromURL(pluginURL)}>Install</DialogButton> <DialogButton disabled={pluginURL.length == 0} onClick={() => installFromURL(pluginURL)}>
Install
</DialogButton>
</Field> </Field>
</div> </div>
); );
@@ -1,7 +1,7 @@
import { DialogButton, staticClasses } from 'decky-frontend-lib'; import { DialogButton, staticClasses } from 'decky-frontend-lib';
import { FaTrash } from 'react-icons/fa'; import { FaTrash } from 'react-icons/fa';
import { useDeckyState } from '../../DeckyState'; import { useDeckyState } from '../../../DeckyState';
export default function PluginList() { export default function PluginList() {
const { plugins } = useDeckyState(); const { plugins } = useDeckyState();
+2
View File
@@ -1,8 +1,10 @@
import PluginLoader from './plugin-loader'; import PluginLoader from './plugin-loader';
import { DeckyUpdater } from './updater';
declare global { declare global {
interface Window { interface Window {
DeckyPluginLoader: PluginLoader; DeckyPluginLoader: PluginLoader;
DeckyUpdater?: DeckyUpdater;
importDeckyPlugin: Function; importDeckyPlugin: Function;
syncDeckyPlugins: Function; syncDeckyPlugins: Function;
} }
+30
View File
@@ -0,0 +1,30 @@
import { sleep } from 'decky-frontend-lib';
export enum Branches {
Release,
Prerelease,
Nightly,
}
export interface DeckyUpdater {
updateProgress: (val: number) => void;
finish: () => void;
}
export async function callUpdaterMethod(methodName: string, args = {}) {
const response = await fetch(`http://127.0.0.1:1337/updater/${methodName}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(args),
});
return response.json();
}
export async function finishUpdate() {
callUpdaterMethod('do_restart');
await sleep(3000);
location.reload();
}
+1
View File
@@ -5,6 +5,7 @@
"target": "ES2020", "target": "ES2020",
"jsx": "react", "jsx": "react",
"jsxFactory": "window.SP_REACT.createElement", "jsxFactory": "window.SP_REACT.createElement",
"jsxFragmentFactory": "window.SP_REACT.Fragment",
"declaration": false, "declaration": false,
"moduleResolution": "node", "moduleResolution": "node",
"noUnusedLocals": true, "noUnusedLocals": true,