Skip to content

Commit

Permalink
Migrate most of frontend callServerMethod usage over to websocket
Browse files Browse the repository at this point in the history
  • Loading branch information
AAGaming00 committed Oct 31, 2023
1 parent 8e20bdd commit a3872b8
Show file tree
Hide file tree
Showing 14 changed files with 163 additions and 161 deletions.
98 changes: 45 additions & 53 deletions backend/src/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,21 @@ def __init__(self, context: PluginManager) -> None:
context.ws.add_route("utilities/ping", self.ping)
context.ws.add_route("utilities/settings/get", self.get_setting)
context.ws.add_route("utilities/settings/set", self.set_setting)
context.ws.add_route("utilities/install_plugin", self.install_plugin)
context.ws.add_route("utilities/install_plugins", self.install_plugins)
context.ws.add_route("utilities/cancel_plugin_install", self.cancel_plugin_install)
context.ws.add_route("utilities/confirm_plugin_install", self.confirm_plugin_install)
context.ws.add_route("utilities/uninstall_plugin", self.uninstall_plugin)
context.ws.add_route("utilities/execute_in_tab", self.execute_in_tab)
context.ws.add_route("utilities/inject_css_into_tab", self.inject_css_into_tab)
context.ws.add_route("utilities/remove_css_from_tab", self.remove_css_from_tab)
context.ws.add_route("utilities/allow_remote_debugging", self.allow_remote_debugging)
context.ws.add_route("utilities/disallow_remote_debugging", self.disallow_remote_debugging)
context.ws.add_route("utilities/filepicker_ls", self.filepicker_ls)
context.ws.add_route("utilities/disable_rdt", self.disable_rdt)
context.ws.add_route("utilities/enable_rdt", self.enable_rdt)
context.ws.add_route("utilities/get_tab_id", self.get_tab_id)
context.ws.add_route("utilities/get_user_info", self.get_user_info)

async def _handle_server_method_call(self, request):
method_name = request.match_info["method_name"]
Expand Down Expand Up @@ -139,62 +154,39 @@ async def execute_in_tab(self, tab: str, run_async: bool, code: str):
"result": e
}

async def inject_css_into_tab(self, tab: str, style: str):
try:
css_id = str(uuid.uuid4())

result = await inject_to_tab(tab,
f"""
(function() {{
const style = document.createElement('style');
style.id = "{css_id}";
document.head.append(style);
style.textContent = `{style}`;
}})()
""", False)

if result and "exceptionDetails" in result["result"]:
return {
"success": False,
"result": result["result"]
}
async def inject_css_into_tab(self, tab: str, style: str) -> str:
css_id = str(uuid.uuid4())

return {
"success": True,
"result": css_id
}
except Exception as e:
return {
"success": False,
"result": e
}
result = await inject_to_tab(tab,
f"""
(function() {{
const style = document.createElement('style');
style.id = "{css_id}";
document.head.append(style);
style.textContent = `{style}`;
}})()
""", False)

if "exceptionDetails" in result["result"]:
raise result["result"]["exceptionDetails"]

return css_id

async def remove_css_from_tab(self, tab: str, css_id: str):
try:
result = await inject_to_tab(tab,
f"""
(function() {{
let style = document.getElementById("{css_id}");
result = await inject_to_tab(tab,
f"""
(function() {{
let style = document.getElementById("{css_id}");
if (style.nodeName.toLowerCase() == 'style')
style.parentNode.removeChild(style);
}})()
""", False)
if (style.nodeName.toLowerCase() == 'style')
style.parentNode.removeChild(style);
}})()
""", False)

if result and "exceptionDetails" in result["result"]:
return {
"success": False,
"result": result
}
if "exceptionDetails" in result["result"]:
raise result["result"]["exceptionDetails"]

return {
"success": True
}
except Exception as e:
return {
"success": False,
"result": e
}
return

async def get_setting(self, key: str, default: Any):
return self.context.settings.getSetting(key, default)
Expand All @@ -211,12 +203,12 @@ async def disallow_remote_debugging(self):
return True

