Update USDPL WIP
This commit is contained in:
parent
51d9e6565d
commit
0435f14680
16 changed files with 3218 additions and 1223 deletions
2587
package-lock.json
generated
Normal file
2587
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
13
package.json
13
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "decky-plugin-template",
|
||||
"name": "kaylon",
|
||||
"version": "0.0.1",
|
||||
"description": "A template to quickly create decky plugins from scratch, based on TypeScript and webpack",
|
||||
"description": "Better than the Borg",
|
||||
"scripts": {
|
||||
"build": "shx rm -rf dist && rollup -c",
|
||||
"watch": "rollup -c -w",
|
||||
|
@ -9,21 +9,20 @@
|
|||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/SteamDeckHomebrew/decky-plugin-template.git"
|
||||
"url": "git+https://github.com/NGnius/kaylon.git"
|
||||
},
|
||||
"keywords": [
|
||||
"decky",
|
||||
"plugin",
|
||||
"plugin-template",
|
||||
"steam-deck",
|
||||
"deck"
|
||||
],
|
||||
"author": "Jonas Dellinger <jonas@dellinger.dev>",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"bugs": {
|
||||
"url": "https://github.com/SteamDeckHomebrew/decky-plugin-template/issues"
|
||||
"url": "https://github.com/NGnius/kaylon/issues"
|
||||
},
|
||||
"homepage": "https://github.com/SteamDeckHomebrew/decky-plugin-template#readme",
|
||||
"homepage": "https://github.com/NGnius/kaylon#readme",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^21.1.0",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
|
@ -41,7 +40,7 @@
|
|||
"dependencies": {
|
||||
"decky-frontend-lib": "^1.0.1",
|
||||
"react-icons": "^4.3.1",
|
||||
"usdpl-front": "file:./src/usdpl-front"
|
||||
"usdpl-front": "file:./src/usdpl_front"
|
||||
},
|
||||
"pnpm": {
|
||||
"peerDependencyRules": {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"name": "Example Plugin",
|
||||
"author": "John Doe",
|
||||
"name": "Kaylon",
|
||||
"author": "NGnius",
|
||||
"flags": ["debug", "_root"],
|
||||
"publish": {
|
||||
"tags": ["template", "root"],
|
||||
"description": "Decky example plugin.",
|
||||
"image": "https://opengraph.githubassets.com/1/SteamDeckHomebrew/PluginLoader"
|
||||
"description": "Better than the Borg",
|
||||
"image": ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,13 +38,13 @@ export type CButton = {
|
|||
title: string;
|
||||
}
|
||||
|
||||
export type CToggle {
|
||||
export type CToggle = {
|
||||
element: string; // "toggle"
|
||||
title: string;
|
||||
description: string | null;
|
||||
}
|
||||
|
||||
export type CSlider {
|
||||
export type CSlider = {
|
||||
element: string; // "slider"
|
||||
title: string;
|
||||
min: number;
|
||||
|
@ -52,7 +52,7 @@ export type CSlider {
|
|||
notches: string[] | null;
|
||||
}
|
||||
|
||||
export type CReading {
|
||||
export type CReading = {
|
||||
element: string; // "reading"
|
||||
title: string;
|
||||
period_ms: number;
|
||||
|
|
145
src/index.tsx
145
src/index.tsx
|
@ -2,21 +2,24 @@ import {
|
|||
ButtonItem,
|
||||
definePlugin,
|
||||
DialogButton,
|
||||
Menu,
|
||||
MenuItem,
|
||||
//Menu,
|
||||
//MenuItem,
|
||||
PanelSection,
|
||||
PanelSectionRow,
|
||||
Router,
|
||||
//Router,
|
||||
ServerAPI,
|
||||
showContextMenu,
|
||||
//showContextMenu,
|
||||
staticClasses,
|
||||
SliderField,
|
||||
ToggleField,
|
||||
//NotchLabel
|
||||
gamepadDialogClasses,
|
||||
joinClassNames,
|
||||
} from "decky-frontend-lib";
|
||||
import { VFC } from "react";
|
||||
import { FaShip } from "react-icons/fa";
|
||||
import { VFC, useState } from "react";
|
||||
import { GiWashingMachine } from "react-icons/gi";
|
||||
|
||||
import logo from "../assets/logo.png";
|
||||
|
||||
import {init_usdpl, target, init_embedded, call_backend} from "usdpl-front";
|
||||
import { call_backend } from "usdpl-front";
|
||||
import * as backend from "./backend";
|
||||
|
||||
// interface AddMethodArgs {
|
||||
|
@ -24,6 +27,10 @@ import * as backend from "./backend";
|
|||
// right: number;
|
||||
// }
|
||||
|
||||
const FieldWithSeparator = joinClassNames(gamepadDialogClasses.Field, gamepadDialogClasses.WithBottomSeparatorStandard);
|
||||
|
||||
let items: backend.CElement[] = [];
|
||||
|
||||
const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||
// const [result, setResult] = useState<number | undefined>();
|
||||
|
||||
|
@ -40,6 +47,16 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
|||
// }
|
||||
// };
|
||||
|
||||
const [triggerInternal, updateInternal] = useState<boolean>(false);
|
||||
|
||||
function update() {
|
||||
updateInternal(!triggerInternal);
|
||||
}
|
||||
|
||||
function updateIdc(_: any) {
|
||||
update();
|
||||
}
|
||||
|
||||
// call hello callback on backend
|
||||
(async () => {
|
||||
let response = await call_backend("hello", []);
|
||||
|
@ -48,41 +65,11 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
|||
|
||||
return (
|
||||
<PanelSection title="Panel Section">
|
||||
<PanelSectionRow>
|
||||
<ButtonItem
|
||||
layout="below"
|
||||
onClick={(e) =>
|
||||
showContextMenu(
|
||||
<Menu label="Menu" cancelText="CAAAANCEL" onCancel={() => {}}>
|
||||
<MenuItem onSelected={() => {}}>Item #1</MenuItem>
|
||||
<MenuItem onSelected={() => {}}>Item #2</MenuItem>
|
||||
<MenuItem onSelected={() => {}}>Item #3</MenuItem>
|
||||
</Menu>,
|
||||
e.currentTarget ?? window
|
||||
)
|
||||
{items.map(
|
||||
(elem, i) => {
|
||||
return <PanelSectionRow>{buildHtmlElement(elem, i, updateIdc)}</PanelSectionRow>
|
||||
})
|
||||
}
|
||||
>
|
||||
Server says yolo
|
||||
</ButtonItem>
|
||||
</PanelSectionRow>
|
||||
|
||||
<PanelSectionRow>
|
||||
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||
<img src={logo} />
|
||||
</div>
|
||||
</PanelSectionRow>
|
||||
|
||||
<PanelSectionRow>
|
||||
<ButtonItem
|
||||
layout="below"
|
||||
onClick={() => {
|
||||
Router.CloseSideMenus();
|
||||
Router.Navigate("/decky-plugin-test");
|
||||
}}
|
||||
>
|
||||
Router
|
||||
</ButtonItem>
|
||||
</PanelSectionRow>
|
||||
</PanelSection>
|
||||
);
|
||||
};
|
||||
|
@ -91,13 +78,76 @@ const DeckyPluginRouterTest: VFC = () => {
|
|||
return (
|
||||
<div style={{ marginTop: "50px", color: "white" }}>
|
||||
Hello World!
|
||||
<DialogButton onClick={() => Router.NavigateToStore()}>
|
||||
<DialogButton onClick={() => {}}>
|
||||
Go to Store
|
||||
</DialogButton>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function buildHtmlElement(element: backend.CElement, index: number, updateIdc: any) {
|
||||
switch (element.element) {
|
||||
case "button":
|
||||
return buildButton(element as backend.CButton, index, updateIdc);
|
||||
case "slider":
|
||||
return buildSlider(element as backend.CSlider, index, updateIdc);
|
||||
case "toggle":
|
||||
return buildToggle(element as backend.CToggle, index, updateIdc);
|
||||
case "reading":
|
||||
return buildReading(element as backend.CReading, index, updateIdc);
|
||||
}
|
||||
return "Unsupported";
|
||||
}
|
||||
|
||||
function buildButton(element: backend.CButton, index: number, updateIdc: any) {
|
||||
return (
|
||||
<ButtonItem
|
||||
layout="below"
|
||||
onClick={() => {backend.resolve(backend.onUpdate(index, null), updateIdc)}}>
|
||||
{element.title}
|
||||
</ButtonItem>
|
||||
);
|
||||
}
|
||||
|
||||
function buildSlider(element: backend.CSlider, index: number, updateIdc: any) {
|
||||
return (
|
||||
<SliderField
|
||||
label={element.title}
|
||||
value={element.min}
|
||||
max={element.max}
|
||||
min={element.min}
|
||||
showValue={true}
|
||||
onChange={(value: number) => {
|
||||
backend.resolve(backend.onUpdate(index, value), updateIdc)
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function buildToggle(element: backend.CToggle, index: number, updateIdc: any) {
|
||||
return (
|
||||
<ToggleField
|
||||
checked={false}
|
||||
label={element.title}
|
||||
description={element.description!}
|
||||
onChange={(value: boolean) => {
|
||||
backend.resolve(backend.onUpdate(index, value), updateIdc)
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function buildReading(element: backend.CReading, _index: number, _updateIdc: any) {
|
||||
return (
|
||||
<div className={FieldWithSeparator}>
|
||||
<div className={gamepadDialogClasses.FieldLabelRow}>
|
||||
<div className={gamepadDialogClasses.FieldLabel}>{element.title}</div>
|
||||
<div className={gamepadDialogClasses.FieldChildren}>{"idk"}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default definePlugin((serverApi: ServerAPI) => {
|
||||
serverApi.routerHook.addRoute("/decky-plugin-test", DeckyPluginRouterTest, {
|
||||
exact: true,
|
||||
|
@ -106,15 +156,14 @@ export default definePlugin((serverApi: ServerAPI) => {
|
|||
// init USDPL WASM frontend
|
||||
// this is required to interface with the backend
|
||||
(async () => {
|
||||
await init_embedded();
|
||||
init_usdpl(USDPL_PORT);
|
||||
console.log("USDPL started for framework: " + target());
|
||||
await backend.initBackend();
|
||||
items = await backend.getElements();
|
||||
})();
|
||||
|
||||
return {
|
||||
title: <div className={staticClasses.Title}>Example Plugin</div>,
|
||||
content: <Content serverAPI={serverApi} />,
|
||||
icon: <FaShip />,
|
||||
icon: <GiWashingMachine />,
|
||||
onDismount() {
|
||||
serverApi.routerHook.removeRoute("/decky-plugin-test");
|
||||
},
|
||||
|
|
57
src/usdpl-front/usdpl.d.ts
vendored
57
src/usdpl-front/usdpl.d.ts
vendored
|
@ -1,57 +0,0 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Initialize the front-end library
|
||||
* @param {number} port
|
||||
*/
|
||||
export function init_usdpl(port: number): void;
|
||||
/**
|
||||
* Get the targeted plugin framework, or "any" if unknown
|
||||
* @returns {string}
|
||||
*/
|
||||
export function target(): string;
|
||||
/**
|
||||
* Call a function on the back-end.
|
||||
* Returns null (None) if this fails for any reason.
|
||||
* @param {string} name
|
||||
* @param {any[]} parameters
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
export function call_backend(name: string, parameters: any[]): Promise<any>;
|
||||
/**
|
||||
*/
|
||||
export class UsdplContext {
|
||||
free(): void;
|
||||
}
|
||||
|
||||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||
|
||||
export interface InitOutput {
|
||||
readonly memory: WebAssembly.Memory;
|
||||
readonly __wbg_usdplcontext_free: (a: number) => void;
|
||||
readonly init_usdpl: (a: number) => void;
|
||||
readonly target: (a: number) => void;
|
||||
readonly call_backend: (a: number, b: number, c: number, d: number) => number;
|
||||
readonly __wbindgen_malloc: (a: number) => number;
|
||||
readonly __wbindgen_realloc: (a: number, b: number, c: number) => number;
|
||||
readonly __wbindgen_export_2: WebAssembly.Table;
|
||||
readonly _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h16ac289f583b8044: (a: number, b: number, c: number) => void;
|
||||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||
readonly __wbindgen_free: (a: number, b: number) => void;
|
||||
readonly __wbindgen_exn_store: (a: number) => void;
|
||||
readonly wasm_bindgen__convert__closures__invoke2_mut__ha1c5a356ae6a22de: (a: number, b: number, c: number, d: number) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||
*
|
||||
* @param {InitInput | Promise<InitInput>} module_or_path
|
||||
*
|
||||
* @returns {Promise<InitOutput>}
|
||||
*/
|
||||
export default function init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
|
||||
|
||||
|
||||
// USDPL customization
|
||||
export function init_embedded();
|
File diff suppressed because one or more lines are too long
Binary file not shown.
15
src/usdpl-front/usdpl_bg.wasm.d.ts
vendored
15
src/usdpl-front/usdpl_bg.wasm.d.ts
vendored
|
@ -1,15 +0,0 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export const memory: WebAssembly.Memory;
|
||||
export function __wbg_usdplcontext_free(a: number): void;
|
||||
export function init_usdpl(a: number): void;
|
||||
export function target(a: number): void;
|
||||
export function call_backend(a: number, b: number, c: number, d: number): number;
|
||||
export function __wbindgen_malloc(a: number): number;
|
||||
export function __wbindgen_realloc(a: number, b: number, c: number): number;
|
||||
export const __wbindgen_export_2: WebAssembly.Table;
|
||||
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h16ac289f583b8044(a: number, b: number, c: number): void;
|
||||
export function __wbindgen_add_to_stack_pointer(a: number): number;
|
||||
export function __wbindgen_free(a: number, b: number): void;
|
||||
export function __wbindgen_exn_store(a: number): void;
|
||||
export function wasm_bindgen__convert__closures__invoke2_mut__ha1c5a356ae6a22de(a: number, b: number, c: number, d: number): void;
|
File diff suppressed because one or more lines are too long
Binary file not shown.
21
src/usdpl_front/package.json
Normal file
21
src/usdpl_front/package.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "usdpl-front",
|
||||
"collaborators": [
|
||||
"NGnius (Graham) <ngniusness@gmail.com>"
|
||||
],
|
||||
"description": "Universal Steam Deck Plugin Library front-end designed for WASM",
|
||||
"version": "0.6.0",
|
||||
"license": "GPL-3.0-only",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/NGnius/usdpl-rs"
|
||||
},
|
||||
"files": [
|
||||
"usdpl_front_bg.wasm",
|
||||
"usdpl_front.js",
|
||||
"usdpl_front.d.ts"
|
||||
],
|
||||
"module": "usdpl_front.js",
|
||||
"types": "usdpl_front.d.ts",
|
||||
"sideEffects": false
|
||||
}
|
499
src/usdpl_front/usdpl_front.js
Normal file
499
src/usdpl_front/usdpl_front.js
Normal file
File diff suppressed because one or more lines are too long
BIN
src/usdpl_front/usdpl_front_bg.wasm
Normal file
BIN
src/usdpl_front/usdpl_front_bg.wasm
Normal file
Binary file not shown.
Reference in a new issue