experiments(dui3): extra cleanup and comments around
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
// TODO
|
||||
import { rejects } from 'assert'
|
||||
import { uniqueId } from 'lodash-es'
|
||||
import { resolve } from 'path'
|
||||
|
||||
declare let sketchup: {
|
||||
exec: (data: Record<string, unknown>) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* This class operates in different way than the others, because calls into Sketchup are one way only.
|
||||
* E.g., we cannot return values from internal calls to it (e.g., const test = sketchup.rubyCall() does not work ).
|
||||
* Values are passed back
|
||||
*/
|
||||
export class SketchupBridge {
|
||||
private requests = {} as Record<
|
||||
string,
|
||||
@@ -19,38 +22,51 @@ export class SketchupBridge {
|
||||
private bindingsName: string
|
||||
private TIMEOUT_MS = 2000 // 2s
|
||||
public isInitalized: Promise<void>
|
||||
private isInitializedResolved!: () => unknown
|
||||
private resolveIsInitializedPromise!: () => unknown
|
||||
|
||||
constructor(bindingsName: string) {
|
||||
// window.sketchup
|
||||
this.bindingsName = bindingsName || 'default_bindings'
|
||||
|
||||
// Initialization continues in the receiveCommandsAndInitializeBridge function,
|
||||
// where we expect sketchup to return to us the command names.
|
||||
sketchup.exec({ name: 'get_commands' })
|
||||
// Initialization continues in the receiveCommandsAndInitializeBridge function
|
||||
|
||||
this.isInitalized = new Promise((resolve, reject) => {
|
||||
// TODO
|
||||
this.isInitializedResolved = resolve
|
||||
this.resolveIsInitializedPromise = resolve
|
||||
setTimeout(
|
||||
() =>
|
||||
reject(
|
||||
`Failed to get command names from Sketchup; timed out after ${this.TIMEOUT_MS}ms.`
|
||||
),
|
||||
this.TIMEOUT_MS
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// executeScript(...) from skp
|
||||
/**
|
||||
* Will be called by `executeScript('bindings.receiveCommandsAndInitializeBridge()')` from sketchup. This is where the hoisting happens.
|
||||
* NOTE: Oguhzan, we can defintively have commandNames be a string, and not a string[]
|
||||
* And do JSON.parse() here to get them out properly.
|
||||
* @param commandNames
|
||||
*/
|
||||
private receiveCommandsAndInitializeBridge(commandNames: string[]) {
|
||||
const hoistTarget = this as unknown as Record<string, unknown>
|
||||
|
||||
for (const commandName of commandNames) {
|
||||
hoistTarget[commandName] = (...args: unknown[]) =>
|
||||
this.runMethod(commandName, args)
|
||||
}
|
||||
|
||||
// this.isInitalized = true
|
||||
this.isInitializedResolved()
|
||||
this.resolveIsInitializedPromise()
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal calls to Sketchup.
|
||||
* @param methodName
|
||||
* @param args
|
||||
*/
|
||||
private async runMethod(methodName: string, args: unknown[]): Promise<unknown> {
|
||||
const requestId = uniqueId(this.bindingsName)
|
||||
|
||||
// The single exec way
|
||||
sketchup.exec({ name: methodName, requestId, args })
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -59,22 +75,22 @@ export class SketchupBridge {
|
||||
reject,
|
||||
rejectTimerId: window.setTimeout(() => {
|
||||
reject(
|
||||
'Sketchup response timed out - did not receive anything back in good time.'
|
||||
`Sketchup response timed out - did not receive anything back in good time (${this.TIMEOUT_MS}ms).`
|
||||
)
|
||||
// TODO: clear request from requests object
|
||||
delete this.requests[requestId]
|
||||
}, this.TIMEOUT_MS)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private receiveResponse(requestId: string, data: string) {
|
||||
// TODO
|
||||
if (!this.requests[requestId]) return // throw new error?
|
||||
if (!this.requests[requestId])
|
||||
throw new Error(
|
||||
`Sketchup Bridge found no request to resolve with the id of ${requestId}. Something is weird!`
|
||||
)
|
||||
const request = this.requests[requestId]
|
||||
try {
|
||||
// TODO: resolve also if data is null, it means it's a
|
||||
// 'void' function call (does not return anything)
|
||||
const parsedData = JSON.parse(data) as Record<string, unknown>
|
||||
const parsedData = JSON.parse(data) as Record<string, unknown> // TODO: check if data is undefined
|
||||
request.resolve(parsedData)
|
||||
} catch (e) {
|
||||
request.reject(e as Error)
|
||||
|
||||
@@ -30,7 +30,9 @@ export default defineNuxtPlugin(async () => {
|
||||
console.info('Bound WebUIBinding object for CefSharp.')
|
||||
bindings = new CefSharpBridge(WebUIBinding) as unknown as IWebUiBinding
|
||||
} catch (e) {
|
||||
console.warn('Failed to bind CefSharp.')
|
||||
console.warn(
|
||||
'Failed to bind CefSharp. This can be totally normal if the host is different.'
|
||||
)
|
||||
console.warn(e)
|
||||
}
|
||||
|
||||
@@ -38,24 +40,26 @@ export default defineNuxtPlugin(async () => {
|
||||
if (!chrome.webview) throw new Error('No global Webview2 object found.')
|
||||
bindings = new WebView2Bridge('WebUIBinding') as unknown as IWebUiBinding
|
||||
console.info('Bound WebUIBinding object for Webview2.')
|
||||
|
||||
const res = await bindings.sayHi('Test')
|
||||
console.log(res)
|
||||
} catch (e) {
|
||||
console.warn('Failed to bind Webview2.')
|
||||
console.warn(
|
||||
'Failed to bind Webview2. This can be totally normal if the host is different.'
|
||||
)
|
||||
console.warn(e)
|
||||
}
|
||||
|
||||
try {
|
||||
if (!sketchup) throw new Error('No global sketchup object found.')
|
||||
console.info('Found Sketchup. Hi SketchUp! We have yet... a lot of work to do :) ')
|
||||
// TODO
|
||||
const skpBindings = new SketchupBridge('default_bindings')
|
||||
await skpBindings.isInitalized // resolve({...})
|
||||
|
||||
const skpBindings = new SketchupBridge('default_bindings')
|
||||
// Note, because of the way Sketchup bindings work, we need to wait here
|
||||
// for them to be fully initialized.
|
||||
await skpBindings.isInitalized
|
||||
bindings = skpBindings as unknown as IWebUiBinding
|
||||
} catch (e) {
|
||||
console.warn('Failed to bind sketchup.')
|
||||
console.warn(
|
||||
'Failed to bind sketchup. This can be totally normal if the host is different.'
|
||||
)
|
||||
console.warn(e)
|
||||
}
|
||||
|
||||
@@ -64,17 +68,10 @@ export default defineNuxtPlugin(async () => {
|
||||
bindings = MockedBindings
|
||||
}
|
||||
|
||||
// We need the bindings object in global scope to allow
|
||||
// host applications to send messages back to it.
|
||||
;(globalThis as Record<string, unknown>).bindings = bindings
|
||||
|
||||
// bindings.on('test', (args) => {
|
||||
// console.log(args)
|
||||
// })
|
||||
|
||||
// bindings.on('documentChanged', (args) => {
|
||||
// // do somethings
|
||||
// args.x
|
||||
// })
|
||||
|
||||
return {
|
||||
provide: {
|
||||
bindings
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createNanoEvents, Emitter } from 'nanoevents'
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
import { createNanoEvents } from 'nanoevents'
|
||||
|
||||
export type Account = {
|
||||
id: string
|
||||
isDefault: boolean
|
||||
|
||||
@@ -10933,6 +10933,7 @@ __metadata:
|
||||
graphql: ^16.6.0
|
||||
graphql-tag: ^2.12.6
|
||||
lodash-es: ^4.17.21
|
||||
nanoevents: ^8.0.0
|
||||
nuxt: ^3.5.0
|
||||
portal-vue: ^3.0.0
|
||||
postcss: ^8.4.18
|
||||
@@ -32762,6 +32763,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"nanoevents@npm:^8.0.0":
|
||||
version: 8.0.0
|
||||
resolution: "nanoevents@npm:8.0.0"
|
||||
checksum: 46806fb1bca823de1dac0ec38352c9ebd25dd9f2186eada6357f2941983203c1c77fc383e460852a139b4ced569af2a2777f82cb574f705fd6f8402497f4bfc2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"nanoid@npm:3.3.3":
|
||||
version: 3.3.3
|
||||
resolution: "nanoid@npm:3.3.3"
|
||||
|
||||
Reference in New Issue
Block a user