@lvce-editor/source-control-worker 1.0.0 → 1.2.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/sourceControlWorkerMain.js +1118 -16
- package/package.json +1 -1
|
@@ -54,6 +54,47 @@ class VError extends Error {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
class AssertionError extends Error {
|
|
58
|
+
constructor(message) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = 'AssertionError';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
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';
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const number = value => {
|
|
86
|
+
const type = getType(value);
|
|
87
|
+
if (type !== 'number') {
|
|
88
|
+
throw new AssertionError('expected value to be of type number');
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const string = value => {
|
|
92
|
+
const type = getType(value);
|
|
93
|
+
if (type !== 'string') {
|
|
94
|
+
throw new AssertionError('expected value to be of type string');
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
57
98
|
const isMessagePort = value => {
|
|
58
99
|
return value && value instanceof MessagePort;
|
|
59
100
|
};
|
|
@@ -379,6 +420,100 @@ const IpcChildWithModuleWorkerAndMessagePort$1 = {
|
|
|
379
420
|
listen: listen$6,
|
|
380
421
|
wrap: wrap$e
|
|
381
422
|
};
|
|
423
|
+
const addListener = (emitter, type, callback) => {
|
|
424
|
+
if ('addEventListener' in emitter) {
|
|
425
|
+
emitter.addEventListener(type, callback);
|
|
426
|
+
} else {
|
|
427
|
+
emitter.on(type, callback);
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
const removeListener = (emitter, type, callback) => {
|
|
431
|
+
if ('removeEventListener' in emitter) {
|
|
432
|
+
emitter.removeEventListener(type, callback);
|
|
433
|
+
} else {
|
|
434
|
+
emitter.off(type, callback);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
const getFirstEvent = (eventEmitter, eventMap) => {
|
|
438
|
+
const {
|
|
439
|
+
resolve,
|
|
440
|
+
promise
|
|
441
|
+
} = withResolvers();
|
|
442
|
+
const listenerMap = Object.create(null);
|
|
443
|
+
const cleanup = value => {
|
|
444
|
+
for (const event of Object.keys(eventMap)) {
|
|
445
|
+
removeListener(eventEmitter, event, listenerMap[event]);
|
|
446
|
+
}
|
|
447
|
+
resolve(value);
|
|
448
|
+
};
|
|
449
|
+
for (const [event, type] of Object.entries(eventMap)) {
|
|
450
|
+
const listener = event => {
|
|
451
|
+
cleanup({
|
|
452
|
+
type,
|
|
453
|
+
event
|
|
454
|
+
});
|
|
455
|
+
};
|
|
456
|
+
addListener(eventEmitter, event, listener);
|
|
457
|
+
listenerMap[event] = listener;
|
|
458
|
+
}
|
|
459
|
+
return promise;
|
|
460
|
+
};
|
|
461
|
+
const Message$1 = 3;
|
|
462
|
+
const create$5$1 = async ({
|
|
463
|
+
messagePort,
|
|
464
|
+
isMessagePortOpen
|
|
465
|
+
}) => {
|
|
466
|
+
if (!isMessagePort(messagePort)) {
|
|
467
|
+
throw new IpcError('port must be of type MessagePort');
|
|
468
|
+
}
|
|
469
|
+
if (isMessagePortOpen) {
|
|
470
|
+
return messagePort;
|
|
471
|
+
}
|
|
472
|
+
const eventPromise = getFirstEvent(messagePort, {
|
|
473
|
+
message: Message$1
|
|
474
|
+
});
|
|
475
|
+
messagePort.start();
|
|
476
|
+
const {
|
|
477
|
+
type,
|
|
478
|
+
event
|
|
479
|
+
} = await eventPromise;
|
|
480
|
+
if (type !== Message$1) {
|
|
481
|
+
throw new IpcError('Failed to wait for ipc message');
|
|
482
|
+
}
|
|
483
|
+
if (event.data !== readyMessage) {
|
|
484
|
+
throw new IpcError('unexpected first message');
|
|
485
|
+
}
|
|
486
|
+
return messagePort;
|
|
487
|
+
};
|
|
488
|
+
const signal$1 = messagePort => {
|
|
489
|
+
messagePort.start();
|
|
490
|
+
};
|
|
491
|
+
class IpcParentWithMessagePort extends Ipc {
|
|
492
|
+
getData = getData$2;
|
|
493
|
+
send(message) {
|
|
494
|
+
this._rawIpc.postMessage(message);
|
|
495
|
+
}
|
|
496
|
+
sendAndTransfer(message) {
|
|
497
|
+
const transfer = getTransferrables(message);
|
|
498
|
+
this._rawIpc.postMessage(message, transfer);
|
|
499
|
+
}
|
|
500
|
+
dispose() {
|
|
501
|
+
this._rawIpc.close();
|
|
502
|
+
}
|
|
503
|
+
onMessage(callback) {
|
|
504
|
+
this._rawIpc.addEventListener('message', callback);
|
|
505
|
+
}
|
|
506
|
+
onClose(callback) {}
|
|
507
|
+
}
|
|
508
|
+
const wrap$5 = messagePort => {
|
|
509
|
+
return new IpcParentWithMessagePort(messagePort);
|
|
510
|
+
};
|
|
511
|
+
const IpcParentWithMessagePort$1 = {
|
|
512
|
+
__proto__: null,
|
|
513
|
+
create: create$5$1,
|
|
514
|
+
signal: signal$1,
|
|
515
|
+
wrap: wrap$5
|
|
516
|
+
};
|
|
382
517
|
|
|
383
518
|
const Two = '2.0';
|
|
384
519
|
const create$4 = (method, params) => {
|
|
@@ -389,10 +524,10 @@ const create$4 = (method, params) => {
|
|
|
389
524
|
};
|
|
390
525
|
};
|
|
391
526
|
const callbacks = Object.create(null);
|
|
392
|
-
const set$
|
|
527
|
+
const set$2 = (id, fn) => {
|
|
393
528
|
callbacks[id] = fn;
|
|
394
529
|
};
|
|
395
|
-
const get = id => {
|
|
530
|
+
const get$3 = id => {
|
|
396
531
|
return callbacks[id];
|
|
397
532
|
};
|
|
398
533
|
const remove = id => {
|
|
@@ -408,7 +543,7 @@ const registerPromise = () => {
|
|
|
408
543
|
resolve,
|
|
409
544
|
promise
|
|
410
545
|
} = Promise.withResolvers();
|
|
411
|
-
set$
|
|
546
|
+
set$2(id, resolve);
|
|
412
547
|
return {
|
|
413
548
|
id,
|
|
414
549
|
promise
|
|
@@ -565,7 +700,7 @@ const warn = (...args) => {
|
|
|
565
700
|
console.warn(...args);
|
|
566
701
|
};
|
|
567
702
|
const resolve = (id, response) => {
|
|
568
|
-
const fn = get(id);
|
|
703
|
+
const fn = get$3(id);
|
|
569
704
|
if (!fn) {
|
|
570
705
|
console.log(response);
|
|
571
706
|
warn(`callback ${id} may already be disposed`);
|
|
@@ -604,7 +739,7 @@ const getErrorProperty = (error, prettyError) => {
|
|
|
604
739
|
}
|
|
605
740
|
};
|
|
606
741
|
};
|
|
607
|
-
const create$1 = (message, error) => {
|
|
742
|
+
const create$1$1 = (message, error) => {
|
|
608
743
|
return {
|
|
609
744
|
jsonrpc: Two,
|
|
610
745
|
id: message.id,
|
|
@@ -615,7 +750,7 @@ const getErrorResponse = (message, error, preparePrettyError, logError) => {
|
|
|
615
750
|
const prettyError = preparePrettyError(error);
|
|
616
751
|
logError(error, prettyError);
|
|
617
752
|
const errorProperty = getErrorProperty(error, prettyError);
|
|
618
|
-
return create$1(message, errorProperty);
|
|
753
|
+
return create$1$1(message, errorProperty);
|
|
619
754
|
};
|
|
620
755
|
const create$5 = (message, result) => {
|
|
621
756
|
return {
|
|
@@ -719,10 +854,10 @@ const send = (transport, method, ...params) => {
|
|
|
719
854
|
const message = create$4(method, params);
|
|
720
855
|
transport.send(message);
|
|
721
856
|
};
|
|
722
|
-
const invoke = (ipc, method, ...params) => {
|
|
857
|
+
const invoke$2 = (ipc, method, ...params) => {
|
|
723
858
|
return invokeHelper(ipc, method, params, false);
|
|
724
859
|
};
|
|
725
|
-
const invokeAndTransfer = (ipc, method, ...params) => {
|
|
860
|
+
const invokeAndTransfer$1 = (ipc, method, ...params) => {
|
|
726
861
|
return invokeHelper(ipc, method, params, true);
|
|
727
862
|
};
|
|
728
863
|
|
|
@@ -752,10 +887,10 @@ const createRpc = ipc => {
|
|
|
752
887
|
send(ipc, method, ...params);
|
|
753
888
|
},
|
|
754
889
|
invoke(method, ...params) {
|
|
755
|
-
return invoke(ipc, method, ...params);
|
|
890
|
+
return invoke$2(ipc, method, ...params);
|
|
756
891
|
},
|
|
757
892
|
invokeAndTransfer(method, ...params) {
|
|
758
|
-
return invokeAndTransfer(ipc, method, ...params);
|
|
893
|
+
return invokeAndTransfer$1(ipc, method, ...params);
|
|
759
894
|
},
|
|
760
895
|
async dispose() {
|
|
761
896
|
await ipc?.dispose();
|
|
@@ -793,7 +928,27 @@ const listen$1 = async (module, options) => {
|
|
|
793
928
|
const ipc = module.wrap(rawIpc);
|
|
794
929
|
return ipc;
|
|
795
930
|
};
|
|
796
|
-
const create = async ({
|
|
931
|
+
const create$8 = async ({
|
|
932
|
+
commandMap,
|
|
933
|
+
messagePort,
|
|
934
|
+
isMessagePortOpen
|
|
935
|
+
}) => {
|
|
936
|
+
// TODO create a commandMap per rpc instance
|
|
937
|
+
register(commandMap);
|
|
938
|
+
const rawIpc = await IpcParentWithMessagePort$1.create({
|
|
939
|
+
messagePort,
|
|
940
|
+
isMessagePortOpen
|
|
941
|
+
});
|
|
942
|
+
const ipc = IpcParentWithMessagePort$1.wrap(rawIpc);
|
|
943
|
+
handleIpc(ipc);
|
|
944
|
+
const rpc = createRpc(ipc);
|
|
945
|
+
return rpc;
|
|
946
|
+
};
|
|
947
|
+
const MessagePortRpcParent = {
|
|
948
|
+
__proto__: null,
|
|
949
|
+
create: create$8
|
|
950
|
+
};
|
|
951
|
+
const create$1 = async ({
|
|
797
952
|
commandMap
|
|
798
953
|
}) => {
|
|
799
954
|
// TODO create a commandMap per rpc instance
|
|
@@ -805,23 +960,970 @@ const create = async ({
|
|
|
805
960
|
};
|
|
806
961
|
const WebWorkerRpcClient = {
|
|
807
962
|
__proto__: null,
|
|
808
|
-
create
|
|
963
|
+
create: create$1
|
|
809
964
|
};
|
|
810
965
|
|
|
811
|
-
const
|
|
812
|
-
|
|
966
|
+
const create = () => {
|
|
967
|
+
const states = Object.create(null);
|
|
968
|
+
return {
|
|
969
|
+
get(uid) {
|
|
970
|
+
return states[uid];
|
|
971
|
+
},
|
|
972
|
+
set(uid, oldState, newState) {
|
|
973
|
+
states[uid] = {
|
|
974
|
+
oldState,
|
|
975
|
+
newState
|
|
976
|
+
};
|
|
977
|
+
},
|
|
978
|
+
dispose(uid) {
|
|
979
|
+
delete states[uid];
|
|
980
|
+
},
|
|
981
|
+
getKeys() {
|
|
982
|
+
return Object.keys(states).map(key => {
|
|
983
|
+
return Number.parseInt(key);
|
|
984
|
+
});
|
|
985
|
+
},
|
|
986
|
+
clear() {
|
|
987
|
+
for (const key of Object.keys(states)) {
|
|
988
|
+
delete states[key];
|
|
989
|
+
}
|
|
990
|
+
},
|
|
991
|
+
wrapCommand(fn) {
|
|
992
|
+
const wrapped = async (uid, ...args) => {
|
|
993
|
+
const {
|
|
994
|
+
newState
|
|
995
|
+
} = states[uid];
|
|
996
|
+
const newerState = await fn(newState, ...args);
|
|
997
|
+
if (newState === newerState) {
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
const latest = states[uid];
|
|
1001
|
+
states[uid] = {
|
|
1002
|
+
oldState: latest.oldState,
|
|
1003
|
+
newState: newerState
|
|
1004
|
+
};
|
|
1005
|
+
};
|
|
1006
|
+
return wrapped;
|
|
1007
|
+
},
|
|
1008
|
+
diff(uid, modules, numbers) {
|
|
1009
|
+
const {
|
|
1010
|
+
oldState,
|
|
1011
|
+
newState
|
|
1012
|
+
} = states[uid];
|
|
1013
|
+
const diffResult = [];
|
|
1014
|
+
for (let i = 0; i < modules.length; i++) {
|
|
1015
|
+
const fn = modules[i];
|
|
1016
|
+
if (!fn(oldState, newState)) {
|
|
1017
|
+
diffResult.push(numbers[i]);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
return diffResult;
|
|
1021
|
+
}
|
|
1022
|
+
};
|
|
813
1023
|
};
|
|
814
1024
|
|
|
815
|
-
const
|
|
816
|
-
|
|
1025
|
+
const {
|
|
1026
|
+
get: get$2,
|
|
1027
|
+
set: set$1,
|
|
1028
|
+
wrapCommand
|
|
1029
|
+
} = create();
|
|
1030
|
+
|
|
1031
|
+
const create2 = (id, uri, x, y, width, height, workspacePath) => {
|
|
1032
|
+
const state = {
|
|
1033
|
+
id,
|
|
1034
|
+
root: '',
|
|
1035
|
+
items: [],
|
|
1036
|
+
x,
|
|
1037
|
+
y,
|
|
1038
|
+
width,
|
|
1039
|
+
height,
|
|
1040
|
+
deltaY: 0,
|
|
1041
|
+
minLineY: 0,
|
|
1042
|
+
maxLineY: 0,
|
|
1043
|
+
fileIconCache: Object.create(null),
|
|
1044
|
+
icons: [],
|
|
1045
|
+
finalDeltaY: 0,
|
|
1046
|
+
handleOffset: 0,
|
|
1047
|
+
scrollBarActive: false,
|
|
1048
|
+
scrollBarHeight: 0,
|
|
1049
|
+
merge: [],
|
|
1050
|
+
index: [],
|
|
1051
|
+
untracked: [],
|
|
1052
|
+
workingTree: [],
|
|
1053
|
+
inputValue: '',
|
|
1054
|
+
displayItems: [],
|
|
1055
|
+
buttonIndex: -1,
|
|
1056
|
+
enabledProviderIds: [],
|
|
1057
|
+
isExpanded: true,
|
|
1058
|
+
buttons: [],
|
|
1059
|
+
providerId: '',
|
|
1060
|
+
splitButtonEnabled: false,
|
|
1061
|
+
allGroups: [],
|
|
1062
|
+
gitRoot: '',
|
|
1063
|
+
itemHeight: 20,
|
|
1064
|
+
minimumSliderSize: 20,
|
|
1065
|
+
workspacePath
|
|
1066
|
+
};
|
|
1067
|
+
set$1(id, state, state);
|
|
1068
|
+
};
|
|
1069
|
+
|
|
1070
|
+
const RenderItems = 4;
|
|
1071
|
+
|
|
1072
|
+
const diffType = RenderItems;
|
|
1073
|
+
const isEqual = (oldState, newState) => {
|
|
1074
|
+
return oldState.allGroups === newState.allGroups && oldState.displayItems === newState.displayItems && oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.deltaY === newState.deltaY && oldState.buttonIndex === newState.buttonIndex && oldState.buttons === newState.buttons;
|
|
1075
|
+
};
|
|
1076
|
+
|
|
1077
|
+
const modules = [isEqual];
|
|
1078
|
+
const numbers = [diffType];
|
|
1079
|
+
|
|
1080
|
+
const diff = (oldState, newState) => {
|
|
1081
|
+
const diffResult = [];
|
|
1082
|
+
for (let i = 0; i < modules.length; i++) {
|
|
1083
|
+
const fn = modules[i];
|
|
1084
|
+
if (!fn(oldState, newState)) {
|
|
1085
|
+
diffResult.push(numbers[i]);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
return diffResult;
|
|
1089
|
+
};
|
|
1090
|
+
|
|
1091
|
+
const diff2 = uid => {
|
|
1092
|
+
const {
|
|
1093
|
+
oldState,
|
|
1094
|
+
newState
|
|
1095
|
+
} = get$2(uid);
|
|
1096
|
+
const result = diff(oldState, newState);
|
|
1097
|
+
return result;
|
|
1098
|
+
};
|
|
1099
|
+
|
|
1100
|
+
const commandIds = ['acceptInput', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusNone', 'focusPrevious', 'handleClick', 'handleClickAt', 'handleIconThemeChange', 'handleWheel'];
|
|
1101
|
+
|
|
1102
|
+
const getCommandIds = () => {
|
|
1103
|
+
return commandIds;
|
|
817
1104
|
};
|
|
818
1105
|
|
|
819
1106
|
const RendererWorker = 1;
|
|
1107
|
+
const ExtensionHostWorker = 44;
|
|
1108
|
+
const DebugWorker = 55;
|
|
820
1109
|
|
|
821
1110
|
const rpcs = Object.create(null);
|
|
822
1111
|
const set = (id, rpc) => {
|
|
823
1112
|
rpcs[id] = rpc;
|
|
824
1113
|
};
|
|
1114
|
+
const get$1 = id => {
|
|
1115
|
+
return rpcs[id];
|
|
1116
|
+
};
|
|
1117
|
+
|
|
1118
|
+
const invoke$1 = (method, ...params) => {
|
|
1119
|
+
const rpc = get$1(RendererWorker);
|
|
1120
|
+
// @ts-ignore
|
|
1121
|
+
return rpc.invoke(method, ...params);
|
|
1122
|
+
};
|
|
1123
|
+
const invokeAndTransfer = (method, ...params) => {
|
|
1124
|
+
const rpc = get$1(RendererWorker);
|
|
1125
|
+
// @ts-ignore
|
|
1126
|
+
return rpc.invokeAndTransfer(method, ...params);
|
|
1127
|
+
};
|
|
1128
|
+
|
|
1129
|
+
const activateByEvent = event => {
|
|
1130
|
+
return invoke$1('ExtensionHostManagement.activateByEvent', event);
|
|
1131
|
+
};
|
|
1132
|
+
|
|
1133
|
+
const invoke = async (method, ...params) => {
|
|
1134
|
+
const rpc = get$1(ExtensionHostWorker);
|
|
1135
|
+
return rpc.invoke(method, ...params);
|
|
1136
|
+
};
|
|
1137
|
+
|
|
1138
|
+
const executeProvider = async ({
|
|
1139
|
+
event,
|
|
1140
|
+
method,
|
|
1141
|
+
params
|
|
1142
|
+
}) => {
|
|
1143
|
+
await activateByEvent(event);
|
|
1144
|
+
const result = await invoke(method, ...params);
|
|
1145
|
+
return result;
|
|
1146
|
+
};
|
|
1147
|
+
|
|
1148
|
+
const CommandExecute = 'ExtensionHostCommand.executeCommand';
|
|
1149
|
+
const SourceControlGetEnabledProviderIds = 'ExtensionHostSourceControl.getEnabledProviderIds';
|
|
1150
|
+
const SourceControlGetGroups = 'ExtensionHostSourceControl.getGroups';
|
|
1151
|
+
|
|
1152
|
+
const executeCommand = (id, ...args) => {
|
|
1153
|
+
return executeProvider({
|
|
1154
|
+
event: `onCommand:${id}`,
|
|
1155
|
+
method: CommandExecute,
|
|
1156
|
+
params: [id, ...args]
|
|
1157
|
+
});
|
|
1158
|
+
};
|
|
1159
|
+
|
|
1160
|
+
const Directory = 3;
|
|
1161
|
+
const DirectoryExpanded = 4;
|
|
1162
|
+
const File = 7;
|
|
1163
|
+
|
|
1164
|
+
const getFileIcon = ({
|
|
1165
|
+
name
|
|
1166
|
+
}) => {
|
|
1167
|
+
return '';
|
|
1168
|
+
};
|
|
1169
|
+
|
|
1170
|
+
// TODO this should be in FileSystem module
|
|
1171
|
+
const pathBaseName = path => {
|
|
1172
|
+
return path.slice(path.lastIndexOf('/') + 1);
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1175
|
+
const getDisplayItemsGroup = (group, isExpanded) => {
|
|
1176
|
+
const displayItems = [];
|
|
1177
|
+
const {
|
|
1178
|
+
id,
|
|
1179
|
+
label,
|
|
1180
|
+
items
|
|
1181
|
+
} = group;
|
|
1182
|
+
if (!items) {
|
|
1183
|
+
throw new Error('Source control group is missing an items property');
|
|
1184
|
+
}
|
|
1185
|
+
const length = items.length;
|
|
1186
|
+
const type = DirectoryExpanded ;
|
|
1187
|
+
const icon = 'ChevronDown' ;
|
|
1188
|
+
if (length > 0) {
|
|
1189
|
+
displayItems.push({
|
|
1190
|
+
file: '',
|
|
1191
|
+
label,
|
|
1192
|
+
detail: '',
|
|
1193
|
+
posInSet: 1,
|
|
1194
|
+
setSize: 1,
|
|
1195
|
+
icon,
|
|
1196
|
+
decorationIcon: '',
|
|
1197
|
+
decorationIconTitle: '',
|
|
1198
|
+
decorationStrikeThrough: false,
|
|
1199
|
+
type,
|
|
1200
|
+
badgeCount: length,
|
|
1201
|
+
groupId: id
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
{
|
|
1205
|
+
for (let i = 0; i < length; i++) {
|
|
1206
|
+
const item = items[i];
|
|
1207
|
+
const {
|
|
1208
|
+
file,
|
|
1209
|
+
icon,
|
|
1210
|
+
iconTitle,
|
|
1211
|
+
strikeThrough
|
|
1212
|
+
} = item;
|
|
1213
|
+
const baseName = pathBaseName(file);
|
|
1214
|
+
const folderName = file.slice(0, -baseName.length - 1);
|
|
1215
|
+
displayItems.push({
|
|
1216
|
+
file,
|
|
1217
|
+
label: baseName,
|
|
1218
|
+
detail: folderName,
|
|
1219
|
+
posInSet: i + 1,
|
|
1220
|
+
setSize: length,
|
|
1221
|
+
icon: getFileIcon({
|
|
1222
|
+
name: file
|
|
1223
|
+
}),
|
|
1224
|
+
decorationIcon: icon,
|
|
1225
|
+
decorationIconTitle: iconTitle,
|
|
1226
|
+
decorationStrikeThrough: strikeThrough,
|
|
1227
|
+
type: File,
|
|
1228
|
+
badgeCount: 0,
|
|
1229
|
+
groupId: id
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
return displayItems;
|
|
1234
|
+
};
|
|
1235
|
+
const getDisplayItems = (allGroups, isExpanded) => {
|
|
1236
|
+
const displayItems = [];
|
|
1237
|
+
for (const group of allGroups) {
|
|
1238
|
+
const groupDisplayItems = getDisplayItemsGroup(group);
|
|
1239
|
+
displayItems.push(...groupDisplayItems);
|
|
1240
|
+
}
|
|
1241
|
+
return displayItems;
|
|
1242
|
+
};
|
|
1243
|
+
|
|
1244
|
+
const getFinalDeltaY = (height, itemHeight, itemsLength) => {
|
|
1245
|
+
const contentHeight = itemsLength * itemHeight;
|
|
1246
|
+
const finalDeltaY = Math.max(contentHeight - height, 0);
|
|
1247
|
+
return finalDeltaY;
|
|
1248
|
+
};
|
|
1249
|
+
|
|
1250
|
+
const getListHeight = (itemsLength, itemHeight, maxHeight) => {
|
|
1251
|
+
number(itemsLength);
|
|
1252
|
+
number(itemHeight);
|
|
1253
|
+
number(maxHeight);
|
|
1254
|
+
if (itemsLength === 0) {
|
|
1255
|
+
return itemHeight;
|
|
1256
|
+
}
|
|
1257
|
+
const totalHeight = itemsLength * itemHeight;
|
|
1258
|
+
return Math.min(totalHeight, maxHeight);
|
|
1259
|
+
};
|
|
1260
|
+
|
|
1261
|
+
// TODO optimize this function to return the minimum number
|
|
1262
|
+
// of visible items needed, e.g. when not scrolled 5 items with
|
|
1263
|
+
// 20px fill 100px but when scrolled 6 items are needed
|
|
1264
|
+
const getNumberOfVisibleItems = (listHeight, itemHeight) => {
|
|
1265
|
+
return Math.ceil(listHeight / itemHeight) + 1;
|
|
1266
|
+
};
|
|
1267
|
+
|
|
1268
|
+
const Disk = 'file';
|
|
1269
|
+
|
|
1270
|
+
const RE_PROTOCOL = /^([a-z-]+):\/\//;
|
|
1271
|
+
const getProtocol = uri => {
|
|
1272
|
+
if (!uri) {
|
|
1273
|
+
return Disk;
|
|
1274
|
+
}
|
|
1275
|
+
const protocolMatch = uri.match(RE_PROTOCOL);
|
|
1276
|
+
if (protocolMatch) {
|
|
1277
|
+
return protocolMatch[1];
|
|
1278
|
+
}
|
|
1279
|
+
return Disk;
|
|
1280
|
+
};
|
|
1281
|
+
|
|
1282
|
+
const get = key => {
|
|
1283
|
+
return false;
|
|
1284
|
+
};
|
|
1285
|
+
|
|
1286
|
+
const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
|
|
1287
|
+
if (size >= contentSize) {
|
|
1288
|
+
return 0;
|
|
1289
|
+
}
|
|
1290
|
+
return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
|
|
1291
|
+
};
|
|
1292
|
+
|
|
1293
|
+
const getGroups$2 = (providerId, path) => {
|
|
1294
|
+
return executeProvider({
|
|
1295
|
+
event: 'none',
|
|
1296
|
+
method: SourceControlGetGroups,
|
|
1297
|
+
params: [providerId, path]
|
|
1298
|
+
// noProviderFoundMessage: 'No source control provider found',
|
|
1299
|
+
});
|
|
1300
|
+
};
|
|
1301
|
+
const getEnabledProviderIds$1 = (scheme, root) => {
|
|
1302
|
+
return executeProvider({
|
|
1303
|
+
event: `onSourceControl:${scheme}`,
|
|
1304
|
+
method: SourceControlGetEnabledProviderIds,
|
|
1305
|
+
params: [scheme, root]
|
|
1306
|
+
// noProviderFoundMessage: 'No source control provider found',
|
|
1307
|
+
});
|
|
1308
|
+
};
|
|
1309
|
+
|
|
1310
|
+
const getEnabledProviderIds = (scheme, root) => {
|
|
1311
|
+
string(scheme);
|
|
1312
|
+
string(root);
|
|
1313
|
+
return getEnabledProviderIds$1(scheme, root);
|
|
1314
|
+
};
|
|
1315
|
+
const getGroups$1 = (providerId, root) => {
|
|
1316
|
+
return getGroups$2(providerId, root);
|
|
1317
|
+
};
|
|
1318
|
+
|
|
1319
|
+
const getExtensions = async () => {
|
|
1320
|
+
return invoke('Extensions.getExtensions');
|
|
1321
|
+
};
|
|
1322
|
+
|
|
1323
|
+
const state = {
|
|
1324
|
+
cache: Object.create(null)
|
|
1325
|
+
};
|
|
1326
|
+
const getContextId = (groupId, type) => {
|
|
1327
|
+
if (type === File) {
|
|
1328
|
+
return `${groupId}-item`;
|
|
1329
|
+
}
|
|
1330
|
+
return groupId;
|
|
1331
|
+
};
|
|
1332
|
+
const ensureActions = async () => {
|
|
1333
|
+
if (Object.keys(state.cache).length > 0) {
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
const extensions = await getExtensions();
|
|
1337
|
+
for (const extension of extensions) {
|
|
1338
|
+
if (extension && extension['source-control-actions']) {
|
|
1339
|
+
for (const [key, value] of Object.entries(extension['source-control-actions'])) {
|
|
1340
|
+
state.cache[key] = value;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
};
|
|
1345
|
+
const getSourceControlActions = async (providerId, groupId, type) => {
|
|
1346
|
+
string(groupId);
|
|
1347
|
+
await ensureActions();
|
|
1348
|
+
const contextId = getContextId(groupId, type);
|
|
1349
|
+
const value = state.cache[contextId] || [];
|
|
1350
|
+
return value;
|
|
1351
|
+
};
|
|
1352
|
+
|
|
1353
|
+
const getGroups = async enabledProviderIds => {
|
|
1354
|
+
const allGroups = [];
|
|
1355
|
+
for (const providerId of enabledProviderIds) {
|
|
1356
|
+
// @ts-ignore
|
|
1357
|
+
const groups = await getGroups$1(providerId);
|
|
1358
|
+
allGroups.push(...groups);
|
|
1359
|
+
}
|
|
1360
|
+
return {
|
|
1361
|
+
allGroups,
|
|
1362
|
+
gitRoot: ''
|
|
1363
|
+
};
|
|
1364
|
+
};
|
|
1365
|
+
const getNewButtons = async (displayItems, providerId, buttonIndex) => {
|
|
1366
|
+
if (buttonIndex === -1) {
|
|
1367
|
+
return [];
|
|
1368
|
+
}
|
|
1369
|
+
const item = displayItems[buttonIndex];
|
|
1370
|
+
if (!item) {
|
|
1371
|
+
return [];
|
|
1372
|
+
}
|
|
1373
|
+
const actions = await getSourceControlActions(providerId, item.groupId, item.type);
|
|
1374
|
+
return actions;
|
|
1375
|
+
};
|
|
1376
|
+
const loadContent = async state => {
|
|
1377
|
+
const {
|
|
1378
|
+
itemHeight,
|
|
1379
|
+
height,
|
|
1380
|
+
minimumSliderSize,
|
|
1381
|
+
workspacePath
|
|
1382
|
+
} = state;
|
|
1383
|
+
const root = workspacePath;
|
|
1384
|
+
const scheme = getProtocol(root);
|
|
1385
|
+
const enabledProviderIds = await getEnabledProviderIds(scheme, root);
|
|
1386
|
+
const {
|
|
1387
|
+
allGroups,
|
|
1388
|
+
gitRoot
|
|
1389
|
+
} = await getGroups(enabledProviderIds);
|
|
1390
|
+
const isExpanded = true;
|
|
1391
|
+
const items = getDisplayItems(allGroups);
|
|
1392
|
+
const buttons = await getNewButtons(items, state.providerId, state.buttonIndex);
|
|
1393
|
+
const splitButtonEnabled = get();
|
|
1394
|
+
const total = items.length;
|
|
1395
|
+
const contentHeight = total * itemHeight;
|
|
1396
|
+
const listHeight = getListHeight(total, itemHeight, height);
|
|
1397
|
+
const scrollBarHeight = getScrollBarSize(height, contentHeight, minimumSliderSize);
|
|
1398
|
+
const numberOfVisible = getNumberOfVisibleItems(listHeight, itemHeight);
|
|
1399
|
+
const maxLineY = Math.min(numberOfVisible, total);
|
|
1400
|
+
const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, total);
|
|
1401
|
+
return {
|
|
1402
|
+
...state,
|
|
1403
|
+
allGroups,
|
|
1404
|
+
gitRoot,
|
|
1405
|
+
items,
|
|
1406
|
+
enabledProviderIds,
|
|
1407
|
+
isExpanded,
|
|
1408
|
+
buttons,
|
|
1409
|
+
root,
|
|
1410
|
+
splitButtonEnabled,
|
|
1411
|
+
maxLineY,
|
|
1412
|
+
scrollBarHeight,
|
|
1413
|
+
finalDeltaY
|
|
1414
|
+
};
|
|
1415
|
+
};
|
|
1416
|
+
|
|
1417
|
+
const handleButtonClick = async (state, clickedIndex) => {
|
|
1418
|
+
const {
|
|
1419
|
+
buttonIndex,
|
|
1420
|
+
buttons,
|
|
1421
|
+
items
|
|
1422
|
+
} = state;
|
|
1423
|
+
const button = buttons[clickedIndex];
|
|
1424
|
+
const item = items[buttonIndex];
|
|
1425
|
+
if (!button) {
|
|
1426
|
+
return state;
|
|
1427
|
+
}
|
|
1428
|
+
await executeCommand(button.command, item.file);
|
|
1429
|
+
const newState = await loadContent(state);
|
|
1430
|
+
return newState;
|
|
1431
|
+
};
|
|
1432
|
+
|
|
1433
|
+
const show = async (x, y, id, ...args) => {
|
|
1434
|
+
return invoke$1('ContextMenu.show', x, y, id, ...args);
|
|
1435
|
+
};
|
|
1436
|
+
|
|
1437
|
+
const SourceControl = 22;
|
|
1438
|
+
|
|
1439
|
+
const handleContextMenu = async (state, button, x, y) => {
|
|
1440
|
+
await show(x, y, SourceControl);
|
|
1441
|
+
return state;
|
|
1442
|
+
};
|
|
1443
|
+
|
|
1444
|
+
const getPortTuple = () => {
|
|
1445
|
+
const {
|
|
1446
|
+
port1,
|
|
1447
|
+
port2
|
|
1448
|
+
} = new MessageChannel();
|
|
1449
|
+
return {
|
|
1450
|
+
port1,
|
|
1451
|
+
port2
|
|
1452
|
+
};
|
|
1453
|
+
};
|
|
1454
|
+
|
|
1455
|
+
const sendMessagePortToExtensionHostWorker = async port => {
|
|
1456
|
+
const command = 'HandleMessagePort.handleMessagePort';
|
|
1457
|
+
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, command, DebugWorker);
|
|
1458
|
+
};
|
|
1459
|
+
|
|
1460
|
+
const createExtensionHostRpc = async () => {
|
|
1461
|
+
try {
|
|
1462
|
+
const {
|
|
1463
|
+
port1,
|
|
1464
|
+
port2
|
|
1465
|
+
} = getPortTuple();
|
|
1466
|
+
await sendMessagePortToExtensionHostWorker(port2);
|
|
1467
|
+
port1.start();
|
|
1468
|
+
const rpc = await MessagePortRpcParent.create({
|
|
1469
|
+
commandMap: {},
|
|
1470
|
+
messagePort: port1,
|
|
1471
|
+
isMessagePortOpen: false
|
|
1472
|
+
});
|
|
1473
|
+
// TODO createMessageportRpcParent should call port start
|
|
1474
|
+
return rpc;
|
|
1475
|
+
} catch (error) {
|
|
1476
|
+
throw new VError(error, `Failed to create extension host rpc`);
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
|
|
1480
|
+
const initialize = async () => {
|
|
1481
|
+
const extensionHostRpc = await createExtensionHostRpc();
|
|
1482
|
+
set(ExtensionHostWorker, extensionHostRpc);
|
|
1483
|
+
};
|
|
1484
|
+
|
|
1485
|
+
const HandleClick = 'handleClick';
|
|
1486
|
+
const HandleContextMenu = 'handleContextMenu';
|
|
1487
|
+
const HandleMouseOut = 'handleMouseOut';
|
|
1488
|
+
const HandleMouseOver = 'handleMouseOver';
|
|
1489
|
+
const HandleWheel = 'handleWheel';
|
|
1490
|
+
|
|
1491
|
+
const None = 'none';
|
|
1492
|
+
const ToolBar = 'toolbar';
|
|
1493
|
+
const Tree = 'tree';
|
|
1494
|
+
const TreeItem$1 = 'treeitem';
|
|
1495
|
+
|
|
1496
|
+
const Actions = 'Actions';
|
|
1497
|
+
const Chevron = 'Chevron';
|
|
1498
|
+
const ChevronRight = 'ChevronRight';
|
|
1499
|
+
const DecorationIcon = 'DecorationIcon';
|
|
1500
|
+
const FileIcon = 'FileIcon';
|
|
1501
|
+
const IconButton = 'IconButton';
|
|
1502
|
+
const InputBox = 'InputBox';
|
|
1503
|
+
const Label = 'Label';
|
|
1504
|
+
const LabelDetail = 'LabelDetail';
|
|
1505
|
+
const MaskIcon = 'MaskIcon';
|
|
1506
|
+
const MaskIconChevronDown = 'MaskIconChevronDown';
|
|
1507
|
+
const SourceControlBadge = 'SourceControlBadge';
|
|
1508
|
+
const SourceControlButton = 'SourceControlButton';
|
|
1509
|
+
const SourceControlHeader = 'SourceControlHeader';
|
|
1510
|
+
const SourceControlItems = 'SourceControlItems';
|
|
1511
|
+
const SplitButton = 'SplitButton';
|
|
1512
|
+
const SplitButtonContent = 'SplitButtonContent';
|
|
1513
|
+
const SplitButtonContentDisabled = 'SplitButtonContentDisabled';
|
|
1514
|
+
const SplitButtonDisabled = 'SplitButtonDisabled';
|
|
1515
|
+
const SplitButtonDropDown = 'SplitButtonDropDown';
|
|
1516
|
+
const SplitButtonDropDownDisabled = 'SplitButtonDropDownDisabled';
|
|
1517
|
+
const SplitButtonSeparator = 'SplitButtonSeparator';
|
|
1518
|
+
const StrikeThrough = 'StrikeThrough';
|
|
1519
|
+
const TreeItem = 'TreeItem';
|
|
1520
|
+
|
|
1521
|
+
const emptySourceControlButtons = [];
|
|
1522
|
+
|
|
1523
|
+
const Button$1 = 1;
|
|
1524
|
+
const Div = 4;
|
|
1525
|
+
const Input = 6;
|
|
1526
|
+
const Span = 8;
|
|
1527
|
+
const Img = 17;
|
|
1528
|
+
|
|
1529
|
+
const Text = 12;
|
|
1530
|
+
const text = data => {
|
|
1531
|
+
return {
|
|
1532
|
+
type: Text,
|
|
1533
|
+
text: data,
|
|
1534
|
+
childCount: 0
|
|
1535
|
+
};
|
|
1536
|
+
};
|
|
1537
|
+
|
|
1538
|
+
const getBadgeVirtualDom = (className, count) => {
|
|
1539
|
+
return [{
|
|
1540
|
+
type: Div,
|
|
1541
|
+
className: `Badge ${className}`,
|
|
1542
|
+
childCount: 1
|
|
1543
|
+
}, text(`${count}`)];
|
|
1544
|
+
};
|
|
1545
|
+
|
|
1546
|
+
const getFileIconVirtualDom = icon => {
|
|
1547
|
+
return {
|
|
1548
|
+
type: Img,
|
|
1549
|
+
className: FileIcon,
|
|
1550
|
+
src: icon,
|
|
1551
|
+
role: None,
|
|
1552
|
+
childCount: 0
|
|
1553
|
+
};
|
|
1554
|
+
};
|
|
1555
|
+
|
|
1556
|
+
const getIconVirtualDom = (icon, type = Div) => {
|
|
1557
|
+
return {
|
|
1558
|
+
type,
|
|
1559
|
+
className: `MaskIcon MaskIcon${icon}`,
|
|
1560
|
+
role: None,
|
|
1561
|
+
childCount: 0
|
|
1562
|
+
};
|
|
1563
|
+
};
|
|
1564
|
+
|
|
1565
|
+
const PaddingLeft = '1rem';
|
|
1566
|
+
const PaddingRight = '12px';
|
|
1567
|
+
|
|
1568
|
+
const getLabelClassName = decorationStrikeThrough => {
|
|
1569
|
+
let className = Label + ' Grow';
|
|
1570
|
+
if (decorationStrikeThrough) {
|
|
1571
|
+
className += ` ${StrikeThrough}`;
|
|
1572
|
+
}
|
|
1573
|
+
return className;
|
|
1574
|
+
};
|
|
1575
|
+
const addButtons = (dom, buttons) => {
|
|
1576
|
+
if (buttons === emptySourceControlButtons) {
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1579
|
+
dom[0].childCount += buttons.length;
|
|
1580
|
+
for (const button of buttons) {
|
|
1581
|
+
const {
|
|
1582
|
+
icon,
|
|
1583
|
+
label
|
|
1584
|
+
} = button;
|
|
1585
|
+
dom.push({
|
|
1586
|
+
type: Button$1,
|
|
1587
|
+
className: SourceControlButton,
|
|
1588
|
+
title: label,
|
|
1589
|
+
ariaLabel: label,
|
|
1590
|
+
childCount: 1
|
|
1591
|
+
}, getIconVirtualDom(icon, Span));
|
|
1592
|
+
}
|
|
1593
|
+
};
|
|
1594
|
+
const createItemDirectory = item => {
|
|
1595
|
+
const {
|
|
1596
|
+
posInSet,
|
|
1597
|
+
setSize,
|
|
1598
|
+
icon,
|
|
1599
|
+
label,
|
|
1600
|
+
badgeCount,
|
|
1601
|
+
decorationStrikeThrough,
|
|
1602
|
+
type,
|
|
1603
|
+
buttons
|
|
1604
|
+
} = item;
|
|
1605
|
+
const labelClassName = getLabelClassName(decorationStrikeThrough);
|
|
1606
|
+
const dom = [{
|
|
1607
|
+
type: Div,
|
|
1608
|
+
className: TreeItem,
|
|
1609
|
+
role: TreeItem$1,
|
|
1610
|
+
ariaExpanded: type === DirectoryExpanded,
|
|
1611
|
+
ariaPosInSet: posInSet,
|
|
1612
|
+
ariaSetSize: setSize,
|
|
1613
|
+
childCount: 3,
|
|
1614
|
+
paddingLeft: PaddingLeft,
|
|
1615
|
+
paddingRight: PaddingRight
|
|
1616
|
+
}, {
|
|
1617
|
+
type: Div,
|
|
1618
|
+
className: `${Chevron} MaskIcon${icon}`,
|
|
1619
|
+
childCount: 0
|
|
1620
|
+
}, {
|
|
1621
|
+
type: Div,
|
|
1622
|
+
className: labelClassName,
|
|
1623
|
+
childCount: 1
|
|
1624
|
+
}, text(label)];
|
|
1625
|
+
addButtons(dom, buttons);
|
|
1626
|
+
dom.push(...getBadgeVirtualDom(SourceControlBadge, badgeCount));
|
|
1627
|
+
return dom;
|
|
1628
|
+
};
|
|
1629
|
+
const createItemOther = item => {
|
|
1630
|
+
const {
|
|
1631
|
+
posInSet,
|
|
1632
|
+
setSize,
|
|
1633
|
+
icon,
|
|
1634
|
+
file,
|
|
1635
|
+
label,
|
|
1636
|
+
decorationIcon,
|
|
1637
|
+
decorationIconTitle,
|
|
1638
|
+
decorationStrikeThrough,
|
|
1639
|
+
detail,
|
|
1640
|
+
buttons
|
|
1641
|
+
} = item;
|
|
1642
|
+
const labelClassName = getLabelClassName(decorationStrikeThrough);
|
|
1643
|
+
/**
|
|
1644
|
+
* @type {any[]}
|
|
1645
|
+
*/
|
|
1646
|
+
const dom = [];
|
|
1647
|
+
dom.push({
|
|
1648
|
+
type: Div,
|
|
1649
|
+
className: TreeItem,
|
|
1650
|
+
role: TreeItem$1,
|
|
1651
|
+
ariaPosInSet: posInSet,
|
|
1652
|
+
ariaSetSize: setSize,
|
|
1653
|
+
title: file,
|
|
1654
|
+
childCount: 3,
|
|
1655
|
+
paddingLeft: '1rem',
|
|
1656
|
+
paddingRight: '12px'
|
|
1657
|
+
}, ...(icon === ChevronRight ? [{
|
|
1658
|
+
type: Div,
|
|
1659
|
+
className: Chevron,
|
|
1660
|
+
childCount: 1
|
|
1661
|
+
}, getIconVirtualDom(icon)] : [getFileIconVirtualDom(icon)]));
|
|
1662
|
+
const labelDom = {
|
|
1663
|
+
type: Div,
|
|
1664
|
+
className: labelClassName,
|
|
1665
|
+
childCount: 1
|
|
1666
|
+
};
|
|
1667
|
+
dom.push(labelDom, text(label));
|
|
1668
|
+
if (detail) {
|
|
1669
|
+
labelDom.childCount++;
|
|
1670
|
+
dom.push({
|
|
1671
|
+
type: Span,
|
|
1672
|
+
className: LabelDetail,
|
|
1673
|
+
childCount: 1
|
|
1674
|
+
}, text(detail));
|
|
1675
|
+
}
|
|
1676
|
+
addButtons(dom, buttons);
|
|
1677
|
+
dom.push({
|
|
1678
|
+
type: Img,
|
|
1679
|
+
className: DecorationIcon,
|
|
1680
|
+
title: decorationIconTitle,
|
|
1681
|
+
src: decorationIcon,
|
|
1682
|
+
childCount: 0
|
|
1683
|
+
});
|
|
1684
|
+
return dom;
|
|
1685
|
+
};
|
|
1686
|
+
const getSourceControlItemVirtualDom = item => {
|
|
1687
|
+
switch (item.type) {
|
|
1688
|
+
case DirectoryExpanded:
|
|
1689
|
+
case Directory:
|
|
1690
|
+
return createItemDirectory(item);
|
|
1691
|
+
default:
|
|
1692
|
+
return createItemOther(item);
|
|
1693
|
+
}
|
|
1694
|
+
};
|
|
1695
|
+
|
|
1696
|
+
const getSourceControlItemsVirtualDom$1 = (hasItems, buttonText) => {
|
|
1697
|
+
const dom = [];
|
|
1698
|
+
dom.push({
|
|
1699
|
+
type: Div,
|
|
1700
|
+
className: `${SplitButton} ${hasItems ? '' : SplitButtonDisabled}`,
|
|
1701
|
+
childCount: 3
|
|
1702
|
+
}, {
|
|
1703
|
+
type: Div,
|
|
1704
|
+
className: `${SplitButtonContent} ${hasItems ? '' : SplitButtonContentDisabled}`,
|
|
1705
|
+
childCount: 1,
|
|
1706
|
+
tabIndex: 0
|
|
1707
|
+
}, text(buttonText), {
|
|
1708
|
+
type: Div,
|
|
1709
|
+
className: SplitButtonSeparator,
|
|
1710
|
+
childCount: 0
|
|
1711
|
+
}, {
|
|
1712
|
+
type: Div,
|
|
1713
|
+
className: `${SplitButtonDropDown} ${hasItems ? '' : SplitButtonDropDownDisabled}`,
|
|
1714
|
+
childCount: 1,
|
|
1715
|
+
tabIndex: 0
|
|
1716
|
+
}, {
|
|
1717
|
+
type: Div,
|
|
1718
|
+
className: `${MaskIcon} ${MaskIconChevronDown}`,
|
|
1719
|
+
childCount: 0
|
|
1720
|
+
});
|
|
1721
|
+
return dom;
|
|
1722
|
+
};
|
|
1723
|
+
|
|
1724
|
+
const emptyObject = {};
|
|
1725
|
+
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
|
|
1726
|
+
const i18nString = (key, placeholders = emptyObject) => {
|
|
1727
|
+
if (placeholders === emptyObject) {
|
|
1728
|
+
return key;
|
|
1729
|
+
}
|
|
1730
|
+
const replacer = (match, rest) => {
|
|
1731
|
+
return placeholders[rest];
|
|
1732
|
+
};
|
|
1733
|
+
return key.replaceAll(RE_PLACEHOLDER, replacer);
|
|
1734
|
+
};
|
|
1735
|
+
|
|
1736
|
+
const MessageEnterToCommitOnMaster = `Message (Enter) to commit on 'master'`;
|
|
1737
|
+
const SourceControlInput = 'Source Control Input';
|
|
1738
|
+
|
|
1739
|
+
const messageEnterToCommitOnMaster = () => {
|
|
1740
|
+
return i18nString(MessageEnterToCommitOnMaster);
|
|
1741
|
+
};
|
|
1742
|
+
const sourceControlInput = () => {
|
|
1743
|
+
return i18nString(SourceControlInput);
|
|
1744
|
+
};
|
|
1745
|
+
|
|
1746
|
+
const getSourceControlItemsVirtualDom = (items, splitButtonEnabled) => {
|
|
1747
|
+
const dom = [];
|
|
1748
|
+
dom.push({
|
|
1749
|
+
type: Div,
|
|
1750
|
+
className: SourceControlHeader,
|
|
1751
|
+
childCount: 1
|
|
1752
|
+
}, {
|
|
1753
|
+
type: Input,
|
|
1754
|
+
className: InputBox,
|
|
1755
|
+
spellcheck: false,
|
|
1756
|
+
autocapitalize: 'off',
|
|
1757
|
+
autocorrect: 'off',
|
|
1758
|
+
placeholder: messageEnterToCommitOnMaster(),
|
|
1759
|
+
ariaLabel: sourceControlInput(),
|
|
1760
|
+
childCount: 0,
|
|
1761
|
+
onInput: 'handleInput',
|
|
1762
|
+
onFocus: 'handleFocus'
|
|
1763
|
+
});
|
|
1764
|
+
if (splitButtonEnabled) {
|
|
1765
|
+
const hasItems = items.length > 0;
|
|
1766
|
+
dom.push(...getSourceControlItemsVirtualDom$1(hasItems, 'Commit'));
|
|
1767
|
+
}
|
|
1768
|
+
dom.push({
|
|
1769
|
+
type: Div,
|
|
1770
|
+
className: SourceControlItems,
|
|
1771
|
+
role: Tree,
|
|
1772
|
+
childCount: items.length
|
|
1773
|
+
}, ...items.flatMap(getSourceControlItemVirtualDom));
|
|
1774
|
+
return dom;
|
|
1775
|
+
};
|
|
1776
|
+
|
|
1777
|
+
const getSourceControlVirtualDom = (items, splitButtonEnabled) => {
|
|
1778
|
+
const dom = [{
|
|
1779
|
+
type: Div,
|
|
1780
|
+
className: 'Viewlet SourceControl',
|
|
1781
|
+
tabIndex: 0,
|
|
1782
|
+
onClick: HandleClick,
|
|
1783
|
+
onContextMenu: HandleContextMenu,
|
|
1784
|
+
onMouseOver: HandleMouseOver,
|
|
1785
|
+
onMouseOut: HandleMouseOut,
|
|
1786
|
+
onWheel: HandleWheel,
|
|
1787
|
+
childCount: splitButtonEnabled ? 3 : 2
|
|
1788
|
+
}, ...getSourceControlItemsVirtualDom(items, splitButtonEnabled)];
|
|
1789
|
+
return dom;
|
|
1790
|
+
};
|
|
1791
|
+
|
|
1792
|
+
const getVisibleSourceControlItems = (items, minLineY, maxLineY, buttons, buttonIndex) => {
|
|
1793
|
+
const visible = [];
|
|
1794
|
+
for (let i = minLineY; i < maxLineY; i++) {
|
|
1795
|
+
const item = items[i];
|
|
1796
|
+
const itemButtons = i === buttonIndex ? buttons : emptySourceControlButtons;
|
|
1797
|
+
visible.push({
|
|
1798
|
+
...item,
|
|
1799
|
+
buttons: itemButtons
|
|
1800
|
+
});
|
|
1801
|
+
}
|
|
1802
|
+
return visible;
|
|
1803
|
+
};
|
|
1804
|
+
|
|
1805
|
+
const renderItems = (oldState, newState) => {
|
|
1806
|
+
const visible = getVisibleSourceControlItems(newState.items, newState.minLineY, newState.maxLineY, newState.buttons, newState.buttonIndex);
|
|
1807
|
+
const dom = getSourceControlVirtualDom(visible, newState.splitButtonEnabled);
|
|
1808
|
+
return ['Viewlet.setDom2', dom];
|
|
1809
|
+
};
|
|
1810
|
+
|
|
1811
|
+
const getRenderer = diffType => {
|
|
1812
|
+
switch (diffType) {
|
|
1813
|
+
case RenderItems:
|
|
1814
|
+
return renderItems;
|
|
1815
|
+
default:
|
|
1816
|
+
throw new Error('unknown renderer');
|
|
1817
|
+
}
|
|
1818
|
+
};
|
|
1819
|
+
|
|
1820
|
+
const applyRender = (oldState, newState, diffResult) => {
|
|
1821
|
+
const commands = [];
|
|
1822
|
+
for (const item of diffResult) {
|
|
1823
|
+
const fn = getRenderer(item);
|
|
1824
|
+
const result = fn(oldState, newState);
|
|
1825
|
+
if (result.length > 0) {
|
|
1826
|
+
commands.push(result);
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
return commands;
|
|
1830
|
+
};
|
|
1831
|
+
|
|
1832
|
+
const render2 = (uid, diffResult) => {
|
|
1833
|
+
const {
|
|
1834
|
+
oldState,
|
|
1835
|
+
newState
|
|
1836
|
+
} = get$2(uid);
|
|
1837
|
+
set$1(uid, newState, newState);
|
|
1838
|
+
const commands = applyRender(oldState, newState, diffResult);
|
|
1839
|
+
return commands;
|
|
1840
|
+
};
|
|
1841
|
+
|
|
1842
|
+
const Button = 1;
|
|
1843
|
+
|
|
1844
|
+
const getActionButtonVirtualDom = action => {
|
|
1845
|
+
const {
|
|
1846
|
+
id,
|
|
1847
|
+
icon,
|
|
1848
|
+
command
|
|
1849
|
+
} = action;
|
|
1850
|
+
return [{
|
|
1851
|
+
type: Button$1,
|
|
1852
|
+
className: IconButton,
|
|
1853
|
+
title: id,
|
|
1854
|
+
'data-command': command,
|
|
1855
|
+
childCount: 1
|
|
1856
|
+
}, getIconVirtualDom(icon)];
|
|
1857
|
+
};
|
|
1858
|
+
|
|
1859
|
+
const getActionVirtualDom = action => {
|
|
1860
|
+
switch (action.type) {
|
|
1861
|
+
case Button:
|
|
1862
|
+
return getActionButtonVirtualDom(action);
|
|
1863
|
+
default:
|
|
1864
|
+
return [];
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
|
|
1868
|
+
const getActionsVirtualDom = actions => {
|
|
1869
|
+
return [{
|
|
1870
|
+
type: Div,
|
|
1871
|
+
className: Actions,
|
|
1872
|
+
role: ToolBar,
|
|
1873
|
+
childCount: actions.length
|
|
1874
|
+
}, ...actions.flatMap(getActionVirtualDom)];
|
|
1875
|
+
};
|
|
1876
|
+
|
|
1877
|
+
const renderActions = uid => {
|
|
1878
|
+
const actions = [];
|
|
1879
|
+
const dom = getActionsVirtualDom(actions);
|
|
1880
|
+
return dom;
|
|
1881
|
+
};
|
|
1882
|
+
|
|
1883
|
+
const renderEventListeners = () => {
|
|
1884
|
+
return [{
|
|
1885
|
+
name: HandleWheel,
|
|
1886
|
+
params: ['handleWheel', 'event.deltaMode', 'event.deltaY'],
|
|
1887
|
+
passive: true
|
|
1888
|
+
}];
|
|
1889
|
+
};
|
|
1890
|
+
|
|
1891
|
+
const saveState = uid => {
|
|
1892
|
+
number(uid);
|
|
1893
|
+
const value = get$2(uid);
|
|
1894
|
+
const {
|
|
1895
|
+
newState
|
|
1896
|
+
} = value;
|
|
1897
|
+
const {
|
|
1898
|
+
root,
|
|
1899
|
+
maxLineY
|
|
1900
|
+
} = newState;
|
|
1901
|
+
return {
|
|
1902
|
+
root,
|
|
1903
|
+
minLineY: 0,
|
|
1904
|
+
maxLineY,
|
|
1905
|
+
deltaY: 0
|
|
1906
|
+
};
|
|
1907
|
+
};
|
|
1908
|
+
|
|
1909
|
+
const terminate = () => {
|
|
1910
|
+
globalThis.close();
|
|
1911
|
+
};
|
|
1912
|
+
|
|
1913
|
+
const commandMap = {
|
|
1914
|
+
'Initialize.initialize': initialize,
|
|
1915
|
+
'SourceControl.create2': create2,
|
|
1916
|
+
'SourceControl.diff2': diff2,
|
|
1917
|
+
'SourceControl.getCommandIds': getCommandIds,
|
|
1918
|
+
'SourceControl.handleButtonClick': wrapCommand(handleButtonClick),
|
|
1919
|
+
'SourceControl.handleContextMenu': wrapCommand(handleContextMenu),
|
|
1920
|
+
'SourceControl.loadContent': wrapCommand(loadContent),
|
|
1921
|
+
'SourceControl.render2': render2,
|
|
1922
|
+
'SourceControl.renderActions2': renderActions,
|
|
1923
|
+
'SourceControl.renderEventListeners': renderEventListeners,
|
|
1924
|
+
'SourceControl.saveState': saveState,
|
|
1925
|
+
'SourceControl.terminate': terminate
|
|
1926
|
+
};
|
|
825
1927
|
|
|
826
1928
|
const listen = async () => {
|
|
827
1929
|
const rpc = await WebWorkerRpcClient.create({
|