@lvce-editor/title-bar-worker 1.0.0 → 1.1.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/dist/titleBarWorkerMain.js +2132 -868
- package/package.json +1 -1
|
@@ -1,368 +1,161 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const state$1 = {
|
|
10
|
-
callbacks: Object.create(null)
|
|
11
|
-
};
|
|
12
|
-
const set = (id, fn) => {
|
|
13
|
-
state$1.callbacks[id] = fn;
|
|
14
|
-
};
|
|
15
|
-
const get = id => {
|
|
16
|
-
return state$1.callbacks[id];
|
|
17
|
-
};
|
|
18
|
-
const remove = id => {
|
|
19
|
-
delete state$1.callbacks[id];
|
|
20
|
-
};
|
|
21
|
-
let id = 0;
|
|
22
|
-
const create$3 = () => {
|
|
23
|
-
return ++id;
|
|
1
|
+
const normalizeLine = line => {
|
|
2
|
+
if (line.startsWith('Error: ')) {
|
|
3
|
+
return line.slice('Error: '.length);
|
|
4
|
+
}
|
|
5
|
+
if (line.startsWith('VError: ')) {
|
|
6
|
+
return line.slice('VError: '.length);
|
|
7
|
+
}
|
|
8
|
+
return line;
|
|
24
9
|
};
|
|
25
|
-
const
|
|
26
|
-
|
|
10
|
+
const getCombinedMessage = (error, message) => {
|
|
11
|
+
const stringifiedError = normalizeLine(`${error}`);
|
|
12
|
+
if (message) {
|
|
13
|
+
return `${message}: ${stringifiedError}`;
|
|
14
|
+
}
|
|
15
|
+
return stringifiedError;
|
|
27
16
|
};
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
resolve,
|
|
32
|
-
promise
|
|
33
|
-
} = Promise.withResolvers();
|
|
34
|
-
set(id, resolve);
|
|
35
|
-
return {
|
|
36
|
-
id,
|
|
37
|
-
promise
|
|
38
|
-
};
|
|
17
|
+
const NewLine$2 = '\n';
|
|
18
|
+
const getNewLineIndex$1 = (string, startIndex = undefined) => {
|
|
19
|
+
return string.indexOf(NewLine$2, startIndex);
|
|
39
20
|
};
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
console.log(response);
|
|
44
|
-
warn(`callback ${id} may already be disposed`);
|
|
45
|
-
return;
|
|
21
|
+
const mergeStacks = (parent, child) => {
|
|
22
|
+
if (!child) {
|
|
23
|
+
return parent;
|
|
46
24
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
id
|
|
60
|
-
};
|
|
61
|
-
return {
|
|
62
|
-
message,
|
|
63
|
-
promise
|
|
64
|
-
};
|
|
25
|
+
const parentNewLineIndex = getNewLineIndex$1(parent);
|
|
26
|
+
const childNewLineIndex = getNewLineIndex$1(child);
|
|
27
|
+
if (childNewLineIndex === -1) {
|
|
28
|
+
return parent;
|
|
29
|
+
}
|
|
30
|
+
const parentFirstLine = parent.slice(0, parentNewLineIndex);
|
|
31
|
+
const childRest = child.slice(childNewLineIndex);
|
|
32
|
+
const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
|
|
33
|
+
if (parentFirstLine.includes(childFirstLine)) {
|
|
34
|
+
return parentFirstLine + childRest;
|
|
35
|
+
}
|
|
36
|
+
return child;
|
|
65
37
|
};
|
|
66
|
-
class
|
|
38
|
+
class VError extends Error {
|
|
39
|
+
constructor(error, message) {
|
|
40
|
+
const combinedMessage = getCombinedMessage(error, message);
|
|
41
|
+
super(combinedMessage);
|
|
42
|
+
this.name = 'VError';
|
|
43
|
+
if (error instanceof Error) {
|
|
44
|
+
this.stack = mergeStacks(this.stack, error.stack);
|
|
45
|
+
}
|
|
46
|
+
if (error.codeFrame) {
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
this.codeFrame = error.codeFrame;
|
|
49
|
+
}
|
|
50
|
+
if (error.code) {
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
this.code = error.code;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class AssertionError extends Error {
|
|
67
58
|
constructor(message) {
|
|
68
59
|
super(message);
|
|
69
|
-
this.name = '
|
|
60
|
+
this.name = 'AssertionError';
|
|
70
61
|
}
|
|
71
62
|
}
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (message.startsWith('TypeError: ')) {
|
|
93
|
-
return TypeError;
|
|
63
|
+
const getType = value => {
|
|
64
|
+
switch (typeof value) {
|
|
65
|
+
case 'number':
|
|
66
|
+
return 'number';
|
|
67
|
+
case 'function':
|
|
68
|
+
return 'function';
|
|
69
|
+
case 'string':
|
|
70
|
+
return 'string';
|
|
71
|
+
case 'object':
|
|
72
|
+
if (value === null) {
|
|
73
|
+
return 'null';
|
|
74
|
+
}
|
|
75
|
+
if (Array.isArray(value)) {
|
|
76
|
+
return 'array';
|
|
77
|
+
}
|
|
78
|
+
return 'object';
|
|
79
|
+
case 'boolean':
|
|
80
|
+
return 'boolean';
|
|
81
|
+
default:
|
|
82
|
+
return 'unknown';
|
|
94
83
|
}
|
|
95
|
-
|
|
96
|
-
|
|
84
|
+
};
|
|
85
|
+
const object = value => {
|
|
86
|
+
const type = getType(value);
|
|
87
|
+
if (type !== 'object') {
|
|
88
|
+
throw new AssertionError('expected value to be of type object');
|
|
97
89
|
}
|
|
98
|
-
|
|
99
|
-
|
|
90
|
+
};
|
|
91
|
+
const number = value => {
|
|
92
|
+
const type = getType(value);
|
|
93
|
+
if (type !== 'number') {
|
|
94
|
+
throw new AssertionError('expected value to be of type number');
|
|
100
95
|
}
|
|
101
|
-
return Error;
|
|
102
96
|
};
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
106
|
-
|
|
97
|
+
const string = value => {
|
|
98
|
+
const type = getType(value);
|
|
99
|
+
if (type !== 'string') {
|
|
100
|
+
throw new AssertionError('expected value to be of type string');
|
|
107
101
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return error;
|
|
102
|
+
};
|
|
103
|
+
const boolean = value => {
|
|
104
|
+
const type = getType(value);
|
|
105
|
+
if (type !== 'boolean') {
|
|
106
|
+
throw new AssertionError('expected value to be of type boolean');
|
|
114
107
|
}
|
|
115
|
-
return new ErrorConstructor(message);
|
|
116
108
|
};
|
|
117
|
-
|
|
118
|
-
|
|
109
|
+
|
|
110
|
+
const isMessagePort = value => {
|
|
111
|
+
return value && value instanceof MessagePort;
|
|
119
112
|
};
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
if (parentStack.startsWith(' at')) {
|
|
123
|
-
parentStack = error.message + NewLine$2 + parentStack;
|
|
124
|
-
}
|
|
125
|
-
return parentStack;
|
|
113
|
+
const isMessagePortMain = value => {
|
|
114
|
+
return value && value.constructor && value.constructor.name === 'MessagePortMain';
|
|
126
115
|
};
|
|
127
|
-
const
|
|
128
|
-
return
|
|
116
|
+
const isOffscreenCanvas = value => {
|
|
117
|
+
return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
|
|
129
118
|
};
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
const splitLines$1 = lines => {
|
|
133
|
-
return lines.split(NewLine$2);
|
|
119
|
+
const isInstanceOf = (value, constructorName) => {
|
|
120
|
+
return value?.constructor?.name === constructorName;
|
|
134
121
|
};
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
restoredError.stack = parentStack + NewLine$2 + currentStack;
|
|
144
|
-
return restoredError;
|
|
145
|
-
}
|
|
146
|
-
if (error && error.message) {
|
|
147
|
-
const restoredError = constructError(error.message, error.type, error.name);
|
|
148
|
-
if (error.data) {
|
|
149
|
-
if (error.data.stack && error.data.type && error.message) {
|
|
150
|
-
restoredError.stack = error.data.type + ': ' + error.message + NewLine$2 + error.data.stack + NewLine$2 + currentStack;
|
|
151
|
-
} else if (error.data.stack) {
|
|
152
|
-
restoredError.stack = error.data.stack;
|
|
153
|
-
}
|
|
154
|
-
if (error.data.codeFrame) {
|
|
155
|
-
// @ts-ignore
|
|
156
|
-
restoredError.codeFrame = error.data.codeFrame;
|
|
157
|
-
}
|
|
158
|
-
if (error.data.code) {
|
|
159
|
-
// @ts-ignore
|
|
160
|
-
restoredError.code = error.data.code;
|
|
161
|
-
}
|
|
162
|
-
if (error.data.type) {
|
|
163
|
-
// @ts-ignore
|
|
164
|
-
restoredError.name = error.data.type;
|
|
165
|
-
}
|
|
166
|
-
} else {
|
|
167
|
-
if (error.stack) {
|
|
168
|
-
const lowerStack = restoredError.stack || '';
|
|
169
|
-
// @ts-ignore
|
|
170
|
-
const indexNewLine = getNewLineIndex$1(lowerStack);
|
|
171
|
-
const parentStack = getParentStack(error);
|
|
172
|
-
// @ts-ignore
|
|
173
|
-
restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
|
|
174
|
-
}
|
|
175
|
-
if (error.codeFrame) {
|
|
176
|
-
// @ts-ignore
|
|
177
|
-
restoredError.codeFrame = error.codeFrame;
|
|
178
|
-
}
|
|
122
|
+
const isSocket = value => {
|
|
123
|
+
return isInstanceOf(value, 'Socket');
|
|
124
|
+
};
|
|
125
|
+
const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
|
|
126
|
+
const isTransferrable = value => {
|
|
127
|
+
for (const fn of transferrables) {
|
|
128
|
+
if (fn(value)) {
|
|
129
|
+
return true;
|
|
179
130
|
}
|
|
180
|
-
return restoredError;
|
|
181
|
-
}
|
|
182
|
-
if (typeof error === 'string') {
|
|
183
|
-
return new Error(`JsonRpc Error: ${error}`);
|
|
184
131
|
}
|
|
185
|
-
return
|
|
132
|
+
return false;
|
|
186
133
|
};
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
189
|
-
|
|
190
|
-
throw restoredError;
|
|
191
|
-
}
|
|
192
|
-
if ('result' in responseMessage) {
|
|
193
|
-
return responseMessage.result;
|
|
194
|
-
}
|
|
195
|
-
throw new JsonRpcError('unexpected response message');
|
|
196
|
-
};
|
|
197
|
-
const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
|
|
198
|
-
const getErrorType = prettyError => {
|
|
199
|
-
if (prettyError && prettyError.type) {
|
|
200
|
-
return prettyError.type;
|
|
201
|
-
}
|
|
202
|
-
if (prettyError && prettyError.constructor && prettyError.constructor.name) {
|
|
203
|
-
return prettyError.constructor.name;
|
|
204
|
-
}
|
|
205
|
-
return undefined;
|
|
206
|
-
};
|
|
207
|
-
const getErrorProperty = (error, prettyError) => {
|
|
208
|
-
if (error && error.code === E_COMMAND_NOT_FOUND) {
|
|
209
|
-
return {
|
|
210
|
-
code: MethodNotFound,
|
|
211
|
-
message: error.message,
|
|
212
|
-
data: error.stack
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
return {
|
|
216
|
-
code: Custom,
|
|
217
|
-
message: prettyError.message,
|
|
218
|
-
data: {
|
|
219
|
-
stack: prettyError.stack,
|
|
220
|
-
codeFrame: prettyError.codeFrame,
|
|
221
|
-
type: getErrorType(prettyError),
|
|
222
|
-
code: prettyError.code,
|
|
223
|
-
name: prettyError.name
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
|
-
};
|
|
227
|
-
const create$1$1 = (message, error) => {
|
|
228
|
-
return {
|
|
229
|
-
jsonrpc: Two,
|
|
230
|
-
id: message.id,
|
|
231
|
-
error
|
|
232
|
-
};
|
|
233
|
-
};
|
|
234
|
-
const getErrorResponse = (message, error, preparePrettyError, logError) => {
|
|
235
|
-
const prettyError = preparePrettyError(error);
|
|
236
|
-
logError(error, prettyError);
|
|
237
|
-
const errorProperty = getErrorProperty(error, prettyError);
|
|
238
|
-
return create$1$1(message, errorProperty);
|
|
239
|
-
};
|
|
240
|
-
const create$5 = (message, result) => {
|
|
241
|
-
return {
|
|
242
|
-
jsonrpc: Two,
|
|
243
|
-
id: message.id,
|
|
244
|
-
result: result ?? null
|
|
245
|
-
};
|
|
246
|
-
};
|
|
247
|
-
const getSuccessResponse = (message, result) => {
|
|
248
|
-
const resultProperty = result ?? null;
|
|
249
|
-
return create$5(message, resultProperty);
|
|
250
|
-
};
|
|
251
|
-
const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
|
|
252
|
-
try {
|
|
253
|
-
const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
|
|
254
|
-
return getSuccessResponse(message, result);
|
|
255
|
-
} catch (error) {
|
|
256
|
-
return getErrorResponse(message, error, preparePrettyError, logError);
|
|
134
|
+
const walkValue = (value, transferrables, isTransferrable) => {
|
|
135
|
+
if (!value) {
|
|
136
|
+
return;
|
|
257
137
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
};
|
|
262
|
-
const defaultLogError = () => {
|
|
263
|
-
// ignore
|
|
264
|
-
};
|
|
265
|
-
const defaultRequiresSocket = () => {
|
|
266
|
-
return false;
|
|
267
|
-
};
|
|
268
|
-
const defaultResolve = resolve;
|
|
269
|
-
|
|
270
|
-
// TODO maybe remove this in v6 or v7, only accept options object to simplify the code
|
|
271
|
-
const normalizeParams = args => {
|
|
272
|
-
if (args.length === 1) {
|
|
273
|
-
const options = args[0];
|
|
274
|
-
return {
|
|
275
|
-
ipc: options.ipc,
|
|
276
|
-
message: options.message,
|
|
277
|
-
execute: options.execute,
|
|
278
|
-
resolve: options.resolve || defaultResolve,
|
|
279
|
-
preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
|
|
280
|
-
logError: options.logError || defaultLogError,
|
|
281
|
-
requiresSocket: options.requiresSocket || defaultRequiresSocket
|
|
282
|
-
};
|
|
138
|
+
if (isTransferrable(value)) {
|
|
139
|
+
transferrables.push(value);
|
|
140
|
+
return;
|
|
283
141
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
execute: args[2],
|
|
288
|
-
resolve: args[3],
|
|
289
|
-
preparePrettyError: args[4],
|
|
290
|
-
logError: args[5],
|
|
291
|
-
requiresSocket: args[6]
|
|
292
|
-
};
|
|
293
|
-
};
|
|
294
|
-
const handleJsonRpcMessage = async (...args) => {
|
|
295
|
-
const options = normalizeParams(args);
|
|
296
|
-
const {
|
|
297
|
-
message,
|
|
298
|
-
ipc,
|
|
299
|
-
execute,
|
|
300
|
-
resolve,
|
|
301
|
-
preparePrettyError,
|
|
302
|
-
logError,
|
|
303
|
-
requiresSocket
|
|
304
|
-
} = options;
|
|
305
|
-
if ('id' in message) {
|
|
306
|
-
if ('method' in message) {
|
|
307
|
-
const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
|
|
308
|
-
try {
|
|
309
|
-
ipc.send(response);
|
|
310
|
-
} catch (error) {
|
|
311
|
-
const errorResponse = getErrorResponse(message, error, preparePrettyError, logError);
|
|
312
|
-
ipc.send(errorResponse);
|
|
313
|
-
}
|
|
314
|
-
return;
|
|
142
|
+
if (Array.isArray(value)) {
|
|
143
|
+
for (const item of value) {
|
|
144
|
+
walkValue(item, transferrables, isTransferrable);
|
|
315
145
|
}
|
|
316
|
-
resolve(message.id, message);
|
|
317
146
|
return;
|
|
318
147
|
}
|
|
319
|
-
if ('
|
|
320
|
-
|
|
148
|
+
if (typeof value === 'object') {
|
|
149
|
+
for (const property of Object.values(value)) {
|
|
150
|
+
walkValue(property, transferrables, isTransferrable);
|
|
151
|
+
}
|
|
321
152
|
return;
|
|
322
153
|
}
|
|
323
|
-
throw new JsonRpcError('unexpected message');
|
|
324
|
-
};
|
|
325
|
-
const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
|
|
326
|
-
const {
|
|
327
|
-
message,
|
|
328
|
-
promise
|
|
329
|
-
} = create$2(method, params);
|
|
330
|
-
if (useSendAndTransfer && ipc.sendAndTransfer) {
|
|
331
|
-
ipc.sendAndTransfer(message);
|
|
332
|
-
} else {
|
|
333
|
-
ipc.send(message);
|
|
334
|
-
}
|
|
335
|
-
const responseMessage = await promise;
|
|
336
|
-
return unwrapJsonRpcResult(responseMessage);
|
|
337
|
-
};
|
|
338
|
-
const send = (transport, method, ...params) => {
|
|
339
|
-
const message = create$4(method, params);
|
|
340
|
-
transport.send(message);
|
|
341
|
-
};
|
|
342
|
-
const invoke = (ipc, method, ...params) => {
|
|
343
|
-
return invokeHelper(ipc, method, params, false);
|
|
344
|
-
};
|
|
345
|
-
const invokeAndTransfer = (ipc, method, ...params) => {
|
|
346
|
-
return invokeHelper(ipc, method, params, true);
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
const commands = Object.create(null);
|
|
350
|
-
const register = commandMap => {
|
|
351
|
-
Object.assign(commands, commandMap);
|
|
352
|
-
};
|
|
353
|
-
const getCommand = key => {
|
|
354
|
-
return commands[key];
|
|
355
|
-
};
|
|
356
|
-
const execute = (command, ...args) => {
|
|
357
|
-
const fn = getCommand(command);
|
|
358
|
-
if (!fn) {
|
|
359
|
-
throw new Error(`command not found ${command}`);
|
|
360
|
-
}
|
|
361
|
-
return fn(...args);
|
|
362
154
|
};
|
|
363
|
-
|
|
364
|
-
const
|
|
365
|
-
|
|
155
|
+
const getTransferrables = value => {
|
|
156
|
+
const transferrables = [];
|
|
157
|
+
walkValue(value, transferrables, isTransferrable);
|
|
158
|
+
return transferrables;
|
|
366
159
|
};
|
|
367
160
|
const attachEvents = that => {
|
|
368
161
|
const handleMessage = (...args) => {
|
|
@@ -384,108 +177,61 @@ class Ipc extends EventTarget {
|
|
|
384
177
|
attachEvents(this);
|
|
385
178
|
}
|
|
386
179
|
}
|
|
387
|
-
const
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
180
|
+
const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
|
|
181
|
+
const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
|
|
182
|
+
const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
|
|
183
|
+
const NewLine$1 = '\n';
|
|
184
|
+
const joinLines$1 = lines => {
|
|
185
|
+
return lines.join(NewLine$1);
|
|
186
|
+
};
|
|
187
|
+
const RE_AT = /^\s+at/;
|
|
188
|
+
const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
|
|
189
|
+
const isNormalStackLine = line => {
|
|
190
|
+
return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
|
|
191
|
+
};
|
|
192
|
+
const getDetails = lines => {
|
|
193
|
+
const index = lines.findIndex(isNormalStackLine);
|
|
194
|
+
if (index === -1) {
|
|
195
|
+
return {
|
|
196
|
+
actualMessage: joinLines$1(lines),
|
|
197
|
+
rest: []
|
|
198
|
+
};
|
|
401
199
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
200
|
+
let lastIndex = index - 1;
|
|
201
|
+
while (++lastIndex < lines.length) {
|
|
202
|
+
if (!isNormalStackLine(lines[lastIndex])) {
|
|
203
|
+
break;
|
|
405
204
|
}
|
|
406
|
-
return;
|
|
407
205
|
}
|
|
206
|
+
return {
|
|
207
|
+
actualMessage: lines[index - 1],
|
|
208
|
+
rest: lines.slice(index, lastIndex)
|
|
209
|
+
};
|
|
408
210
|
};
|
|
409
|
-
const
|
|
410
|
-
return
|
|
211
|
+
const splitLines$1 = lines => {
|
|
212
|
+
return lines.split(NewLine$1);
|
|
411
213
|
};
|
|
412
|
-
const
|
|
413
|
-
|
|
214
|
+
const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
|
|
215
|
+
const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
|
|
216
|
+
const isMessageCodeBlockStartIndex = line => {
|
|
217
|
+
return RE_MESSAGE_CODE_BLOCK_START.test(line);
|
|
414
218
|
};
|
|
415
|
-
const
|
|
416
|
-
return
|
|
219
|
+
const isMessageCodeBlockEndIndex = line => {
|
|
220
|
+
return RE_MESSAGE_CODE_BLOCK_END.test(line);
|
|
417
221
|
};
|
|
418
|
-
const
|
|
419
|
-
|
|
222
|
+
const getMessageCodeBlock = stderr => {
|
|
223
|
+
const lines = splitLines$1(stderr);
|
|
224
|
+
const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
|
|
225
|
+
const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
|
|
226
|
+
const relevantLines = lines.slice(startIndex, endIndex);
|
|
227
|
+
const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
|
|
228
|
+
return relevantMessage;
|
|
420
229
|
};
|
|
421
|
-
const
|
|
422
|
-
return
|
|
423
|
-
};
|
|
424
|
-
const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
|
|
425
|
-
const isTransferrable = value => {
|
|
426
|
-
for (const fn of transferrables) {
|
|
427
|
-
if (fn(value)) {
|
|
428
|
-
return true;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return false;
|
|
432
|
-
};
|
|
433
|
-
const getTransferrables = value => {
|
|
434
|
-
const transferrables = [];
|
|
435
|
-
walkValue(value, transferrables, isTransferrable);
|
|
436
|
-
return transferrables;
|
|
437
|
-
};
|
|
438
|
-
const listen$2 = () => {
|
|
439
|
-
// @ts-ignore
|
|
440
|
-
if (typeof WorkerGlobalScope === 'undefined') {
|
|
441
|
-
throw new TypeError('module is not in web worker scope');
|
|
442
|
-
}
|
|
443
|
-
return globalThis;
|
|
444
|
-
};
|
|
445
|
-
const signal$2 = global => {
|
|
446
|
-
global.postMessage(readyMessage);
|
|
447
|
-
};
|
|
448
|
-
class IpcChildWithModuleWorker extends Ipc {
|
|
449
|
-
getData(event) {
|
|
450
|
-
return getData$1(event);
|
|
451
|
-
}
|
|
452
|
-
send(message) {
|
|
453
|
-
// @ts-ignore
|
|
454
|
-
this._rawIpc.postMessage(message);
|
|
455
|
-
}
|
|
456
|
-
sendAndTransfer(message) {
|
|
457
|
-
const transfer = getTransferrables(message);
|
|
458
|
-
// @ts-ignore
|
|
459
|
-
this._rawIpc.postMessage(message, transfer);
|
|
460
|
-
}
|
|
461
|
-
dispose() {
|
|
462
|
-
// ignore
|
|
463
|
-
}
|
|
464
|
-
onClose(callback) {
|
|
465
|
-
// ignore
|
|
466
|
-
}
|
|
467
|
-
onMessage(callback) {
|
|
468
|
-
this._rawIpc.addEventListener('message', callback);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
const wrap$5 = global => {
|
|
472
|
-
return new IpcChildWithModuleWorker(global);
|
|
473
|
-
};
|
|
474
|
-
const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
|
|
475
|
-
const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
|
|
476
|
-
const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
|
|
477
|
-
const NewLine$1 = '\n';
|
|
478
|
-
const joinLines = lines => {
|
|
479
|
-
return lines.join(NewLine$1);
|
|
480
|
-
};
|
|
481
|
-
const splitLines = lines => {
|
|
482
|
-
return lines.split(NewLine$1);
|
|
483
|
-
};
|
|
484
|
-
const isModuleNotFoundMessage = line => {
|
|
485
|
-
return line.includes('[ERR_MODULE_NOT_FOUND]');
|
|
230
|
+
const isModuleNotFoundMessage = line => {
|
|
231
|
+
return line.includes('[ERR_MODULE_NOT_FOUND]');
|
|
486
232
|
};
|
|
487
233
|
const getModuleNotFoundError = stderr => {
|
|
488
|
-
const lines = splitLines(stderr);
|
|
234
|
+
const lines = splitLines$1(stderr);
|
|
489
235
|
const messageIndex = lines.findIndex(isModuleNotFoundMessage);
|
|
490
236
|
const message = lines[messageIndex];
|
|
491
237
|
return {
|
|
@@ -493,29 +239,23 @@ const getModuleNotFoundError = stderr => {
|
|
|
493
239
|
code: ERR_MODULE_NOT_FOUND
|
|
494
240
|
};
|
|
495
241
|
};
|
|
242
|
+
const isModuleNotFoundError = stderr => {
|
|
243
|
+
if (!stderr) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
return stderr.includes('ERR_MODULE_NOT_FOUND');
|
|
247
|
+
};
|
|
248
|
+
const isModulesSyntaxError = stderr => {
|
|
249
|
+
if (!stderr) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
return stderr.includes('SyntaxError: Cannot use import statement outside a module');
|
|
253
|
+
};
|
|
496
254
|
const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
|
|
497
255
|
const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
|
|
498
|
-
const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
|
|
499
|
-
const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
|
|
500
|
-
const RE_AT = /^\s+at/;
|
|
501
|
-
const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
|
|
502
256
|
const isUnhelpfulNativeModuleError = stderr => {
|
|
503
257
|
return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
|
|
504
258
|
};
|
|
505
|
-
const isMessageCodeBlockStartIndex = line => {
|
|
506
|
-
return RE_MESSAGE_CODE_BLOCK_START.test(line);
|
|
507
|
-
};
|
|
508
|
-
const isMessageCodeBlockEndIndex = line => {
|
|
509
|
-
return RE_MESSAGE_CODE_BLOCK_END.test(line);
|
|
510
|
-
};
|
|
511
|
-
const getMessageCodeBlock = stderr => {
|
|
512
|
-
const lines = splitLines(stderr);
|
|
513
|
-
const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
|
|
514
|
-
const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
|
|
515
|
-
const relevantLines = lines.slice(startIndex, endIndex);
|
|
516
|
-
const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
|
|
517
|
-
return relevantMessage;
|
|
518
|
-
};
|
|
519
259
|
const getNativeModuleErrorMessage = stderr => {
|
|
520
260
|
const message = getMessageCodeBlock(stderr);
|
|
521
261
|
return {
|
|
@@ -523,46 +263,12 @@ const getNativeModuleErrorMessage = stderr => {
|
|
|
523
263
|
code: E_INCOMPATIBLE_NATIVE_MODULE
|
|
524
264
|
};
|
|
525
265
|
};
|
|
526
|
-
const isModulesSyntaxError = stderr => {
|
|
527
|
-
if (!stderr) {
|
|
528
|
-
return false;
|
|
529
|
-
}
|
|
530
|
-
return stderr.includes('SyntaxError: Cannot use import statement outside a module');
|
|
531
|
-
};
|
|
532
266
|
const getModuleSyntaxError = () => {
|
|
533
267
|
return {
|
|
534
268
|
message: `ES Modules are not supported in electron`,
|
|
535
269
|
code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
|
|
536
270
|
};
|
|
537
271
|
};
|
|
538
|
-
const isModuleNotFoundError = stderr => {
|
|
539
|
-
if (!stderr) {
|
|
540
|
-
return false;
|
|
541
|
-
}
|
|
542
|
-
return stderr.includes('ERR_MODULE_NOT_FOUND');
|
|
543
|
-
};
|
|
544
|
-
const isNormalStackLine = line => {
|
|
545
|
-
return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
|
|
546
|
-
};
|
|
547
|
-
const getDetails = lines => {
|
|
548
|
-
const index = lines.findIndex(isNormalStackLine);
|
|
549
|
-
if (index === -1) {
|
|
550
|
-
return {
|
|
551
|
-
actualMessage: joinLines(lines),
|
|
552
|
-
rest: []
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
let lastIndex = index - 1;
|
|
556
|
-
while (++lastIndex < lines.length) {
|
|
557
|
-
if (!isNormalStackLine(lines[lastIndex])) {
|
|
558
|
-
break;
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
return {
|
|
562
|
-
actualMessage: lines[index - 1],
|
|
563
|
-
rest: lines.slice(index, lastIndex)
|
|
564
|
-
};
|
|
565
|
-
};
|
|
566
272
|
const getHelpfulChildProcessError = (stdout, stderr) => {
|
|
567
273
|
if (isUnhelpfulNativeModuleError(stderr)) {
|
|
568
274
|
return getNativeModuleErrorMessage(stderr);
|
|
@@ -573,72 +279,17 @@ const getHelpfulChildProcessError = (stdout, stderr) => {
|
|
|
573
279
|
if (isModuleNotFoundError(stderr)) {
|
|
574
280
|
return getModuleNotFoundError(stderr);
|
|
575
281
|
}
|
|
576
|
-
const lines = splitLines(stderr);
|
|
282
|
+
const lines = splitLines$1(stderr);
|
|
577
283
|
const {
|
|
578
284
|
actualMessage,
|
|
579
285
|
rest
|
|
580
286
|
} = getDetails(lines);
|
|
581
287
|
return {
|
|
582
|
-
message:
|
|
288
|
+
message: actualMessage,
|
|
583
289
|
code: '',
|
|
584
290
|
stack: rest
|
|
585
291
|
};
|
|
586
292
|
};
|
|
587
|
-
const normalizeLine = line => {
|
|
588
|
-
if (line.startsWith('Error: ')) {
|
|
589
|
-
return line.slice('Error: '.length);
|
|
590
|
-
}
|
|
591
|
-
if (line.startsWith('VError: ')) {
|
|
592
|
-
return line.slice('VError: '.length);
|
|
593
|
-
}
|
|
594
|
-
return line;
|
|
595
|
-
};
|
|
596
|
-
const getCombinedMessage = (error, message) => {
|
|
597
|
-
const stringifiedError = normalizeLine(`${error}`);
|
|
598
|
-
if (message) {
|
|
599
|
-
return `${message}: ${stringifiedError}`;
|
|
600
|
-
}
|
|
601
|
-
return stringifiedError;
|
|
602
|
-
};
|
|
603
|
-
const NewLine = '\n';
|
|
604
|
-
const getNewLineIndex = (string, startIndex = undefined) => {
|
|
605
|
-
return string.indexOf(NewLine, startIndex);
|
|
606
|
-
};
|
|
607
|
-
const mergeStacks = (parent, child) => {
|
|
608
|
-
if (!child) {
|
|
609
|
-
return parent;
|
|
610
|
-
}
|
|
611
|
-
const parentNewLineIndex = getNewLineIndex(parent);
|
|
612
|
-
const childNewLineIndex = getNewLineIndex(child);
|
|
613
|
-
if (childNewLineIndex === -1) {
|
|
614
|
-
return parent;
|
|
615
|
-
}
|
|
616
|
-
const parentFirstLine = parent.slice(0, parentNewLineIndex);
|
|
617
|
-
const childRest = child.slice(childNewLineIndex);
|
|
618
|
-
const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
|
|
619
|
-
if (parentFirstLine.includes(childFirstLine)) {
|
|
620
|
-
return parentFirstLine + childRest;
|
|
621
|
-
}
|
|
622
|
-
return child;
|
|
623
|
-
};
|
|
624
|
-
class VError extends Error {
|
|
625
|
-
constructor(error, message) {
|
|
626
|
-
const combinedMessage = getCombinedMessage(error, message);
|
|
627
|
-
super(combinedMessage);
|
|
628
|
-
this.name = 'VError';
|
|
629
|
-
if (error instanceof Error) {
|
|
630
|
-
this.stack = mergeStacks(this.stack, error.stack);
|
|
631
|
-
}
|
|
632
|
-
if (error.codeFrame) {
|
|
633
|
-
// @ts-ignore
|
|
634
|
-
this.codeFrame = error.codeFrame;
|
|
635
|
-
}
|
|
636
|
-
if (error.code) {
|
|
637
|
-
// @ts-ignore
|
|
638
|
-
this.code = error.code;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
293
|
class IpcError extends VError {
|
|
643
294
|
// @ts-ignore
|
|
644
295
|
constructor(betterMessage, stdout = '', stderr = '') {
|
|
@@ -665,12 +316,53 @@ class IpcError extends VError {
|
|
|
665
316
|
this.stderr = stderr;
|
|
666
317
|
}
|
|
667
318
|
}
|
|
319
|
+
const readyMessage = 'ready';
|
|
320
|
+
const getData$2 = event => {
|
|
321
|
+
return event.data;
|
|
322
|
+
};
|
|
323
|
+
const listen$7 = () => {
|
|
324
|
+
// @ts-ignore
|
|
325
|
+
if (typeof WorkerGlobalScope === 'undefined') {
|
|
326
|
+
throw new TypeError('module is not in web worker scope');
|
|
327
|
+
}
|
|
328
|
+
return globalThis;
|
|
329
|
+
};
|
|
330
|
+
const signal$8 = global => {
|
|
331
|
+
global.postMessage(readyMessage);
|
|
332
|
+
};
|
|
333
|
+
class IpcChildWithModuleWorker extends Ipc {
|
|
334
|
+
getData(event) {
|
|
335
|
+
return getData$2(event);
|
|
336
|
+
}
|
|
337
|
+
send(message) {
|
|
338
|
+
// @ts-ignore
|
|
339
|
+
this._rawIpc.postMessage(message);
|
|
340
|
+
}
|
|
341
|
+
sendAndTransfer(message) {
|
|
342
|
+
const transfer = getTransferrables(message);
|
|
343
|
+
// @ts-ignore
|
|
344
|
+
this._rawIpc.postMessage(message, transfer);
|
|
345
|
+
}
|
|
346
|
+
dispose() {
|
|
347
|
+
// ignore
|
|
348
|
+
}
|
|
349
|
+
onClose(callback) {
|
|
350
|
+
// ignore
|
|
351
|
+
}
|
|
352
|
+
onMessage(callback) {
|
|
353
|
+
this._rawIpc.addEventListener('message', callback);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const wrap$f = global => {
|
|
357
|
+
return new IpcChildWithModuleWorker(global);
|
|
358
|
+
};
|
|
668
359
|
const withResolvers = () => {
|
|
669
360
|
let _resolve;
|
|
670
361
|
const promise = new Promise(resolve => {
|
|
671
362
|
_resolve = resolve;
|
|
672
363
|
});
|
|
673
364
|
return {
|
|
365
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
674
366
|
resolve: _resolve,
|
|
675
367
|
promise
|
|
676
368
|
};
|
|
@@ -687,10 +379,10 @@ const waitForFirstMessage = async port => {
|
|
|
687
379
|
// @ts-ignore
|
|
688
380
|
return event.data;
|
|
689
381
|
};
|
|
690
|
-
const listen$
|
|
691
|
-
const parentIpcRaw = listen$
|
|
692
|
-
signal$
|
|
693
|
-
const parentIpc = wrap$
|
|
382
|
+
const listen$6 = async () => {
|
|
383
|
+
const parentIpcRaw = listen$7();
|
|
384
|
+
signal$8(parentIpcRaw);
|
|
385
|
+
const parentIpc = wrap$f(parentIpcRaw);
|
|
694
386
|
const firstMessage = await waitForFirstMessage(parentIpc);
|
|
695
387
|
if (firstMessage.method !== 'initialize') {
|
|
696
388
|
throw new IpcError('unexpected first message');
|
|
@@ -709,11 +401,8 @@ const listen$1$1 = async () => {
|
|
|
709
401
|
return globalThis;
|
|
710
402
|
};
|
|
711
403
|
class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
|
|
712
|
-
constructor(port) {
|
|
713
|
-
super(port);
|
|
714
|
-
}
|
|
715
404
|
getData(event) {
|
|
716
|
-
return getData$
|
|
405
|
+
return getData$2(event);
|
|
717
406
|
}
|
|
718
407
|
send(message) {
|
|
719
408
|
this._rawIpc.postMessage(message);
|
|
@@ -735,416 +424,1991 @@ class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
|
|
|
735
424
|
this._rawIpc.start();
|
|
736
425
|
}
|
|
737
426
|
}
|
|
738
|
-
const wrap$
|
|
427
|
+
const wrap$e = port => {
|
|
739
428
|
return new IpcChildWithModuleWorkerAndMessagePort(port);
|
|
740
429
|
};
|
|
741
430
|
const IpcChildWithModuleWorkerAndMessagePort$1 = {
|
|
742
431
|
__proto__: null,
|
|
743
|
-
listen: listen$
|
|
744
|
-
wrap: wrap$
|
|
432
|
+
listen: listen$6,
|
|
433
|
+
wrap: wrap$e
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
const Two = '2.0';
|
|
437
|
+
const create$4 = (method, params) => {
|
|
438
|
+
return {
|
|
439
|
+
jsonrpc: Two,
|
|
440
|
+
method,
|
|
441
|
+
params
|
|
442
|
+
};
|
|
443
|
+
};
|
|
444
|
+
const callbacks = Object.create(null);
|
|
445
|
+
const set = (id, fn) => {
|
|
446
|
+
callbacks[id] = fn;
|
|
447
|
+
};
|
|
448
|
+
const get = id => {
|
|
449
|
+
return callbacks[id];
|
|
450
|
+
};
|
|
451
|
+
const remove = id => {
|
|
452
|
+
delete callbacks[id];
|
|
453
|
+
};
|
|
454
|
+
let id$a = 0;
|
|
455
|
+
const create$3 = () => {
|
|
456
|
+
return ++id$a;
|
|
457
|
+
};
|
|
458
|
+
const registerPromise = () => {
|
|
459
|
+
const id = create$3();
|
|
460
|
+
const {
|
|
461
|
+
resolve,
|
|
462
|
+
promise
|
|
463
|
+
} = Promise.withResolvers();
|
|
464
|
+
set(id, resolve);
|
|
465
|
+
return {
|
|
466
|
+
id,
|
|
467
|
+
promise
|
|
468
|
+
};
|
|
469
|
+
};
|
|
470
|
+
const create$2 = (method, params) => {
|
|
471
|
+
const {
|
|
472
|
+
id,
|
|
473
|
+
promise
|
|
474
|
+
} = registerPromise();
|
|
475
|
+
const message = {
|
|
476
|
+
jsonrpc: Two,
|
|
477
|
+
method,
|
|
478
|
+
params,
|
|
479
|
+
id
|
|
480
|
+
};
|
|
481
|
+
return {
|
|
482
|
+
message,
|
|
483
|
+
promise
|
|
484
|
+
};
|
|
485
|
+
};
|
|
486
|
+
class JsonRpcError extends Error {
|
|
487
|
+
constructor(message) {
|
|
488
|
+
super(message);
|
|
489
|
+
this.name = 'JsonRpcError';
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
const NewLine = '\n';
|
|
493
|
+
const DomException = 'DOMException';
|
|
494
|
+
const ReferenceError$1 = 'ReferenceError';
|
|
495
|
+
const SyntaxError$1 = 'SyntaxError';
|
|
496
|
+
const TypeError$1 = 'TypeError';
|
|
497
|
+
const getErrorConstructor = (message, type) => {
|
|
498
|
+
if (type) {
|
|
499
|
+
switch (type) {
|
|
500
|
+
case DomException:
|
|
501
|
+
return DOMException;
|
|
502
|
+
case TypeError$1:
|
|
503
|
+
return TypeError;
|
|
504
|
+
case SyntaxError$1:
|
|
505
|
+
return SyntaxError;
|
|
506
|
+
case ReferenceError$1:
|
|
507
|
+
return ReferenceError;
|
|
508
|
+
default:
|
|
509
|
+
return Error;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (message.startsWith('TypeError: ')) {
|
|
513
|
+
return TypeError;
|
|
514
|
+
}
|
|
515
|
+
if (message.startsWith('SyntaxError: ')) {
|
|
516
|
+
return SyntaxError;
|
|
517
|
+
}
|
|
518
|
+
if (message.startsWith('ReferenceError: ')) {
|
|
519
|
+
return ReferenceError;
|
|
520
|
+
}
|
|
521
|
+
return Error;
|
|
522
|
+
};
|
|
523
|
+
const constructError = (message, type, name) => {
|
|
524
|
+
const ErrorConstructor = getErrorConstructor(message, type);
|
|
525
|
+
if (ErrorConstructor === DOMException && name) {
|
|
526
|
+
return new ErrorConstructor(message, name);
|
|
527
|
+
}
|
|
528
|
+
if (ErrorConstructor === Error) {
|
|
529
|
+
const error = new Error(message);
|
|
530
|
+
if (name && name !== 'VError') {
|
|
531
|
+
error.name = name;
|
|
532
|
+
}
|
|
533
|
+
return error;
|
|
534
|
+
}
|
|
535
|
+
return new ErrorConstructor(message);
|
|
536
|
+
};
|
|
537
|
+
const getNewLineIndex = (string, startIndex = undefined) => {
|
|
538
|
+
return string.indexOf(NewLine, startIndex);
|
|
539
|
+
};
|
|
540
|
+
const getParentStack = error => {
|
|
541
|
+
let parentStack = error.stack || error.data || error.message || '';
|
|
542
|
+
if (parentStack.startsWith(' at')) {
|
|
543
|
+
parentStack = error.message + NewLine + parentStack;
|
|
544
|
+
}
|
|
545
|
+
return parentStack;
|
|
546
|
+
};
|
|
547
|
+
const joinLines = lines => {
|
|
548
|
+
return lines.join(NewLine);
|
|
549
|
+
};
|
|
550
|
+
const MethodNotFound = -32601;
|
|
551
|
+
const Custom = -32001;
|
|
552
|
+
const splitLines = lines => {
|
|
553
|
+
return lines.split(NewLine);
|
|
554
|
+
};
|
|
555
|
+
const restoreJsonRpcError = error => {
|
|
556
|
+
if (error && error instanceof Error) {
|
|
557
|
+
return error;
|
|
558
|
+
}
|
|
559
|
+
const currentStack = joinLines(splitLines(new Error().stack || '').slice(1));
|
|
560
|
+
if (error && error.code && error.code === MethodNotFound) {
|
|
561
|
+
const restoredError = new JsonRpcError(error.message);
|
|
562
|
+
const parentStack = getParentStack(error);
|
|
563
|
+
restoredError.stack = parentStack + NewLine + currentStack;
|
|
564
|
+
return restoredError;
|
|
565
|
+
}
|
|
566
|
+
if (error && error.message) {
|
|
567
|
+
const restoredError = constructError(error.message, error.type, error.name);
|
|
568
|
+
if (error.data) {
|
|
569
|
+
if (error.data.stack && error.data.type && error.message) {
|
|
570
|
+
restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
|
|
571
|
+
} else if (error.data.stack) {
|
|
572
|
+
restoredError.stack = error.data.stack;
|
|
573
|
+
}
|
|
574
|
+
if (error.data.codeFrame) {
|
|
575
|
+
// @ts-ignore
|
|
576
|
+
restoredError.codeFrame = error.data.codeFrame;
|
|
577
|
+
}
|
|
578
|
+
if (error.data.code) {
|
|
579
|
+
// @ts-ignore
|
|
580
|
+
restoredError.code = error.data.code;
|
|
581
|
+
}
|
|
582
|
+
if (error.data.type) {
|
|
583
|
+
// @ts-ignore
|
|
584
|
+
restoredError.name = error.data.type;
|
|
585
|
+
}
|
|
586
|
+
} else {
|
|
587
|
+
if (error.stack) {
|
|
588
|
+
const lowerStack = restoredError.stack || '';
|
|
589
|
+
// @ts-ignore
|
|
590
|
+
const indexNewLine = getNewLineIndex(lowerStack);
|
|
591
|
+
const parentStack = getParentStack(error);
|
|
592
|
+
// @ts-ignore
|
|
593
|
+
restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
|
|
594
|
+
}
|
|
595
|
+
if (error.codeFrame) {
|
|
596
|
+
// @ts-ignore
|
|
597
|
+
restoredError.codeFrame = error.codeFrame;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return restoredError;
|
|
601
|
+
}
|
|
602
|
+
if (typeof error === 'string') {
|
|
603
|
+
return new Error(`JsonRpc Error: ${error}`);
|
|
604
|
+
}
|
|
605
|
+
return new Error(`JsonRpc Error: ${error}`);
|
|
606
|
+
};
|
|
607
|
+
const unwrapJsonRpcResult = responseMessage => {
|
|
608
|
+
if ('error' in responseMessage) {
|
|
609
|
+
const restoredError = restoreJsonRpcError(responseMessage.error);
|
|
610
|
+
throw restoredError;
|
|
611
|
+
}
|
|
612
|
+
if ('result' in responseMessage) {
|
|
613
|
+
return responseMessage.result;
|
|
614
|
+
}
|
|
615
|
+
throw new JsonRpcError('unexpected response message');
|
|
616
|
+
};
|
|
617
|
+
const warn = (...args) => {
|
|
618
|
+
console.warn(...args);
|
|
619
|
+
};
|
|
620
|
+
const resolve = (id, response) => {
|
|
621
|
+
const fn = get(id);
|
|
622
|
+
if (!fn) {
|
|
623
|
+
console.log(response);
|
|
624
|
+
warn(`callback ${id} may already be disposed`);
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
fn(response);
|
|
628
|
+
remove(id);
|
|
629
|
+
};
|
|
630
|
+
const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
|
|
631
|
+
const getErrorType = prettyError => {
|
|
632
|
+
if (prettyError && prettyError.type) {
|
|
633
|
+
return prettyError.type;
|
|
634
|
+
}
|
|
635
|
+
if (prettyError && prettyError.constructor && prettyError.constructor.name) {
|
|
636
|
+
return prettyError.constructor.name;
|
|
637
|
+
}
|
|
638
|
+
return undefined;
|
|
639
|
+
};
|
|
640
|
+
const getErrorProperty = (error, prettyError) => {
|
|
641
|
+
if (error && error.code === E_COMMAND_NOT_FOUND) {
|
|
642
|
+
return {
|
|
643
|
+
code: MethodNotFound,
|
|
644
|
+
message: error.message,
|
|
645
|
+
data: error.stack
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
return {
|
|
649
|
+
code: Custom,
|
|
650
|
+
message: prettyError.message,
|
|
651
|
+
data: {
|
|
652
|
+
stack: prettyError.stack,
|
|
653
|
+
codeFrame: prettyError.codeFrame,
|
|
654
|
+
type: getErrorType(prettyError),
|
|
655
|
+
code: prettyError.code,
|
|
656
|
+
name: prettyError.name
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
};
|
|
660
|
+
const create$1$1 = (message, error) => {
|
|
661
|
+
return {
|
|
662
|
+
jsonrpc: Two,
|
|
663
|
+
id: message.id,
|
|
664
|
+
error
|
|
665
|
+
};
|
|
666
|
+
};
|
|
667
|
+
const getErrorResponse = (message, error, preparePrettyError, logError) => {
|
|
668
|
+
const prettyError = preparePrettyError(error);
|
|
669
|
+
logError(error, prettyError);
|
|
670
|
+
const errorProperty = getErrorProperty(error, prettyError);
|
|
671
|
+
return create$1$1(message, errorProperty);
|
|
672
|
+
};
|
|
673
|
+
const create$5 = (message, result) => {
|
|
674
|
+
return {
|
|
675
|
+
jsonrpc: Two,
|
|
676
|
+
id: message.id,
|
|
677
|
+
result: result ?? null
|
|
678
|
+
};
|
|
679
|
+
};
|
|
680
|
+
const getSuccessResponse = (message, result) => {
|
|
681
|
+
const resultProperty = result ?? null;
|
|
682
|
+
return create$5(message, resultProperty);
|
|
683
|
+
};
|
|
684
|
+
const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
|
|
685
|
+
try {
|
|
686
|
+
const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
|
|
687
|
+
return getSuccessResponse(message, result);
|
|
688
|
+
} catch (error) {
|
|
689
|
+
return getErrorResponse(message, error, preparePrettyError, logError);
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
const defaultPreparePrettyError = error => {
|
|
693
|
+
return error;
|
|
694
|
+
};
|
|
695
|
+
const defaultLogError = () => {
|
|
696
|
+
// ignore
|
|
697
|
+
};
|
|
698
|
+
const defaultRequiresSocket = () => {
|
|
699
|
+
return false;
|
|
700
|
+
};
|
|
701
|
+
const defaultResolve = resolve;
|
|
702
|
+
|
|
703
|
+
// TODO maybe remove this in v6 or v7, only accept options object to simplify the code
|
|
704
|
+
const normalizeParams = args => {
|
|
705
|
+
if (args.length === 1) {
|
|
706
|
+
const options = args[0];
|
|
707
|
+
return {
|
|
708
|
+
ipc: options.ipc,
|
|
709
|
+
message: options.message,
|
|
710
|
+
execute: options.execute,
|
|
711
|
+
resolve: options.resolve || defaultResolve,
|
|
712
|
+
preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
|
|
713
|
+
logError: options.logError || defaultLogError,
|
|
714
|
+
requiresSocket: options.requiresSocket || defaultRequiresSocket
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
return {
|
|
718
|
+
ipc: args[0],
|
|
719
|
+
message: args[1],
|
|
720
|
+
execute: args[2],
|
|
721
|
+
resolve: args[3],
|
|
722
|
+
preparePrettyError: args[4],
|
|
723
|
+
logError: args[5],
|
|
724
|
+
requiresSocket: args[6]
|
|
725
|
+
};
|
|
726
|
+
};
|
|
727
|
+
const handleJsonRpcMessage = async (...args) => {
|
|
728
|
+
const options = normalizeParams(args);
|
|
729
|
+
const {
|
|
730
|
+
message,
|
|
731
|
+
ipc,
|
|
732
|
+
execute,
|
|
733
|
+
resolve,
|
|
734
|
+
preparePrettyError,
|
|
735
|
+
logError,
|
|
736
|
+
requiresSocket
|
|
737
|
+
} = options;
|
|
738
|
+
if ('id' in message) {
|
|
739
|
+
if ('method' in message) {
|
|
740
|
+
const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
|
|
741
|
+
try {
|
|
742
|
+
ipc.send(response);
|
|
743
|
+
} catch (error) {
|
|
744
|
+
const errorResponse = getErrorResponse(message, error, preparePrettyError, logError);
|
|
745
|
+
ipc.send(errorResponse);
|
|
746
|
+
}
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
resolve(message.id, message);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if ('method' in message) {
|
|
753
|
+
await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
throw new JsonRpcError('unexpected message');
|
|
757
|
+
};
|
|
758
|
+
const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
|
|
759
|
+
const {
|
|
760
|
+
message,
|
|
761
|
+
promise
|
|
762
|
+
} = create$2(method, params);
|
|
763
|
+
if (useSendAndTransfer && ipc.sendAndTransfer) {
|
|
764
|
+
ipc.sendAndTransfer(message);
|
|
765
|
+
} else {
|
|
766
|
+
ipc.send(message);
|
|
767
|
+
}
|
|
768
|
+
const responseMessage = await promise;
|
|
769
|
+
return unwrapJsonRpcResult(responseMessage);
|
|
770
|
+
};
|
|
771
|
+
const send = (transport, method, ...params) => {
|
|
772
|
+
const message = create$4(method, params);
|
|
773
|
+
transport.send(message);
|
|
774
|
+
};
|
|
775
|
+
const invoke$1 = (ipc, method, ...params) => {
|
|
776
|
+
return invokeHelper(ipc, method, params, false);
|
|
777
|
+
};
|
|
778
|
+
const invokeAndTransfer = (ipc, method, ...params) => {
|
|
779
|
+
return invokeHelper(ipc, method, params, true);
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
const commands = Object.create(null);
|
|
783
|
+
const register = commandMap => {
|
|
784
|
+
Object.assign(commands, commandMap);
|
|
785
|
+
};
|
|
786
|
+
const getCommand = key => {
|
|
787
|
+
return commands[key];
|
|
788
|
+
};
|
|
789
|
+
const execute = (command, ...args) => {
|
|
790
|
+
const fn = getCommand(command);
|
|
791
|
+
if (!fn) {
|
|
792
|
+
throw new Error(`command not found ${command}`);
|
|
793
|
+
}
|
|
794
|
+
return fn(...args);
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
const createRpc = ipc => {
|
|
798
|
+
const rpc = {
|
|
799
|
+
// @ts-ignore
|
|
800
|
+
ipc,
|
|
801
|
+
/**
|
|
802
|
+
* @deprecated
|
|
803
|
+
*/
|
|
804
|
+
send(method, ...params) {
|
|
805
|
+
send(ipc, method, ...params);
|
|
806
|
+
},
|
|
807
|
+
invoke(method, ...params) {
|
|
808
|
+
return invoke$1(ipc, method, ...params);
|
|
809
|
+
},
|
|
810
|
+
invokeAndTransfer(method, ...params) {
|
|
811
|
+
return invokeAndTransfer(ipc, method, ...params);
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
return rpc;
|
|
815
|
+
};
|
|
816
|
+
const requiresSocket = () => {
|
|
817
|
+
return false;
|
|
818
|
+
};
|
|
819
|
+
const preparePrettyError = error => {
|
|
820
|
+
return error;
|
|
821
|
+
};
|
|
822
|
+
const logError = () => {
|
|
823
|
+
// handled by renderer worker
|
|
824
|
+
};
|
|
825
|
+
const handleMessage = event => {
|
|
826
|
+
const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
|
|
827
|
+
const actualExecute = event?.target?.execute || execute;
|
|
828
|
+
return handleJsonRpcMessage(event.target, event.data, actualExecute, resolve, preparePrettyError, logError, actualRequiresSocket);
|
|
829
|
+
};
|
|
830
|
+
const handleIpc = ipc => {
|
|
831
|
+
if ('addEventListener' in ipc) {
|
|
832
|
+
ipc.addEventListener('message', handleMessage);
|
|
833
|
+
} else if ('on' in ipc) {
|
|
834
|
+
// deprecated
|
|
835
|
+
ipc.on('message', handleMessage);
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
const listen$1 = async (module, options) => {
|
|
839
|
+
const rawIpc = await module.listen(options);
|
|
840
|
+
if (module.signal) {
|
|
841
|
+
module.signal(rawIpc);
|
|
842
|
+
}
|
|
843
|
+
const ipc = module.wrap(rawIpc);
|
|
844
|
+
return ipc;
|
|
845
|
+
};
|
|
846
|
+
const create$1 = async ({
|
|
847
|
+
commandMap
|
|
848
|
+
}) => {
|
|
849
|
+
// TODO create a commandMap per rpc instance
|
|
850
|
+
register(commandMap);
|
|
851
|
+
const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
|
|
852
|
+
handleIpc(ipc);
|
|
853
|
+
const rpc = createRpc(ipc);
|
|
854
|
+
return rpc;
|
|
855
|
+
};
|
|
856
|
+
const WebWorkerRpcClient = {
|
|
857
|
+
__proto__: null,
|
|
858
|
+
create: create$1
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
const Enter = 3;
|
|
862
|
+
const Escape = 8;
|
|
863
|
+
const Space = 9;
|
|
864
|
+
const End = 255;
|
|
865
|
+
const Home = 12;
|
|
866
|
+
const LeftArrow = 13;
|
|
867
|
+
const UpArrow = 14;
|
|
868
|
+
const RightArrow = 15;
|
|
869
|
+
const DownArrow = 16;
|
|
870
|
+
const Delete = 18;
|
|
871
|
+
const KeyC = 31;
|
|
872
|
+
const KeyV = 50;
|
|
873
|
+
const F2 = 58;
|
|
874
|
+
const Star = 131;
|
|
875
|
+
|
|
876
|
+
const CtrlCmd = 1 << 11 >>> 0;
|
|
877
|
+
const Alt = 1 << 9 >>> 0;
|
|
878
|
+
|
|
879
|
+
const FocusExplorer = 13;
|
|
880
|
+
const FocusExplorerEditBox = 14;
|
|
881
|
+
const FocusTitleBarMenuBar = 26;
|
|
882
|
+
|
|
883
|
+
const getKeyBindings = () => {
|
|
884
|
+
return [{
|
|
885
|
+
key: RightArrow,
|
|
886
|
+
command: 'Explorer.handleArrowRight',
|
|
887
|
+
when: FocusExplorer
|
|
888
|
+
}, {
|
|
889
|
+
key: LeftArrow,
|
|
890
|
+
command: 'Explorer.handleArrowLeft',
|
|
891
|
+
when: FocusExplorer
|
|
892
|
+
}, {
|
|
893
|
+
key: Home,
|
|
894
|
+
command: 'Explorer.focusFirst',
|
|
895
|
+
when: FocusExplorer
|
|
896
|
+
}, {
|
|
897
|
+
key: End,
|
|
898
|
+
command: 'Explorer.focusLast',
|
|
899
|
+
when: FocusExplorer
|
|
900
|
+
}, {
|
|
901
|
+
key: UpArrow,
|
|
902
|
+
command: 'Explorer.focusPrevious',
|
|
903
|
+
when: FocusExplorer
|
|
904
|
+
}, {
|
|
905
|
+
key: DownArrow,
|
|
906
|
+
command: 'Explorer.focusNext',
|
|
907
|
+
when: FocusExplorer
|
|
908
|
+
}, {
|
|
909
|
+
key: CtrlCmd | Star,
|
|
910
|
+
command: 'Explorer.expandAll',
|
|
911
|
+
when: FocusExplorer
|
|
912
|
+
}, {
|
|
913
|
+
key: Alt | RightArrow,
|
|
914
|
+
command: 'Explorer.expandRecursively',
|
|
915
|
+
when: FocusExplorer
|
|
916
|
+
}, {
|
|
917
|
+
key: CtrlCmd | LeftArrow,
|
|
918
|
+
command: 'Explorer.collapseAll',
|
|
919
|
+
when: FocusExplorer
|
|
920
|
+
}, {
|
|
921
|
+
key: CtrlCmd | KeyV,
|
|
922
|
+
command: 'Explorer.handlePaste',
|
|
923
|
+
when: FocusExplorer
|
|
924
|
+
}, {
|
|
925
|
+
key: CtrlCmd | KeyC,
|
|
926
|
+
command: 'Explorer.handleCopy',
|
|
927
|
+
when: FocusExplorer
|
|
928
|
+
}, {
|
|
929
|
+
key: F2,
|
|
930
|
+
command: 'Explorer.rename',
|
|
931
|
+
when: FocusExplorer
|
|
932
|
+
}, {
|
|
933
|
+
key: Escape,
|
|
934
|
+
command: 'Explorer.cancelEdit',
|
|
935
|
+
when: FocusExplorerEditBox
|
|
936
|
+
}, {
|
|
937
|
+
key: Enter,
|
|
938
|
+
command: 'Explorer.acceptEdit',
|
|
939
|
+
when: FocusExplorerEditBox
|
|
940
|
+
}, {
|
|
941
|
+
key: Delete,
|
|
942
|
+
command: 'Explorer.removeDirent',
|
|
943
|
+
when: FocusExplorer
|
|
944
|
+
}, {
|
|
945
|
+
key: Escape,
|
|
946
|
+
command: 'Explorer.focusNone',
|
|
947
|
+
when: FocusExplorer
|
|
948
|
+
}, {
|
|
949
|
+
key: Space,
|
|
950
|
+
command: 'Explorer.handleClickCurrentButKeepFocus',
|
|
951
|
+
when: FocusExplorer
|
|
952
|
+
}, {
|
|
953
|
+
key: Enter,
|
|
954
|
+
command: 'Explorer.handleClickCurrent',
|
|
955
|
+
when: FocusExplorer
|
|
956
|
+
}];
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
const MenuBar = 'menubar';
|
|
960
|
+
const MenuItem = 'menuitem';
|
|
961
|
+
|
|
962
|
+
const HandleClick = 'handleClick';
|
|
963
|
+
const HandleFocusIn = 'handleFocusIn';
|
|
964
|
+
const HandleFocusOut = 'handleFocusOut';
|
|
965
|
+
const HandlePointerOut = 'handlePointerOut';
|
|
966
|
+
const HandlePointerOver = 'handlePointerOver';
|
|
967
|
+
|
|
968
|
+
const TitleBarEntryActive = 'TitleBarEntryActive';
|
|
969
|
+
const TitleBarTopLevelEntry = 'TitleBarTopLevelEntry';
|
|
970
|
+
const TitleBarTopLevelEntryLabel = 'TitleBarTopLevelEntryLabel';
|
|
971
|
+
|
|
972
|
+
const Div = 4;
|
|
973
|
+
const Text = 12;
|
|
974
|
+
|
|
975
|
+
const text = data => {
|
|
976
|
+
return {
|
|
977
|
+
type: Text,
|
|
978
|
+
text: data,
|
|
979
|
+
childCount: 0
|
|
980
|
+
};
|
|
981
|
+
};
|
|
982
|
+
|
|
983
|
+
const getItemVirtualDom = item => {
|
|
984
|
+
// @ts-ignore
|
|
985
|
+
const {
|
|
986
|
+
keyboardShortCut,
|
|
987
|
+
label,
|
|
988
|
+
isOpen,
|
|
989
|
+
isFocused
|
|
990
|
+
} = item;
|
|
991
|
+
const dom = [];
|
|
992
|
+
dom.push({
|
|
993
|
+
type: Div,
|
|
994
|
+
className: TitleBarTopLevelEntry,
|
|
995
|
+
ariaHasPopup: true,
|
|
996
|
+
ariaExpanded: isOpen,
|
|
997
|
+
role: MenuItem,
|
|
998
|
+
childCount: 1,
|
|
999
|
+
ariaKeyShortcuts: keyboardShortCut
|
|
1000
|
+
});
|
|
1001
|
+
if (isOpen) {
|
|
1002
|
+
// @ts-ignore
|
|
1003
|
+
dom[0].ariaOwns = 'Menu-0';
|
|
1004
|
+
}
|
|
1005
|
+
if (isFocused) {
|
|
1006
|
+
dom[0].className += ' ' + TitleBarEntryActive;
|
|
1007
|
+
// @ts-ignore
|
|
1008
|
+
dom[0].id = 'TitleBarEntryActive';
|
|
1009
|
+
dom.push({
|
|
1010
|
+
type: Div,
|
|
1011
|
+
className: TitleBarTopLevelEntryLabel,
|
|
1012
|
+
childCount: 1
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
dom.push(text(label));
|
|
1016
|
+
return dom;
|
|
1017
|
+
};
|
|
1018
|
+
const getTitleBarMenuBarItemsVirtualDom = visibleItems => {
|
|
1019
|
+
const dom = visibleItems.flatMap(getItemVirtualDom);
|
|
1020
|
+
return dom;
|
|
1021
|
+
};
|
|
1022
|
+
|
|
1023
|
+
const getTitleBarMenuBarVirtualDom = visibleItems => {
|
|
1024
|
+
return [{
|
|
1025
|
+
type: Div,
|
|
1026
|
+
className: 'Viewlet TitleBarMenuBar',
|
|
1027
|
+
role: MenuBar,
|
|
1028
|
+
tabIndex: 0,
|
|
1029
|
+
childCount: visibleItems.length,
|
|
1030
|
+
onMouseDown: HandleClick,
|
|
1031
|
+
onFocusOut: HandleFocusOut,
|
|
1032
|
+
onFocusIn: HandleFocusIn,
|
|
1033
|
+
onPointerOver: HandlePointerOver,
|
|
1034
|
+
onPointerOut: HandlePointerOut
|
|
1035
|
+
}, ...getTitleBarMenuBarItemsVirtualDom(visibleItems)];
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
const emptyObject = {};
|
|
1039
|
+
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
|
|
1040
|
+
const i18nString = (key, placeholders = emptyObject) => {
|
|
1041
|
+
if (placeholders === emptyObject) {
|
|
1042
|
+
return key;
|
|
1043
|
+
}
|
|
1044
|
+
const replacer = (match, rest) => {
|
|
1045
|
+
return placeholders[rest];
|
|
1046
|
+
};
|
|
1047
|
+
return key.replaceAll(RE_PLACEHOLDER, replacer);
|
|
1048
|
+
};
|
|
1049
|
+
|
|
1050
|
+
/**
|
|
1051
|
+
* @enum {string}
|
|
1052
|
+
*/
|
|
1053
|
+
const UiStrings$5 = {
|
|
1054
|
+
Copy: 'Copy',
|
|
1055
|
+
CopyLineDown: 'Copy Line Down',
|
|
1056
|
+
CopyLineUp: 'Copy Line Up',
|
|
1057
|
+
Cut: 'Cut',
|
|
1058
|
+
MoveLineDown: 'Move Line Down',
|
|
1059
|
+
MoveLineUp: 'Move Line Up',
|
|
1060
|
+
Paste: 'Paste',
|
|
1061
|
+
Redo: 'Redo',
|
|
1062
|
+
SelectAll: 'Select All',
|
|
1063
|
+
ToggleBlockComment: 'Toggle Block Comment',
|
|
1064
|
+
ToggleLineComment: 'Toggle Line Comment',
|
|
1065
|
+
Undo: 'Undo'};
|
|
1066
|
+
const cut = () => {
|
|
1067
|
+
return i18nString(UiStrings$5.Cut);
|
|
1068
|
+
};
|
|
1069
|
+
const copy = () => {
|
|
1070
|
+
return i18nString(UiStrings$5.Copy);
|
|
1071
|
+
};
|
|
1072
|
+
const paste = () => {
|
|
1073
|
+
return i18nString(UiStrings$5.Paste);
|
|
1074
|
+
};
|
|
1075
|
+
const undo = () => {
|
|
1076
|
+
return i18nString(UiStrings$5.Undo);
|
|
1077
|
+
};
|
|
1078
|
+
const redo = () => {
|
|
1079
|
+
return i18nString(UiStrings$5.Redo);
|
|
1080
|
+
};
|
|
1081
|
+
const toggleLineComment = () => {
|
|
1082
|
+
return i18nString(UiStrings$5.ToggleLineComment);
|
|
1083
|
+
};
|
|
1084
|
+
const toggleBlockComment = () => {
|
|
1085
|
+
return i18nString(UiStrings$5.ToggleBlockComment);
|
|
1086
|
+
};
|
|
1087
|
+
const selectAll = () => {
|
|
1088
|
+
return i18nString(UiStrings$5.SelectAll);
|
|
1089
|
+
};
|
|
1090
|
+
const copyLineUp = () => {
|
|
1091
|
+
return i18nString(UiStrings$5.CopyLineUp);
|
|
1092
|
+
};
|
|
1093
|
+
const copyLineDown = () => {
|
|
1094
|
+
return i18nString(UiStrings$5.CopyLineDown);
|
|
1095
|
+
};
|
|
1096
|
+
const moveLineUp = () => {
|
|
1097
|
+
return i18nString(UiStrings$5.MoveLineUp);
|
|
1098
|
+
};
|
|
1099
|
+
const moveLineDown = () => {
|
|
1100
|
+
return i18nString(UiStrings$5.MoveLineDown);
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
const Separator = 1;
|
|
1104
|
+
const None = 0;
|
|
1105
|
+
const SubMenu = 4;
|
|
1106
|
+
const Disabled = 5;
|
|
1107
|
+
const RestoreFocus = 6;
|
|
1108
|
+
const Ignore = 7;
|
|
1109
|
+
|
|
1110
|
+
const menuEntrySeparator = {
|
|
1111
|
+
id: 'separator',
|
|
1112
|
+
label: '',
|
|
1113
|
+
flags: Separator,
|
|
1114
|
+
command: ''
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
const Edit = 2;
|
|
1118
|
+
const File = 5;
|
|
1119
|
+
const Go = 6;
|
|
1120
|
+
const Help = 7;
|
|
1121
|
+
const OpenRecent = 9;
|
|
1122
|
+
const Run = 10;
|
|
1123
|
+
const Selection = 11;
|
|
1124
|
+
const Terminal = 14;
|
|
1125
|
+
const TitleBar = 15;
|
|
1126
|
+
const View = 16;
|
|
1127
|
+
|
|
1128
|
+
const id$9 = Edit;
|
|
1129
|
+
const getMenuEntries$c = () => {
|
|
1130
|
+
return [{
|
|
1131
|
+
id: 'undo',
|
|
1132
|
+
label: undo(),
|
|
1133
|
+
flags: Disabled,
|
|
1134
|
+
command: /* TODO */-1
|
|
1135
|
+
}, {
|
|
1136
|
+
id: 'redo',
|
|
1137
|
+
label: redo(),
|
|
1138
|
+
flags: Disabled,
|
|
1139
|
+
command: /* TODO */-1
|
|
1140
|
+
}, menuEntrySeparator, {
|
|
1141
|
+
id: 'cut',
|
|
1142
|
+
label: cut(),
|
|
1143
|
+
flags: None,
|
|
1144
|
+
command: /* Editor.cut */'Editor.cut'
|
|
1145
|
+
}, {
|
|
1146
|
+
id: 'copy',
|
|
1147
|
+
label: copy(),
|
|
1148
|
+
flags: None,
|
|
1149
|
+
command: /* Editor.copy */'Editor.copy'
|
|
1150
|
+
}, {
|
|
1151
|
+
id: 'paste',
|
|
1152
|
+
label: paste(),
|
|
1153
|
+
flags: None,
|
|
1154
|
+
command: /* Editor.paste */'Editor.paste'
|
|
1155
|
+
}, menuEntrySeparator, {
|
|
1156
|
+
id: 'toggle-line-comment',
|
|
1157
|
+
label: toggleLineComment(),
|
|
1158
|
+
flags: None,
|
|
1159
|
+
command: /* Editor.toggleLineComment */'Editor.toggleLineComment'
|
|
1160
|
+
}, {
|
|
1161
|
+
id: 'toggle-block-comment',
|
|
1162
|
+
label: toggleBlockComment(),
|
|
1163
|
+
flags: None,
|
|
1164
|
+
command: /* Editor.toggleBlockComment */'Editor.toggleBlockComment'
|
|
1165
|
+
}];
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
const MenuEntriesEdit = {
|
|
1169
|
+
__proto__: null,
|
|
1170
|
+
getMenuEntries: getMenuEntries$c,
|
|
1171
|
+
id: id$9
|
|
1172
|
+
};
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* @enum {string}
|
|
1176
|
+
*/
|
|
1177
|
+
const UiStrings$4 = {
|
|
1178
|
+
NewFile: 'New File',
|
|
1179
|
+
NewWindow: 'New Window',
|
|
1180
|
+
OpenFile: 'Open File',
|
|
1181
|
+
OpenFolder: 'Open Folder',
|
|
1182
|
+
OpenRecent: 'Open Recent',
|
|
1183
|
+
Save: 'Save',
|
|
1184
|
+
SaveAll: 'Save All'
|
|
1185
|
+
};
|
|
1186
|
+
const newFile = () => {
|
|
1187
|
+
return i18nString(UiStrings$4.NewFile);
|
|
1188
|
+
};
|
|
1189
|
+
const newWindow = () => {
|
|
1190
|
+
return i18nString(UiStrings$4.NewWindow);
|
|
1191
|
+
};
|
|
1192
|
+
const openFile = () => {
|
|
1193
|
+
return i18nString(UiStrings$4.OpenFile);
|
|
1194
|
+
};
|
|
1195
|
+
const openFolder = () => {
|
|
1196
|
+
return i18nString(UiStrings$4.OpenFolder);
|
|
1197
|
+
};
|
|
1198
|
+
const openRecent = () => {
|
|
1199
|
+
return i18nString(UiStrings$4.OpenRecent);
|
|
1200
|
+
};
|
|
1201
|
+
const save = () => {
|
|
1202
|
+
return i18nString(UiStrings$4.Save);
|
|
1203
|
+
};
|
|
1204
|
+
const saveAll = () => {
|
|
1205
|
+
return i18nString(UiStrings$4.SaveAll);
|
|
1206
|
+
};
|
|
1207
|
+
|
|
1208
|
+
const platform = 1;
|
|
1209
|
+
|
|
1210
|
+
const Web = 1;
|
|
1211
|
+
|
|
1212
|
+
const id$8 = File;
|
|
1213
|
+
const getMenuEntries$b = () => {
|
|
1214
|
+
const entries = [{
|
|
1215
|
+
id: 'newFile',
|
|
1216
|
+
label: newFile(),
|
|
1217
|
+
flags: None,
|
|
1218
|
+
command: -1
|
|
1219
|
+
}, {
|
|
1220
|
+
id: 'newWindow',
|
|
1221
|
+
label: newWindow(),
|
|
1222
|
+
flags: None,
|
|
1223
|
+
command: /* Window.openNew */'Window.openNew'
|
|
1224
|
+
}, menuEntrySeparator, {
|
|
1225
|
+
id: 'openFile',
|
|
1226
|
+
label: openFile(),
|
|
1227
|
+
flags: None,
|
|
1228
|
+
command: 'Dialog.openFile'
|
|
1229
|
+
}, {
|
|
1230
|
+
id: 'openFolder',
|
|
1231
|
+
label: openFolder(),
|
|
1232
|
+
flags: RestoreFocus,
|
|
1233
|
+
command: 'Dialog.openFolder'
|
|
1234
|
+
}, {
|
|
1235
|
+
id: OpenRecent,
|
|
1236
|
+
label: openRecent(),
|
|
1237
|
+
flags: SubMenu,
|
|
1238
|
+
command: ''
|
|
1239
|
+
}, menuEntrySeparator, {
|
|
1240
|
+
id: 'save',
|
|
1241
|
+
label: save(),
|
|
1242
|
+
flags: None,
|
|
1243
|
+
command: 'Main.save'
|
|
1244
|
+
}, {
|
|
1245
|
+
id: 'saveAll',
|
|
1246
|
+
label: saveAll(),
|
|
1247
|
+
flags: None,
|
|
1248
|
+
command: 'Main.saveAll'
|
|
1249
|
+
}];
|
|
1250
|
+
return entries;
|
|
1251
|
+
};
|
|
1252
|
+
|
|
1253
|
+
const MenuEntriesFile = {
|
|
1254
|
+
__proto__: null,
|
|
1255
|
+
getMenuEntries: getMenuEntries$b,
|
|
1256
|
+
id: id$8
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
const id$7 = Go;
|
|
1260
|
+
const getMenuEntries$a = () => {
|
|
1261
|
+
return [];
|
|
1262
|
+
};
|
|
1263
|
+
|
|
1264
|
+
const MenuEntriesGo = {
|
|
1265
|
+
__proto__: null,
|
|
1266
|
+
getMenuEntries: getMenuEntries$a,
|
|
1267
|
+
id: id$7
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* @enum {string}
|
|
1272
|
+
*/
|
|
1273
|
+
const UiStrings$3 = {
|
|
1274
|
+
About: 'About',
|
|
1275
|
+
CheckForUpdates: 'Check For Updates'};
|
|
1276
|
+
const checkForUpdates = () => {
|
|
1277
|
+
return i18nString(UiStrings$3.CheckForUpdates);
|
|
1278
|
+
};
|
|
1279
|
+
const about = () => {
|
|
1280
|
+
return i18nString(UiStrings$3.About);
|
|
1281
|
+
};
|
|
1282
|
+
|
|
1283
|
+
const isAutoUpdateSupported = () => {
|
|
1284
|
+
{
|
|
1285
|
+
return false;
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
|
|
1289
|
+
const id$6 = Help;
|
|
1290
|
+
const getMenuEntries$9 = async () => {
|
|
1291
|
+
const autoUpdateSupported = isAutoUpdateSupported();
|
|
1292
|
+
const entries = [];
|
|
1293
|
+
if (autoUpdateSupported) {
|
|
1294
|
+
entries.push(menuEntrySeparator, {
|
|
1295
|
+
id: 'checkForUpdates',
|
|
1296
|
+
label: checkForUpdates(),
|
|
1297
|
+
flags: RestoreFocus,
|
|
1298
|
+
command: 'AutoUpdater.checkForUpdates'
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
if (entries.length > 0) {
|
|
1302
|
+
entries.push(menuEntrySeparator);
|
|
1303
|
+
}
|
|
1304
|
+
entries.push({
|
|
1305
|
+
id: 'about',
|
|
1306
|
+
label: about(),
|
|
1307
|
+
flags: RestoreFocus,
|
|
1308
|
+
command: 'About.showAbout'
|
|
1309
|
+
});
|
|
1310
|
+
return entries;
|
|
1311
|
+
};
|
|
1312
|
+
|
|
1313
|
+
const MenuEntriesHelp = {
|
|
1314
|
+
__proto__: null,
|
|
1315
|
+
getMenuEntries: getMenuEntries$9,
|
|
1316
|
+
id: id$6
|
|
1317
|
+
};
|
|
1318
|
+
|
|
1319
|
+
const state$1 = {
|
|
1320
|
+
rpc: undefined
|
|
1321
|
+
};
|
|
1322
|
+
const invoke = (method, ...params) => {
|
|
1323
|
+
const rpc = state$1.rpc;
|
|
1324
|
+
// @ts-ignore
|
|
1325
|
+
return rpc.invoke(method, ...params);
|
|
1326
|
+
};
|
|
1327
|
+
const setRpc = rpc => {
|
|
1328
|
+
state$1.rpc = rpc;
|
|
1329
|
+
};
|
|
1330
|
+
|
|
1331
|
+
const getTitle = uri => {
|
|
1332
|
+
if (!uri) {
|
|
1333
|
+
return '';
|
|
1334
|
+
}
|
|
1335
|
+
return uri;
|
|
1336
|
+
};
|
|
1337
|
+
|
|
1338
|
+
/**
|
|
1339
|
+
* @enum {string}
|
|
1340
|
+
*/
|
|
1341
|
+
const UiStrings$2 = {
|
|
1342
|
+
MoreDot: 'More ...',
|
|
1343
|
+
ClearRecentlyOpened: 'Clear Recently Opened'
|
|
1344
|
+
};
|
|
1345
|
+
const moreDot = () => {
|
|
1346
|
+
return i18nString(UiStrings$2.MoreDot);
|
|
1347
|
+
};
|
|
1348
|
+
const clearRecentlyOpened = () => {
|
|
1349
|
+
return i18nString(UiStrings$2.ClearRecentlyOpened);
|
|
1350
|
+
};
|
|
1351
|
+
|
|
1352
|
+
const MAX_MENU_RECENT_ENTRIES = 10;
|
|
1353
|
+
const toMenuItem = folder => {
|
|
1354
|
+
const label = getTitle(folder);
|
|
1355
|
+
return {
|
|
1356
|
+
label,
|
|
1357
|
+
flags: None,
|
|
1358
|
+
command: 'Workspace.setPath',
|
|
1359
|
+
args: [folder]
|
|
1360
|
+
};
|
|
1361
|
+
};
|
|
1362
|
+
const getRecentlyOpened = () => {
|
|
1363
|
+
return invoke(/* RecentlyOpened.getRecentlyOpened */'RecentlyOpened.getRecentlyOpened');
|
|
1364
|
+
};
|
|
1365
|
+
const id$5 = OpenRecent;
|
|
1366
|
+
const getMenuEntries$8 = async () => {
|
|
1367
|
+
const allItems = await getRecentlyOpened();
|
|
1368
|
+
const itemsToShow = allItems.slice(0, MAX_MENU_RECENT_ENTRIES);
|
|
1369
|
+
const items = [];
|
|
1370
|
+
if (itemsToShow.length > 0) {
|
|
1371
|
+
items.push(...itemsToShow.map(toMenuItem), menuEntrySeparator);
|
|
1372
|
+
}
|
|
1373
|
+
items.push({
|
|
1374
|
+
id: 'more',
|
|
1375
|
+
label: moreDot(),
|
|
1376
|
+
flags: None,
|
|
1377
|
+
command: 'QuickPick.showRecent'
|
|
1378
|
+
}, menuEntrySeparator, {
|
|
1379
|
+
id: 'clearRecentlyOpened',
|
|
1380
|
+
label: clearRecentlyOpened(),
|
|
1381
|
+
flags: None,
|
|
1382
|
+
command: 'RecentlyOpened.clearRecentlyOpened'
|
|
1383
|
+
});
|
|
1384
|
+
return items;
|
|
1385
|
+
};
|
|
1386
|
+
|
|
1387
|
+
const MenuEntriesOpenRecent = {
|
|
1388
|
+
__proto__: null,
|
|
1389
|
+
getMenuEntries: getMenuEntries$8,
|
|
1390
|
+
id: id$5
|
|
1391
|
+
};
|
|
1392
|
+
|
|
1393
|
+
const id$4 = Run;
|
|
1394
|
+
const getMenuEntries$7 = () => {
|
|
1395
|
+
return [];
|
|
1396
|
+
};
|
|
1397
|
+
|
|
1398
|
+
const MenuEntriesRun = {
|
|
1399
|
+
__proto__: null,
|
|
1400
|
+
getMenuEntries: getMenuEntries$7,
|
|
1401
|
+
id: id$4
|
|
1402
|
+
};
|
|
1403
|
+
|
|
1404
|
+
const id$3 = Selection;
|
|
1405
|
+
const getMenuEntries$6 = () => {
|
|
1406
|
+
return [{
|
|
1407
|
+
id: 'selectAll',
|
|
1408
|
+
label: selectAll(),
|
|
1409
|
+
flags: None,
|
|
1410
|
+
command: 'Editor.selectAll'
|
|
1411
|
+
}, {
|
|
1412
|
+
id: 'copyLineUp',
|
|
1413
|
+
label: copyLineUp(),
|
|
1414
|
+
flags: None,
|
|
1415
|
+
command: 'Editor.copyLineUp'
|
|
1416
|
+
}, {
|
|
1417
|
+
id: 'copyLineDown',
|
|
1418
|
+
label: copyLineDown(),
|
|
1419
|
+
flags: None,
|
|
1420
|
+
command: 'Editor.copyLineDown'
|
|
1421
|
+
}, {
|
|
1422
|
+
id: 'moveLineUp',
|
|
1423
|
+
label: moveLineUp(),
|
|
1424
|
+
flags: Disabled,
|
|
1425
|
+
command: 'Editor.moveLineUp'
|
|
1426
|
+
}, {
|
|
1427
|
+
id: 'moveLineDown',
|
|
1428
|
+
label: moveLineDown(),
|
|
1429
|
+
flags: Disabled,
|
|
1430
|
+
command: 'Editor.moveLineDown'
|
|
1431
|
+
}];
|
|
1432
|
+
};
|
|
1433
|
+
|
|
1434
|
+
const MenuEntriesSelection = {
|
|
1435
|
+
__proto__: null,
|
|
1436
|
+
getMenuEntries: getMenuEntries$6,
|
|
1437
|
+
id: id$3
|
|
1438
|
+
};
|
|
1439
|
+
|
|
1440
|
+
/**
|
|
1441
|
+
* @enum {string}
|
|
1442
|
+
*/
|
|
1443
|
+
const UiStrings$1 = {
|
|
1444
|
+
NewTerminal: 'New Terminal'
|
|
1445
|
+
};
|
|
1446
|
+
const newTerminal = () => {
|
|
1447
|
+
return i18nString(UiStrings$1.NewTerminal);
|
|
1448
|
+
};
|
|
1449
|
+
|
|
1450
|
+
const id$2 = Terminal;
|
|
1451
|
+
const getMenuEntries$5 = () => {
|
|
1452
|
+
return [{
|
|
1453
|
+
id: 'newTerminal',
|
|
1454
|
+
label: newTerminal(),
|
|
1455
|
+
flags: None,
|
|
1456
|
+
command: 'Layout.togglePanel',
|
|
1457
|
+
args: ['Terminal']
|
|
1458
|
+
}];
|
|
1459
|
+
};
|
|
1460
|
+
|
|
1461
|
+
const MenuEntriesTerminal = {
|
|
1462
|
+
__proto__: null,
|
|
1463
|
+
getMenuEntries: getMenuEntries$5,
|
|
1464
|
+
id: id$2
|
|
1465
|
+
};
|
|
1466
|
+
|
|
1467
|
+
/**
|
|
1468
|
+
* @enum {string}
|
|
1469
|
+
*/
|
|
1470
|
+
const UiStrings = {
|
|
1471
|
+
File: 'File',
|
|
1472
|
+
Edit: 'Edit',
|
|
1473
|
+
Selection: 'Selection',
|
|
1474
|
+
View: 'View',
|
|
1475
|
+
Go: 'Go',
|
|
1476
|
+
Run: 'Run',
|
|
1477
|
+
Terminal: 'Terminal',
|
|
1478
|
+
Help: 'Help'
|
|
1479
|
+
};
|
|
1480
|
+
const file = () => {
|
|
1481
|
+
return i18nString(UiStrings.File);
|
|
1482
|
+
};
|
|
1483
|
+
const edit = () => {
|
|
1484
|
+
return i18nString(UiStrings.Edit);
|
|
1485
|
+
};
|
|
1486
|
+
const selection = () => {
|
|
1487
|
+
return i18nString(UiStrings.Selection);
|
|
1488
|
+
};
|
|
1489
|
+
const view = () => {
|
|
1490
|
+
return i18nString(UiStrings.View);
|
|
1491
|
+
};
|
|
1492
|
+
const go = () => {
|
|
1493
|
+
return i18nString(UiStrings.Go);
|
|
1494
|
+
};
|
|
1495
|
+
const run = () => {
|
|
1496
|
+
return i18nString(UiStrings.Run);
|
|
1497
|
+
};
|
|
1498
|
+
const terminal = () => {
|
|
1499
|
+
return i18nString(UiStrings.Terminal);
|
|
1500
|
+
};
|
|
1501
|
+
const help = () => {
|
|
1502
|
+
return i18nString(UiStrings.Help);
|
|
1503
|
+
};
|
|
1504
|
+
|
|
1505
|
+
const getMenuEntries$4 = () => {
|
|
1506
|
+
return [{
|
|
1507
|
+
id: File,
|
|
1508
|
+
label: file(),
|
|
1509
|
+
flags: SubMenu
|
|
1510
|
+
}, {
|
|
1511
|
+
id: Edit,
|
|
1512
|
+
label: edit(),
|
|
1513
|
+
flags: SubMenu
|
|
1514
|
+
}, {
|
|
1515
|
+
id: Selection,
|
|
1516
|
+
label: selection(),
|
|
1517
|
+
flags: SubMenu
|
|
1518
|
+
}, {
|
|
1519
|
+
id: View,
|
|
1520
|
+
label: view(),
|
|
1521
|
+
flags: SubMenu
|
|
1522
|
+
}, {
|
|
1523
|
+
id: Go,
|
|
1524
|
+
label: go(),
|
|
1525
|
+
flags: SubMenu
|
|
1526
|
+
}, {
|
|
1527
|
+
id: Run,
|
|
1528
|
+
label: run(),
|
|
1529
|
+
keyboardShortCut: 'Alt+r',
|
|
1530
|
+
flags: SubMenu
|
|
1531
|
+
}, {
|
|
1532
|
+
id: Terminal,
|
|
1533
|
+
label: terminal(),
|
|
1534
|
+
keyboardShortCut: 'Alt+t',
|
|
1535
|
+
flags: SubMenu
|
|
1536
|
+
}, {
|
|
1537
|
+
id: Help,
|
|
1538
|
+
label: help(),
|
|
1539
|
+
keyboardShortCut: 'Alt+h',
|
|
1540
|
+
flags: SubMenu
|
|
1541
|
+
}];
|
|
1542
|
+
};
|
|
1543
|
+
|
|
1544
|
+
const getMenuEntries$3 = () => {
|
|
1545
|
+
return [{
|
|
1546
|
+
id: File,
|
|
1547
|
+
label: file(),
|
|
1548
|
+
flags: None
|
|
1549
|
+
}, {
|
|
1550
|
+
id: Edit,
|
|
1551
|
+
label: edit(),
|
|
1552
|
+
flags: None
|
|
1553
|
+
}, {
|
|
1554
|
+
id: Selection,
|
|
1555
|
+
label: selection(),
|
|
1556
|
+
flags: None
|
|
1557
|
+
}, {
|
|
1558
|
+
id: View,
|
|
1559
|
+
label: view(),
|
|
1560
|
+
flags: None
|
|
1561
|
+
}, {
|
|
1562
|
+
id: Go,
|
|
1563
|
+
label: go(),
|
|
1564
|
+
flags: None
|
|
1565
|
+
}, {
|
|
1566
|
+
id: Help,
|
|
1567
|
+
label: help(),
|
|
1568
|
+
flags: None
|
|
1569
|
+
}];
|
|
1570
|
+
};
|
|
1571
|
+
|
|
1572
|
+
const getFn = () => {
|
|
1573
|
+
switch (platform) {
|
|
1574
|
+
case Web:
|
|
1575
|
+
return getMenuEntries$3;
|
|
1576
|
+
default:
|
|
1577
|
+
return getMenuEntries$4;
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
const id$1 = TitleBar;
|
|
1581
|
+
const getMenuEntries$2 = async () => {
|
|
1582
|
+
const fn = getFn();
|
|
1583
|
+
return fn();
|
|
1584
|
+
};
|
|
1585
|
+
|
|
1586
|
+
const MenuEntriesTitleBar = {
|
|
1587
|
+
__proto__: null,
|
|
1588
|
+
getMenuEntries: getMenuEntries$2,
|
|
1589
|
+
id: id$1
|
|
1590
|
+
};
|
|
1591
|
+
|
|
1592
|
+
const id = View;
|
|
1593
|
+
const getMenuEntries$1 = () => {
|
|
1594
|
+
return [];
|
|
1595
|
+
};
|
|
1596
|
+
|
|
1597
|
+
const MenuEntriesView = {
|
|
1598
|
+
__proto__: null,
|
|
1599
|
+
getMenuEntries: getMenuEntries$1,
|
|
1600
|
+
id
|
|
1601
|
+
};
|
|
1602
|
+
|
|
1603
|
+
const menus = [MenuEntriesEdit, MenuEntriesFile, MenuEntriesGo, MenuEntriesHelp, MenuEntriesRun, MenuEntriesSelection, MenuEntriesTerminal, MenuEntriesTitleBar, MenuEntriesView, MenuEntriesOpenRecent];
|
|
1604
|
+
const getMenus = () => {
|
|
1605
|
+
return menus;
|
|
1606
|
+
};
|
|
1607
|
+
const getMenuEntries = async (id, ...args) => {
|
|
1608
|
+
try {
|
|
1609
|
+
const module = menus[0];
|
|
1610
|
+
// @ts-ignore
|
|
1611
|
+
const inject = module.inject || [];
|
|
1612
|
+
// @ts-ignore
|
|
1613
|
+
return module.getMenuEntries(...args);
|
|
1614
|
+
} catch (error) {
|
|
1615
|
+
throw new VError(error, `Failed to load menu entries for id ${id}`);
|
|
1616
|
+
}
|
|
1617
|
+
};
|
|
1618
|
+
|
|
1619
|
+
const getFontString = (fontWeight, fontSize, fontFamily) => {
|
|
1620
|
+
return `${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
1621
|
+
};
|
|
1622
|
+
|
|
1623
|
+
const state = {
|
|
1624
|
+
ctx: undefined
|
|
1625
|
+
};
|
|
1626
|
+
const getOrCreate = createCtx => {
|
|
1627
|
+
if (state.ctx) {
|
|
1628
|
+
return state.ctx;
|
|
1629
|
+
}
|
|
1630
|
+
state.ctx = createCtx();
|
|
1631
|
+
return state.ctx;
|
|
1632
|
+
};
|
|
1633
|
+
|
|
1634
|
+
const createCtx = () => {
|
|
1635
|
+
const canvas = new OffscreenCanvas(0, 0);
|
|
1636
|
+
const ctx = /** @type {OffscreenCanvasRenderingContext2D} */canvas.getContext('2d');
|
|
1637
|
+
if (!ctx) {
|
|
1638
|
+
throw new Error('Failed to get canvas context 2d');
|
|
1639
|
+
}
|
|
1640
|
+
return ctx;
|
|
1641
|
+
};
|
|
1642
|
+
const getContext = () => {
|
|
1643
|
+
const ctx = getOrCreate(createCtx);
|
|
1644
|
+
return ctx;
|
|
1645
|
+
};
|
|
1646
|
+
|
|
1647
|
+
const px = value => {
|
|
1648
|
+
return `${value}px`;
|
|
1649
|
+
};
|
|
1650
|
+
|
|
1651
|
+
const getLetterSpacingString = letterSpacing => {
|
|
1652
|
+
return px(letterSpacing);
|
|
1653
|
+
};
|
|
1654
|
+
const measureTextWidth = (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
1655
|
+
string(text);
|
|
1656
|
+
number(fontWeight);
|
|
1657
|
+
number(fontSize);
|
|
1658
|
+
string(fontFamily);
|
|
1659
|
+
boolean(isMonoSpaceFont);
|
|
1660
|
+
number(charWidth);
|
|
1661
|
+
if (typeof letterSpacing !== 'number') {
|
|
1662
|
+
throw new TypeError('letterSpacing must be of type number');
|
|
1663
|
+
}
|
|
1664
|
+
const letterSpacingString = getLetterSpacingString(letterSpacing);
|
|
1665
|
+
const fontString = getFontString(fontWeight, fontSize, fontFamily);
|
|
1666
|
+
const ctx = getContext();
|
|
1667
|
+
// @ts-ignore
|
|
1668
|
+
ctx.letterSpacing = letterSpacingString;
|
|
1669
|
+
ctx.font = fontString;
|
|
1670
|
+
const metrics = ctx.measureText(text);
|
|
1671
|
+
const width = metrics.width;
|
|
1672
|
+
return width;
|
|
1673
|
+
};
|
|
1674
|
+
|
|
1675
|
+
const measureTitleBarEntryWidth = (label, fontWeight, fontSize, fontFamily, letterSpacing) => {
|
|
1676
|
+
const isMonospaceFont = false;
|
|
1677
|
+
const charWidth = 0;
|
|
1678
|
+
return measureTextWidth(label, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
1679
|
+
};
|
|
1680
|
+
|
|
1681
|
+
const create = (id, uri, x, y, width, height) => {
|
|
1682
|
+
return {
|
|
1683
|
+
uid: id,
|
|
1684
|
+
titleBarEntries: [],
|
|
1685
|
+
focusedIndex: -1,
|
|
1686
|
+
isMenuOpen: false,
|
|
1687
|
+
menus: [],
|
|
1688
|
+
labelFontWeight: 400,
|
|
1689
|
+
labelFontSize: 13,
|
|
1690
|
+
labelFontFamily: 'system-ui, Ubuntu, Droid Sans, sans-serif',
|
|
1691
|
+
labelPadding: 8,
|
|
1692
|
+
labelLetterSpacing: 0,
|
|
1693
|
+
titleBarHeight: height,
|
|
1694
|
+
x,
|
|
1695
|
+
y,
|
|
1696
|
+
width,
|
|
1697
|
+
height
|
|
1698
|
+
};
|
|
1699
|
+
};
|
|
1700
|
+
const addWidths = (entries, labelPadding, fontWeight, fontSize, fontFamily, letterSpacing) => {
|
|
1701
|
+
const withWidths = [];
|
|
1702
|
+
for (const entry of entries) {
|
|
1703
|
+
const textWidth = measureTitleBarEntryWidth(entry.label, fontWeight, fontSize, fontFamily, letterSpacing);
|
|
1704
|
+
const width = textWidth + labelPadding * 2;
|
|
1705
|
+
withWidths.push({
|
|
1706
|
+
...entry,
|
|
1707
|
+
width
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
return withWidths;
|
|
1711
|
+
};
|
|
1712
|
+
const loadContent = async state => {
|
|
1713
|
+
const {
|
|
1714
|
+
labelFontFamily,
|
|
1715
|
+
labelFontSize,
|
|
1716
|
+
labelFontWeight,
|
|
1717
|
+
labelLetterSpacing,
|
|
1718
|
+
labelPadding
|
|
1719
|
+
} = state;
|
|
1720
|
+
const titleBarEntries = [];
|
|
1721
|
+
const withWidths = addWidths(titleBarEntries, labelPadding, labelFontWeight, labelFontSize, labelFontFamily, labelLetterSpacing);
|
|
1722
|
+
// const visible = GetVisibleTitleBarEntries.getVisibleTitleBarEntries(withWidths, width)
|
|
1723
|
+
// console.log({ visible })
|
|
1724
|
+
return {
|
|
1725
|
+
...state,
|
|
1726
|
+
titleBarEntries: withWidths
|
|
1727
|
+
};
|
|
745
1728
|
};
|
|
746
1729
|
|
|
747
|
-
const
|
|
748
|
-
const
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
}
|
|
1730
|
+
const closeMenu = (state, keepFocus) => {
|
|
1731
|
+
const {
|
|
1732
|
+
focusedIndex
|
|
1733
|
+
} = state;
|
|
1734
|
+
// TODO send to renderer process
|
|
1735
|
+
// 1. close menu
|
|
1736
|
+
// 2. focus top level entry
|
|
1737
|
+
const newFocusedIndex = keepFocus ? focusedIndex : -1;
|
|
1738
|
+
return {
|
|
1739
|
+
...state,
|
|
1740
|
+
menus: [],
|
|
1741
|
+
isMenuOpen: false,
|
|
1742
|
+
focusedIndex: newFocusedIndex
|
|
761
1743
|
};
|
|
762
|
-
return rpc;
|
|
763
1744
|
};
|
|
764
|
-
|
|
765
|
-
|
|
1745
|
+
|
|
1746
|
+
const first = () => {
|
|
1747
|
+
return 0;
|
|
766
1748
|
};
|
|
767
|
-
const
|
|
768
|
-
return
|
|
1749
|
+
const last = items => {
|
|
1750
|
+
return items.length - 1;
|
|
769
1751
|
};
|
|
770
|
-
const
|
|
771
|
-
|
|
1752
|
+
const next = (items, index) => {
|
|
1753
|
+
return (index + 1) % items.length;
|
|
772
1754
|
};
|
|
773
|
-
const
|
|
774
|
-
return
|
|
1755
|
+
const previous = (items, index) => {
|
|
1756
|
+
return index === 0 ? items.length - 1 : index - 1;
|
|
775
1757
|
};
|
|
776
|
-
|
|
777
|
-
|
|
1758
|
+
|
|
1759
|
+
// TODO lazyload menuEntries and use Command.execute (maybe)
|
|
1760
|
+
const MENU_WIDTH = 150;
|
|
1761
|
+
const CONTEXT_MENU_ITEM_HEIGHT = 26;
|
|
1762
|
+
const CONTEXT_MENU_SEPARATOR_HEIGHT = 11;
|
|
1763
|
+
const CONTEXT_MENU_PADDING = 8;
|
|
1764
|
+
const CONTEXT_MENU_WIDTH = 250;
|
|
1765
|
+
const getMenuWidth = () => {
|
|
1766
|
+
return CONTEXT_MENU_WIDTH;
|
|
1767
|
+
};
|
|
1768
|
+
const getMenuHeight = items => {
|
|
1769
|
+
let height = CONTEXT_MENU_PADDING;
|
|
1770
|
+
for (const item of items) {
|
|
1771
|
+
switch (item.flags) {
|
|
1772
|
+
case Separator:
|
|
1773
|
+
height += CONTEXT_MENU_SEPARATOR_HEIGHT;
|
|
1774
|
+
break;
|
|
1775
|
+
default:
|
|
1776
|
+
height += CONTEXT_MENU_ITEM_HEIGHT;
|
|
1777
|
+
break;
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
return height;
|
|
778
1781
|
};
|
|
779
1782
|
|
|
780
|
-
//
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
1783
|
+
// TODO difference between focusing with mouse or keyboard
|
|
1784
|
+
// with mouse -> open submenu
|
|
1785
|
+
// with keyboard -> don't open submenu, only focus
|
|
1786
|
+
|
|
1787
|
+
const getIndexToFocusNextStartingAt = (items, startIndex) => {
|
|
1788
|
+
for (let i = startIndex; i < startIndex + items.length; i++) {
|
|
1789
|
+
const index = i % items.length;
|
|
1790
|
+
const item = items[index];
|
|
1791
|
+
if (canBeFocused(item)) {
|
|
1792
|
+
return index;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
return -1;
|
|
786
1796
|
};
|
|
787
|
-
const
|
|
788
|
-
|
|
789
|
-
}) => {
|
|
790
|
-
// TODO create a commandMap per rpc instance
|
|
791
|
-
register(commandMap);
|
|
792
|
-
const ipc = await listen$1();
|
|
793
|
-
handleIpc(ipc);
|
|
794
|
-
const rpc = createRpc(ipc);
|
|
795
|
-
return rpc;
|
|
1797
|
+
const getIndexToFocusFirst = items => {
|
|
1798
|
+
return getIndexToFocusNextStartingAt(items, 0);
|
|
796
1799
|
};
|
|
797
|
-
const
|
|
798
|
-
|
|
799
|
-
create: create$1
|
|
1800
|
+
const getIndexToFocusLast = items => {
|
|
1801
|
+
return getIndexToFocusPreviousStartingAt(items, items.length - 1);
|
|
800
1802
|
};
|
|
801
1803
|
|
|
802
|
-
|
|
803
|
-
const
|
|
804
|
-
|
|
805
|
-
const
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
const
|
|
814
|
-
const
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
const
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
key: LeftArrow,
|
|
830
|
-
command: 'Explorer.handleArrowLeft',
|
|
831
|
-
when: FocusExplorer
|
|
832
|
-
}, {
|
|
833
|
-
key: Home,
|
|
834
|
-
command: 'Explorer.focusFirst',
|
|
835
|
-
when: FocusExplorer
|
|
836
|
-
}, {
|
|
837
|
-
key: End,
|
|
838
|
-
command: 'Explorer.focusLast',
|
|
839
|
-
when: FocusExplorer
|
|
840
|
-
}, {
|
|
841
|
-
key: UpArrow,
|
|
842
|
-
command: 'Explorer.focusPrevious',
|
|
843
|
-
when: FocusExplorer
|
|
844
|
-
}, {
|
|
845
|
-
key: DownArrow,
|
|
846
|
-
command: 'Explorer.focusNext',
|
|
847
|
-
when: FocusExplorer
|
|
848
|
-
}, {
|
|
849
|
-
key: CtrlCmd | Star,
|
|
850
|
-
command: 'Explorer.expandAll',
|
|
851
|
-
when: FocusExplorer
|
|
852
|
-
}, {
|
|
853
|
-
key: Alt | RightArrow,
|
|
854
|
-
command: 'Explorer.expandRecursively',
|
|
855
|
-
when: FocusExplorer
|
|
856
|
-
}, {
|
|
857
|
-
key: CtrlCmd | LeftArrow,
|
|
858
|
-
command: 'Explorer.collapseAll',
|
|
859
|
-
when: FocusExplorer
|
|
860
|
-
}, {
|
|
861
|
-
key: CtrlCmd | KeyV,
|
|
862
|
-
command: 'Explorer.handlePaste',
|
|
863
|
-
when: FocusExplorer
|
|
864
|
-
}, {
|
|
865
|
-
key: CtrlCmd | KeyC,
|
|
866
|
-
command: 'Explorer.handleCopy',
|
|
867
|
-
when: FocusExplorer
|
|
868
|
-
}, {
|
|
869
|
-
key: F2,
|
|
870
|
-
command: 'Explorer.rename',
|
|
871
|
-
when: FocusExplorer
|
|
872
|
-
}, {
|
|
873
|
-
key: Escape,
|
|
874
|
-
command: 'Explorer.cancelEdit',
|
|
875
|
-
when: FocusExplorerEditBox
|
|
876
|
-
}, {
|
|
877
|
-
key: Enter,
|
|
878
|
-
command: 'Explorer.acceptEdit',
|
|
879
|
-
when: FocusExplorerEditBox
|
|
880
|
-
}, {
|
|
881
|
-
key: Delete,
|
|
882
|
-
command: 'Explorer.removeDirent',
|
|
883
|
-
when: FocusExplorer
|
|
884
|
-
}, {
|
|
885
|
-
key: Escape,
|
|
886
|
-
command: 'Explorer.focusNone',
|
|
887
|
-
when: FocusExplorer
|
|
888
|
-
}, {
|
|
889
|
-
key: Space,
|
|
890
|
-
command: 'Explorer.handleClickCurrentButKeepFocus',
|
|
891
|
-
when: FocusExplorer
|
|
892
|
-
}, {
|
|
893
|
-
key: Enter,
|
|
894
|
-
command: 'Explorer.handleClickCurrent',
|
|
895
|
-
when: FocusExplorer
|
|
896
|
-
}];
|
|
1804
|
+
// TODO this code seems a bit too complicated, maybe it can be simplified
|
|
1805
|
+
const getIndexToFocusPreviousStartingAt = (items, startIndex) => {
|
|
1806
|
+
for (let i = startIndex; i > startIndex - items.length; i--) {
|
|
1807
|
+
const index = (i + items.length) % items.length;
|
|
1808
|
+
const item = items[index];
|
|
1809
|
+
if (canBeFocused(item)) {
|
|
1810
|
+
return index;
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
return -1;
|
|
1814
|
+
};
|
|
1815
|
+
const getIndexToFocusPrevious = menu => {
|
|
1816
|
+
const startIndex = menu.focusedIndex === -1 ? menu.items.length - 1 : menu.focusedIndex - 1;
|
|
1817
|
+
return getIndexToFocusPreviousStartingAt(menu.items, startIndex);
|
|
1818
|
+
};
|
|
1819
|
+
const canBeFocused = item => {
|
|
1820
|
+
switch (item.flags) {
|
|
1821
|
+
case Separator:
|
|
1822
|
+
case Disabled:
|
|
1823
|
+
return false;
|
|
1824
|
+
default:
|
|
1825
|
+
return true;
|
|
1826
|
+
}
|
|
1827
|
+
};
|
|
1828
|
+
const getIndexToFocusNext = menu => {
|
|
1829
|
+
const startIndex = menu.focusedIndex + 1;
|
|
1830
|
+
return getIndexToFocusNextStartingAt(menu.items, startIndex);
|
|
897
1831
|
};
|
|
898
1832
|
|
|
899
|
-
|
|
900
|
-
const MenuItem = 'menuitem';
|
|
1833
|
+
// TODO handle printable letter and focus item that starts with that letter
|
|
901
1834
|
|
|
902
|
-
|
|
903
|
-
const HandleFocusIn = 'handleFocusIn';
|
|
904
|
-
const HandleFocusOut = 'handleFocusOut';
|
|
905
|
-
const HandlePointerOut = 'handlePointerOut';
|
|
906
|
-
const HandlePointerOver = 'handlePointerOver';
|
|
1835
|
+
// TODO pageup / pagedown keys
|
|
907
1836
|
|
|
908
|
-
|
|
909
|
-
const TitleBarTopLevelEntry = 'TitleBarTopLevelEntry';
|
|
910
|
-
const TitleBarTopLevelEntryLabel = 'TitleBarTopLevelEntryLabel';
|
|
1837
|
+
// TODO more tests
|
|
911
1838
|
|
|
912
|
-
const
|
|
913
|
-
|
|
1839
|
+
const getTotalWidth = entries => {
|
|
1840
|
+
let total = 0;
|
|
1841
|
+
for (const entry of entries) {
|
|
1842
|
+
total += entry.width;
|
|
1843
|
+
}
|
|
1844
|
+
return total;
|
|
1845
|
+
};
|
|
1846
|
+
const openMenuAtIndex = async (state, index, shouldBeFocused) => {
|
|
1847
|
+
const {
|
|
1848
|
+
titleBarEntries,
|
|
1849
|
+
titleBarHeight,
|
|
1850
|
+
x
|
|
1851
|
+
} = state;
|
|
1852
|
+
// TODO race conditions
|
|
1853
|
+
// TODO send renderer process
|
|
1854
|
+
// 1. open menu, items to show
|
|
1855
|
+
// 2. focus menu
|
|
1856
|
+
const titleBarEntry = titleBarEntries[index];
|
|
1857
|
+
const {
|
|
1858
|
+
id
|
|
1859
|
+
} = titleBarEntry;
|
|
1860
|
+
const items = await getMenuEntries(id);
|
|
1861
|
+
const relevantEntries = titleBarEntries.slice(0, index);
|
|
1862
|
+
const totalWidths = getTotalWidth(relevantEntries);
|
|
1863
|
+
const offset = totalWidths;
|
|
1864
|
+
// TODO race condition: another menu might already be open at this point
|
|
914
1865
|
|
|
915
|
-
const
|
|
1866
|
+
const menuX = x + offset;
|
|
1867
|
+
const menuY = titleBarHeight;
|
|
1868
|
+
const width = getMenuWidth();
|
|
1869
|
+
const height = getMenuHeight(items);
|
|
1870
|
+
const menuFocusedIndex = shouldBeFocused ? getIndexToFocusNextStartingAt(items, 0) : -1;
|
|
1871
|
+
const menu = {
|
|
1872
|
+
id,
|
|
1873
|
+
items,
|
|
1874
|
+
focusedIndex: menuFocusedIndex,
|
|
1875
|
+
level: 0,
|
|
1876
|
+
x: menuX,
|
|
1877
|
+
y: menuY,
|
|
1878
|
+
width,
|
|
1879
|
+
height
|
|
1880
|
+
};
|
|
1881
|
+
const menus = [menu];
|
|
916
1882
|
return {
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
1883
|
+
...state,
|
|
1884
|
+
isMenuOpen: true,
|
|
1885
|
+
focusedIndex: index,
|
|
1886
|
+
menus
|
|
920
1887
|
};
|
|
921
1888
|
};
|
|
922
1889
|
|
|
923
|
-
const
|
|
924
|
-
|
|
1890
|
+
const focusIndex = (state, index) => {
|
|
1891
|
+
object(state);
|
|
1892
|
+
number(index);
|
|
925
1893
|
const {
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
isFocused
|
|
931
|
-
} = item;
|
|
932
|
-
const dom = [];
|
|
933
|
-
dom.push({
|
|
934
|
-
type: Div,
|
|
935
|
-
className: TitleBarTopLevelEntry,
|
|
936
|
-
ariaHasPopup: true,
|
|
937
|
-
ariaExpanded: isOpen,
|
|
938
|
-
role: MenuItem,
|
|
939
|
-
childCount: 1,
|
|
940
|
-
ariaKeyShortcuts: keyboardShortCut
|
|
941
|
-
});
|
|
942
|
-
if (isOpen) {
|
|
943
|
-
// @ts-ignore
|
|
944
|
-
dom[0].ariaOwns = 'Menu-0';
|
|
945
|
-
}
|
|
946
|
-
if (isFocused) {
|
|
947
|
-
dom[0].className += ' ' + TitleBarEntryActive;
|
|
948
|
-
// @ts-ignore
|
|
949
|
-
dom[0].id = 'TitleBarEntryActive';
|
|
950
|
-
dom.push({
|
|
951
|
-
type: Div,
|
|
952
|
-
className: TitleBarTopLevelEntryLabel,
|
|
953
|
-
childCount: 1
|
|
954
|
-
});
|
|
1894
|
+
isMenuOpen
|
|
1895
|
+
} = state;
|
|
1896
|
+
if (isMenuOpen) {
|
|
1897
|
+
return openMenuAtIndex(state, index, /* focus */false);
|
|
955
1898
|
}
|
|
956
|
-
|
|
957
|
-
|
|
1899
|
+
return {
|
|
1900
|
+
...state,
|
|
1901
|
+
focusedIndex: index
|
|
1902
|
+
};
|
|
958
1903
|
};
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1904
|
+
|
|
1905
|
+
const focusFirst = state => {
|
|
1906
|
+
const indexToFocus = first();
|
|
1907
|
+
return focusIndex(state, indexToFocus);
|
|
962
1908
|
};
|
|
963
1909
|
|
|
964
|
-
const
|
|
965
|
-
return
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1910
|
+
const focus = state => {
|
|
1911
|
+
return focusFirst(state);
|
|
1912
|
+
};
|
|
1913
|
+
|
|
1914
|
+
const focusLast = state => {
|
|
1915
|
+
const {
|
|
1916
|
+
titleBarEntries
|
|
1917
|
+
} = state;
|
|
1918
|
+
const indexToFocus = last(titleBarEntries);
|
|
1919
|
+
return focusIndex(state, indexToFocus);
|
|
1920
|
+
};
|
|
1921
|
+
|
|
1922
|
+
const focusNext = state => {
|
|
1923
|
+
const {
|
|
1924
|
+
titleBarEntries,
|
|
1925
|
+
focusedIndex
|
|
1926
|
+
} = state;
|
|
1927
|
+
const indexToFocus = next(titleBarEntries, focusedIndex);
|
|
1928
|
+
return focusIndex(state, indexToFocus);
|
|
1929
|
+
};
|
|
1930
|
+
|
|
1931
|
+
const focusPrevious = state => {
|
|
1932
|
+
const {
|
|
1933
|
+
titleBarEntries,
|
|
1934
|
+
focusedIndex
|
|
1935
|
+
} = state;
|
|
1936
|
+
const indexToFocus = previous(titleBarEntries, focusedIndex);
|
|
1937
|
+
return focusIndex(state, indexToFocus);
|
|
1938
|
+
};
|
|
1939
|
+
|
|
1940
|
+
const LeftClick = 0;
|
|
1941
|
+
|
|
1942
|
+
const toggleIndex = (state, index) => {
|
|
1943
|
+
const {
|
|
1944
|
+
isMenuOpen,
|
|
1945
|
+
focusedIndex
|
|
1946
|
+
} = state;
|
|
1947
|
+
if (isMenuOpen && focusedIndex === index) {
|
|
1948
|
+
return closeMenu(state, /* keepFocus */true);
|
|
1949
|
+
}
|
|
1950
|
+
return openMenuAtIndex(state, index, /* focus */false);
|
|
977
1951
|
};
|
|
978
1952
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
this.name = 'AssertionError';
|
|
1953
|
+
const handleClick = (state, button, index) => {
|
|
1954
|
+
if (button !== LeftClick) {
|
|
1955
|
+
return state;
|
|
983
1956
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
switch (typeof value) {
|
|
987
|
-
case 'number':
|
|
988
|
-
return 'number';
|
|
989
|
-
case 'function':
|
|
990
|
-
return 'function';
|
|
991
|
-
case 'string':
|
|
992
|
-
return 'string';
|
|
993
|
-
case 'object':
|
|
994
|
-
if (value === null) {
|
|
995
|
-
return 'null';
|
|
996
|
-
}
|
|
997
|
-
if (Array.isArray(value)) {
|
|
998
|
-
return 'array';
|
|
999
|
-
}
|
|
1000
|
-
return 'object';
|
|
1001
|
-
case 'boolean':
|
|
1002
|
-
return 'boolean';
|
|
1003
|
-
default:
|
|
1004
|
-
return 'unknown';
|
|
1957
|
+
if (index === -1) {
|
|
1958
|
+
return state;
|
|
1005
1959
|
}
|
|
1960
|
+
return toggleIndex(state, index);
|
|
1006
1961
|
};
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1962
|
+
|
|
1963
|
+
// TODO remove this file and merge with whenExpressions
|
|
1964
|
+
const TitleBarMenuBar = FocusTitleBarMenuBar;
|
|
1965
|
+
|
|
1966
|
+
const handleFocus = async state => {
|
|
1967
|
+
await invoke('Focus.setFocus', TitleBarMenuBar);
|
|
1968
|
+
return state;
|
|
1012
1969
|
};
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1970
|
+
|
|
1971
|
+
/**
|
|
1972
|
+
* @param {boolean} focus
|
|
1973
|
+
*/
|
|
1974
|
+
const openMenu = (state, focus) => {
|
|
1975
|
+
const {
|
|
1976
|
+
focusedIndex
|
|
1977
|
+
} = state;
|
|
1978
|
+
if (focusedIndex === -1) {
|
|
1979
|
+
return state;
|
|
1017
1980
|
}
|
|
1981
|
+
return openMenuAtIndex(state, focusedIndex, focus);
|
|
1018
1982
|
};
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
throw new AssertionError('expected value to be of type boolean');
|
|
1023
|
-
}
|
|
1983
|
+
|
|
1984
|
+
const handleKeyArrowDownMenuClosed = state => {
|
|
1985
|
+
return openMenu(state, /* focus */true);
|
|
1024
1986
|
};
|
|
1025
1987
|
|
|
1026
|
-
const
|
|
1027
|
-
|
|
1988
|
+
const handleKeyArrowDownMenuOpen = state => {
|
|
1989
|
+
const {
|
|
1990
|
+
menus
|
|
1991
|
+
} = state;
|
|
1992
|
+
const menu = menus.at(-1);
|
|
1993
|
+
const newFocusedIndex = getIndexToFocusNext(menu);
|
|
1994
|
+
const newMenus = [...menus.slice(0, -1), {
|
|
1995
|
+
...menu,
|
|
1996
|
+
focusedIndex: newFocusedIndex
|
|
1997
|
+
}];
|
|
1998
|
+
return {
|
|
1999
|
+
...state,
|
|
2000
|
+
menus: newMenus
|
|
2001
|
+
};
|
|
1028
2002
|
};
|
|
1029
2003
|
|
|
1030
|
-
const
|
|
1031
|
-
|
|
2004
|
+
const ifElse = (menuOpenFunction, menuClosedFunction) => {
|
|
2005
|
+
const ifElseFunction = (state, ...args) => {
|
|
2006
|
+
const {
|
|
2007
|
+
isMenuOpen
|
|
2008
|
+
} = state;
|
|
2009
|
+
if (isMenuOpen) {
|
|
2010
|
+
return menuOpenFunction(state, ...args);
|
|
2011
|
+
}
|
|
2012
|
+
return menuClosedFunction(state, ...args);
|
|
2013
|
+
};
|
|
2014
|
+
return ifElseFunction;
|
|
1032
2015
|
};
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
2016
|
+
|
|
2017
|
+
const handleKeyArrowDown = ifElse(handleKeyArrowDownMenuOpen, handleKeyArrowDownMenuClosed);
|
|
2018
|
+
|
|
2019
|
+
const handleKeyArrowLeftMenuClosed = state => {
|
|
2020
|
+
// TODO menu collapse
|
|
2021
|
+
return focusPrevious(state);
|
|
2022
|
+
};
|
|
2023
|
+
|
|
2024
|
+
const closeOneMenu = state => {
|
|
2025
|
+
const {
|
|
2026
|
+
menus
|
|
2027
|
+
} = state;
|
|
2028
|
+
const parentMenu = menus.at(-2);
|
|
2029
|
+
const newParentMenu = {
|
|
2030
|
+
...parentMenu,
|
|
2031
|
+
expanded: false
|
|
2032
|
+
};
|
|
2033
|
+
const newMenus = [...menus.slice(0, -2), newParentMenu];
|
|
2034
|
+
return {
|
|
2035
|
+
...state,
|
|
2036
|
+
menus: newMenus
|
|
2037
|
+
};
|
|
2038
|
+
};
|
|
2039
|
+
|
|
2040
|
+
const handleKeyArrowLeftMenuOpen = state => {
|
|
2041
|
+
const {
|
|
2042
|
+
menus
|
|
2043
|
+
} = state;
|
|
2044
|
+
if (menus.length > 1) {
|
|
2045
|
+
return closeOneMenu(state);
|
|
1036
2046
|
}
|
|
1037
|
-
|
|
1038
|
-
return state.ctx;
|
|
2047
|
+
return focusPrevious(state);
|
|
1039
2048
|
};
|
|
1040
2049
|
|
|
1041
|
-
const
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
2050
|
+
const handleKeyArrowLeft = ifElse(handleKeyArrowLeftMenuOpen, handleKeyArrowLeftMenuClosed);
|
|
2051
|
+
|
|
2052
|
+
// TODO menu should not be needed initially, only when item is selected and menu is opened
|
|
2053
|
+
const handleKeyArrowRightMenuOpen = async state => {
|
|
2054
|
+
const {
|
|
2055
|
+
menus
|
|
2056
|
+
} = state;
|
|
2057
|
+
// if menu can open sub menu to the right -> do that
|
|
2058
|
+
const menu = menus.at(-1);
|
|
2059
|
+
const {
|
|
2060
|
+
items,
|
|
2061
|
+
focusedIndex,
|
|
2062
|
+
x,
|
|
2063
|
+
y
|
|
2064
|
+
} = menu;
|
|
2065
|
+
if (focusedIndex === -1) {
|
|
2066
|
+
return focusNext(state);
|
|
2067
|
+
}
|
|
2068
|
+
const item = items[focusedIndex];
|
|
2069
|
+
if (item.flags === SubMenu) {
|
|
2070
|
+
const subMenuEntries = await getMenuEntries(item.id);
|
|
2071
|
+
const subMenu = {
|
|
2072
|
+
level: menus.length,
|
|
2073
|
+
items: subMenuEntries,
|
|
2074
|
+
focusedIndex: 0,
|
|
2075
|
+
y: y + focusedIndex * 25,
|
|
2076
|
+
x: x + MENU_WIDTH
|
|
2077
|
+
};
|
|
2078
|
+
const newParentMenu = {
|
|
2079
|
+
...menu,
|
|
2080
|
+
expanded: true
|
|
2081
|
+
};
|
|
2082
|
+
const newMenus = [...menus.slice(0, -1), newParentMenu, subMenu];
|
|
2083
|
+
return {
|
|
2084
|
+
...state,
|
|
2085
|
+
menus: newMenus
|
|
2086
|
+
};
|
|
1046
2087
|
}
|
|
1047
|
-
return
|
|
2088
|
+
return focusNext(state);
|
|
1048
2089
|
};
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
2090
|
+
|
|
2091
|
+
const handleKeyArrowRight = ifElse(handleKeyArrowRightMenuOpen, focusNext);
|
|
2092
|
+
|
|
2093
|
+
const noop = state => {
|
|
2094
|
+
return state;
|
|
1052
2095
|
};
|
|
1053
2096
|
|
|
1054
|
-
const
|
|
1055
|
-
|
|
2097
|
+
const handleKeyArrowUpMenuOpen = state => {
|
|
2098
|
+
const {
|
|
2099
|
+
menus
|
|
2100
|
+
} = state;
|
|
2101
|
+
const menu = menus.at(-1);
|
|
2102
|
+
const previousIndex = getIndexToFocusPrevious(menu);
|
|
2103
|
+
const newMenus = [...menus.slice(0, -1), {
|
|
2104
|
+
...menu,
|
|
2105
|
+
focusedIndex: previousIndex
|
|
2106
|
+
}];
|
|
2107
|
+
return {
|
|
2108
|
+
...state,
|
|
2109
|
+
menus: newMenus
|
|
2110
|
+
};
|
|
1056
2111
|
};
|
|
1057
2112
|
|
|
1058
|
-
const
|
|
1059
|
-
|
|
2113
|
+
const handleKeyArrowUp = ifElse(handleKeyArrowUpMenuOpen, noop);
|
|
2114
|
+
|
|
2115
|
+
const handleKeyEndMenuOpen = state => {
|
|
2116
|
+
const {
|
|
2117
|
+
menus
|
|
2118
|
+
} = state;
|
|
2119
|
+
const menu = menus[0];
|
|
2120
|
+
const newFocusedIndex = getIndexToFocusLast(menu.items);
|
|
2121
|
+
const newMenus = [{
|
|
2122
|
+
...menu,
|
|
2123
|
+
focusedIndex: newFocusedIndex
|
|
2124
|
+
}];
|
|
2125
|
+
return {
|
|
2126
|
+
...state,
|
|
2127
|
+
menus: newMenus
|
|
2128
|
+
};
|
|
1060
2129
|
};
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
2130
|
+
|
|
2131
|
+
// TODO this is also use for pagedown -> maybe find a better name for this function
|
|
2132
|
+
const handleKeyEnd = ifElse(handleKeyEndMenuOpen, focusLast);
|
|
2133
|
+
|
|
2134
|
+
const handleKeyEnterMenuClosed = state => {
|
|
2135
|
+
return openMenu(state, /* focus */true);
|
|
2136
|
+
};
|
|
2137
|
+
|
|
2138
|
+
const handleKeyEnterMenuOpen = state => {
|
|
2139
|
+
// TODO
|
|
2140
|
+
// await Menu.selectCurrent()
|
|
2141
|
+
return state;
|
|
2142
|
+
};
|
|
2143
|
+
|
|
2144
|
+
const handleKeyEnter = ifElse(handleKeyEnterMenuOpen, handleKeyEnterMenuClosed);
|
|
2145
|
+
|
|
2146
|
+
const handleKeyEscapeMenuOpen = state => {
|
|
2147
|
+
const {
|
|
2148
|
+
menus
|
|
2149
|
+
} = state;
|
|
2150
|
+
if (menus.length > 1) {
|
|
2151
|
+
return closeOneMenu(state);
|
|
1070
2152
|
}
|
|
1071
|
-
|
|
1072
|
-
const fontString = getFontString(fontWeight, fontSize, fontFamily);
|
|
1073
|
-
const ctx = getContext();
|
|
1074
|
-
// @ts-ignore
|
|
1075
|
-
ctx.letterSpacing = letterSpacingString;
|
|
1076
|
-
ctx.font = fontString;
|
|
1077
|
-
const metrics = ctx.measureText(text);
|
|
1078
|
-
const width = metrics.width;
|
|
1079
|
-
return width;
|
|
2153
|
+
return closeMenu(state, /* keepFocus */true);
|
|
1080
2154
|
};
|
|
1081
2155
|
|
|
1082
|
-
const
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
2156
|
+
const handleKeyEscape = ifElse(handleKeyEscapeMenuOpen, noop);
|
|
2157
|
+
|
|
2158
|
+
const handleKeyHomeMenuOpen = state => {
|
|
2159
|
+
const {
|
|
2160
|
+
menus
|
|
2161
|
+
} = state;
|
|
2162
|
+
const menu = menus[0];
|
|
2163
|
+
const newFocusedIndex = getIndexToFocusFirst(menu.items);
|
|
2164
|
+
const newMenus = [{
|
|
2165
|
+
...menu,
|
|
2166
|
+
focusedIndex: newFocusedIndex
|
|
2167
|
+
}];
|
|
2168
|
+
return {
|
|
2169
|
+
...state,
|
|
2170
|
+
menus: newMenus
|
|
2171
|
+
};
|
|
1086
2172
|
};
|
|
1087
2173
|
|
|
1088
|
-
const
|
|
2174
|
+
const handleKeyHome = ifElse(handleKeyHomeMenuOpen, focusFirst);
|
|
2175
|
+
|
|
2176
|
+
const handleKeySpaceMenuClosed = state => {
|
|
2177
|
+
return openMenu(state, /* focus */true);
|
|
2178
|
+
};
|
|
2179
|
+
|
|
2180
|
+
const handleKeySpaceMenuOpen = state => {
|
|
2181
|
+
// TODO
|
|
2182
|
+
// await Menu.selectCurrent()
|
|
2183
|
+
return state;
|
|
2184
|
+
};
|
|
2185
|
+
|
|
2186
|
+
// TODO this is same as handle key enter -> merge the functions
|
|
2187
|
+
const handleKeySpace = ifElse(handleKeySpaceMenuOpen, handleKeySpaceMenuClosed);
|
|
2188
|
+
|
|
2189
|
+
const executeMenuItemCommand = async item => {
|
|
2190
|
+
// TODO
|
|
2191
|
+
throw new Error('not implemented');
|
|
2192
|
+
};
|
|
2193
|
+
|
|
2194
|
+
const selectIndexIgnore = async (state, item) => {
|
|
2195
|
+
await executeMenuItemCommand();
|
|
2196
|
+
return state;
|
|
2197
|
+
};
|
|
2198
|
+
|
|
2199
|
+
const selectIndexNone = async (state, item) => {
|
|
2200
|
+
await executeMenuItemCommand();
|
|
1089
2201
|
return {
|
|
1090
|
-
|
|
1091
|
-
titleBarEntries: [],
|
|
1092
|
-
focusedIndex: -1,
|
|
1093
|
-
isMenuOpen: false,
|
|
2202
|
+
...state,
|
|
1094
2203
|
menus: [],
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
2204
|
+
isMenuOpen: false
|
|
2205
|
+
};
|
|
2206
|
+
};
|
|
2207
|
+
|
|
2208
|
+
const selectIndexRestoreFocus = async (state, item) => {
|
|
2209
|
+
await executeMenuItemCommand();
|
|
2210
|
+
return {
|
|
2211
|
+
...state,
|
|
2212
|
+
menus: [],
|
|
2213
|
+
isMenuOpen: false
|
|
2214
|
+
};
|
|
2215
|
+
};
|
|
2216
|
+
|
|
2217
|
+
const selectIndexSubMenu = async (state, menu, index) => {
|
|
2218
|
+
const {
|
|
2219
|
+
menus
|
|
2220
|
+
} = state;
|
|
2221
|
+
const {
|
|
2222
|
+
items,
|
|
1101
2223
|
x,
|
|
1102
2224
|
y,
|
|
1103
|
-
|
|
1104
|
-
|
|
2225
|
+
level
|
|
2226
|
+
} = menu;
|
|
2227
|
+
const item = items[index];
|
|
2228
|
+
const subMenuEntries = await getMenuEntries(item.id);
|
|
2229
|
+
const subMenu = {
|
|
2230
|
+
level: menus.length,
|
|
2231
|
+
items: subMenuEntries,
|
|
2232
|
+
focusedIndex: -1,
|
|
2233
|
+
x: x + MENU_WIDTH,
|
|
2234
|
+
y: y + index * 25
|
|
2235
|
+
};
|
|
2236
|
+
const newParentMenu = {
|
|
2237
|
+
...menu,
|
|
2238
|
+
focusedIndex: index
|
|
2239
|
+
};
|
|
2240
|
+
const newMenus = [...menus.slice(0, level - 1), newParentMenu, subMenu];
|
|
2241
|
+
return {
|
|
2242
|
+
...state,
|
|
2243
|
+
menus: newMenus
|
|
1105
2244
|
};
|
|
1106
2245
|
};
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
2246
|
+
|
|
2247
|
+
const handleMenuClick = (state, level, index) => {
|
|
2248
|
+
const {
|
|
2249
|
+
menus
|
|
2250
|
+
} = state;
|
|
2251
|
+
const menu = menus[level];
|
|
2252
|
+
const item = menu.items[index];
|
|
2253
|
+
switch (item.flags) {
|
|
2254
|
+
case None:
|
|
2255
|
+
return selectIndexNone(state);
|
|
2256
|
+
case SubMenu:
|
|
2257
|
+
return selectIndexSubMenu(state, menu, index);
|
|
2258
|
+
case RestoreFocus:
|
|
2259
|
+
return selectIndexRestoreFocus(state);
|
|
2260
|
+
case Ignore:
|
|
2261
|
+
return selectIndexIgnore(state);
|
|
2262
|
+
default:
|
|
2263
|
+
return state;
|
|
1116
2264
|
}
|
|
1117
|
-
return withWidths;
|
|
1118
2265
|
};
|
|
1119
|
-
|
|
2266
|
+
|
|
2267
|
+
const handleMenuMouseOver = async (state, level, index) => {
|
|
2268
|
+
object(state);
|
|
2269
|
+
number(level);
|
|
2270
|
+
number(index);
|
|
1120
2271
|
const {
|
|
1121
|
-
|
|
1122
|
-
labelFontSize,
|
|
1123
|
-
labelFontWeight,
|
|
1124
|
-
labelLetterSpacing,
|
|
1125
|
-
labelPadding
|
|
2272
|
+
menus
|
|
1126
2273
|
} = state;
|
|
1127
|
-
const
|
|
1128
|
-
const
|
|
1129
|
-
|
|
1130
|
-
|
|
2274
|
+
const menu = menus[level];
|
|
2275
|
+
const {
|
|
2276
|
+
items,
|
|
2277
|
+
focusedIndex,
|
|
2278
|
+
y,
|
|
2279
|
+
x
|
|
2280
|
+
} = menu;
|
|
2281
|
+
const item = items[index];
|
|
2282
|
+
if (focusedIndex === index) {
|
|
2283
|
+
if (index === -1) {
|
|
2284
|
+
return state;
|
|
2285
|
+
}
|
|
2286
|
+
if (item.flags === SubMenu && level === menus.length - 2) {
|
|
2287
|
+
const subMenu = menus[level + 1];
|
|
2288
|
+
if (subMenu.focusedIndex !== -1) {
|
|
2289
|
+
const newSubMenu = {
|
|
2290
|
+
...subMenu,
|
|
2291
|
+
focusedIndex: -1
|
|
2292
|
+
};
|
|
2293
|
+
const newMenus = [...menus.slice(0, -1), newSubMenu];
|
|
2294
|
+
return {
|
|
2295
|
+
...state,
|
|
2296
|
+
menus: newMenus
|
|
2297
|
+
};
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
return state;
|
|
2301
|
+
}
|
|
2302
|
+
if (index === -1) {
|
|
2303
|
+
const newMenus = [...menus.slice(0, level), {
|
|
2304
|
+
...menu,
|
|
2305
|
+
focusedIndex: -1
|
|
2306
|
+
}];
|
|
2307
|
+
return {
|
|
2308
|
+
...state,
|
|
2309
|
+
menus: newMenus
|
|
2310
|
+
};
|
|
2311
|
+
}
|
|
2312
|
+
if (item.flags === SubMenu) {
|
|
2313
|
+
const item = items[index];
|
|
2314
|
+
const subMenuEntries = await getMenuEntries(item.id);
|
|
2315
|
+
const subMenu = {
|
|
2316
|
+
level: menus.length,
|
|
2317
|
+
items: subMenuEntries,
|
|
2318
|
+
focusedIndex: -1,
|
|
2319
|
+
y: y + index * 25,
|
|
2320
|
+
x: x + MENU_WIDTH
|
|
2321
|
+
};
|
|
2322
|
+
const newParentMenu = {
|
|
2323
|
+
...menu,
|
|
2324
|
+
focusedIndex: index
|
|
2325
|
+
};
|
|
2326
|
+
const newMenus = [...menus.slice(0, level - 1), newParentMenu, subMenu];
|
|
2327
|
+
return {
|
|
2328
|
+
...state,
|
|
2329
|
+
menus: newMenus
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2332
|
+
const newMenus = [...menus.slice(0, level), {
|
|
2333
|
+
...menu,
|
|
2334
|
+
focusedIndex: index
|
|
2335
|
+
}];
|
|
1131
2336
|
return {
|
|
1132
2337
|
...state,
|
|
1133
|
-
|
|
2338
|
+
menus: newMenus
|
|
1134
2339
|
};
|
|
1135
2340
|
};
|
|
1136
2341
|
|
|
2342
|
+
const handleMouseOutMenuClosed = state => {
|
|
2343
|
+
return focusIndex(state, -1);
|
|
2344
|
+
};
|
|
2345
|
+
|
|
2346
|
+
const handleMouseOutMenuOpen = state => {
|
|
2347
|
+
return state;
|
|
2348
|
+
};
|
|
2349
|
+
|
|
2350
|
+
const handleMouseOut = ifElse(handleMouseOutMenuOpen, handleMouseOutMenuClosed);
|
|
2351
|
+
|
|
2352
|
+
const handleMouseOverMenuClosed = (state, index) => {
|
|
2353
|
+
return focusIndex(state, index);
|
|
2354
|
+
};
|
|
2355
|
+
|
|
2356
|
+
const handleMouseOverMenuOpen = (state, index) => {
|
|
2357
|
+
if (index === -1) {
|
|
2358
|
+
return state;
|
|
2359
|
+
}
|
|
2360
|
+
return focusIndex(state, index);
|
|
2361
|
+
};
|
|
2362
|
+
|
|
2363
|
+
const handleMouseOver = ifElse(handleMouseOverMenuOpen, handleMouseOverMenuClosed);
|
|
2364
|
+
|
|
2365
|
+
const toggleMenu = state => {
|
|
2366
|
+
const {
|
|
2367
|
+
isMenuOpen
|
|
2368
|
+
} = state;
|
|
2369
|
+
if (isMenuOpen) {
|
|
2370
|
+
return closeMenu(state, /* keepFocus */true);
|
|
2371
|
+
}
|
|
2372
|
+
return openMenu(state, /* focus */false);
|
|
2373
|
+
};
|
|
2374
|
+
|
|
1137
2375
|
const commandMap = {
|
|
2376
|
+
'TitleBarMenuBar.closeMenu': closeMenu,
|
|
1138
2377
|
'TitleBarMenuBar.create': create,
|
|
2378
|
+
'TitleBarMenuBar.focus': focus,
|
|
2379
|
+
'TitleBarMenuBar.focusFirst': focusFirst,
|
|
2380
|
+
'TitleBarMenuBar.focusIndex': focusLast,
|
|
2381
|
+
'TitleBarMenuBar.focusLast': focusIndex,
|
|
2382
|
+
'TitleBarMenuBar.focusNext': focusNext,
|
|
2383
|
+
'TitleBarMenuBar.focusPrevious': focusPrevious,
|
|
2384
|
+
'TitleBarMenuBar.getKeyBindings': getKeyBindings,
|
|
2385
|
+
'TitleBarMenuBar.getMenus': getMenus,
|
|
1139
2386
|
'TitleBarMenuBar.getVirtualDom': getTitleBarMenuBarVirtualDom,
|
|
2387
|
+
'TitleBarMenuBar.handleClick': handleClick,
|
|
2388
|
+
'TitleBarMenuBar.handleFocus': handleFocus,
|
|
2389
|
+
'TitleBarMenuBar.handleKeyArrowDown': handleKeyArrowDown,
|
|
2390
|
+
'TitleBarMenuBar.handleKeyArrowLeft': handleKeyArrowLeft,
|
|
2391
|
+
'TitleBarMenuBar.handleKeyArrowRight': handleKeyArrowRight,
|
|
2392
|
+
'TitleBarMenuBar.handleKeyArrowUp': handleKeyArrowUp,
|
|
2393
|
+
'TitleBarMenuBar.handleKeyEnd': handleKeyEnd,
|
|
2394
|
+
'TitleBarMenuBar.handleKeyEnter': handleKeyEnter,
|
|
2395
|
+
'TitleBarMenuBar.handleKeyEscape': handleKeyEscape,
|
|
2396
|
+
'TitleBarMenuBar.handleKeyHome': handleKeyHome,
|
|
2397
|
+
'TitleBarMenuBar.handleKeySpace': handleKeySpace,
|
|
2398
|
+
'TitleBarMenuBar.handleMenuClick': handleMenuClick,
|
|
2399
|
+
'TitleBarMenuBar.handleMenuMouseOver': handleMenuMouseOver,
|
|
2400
|
+
'TitleBarMenuBar.handleMouseOut': handleMouseOut,
|
|
2401
|
+
'TitleBarMenuBar.handleMouseOver': handleMouseOver,
|
|
1140
2402
|
'TitleBarMenuBar.loadContent': loadContent,
|
|
1141
|
-
'TitleBarMenuBar.
|
|
2403
|
+
'TitleBarMenuBar.toggleIndex': toggleIndex,
|
|
2404
|
+
'TitleBarMenuBar.toggleMenu': toggleMenu
|
|
1142
2405
|
};
|
|
1143
2406
|
|
|
1144
2407
|
const listen = async () => {
|
|
1145
|
-
await WebWorkerRpcClient.create({
|
|
2408
|
+
const rpc = await WebWorkerRpcClient.create({
|
|
1146
2409
|
commandMap: commandMap
|
|
1147
2410
|
});
|
|
2411
|
+
setRpc(rpc);
|
|
1148
2412
|
};
|
|
1149
2413
|
|
|
1150
2414
|
const main = async () => {
|