@webspatial/builder 1.0.4 → 1.0.5
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/dist/lib/pwa/config.js +55 -18
- package/dist/lib/utils/sceneUtils.d.ts +40 -0
- package/dist/lib/utils/sceneUtils.js +158 -0
- package/dist/lib/xcode/manifestSwiftTemplate.d.ts +1 -1
- package/dist/lib/xcode/manifestSwiftTemplate.js +8 -3
- package/dist/lib/xcode/xcodeproject.d.ts +2 -0
- package/dist/lib/xcode/xcodeproject.js +26 -7
- package/dist/lib/xcode/xcrun.d.ts +1 -0
- package/dist/lib/xcode/xcrun.js +21 -7
- package/dist/schema.json +95 -0
- package/package.json +5 -4
package/dist/lib/pwa/config.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.configScope = configScope;
|
|
|
7
7
|
exports.configDisplay = configDisplay;
|
|
8
8
|
exports.configMainScene = configMainScene;
|
|
9
9
|
exports.configDeeplink = configDeeplink;
|
|
10
|
+
const sceneUtils_1 = require("../utils/sceneUtils");
|
|
10
11
|
const utils_1 = require("../utils/utils");
|
|
11
12
|
const validate_1 = require("./validate");
|
|
12
13
|
const path_1 = require("path");
|
|
@@ -139,38 +140,74 @@ function configDisplay(manifestJson) {
|
|
|
139
140
|
manifestJson.display = display;
|
|
140
141
|
}
|
|
141
142
|
function configMainScene(manifestJson) {
|
|
142
|
-
var _a, _b;
|
|
143
|
-
const resizabilities = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight'];
|
|
143
|
+
var _a, _b, _c, _d, _e, _f;
|
|
144
144
|
let mainScene = {
|
|
145
|
-
|
|
146
|
-
width: 1280,
|
|
147
|
-
height: 1280,
|
|
148
|
-
},
|
|
145
|
+
...sceneUtils_1.defaultSceneConfig,
|
|
149
146
|
resizability: {},
|
|
147
|
+
type: 'window',
|
|
148
|
+
worldScaling: 'automatic',
|
|
149
|
+
worldAlignment: 'automatic',
|
|
150
|
+
baseplateVisibility: 'automatic',
|
|
150
151
|
};
|
|
152
|
+
// set type
|
|
153
|
+
if (((_a = manifestJson.xr_main_scene) === null || _a === void 0 ? void 0 : _a.type) == 'volume') {
|
|
154
|
+
mainScene.type = 'volume';
|
|
155
|
+
}
|
|
156
|
+
// set default value by type
|
|
157
|
+
if (mainScene.type == 'volume') {
|
|
158
|
+
mainScene = {
|
|
159
|
+
...mainScene,
|
|
160
|
+
...sceneUtils_1.defaultSceneConfigVolume,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
151
163
|
let hasResizability = false;
|
|
152
164
|
if (manifestJson.xr_main_scene &&
|
|
153
165
|
typeof manifestJson.xr_main_scene === 'object') {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
166
|
+
let defaultSizeKeys = ['width', 'height', 'depth'];
|
|
167
|
+
for (let k of defaultSizeKeys) {
|
|
168
|
+
if ((0, sceneUtils_1.isValidSceneUnit)((_b = manifestJson.xr_main_scene.default_size) === null || _b === void 0 ? void 0 : _b[k])) {
|
|
169
|
+
;
|
|
170
|
+
mainScene.defaultSize[k] = (0, sceneUtils_1.formatToNumber)((_c = manifestJson.xr_main_scene.default_size) === null || _c === void 0 ? void 0 : _c[k], mainScene.type === 'window' ? 'px' : 'm', mainScene.type === 'window' ? 'px' : 'm');
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
console.warn('invalid defaultSize type');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
162
176
|
if (typeof manifestJson.xr_main_scene.resizability === 'object') {
|
|
177
|
+
const resizabilities = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight'];
|
|
163
178
|
for (var i = 0; i < resizabilities.length; i++) {
|
|
164
|
-
if (manifestJson.xr_main_scene.resizability[resizabilities[i]]
|
|
179
|
+
if ((0, sceneUtils_1.isValidSceneUnit)(manifestJson.xr_main_scene.resizability[resizabilities[i]])) {
|
|
165
180
|
hasResizability = true;
|
|
166
|
-
|
|
167
|
-
|
|
181
|
+
//@ts-ignore
|
|
182
|
+
mainScene.resizability[resizabilities[i]] = (0, sceneUtils_1.formatToNumber)(manifestJson.xr_main_scene.resizability[resizabilities[i]], 'px', mainScene.type === 'window' ? 'px' : 'm');
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
console.warn('invalid resizability type');
|
|
168
186
|
}
|
|
169
187
|
}
|
|
170
188
|
}
|
|
171
189
|
}
|
|
172
190
|
if (!hasResizability) {
|
|
173
|
-
mainScene.resizability =
|
|
191
|
+
mainScene.resizability = undefined;
|
|
192
|
+
}
|
|
193
|
+
if ((0, sceneUtils_1.isValidWorldScalingType)((_d = manifestJson.xr_main_scene) === null || _d === void 0 ? void 0 : _d.worldScaling)) {
|
|
194
|
+
mainScene.worldScaling = manifestJson.xr_main_scene.worldScaling;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
console.warn('invalid worldScaling type');
|
|
198
|
+
}
|
|
199
|
+
if ((0, sceneUtils_1.isValidWorldAlignmentType)((_e = manifestJson.xr_main_scene) === null || _e === void 0 ? void 0 : _e.worldAlignment)) {
|
|
200
|
+
mainScene.worldAlignment = manifestJson.xr_main_scene.worldAlignment;
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
console.warn('invalid worldAlignment type');
|
|
204
|
+
}
|
|
205
|
+
if ((0, sceneUtils_1.isValidBaseplateVisibilityType)((_f = manifestJson.xr_main_scene) === null || _f === void 0 ? void 0 : _f.baseplateVisibility)) {
|
|
206
|
+
mainScene.baseplateVisibility =
|
|
207
|
+
manifestJson.xr_main_scene.baseplateVisibility;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
console.warn('invalid baseplateVisibility type');
|
|
174
211
|
}
|
|
175
212
|
manifestJson.xr_main_scene = mainScene;
|
|
176
213
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface SpatialSceneCreationOptions {
|
|
2
|
+
defaultSize?: {
|
|
3
|
+
width: number | string;
|
|
4
|
+
height: number | string;
|
|
5
|
+
depth?: number | string;
|
|
6
|
+
};
|
|
7
|
+
resizability?: {
|
|
8
|
+
minWidth?: number | string;
|
|
9
|
+
minHeight?: number | string;
|
|
10
|
+
maxWidth?: number | string;
|
|
11
|
+
maxHeight?: number | string;
|
|
12
|
+
};
|
|
13
|
+
worldScaling?: WorldScalingType;
|
|
14
|
+
worldAlignment?: WorldAlignmentType;
|
|
15
|
+
baseplateVisibility?: BaseplateVisibilityType;
|
|
16
|
+
}
|
|
17
|
+
export declare const BaseplateVisibilityValues: readonly ["automatic", "visible", "hidden"];
|
|
18
|
+
export type BaseplateVisibilityType = (typeof BaseplateVisibilityValues)[number];
|
|
19
|
+
export declare function isValidBaseplateVisibilityType(type: string): Boolean;
|
|
20
|
+
export declare const WorldScalingValues: readonly ["automatic", "dynamic"];
|
|
21
|
+
export type WorldScalingType = (typeof WorldScalingValues)[number];
|
|
22
|
+
export declare function isValidWorldScalingType(type: string): Boolean;
|
|
23
|
+
export declare const WorldAlignmentValues: readonly ["adaptive", "automatic", "gravityAligned"];
|
|
24
|
+
export type WorldAlignmentType = (typeof WorldAlignmentValues)[number];
|
|
25
|
+
export declare function isValidWorldAlignmentType(type: string): Boolean;
|
|
26
|
+
export declare const SpatialSceneValues: readonly ["window", "volume"];
|
|
27
|
+
export type SpatialSceneType = (typeof SpatialSceneValues)[number];
|
|
28
|
+
export declare function isValidSpatialSceneType(type: string): Boolean;
|
|
29
|
+
export type SpatialSceneCreationOptionsInternal = SpatialSceneCreationOptions & {
|
|
30
|
+
type: SpatialSceneType;
|
|
31
|
+
};
|
|
32
|
+
export declare function formatToNumber(str: string | number, targetUnit: 'px' | 'm', defaultUnit: 'px' | 'm'): number;
|
|
33
|
+
export declare function formatSceneConfig(config: SpatialSceneCreationOptions, sceneType: SpatialSceneType): SpatialSceneCreationOptions;
|
|
34
|
+
/**
|
|
35
|
+
* check px,m and number, number must be >= 0
|
|
36
|
+
*
|
|
37
|
+
* */
|
|
38
|
+
export declare function isValidSceneUnit(val: string | number): boolean;
|
|
39
|
+
export declare const defaultSceneConfig: SpatialSceneCreationOptions;
|
|
40
|
+
export declare const defaultSceneConfigVolume: SpatialSceneCreationOptions;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultSceneConfigVolume = exports.defaultSceneConfig = exports.SpatialSceneValues = exports.WorldAlignmentValues = exports.WorldScalingValues = exports.BaseplateVisibilityValues = void 0;
|
|
4
|
+
exports.isValidBaseplateVisibilityType = isValidBaseplateVisibilityType;
|
|
5
|
+
exports.isValidWorldScalingType = isValidWorldScalingType;
|
|
6
|
+
exports.isValidWorldAlignmentType = isValidWorldAlignmentType;
|
|
7
|
+
exports.isValidSpatialSceneType = isValidSpatialSceneType;
|
|
8
|
+
exports.formatToNumber = formatToNumber;
|
|
9
|
+
exports.formatSceneConfig = formatSceneConfig;
|
|
10
|
+
exports.isValidSceneUnit = isValidSceneUnit;
|
|
11
|
+
exports.BaseplateVisibilityValues = [
|
|
12
|
+
'automatic',
|
|
13
|
+
'visible',
|
|
14
|
+
'hidden',
|
|
15
|
+
];
|
|
16
|
+
function isValidBaseplateVisibilityType(type) {
|
|
17
|
+
return exports.BaseplateVisibilityValues.includes(type);
|
|
18
|
+
}
|
|
19
|
+
exports.WorldScalingValues = ['automatic', 'dynamic'];
|
|
20
|
+
function isValidWorldScalingType(type) {
|
|
21
|
+
return exports.WorldScalingValues.includes(type);
|
|
22
|
+
}
|
|
23
|
+
exports.WorldAlignmentValues = [
|
|
24
|
+
'adaptive',
|
|
25
|
+
'automatic',
|
|
26
|
+
'gravityAligned',
|
|
27
|
+
];
|
|
28
|
+
function isValidWorldAlignmentType(type) {
|
|
29
|
+
return exports.WorldAlignmentValues.includes(type);
|
|
30
|
+
}
|
|
31
|
+
exports.SpatialSceneValues = ['window', 'volume'];
|
|
32
|
+
function isValidSpatialSceneType(type) {
|
|
33
|
+
return exports.SpatialSceneValues.includes(type);
|
|
34
|
+
}
|
|
35
|
+
function pxToMeter(px) {
|
|
36
|
+
return px / 1360;
|
|
37
|
+
}
|
|
38
|
+
function meterToPx(meter) {
|
|
39
|
+
return meter * 1360;
|
|
40
|
+
}
|
|
41
|
+
function formatToNumber(str, targetUnit, defaultUnit) {
|
|
42
|
+
if (typeof str === 'number') {
|
|
43
|
+
if ((defaultUnit === 'px' && targetUnit === 'px') ||
|
|
44
|
+
(defaultUnit === 'm' && targetUnit === 'm')) {
|
|
45
|
+
return str;
|
|
46
|
+
}
|
|
47
|
+
// unit not match target
|
|
48
|
+
if (defaultUnit === 'px' && targetUnit === 'm') {
|
|
49
|
+
return pxToMeter(str);
|
|
50
|
+
}
|
|
51
|
+
else if (defaultUnit === 'm' && targetUnit === 'px') {
|
|
52
|
+
return meterToPx(str);
|
|
53
|
+
}
|
|
54
|
+
// fallback
|
|
55
|
+
return str;
|
|
56
|
+
}
|
|
57
|
+
if (targetUnit === 'm') {
|
|
58
|
+
if (str.endsWith('m')) {
|
|
59
|
+
// 1m
|
|
60
|
+
return Number(str.slice(0, -1));
|
|
61
|
+
}
|
|
62
|
+
else if (str.endsWith('px')) {
|
|
63
|
+
// 100px
|
|
64
|
+
return pxToMeter(Number(str.slice(0, -2)));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
throw new Error('formatToNumber: invalid str');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (targetUnit === 'px') {
|
|
71
|
+
if (str.endsWith('px')) {
|
|
72
|
+
// 100px
|
|
73
|
+
return Number(str.slice(0, -2));
|
|
74
|
+
}
|
|
75
|
+
else if (str.endsWith('m')) {
|
|
76
|
+
// 1m
|
|
77
|
+
return meterToPx(Number(str.slice(0, -1)));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
throw new Error('formatToNumber: invalid str');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
throw new Error('formatToNumber: invalid targetUnit');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function formatSceneConfig(config, sceneType) {
|
|
88
|
+
// defaultSize and resizability's width/height/depth can be 100 or "100px" or "1m"
|
|
89
|
+
// expect:
|
|
90
|
+
// resizability should format into px
|
|
91
|
+
// defaultSize should format into px if window
|
|
92
|
+
// defaultSize should format into m if volume
|
|
93
|
+
const isWindow = sceneType === 'window';
|
|
94
|
+
// const isVolume = sceneType === 'volume'
|
|
95
|
+
// format resizability
|
|
96
|
+
if (config.resizability) {
|
|
97
|
+
const iterKeys = Object.keys(config.resizability);
|
|
98
|
+
for (let k of iterKeys) {
|
|
99
|
+
if (config.resizability[k]) {
|
|
100
|
+
;
|
|
101
|
+
config.resizability[k] = formatToNumber(config.resizability[k], 'px', isWindow ? 'px' : 'm');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// format defaultSize
|
|
106
|
+
if (config.defaultSize) {
|
|
107
|
+
const iterKeys = Object.keys(config.defaultSize);
|
|
108
|
+
for (let k of iterKeys) {
|
|
109
|
+
if (config.defaultSize[k]) {
|
|
110
|
+
;
|
|
111
|
+
config.defaultSize[k] = formatToNumber(config.defaultSize[k], isWindow ? 'px' : 'm', isWindow ? 'px' : 'm');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return config;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* check px,m and number, number must be >= 0
|
|
119
|
+
*
|
|
120
|
+
* */
|
|
121
|
+
function isValidSceneUnit(val) {
|
|
122
|
+
// only support number or string with unit px or m
|
|
123
|
+
// rpx cm mm not allowed
|
|
124
|
+
if (typeof val === 'number') {
|
|
125
|
+
return val >= 0;
|
|
126
|
+
}
|
|
127
|
+
if (typeof val === 'string') {
|
|
128
|
+
if (val.endsWith('px')) {
|
|
129
|
+
// check if number
|
|
130
|
+
if (isNaN(Number(val.slice(0, -2)))) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
return Number(val.slice(0, -2)) >= 0;
|
|
134
|
+
}
|
|
135
|
+
if (val.endsWith('m')) {
|
|
136
|
+
// check if number
|
|
137
|
+
if (isNaN(Number(val.slice(0, -1)))) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
return Number(val.slice(0, -1)) >= 0;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
exports.defaultSceneConfig = {
|
|
146
|
+
defaultSize: {
|
|
147
|
+
width: 1280,
|
|
148
|
+
height: 720,
|
|
149
|
+
depth: 0,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
exports.defaultSceneConfigVolume = {
|
|
153
|
+
defaultSize: {
|
|
154
|
+
width: 0.94,
|
|
155
|
+
height: 0.94,
|
|
156
|
+
depth: 0.94,
|
|
157
|
+
},
|
|
158
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const manifestSwiftTemplate = "\nimport Foundation\n\nvar pwaManager = PWAManager()\n\nstruct PWAManager: Codable {\n var isLocal: Bool = false\n var start_url: String = \"START_URL\"\n var scope: String = \"SCOPE\"\n var id: String = \"AppID\"\n\n var name: String = \"AppName\"\n var short_name: String = \"name\"\n var description: String = \"Description\"\n\n var display: PWADisplayMode = .minimal\n var display_override: [PWADisplayMode] = []\n var protocol_handlers: [PWAProtocol] = [PWAProtocol(protocolValue: \"\", url: \"\")]\n var mainScene:
|
|
1
|
+
export declare const manifestSwiftTemplate = "\nimport Foundation\n\nvar pwaManager = PWAManager()\n\nstruct PWAManager: Codable {\n var isLocal: Bool = false\n var start_url: String = \"START_URL\"\n var scope: String = \"SCOPE\"\n var id: String = \"AppID\"\n\n var name: String = \"AppName\"\n var short_name: String = \"name\"\n var description: String = \"Description\"\n\n var display: PWADisplayMode = .minimal\n var display_override: [PWADisplayMode] = []\n var protocol_handlers: [PWAProtocol] = [PWAProtocol(protocolValue: \"\", url: \"\")]\n var mainScene: XSceneOptionsJSB = .init(\n defaultSize: .init(\n width: SceneWidth,\n height: SceneHeight,\n depth: SceneDepth\n ),\n type: .SceneType,\n resizability: SceneResizability,\n worldScaling: .WorldScaling,\n worldAlignment: .WorldAlignment,\n baseplateVisibility: .BaseplateVisibility\n )\n private var version: String = \"PACKAGE_VERSION\"\n\n mutating func _init() {\n let urlType = start_url.split(separator: \"://\").first\n if !(urlType == \"http\" || urlType == \"https\") {\n if scope == \"\" || scope == \"/\" {\n scope = \"./\"\n }\n let startUrl = Bundle.main.url(forResource: start_url, withExtension: \"\", subdirectory: \"\")\n start_url = startUrl!.absoluteString\n scope = URL(string: (scope.starts(with: \"/\") ? \".\" : \"./\") + scope, relativeTo: Bundle.main.executableURL)!.absoluteString\n isLocal = true\n }\n\n if display_override.count > 0 {\n display = display_override[0]\n }\n\n for i in 0 ... protocol_handlers.count - 1 {\n let item = protocol_handlers[i]\n protocol_handlers[i].updateUrl(scope + item.url)\n }\n }\n\n func checkInScope(url: String) -> Bool {\n return url.starts(with: scope)\n }\n\n // web+spatial://test\n func checkInDeeplink(url: String) -> String {\n var linkUrl: String = url\n for item in protocol_handlers {\n if linkUrl.starts(with: item.protocolValue) {\n let queryString: String = linkUrl.replacingOccurrences(of: item.protocolValue, with: \"\").addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!\n linkUrl = item.url.replacingOccurrences(of: \"%s\", with: item.protocolValue + queryString)\n }\n }\n logger.debug(linkUrl)\n return linkUrl\n }\n\n func getLocalResourceURL(url: String) -> String {\n let path = String(url.split(separator: \"file://\").first!.split(separator: \"?\").first!)\n let newUrl = URL(string: url)\n let fileManager = FileManager.default\n if fileManager.fileExists(atPath: newUrl!.path) {\n return url\n }\n var resource: String = Bundle.main.url(forResource: newUrl?.path, withExtension: \"\", subdirectory: \"\")?.absoluteString ?? \"\"\n if resource == \"\" {\n resource = Bundle.main.url(forResource: \"static-web\" + path, withExtension: \"\", subdirectory: \"\")?.absoluteString ?? \"\"\n }\n if resource == \"\" {\n return url\n }\n if newUrl?.query() != nil {\n resource += \"?\" + (newUrl?.query())!\n }\n if newUrl?.fragment() != nil {\n resource += \"#\" + (newUrl?.fragment())!\n }\n return resource\n }\n \n func getVersion() -> String {\n return version\n }\n}\n\nenum PWADisplayMode: Codable {\n case minimal\n case standalone\n case fullscreen\n}\n\nstruct PWAProtocol: Codable {\n var protocolValue: String = \"\"\n var url: String = \"\"\n\n mutating func updateUrl(_ str: String) {\n url = str\n }\n}\n\n";
|
|
@@ -19,12 +19,17 @@ struct PWAManager: Codable {
|
|
|
19
19
|
var display: PWADisplayMode = .minimal
|
|
20
20
|
var display_override: [PWADisplayMode] = []
|
|
21
21
|
var protocol_handlers: [PWAProtocol] = [PWAProtocol(protocolValue: "", url: "")]
|
|
22
|
-
var mainScene:
|
|
22
|
+
var mainScene: XSceneOptionsJSB = .init(
|
|
23
23
|
defaultSize: .init(
|
|
24
24
|
width: SceneWidth,
|
|
25
|
-
height: SceneHeight
|
|
25
|
+
height: SceneHeight,
|
|
26
|
+
depth: SceneDepth
|
|
26
27
|
),
|
|
27
|
-
|
|
28
|
+
type: .SceneType,
|
|
29
|
+
resizability: SceneResizability,
|
|
30
|
+
worldScaling: .WorldScaling,
|
|
31
|
+
worldAlignment: .WorldAlignment,
|
|
32
|
+
baseplateVisibility: .BaseplateVisibility
|
|
28
33
|
)
|
|
29
34
|
private var version: String = "PACKAGE_VERSION"
|
|
30
35
|
|
|
@@ -6,6 +6,8 @@ export default class XcodeProject {
|
|
|
6
6
|
private static updateExportOptions;
|
|
7
7
|
private static bindManifestInfo;
|
|
8
8
|
private static updateVersion;
|
|
9
|
+
private static writeInfoPlist;
|
|
10
|
+
private static updateSceneType;
|
|
9
11
|
private static updateDeeplink;
|
|
10
12
|
private static modifySwift;
|
|
11
13
|
}
|
|
@@ -50,7 +50,7 @@ const infoPlistXML = `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
50
50
|
<key>UIApplicationSceneManifest</key>
|
|
51
51
|
<dict>
|
|
52
52
|
<key>UIApplicationPreferredDefaultSceneSessionRole</key>
|
|
53
|
-
<string>
|
|
53
|
+
<string>SCENE_SESSION_ROLE</string>
|
|
54
54
|
<key>UIApplicationSupportsMultipleScenes</key>
|
|
55
55
|
<true/>
|
|
56
56
|
<key>UISceneConfigurations</key>
|
|
@@ -190,30 +190,44 @@ class XcodeProject {
|
|
|
190
190
|
fs.writeFileSync((0, path_1.join)(resource_1.PROJECT_BUILD_DIRECTORY, 'ExportOptions.plist'), useExportOptionsXML);
|
|
191
191
|
}
|
|
192
192
|
static async bindManifestInfo(xcodeProject, manifest, isDev = false) {
|
|
193
|
-
var _a;
|
|
193
|
+
var _a, _b;
|
|
194
194
|
xcodeProject.updateProductName(manifest.name);
|
|
195
195
|
// set PRODUCT_BUNDLE_IDENTIFIER need ""
|
|
196
196
|
if (manifest.id) {
|
|
197
197
|
xcodeProject.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', `"${manifest.id}"`);
|
|
198
198
|
}
|
|
199
|
-
|
|
199
|
+
let tempInfoPlistXML = infoPlistXML.slice(); // clone
|
|
200
|
+
tempInfoPlistXML = this.updateDeeplink((_a = manifest.protocol_handlers) !== null && _a !== void 0 ? _a : [], tempInfoPlistXML);
|
|
201
|
+
tempInfoPlistXML = this.updateSceneType((_b = manifest.xr_main_scene) === null || _b === void 0 ? void 0 : _b.type, tempInfoPlistXML);
|
|
202
|
+
this.writeInfoPlist(tempInfoPlistXML);
|
|
200
203
|
await this.modifySwift(manifest);
|
|
201
204
|
}
|
|
202
205
|
static updateVersion(xcodeProject, version) {
|
|
203
206
|
xcodeProject.updateBuildProperty('CURRENT_PROJECT_VERSION', version);
|
|
204
207
|
}
|
|
205
|
-
static
|
|
206
|
-
|
|
208
|
+
static writeInfoPlist(infoPlistXML) {
|
|
209
|
+
const infoPlistPath = (0, path_1.join)(resource_1.PROJECT_DIRECTORY, './web-spatial/Info.plist');
|
|
210
|
+
fs.writeFileSync(infoPlistPath, infoPlistXML);
|
|
211
|
+
}
|
|
212
|
+
static updateSceneType(sceneType, infoPlistXML) {
|
|
213
|
+
let sceneSessionRole = 'UIWindowSceneSessionRoleApplication';
|
|
214
|
+
if (sceneType === 'volume') {
|
|
215
|
+
sceneSessionRole = 'UIWindowSceneSessionRoleVolumetricApplication';
|
|
216
|
+
}
|
|
217
|
+
infoPlistXML = infoPlistXML.replace('SCENE_SESSION_ROLE', sceneSessionRole);
|
|
218
|
+
return infoPlistXML;
|
|
219
|
+
}
|
|
220
|
+
static updateDeeplink(deeplinks, infoPlistXML) {
|
|
207
221
|
let deeplinkString = '';
|
|
208
222
|
for (let i = 0; i < deeplinks.length; i++) {
|
|
209
223
|
deeplinkString += `<string>${deeplinks[i].protocol}</string>`;
|
|
210
224
|
}
|
|
211
225
|
const newInfoPlist = infoPlistXML.replace('DEEPLINK', deeplinkString);
|
|
212
|
-
|
|
226
|
+
return newInfoPlist;
|
|
213
227
|
}
|
|
214
228
|
static async modifySwift(manifest) {
|
|
215
229
|
var _a;
|
|
216
|
-
const manifestSwiftPath = (0, path_1.join)(resource_1.PROJECT_DIRECTORY, './web-spatial/
|
|
230
|
+
const manifestSwiftPath = (0, path_1.join)(resource_1.PROJECT_DIRECTORY, './web-spatial/manifest.swift');
|
|
217
231
|
const xcodePackageJsonPath = (0, path_1.join)(resource_1.PROJECT_DIRECTORY, 'package.json');
|
|
218
232
|
const packageJson = await (0, load_1.loadJsonFromDisk)(xcodePackageJsonPath);
|
|
219
233
|
let manifestSwift = manifestSwiftTemplate_1.manifestSwiftTemplate;
|
|
@@ -233,6 +247,7 @@ class XcodeProject {
|
|
|
233
247
|
}
|
|
234
248
|
manifestSwift = manifestSwift.replace('SceneWidth', manifest.xr_main_scene.defaultSize.width);
|
|
235
249
|
manifestSwift = manifestSwift.replace('SceneHeight', manifest.xr_main_scene.defaultSize.height);
|
|
250
|
+
manifestSwift = manifestSwift.replace('SceneDepth', manifest.xr_main_scene.defaultSize.depth);
|
|
236
251
|
let res = 'nil';
|
|
237
252
|
const resizabilities = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight'];
|
|
238
253
|
if (manifest.xr_main_scene.resizability) {
|
|
@@ -246,6 +261,10 @@ class XcodeProject {
|
|
|
246
261
|
res += ')';
|
|
247
262
|
}
|
|
248
263
|
manifestSwift = manifestSwift.replace('SceneResizability', res);
|
|
264
|
+
manifestSwift = manifestSwift.replace('SceneType', manifest.xr_main_scene.type);
|
|
265
|
+
manifestSwift = manifestSwift.replace('WorldScaling', manifest.xr_main_scene.worldScaling);
|
|
266
|
+
manifestSwift = manifestSwift.replace('WorldAlignment', manifest.xr_main_scene.worldAlignment);
|
|
267
|
+
manifestSwift = manifestSwift.replace('BaseplateVisibility', manifest.xr_main_scene.baseplateVisibility);
|
|
249
268
|
fs.writeFileSync(manifestSwiftPath, manifestSwift, 'utf-8');
|
|
250
269
|
}
|
|
251
270
|
}
|
|
@@ -32,6 +32,7 @@ export default class Xcrun {
|
|
|
32
32
|
private static buildTestApp;
|
|
33
33
|
private static terminateApp;
|
|
34
34
|
private static installApp;
|
|
35
|
+
private static uninstallApp;
|
|
35
36
|
private static launchApp;
|
|
36
37
|
private static parseDestinationDevices;
|
|
37
38
|
private static parseSupportDevices;
|
package/dist/lib/xcode/xcrun.js
CHANGED
|
@@ -111,7 +111,7 @@ class Xcrun {
|
|
|
111
111
|
// launch visionOS simulator
|
|
112
112
|
this.launchSimulator(device);
|
|
113
113
|
try {
|
|
114
|
-
this.
|
|
114
|
+
this.uninstallApp(device.deviceId, appInfo.id);
|
|
115
115
|
}
|
|
116
116
|
catch (_a) { }
|
|
117
117
|
// install app
|
|
@@ -182,6 +182,9 @@ class Xcrun {
|
|
|
182
182
|
cmd.install(deviceId, appFile);
|
|
183
183
|
(0, child_process_1.execSync)(cmd.line);
|
|
184
184
|
}
|
|
185
|
+
static uninstallApp(deviceId, appId) {
|
|
186
|
+
(0, child_process_1.execSync)(new XcrunCMD().simctl().uninstall(deviceId, appId).line);
|
|
187
|
+
}
|
|
185
188
|
static launchApp(deviceId, bundleId) {
|
|
186
189
|
(0, child_process_1.execSync)(new XcrunCMD().simctl().launch(deviceId, bundleId).line);
|
|
187
190
|
}
|
|
@@ -283,15 +286,22 @@ class Xcrun {
|
|
|
283
286
|
/*
|
|
284
287
|
* device info like:
|
|
285
288
|
* Apple Vision Pro (8C7AD003-4039-478F-9F94-938876D57817) (Shutdown)
|
|
289
|
+
* Apple Vision Pro (xxx) (8C7AD003-4039-478F-9F94-938876D57817) (Shutdown)
|
|
286
290
|
*/
|
|
287
291
|
static parseDeviceInfo(device) {
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
292
|
+
var _a;
|
|
293
|
+
const uuidRegex = /[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}/i;
|
|
294
|
+
const uuidMatch = (_a = device.match(uuidRegex)) !== null && _a !== void 0 ? _a : ["()"];
|
|
295
|
+
const deviceId = uuidMatch[0];
|
|
296
|
+
const name = device.substring(0, device.indexOf(deviceId) - 1).trim();
|
|
297
|
+
const statePart = device.substring(device.indexOf(deviceId) + deviceId.length).trim();
|
|
298
|
+
const stateMatch = statePart.match(/\(([^)]+)\)/);
|
|
299
|
+
const state = stateMatch ? stateMatch[1].trim() : 'Unknown';
|
|
300
|
+
return {
|
|
301
|
+
name: name,
|
|
302
|
+
deviceId: deviceId,
|
|
303
|
+
state: state
|
|
293
304
|
};
|
|
294
|
-
return deviceInfo;
|
|
295
305
|
}
|
|
296
306
|
// Try to find an available simulator, if not, create one and save the running record for the next time direct use.
|
|
297
307
|
static findSimulator(deviceId) {
|
|
@@ -433,6 +443,10 @@ class XcrunCMD {
|
|
|
433
443
|
this.line += ` install "${device}" "${path}"`;
|
|
434
444
|
return this;
|
|
435
445
|
}
|
|
446
|
+
uninstall(device, packName) {
|
|
447
|
+
this.line += ` uninstall "${device}" "${packName}"`;
|
|
448
|
+
return this;
|
|
449
|
+
}
|
|
436
450
|
launch(device, packName) {
|
|
437
451
|
this.line += ` launch "${device}" "${packName}"`;
|
|
438
452
|
return this;
|
package/dist/schema.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
+
"title": "Schema for PWA Manifest",
|
|
4
|
+
"description": "Schema for PWA Manifest",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
"start_url": {
|
|
11
|
+
"type": "string"
|
|
12
|
+
},
|
|
13
|
+
"display": {
|
|
14
|
+
"type": "string"
|
|
15
|
+
},
|
|
16
|
+
"xr_main_scene": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": {
|
|
19
|
+
"type": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"enum": ["window", "volume"]
|
|
22
|
+
},
|
|
23
|
+
"default_size": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"properties": {
|
|
26
|
+
"width": {
|
|
27
|
+
"type": ["number", "string"]
|
|
28
|
+
},
|
|
29
|
+
"height": {
|
|
30
|
+
"type": ["number", "string"]
|
|
31
|
+
},
|
|
32
|
+
"depth": {
|
|
33
|
+
"type": ["number", "string"]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"required": ["height", "width"]
|
|
37
|
+
},
|
|
38
|
+
"resizability": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"properties": {
|
|
41
|
+
"minWidth": {
|
|
42
|
+
"type": ["number", "string"]
|
|
43
|
+
},
|
|
44
|
+
"maxWidth": {
|
|
45
|
+
"type": ["number", "string"]
|
|
46
|
+
},
|
|
47
|
+
"minHeight": {
|
|
48
|
+
"type": ["number", "string"]
|
|
49
|
+
},
|
|
50
|
+
"maxHeight": {
|
|
51
|
+
"type": ["number", "string"]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"required": []
|
|
55
|
+
},
|
|
56
|
+
"worldScaling": {
|
|
57
|
+
"enum": ["automatic", "dynamic"],
|
|
58
|
+
"type": "string"
|
|
59
|
+
},
|
|
60
|
+
"worldAlignment": {
|
|
61
|
+
"enum": ["adaptive", "automatic", "gravityAligned"],
|
|
62
|
+
"type": "string"
|
|
63
|
+
},
|
|
64
|
+
"baseplateVisibility": {
|
|
65
|
+
"enum": ["visible", "hidden", "automatic"],
|
|
66
|
+
"type": "string"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"required": []
|
|
70
|
+
},
|
|
71
|
+
"icons": {
|
|
72
|
+
"type": "array",
|
|
73
|
+
"items": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"properties": {
|
|
76
|
+
"src": {
|
|
77
|
+
"type": "string"
|
|
78
|
+
},
|
|
79
|
+
"sizes": {
|
|
80
|
+
"type": "string"
|
|
81
|
+
},
|
|
82
|
+
"type": {
|
|
83
|
+
"type": "string"
|
|
84
|
+
},
|
|
85
|
+
"purpose": {
|
|
86
|
+
"type": "string"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"required": ["purpose", "sizes", "src", "type"]
|
|
90
|
+
},
|
|
91
|
+
"minItems": 0
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"required": ["display", "icons", "name", "start_url"]
|
|
95
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webspatial/builder",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Client CLI tool to Generate XRApp project for Apple Vision Pro",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"engines": {
|
|
@@ -19,12 +19,13 @@
|
|
|
19
19
|
"dist/assets",
|
|
20
20
|
"dist/index.d.ts",
|
|
21
21
|
"dist/index.js",
|
|
22
|
+
"dist/schema.json",
|
|
22
23
|
"bin",
|
|
23
24
|
"package.json",
|
|
24
25
|
"README.md"
|
|
25
26
|
],
|
|
26
27
|
"author": "",
|
|
27
|
-
"license": "
|
|
28
|
+
"license": "MIT",
|
|
28
29
|
"dependencies": {
|
|
29
30
|
"@resvg/resvg-js": "^2.6.2",
|
|
30
31
|
"cli-progress": "^3.8.2",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"sharp": "^0.33.5",
|
|
41
42
|
"valid-url": "^1.0.9",
|
|
42
43
|
"xcode": "^3.0.1",
|
|
43
|
-
"@webspatial/platform-visionos": "^1.0.
|
|
44
|
+
"@webspatial/platform-visionos": "^1.0.5"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"@rollup/plugin-terser": "^0.4.3",
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
"build": "tsc && npm run copy-assets",
|
|
75
76
|
"build1": "rollup -c ./rollup.config.js",
|
|
76
77
|
"build2": "tsc && npm run copy-assets",
|
|
77
|
-
"copy-assets": "cp -R src/assets/ dist/assets/",
|
|
78
|
+
"copy-assets": "cp -R src/assets/ dist/assets/ && cp -R src/schema.json dist/",
|
|
78
79
|
"clean": "rm -rf dist",
|
|
79
80
|
"lint": "eslint \"src/**/*.{js,ts}\""
|
|
80
81
|
}
|