async def filepicker_ls(self,
path : str | None = None,
path: str | None = None,
include_files: bool = True,
include_folders: bool = True,
include_ext: list[str] = [],
include_ext: list[str] | None = None,
include_hidden: bool = False,
order_by: str = "name_asc",
order_by: str = "name_desc",
filter_for: str | None = None,
page: int = 1,
max: int = 1000):
Expand Down
5 changes: 3 additions & 2 deletions backend/src/wsrouter.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,16 @@ async def handle(self, request: Request):
match data["type"]:
case MessageType.CALL.value:
# do stuff with the message
if self.routes[data["route"]]:
if data["route"] in self.routes:
try:
res = await self.routes[data["route"]](*data["args"])
await self.write({"type": MessageType.REPLY.value, "id": data["id"], "result": res})
self.logger.debug(f'Started PY call {data["route"]} ID {data["id"]}')
except:
await self.write({"type": MessageType.ERROR.value, "id": data["id"], "error": format_exc()})
else:
await self.write({"type": MessageType.ERROR.value, "id": data["id"], "error": "Route does not exist."})
# Dunno why but fstring doesnt work here
await self.write({"type": MessageType.ERROR.value, "id": data["id"], "error": "Route " + data["route"] + " does not exist."})
case MessageType.REPLY.value:
if self.running_calls[data["id"]]:
self.running_calls[data["id"]].set_result(data["result"])
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/modals/PluginUninstallModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ConfirmModal } from 'decky-frontend-lib';
import { FC } from 'react';

import { uninstallPlugin } from '../../plugin';

