add webview threaded api
This commit is contained in:
committed by
hsjobeki
parent
3b3426d219
commit
484247de6d
36
pkgs/webview-ui/app/src/App.tsx
Normal file
36
pkgs/webview-ui/app/src/App.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Match, Switch, createSignal, type Component } from "solid-js";
|
||||
import { CountProvider } from "./Config";
|
||||
import { Nested } from "./nested";
|
||||
|
||||
type Route = "home" | "graph";
|
||||
|
||||
const App: Component = () => {
|
||||
const [route, setRoute] = createSignal<Route>("home");
|
||||
return (
|
||||
<CountProvider>
|
||||
<div class="w-full flex items-center flex-col gap-2 my-2">
|
||||
<div>Clan</div>
|
||||
<p>Current route: {route()}</p>
|
||||
|
||||
<div class="flex items-center">
|
||||
<button
|
||||
onClick={() => setRoute((o) => (o === "graph" ? "home" : "graph"))}
|
||||
class="btn btn-link"
|
||||
>
|
||||
Navigate to {route() === "home" ? "graph" : "home"}
|
||||
</button>
|
||||
</div>
|
||||
<Switch fallback={<p>{route()} not found</p>}>
|
||||
<Match when={route() == "home"}>
|
||||
<Nested />
|
||||
</Match>
|
||||
<Match when={route() == "graph"}>
|
||||
<p></p>
|
||||
</Match>
|
||||
</Switch>
|
||||
</div>
|
||||
</CountProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
42
pkgs/webview-ui/app/src/Config.tsx
Normal file
42
pkgs/webview-ui/app/src/Config.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { createSignal, createContext, useContext, JSXElement } from "solid-js";
|
||||
import { PYAPI } from "./message";
|
||||
|
||||
export const makeCountContext = () => {
|
||||
const [machines, setMachines] = createSignal<string[]>([]);
|
||||
const [loading, setLoading] = createSignal(false);
|
||||
|
||||
PYAPI.list_machines.receive((machines) => {
|
||||
setLoading(false);
|
||||
setMachines(machines);
|
||||
});
|
||||
|
||||
return [
|
||||
{ loading, machines },
|
||||
{
|
||||
getMachines: () => {
|
||||
// When the gtk function sends its data the loading state will be set to false
|
||||
setLoading(true);
|
||||
PYAPI.list_machines.dispatch(null);
|
||||
},
|
||||
},
|
||||
] as const;
|
||||
// `as const` forces tuple type inference
|
||||
};
|
||||
type CountContextType = ReturnType<typeof makeCountContext>;
|
||||
|
||||
export const CountContext = createContext<CountContextType>([
|
||||
{ loading: () => false, machines: () => [] },
|
||||
{
|
||||
getMachines: () => {},
|
||||
},
|
||||
]);
|
||||
|
||||
export const useCountContext = () => useContext(CountContext);
|
||||
|
||||
export function CountProvider(props: { children: JSXElement }) {
|
||||
return (
|
||||
<CountContext.Provider value={makeCountContext()}>
|
||||
{props.children}
|
||||
</CountContext.Provider>
|
||||
);
|
||||
}
|
||||
3
pkgs/webview-ui/app/src/index.css
Normal file
3
pkgs/webview-ui/app/src/index.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
18
pkgs/webview-ui/app/src/index.tsx
Normal file
18
pkgs/webview-ui/app/src/index.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
/* @refresh reload */
|
||||
import { render } from "solid-js/web";
|
||||
|
||||
import "./index.css";
|
||||
import App from "./App";
|
||||
|
||||
const root = document.getElementById("app");
|
||||
|
||||
// @ts-ignore: add the clan scope to the window object so we can register callbacks for gtk
|
||||
window.clan = window.clan || {};
|
||||
|
||||
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
|
||||
throw new Error(
|
||||
"Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?"
|
||||
);
|
||||
}
|
||||
|
||||
render(() => <App />, root!);
|
||||
22
pkgs/webview-ui/app/src/message.ts
Normal file
22
pkgs/webview-ui/app/src/message.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
const deserialize = (fn: Function) => (str: string) => {
|
||||
try {
|
||||
fn(JSON.parse(str));
|
||||
} catch (e) {
|
||||
alert(`Error parsing JSON: ${e}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const PYAPI = {
|
||||
list_machines: {
|
||||
dispatch: (data: null) =>
|
||||
// @ts-ignore
|
||||
window.webkit.messageHandlers.gtk.postMessage({
|
||||
method: "list_machines",
|
||||
data,
|
||||
}),
|
||||
receive: (fn: (response: string[]) => void) => {
|
||||
// @ts-ignore
|
||||
window.clan.list_machines = deserialize(fn);
|
||||
},
|
||||
},
|
||||
};
|
||||
29
pkgs/webview-ui/app/src/nested.tsx
Normal file
29
pkgs/webview-ui/app/src/nested.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { For, Match, Switch, type Component } from "solid-js";
|
||||
import { useCountContext } from "./Config";
|
||||
|
||||
export const Nested: Component = () => {
|
||||
const [{ machines, loading }, { getMachines }] = useCountContext();
|
||||
return (
|
||||
<div>
|
||||
<button onClick={() => getMachines()} class="btn btn-primary">
|
||||
Get machines
|
||||
</button>
|
||||
<hr />
|
||||
<Switch>
|
||||
<Match when={loading()}>Loading...</Match>
|
||||
<Match when={!loading() && machines().length === 0}>
|
||||
No machines found
|
||||
</Match>
|
||||
<Match when={!loading() && machines().length}>
|
||||
<For each={machines()}>
|
||||
{(machine, i) => (
|
||||
<li>
|
||||
{i() + 1}: {machine}
|
||||
</li>
|
||||
)}
|
||||
</For>
|
||||
</Match>
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user