@webspatial/core-sdk 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/iife/index.d.ts +386 -236
- package/dist/iife/index.global.js +7 -7
- package/dist/iife/index.global.js.map +1 -1
- package/dist/index.d.ts +386 -236
- package/dist/index.js +1467 -1210
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/JSBCommand.ts +30 -100
- package/src/Spatial.ts +0 -21
- package/src/SpatialScene.ts +1 -5
- package/src/SpatialSession.ts +17 -3
- package/src/SpatializedDynamic3DElement.ts +0 -1
- package/src/SpatializedElementCreator.ts +6 -4
- package/src/SpatializedStatic3DElement.test.ts +99 -0
- package/src/SpatializedStatic3DElement.ts +99 -1
- package/src/WebMsgCommand.ts +10 -0
- package/src/coverage-boost.test.ts +38 -119
- package/src/index.ts +3 -1
- package/src/jsbcommand.coverage.test.ts +19 -48
- package/src/platform-adapter/CommandResultUtils.ts +2 -2
- package/src/platform-adapter/createPlatformSync.ts +34 -0
- package/src/platform-adapter/index.ts +5 -51
- package/src/platform-adapter/interface.ts +35 -23
- package/src/platform-adapter/pico-os/PicoOSPlatform.ts +84 -52
- package/src/platform-adapter/puppeteer/PuppeteerPlatform.ts +37 -11
- package/src/platform-adapter/spatialSceneQuery.ts +17 -0
- package/src/platform-adapter/ssr/SSRPlatform.ts +24 -15
- package/src/platform-adapter/vision-os/VisionOSPlatform.ts +55 -24
- package/src/platform-runtime.ts +13 -0
- package/src/reality/Attachment.ts +2 -2
- package/src/reality/entity/SpatialEntity.ts +0 -2
- package/src/reality/realityCreator.ts +15 -1
- package/src/reality/resource/SpatialTextureResource.ts +16 -0
- package/src/reality/resource/index.ts +1 -0
- package/src/runtime/WebSpatialRuntimeError.ts +16 -0
- package/src/runtime/capability-data.ts +113 -0
- package/src/runtime/contract-review.test.ts +44 -0
- package/src/runtime/index.ts +28 -0
- package/src/runtime/jsbAdapterPlatform.test.ts +36 -0
- package/src/runtime/jsbAdapterPlatform.ts +51 -0
- package/src/runtime/keys.ts +129 -0
- package/src/runtime/semver.ts +33 -0
- package/src/runtime/supports.test.ts +207 -0
- package/src/runtime/supports.ts +110 -0
- package/src/runtime/types.ts +11 -0
- package/src/runtime/userAgent.ts +64 -0
- package/src/scene-polyfill.manifest.test.ts +7 -5
- package/src/scene-polyfill.ts +8 -5
- package/src/spatial-host.ts +25 -0
- package/src/types/{global.d.ts → global.ts} +10 -5
- package/src/types/types.ts +9 -0
- package/src/platform-adapter/android/AndroidPlatform.ts +0 -133
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { CAPABILITY_TABLE, type CapabilityVersionRow } from './capability-data'
|
|
2
|
+
import { compareSemver, parseSemverOrNull } from './semver'
|
|
3
|
+
import type { WebSpatialRuntimeSnapshot } from './types'
|
|
4
|
+
import { computeRuntimeFromUserAgent } from './userAgent'
|
|
5
|
+
import {
|
|
6
|
+
type CapabilityKey,
|
|
7
|
+
isKnownSubToken,
|
|
8
|
+
isKnownTopLevel,
|
|
9
|
+
normalizeCapabilityName,
|
|
10
|
+
} from './keys'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Unsubstituted shell version placeholder from visionOS manifest / Xcode template
|
|
14
|
+
* (`manifest.swift`). When still present in `WSAppShell/<version>`, treat as debug
|
|
15
|
+
* build: {@link supports} returns true for every valid capability query.
|
|
16
|
+
*/
|
|
17
|
+
export const VISIONOS_DEBUG_SHELL_VERSION_PLACEHOLDER = 'WS_SHELL_VERSION'
|
|
18
|
+
|
|
19
|
+
let runtimeCache: WebSpatialRuntimeSnapshot | undefined
|
|
20
|
+
|
|
21
|
+
/** Test helper: clear cached UA/runtime snapshot between Vitest cases. */
|
|
22
|
+
export function resetRuntimeCacheForTests(): void {
|
|
23
|
+
runtimeCache = undefined
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Internal runtime snapshot (not part of the public `@webspatial/react-sdk` surface).
|
|
28
|
+
*/
|
|
29
|
+
export function getRuntime(): WebSpatialRuntimeSnapshot {
|
|
30
|
+
if (runtimeCache !== undefined) return runtimeCache
|
|
31
|
+
if (typeof navigator === 'undefined') {
|
|
32
|
+
runtimeCache = { type: null, shellVersion: null }
|
|
33
|
+
return runtimeCache
|
|
34
|
+
}
|
|
35
|
+
runtimeCache = computeRuntimeFromUserAgent(navigator.userAgent)
|
|
36
|
+
return runtimeCache
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function selectRow(
|
|
40
|
+
type: 'visionos' | 'picoos',
|
|
41
|
+
shellVersion: string,
|
|
42
|
+
): CapabilityVersionRow | null {
|
|
43
|
+
const norm = parseSemverOrNull(shellVersion)
|
|
44
|
+
if (!norm) return null
|
|
45
|
+
const rows = CAPABILITY_TABLE[type]
|
|
46
|
+
if (!rows.length) return null
|
|
47
|
+
const sorted = [...rows].sort((a, b) => compareSemver(a.version, b.version))
|
|
48
|
+
const minV = sorted[0].version
|
|
49
|
+
if (compareSemver(norm, minV) < 0) return null
|
|
50
|
+
|
|
51
|
+
let chosen: CapabilityVersionRow | null = null
|
|
52
|
+
for (const row of sorted) {
|
|
53
|
+
if (compareSemver(row.version, norm) <= 0) {
|
|
54
|
+
chosen = row
|
|
55
|
+
} else {
|
|
56
|
+
break
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return chosen
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Public capability probe (`WebSpatialRuntime.supports` re-exports this from React SDK).
|
|
64
|
+
*/
|
|
65
|
+
export function supports(
|
|
66
|
+
name: CapabilityKey,
|
|
67
|
+
tokens?: readonly string[],
|
|
68
|
+
): boolean
|
|
69
|
+
export function supports(name: string, tokens?: readonly string[]): boolean
|
|
70
|
+
export function supports(name: string, tokens?: readonly string[]): boolean {
|
|
71
|
+
if (typeof name !== 'string') return false
|
|
72
|
+
const canonical = normalizeCapabilityName(name)
|
|
73
|
+
if (!isKnownTopLevel(canonical)) return false
|
|
74
|
+
|
|
75
|
+
const tokList =
|
|
76
|
+
tokens === undefined ? [] : Array.isArray(tokens) ? [...tokens] : []
|
|
77
|
+
if (tokList.some(t => typeof t !== 'string')) return false
|
|
78
|
+
|
|
79
|
+
for (const t of tokList) {
|
|
80
|
+
if (!isKnownSubToken(canonical, t)) return false
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const rt = getRuntime()
|
|
84
|
+
if (rt.type === 'puppeteer') {
|
|
85
|
+
return true
|
|
86
|
+
}
|
|
87
|
+
if (rt.type === null) return false
|
|
88
|
+
if (rt.shellVersion === null) return false
|
|
89
|
+
|
|
90
|
+
if (
|
|
91
|
+
rt.type === 'visionos' &&
|
|
92
|
+
rt.shellVersion === VISIONOS_DEBUG_SHELL_VERSION_PLACEHOLDER
|
|
93
|
+
) {
|
|
94
|
+
return true
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const parsedShell = parseSemverOrNull(rt.shellVersion)
|
|
98
|
+
if (!parsedShell) return false
|
|
99
|
+
|
|
100
|
+
if (rt.type !== 'visionos' && rt.type !== 'picoos') return false
|
|
101
|
+
|
|
102
|
+
const row = selectRow(rt.type, parsedShell)
|
|
103
|
+
if (!row) return false
|
|
104
|
+
|
|
105
|
+
if (tokList.length === 0) {
|
|
106
|
+
return row.flags[canonical] === true
|
|
107
|
+
}
|
|
108
|
+
if (row.flags[canonical] !== true) return false
|
|
109
|
+
return tokList.every(t => row.flags[`${canonical}:${t}`] === true)
|
|
110
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal runtime classification (see OpenSpec `review.md`).
|
|
3
|
+
* `puppeteer`: automation / test harness UA — not a product matrix row; see `supports()`.
|
|
4
|
+
*/
|
|
5
|
+
export type WebSpatialRuntimeType = 'visionos' | 'picoos' | 'puppeteer' | null
|
|
6
|
+
|
|
7
|
+
/** Snapshot returned by internal `getRuntime()` (not a public app API). */
|
|
8
|
+
export type WebSpatialRuntimeSnapshot = {
|
|
9
|
+
type: WebSpatialRuntimeType
|
|
10
|
+
shellVersion: string | null
|
|
11
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { WebSpatialRuntimeSnapshot } from './types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parse shell token from UA:
|
|
5
|
+
* - packaged/hybrid runtimes use `WSAppShell/<version>`
|
|
6
|
+
* - browser-mode runtime on Pico OS uses `PicoWebApp/<version>`
|
|
7
|
+
*
|
|
8
|
+
* Keep `WSAppShell` precedence when both appear in one UA.
|
|
9
|
+
*/
|
|
10
|
+
export function parseShellToken(ua: string): {
|
|
11
|
+
version: string | null
|
|
12
|
+
source: 'wsapp' | 'picoapp' | null
|
|
13
|
+
} {
|
|
14
|
+
const ws = /\bWSAppShell\/([\w.-]+)/i.exec(ua)
|
|
15
|
+
if (ws?.[1]) return { version: ws[1], source: 'wsapp' }
|
|
16
|
+
const pico = /\bPicoWebApp\/([\w.-]+)/i.exec(ua)
|
|
17
|
+
if (pico?.[1]) return { version: pico[1], source: 'picoapp' }
|
|
18
|
+
return { version: null, source: null }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Pico runtime: require explicit Pico tokens (do not treat generic `like Quest` VR UAs as picoos). */
|
|
22
|
+
function inferPicoOs(ua: string): boolean {
|
|
23
|
+
return /\bPicoWebApp\//i.test(ua) || /\bPicoBrowser\b/i.test(ua)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** visionOS-class WebView UAs include a Mac OS X platform token; `WSAppShell` alone is not enough. */
|
|
27
|
+
function inferVisionOsFromUa(ua: string): boolean {
|
|
28
|
+
return /Mac OS X/i.test(ua)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resolve internal runtime snapshot from `navigator.userAgent`.
|
|
33
|
+
* SSR / no navigator → `{ type: null, shellVersion: null }` (no throw).
|
|
34
|
+
*/
|
|
35
|
+
export function computeRuntimeFromUserAgent(
|
|
36
|
+
userAgent: string | undefined,
|
|
37
|
+
): WebSpatialRuntimeSnapshot {
|
|
38
|
+
if (userAgent === undefined || userAgent === '') {
|
|
39
|
+
return { type: null, shellVersion: null }
|
|
40
|
+
}
|
|
41
|
+
// Must run before the shell-token gate: Puppeteer UAs may omit WSAppShell/PicoWebApp.
|
|
42
|
+
if (userAgent.includes('Puppeteer')) {
|
|
43
|
+
const { version } = parseShellToken(userAgent)
|
|
44
|
+
return { type: 'puppeteer', shellVersion: version }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const { version, source } = parseShellToken(userAgent)
|
|
48
|
+
if (!version) {
|
|
49
|
+
return { type: null, shellVersion: null }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (source === 'picoapp' || inferPicoOs(userAgent)) {
|
|
53
|
+
return { type: 'picoos', shellVersion: version }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (source === 'wsapp') {
|
|
57
|
+
if (inferVisionOsFromUa(userAgent)) {
|
|
58
|
+
return { type: 'visionos', shellVersion: version }
|
|
59
|
+
}
|
|
60
|
+
return { type: null, shellVersion: version }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { type: null, shellVersion: version }
|
|
64
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest'
|
|
2
2
|
|
|
3
|
+
vi.mock('./spatial-host', () => ({
|
|
4
|
+
openSpatialSceneSync: vi.fn().mockReturnValue({
|
|
5
|
+
success: true,
|
|
6
|
+
data: { id: 'scene-1', windowProxy: {} },
|
|
7
|
+
}),
|
|
8
|
+
}))
|
|
9
|
+
|
|
3
10
|
vi.mock('./JSBCommand', () => {
|
|
4
11
|
return {
|
|
5
|
-
createSpatialSceneCommand: vi.fn().mockImplementation(() => ({
|
|
6
|
-
executeSync: vi.fn().mockReturnValue({
|
|
7
|
-
data: { id: 'scene-1', windowProxy: {} },
|
|
8
|
-
}),
|
|
9
|
-
})),
|
|
10
12
|
FocusScene: vi.fn().mockImplementation(() => ({
|
|
11
13
|
execute: vi.fn().mockResolvedValue(undefined),
|
|
12
14
|
})),
|
package/src/scene-polyfill.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FocusScene } from './JSBCommand'
|
|
2
|
+
import { openSpatialSceneSync } from './spatial-host'
|
|
2
3
|
import { SpatialScene } from './SpatialScene'
|
|
3
4
|
import {
|
|
4
5
|
SpatialSceneCreationOptions,
|
|
@@ -221,8 +222,12 @@ class SceneManager {
|
|
|
221
222
|
cfg = { ...ans, type: 'window' }
|
|
222
223
|
}
|
|
223
224
|
|
|
224
|
-
const
|
|
225
|
-
|
|
225
|
+
const result = openSpatialSceneSync(
|
|
226
|
+
url!,
|
|
227
|
+
cfg as SpatialSceneCreationOptionsInternal,
|
|
228
|
+
target,
|
|
229
|
+
features,
|
|
230
|
+
)
|
|
226
231
|
|
|
227
232
|
const id = result.data?.id
|
|
228
233
|
|
|
@@ -429,8 +434,6 @@ export function formatSceneConfig(
|
|
|
429
434
|
// defaultSize should format into px if window
|
|
430
435
|
// defaultSize should format into m if volume
|
|
431
436
|
|
|
432
|
-
const defaultSceneConfig = getSceneDefaultConfig(sceneType)
|
|
433
|
-
|
|
434
437
|
const errors: string[] = []
|
|
435
438
|
|
|
436
439
|
const isWindow = sceneType === 'window'
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { WebSpatialProtocolResult } from './platform-adapter/interface'
|
|
2
|
+
import { getPlatform, getPlatformSync } from './platform-runtime'
|
|
3
|
+
import type { SpatialSceneCreationOptionsInternal } from './types/internal'
|
|
4
|
+
import type { AttachmentEntityOptions } from './types/types'
|
|
5
|
+
|
|
6
|
+
export async function createNativeSpatialDiv(): Promise<WebSpatialProtocolResult> {
|
|
7
|
+
const platform = await getPlatform()
|
|
8
|
+
return platform.createNativeSpatialDiv()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function createNativeAttachment(
|
|
12
|
+
options: AttachmentEntityOptions,
|
|
13
|
+
): Promise<WebSpatialProtocolResult> {
|
|
14
|
+
const platform = await getPlatform()
|
|
15
|
+
return platform.createNativeAttachment(options)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function openSpatialSceneSync(
|
|
19
|
+
url: string,
|
|
20
|
+
config: SpatialSceneCreationOptionsInternal | undefined,
|
|
21
|
+
target?: string,
|
|
22
|
+
features?: string,
|
|
23
|
+
): WebSpatialProtocolResult {
|
|
24
|
+
return getPlatformSync().openSpatialSceneSync(url, config, target, features)
|
|
25
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { PhysicalMetricsValueShape } from '../physicalMetrics'
|
|
2
|
+
import type { SpatialSceneCreationOptions, SpatialSceneType } from './types'
|
|
2
3
|
|
|
3
4
|
declare global {
|
|
4
|
-
|
|
5
|
+
const __WEBSPATIAL_CORE_SDK_VERSION__: string
|
|
5
6
|
|
|
6
7
|
interface Window {
|
|
7
8
|
xrCurrentSceneType: SpatialSceneType
|
|
@@ -41,13 +42,17 @@ declare global {
|
|
|
41
42
|
physicalMetrics?: PhysicalMetricsValueShape
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
xrInnerDepth
|
|
45
|
-
|
|
45
|
+
/** Present when `supports('xrInnerDepth')` is true; otherwise `undefined`. */
|
|
46
|
+
xrInnerDepth?: number
|
|
47
|
+
/** Present when `supports('xrOuterDepth')` is true; otherwise `undefined`. */
|
|
48
|
+
xrOuterDepth?: number
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
interface HTMLElement {
|
|
49
|
-
xrOffsetBack
|
|
50
|
-
|
|
52
|
+
/** Present when `supports('xrOffsetBack')` is true for element readbacks. */
|
|
53
|
+
xrOffsetBack?: number
|
|
54
|
+
/** Present when `supports('xrClientDepth')` is true for element readbacks. */
|
|
55
|
+
xrClientDepth?: number
|
|
51
56
|
}
|
|
52
57
|
}
|
|
53
58
|
|
package/src/types/types.ts
CHANGED
|
@@ -100,6 +100,8 @@ export interface ModelSource {
|
|
|
100
100
|
type?: string
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
export type ModelLoadingMode = 'eager' | 'lazy'
|
|
104
|
+
|
|
103
105
|
export interface SpatializedStatic3DElementProperties
|
|
104
106
|
extends SpatializedElementProperties {
|
|
105
107
|
modelURL: string
|
|
@@ -109,6 +111,9 @@ export interface SpatializedStatic3DElementProperties
|
|
|
109
111
|
loop?: boolean
|
|
110
112
|
animationPaused?: boolean
|
|
111
113
|
playbackRate?: number
|
|
114
|
+
currentTime?: number
|
|
115
|
+
posterURL?: string
|
|
116
|
+
loading?: ModelLoadingMode
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
export interface SpatialSceneCreationOptions {
|
|
@@ -262,6 +267,10 @@ export interface SpatialUnlitMaterialOptions {
|
|
|
262
267
|
opacity?: number
|
|
263
268
|
}
|
|
264
269
|
|
|
270
|
+
export interface SpatialTextureResourceOptions {
|
|
271
|
+
url: string
|
|
272
|
+
}
|
|
273
|
+
|
|
265
274
|
export interface ModelComponentOptions {
|
|
266
275
|
mesh: SpatialGeometry
|
|
267
276
|
materials: SpatialMaterial[]
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { PlatformAbility, CommandResult } from '../interface'
|
|
2
|
-
import {
|
|
3
|
-
CommandResultFailure,
|
|
4
|
-
CommandResultSuccess,
|
|
5
|
-
} from '../CommandResultUtils'
|
|
6
|
-
import { CheckWebViewCanCreateCommand } from '../../JSBCommand'
|
|
7
|
-
import { SpatialWebEvent } from '../../SpatialWebEvent'
|
|
8
|
-
|
|
9
|
-
interface JSBResponse {
|
|
10
|
-
success: boolean
|
|
11
|
-
data: any
|
|
12
|
-
}
|
|
13
|
-
type JSBError = {
|
|
14
|
-
code: string
|
|
15
|
-
message: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
let creatingElementCount = 0
|
|
19
|
-
|
|
20
|
-
let requestId = 0
|
|
21
|
-
|
|
22
|
-
const MAX_ID = 100000
|
|
23
|
-
|
|
24
|
-
function nextRequestId() {
|
|
25
|
-
requestId = (requestId + 1) % MAX_ID
|
|
26
|
-
return `rId_${requestId}`
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class AndroidPlatform implements PlatformAbility {
|
|
30
|
-
async callJSB(cmd: string, msg: string): Promise<CommandResult> {
|
|
31
|
-
// android JS Bridge interface only support sync invoking
|
|
32
|
-
// in order to implement promise API, register every request by requestId and remove when resolve/reject.
|
|
33
|
-
return new Promise((resolve, reject) => {
|
|
34
|
-
try {
|
|
35
|
-
const rId = nextRequestId()
|
|
36
|
-
|
|
37
|
-
SpatialWebEvent.addEventReceiver(rId, (result: JSBResponse) => {
|
|
38
|
-
SpatialWebEvent.removeEventReceiver(rId)
|
|
39
|
-
if (result.success) {
|
|
40
|
-
resolve(CommandResultSuccess(result.data))
|
|
41
|
-
} else {
|
|
42
|
-
const { code, message } = result.data as JSBError
|
|
43
|
-
resolve(CommandResultFailure(code, message))
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const ans = window.webspatialBridge.postMessage(rId, cmd, msg)
|
|
48
|
-
if (ans !== '') {
|
|
49
|
-
SpatialWebEvent.removeEventReceiver(rId)
|
|
50
|
-
// sync call
|
|
51
|
-
const result = JSON.parse(ans) as JSBResponse
|
|
52
|
-
if (result.success) {
|
|
53
|
-
resolve(CommandResultSuccess(result.data))
|
|
54
|
-
} else {
|
|
55
|
-
const { code, message } = result.data as JSBError
|
|
56
|
-
resolve(CommandResultFailure(code, message))
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
} catch (error: unknown) {
|
|
60
|
-
console.error(
|
|
61
|
-
`AndroidPlatform cmd: ${cmd}, msg: ${msg} error: ${error}`,
|
|
62
|
-
)
|
|
63
|
-
const { code, message } = error as JSBError
|
|
64
|
-
resolve(CommandResultFailure(code, message))
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async callWebSpatialProtocol(
|
|
70
|
-
command: string,
|
|
71
|
-
query?: string,
|
|
72
|
-
target?: string,
|
|
73
|
-
features?: string,
|
|
74
|
-
): Promise<CommandResult> {
|
|
75
|
-
// Waiting for request to create spatial div
|
|
76
|
-
await new Promise(resolve => setTimeout(resolve, 16 * creatingElementCount))
|
|
77
|
-
// Count the current total number of created spatial div queues
|
|
78
|
-
creatingElementCount++
|
|
79
|
-
// Create a spatial div through JSB polling request
|
|
80
|
-
let canCreate = await new CheckWebViewCanCreateCommand().execute()
|
|
81
|
-
while (!canCreate.data.can) {
|
|
82
|
-
await new Promise(resolve => setTimeout(resolve, 16))
|
|
83
|
-
canCreate = await new CheckWebViewCanCreateCommand().execute()
|
|
84
|
-
}
|
|
85
|
-
// Request successful, call window.open
|
|
86
|
-
const { windowProxy } = this.openWindow(command, query, target, features)
|
|
87
|
-
// Polling waiting for windowProxy to convert into a real window object
|
|
88
|
-
while (!windowProxy?.open) {
|
|
89
|
-
await new Promise(resolve => setTimeout(resolve, 16))
|
|
90
|
-
}
|
|
91
|
-
// Make the page renderable through window.open
|
|
92
|
-
windowProxy?.open('about:blank', '_self')
|
|
93
|
-
// Polling to check if SpatialId injection is successful
|
|
94
|
-
while (!windowProxy?.__SpatialId) {
|
|
95
|
-
await new Promise(resolve => setTimeout(resolve, 16))
|
|
96
|
-
}
|
|
97
|
-
let spatialId = windowProxy?.__SpatialId
|
|
98
|
-
creatingElementCount--
|
|
99
|
-
return Promise.resolve(
|
|
100
|
-
CommandResultSuccess({ windowProxy: windowProxy, id: spatialId }),
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
callWebSpatialProtocolSync(
|
|
105
|
-
command: string,
|
|
106
|
-
query?: string,
|
|
107
|
-
target?: string,
|
|
108
|
-
features?: string,
|
|
109
|
-
): CommandResult {
|
|
110
|
-
const { spatialId: id = '', windowProxy } = this.openWindow(
|
|
111
|
-
command,
|
|
112
|
-
query,
|
|
113
|
-
target,
|
|
114
|
-
features,
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
return CommandResultSuccess({ windowProxy, id })
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private openWindow(
|
|
121
|
-
command: string,
|
|
122
|
-
query?: string,
|
|
123
|
-
target?: string,
|
|
124
|
-
features?: string,
|
|
125
|
-
) {
|
|
126
|
-
const windowProxy = window.open(
|
|
127
|
-
`webspatial://${command}?${query || ''}`,
|
|
128
|
-
target,
|
|
129
|
-
features,
|
|
130
|
-
)
|
|
131
|
-
return { spatialId: '', windowProxy }
|
|
132
|
-
}
|
|
133
|
-
}
|