interface PluginUninstallModalProps {
name: string;
title: string;
Expand All @@ -14,7 +16,7 @@ const PluginUninstallModal: FC<PluginUninstallModalProps> = ({ name, title, butt
<ConfirmModal
closeModal={closeModal}
onOK={async () => {
await window.DeckyPluginLoader.callServerMethod('uninstall_plugin', { name });
await uninstallPlugin(name);
// uninstalling a plugin resets the hidden setting for it server-side
// we invalidate here so if you re-install it, you won't have an out-of-date hidden filter
await window.DeckyPluginLoader.hiddenPluginsService.invalidate();
Expand Down
90 changes: 40 additions & 50 deletions frontend/src/components/modals/filepicker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,29 +95,20 @@ const sortOptions = [
},
];

function getList(
path: string,
includeFiles: boolean,
includeFolders: boolean = true,
includeExt: string[] | null = null,
includeHidden: boolean = false,
orderBy: SortOptions = SortOptions.name_desc,
filterFor: RegExp | ((file: File) => boolean) | null = null,
pageNumber: number = 1,
max: number = 1000,
): Promise<{ result: FileListing | string; success: boolean }> {
return window.DeckyPluginLoader.callServerMethod('filepicker_ls', {
path,
include_files: includeFiles,
include_folders: includeFolders,
include_ext: includeExt ? includeExt : [],
include_hidden: includeHidden,
order_by: orderBy,
filter_for: filterFor,
page: pageNumber,
max: max,
});
}
const getList = window.DeckyBackend.callable<
[
path: string,
includeFiles?: boolean,
includeFolders?: boolean,
includeExt?: string[] | null,
includeHidden?: boolean,
orderBy?: SortOptions,
filterFor?: RegExp | ((file: File) => boolean) | null,
pageNumber?: number,
max?: number,
],
FileListing
>('utilities/filepicker_ls');

const iconStyles = {
paddingRight: '10px',
Expand All @@ -126,20 +117,20 @@ const iconStyles = {

const FilePicker: FunctionComponent<FilePickerProps> = ({
startPath,
//What are we allowing to show in the file picker
// What are we allowing to show in the file picker
includeFiles = true,
includeFolders = true,
//Parameter for specifying a specific filename match
// Parameter for specifying a specific filename match
filter = undefined,
//Filter for specific extensions as an array
// Filter for specific extensions as an array
validFileExtensions = undefined,
//Allow to override the fixed extension above
// Allow to override the fixed extension above
allowAllFiles = true,
//If we need to show hidden files and folders (both Win and Linux should work)
// If we need to show hidden files and folders (both Win and Linux should work)
defaultHidden = false, // false by default makes sense for most users
//How much files per page to show, default 1000
// How many files per page to show, default 1000
max = 1000,
//Which picking option to select by default
// Which picking option to select by default
fileSelType = FileSelectionType.FOLDER,
onSubmit,
closeModal,
Expand Down Expand Up @@ -190,21 +181,27 @@ const FilePicker: FunctionComponent<FilePickerProps> = ({
useEffect(() => {
(async () => {
setLoading(true);
const listing = await getList(
path,
includeFiles,
includeFolders,
selectedExts,
showHidden,
sort,
filter,
page,
max,
);
if (!listing.success) {
try {
const listing = await getList(
path,
includeFiles,
includeFolders,
selectedExts,
showHidden,
sort,
filter,
page,
max,
);
setRawError(null);
setError(FileErrorTypes.None);
setFiles(listing.files);
setLoading(false);
setListing(listing);
logger.log('reloaded', path, listing);
} catch (theError: any) {
setListing({ files: [], realpath: path, total: 0 });
setLoading(false);
const theError = listing.result as string;
switch (theError) {
case theError.match(/\[Errno\s2.*/i)?.input:
case theError.match(/\[WinError\s3.*/i)?.input:
Expand All @@ -220,14 +217,7 @@ const FilePicker: FunctionComponent<FilePickerProps> = ({
}
logger.debug(theError);
return;
} else {
setRawError(null);
setError(FileErrorTypes.None);
setFiles((listing.result as FileListing).files);
}
setLoading(false);
setListing(listing.result as FileListing);
logger.log('reloaded', path, listing);
})();
}, [error, path, includeFiles, includeFolders, showHidden, sort, selectedExts, page]);

Expand Down
13 changes: 8 additions & 5 deletions frontend/src/components/settings/pages/developer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,16 @@ export default function DeveloperSettings() {
>
<DialogButton
onClick={async () => {
let res = await window.DeckyPluginLoader.callServerMethod('get_tab_id', { name: 'SharedJSContext' });
if (res.success) {
try {
let tabId = await window.DeckyBackend.call<[name: string], string>(
'utilities/get_tab_id',
'SharedJSContext',
);
Navigation.NavigateToExternalWeb(
'localhost:8080/devtools/inspector.html?ws=localhost:8080/devtools/page/' + res.result,
'localhost:8080/devtools/inspector.html?ws=localhost:8080/devtools/page/' + tabId,
);
} else {
console.error('Unable to find ID for SharedJSContext tab ', res.result);
} catch (e) {
console.error('Unable to find ID for SharedJSContext tab ', e);
Navigation.NavigateToExternalWeb('localhost:8080');
}
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export default function RemoteDebuggingSettings() {
value={allowRemoteDebugging || false}
onChange={(toggleValue) => {
setAllowRemoteDebugging(toggleValue);
if (toggleValue) window.DeckyPluginLoader.callServerMethod('allow_remote_debugging');
else window.DeckyPluginLoader.callServerMethod('disallow_remote_debugging');
if (toggleValue) window.DeckyBackend.call('allow_remote_debugging');
else window.DeckyBackend.call('disallow_remote_debugging');
}}
/>
</Field>
Expand Down
4 changes: 1 addition & 3 deletions frontend/src/developer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ export async function setShouldConnectToReactDevTools(enable: boolean) {
icon: <FaReact />,
});
await sleep(5000);
return enable
? window.DeckyPluginLoader.callServerMethod('enable_rdt')
: window.DeckyPluginLoader.callServerMethod('disable_rdt');
return enable ? window.DeckyBackend.call('utilities/enable_rdt') : window.DeckyBackend.call('utilities/disable_rdt');
}

export async function startup() {
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,11 @@
(async () => {
console.debug('Setting up decky-frontend-lib...');
window.DFL = await import('decky-frontend-lib');
console.debug('Authenticating to Decky backend...');
window.deckyAuthToken = await fetch('http://127.0.0.1:1337/auth/token').then((r) => r.text());
console.debug('Connecting to Decky backend...');
window.DeckyBackend = new (await import('./wsrouter')).WSRouter();
await window.DeckyBackend.connect();
console.debug('Starting Decky!');
await import('./start');
})();
Loading

0 comments on commit a3872b8

Please sign in to comment.