Skip to content

Commit

Permalink
Stable references for events in TS and JS
Browse files Browse the repository at this point in the history
  • Loading branch information
Raicuparta committed Jan 16, 2025
1 parent 5cd56fe commit b6e8768
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 49 deletions.
49 changes: 30 additions & 19 deletions src/lang/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,40 @@ import * as TAURI_API_EVENT from "@tauri-apps/api/event";
* }}
*/
function __makeEvents__(mappings) {
const eventsProxies = Object.fromEntries(
Object.keys(mappings).map((event) => {
const name = mappings[event];

const proxyHandlerGet = {
listen: (arg) => TAURI_API_EVENT.listen(name, arg),
once: (arg) => TAURI_API_EVENT.once(name, arg),
emit: (arg) => TAURI_API_EVENT.emit(name, arg),
};

const proxy = new Proxy(
(() => {}),
{
apply: (_, __, [window]) => ({
listen: (arg) => window.listen(name, arg),
once: (arg) => window.once(name, arg),
emit: (arg) => window.emit(name, arg),
}),
get: (_, command) => proxyHandlerGet[command],
},
);

return [event, proxy];
})
);

return new Proxy(
{},
{
get: (_, event) => {
const name = mappings[event];

new Proxy(() => {}, {
apply: (_, __, [window]) => ({
listen: (arg) => window.listen(name, arg),
once: (arg) => window.once(name, arg),
emit: (arg) => window.emit(name, arg),
}),
get: (_, command) => {
switch (command) {
case "listen":
return (arg) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg) => TAURI_API_EVENT.emit(name, arg);
}
},
});
if (typeof event === "string") {
return eventsProxies[event];
}
return undefined;
},
},
);
Expand Down
69 changes: 39 additions & 30 deletions src/lang/globals.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
import {
invoke as TAURI_INVOKE,
Channel as TAURI_CHANNEL,
invoke as TAURI_INVOKE,
Channel as TAURI_CHANNEL,
} from "@tauri-apps/api/core";
import * as TAURI_API_EVENT from "@tauri-apps/api/event";
import { type WebviewWindow as __WebviewWindow__ } from "@tauri-apps/api/webviewWindow";

type __EventObj__<T> = {
listen: (
cb: TAURI_API_EVENT.EventCallback<T>,
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
once: (
cb: TAURI_API_EVENT.EventCallback<T>,
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
emit: null extends T
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
listen: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
once: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
emit: null extends T
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
};

export type Result<T, E> =
| { status: "ok"; data: T }
| { status: "error"; error: E };
| { status: "ok"; data: T }
| { status: "error"; error: E };

function __makeEvents__<T extends Record<string, any>>(
mappings: Record<keyof T, string>,
) {
const eventObjects: Record<string, T[keyof T]> = {};

return new Proxy(
{} as unknown as {
[K in keyof T]: __EventObj__<T[K]> & {
Expand All @@ -34,23 +36,30 @@ function __makeEvents__<T extends Record<string, any>>(
get: (_, event) => {
const name = mappings[event as keyof T];

return new Proxy((() => {}) as any, {
apply: (_, __, [window]: [__WebviewWindow__]) => ({
listen: (arg: any) => window.listen(name, arg),
once: (arg: any) => window.once(name, arg),
emit: (arg: any) => window.emit(name, arg),
}),
get: (_, command: keyof __EventObj__<any>) => {
switch (command) {
case "listen":
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg: any) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
}
},
});
let eventObject = eventObjects[name];
if (!eventObject) {
eventObject = new Proxy((() => {}) as any, {
apply: (_, __, [window]: [__WebviewWindow__]) => ({
listen: (arg: any) => window.listen(name, arg),
once: (arg: any) => window.once(name, arg),
emit: (arg: any) => window.emit(name, arg),
}),
get: (_, command: keyof __EventObj__<any>) => {
switch (command) {
case "listen":
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg: any) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
}
},
});

eventObjects[name] = eventObject;
}

return eventObject;
},
},
);
Expand Down

0 comments on commit b6e8768

Please sign in to comment.