From 2cdc5b7d92d32b978573ef9d99c5cf4ad9b3b3dc Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Tue, 11 Jul 2023 19:16:46 +0100 Subject: [PATCH] experiments(dui3): adds an event emitter base class --- packages/dui3/lib/bridge/base.ts | 24 ++++++++++++++++++++++++ packages/dui3/lib/bridge/cefSharp.ts | 20 +++----------------- packages/dui3/lib/bridge/sketchup.ts | 11 +++++++---- packages/dui3/lib/bridge/webview.ts | 18 +++--------------- 4 files changed, 37 insertions(+), 36 deletions(-) create mode 100644 packages/dui3/lib/bridge/base.ts diff --git a/packages/dui3/lib/bridge/base.ts b/packages/dui3/lib/bridge/base.ts new file mode 100644 index 000000000..3cc01e9fe --- /dev/null +++ b/packages/dui3/lib/bridge/base.ts @@ -0,0 +1,24 @@ +import { createNanoEvents, Emitter } from 'nanoevents' + +/** + * A simple (typed) event emitter base class that host applications can use to send messages (and data) to the web ui, + * e.g. via `browser.executeScriptAsync("myBindings.on('eventName', serializedData)")`. + + */ +export class BaseBridge { + private emitter: Emitter + + constructor() { + this.emitter = createNanoEvents() + } + + // NOTE: these do not need to be typed extra in here, as they will be properly typed on the specific binding's interface. + on(event: string | number, callback: (...args: unknown[]) => void) { + return this.emitter.on(event, callback) + } + + emit(eventName: string, payload: string) { + const parsedPayload = JSON.parse(payload) as unknown + this.emitter.emit(eventName, parsedPayload) + } +} diff --git a/packages/dui3/lib/bridge/cefSharp.ts b/packages/dui3/lib/bridge/cefSharp.ts index 2d480de24..14c04a201 100644 --- a/packages/dui3/lib/bridge/cefSharp.ts +++ b/packages/dui3/lib/bridge/cefSharp.ts @@ -1,28 +1,14 @@ import { IWebUiBinding } from '~/types' -import { createNanoEvents, Emitter } from 'nanoevents' -import { HostAppEvents } from '~/types' - -export class CefSharpBridge { - private emitter: Emitter +import { BaseBridge } from '~/lib/bridge/base' +export class CefSharpBridge extends BaseBridge { constructor(bindingObject: IWebUiBinding) { + super() const hoistTarget = this as unknown as Record const hoistSource = bindingObject as unknown as Record for (const key in bindingObject) { hoistTarget[key] = hoistSource[key] } - - this.emitter = createNanoEvents() - this.emitter.emit('start', 'polo pasta') - } - - on(event: E, callback: HostAppEvents[E]) { - return this.emitter.on(event, callback) - } - - emit(eventName: string, payload: string) { - const parsedPayload = JSON.parse(payload) as unknown - this.emitter.emit(eventName, parsedPayload) } } diff --git a/packages/dui3/lib/bridge/sketchup.ts b/packages/dui3/lib/bridge/sketchup.ts index 1aa5259a3..471536c0f 100644 --- a/packages/dui3/lib/bridge/sketchup.ts +++ b/packages/dui3/lib/bridge/sketchup.ts @@ -1,5 +1,5 @@ -// TODO import { uniqueId } from 'lodash-es' +import { BaseBridge } from './base' declare let sketchup: { exec: (data: Record) => void @@ -11,8 +11,9 @@ declare let sketchup: { * This class basically makes the sketchup bindings work in the same way as cef/webview by returning a promise * on each method call. That promise is either resolved once sketchup sends back (via receiveResponse) a corresponding * reply, or it's rejected after a given TIMEOUT_MS (currently 2s). + * TODO: implement the event dispatcher side as well. */ -export class SketchupBridge { +export class SketchupBridge extends BaseBridge { private requests = {} as Record< string, { @@ -27,6 +28,7 @@ export class SketchupBridge { private resolveIsInitializedPromise!: () => unknown constructor(bindingsName: string) { + super() this.bindingsName = bindingsName || 'default_bindings' this.isInitalized = new Promise((resolve, reject) => { @@ -104,8 +106,9 @@ export class SketchupBridge { ) const request = this.requests[requestId] try { - const parsedData = JSON.parse(data) as Record // TODO: check if data is undefined - request.resolve(parsedData) + // NOTE/TODO: does not need parsing + // const parsedData = JSON.parse(data) as Record // TODO: check if data is undefined + request.resolve(data) } catch (e) { request.reject(e as Error) } finally { diff --git a/packages/dui3/lib/bridge/webview.ts b/packages/dui3/lib/bridge/webview.ts index 0817c6edf..7adfc86e3 100644 --- a/packages/dui3/lib/bridge/webview.ts +++ b/packages/dui3/lib/bridge/webview.ts @@ -1,6 +1,5 @@ // github.com/johot/WebView2-better-bridge/blob/master/web-ui/src/betterBridge.ts -import { createNanoEvents, Emitter } from 'nanoevents' -import { HostAppEvents } from '~/types' +import { BaseBridge } from '~/lib/bridge/base' type IWebView2 = { webview: { @@ -17,11 +16,11 @@ type IRawBridge = { declare let chrome: IWebView2 -export class WebView2Bridge { +export class WebView2Bridge extends BaseBridge { private webViewBridge: IRawBridge - private emitter: Emitter constructor(bridgeName: string) { + super() this.webViewBridge = chrome.webview.hostObjects[bridgeName] // NOTE: GetMethods is a call to the .NET side. @@ -36,8 +35,6 @@ export class WebView2Bridge { hoistTarget[lowercasedMethodName] = (...args: unknown[]) => this.runMethod(methodName, args) } - - this.emitter = createNanoEvents() } private async runMethod(methodName: string, args: unknown[]): Promise { @@ -50,15 +47,6 @@ export class WebView2Bridge { return JSON.parse(result) as unknown } - - on(event: E, callback: HostAppEvents[E]) { - return this.emitter.on(event, callback) - } - - emit(eventName: string, payload: string) { - const parsedPayload = JSON.parse(payload) as unknown - this.emitter.emit(eventName, parsedPayload) - } } const lowercaseMethodName = (name: string) =>