mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-06-17 08:47:49 +00:00
Compare commits
13 Commits
v2.4.3
...
v2.4.6-pre5
| Author | SHA1 | Date | |
|---|---|---|---|
| 0474095a40 | |||
| 346f80beb3 | |||
| 2a6bf75f02 | |||
| f73918c902 | |||
| ea35af2050 | |||
| 6232e3da58 | |||
| 35e46f9ccb | |||
| 2b9a80c151 | |||
| a90ed38c89 | |||
| 3653cf5640 | |||
| 0db45ca71e | |||
| 16681fabb5 | |||
| c210523a22 |
@@ -31,7 +31,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build PluginLoader
|
name: Build PluginLoader
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Print input
|
- name: Print input
|
||||||
|
|||||||
+2
-2
@@ -55,7 +55,7 @@ class PluginBrowser:
|
|||||||
pluginBinPath = path.join(pluginBasePath, 'bin')
|
pluginBinPath = path.join(pluginBasePath, 'bin')
|
||||||
|
|
||||||
if access(packageJsonPath, R_OK):
|
if access(packageJsonPath, R_OK):
|
||||||
with open(packageJsonPath, 'r') as f:
|
with open(packageJsonPath, "r", encoding="utf-8") as f:
|
||||||
packageJson = json.load(f)
|
packageJson = json.load(f)
|
||||||
if "remote_binary" in packageJson and len(packageJson["remote_binary"]) > 0:
|
if "remote_binary" in packageJson and len(packageJson["remote_binary"]) > 0:
|
||||||
# create bin directory if needed.
|
# create bin directory if needed.
|
||||||
@@ -93,7 +93,7 @@ class PluginBrowser:
|
|||||||
def find_plugin_folder(self, name):
|
def find_plugin_folder(self, name):
|
||||||
for folder in listdir(self.plugin_path):
|
for folder in listdir(self.plugin_path):
|
||||||
try:
|
try:
|
||||||
with open(path.join(self.plugin_path, folder, 'plugin.json'), 'r') as f:
|
with open(path.join(self.plugin_path, folder, 'plugin.json'), "r", encoding="utf-8") as f:
|
||||||
plugin = json.load(f)
|
plugin = json.load(f)
|
||||||
|
|
||||||
if plugin['name'] == name:
|
if plugin['name'] == name:
|
||||||
|
|||||||
+3
-3
@@ -118,7 +118,7 @@ class Loader:
|
|||||||
def handle_frontend_bundle(self, request):
|
def handle_frontend_bundle(self, request):
|
||||||
plugin = self.plugins[request.match_info["plugin_name"]]
|
plugin = self.plugins[request.match_info["plugin_name"]]
|
||||||
|
|
||||||
with open(path.join(self.plugin_path, plugin.plugin_directory, "dist/index.js"), 'r') as bundle:
|
with open(path.join(self.plugin_path, plugin.plugin_directory, "dist/index.js"), "r", encoding="utf-8") as bundle:
|
||||||
return web.Response(text=bundle.read(), content_type="application/javascript")
|
return web.Response(text=bundle.read(), content_type="application/javascript")
|
||||||
|
|
||||||
def import_plugin(self, file, plugin_directory, refresh=False, batch=False):
|
def import_plugin(self, file, plugin_directory, refresh=False, batch=False):
|
||||||
@@ -186,7 +186,7 @@ class Loader:
|
|||||||
"""
|
"""
|
||||||
async def load_plugin_main_view(self, request):
|
async def load_plugin_main_view(self, request):
|
||||||
plugin = self.plugins[request.match_info["name"]]
|
plugin = self.plugins[request.match_info["name"]]
|
||||||
with open(path.join(self.plugin_path, plugin.plugin_directory, plugin.main_view_html), 'r') as template:
|
with open(path.join(self.plugin_path, plugin.plugin_directory, plugin.main_view_html), "r", encoding="utf-8") as template:
|
||||||
template_data = template.read()
|
template_data = template.read()
|
||||||
ret = f"""
|
ret = f"""
|
||||||
<script src="/legacy/library.js"></script>
|
<script src="/legacy/library.js"></script>
|
||||||
@@ -202,7 +202,7 @@ class Loader:
|
|||||||
self.logger.info(path)
|
self.logger.info(path)
|
||||||
ret = ""
|
ret = ""
|
||||||
file_path = path.join(self.plugin_path, plugin.plugin_directory, route_path)
|
file_path = path.join(self.plugin_path, plugin.plugin_directory, route_path)
|
||||||
with open(file_path, 'r') as resource_data:
|
with open(file_path, "r", encoding="utf-8") as resource_data:
|
||||||
ret = resource_data.read()
|
ret = resource_data.read()
|
||||||
|
|
||||||
return web.Response(text=ret)
|
return web.Response(text=ret)
|
||||||
|
|||||||
+5
-5
@@ -27,9 +27,9 @@ class PluginWrapper:
|
|||||||
|
|
||||||
self.version = None
|
self.version = None
|
||||||
|
|
||||||
json = load(open(path.join(plugin_path, plugin_directory, "plugin.json"), "r"))
|
json = load(open(path.join(plugin_path, plugin_directory, "plugin.json"), "r", encoding="utf-8"))
|
||||||
if path.isfile(path.join(plugin_path, plugin_directory, "package.json")):
|
if path.isfile(path.join(plugin_path, plugin_directory, "package.json")):
|
||||||
package_json = load(open(path.join(plugin_path, plugin_directory, "package.json"), "r"))
|
package_json = load(open(path.join(plugin_path, plugin_directory, "package.json"), "r", encoding="utf-8"))
|
||||||
self.version = package_json["version"]
|
self.version = package_json["version"]
|
||||||
|
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ class PluginWrapper:
|
|||||||
d["res"] = str(e)
|
d["res"] = str(e)
|
||||||
d["success"] = False
|
d["success"] = False
|
||||||
finally:
|
finally:
|
||||||
writer.write((dumps(d)+"\n").encode("utf-8"))
|
writer.write((dumps(d, ensure_ascii=False)+"\n").encode("utf-8"))
|
||||||
await writer.drain()
|
await writer.drain()
|
||||||
|
|
||||||
async def _open_socket_if_not_exists(self):
|
async def _open_socket_if_not_exists(self):
|
||||||
@@ -140,7 +140,7 @@ class PluginWrapper:
|
|||||||
return
|
return
|
||||||
async def _(self):
|
async def _(self):
|
||||||
if await self._open_socket_if_not_exists():
|
if await self._open_socket_if_not_exists():
|
||||||
self.writer.write((dumps({"stop": True})+"\n").encode("utf-8"))
|
self.writer.write((dumps({ "stop": True }, ensure_ascii=False)+"\n").encode("utf-8"))
|
||||||
await self.writer.drain()
|
await self.writer.drain()
|
||||||
self.writer.close()
|
self.writer.close()
|
||||||
get_event_loop().create_task(_(self))
|
get_event_loop().create_task(_(self))
|
||||||
@@ -151,7 +151,7 @@ class PluginWrapper:
|
|||||||
async with self.method_call_lock:
|
async with self.method_call_lock:
|
||||||
if await self._open_socket_if_not_exists():
|
if await self._open_socket_if_not_exists():
|
||||||
self.writer.write(
|
self.writer.write(
|
||||||
(dumps({"method": method_name, "args": kwargs})+"\n").encode("utf-8"))
|
(dumps({ "method": method_name, "args": kwargs }, ensure_ascii=False) + "\n").encode("utf-8"))
|
||||||
await self.writer.drain()
|
await self.writer.drain()
|
||||||
line = bytearray()
|
line = bytearray()
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
+4
-4
@@ -35,22 +35,22 @@ class SettingsManager:
|
|||||||
self.settings = {}
|
self.settings = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
open(self.path, "x")
|
open(self.path, "x", encoding="utf-8")
|
||||||
except FileExistsError as e:
|
except FileExistsError as e:
|
||||||
self.read()
|
self.read()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def read(self):
|
def read(self):
|
||||||
try:
|
try:
|
||||||
with open(self.path, "r") as file:
|
with open(self.path, "r", encoding="utf-8") as file:
|
||||||
self.settings = load(file)
|
self.settings = load(file)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def commit(self):
|
def commit(self):
|
||||||
with open(self.path, "w+") as file:
|
with open(self.path, "w+", encoding="utf-8") as file:
|
||||||
dump(self.settings, file, indent=4)
|
dump(self.settings, file, indent=4, ensure_ascii=False)
|
||||||
|
|
||||||
def getSetting(self, key, default):
|
def getSetting(self, key, default):
|
||||||
return self.settings.get(key, default)
|
return self.settings.get(key, default)
|
||||||
|
|||||||
+4
-4
@@ -32,7 +32,7 @@ class Updater:
|
|||||||
self.allRemoteVers = None
|
self.allRemoteVers = None
|
||||||
try:
|
try:
|
||||||
logger.info(getcwd())
|
logger.info(getcwd())
|
||||||
with open(path.join(getcwd(), ".loader.version"), 'r') as version_file:
|
with open(path.join(getcwd(), ".loader.version"), "r", encoding="utf-8") as version_file:
|
||||||
self.localVer = version_file.readline().replace("\n", "")
|
self.localVer = version_file.readline().replace("\n", "")
|
||||||
except:
|
except:
|
||||||
self.localVer = False
|
self.localVer = False
|
||||||
@@ -159,10 +159,10 @@ class Updater:
|
|||||||
out.write(data)
|
out.write(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error at %s", exc_info=e)
|
logger.error(f"Error at %s", exc_info=e)
|
||||||
with open(path.join(getcwd(), "plugin_loader.service"), 'r') as service_file:
|
with open(path.join(getcwd(), "plugin_loader.service"), "r", encoding="utf-8") as service_file:
|
||||||
service_data = service_file.read()
|
service_data = service_file.read()
|
||||||
service_data = service_data.replace("${HOMEBREW_FOLDER}", "/home/"+helpers.get_user()+"/homebrew")
|
service_data = service_data.replace("${HOMEBREW_FOLDER}", "/home/"+helpers.get_user()+"/homebrew")
|
||||||
with open(path.join(getcwd(), "plugin_loader.service"), 'w') as service_file:
|
with open(path.join(getcwd(), "plugin_loader.service"), "w", encoding="utf-8") as service_file:
|
||||||
service_file.write(service_data)
|
service_file.write(service_data)
|
||||||
|
|
||||||
logger.debug("Saved service file")
|
logger.debug("Saved service file")
|
||||||
@@ -191,7 +191,7 @@ class Updater:
|
|||||||
self.context.loop.create_task(tab.evaluate_js(f"window.DeckyUpdater.updateProgress({new_progress})", False, False, False))
|
self.context.loop.create_task(tab.evaluate_js(f"window.DeckyUpdater.updateProgress({new_progress})", False, False, False))
|
||||||
progress = new_progress
|
progress = new_progress
|
||||||
|
|
||||||
with open(path.join(getcwd(), ".loader.version"), "w") as out:
|
with open(path.join(getcwd(), ".loader.version"), "w", encoding="utf-8") as out:
|
||||||
out.write(version)
|
out.write(version)
|
||||||
|
|
||||||
call(['chmod', '+x', path.join(getcwd(), "PluginLoader")])
|
call(['chmod', '+x', path.join(getcwd(), "PluginLoader")])
|
||||||
|
|||||||
@@ -81,10 +81,11 @@ class Utilities:
|
|||||||
async def http_request(self, method="", url="", **kwargs):
|
async def http_request(self, method="", url="", **kwargs):
|
||||||
async with ClientSession() as web:
|
async with ClientSession() as web:
|
||||||
res = await web.request(method, url, ssl=helpers.get_ssl_context(), **kwargs)
|
res = await web.request(method, url, ssl=helpers.get_ssl_context(), **kwargs)
|
||||||
|
text = await res.text()
|
||||||
return {
|
return {
|
||||||
"status": res.status,
|
"status": res.status,
|
||||||
"headers": dict(res.headers),
|
"headers": dict(res.headers),
|
||||||
"body": await res.text()
|
"body": text
|
||||||
}
|
}
|
||||||
|
|
||||||
async def ping(self, **kwargs):
|
async def ping(self, **kwargs):
|
||||||
|
|||||||
Vendored
+1
@@ -40,6 +40,7 @@ User=root
|
|||||||
Restart=always
|
Restart=always
|
||||||
ExecStart=${HOMEBREW_FOLDER}/services/PluginLoader
|
ExecStart=${HOMEBREW_FOLDER}/services/PluginLoader
|
||||||
WorkingDirectory=${HOMEBREW_FOLDER}/services
|
WorkingDirectory=${HOMEBREW_FOLDER}/services
|
||||||
|
KillSignal=SIGKILL
|
||||||
Environment=PLUGIN_PATH=${HOMEBREW_FOLDER}/plugins
|
Environment=PLUGIN_PATH=${HOMEBREW_FOLDER}/plugins
|
||||||
Environment=LOG_LEVEL=DEBUG
|
Environment=LOG_LEVEL=DEBUG
|
||||||
[Install]
|
[Install]
|
||||||
|
|||||||
Vendored
+1
@@ -40,6 +40,7 @@ User=root
|
|||||||
Restart=always
|
Restart=always
|
||||||
ExecStart=${HOMEBREW_FOLDER}/services/PluginLoader
|
ExecStart=${HOMEBREW_FOLDER}/services/PluginLoader
|
||||||
WorkingDirectory=${HOMEBREW_FOLDER}/services
|
WorkingDirectory=${HOMEBREW_FOLDER}/services
|
||||||
|
KillSignal=SIGKILL
|
||||||
Environment=PLUGIN_PATH=${HOMEBREW_FOLDER}/plugins
|
Environment=PLUGIN_PATH=${HOMEBREW_FOLDER}/plugins
|
||||||
Environment=LOG_LEVEL=INFO
|
Environment=LOG_LEVEL=INFO
|
||||||
[Install]
|
[Install]
|
||||||
|
|||||||
+2
-1
@@ -8,7 +8,8 @@ User=root
|
|||||||
Restart=always
|
Restart=always
|
||||||
ExecStart=${HOMEBREW_FOLDER}/services/PluginLoader
|
ExecStart=${HOMEBREW_FOLDER}/services/PluginLoader
|
||||||
WorkingDirectory=${HOMEBREW_FOLDER}/services
|
WorkingDirectory=${HOMEBREW_FOLDER}/services
|
||||||
|
KillSignal=SIGKILL
|
||||||
Environment=PLUGIN_PATH=${HOMEBREW_FOLDER}/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
|
||||||
|
|||||||
Vendored
+2
-1
@@ -8,7 +8,8 @@ User=root
|
|||||||
Restart=always
|
Restart=always
|
||||||
ExecStart=${HOMEBREW_FOLDER}/services/PluginLoader
|
ExecStart=${HOMEBREW_FOLDER}/services/PluginLoader
|
||||||
WorkingDirectory=${HOMEBREW_FOLDER}/services
|
WorkingDirectory=${HOMEBREW_FOLDER}/services
|
||||||
|
KillSignal=SIGKILL
|
||||||
Environment=PLUGIN_PATH=${HOMEBREW_FOLDER}/plugins
|
Environment=PLUGIN_PATH=${HOMEBREW_FOLDER}/plugins
|
||||||
Environment=LOG_LEVEL=INFO
|
Environment=LOG_LEVEL=INFO
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"decky-frontend-lib": "^3.7.14",
|
"decky-frontend-lib": "^3.18.4",
|
||||||
"react-file-icon": "^1.2.0",
|
"react-file-icon": "^1.2.0",
|
||||||
"react-icons": "^4.4.0",
|
"react-icons": "^4.4.0",
|
||||||
"react-markdown": "^8.0.3",
|
"react-markdown": "^8.0.3",
|
||||||
|
|||||||
Generated
+4
-4
@@ -10,7 +10,7 @@ specifiers:
|
|||||||
'@types/react-file-icon': ^1.0.1
|
'@types/react-file-icon': ^1.0.1
|
||||||
'@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: ^3.7.14
|
decky-frontend-lib: ^3.18.4
|
||||||
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
|
||||||
@@ -30,7 +30,7 @@ specifiers:
|
|||||||
typescript: ^4.7.4
|
typescript: ^4.7.4
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
decky-frontend-lib: 3.7.14
|
decky-frontend-lib: 3.18.4
|
||||||
react-file-icon: 1.2.0_wcqkhtmu7mswc6yz4uyexck3ty
|
react-file-icon: 1.2.0_wcqkhtmu7mswc6yz4uyexck3ty
|
||||||
react-icons: 4.4.0_react@16.14.0
|
react-icons: 4.4.0_react@16.14.0
|
||||||
react-markdown: 8.0.3_vshvapmxg47tngu7tvrsqpq55u
|
react-markdown: 8.0.3_vshvapmxg47tngu7tvrsqpq55u
|
||||||
@@ -944,8 +944,8 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.2
|
ms: 2.1.2
|
||||||
|
|
||||||
/decky-frontend-lib/3.7.14:
|
/decky-frontend-lib/3.18.4:
|
||||||
resolution: {integrity: sha512-ShAoP3VqiwkJYukDBHsOF9fk7wYw0VaKpHw6j9WdzLxwZwBcg0J7QBNIFYP3nfA0UgEwSJVEg/22kONiplipmA==}
|
resolution: {integrity: sha512-i3TAe3RJtT1TK0rJgW9Ek5jxMWZRCYLDvqHDylGVieUvuyI7c8X+cogz30pP4cqeGOaA1d/MxBEbhlpD3JhVvg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/decode-named-character-reference/1.0.2:
|
/decode-named-character-reference/1.0.2:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import externalGlobals from "rollup-plugin-external-globals";
|
|||||||
import del from 'rollup-plugin-delete'
|
import del from 'rollup-plugin-delete'
|
||||||
import replace from '@rollup/plugin-replace';
|
import replace from '@rollup/plugin-replace';
|
||||||
import typescript from '@rollup/plugin-typescript';
|
import typescript from '@rollup/plugin-typescript';
|
||||||
import { defineConfig, handleWarning } from 'rollup';
|
import { defineConfig } from 'rollup';
|
||||||
|
|
||||||
const hiddenWarnings = [
|
const hiddenWarnings = [
|
||||||
"THIS_IS_UNDEFINED",
|
"THIS_IS_UNDEFINED",
|
||||||
@@ -41,7 +41,7 @@ export default defineConfig({
|
|||||||
return 'chunk-[hash].js'
|
return 'chunk-[hash].js'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onwarn: function ( message ) {
|
onwarn: function ( message, handleWarning ) {
|
||||||
if (hiddenWarnings.some(warning => message.code === warning)) return;
|
if (hiddenWarnings.some(warning => message.code === warning)) return;
|
||||||
handleWarning(message);
|
handleWarning(message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ConfirmModal, QuickAccessTab, Router, Spinner, staticClasses } from 'decky-frontend-lib';
|
import { ConfirmModal, Navigation, QuickAccessTab, Spinner, staticClasses } from 'decky-frontend-lib';
|
||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
|
|
||||||
interface PluginInstallModalProps {
|
interface PluginInstallModalProps {
|
||||||
@@ -20,7 +20,7 @@ const PluginInstallModal: FC<PluginInstallModalProps> = ({ artifact, version, ha
|
|||||||
onOK={async () => {
|
onOK={async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
await onOK();
|
await onOK();
|
||||||
setTimeout(() => Router.OpenQuickAccessMenu(QuickAccessTab.Decky), 250);
|
setTimeout(() => Navigation.OpenQuickAccessMenu(QuickAccessTab.Decky), 250);
|
||||||
setTimeout(() => window.DeckyPluginLoader.checkPluginUpdates(), 1000);
|
setTimeout(() => window.DeckyPluginLoader.checkPluginUpdates(), 1000);
|
||||||
}}
|
}}
|
||||||
onCancel={async () => {
|
onCancel={async () => {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import {
|
|||||||
DialogButton,
|
DialogButton,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
Focusable,
|
Focusable,
|
||||||
|
Navigation,
|
||||||
QuickAccessTab,
|
QuickAccessTab,
|
||||||
Router,
|
|
||||||
SingleDropdownOption,
|
SingleDropdownOption,
|
||||||
SuspensefulImage,
|
SuspensefulImage,
|
||||||
joinClassNames,
|
joinClassNames,
|
||||||
@@ -38,8 +38,8 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
|
|||||||
}}
|
}}
|
||||||
onCancel={(_: CustomEvent) => {
|
onCancel={(_: CustomEvent) => {
|
||||||
if (containerRef.current!.querySelectorAll('* :focus').length === 0) {
|
if (containerRef.current!.querySelectorAll('* :focus').length === 0) {
|
||||||
Router.NavigateBackOrOpenMenu();
|
Navigation.NavigateBack();
|
||||||
setTimeout(() => Router.OpenQuickAccessMenu(QuickAccessTab.Decky), 1000);
|
setTimeout(() => Navigation.OpenQuickAccessMenu(QuickAccessTab.Decky), 1000);
|
||||||
} else {
|
} else {
|
||||||
containerRef.current!.focus();
|
containerRef.current!.focus();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
Navigation,
|
||||||
ReactRouter,
|
ReactRouter,
|
||||||
Router,
|
Router,
|
||||||
fakeRenderComponent,
|
fakeRenderComponent,
|
||||||
@@ -74,13 +75,14 @@ export async function startup() {
|
|||||||
window.DFL = {
|
window.DFL = {
|
||||||
findModuleChild,
|
findModuleChild,
|
||||||
findModule,
|
findModule,
|
||||||
|
Navigation,
|
||||||
|
Router,
|
||||||
|
ReactRouter,
|
||||||
ReactUtils: {
|
ReactUtils: {
|
||||||
fakeRenderComponent,
|
fakeRenderComponent,
|
||||||
findInReactTree,
|
findInReactTree,
|
||||||
findInTree,
|
findInTree,
|
||||||
},
|
},
|
||||||
Router,
|
|
||||||
ReactRouter,
|
|
||||||
classes: {
|
classes: {
|
||||||
scrollClasses,
|
scrollClasses,
|
||||||
staticClasses,
|
staticClasses,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export enum Store {
|
|||||||
export interface StorePluginVersion {
|
export interface StorePluginVersion {
|
||||||
name: string;
|
name: string;
|
||||||
hash: string;
|
hash: string;
|
||||||
|
artifact: string | undefined | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StorePlugin {
|
export interface StorePlugin {
|
||||||
@@ -73,9 +74,11 @@ export async function installFromURL(url: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function requestPluginInstall(plugin: string, selectedVer: StorePluginVersion) {
|
export async function requestPluginInstall(plugin: string, selectedVer: StorePluginVersion) {
|
||||||
|
const artifactUrl =
|
||||||
|
selectedVer.artifact ?? `https://cdn.tzatzikiweeb.moe/file/steam-deck-homebrew/versions/${selectedVer.hash}.zip`;
|
||||||
await window.DeckyPluginLoader.callServerMethod('install_plugin', {
|
await window.DeckyPluginLoader.callServerMethod('install_plugin', {
|
||||||
name: plugin,
|
name: plugin,
|
||||||
artifact: `https://cdn.tzatzikiweeb.moe/file/steam-deck-homebrew/versions/${selectedVer.hash}.zip`,
|
artifact: artifactUrl,
|
||||||
version: selectedVer.name,
|
version: selectedVer.name,
|
||||||
hash: selectedVer.hash,
|
hash: selectedVer.hash,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Patch, ToastData, afterPatch, findInReactTree, sleep } from 'decky-frontend-lib';
|
import { Module, Patch, ToastData, afterPatch, findInReactTree, findModuleChild, sleep } from 'decky-frontend-lib';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
import Toast from './components/Toast';
|
import Toast from './components/Toast';
|
||||||
@@ -7,6 +7,7 @@ import Logger from './logger';
|
|||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
__TOASTER_INSTANCE: any;
|
__TOASTER_INSTANCE: any;
|
||||||
|
settingsStore: any;
|
||||||
NotificationStore: any;
|
NotificationStore: any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +17,7 @@ class Toaster extends Logger {
|
|||||||
// private toasterState: DeckyToasterState = new DeckyToasterState();
|
// private toasterState: DeckyToasterState = new DeckyToasterState();
|
||||||
private node: any;
|
private node: any;
|
||||||
private rNode: any;
|
private rNode: any;
|
||||||
private settingsModule: any;
|
private audioModule: any;
|
||||||
private finishStartup?: () => void;
|
private finishStartup?: () => void;
|
||||||
private ready: Promise<void> = new Promise((res) => (this.finishStartup = res));
|
private ready: Promise<void> = new Promise((res) => (this.finishStartup = res));
|
||||||
private toasterPatch?: Patch;
|
private toasterPatch?: Patch;
|
||||||
@@ -127,6 +128,17 @@ class Toaster extends Logger {
|
|||||||
this.rNode.stateNode.forceUpdate();
|
this.rNode.stateNode.forceUpdate();
|
||||||
delete this.rNode.stateNode.shouldComponentUpdate;
|
delete this.rNode.stateNode.shouldComponentUpdate;
|
||||||
|
|
||||||
|
this.audioModule = findModuleChild((m: Module) => {
|
||||||
|
if (typeof m !== 'object') return undefined;
|
||||||
|
for (let prop in m) {
|
||||||
|
try {
|
||||||
|
if (m[prop].PlayNavSound && m[prop].RegisterCallbackOnPlaySound) return m[prop];
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.log('Initialized');
|
this.log('Initialized');
|
||||||
this.finishStartup?.();
|
this.finishStartup?.();
|
||||||
}
|
}
|
||||||
@@ -135,24 +147,31 @@ class Toaster extends Logger {
|
|||||||
// toast.duration = toast.duration || 5e3;
|
// toast.duration = toast.duration || 5e3;
|
||||||
// this.toasterState.addToast(toast);
|
// this.toasterState.addToast(toast);
|
||||||
await this.ready;
|
await this.ready;
|
||||||
const settings = this.settingsModule?.settings;
|
|
||||||
let toastData = {
|
let toastData = {
|
||||||
nNotificationID: window.NotificationStore.m_nNextTestNotificationID++,
|
nNotificationID: window.NotificationStore.m_nNextTestNotificationID++,
|
||||||
rtCreated: Date.now(),
|
rtCreated: Date.now(),
|
||||||
eType: 15,
|
eType: toast.eType || 11,
|
||||||
nToastDurationMS: toast.duration || (toast.duration = 5e3),
|
nToastDurationMS: toast.duration || (toast.duration = 5e3),
|
||||||
data: toast,
|
data: toast,
|
||||||
decky: true,
|
decky: true,
|
||||||
};
|
};
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
toastData.data.appid = () => 0;
|
toastData.data.appid = () => 0;
|
||||||
|
if (toast.sound === undefined) toast.sound = 6;
|
||||||
|
if (toast.playSound === undefined) toast.playSound = true;
|
||||||
|
if (toast.showToast === undefined) toast.showToast = true;
|
||||||
if (
|
if (
|
||||||
(settings?.bDisableAllToasts && !toast.critical) ||
|
(window.settingsStore.settings.bDisableAllToasts && !toast.critical) ||
|
||||||
(settings?.bDisableToastsInGame && !toast.critical && window.NotificationStore.BIsUserInGame())
|
(window.settingsStore.settings.bDisableToastsInGame &&
|
||||||
|
!toast.critical &&
|
||||||
|
window.NotificationStore.BIsUserInGame())
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
window.NotificationStore.m_rgNotificationToasts.push(toastData);
|
if (toast.playSound) this.audioModule?.PlayNavSound(toast.sound);
|
||||||
window.NotificationStore.DispatchNextToast();
|
if (toast.showToast) {
|
||||||
|
window.NotificationStore.m_rgNotificationToasts.push(toastData);
|
||||||
|
window.NotificationStore.DispatchNextToast();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit() {
|
deinit() {
|
||||||
|
|||||||
Reference in New Issue
Block a user