@lvce-editor/source-control-worker 2.24.0 → 3.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.
@@ -63,7 +63,7 @@ class AssertionError extends Error {
63
63
  const Object$1 = 1;
64
64
  const Number$1 = 2;
65
65
  const Array$1 = 3;
66
- const String = 4;
66
+ const String$1 = 4;
67
67
  const Boolean$1 = 5;
68
68
  const Function = 6;
69
69
  const Null = 7;
@@ -75,7 +75,7 @@ const getType = value => {
75
75
  case 'function':
76
76
  return Function;
77
77
  case 'string':
78
- return String;
78
+ return String$1;
79
79
  case 'object':
80
80
  if (value === null) {
81
81
  return Null;
@@ -98,7 +98,7 @@ const number = value => {
98
98
  };
99
99
  const string = value => {
100
100
  const type = getType(value);
101
- if (type !== String) {
101
+ if (type !== String$1) {
102
102
  throw new AssertionError('expected value to be of type string');
103
103
  }
104
104
  };
@@ -512,56 +512,35 @@ const IpcParentWithMessagePort$1 = {
512
512
  wrap: wrap$5
513
513
  };
514
514
 
515
- const Two = '2.0';
516
- const create$4 = (method, params) => {
517
- return {
518
- jsonrpc: Two,
519
- method,
520
- params
521
- };
515
+ class CommandNotFoundError extends Error {
516
+ constructor(command) {
517
+ super(`Command not found ${command}`);
518
+ this.name = 'CommandNotFoundError';
519
+ }
520
+ }
521
+ const commands = Object.create(null);
522
+ const register = commandMap => {
523
+ Object.assign(commands, commandMap);
522
524
  };
523
- const callbacks = Object.create(null);
524
- const set$5 = (id, fn) => {
525
- callbacks[id] = fn;
525
+ const getCommand = key => {
526
+ return commands[key];
526
527
  };
528
+ const execute = (command, ...args) => {
529
+ const fn = getCommand(command);
530
+ if (!fn) {
531
+ throw new CommandNotFoundError(command);
532
+ }
533
+ return fn(...args);
534
+ };
535
+
536
+ const Two$1 = '2.0';
537
+ const callbacks = Object.create(null);
527
538
  const get$3 = id => {
528
539
  return callbacks[id];
529
540
  };
530
- const remove = id => {
541
+ const remove$1 = id => {
531
542
  delete callbacks[id];
532
543
  };
533
- let id = 0;
534
- const create$3$1 = () => {
535
- return ++id;
536
- };
537
- const registerPromise = () => {
538
- const id = create$3$1();
539
- const {
540
- resolve,
541
- promise
542
- } = Promise.withResolvers();
543
- set$5(id, resolve);
544
- return {
545
- id,
546
- promise
547
- };
548
- };
549
- const create$2$1 = (method, params) => {
550
- const {
551
- id,
552
- promise
553
- } = registerPromise();
554
- const message = {
555
- jsonrpc: Two,
556
- method,
557
- params,
558
- id
559
- };
560
- return {
561
- message,
562
- promise
563
- };
564
- };
565
544
  class JsonRpcError extends Error {
566
545
  constructor(message) {
567
546
  super(message);
@@ -578,12 +557,12 @@ const getErrorConstructor = (message, type) => {
578
557
  switch (type) {
579
558
  case DomException:
580
559
  return DOMException;
581
- case TypeError$1:
582
- return TypeError;
583
- case SyntaxError$1:
584
- return SyntaxError;
585
560
  case ReferenceError$1:
586
561
  return ReferenceError;
562
+ case SyntaxError$1:
563
+ return SyntaxError;
564
+ case TypeError$1:
565
+ return TypeError;
587
566
  default:
588
567
  return Error;
589
568
  }
@@ -712,7 +691,7 @@ const resolve = (id, response) => {
712
691
  return;
713
692
  }
714
693
  fn(response);
715
- remove(id);
694
+ remove$1(id);
716
695
  };
717
696
  const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
718
697
  const getErrorType = prettyError => {
@@ -739,27 +718,27 @@ const getErrorProperty = (error, prettyError) => {
739
718
  if (error && error.code === E_COMMAND_NOT_FOUND) {
740
719
  return {
741
720
  code: MethodNotFound,
742
- message: error.message,
743
- data: error.stack
721
+ data: error.stack,
722
+ message: error.message
744
723
  };
745
724
  }
746
725
  return {
747
726
  code: Custom,
748
- message: prettyError.message,
749
727
  data: {
750
- stack: getStack(prettyError),
751
- codeFrame: prettyError.codeFrame,
752
- type: getErrorType(prettyError),
753
728
  code: prettyError.code,
754
- name: prettyError.name
755
- }
729
+ codeFrame: prettyError.codeFrame,
730
+ name: prettyError.name,
731
+ stack: getStack(prettyError),
732
+ type: getErrorType(prettyError)
733
+ },
734
+ message: prettyError.message
756
735
  };
757
736
  };
758
737
  const create$1$1 = (id, error) => {
759
738
  return {
760
- jsonrpc: Two,
739
+ error,
761
740
  id,
762
- error
741
+ jsonrpc: Two$1
763
742
  };
764
743
  };
765
744
  const getErrorResponse = (id, error, preparePrettyError, logError) => {
@@ -768,27 +747,27 @@ const getErrorResponse = (id, error, preparePrettyError, logError) => {
768
747
  const errorProperty = getErrorProperty(error, prettyError);
769
748
  return create$1$1(id, errorProperty);
770
749
  };
771
- const create$6 = (message, result) => {
750
+ const create$8 = (message, result) => {
772
751
  return {
773
- jsonrpc: Two,
774
752
  id: message.id,
753
+ jsonrpc: Two$1,
775
754
  result: result ?? null
776
755
  };
777
756
  };
778
757
  const getSuccessResponse = (message, result) => {
779
758
  const resultProperty = result ?? null;
780
- return create$6(message, resultProperty);
759
+ return create$8(message, resultProperty);
781
760
  };
782
761
  const getErrorResponseSimple = (id, error) => {
783
762
  return {
784
- jsonrpc: Two,
785
- id,
786
763
  error: {
787
764
  code: Custom,
765
+ data: error,
788
766
  // @ts-ignore
789
- message: error.message,
790
- data: error
791
- }
767
+ message: error.message
768
+ },
769
+ id,
770
+ jsonrpc: Two$1
792
771
  };
793
772
  };
794
773
  const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
@@ -818,35 +797,35 @@ const normalizeParams = args => {
818
797
  if (args.length === 1) {
819
798
  const options = args[0];
820
799
  return {
800
+ execute: options.execute,
821
801
  ipc: options.ipc,
802
+ logError: options.logError || defaultLogError,
822
803
  message: options.message,
823
- execute: options.execute,
824
- resolve: options.resolve || defaultResolve,
825
804
  preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
826
- logError: options.logError || defaultLogError,
827
- requiresSocket: options.requiresSocket || defaultRequiresSocket
805
+ requiresSocket: options.requiresSocket || defaultRequiresSocket,
806
+ resolve: options.resolve || defaultResolve
828
807
  };
829
808
  }
830
809
  return {
810
+ execute: args[2],
831
811
  ipc: args[0],
812
+ logError: args[5],
832
813
  message: args[1],
833
- execute: args[2],
834
- resolve: args[3],
835
814
  preparePrettyError: args[4],
836
- logError: args[5],
837
- requiresSocket: args[6]
815
+ requiresSocket: args[6],
816
+ resolve: args[3]
838
817
  };
839
818
  };
840
819
  const handleJsonRpcMessage = async (...args) => {
841
820
  const options = normalizeParams(args);
842
821
  const {
843
- message,
844
- ipc,
845
822
  execute,
846
- resolve,
847
- preparePrettyError,
823
+ ipc,
848
824
  logError,
849
- requiresSocket
825
+ message,
826
+ preparePrettyError,
827
+ requiresSocket,
828
+ resolve
850
829
  } = options;
851
830
  if ('id' in message) {
852
831
  if ('method' in message) {
@@ -868,11 +847,51 @@ const handleJsonRpcMessage = async (...args) => {
868
847
  }
869
848
  throw new JsonRpcError('unexpected message');
870
849
  };
871
- const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
850
+
851
+ const Two = '2.0';
852
+
853
+ const create$7 = (method, params) => {
854
+ return {
855
+ jsonrpc: Two,
856
+ method,
857
+ params
858
+ };
859
+ };
860
+
861
+ const create$6 = (id, method, params) => {
862
+ const message = {
863
+ id,
864
+ jsonrpc: Two,
865
+ method,
866
+ params
867
+ };
868
+ return message;
869
+ };
870
+
871
+ let id = 0;
872
+ const create$5 = () => {
873
+ return ++id;
874
+ };
875
+
876
+ const registerPromise = map => {
877
+ const id = create$5();
872
878
  const {
873
- message,
879
+ promise,
880
+ resolve
881
+ } = Promise.withResolvers();
882
+ map[id] = resolve;
883
+ return {
884
+ id,
874
885
  promise
875
- } = create$2$1(method, params);
886
+ };
887
+ };
888
+
889
+ const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer) => {
890
+ const {
891
+ id,
892
+ promise
893
+ } = registerPromise(callbacks);
894
+ const message = create$6(id, method, params);
876
895
  if (useSendAndTransfer && ipc.sendAndTransfer) {
877
896
  ipc.sendAndTransfer(message);
878
897
  } else {
@@ -881,60 +900,40 @@ const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
881
900
  const responseMessage = await promise;
882
901
  return unwrapJsonRpcResult(responseMessage);
883
902
  };
884
- const send = (transport, method, ...params) => {
885
- const message = create$4(method, params);
886
- transport.send(message);
887
- };
888
- const invoke$2 = (ipc, method, ...params) => {
889
- return invokeHelper(ipc, method, params, false);
890
- };
891
- const invokeAndTransfer$1 = (ipc, method, ...params) => {
892
- return invokeHelper(ipc, method, params, true);
893
- };
894
-
895
- class CommandNotFoundError extends Error {
896
- constructor(command) {
897
- super(`Command not found ${command}`);
898
- this.name = 'CommandNotFoundError';
899
- }
900
- }
901
- const commands = Object.create(null);
902
- const register = commandMap => {
903
- Object.assign(commands, commandMap);
904
- };
905
- const getCommand = key => {
906
- return commands[key];
907
- };
908
- const execute = (command, ...args) => {
909
- const fn = getCommand(command);
910
- if (!fn) {
911
- throw new CommandNotFoundError(command);
912
- }
913
- return fn(...args);
914
- };
915
-
916
903
  const createRpc = ipc => {
904
+ const callbacks = Object.create(null);
905
+ ipc._resolve = (id, response) => {
906
+ const fn = callbacks[id];
907
+ if (!fn) {
908
+ console.warn(`callback ${id} may already be disposed`);
909
+ return;
910
+ }
911
+ fn(response);
912
+ delete callbacks[id];
913
+ };
917
914
  const rpc = {
915
+ async dispose() {
916
+ await ipc?.dispose();
917
+ },
918
+ invoke(method, ...params) {
919
+ return invokeHelper(callbacks, ipc, method, params, false);
920
+ },
921
+ invokeAndTransfer(method, ...params) {
922
+ return invokeHelper(callbacks, ipc, method, params, true);
923
+ },
918
924
  // @ts-ignore
919
925
  ipc,
920
926
  /**
921
927
  * @deprecated
922
928
  */
923
929
  send(method, ...params) {
924
- send(ipc, method, ...params);
925
- },
926
- invoke(method, ...params) {
927
- return invoke$2(ipc, method, ...params);
928
- },
929
- invokeAndTransfer(method, ...params) {
930
- return invokeAndTransfer$1(ipc, method, ...params);
931
- },
932
- async dispose() {
933
- await ipc?.dispose();
930
+ const message = create$7(method, params);
931
+ ipc.send(message);
934
932
  }
935
933
  };
936
934
  return rpc;
937
935
  };
936
+
938
937
  const requiresSocket = () => {
939
938
  return false;
940
939
  };
@@ -947,8 +946,9 @@ const logError = () => {
947
946
  const handleMessage = event => {
948
947
  const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
949
948
  const actualExecute = event?.target?.execute || execute;
950
- return handleJsonRpcMessage(event.target, event.data, actualExecute, resolve, preparePrettyError, logError, actualRequiresSocket);
949
+ return handleJsonRpcMessage(event.target, event.data, actualExecute, event.target._resolve, preparePrettyError, logError, actualRequiresSocket);
951
950
  };
951
+
952
952
  const handleIpc = ipc => {
953
953
  if ('addEventListener' in ipc) {
954
954
  ipc.addEventListener('message', handleMessage);
@@ -957,6 +957,7 @@ const handleIpc = ipc => {
957
957
  ipc.on('message', handleMessage);
958
958
  }
959
959
  };
960
+
960
961
  const listen$1 = async (module, options) => {
961
962
  const rawIpc = await module.listen(options);
962
963
  if (module.signal) {
@@ -965,15 +966,17 @@ const listen$1 = async (module, options) => {
965
966
  const ipc = module.wrap(rawIpc);
966
967
  return ipc;
967
968
  };
968
- const create$5 = async ({
969
+
970
+ const create$4 = async ({
969
971
  commandMap,
972
+ isMessagePortOpen = true,
970
973
  messagePort
971
974
  }) => {
972
975
  // TODO create a commandMap per rpc instance
973
976
  register(commandMap);
974
977
  const rawIpc = await IpcParentWithMessagePort$1.create({
975
- messagePort,
976
- isMessagePortOpen: true
978
+ isMessagePortOpen,
979
+ messagePort
977
980
  });
978
981
  const ipc = IpcParentWithMessagePort$1.wrap(rawIpc);
979
982
  handleIpc(ipc);
@@ -981,12 +984,10 @@ const create$5 = async ({
981
984
  messagePort.start();
982
985
  return rpc;
983
986
  };
984
- const PlainMessagePortRpc = {
985
- __proto__: null,
986
- create: create$5
987
- };
987
+
988
988
  const create$3 = async ({
989
989
  commandMap,
990
+ isMessagePortOpen,
990
991
  send
991
992
  }) => {
992
993
  const {
@@ -994,15 +995,13 @@ const create$3 = async ({
994
995
  port2
995
996
  } = new MessageChannel();
996
997
  await send(port1);
997
- return create$5({
998
+ return create$4({
998
999
  commandMap,
1000
+ isMessagePortOpen,
999
1001
  messagePort: port2
1000
1002
  });
1001
1003
  };
1002
- const TransferMessagePortRpcParent = {
1003
- __proto__: null,
1004
- create: create$3
1005
- };
1004
+
1006
1005
  const create$2 = async ({
1007
1006
  commandMap
1008
1007
  }) => {
@@ -1013,16 +1012,96 @@ const create$2 = async ({
1013
1012
  const rpc = createRpc(ipc);
1014
1013
  return rpc;
1015
1014
  };
1016
- const WebWorkerRpcClient = {
1017
- __proto__: null,
1018
- create: create$2
1015
+
1016
+ const createMockRpc = ({
1017
+ commandMap
1018
+ }) => {
1019
+ const invocations = [];
1020
+ const invoke = (method, ...params) => {
1021
+ invocations.push([method, ...params]);
1022
+ const command = commandMap[method];
1023
+ if (!command) {
1024
+ throw new Error(`command ${method} not found`);
1025
+ }
1026
+ return command(...params);
1027
+ };
1028
+ const mockRpc = {
1029
+ invocations,
1030
+ invoke,
1031
+ invokeAndTransfer: invoke
1032
+ };
1033
+ return mockRpc;
1034
+ };
1035
+
1036
+ const rpcs = Object.create(null);
1037
+ const set$5 = (id, rpc) => {
1038
+ rpcs[id] = rpc;
1039
+ };
1040
+ const get$2 = id => {
1041
+ return rpcs[id];
1042
+ };
1043
+ const remove = id => {
1044
+ delete rpcs[id];
1045
+ };
1046
+
1047
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
1048
+ const create$1 = rpcId => {
1049
+ return {
1050
+ async dispose() {
1051
+ const rpc = get$2(rpcId);
1052
+ await rpc.dispose();
1053
+ },
1054
+ // @ts-ignore
1055
+ invoke(method, ...params) {
1056
+ const rpc = get$2(rpcId);
1057
+ // @ts-ignore
1058
+ return rpc.invoke(method, ...params);
1059
+ },
1060
+ // @ts-ignore
1061
+ invokeAndTransfer(method, ...params) {
1062
+ const rpc = get$2(rpcId);
1063
+ // @ts-ignore
1064
+ return rpc.invokeAndTransfer(method, ...params);
1065
+ },
1066
+ registerMockRpc(commandMap) {
1067
+ const mockRpc = createMockRpc({
1068
+ commandMap
1069
+ });
1070
+ set$5(rpcId, mockRpc);
1071
+ // @ts-ignore
1072
+ mockRpc[Symbol.dispose] = () => {
1073
+ remove(rpcId);
1074
+ };
1075
+ // @ts-ignore
1076
+ return mockRpc;
1077
+ },
1078
+ set(rpc) {
1079
+ set$5(rpcId, rpc);
1080
+ }
1081
+ };
1019
1082
  };
1020
1083
 
1084
+ const None$1 = 'none';
1085
+ const ToolBar = 'toolbar';
1086
+ const Tree$1 = 'tree';
1087
+ const TreeItem$1 = 'treeitem';
1088
+
1089
+ const Badge = 'Badge';
1090
+ const SourceControlBadge = 'SourceControlBadge';
1091
+
1021
1092
  const Directory = 3;
1022
1093
  const DirectoryExpanded = 4;
1023
1094
  const File = 7;
1024
1095
 
1025
- const Button$2 = 'event.button';
1096
+ const Button$2 = 1;
1097
+ const Div = 4;
1098
+ const Span = 8;
1099
+ const Text = 12;
1100
+ const Img = 17;
1101
+ const TextArea = 62;
1102
+ const Reference = 100;
1103
+
1104
+ const Button$1 = 'event.button';
1026
1105
  const ClientX = 'event.clientX';
1027
1106
  const ClientY = 'event.clientY';
1028
1107
  const DeltaMode = 'event.deltaMode';
@@ -1030,14 +1109,19 @@ const DeltaY = 'event.deltaY';
1030
1109
  const TargetName = 'event.target.name';
1031
1110
  const TargetValue = 'event.target.value';
1032
1111
 
1112
+ const Enter = 3;
1113
+
1033
1114
  const User = 1;
1034
1115
  const Script = 2;
1035
1116
 
1117
+ const CtrlCmd = 1 << 11 >>> 0;
1118
+
1036
1119
  const SourceControl$1 = 22;
1037
1120
 
1038
- const None$1 = 0;
1121
+ const None = 0;
1039
1122
 
1040
1123
  const ExtensionHostWorker = 44;
1124
+ const ExtensionManagementWorker = 9006;
1041
1125
  const IconThemeWorker = 7009;
1042
1126
  const RendererWorker = 1;
1043
1127
  const SourceControlWorker = 66;
@@ -1048,47 +1132,19 @@ const SetFocusContext = 'Viewlet.setFocusContext';
1048
1132
  const SetValueByName = 'Viewlet.setValueByName';
1049
1133
 
1050
1134
  const List = 1;
1051
- const Tree$1 = 2;
1135
+ const Tree = 2;
1052
1136
 
1053
1137
  const FocusSourceControlInput = 24;
1054
1138
 
1055
- const rpcs = Object.create(null);
1056
- const set$4 = (id, rpc) => {
1057
- rpcs[id] = rpc;
1058
- };
1059
- const get$2 = id => {
1060
- return rpcs[id];
1061
- };
1062
-
1063
- const create$1 = rpcId => {
1064
- return {
1065
- async dispose() {
1066
- const rpc = get$2(rpcId);
1067
- await rpc.dispose();
1068
- },
1069
- // @ts-ignore
1070
- invoke(method, ...params) {
1071
- const rpc = get$2(rpcId);
1072
- // @ts-ignore
1073
- return rpc.invoke(method, ...params);
1074
- },
1075
- // @ts-ignore
1076
- invokeAndTransfer(method, ...params) {
1077
- const rpc = get$2(rpcId);
1078
- // @ts-ignore
1079
- return rpc.invokeAndTransfer(method, ...params);
1080
- },
1081
- set(rpc) {
1082
- set$4(rpcId, rpc);
1083
- }
1084
- };
1085
- };
1086
-
1087
1139
  const {
1088
1140
  invoke: invoke$1,
1089
- set: set$3
1141
+ set: set$4
1090
1142
  } = create$1(ExtensionHostWorker);
1091
1143
 
1144
+ const {
1145
+ set: set$3
1146
+ } = create$1(ExtensionManagementWorker);
1147
+
1092
1148
  const {
1093
1149
  invoke,
1094
1150
  invokeAndTransfer,
@@ -1099,7 +1155,6 @@ const showContextMenu2 = async (uid, menuId, x, y, args) => {
1099
1155
  number(menuId);
1100
1156
  number(x);
1101
1157
  number(y);
1102
- // @ts-ignore
1103
1158
  await invoke('ContextMenu.show2', uid, menuId, x, y, args);
1104
1159
  };
1105
1160
  const readFile$1 = async uri => {
@@ -1114,9 +1169,12 @@ const activateByEvent$1 = (event, assetDir, platform) => {
1114
1169
  };
1115
1170
  const sendMessagePortToTextMeasurementWorker$1 = async port => {
1116
1171
  const command = 'TextMeasurement.handleMessagePort';
1117
- // @ts-ignore
1118
1172
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToTextMeasurementWorker', port, command, 0);
1119
1173
  };
1174
+ const sendMessagePortToExtensionManagementWorker = async (port, rpcId) => {
1175
+ const command = 'Extensions.handleMessagePort';
1176
+ await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionManagementWorker', port, command, rpcId);
1177
+ };
1120
1178
  const getPreference = async key => {
1121
1179
  return await invoke('Preferences.get', key);
1122
1180
  };
@@ -1136,42 +1194,68 @@ const create = () => {
1136
1194
  const states = Object.create(null);
1137
1195
  const commandMapRef = {};
1138
1196
  return {
1139
- get(uid) {
1140
- return states[uid];
1197
+ clear() {
1198
+ for (const key of Object.keys(states)) {
1199
+ delete states[key];
1200
+ }
1141
1201
  },
1142
- set(uid, oldState, newState) {
1143
- states[uid] = {
1144
- oldState,
1145
- newState
1146
- };
1202
+ diff(uid, modules, numbers) {
1203
+ const {
1204
+ newState,
1205
+ oldState
1206
+ } = states[uid];
1207
+ const diffResult = [];
1208
+ for (let i = 0; i < modules.length; i++) {
1209
+ const fn = modules[i];
1210
+ if (!fn(oldState, newState)) {
1211
+ diffResult.push(numbers[i]);
1212
+ }
1213
+ }
1214
+ return diffResult;
1147
1215
  },
1148
1216
  dispose(uid) {
1149
1217
  delete states[uid];
1150
1218
  },
1219
+ get(uid) {
1220
+ return states[uid];
1221
+ },
1222
+ getCommandIds() {
1223
+ const keys = Object.keys(commandMapRef);
1224
+ const ids = keys.map(toCommandId);
1225
+ return ids;
1226
+ },
1151
1227
  getKeys() {
1152
1228
  return Object.keys(states).map(key => {
1153
- return Number.parseInt(key);
1229
+ return Number.parseFloat(key);
1154
1230
  });
1155
1231
  },
1156
- clear() {
1157
- for (const key of Object.keys(states)) {
1158
- delete states[key];
1159
- }
1232
+ registerCommands(commandMap) {
1233
+ Object.assign(commandMapRef, commandMap);
1234
+ },
1235
+ set(uid, oldState, newState) {
1236
+ states[uid] = {
1237
+ newState,
1238
+ oldState
1239
+ };
1160
1240
  },
1161
1241
  wrapCommand(fn) {
1162
1242
  const wrapped = async (uid, ...args) => {
1163
1243
  const {
1164
- oldState,
1165
- newState
1244
+ newState,
1245
+ oldState
1166
1246
  } = states[uid];
1167
1247
  const newerState = await fn(newState, ...args);
1168
1248
  if (oldState === newerState || newState === newerState) {
1169
1249
  return;
1170
1250
  }
1171
- const latest = states[uid];
1251
+ const latestOld = states[uid];
1252
+ const latestNew = {
1253
+ ...latestOld.newState,
1254
+ ...newerState
1255
+ };
1172
1256
  states[uid] = {
1173
- oldState: latest.oldState,
1174
- newState: newerState
1257
+ newState: latestNew,
1258
+ oldState: latestOld.oldState
1175
1259
  };
1176
1260
  };
1177
1261
  return wrapped;
@@ -1185,27 +1269,36 @@ const create = () => {
1185
1269
  };
1186
1270
  return wrapped;
1187
1271
  },
1188
- diff(uid, modules, numbers) {
1189
- const {
1190
- oldState,
1191
- newState
1192
- } = states[uid];
1193
- const diffResult = [];
1194
- for (let i = 0; i < modules.length; i++) {
1195
- const fn = modules[i];
1196
- if (!fn(oldState, newState)) {
1197
- diffResult.push(numbers[i]);
1272
+ wrapLoadContent(fn) {
1273
+ const wrapped = async (uid, ...args) => {
1274
+ const {
1275
+ newState,
1276
+ oldState
1277
+ } = states[uid];
1278
+ const result = await fn(newState, ...args);
1279
+ const {
1280
+ error,
1281
+ state
1282
+ } = result;
1283
+ if (oldState === state || newState === state) {
1284
+ return {
1285
+ error
1286
+ };
1198
1287
  }
1199
- }
1200
- return diffResult;
1201
- },
1202
- getCommandIds() {
1203
- const keys = Object.keys(commandMapRef);
1204
- const ids = keys.map(toCommandId);
1205
- return ids;
1206
- },
1207
- registerCommands(commandMap) {
1208
- Object.assign(commandMapRef, commandMap);
1288
+ const latestOld = states[uid];
1289
+ const latestNew = {
1290
+ ...latestOld.newState,
1291
+ ...state
1292
+ };
1293
+ states[uid] = {
1294
+ newState: latestNew,
1295
+ oldState: latestOld.oldState
1296
+ };
1297
+ return {
1298
+ error
1299
+ };
1300
+ };
1301
+ return wrapped;
1209
1302
  }
1210
1303
  };
1211
1304
  };
@@ -1248,7 +1341,7 @@ const getDisplayItemsGroup = (group, expandedGroups, iconDefinitions) => {
1248
1341
  const {
1249
1342
  length
1250
1343
  } = items;
1251
- const isExpanded = expandedGroups[id] || false;
1344
+ const isExpanded = expandedGroups[id] ?? false;
1252
1345
  const type = isExpanded ? DirectoryExpanded : Directory;
1253
1346
  const icon = isExpanded ? 'ChevronDown' : 'ChevronRight';
1254
1347
  if (length > 0) {
@@ -1387,9 +1480,13 @@ const executeProvider = async ({
1387
1480
 
1388
1481
  const CommandExecute = 'ExtensionHostCommand.executeCommand';
1389
1482
  const SourceControlAcceptInput = 'ExtensionHostSourceControl.acceptInput';
1483
+ const SourceControlGenerateCommitMessage = 'ExtensionHostSourceControl.generateCommitMessage';
1484
+ const SourceControlGetBadgeCount = 'ExtensionHostSourceControl.getBadgeCount';
1485
+ const SourceControlGetChangedFiles = 'ExtensionHost.sourceControlGetChangedFiles';
1390
1486
  const SourceControlGetFileDecorations = 'ExtensionHostSourceControl.getFileDecorations';
1391
1487
  const SourceControlGetEnabledProviderIds = 'ExtensionHostSourceControl.getEnabledProviderIds';
1392
1488
  const SourceControlGetFileBefore = 'ExtensionHostSourceControl.getFileBefore';
1489
+ const SourceControlGetFeatures = 'ExtensionHostSourceControl.getFeatures';
1393
1490
  const SourceControlGetGroups = 'ExtensionHostSourceControl.getGroups';
1394
1491
 
1395
1492
  const acceptInput$2 = async (providerId, text, assetDir, platform) => {
@@ -1402,6 +1499,43 @@ const acceptInput$2 = async (providerId, text, assetDir, platform) => {
1402
1499
  // noProviderFoundMessage: 'No source control provider found',
1403
1500
  });
1404
1501
  };
1502
+ const generateCommitMessage$2 = async (providerId, assetDir, platform) => {
1503
+ return executeProvider({
1504
+ assetDir,
1505
+ event: 'none',
1506
+ method: SourceControlGenerateCommitMessage,
1507
+ params: [providerId],
1508
+ platform
1509
+ });
1510
+ };
1511
+ const getFeatures = async (providerId, assetDir, platform) => {
1512
+ return executeProvider({
1513
+ assetDir,
1514
+ event: 'none',
1515
+ method: SourceControlGetFeatures,
1516
+ params: [providerId],
1517
+ platform
1518
+ });
1519
+ };
1520
+ const getChangedFiles = (providerId, assetDir, platform) => {
1521
+ return executeProvider({
1522
+ assetDir,
1523
+ event: 'none',
1524
+ method: SourceControlGetChangedFiles,
1525
+ params: [providerId],
1526
+ platform
1527
+ // noProviderFoundMessage: 'No source control provider found',
1528
+ });
1529
+ };
1530
+ const getBadgeCount$2 = (providerId, assetDir, platform) => {
1531
+ return executeProvider({
1532
+ assetDir,
1533
+ event: 'none',
1534
+ method: SourceControlGetBadgeCount,
1535
+ params: [providerId],
1536
+ platform
1537
+ });
1538
+ };
1405
1539
  const getFileDecorations$1 = (providerId, uris, assetDir, platform) => {
1406
1540
  string(assetDir);
1407
1541
  number(platform);
@@ -1449,11 +1583,68 @@ const getIconDefinitions$1 = async providerId => {
1449
1583
  return result;
1450
1584
  };
1451
1585
 
1586
+ const Disk = 'file';
1587
+
1588
+ const RE_PROTOCOL = /^([a-z-]+):\/\//;
1589
+ const getProtocol = uri => {
1590
+ if (!uri) {
1591
+ return Disk;
1592
+ }
1593
+ const protocolMatch = uri.match(RE_PROTOCOL);
1594
+ if (protocolMatch) {
1595
+ return protocolMatch[1];
1596
+ }
1597
+ return Disk;
1598
+ };
1599
+
1452
1600
  const acceptInput$1 = (providerId, text, assetDir, platform) => {
1453
1601
  string(providerId);
1454
1602
  string(text);
1455
1603
  return acceptInput$2(providerId, text, assetDir, platform);
1456
1604
  };
1605
+ const generateCommitMessage$1 = (providerId, assetDir, platform) => {
1606
+ string(providerId);
1607
+ return generateCommitMessage$2(providerId, assetDir, platform);
1608
+ };
1609
+ const getShowGenerateCommitMessageButton = async (providerId, assetDir, platform) => {
1610
+ string(providerId);
1611
+ try {
1612
+ const features = await getFeatures(providerId, assetDir, platform);
1613
+ if (!features || typeof features !== 'object') {
1614
+ return true;
1615
+ }
1616
+ if ('showGenerateCommitMessageButton' in features && typeof features.showGenerateCommitMessageButton === 'boolean') {
1617
+ return features.showGenerateCommitMessageButton;
1618
+ }
1619
+ return true;
1620
+ } catch {
1621
+ return true;
1622
+ }
1623
+ };
1624
+ const getProviderBadgeCount = async (providerId, assetDir, platform) => {
1625
+ try {
1626
+ return await getBadgeCount$2(providerId, assetDir, platform);
1627
+ } catch {
1628
+ try {
1629
+ const changedFiles = await getChangedFiles(providerId, assetDir, platform);
1630
+ return changedFiles.length;
1631
+ } catch {
1632
+ return 0;
1633
+ }
1634
+ }
1635
+ };
1636
+ const getBadgeCount$1 = async (providerIds, assetDir, platform) => {
1637
+ let badgeCount = 0;
1638
+ for (const providerId of providerIds) {
1639
+ badgeCount += await getProviderBadgeCount(providerId, assetDir, platform);
1640
+ }
1641
+ return badgeCount;
1642
+ };
1643
+ const getWorkspaceBadgeCount = async (root, assetDir, platform) => {
1644
+ const scheme = getProtocol(root);
1645
+ const providerIds = await getEnabledProviderIds(scheme, root, assetDir, platform);
1646
+ return getBadgeCount$1(providerIds, assetDir, platform);
1647
+ };
1457
1648
  const getFileDecorations = (providerId, uris, assetDir, platform) => {
1458
1649
  return getFileDecorations$1(providerId, uris, assetDir, platform);
1459
1650
  };
@@ -1491,6 +1682,12 @@ const getGroups = async (enabledProviderIds, root, assetDir, platform) => {
1491
1682
  };
1492
1683
  };
1493
1684
 
1685
+ const inputPaddingBlock = 11;
1686
+ const buttonBlockHeight = 34;
1687
+ const getHeaderHeight = (inputBoxHeight, sourceControlButtons) => {
1688
+ return inputBoxHeight + inputPaddingBlock + sourceControlButtons.length * buttonBlockHeight;
1689
+ };
1690
+
1494
1691
  const getTextHeight = async (input, width, fontFamily, fontSize, fontWeight, letterSpacing, lineHeight, inputPadding) => {
1495
1692
  try {
1496
1693
  if (!input) {
@@ -1521,31 +1718,17 @@ const getListHeight = (itemsLength, itemHeight, maxHeight) => {
1521
1718
  number(itemHeight);
1522
1719
  number(maxHeight);
1523
1720
  if (itemsLength === 0) {
1524
- return itemHeight;
1525
- }
1526
- const totalHeight = itemsLength * itemHeight;
1527
- return Math.min(totalHeight, maxHeight);
1528
- };
1529
-
1530
- // TODO optimize this function to return the minimum number
1531
- // of visible items needed, e.g. when not scrolled 5 items with
1532
- // 20px fill 100px but when scrolled 6 items are needed
1533
- const getNumberOfVisibleItems = (listHeight, itemHeight) => {
1534
- return Math.ceil(listHeight / itemHeight) + 1;
1535
- };
1536
-
1537
- const Disk = 'file';
1538
-
1539
- const RE_PROTOCOL = /^([a-z-]+):\/\//;
1540
- const getProtocol = uri => {
1541
- if (!uri) {
1542
- return Disk;
1543
- }
1544
- const protocolMatch = uri.match(RE_PROTOCOL);
1545
- if (protocolMatch) {
1546
- return protocolMatch[1];
1721
+ return itemHeight;
1547
1722
  }
1548
- return Disk;
1723
+ const totalHeight = itemsLength * itemHeight;
1724
+ return Math.min(totalHeight, maxHeight);
1725
+ };
1726
+
1727
+ // TODO optimize this function to return the minimum number
1728
+ // of visible items needed, e.g. when not scrolled 5 items with
1729
+ // 20px fill 100px but when scrolled 6 items are needed
1730
+ const getNumberOfVisibleItems = (listHeight, itemHeight) => {
1731
+ return Math.ceil(listHeight / itemHeight) + 1;
1549
1732
  };
1550
1733
 
1551
1734
  const emptySourceControlButtons = [];
@@ -1596,15 +1779,29 @@ const requestSourceActions = async () => {
1596
1779
  const extensions = await getExtensions();
1597
1780
  const newCache = Object.create(null);
1598
1781
  for (const extension of extensions) {
1599
- if (extension && extension['source-control-actions']) {
1600
- for (const [key, value] of Object.entries(extension['source-control-actions'])) {
1601
- newCache[key] = value;
1602
- }
1782
+ if (!extension || !extension['source-control-actions']) {
1783
+ continue;
1784
+ }
1785
+ const sourceControlActions = Object.entries(extension['source-control-actions']);
1786
+ for (const [key, value] of sourceControlActions) {
1787
+ newCache[key] = value;
1603
1788
  }
1604
1789
  }
1605
1790
  return newCache;
1606
1791
  };
1607
1792
 
1793
+ const requestSourceControlButtons = async () => {
1794
+ const extensions = await getExtensions();
1795
+ const buttons = [];
1796
+ for (const extension of extensions) {
1797
+ if (!extension || !Array.isArray(extension['source-control-buttons'])) {
1798
+ continue;
1799
+ }
1800
+ buttons.push(...extension['source-control-buttons']);
1801
+ }
1802
+ return buttons;
1803
+ };
1804
+
1608
1805
  /* eslint-disable unicorn/no-array-reduce */
1609
1806
  const restoreExpandedGroups = groups => {
1610
1807
  return groups.map(group => group.id).reduce((total, current) => {
@@ -1657,6 +1854,7 @@ const RevealInExplorerView = 'Reveal in Explorer View';
1657
1854
  const OpenContainingFolder = 'Open Containing Folder';
1658
1855
  const ViewAsTree$1 = 'View As Tree';
1659
1856
  const CommitAndPush$1 = 'Commit and Push';
1857
+ const GenerateCommitMessage$1 = 'Generate Commit Message';
1660
1858
  const Refresh$2 = 'Refresh';
1661
1859
  const MessageEnterToCommitOnMaster = `Message (Enter) to commit on 'master'`;
1662
1860
  const SourceControlInput$1 = 'Source Control Input';
@@ -1691,6 +1889,9 @@ const viewAsTree$1 = () => {
1691
1889
  const commitAndPush = () => {
1692
1890
  return i18nString(CommitAndPush$1);
1693
1891
  };
1892
+ const generateCommitMessage = () => {
1893
+ return i18nString(GenerateCommitMessage$1);
1894
+ };
1694
1895
  const refresh$1 = () => {
1695
1896
  return i18nString(Refresh$2);
1696
1897
  };
@@ -1726,6 +1927,7 @@ const loadContent = async (state, savedState) => {
1726
1927
  platform
1727
1928
  } = state;
1728
1929
  const enabledProviderIds = await getEnabledProviderIds(scheme, root, assetDir, platform);
1930
+ const showGenerateCommitMessageButton = enabledProviderIds.length === 0 ? false : await getShowGenerateCommitMessageButton(enabledProviderIds[0], assetDir, platform);
1729
1931
  const iconDefinitions = await getIconDefinitions(enabledProviderIds);
1730
1932
  const {
1731
1933
  allGroups,
@@ -1734,10 +1936,11 @@ const loadContent = async (state, savedState) => {
1734
1936
  const expandedGroups = restoreExpandedGroups(allGroups);
1735
1937
  const displayItems = getDisplayItems(allGroups, expandedGroups, iconDefinitions);
1736
1938
  const actionsCache = await requestSourceActions();
1939
+ const sourceControlButtons = await requestSourceControlButtons();
1737
1940
 
1738
1941
  // TODO make preferences async and more functional
1739
1942
  const splitButtonEnabled = await get$1('sourceControl.splitButtonEnabled');
1740
- const badgeCount = allGroups.reduce((sum, group) => sum + group.items.length, 0);
1943
+ const badgeCount = await getBadgeCount$1(enabledProviderIds, assetDir, platform);
1741
1944
  const total = displayItems.length;
1742
1945
  const contentHeight = total * itemHeight;
1743
1946
  const listHeight = getListHeight(total, itemHeight, height);
@@ -1750,6 +1953,7 @@ const loadContent = async (state, savedState) => {
1750
1953
  const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, total);
1751
1954
  const inputPlaceholder = messageEnterToCommitOnMaster();
1752
1955
  const inputBoxHeight = await getInputHeight(inputValue, width, inputFontFamily, inputFontSize, inputFontWeight, inputLetterSpacing, inputLineHeight, inputPadding);
1956
+ const headerHeight = getHeaderHeight(inputBoxHeight, sourceControlButtons);
1753
1957
  return {
1754
1958
  ...state,
1755
1959
  actionsCache,
@@ -1760,7 +1964,9 @@ const loadContent = async (state, savedState) => {
1760
1964
  fileIconCache: newFileIconCache,
1761
1965
  finalDeltaY,
1762
1966
  gitRoot,
1967
+ headerHeight,
1763
1968
  iconDefinitions,
1969
+ initial: false,
1764
1970
  inputBoxHeight,
1765
1971
  inputPlaceholder,
1766
1972
  inputValue,
@@ -1768,6 +1974,8 @@ const loadContent = async (state, savedState) => {
1768
1974
  maxLineY,
1769
1975
  root,
1770
1976
  scrollBarHeight,
1977
+ showGenerateCommitMessageButton,
1978
+ sourceControlButtons,
1771
1979
  splitButtonEnabled,
1772
1980
  visibleItems
1773
1981
  };
@@ -1794,15 +2002,76 @@ const acceptInput = async state => {
1794
2002
  info('[ViewletSourceControl] no source control provider found');
1795
2003
  return state;
1796
2004
  }
1797
- const providerId = enabledProviderIds[0];
1798
- await acceptInput$1(providerId, inputValue, assetDir, platform);
2005
+ for (const providerId of enabledProviderIds) {
2006
+ await acceptInput$1(providerId, inputValue, assetDir, platform);
2007
+ }
1799
2008
  const newState = await loadContent(state, {});
1800
2009
  return {
1801
2010
  ...newState,
2011
+ inputMessage: '',
1802
2012
  inputValue: ''
1803
2013
  };
1804
2014
  };
1805
2015
 
2016
+ const createDefaultState = () => ({
2017
+ actionsCache: Object.create(null),
2018
+ allGroups: [],
2019
+ assetDir: '',
2020
+ badgeCount: 0,
2021
+ decorationIcons: [],
2022
+ deltaY: 0,
2023
+ enabledProviderIds: [],
2024
+ expandedGroups: Object.create(null),
2025
+ fileIconCache: {},
2026
+ finalDeltaY: 0,
2027
+ focus: 0,
2028
+ gitRoot: '',
2029
+ handleOffset: 0,
2030
+ headerHeight: 40,
2031
+ height: 100,
2032
+ history: [],
2033
+ iconDefinitions: [],
2034
+ id: 1,
2035
+ index: [],
2036
+ initial: false,
2037
+ inputBoxHeight: 30,
2038
+ inputBoxMaxHeight: 214,
2039
+ inputFontFamily: '',
2040
+ inputFontSize: 15,
2041
+ inputFontWeight: 400,
2042
+ inputLetterSpacing: 0.5,
2043
+ inputLineHeight: 14.95,
2044
+ inputMessage: '',
2045
+ inputPadding: 2,
2046
+ inputPlaceholder: '',
2047
+ inputSource: 0,
2048
+ inputValue: '',
2049
+ isVisible: true,
2050
+ itemHeight: 20,
2051
+ items: [],
2052
+ maxInputLines: 5,
2053
+ maxLineY: 0,
2054
+ merge: [],
2055
+ minimumSliderSize: 30,
2056
+ minLineY: 0,
2057
+ platform: 0,
2058
+ providerId: '',
2059
+ root: '/',
2060
+ scrollBarActive: false,
2061
+ scrollBarHeight: 0,
2062
+ showGenerateCommitMessageButton: false,
2063
+ sourceControlButtons: [],
2064
+ splitButtonEnabled: false,
2065
+ untracked: [],
2066
+ viewMode: 1,
2067
+ visibleItems: [],
2068
+ width: 100,
2069
+ workingTree: [],
2070
+ workspacePath: '',
2071
+ x: 0,
2072
+ y: 0
2073
+ });
2074
+
1806
2075
  const {
1807
2076
  get,
1808
2077
  getCommandIds,
@@ -1812,58 +2081,16 @@ const {
1812
2081
  wrapGetter
1813
2082
  } = create();
1814
2083
 
1815
- const create2 = (id, uri, x, y, width, height, workspacePath, platform, assetDir) => {
2084
+ const create2 = (id, _uri, x, y, width, height, workspacePath, platform, assetDir) => {
2085
+ const defaultState = createDefaultState();
1816
2086
  const state = {
1817
- actionsCache: Object.create(null),
1818
- allGroups: [],
2087
+ ...defaultState,
1819
2088
  assetDir,
1820
- badgeCount: 0,
1821
- decorationIcons: [],
1822
- deltaY: 0,
1823
- enabledProviderIds: [],
1824
- expandedGroups: Object.create(null),
1825
- fileIconCache: Object.create(null),
1826
- finalDeltaY: 0,
1827
- focus: 0,
1828
- gitRoot: '',
1829
- handleOffset: 0,
1830
- headerHeight: 40,
1831
- // TODO
1832
2089
  height,
1833
- history: [],
1834
- iconDefinitions: [],
1835
2090
  id,
1836
- index: [],
1837
- inputBoxHeight: 30,
1838
- inputBoxMaxHeight: 214,
1839
- inputFontFamily: 'system-ui, Ubuntu, "Droid Sans", sans-serif',
1840
- inputFontSize: 13,
1841
- inputFontWeight: 400,
1842
- inputLetterSpacing: 0,
1843
- inputLineHeight: 20,
1844
- inputPadding: 2,
1845
- inputPlaceholder: '',
1846
- inputSource: 0,
1847
- inputValue: '',
1848
- isVisible: true,
1849
- itemHeight: 20,
1850
- items: [],
1851
- maxInputLines: 5,
1852
- maxLineY: 0,
1853
- merge: [],
1854
- minimumSliderSize: 20,
1855
- minLineY: 0,
2091
+ initial: true,
1856
2092
  platform,
1857
- providerId: '',
1858
- root: '',
1859
- scrollBarActive: false,
1860
- scrollBarHeight: 0,
1861
- splitButtonEnabled: false,
1862
- untracked: [],
1863
- viewMode: 1,
1864
- visibleItems: [],
1865
2093
  width,
1866
- workingTree: [],
1867
2094
  workspacePath,
1868
2095
  x,
1869
2096
  y
@@ -1880,20 +2107,21 @@ const isEqual$2 = (oldState, newState) => {
1880
2107
  };
1881
2108
 
1882
2109
  const isEqual$1 = (oldState, newState) => {
1883
- return oldState.allGroups === newState.allGroups && oldState.deltaY === newState.deltaY && oldState.items === newState.items && oldState.maxLineY === newState.maxLineY && oldState.minLineY === newState.minLineY && oldState.visibleItems === newState.visibleItems;
2110
+ return oldState.allGroups === newState.allGroups && oldState.deltaY === newState.deltaY && oldState.items === newState.items && oldState.maxLineY === newState.maxLineY && oldState.minLineY === newState.minLineY && oldState.sourceControlButtons === newState.sourceControlButtons && oldState.visibleItems === newState.visibleItems;
1884
2111
  };
1885
2112
 
1886
2113
  const RenderItems = 4;
1887
2114
  const RenderFocusContext = 7;
1888
2115
  const RenderValue = 8;
1889
2116
  const RenderCss = 10;
2117
+ const RenderIncremental = 11;
1890
2118
 
1891
2119
  const isEqual = (oldState, newState) => {
1892
2120
  return newState.inputSource === User || oldState.inputValue === newState.inputValue;
1893
2121
  };
1894
2122
 
1895
2123
  const modules = [isEqual$1, isEqual, isEqual$3, isEqual$2];
1896
- const numbers = [RenderItems, RenderValue, RenderCss, RenderFocusContext];
2124
+ const numbers = [RenderIncremental, RenderValue, RenderCss, RenderFocusContext];
1897
2125
 
1898
2126
  const diff = (oldState, newState) => {
1899
2127
  const diffResult = [];
@@ -1928,37 +2156,305 @@ const getInfo = uid => {
1928
2156
  return newState.allGroups;
1929
2157
  };
1930
2158
 
1931
- const None = 'none';
1932
- const ToolBar = 'toolbar';
1933
- const Tree = 'tree';
1934
- const TreeItem$1 = 'treeitem';
1935
-
1936
- const Badge = 'Badge';
1937
- const SourceControlBadge = 'SourceControlBadge';
1938
-
1939
- const Button$1 = 1;
1940
- const Div = 4;
1941
- const Span = 8;
1942
- const Text = 12;
1943
- const Img = 17;
1944
- const TextArea = 62;
1945
-
1946
- const Enter = 3;
1947
-
1948
- const CtrlCmd = 1 << 11 >>> 0;
1949
-
1950
2159
  const mergeClassNames = (...classNames) => {
1951
2160
  return classNames.filter(Boolean).join(' ');
1952
2161
  };
1953
2162
 
1954
2163
  const text = data => {
1955
2164
  return {
1956
- type: Text,
2165
+ childCount: 0,
1957
2166
  text: data,
1958
- childCount: 0
2167
+ type: Text
2168
+ };
2169
+ };
2170
+
2171
+ const SetText = 1;
2172
+ const Replace = 2;
2173
+ const SetAttribute = 3;
2174
+ const RemoveAttribute = 4;
2175
+ const Add = 6;
2176
+ const NavigateChild = 7;
2177
+ const NavigateParent = 8;
2178
+ const RemoveChild = 9;
2179
+ const NavigateSibling = 10;
2180
+ const SetReferenceNodeUid = 11;
2181
+
2182
+ const isKey = key => {
2183
+ return key !== 'type' && key !== 'childCount';
2184
+ };
2185
+
2186
+ const getKeys = node => {
2187
+ const keys = Object.keys(node).filter(isKey);
2188
+ return keys;
2189
+ };
2190
+
2191
+ const arrayToTree = nodes => {
2192
+ const result = [];
2193
+ let i = 0;
2194
+ while (i < nodes.length) {
2195
+ const node = nodes[i];
2196
+ const {
2197
+ children,
2198
+ nodesConsumed
2199
+ } = getChildrenWithCount(nodes, i + 1, node.childCount || 0);
2200
+ result.push({
2201
+ node,
2202
+ children
2203
+ });
2204
+ i += 1 + nodesConsumed;
2205
+ }
2206
+ return result;
2207
+ };
2208
+ const getChildrenWithCount = (nodes, startIndex, childCount) => {
2209
+ if (childCount === 0) {
2210
+ return {
2211
+ children: [],
2212
+ nodesConsumed: 0
2213
+ };
2214
+ }
2215
+ const children = [];
2216
+ let i = startIndex;
2217
+ let remaining = childCount;
2218
+ let totalConsumed = 0;
2219
+ while (remaining > 0 && i < nodes.length) {
2220
+ const node = nodes[i];
2221
+ const nodeChildCount = node.childCount || 0;
2222
+ const {
2223
+ children: nodeChildren,
2224
+ nodesConsumed
2225
+ } = getChildrenWithCount(nodes, i + 1, nodeChildCount);
2226
+ children.push({
2227
+ node,
2228
+ children: nodeChildren
2229
+ });
2230
+ const nodeSize = 1 + nodesConsumed;
2231
+ i += nodeSize;
2232
+ totalConsumed += nodeSize;
2233
+ remaining--;
2234
+ }
2235
+ return {
2236
+ children,
2237
+ nodesConsumed: totalConsumed
1959
2238
  };
1960
2239
  };
1961
2240
 
2241
+ const compareNodes = (oldNode, newNode) => {
2242
+ const patches = [];
2243
+ // Check if node type changed - return null to signal incompatible nodes
2244
+ // (caller should handle this with a Replace operation)
2245
+ if (oldNode.type !== newNode.type) {
2246
+ return null;
2247
+ }
2248
+ // Handle reference nodes - special handling for uid changes
2249
+ if (oldNode.type === Reference) {
2250
+ if (oldNode.uid !== newNode.uid) {
2251
+ patches.push({
2252
+ type: SetReferenceNodeUid,
2253
+ uid: newNode.uid
2254
+ });
2255
+ }
2256
+ return patches;
2257
+ }
2258
+ // Handle text nodes
2259
+ if (oldNode.type === Text && newNode.type === Text) {
2260
+ if (oldNode.text !== newNode.text) {
2261
+ patches.push({
2262
+ type: SetText,
2263
+ value: newNode.text
2264
+ });
2265
+ }
2266
+ return patches;
2267
+ }
2268
+ // Compare attributes
2269
+ const oldKeys = getKeys(oldNode);
2270
+ const newKeys = getKeys(newNode);
2271
+ // Check for attribute changes
2272
+ for (const key of newKeys) {
2273
+ if (oldNode[key] !== newNode[key]) {
2274
+ patches.push({
2275
+ type: SetAttribute,
2276
+ key,
2277
+ value: newNode[key]
2278
+ });
2279
+ }
2280
+ }
2281
+ // Check for removed attributes
2282
+ for (const key of oldKeys) {
2283
+ if (!(key in newNode)) {
2284
+ patches.push({
2285
+ type: RemoveAttribute,
2286
+ key
2287
+ });
2288
+ }
2289
+ }
2290
+ return patches;
2291
+ };
2292
+
2293
+ const treeToArray = node => {
2294
+ const result = [node.node];
2295
+ for (const child of node.children) {
2296
+ result.push(...treeToArray(child));
2297
+ }
2298
+ return result;
2299
+ };
2300
+
2301
+ const diffChildren = (oldChildren, newChildren, patches) => {
2302
+ const maxLength = Math.max(oldChildren.length, newChildren.length);
2303
+ // Track where we are: -1 means at parent, >= 0 means at child index
2304
+ let currentChildIndex = -1;
2305
+ // Collect indices of children to remove (we'll add these patches at the end in reverse order)
2306
+ const indicesToRemove = [];
2307
+ for (let i = 0; i < maxLength; i++) {
2308
+ const oldNode = oldChildren[i];
2309
+ const newNode = newChildren[i];
2310
+ if (!oldNode && !newNode) {
2311
+ continue;
2312
+ }
2313
+ if (!oldNode) {
2314
+ // Add new node - we should be at the parent
2315
+ if (currentChildIndex >= 0) {
2316
+ // Navigate back to parent
2317
+ patches.push({
2318
+ type: NavigateParent
2319
+ });
2320
+ currentChildIndex = -1;
2321
+ }
2322
+ // Flatten the entire subtree so renderInternal can handle it
2323
+ const flatNodes = treeToArray(newNode);
2324
+ patches.push({
2325
+ type: Add,
2326
+ nodes: flatNodes
2327
+ });
2328
+ } else if (newNode) {
2329
+ // Compare nodes to see if we need any patches
2330
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
2331
+ // If nodePatches is null, the node types are incompatible - need to replace
2332
+ if (nodePatches === null) {
2333
+ // Navigate to this child
2334
+ if (currentChildIndex === -1) {
2335
+ patches.push({
2336
+ type: NavigateChild,
2337
+ index: i
2338
+ });
2339
+ currentChildIndex = i;
2340
+ } else if (currentChildIndex !== i) {
2341
+ patches.push({
2342
+ type: NavigateSibling,
2343
+ index: i
2344
+ });
2345
+ currentChildIndex = i;
2346
+ }
2347
+ // Replace the entire subtree
2348
+ const flatNodes = treeToArray(newNode);
2349
+ patches.push({
2350
+ type: Replace,
2351
+ nodes: flatNodes
2352
+ });
2353
+ // After replace, we're at the new element (same position)
2354
+ continue;
2355
+ }
2356
+ // Check if we need to recurse into children
2357
+ const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
2358
+ // Only navigate to this element if we need to do something
2359
+ if (nodePatches.length > 0 || hasChildrenToCompare) {
2360
+ // Navigate to this child if not already there
2361
+ if (currentChildIndex === -1) {
2362
+ patches.push({
2363
+ type: NavigateChild,
2364
+ index: i
2365
+ });
2366
+ currentChildIndex = i;
2367
+ } else if (currentChildIndex !== i) {
2368
+ patches.push({
2369
+ type: NavigateSibling,
2370
+ index: i
2371
+ });
2372
+ currentChildIndex = i;
2373
+ }
2374
+ // Apply node patches (these apply to the current element, not children)
2375
+ if (nodePatches.length > 0) {
2376
+ patches.push(...nodePatches);
2377
+ }
2378
+ // Compare children recursively
2379
+ if (hasChildrenToCompare) {
2380
+ diffChildren(oldNode.children, newNode.children, patches);
2381
+ }
2382
+ }
2383
+ } else {
2384
+ // Remove old node - collect the index for later removal
2385
+ indicesToRemove.push(i);
2386
+ }
2387
+ }
2388
+ // Navigate back to parent if we ended at a child
2389
+ if (currentChildIndex >= 0) {
2390
+ patches.push({
2391
+ type: NavigateParent
2392
+ });
2393
+ }
2394
+ // Add remove patches in reverse order (highest index first)
2395
+ // This ensures indices remain valid as we remove
2396
+ for (let j = indicesToRemove.length - 1; j >= 0; j--) {
2397
+ patches.push({
2398
+ type: RemoveChild,
2399
+ index: indicesToRemove[j]
2400
+ });
2401
+ }
2402
+ };
2403
+ const diffTrees = (oldTree, newTree, patches, path) => {
2404
+ // At the root level (path.length === 0), we're already AT the element
2405
+ // So we compare the root node directly, then compare its children
2406
+ if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
2407
+ const oldNode = oldTree[0];
2408
+ const newNode = newTree[0];
2409
+ // Compare root nodes
2410
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
2411
+ // If nodePatches is null, the root node types are incompatible - need to replace
2412
+ if (nodePatches === null) {
2413
+ const flatNodes = treeToArray(newNode);
2414
+ patches.push({
2415
+ type: Replace,
2416
+ nodes: flatNodes
2417
+ });
2418
+ return;
2419
+ }
2420
+ if (nodePatches.length > 0) {
2421
+ patches.push(...nodePatches);
2422
+ }
2423
+ // Compare children
2424
+ if (oldNode.children.length > 0 || newNode.children.length > 0) {
2425
+ diffChildren(oldNode.children, newNode.children, patches);
2426
+ }
2427
+ } else {
2428
+ // Non-root level or multiple root elements - use the regular comparison
2429
+ diffChildren(oldTree, newTree, patches);
2430
+ }
2431
+ };
2432
+
2433
+ const removeTrailingNavigationPatches = patches => {
2434
+ // Find the last non-navigation patch
2435
+ let lastNonNavigationIndex = -1;
2436
+ for (let i = patches.length - 1; i >= 0; i--) {
2437
+ const patch = patches[i];
2438
+ if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
2439
+ lastNonNavigationIndex = i;
2440
+ break;
2441
+ }
2442
+ }
2443
+ // Return patches up to and including the last non-navigation patch
2444
+ return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
2445
+ };
2446
+
2447
+ const diffTree = (oldNodes, newNodes) => {
2448
+ // Step 1: Convert flat arrays to tree structures
2449
+ const oldTree = arrayToTree(oldNodes);
2450
+ const newTree = arrayToTree(newNodes);
2451
+ // Step 3: Compare the trees
2452
+ const patches = [];
2453
+ diffTrees(oldTree, newTree, patches, []);
2454
+ // Remove trailing navigation patches since they serve no purpose
2455
+ return removeTrailingNavigationPatches(patches);
2456
+ };
2457
+
1962
2458
  const getKeyBindings = () => {
1963
2459
  return [{
1964
2460
  command: 'Source Control.acceptInput',
@@ -1970,42 +2466,42 @@ const getKeyBindings = () => {
1970
2466
  const getMenuEntries = () => {
1971
2467
  return [{
1972
2468
  command: /* TODO */'-1',
1973
- flags: None$1,
2469
+ flags: None,
1974
2470
  id: '',
1975
2471
  label: openChanges()
1976
2472
  }, {
1977
2473
  command: /* TODO */'-1',
1978
- flags: None$1,
2474
+ flags: None,
1979
2475
  id: '',
1980
2476
  label: openFile()
1981
2477
  }, {
1982
2478
  command: /* TODO */'-1',
1983
- flags: None$1,
2479
+ flags: None,
1984
2480
  id: '',
1985
2481
  label: openFileHead()
1986
2482
  }, {
1987
2483
  command: /* TODO */'-1',
1988
- flags: None$1,
2484
+ flags: None,
1989
2485
  id: '',
1990
2486
  label: discardChanges()
1991
2487
  }, {
1992
2488
  command: /* TODO */'-1',
1993
- flags: None$1,
2489
+ flags: None,
1994
2490
  id: '',
1995
2491
  label: stageChanges()
1996
2492
  }, {
1997
2493
  command: /* TODO */'-1',
1998
- flags: None$1,
2494
+ flags: None,
1999
2495
  id: '',
2000
2496
  label: addToGitignore()
2001
2497
  }, {
2002
2498
  command: /* TODO */'-1',
2003
- flags: None$1,
2499
+ flags: None,
2004
2500
  id: '',
2005
2501
  label: revealInExplorerView()
2006
2502
  }, {
2007
2503
  command: /* TODO */'-1',
2008
- flags: None$1,
2504
+ flags: None,
2009
2505
  id: '',
2010
2506
  label: openContainingFolder()
2011
2507
  }];
@@ -2019,10 +2515,64 @@ const getMenuIds = () => {
2019
2515
  return [SourceControl$1];
2020
2516
  };
2021
2517
 
2518
+ const handleInput = async (state, value, inputSource = User) => {
2519
+ const {
2520
+ inputFontFamily,
2521
+ inputFontSize,
2522
+ inputFontWeight,
2523
+ inputLetterSpacing,
2524
+ inputLineHeight,
2525
+ inputPadding,
2526
+ width
2527
+ } = state;
2528
+ const inputBoxHeight = await getInputHeight(value, width, inputFontFamily, inputFontWeight, inputFontSize, inputLetterSpacing, inputLineHeight, inputPadding);
2529
+ return {
2530
+ ...state,
2531
+ inputBoxHeight,
2532
+ inputMessage: '',
2533
+ inputSource,
2534
+ inputValue: value
2535
+ };
2536
+ };
2537
+
2538
+ const toErrorMessage = error => {
2539
+ if (error instanceof Error && error.message) {
2540
+ return `Failed to generate commit message: ${error.message}`;
2541
+ }
2542
+ return 'Failed to generate commit message';
2543
+ };
2544
+ const handleGenerateCommitMessage = async state => {
2545
+ const {
2546
+ assetDir,
2547
+ enabledProviderIds,
2548
+ platform
2549
+ } = state;
2550
+ if (enabledProviderIds.length === 0) {
2551
+ return {
2552
+ ...state,
2553
+ inputMessage: 'Failed to generate commit message: no source control provider found'
2554
+ };
2555
+ }
2556
+ try {
2557
+ const inputValue = await generateCommitMessage$1(enabledProviderIds[0], assetDir, platform);
2558
+ const newState = await handleInput(state, inputValue, Script);
2559
+ return {
2560
+ ...newState,
2561
+ inputMessage: ''
2562
+ };
2563
+ } catch (error) {
2564
+ return {
2565
+ ...state,
2566
+ inputMessage: toErrorMessage(error)
2567
+ };
2568
+ }
2569
+ };
2570
+
2022
2571
  const SourceControlInput = 'SourceControlInput';
2023
2572
  const ViewAsTree = 'ViewAsTree';
2024
2573
  const CommitAndPush = 'CommitAndPush';
2025
2574
  const Refresh$1 = 'Refresh';
2575
+ const GenerateCommitMessage = 'GenerateCommitMessage';
2026
2576
 
2027
2577
  const refresh = async state => {
2028
2578
  const {
@@ -2044,7 +2594,7 @@ const refresh = async state => {
2044
2594
  } = await getGroups(enabledProviderIds, root, assetDir, platform);
2045
2595
  const expandedGroups = restoreExpandedGroups(allGroups);
2046
2596
  const displayItems = getDisplayItems(allGroups, expandedGroups, iconDefinitions);
2047
- const badgeCount = allGroups.reduce((sum, group) => sum + group.items.length, 0);
2597
+ const badgeCount = await getBadgeCount$1(enabledProviderIds, assetDir, platform);
2048
2598
  const total = displayItems.length;
2049
2599
  const contentHeight = total * itemHeight;
2050
2600
  const listHeight = getListHeight(total, itemHeight, height);
@@ -2075,7 +2625,7 @@ const refresh = async state => {
2075
2625
  const viewAsTree = state => {
2076
2626
  return {
2077
2627
  ...state,
2078
- viewMode: Tree$1
2628
+ viewMode: Tree
2079
2629
  };
2080
2630
  };
2081
2631
 
@@ -2084,6 +2634,8 @@ const handleActionClick = async (state, actionName) => {
2084
2634
  case CommitAndPush:
2085
2635
  warn(`[source-control-worker] CommitAndPush action not yet implemented`);
2086
2636
  return state;
2637
+ case GenerateCommitMessage:
2638
+ return handleGenerateCommitMessage(state);
2087
2639
  case Refresh$1:
2088
2640
  return refresh(state);
2089
2641
  case ViewAsTree:
@@ -2288,32 +2840,13 @@ const handleInputFocus = async state => {
2288
2840
  };
2289
2841
  };
2290
2842
 
2291
- const handleInput = async (state, value, inputSource = User) => {
2292
- const {
2293
- inputFontFamily,
2294
- inputFontSize,
2295
- inputFontWeight,
2296
- inputLetterSpacing,
2297
- inputLineHeight,
2298
- inputPadding,
2299
- width
2300
- } = state;
2301
- const inputBoxHeight = await getInputHeight(value, width, inputFontFamily, inputFontWeight, inputFontSize, inputLetterSpacing, inputLineHeight, inputPadding);
2302
- return {
2303
- ...state,
2304
- inputBoxHeight,
2305
- inputSource,
2306
- inputValue: value
2307
- };
2308
- };
2309
-
2310
2843
  const handleInputBlur = async state => {
2311
2844
  // TODO reset focus
2312
2845
  return state;
2313
2846
  };
2314
2847
 
2315
2848
  const handleMessagePort = async port => {
2316
- await PlainMessagePortRpc.create({
2849
+ await create$4({
2317
2850
  commandMap: {},
2318
2851
  messagePort: port
2319
2852
  });
@@ -2354,6 +2887,21 @@ const handleMouseOverAt = async (state, eventX, eventY) => {
2354
2887
  return handleMouseOver(state, index);
2355
2888
  };
2356
2889
 
2890
+ const handleSourceControlButtonClick = async (state, name) => {
2891
+ const button = state.sourceControlButtons.find(button => button.label === name);
2892
+ if (!button) {
2893
+ warn(`[source-control-worker] Source control button not found ${name}`);
2894
+ return state;
2895
+ }
2896
+ await executeCommand(button.command, state.assetDir, state.platform, state.inputValue);
2897
+ const newState = await loadContent(state, {});
2898
+ return {
2899
+ ...newState,
2900
+ inputMessage: '',
2901
+ inputValue: ''
2902
+ };
2903
+ };
2904
+
2357
2905
  const setDeltaY = async (state, newDeltaY) => {
2358
2906
  const {
2359
2907
  actionsCache,
@@ -2393,7 +2941,7 @@ const sendMessagePortToExtensionHostWorker = async port => {
2393
2941
 
2394
2942
  const createExtensionHostRpc = async () => {
2395
2943
  try {
2396
- const rpc = await TransferMessagePortRpcParent.create({
2944
+ const rpc = await create$3({
2397
2945
  commandMap: {},
2398
2946
  send: sendMessagePortToExtensionHostWorker
2399
2947
  });
@@ -2409,7 +2957,7 @@ const sendMessagePortToTextMeasurementWorker = async port => {
2409
2957
 
2410
2958
  const createTextMeasurementWorkerRpc = async () => {
2411
2959
  try {
2412
- const rpc = await TransferMessagePortRpcParent.create({
2960
+ const rpc = await create$3({
2413
2961
  commandMap: {},
2414
2962
  send: sendMessagePortToTextMeasurementWorker
2415
2963
  });
@@ -2419,12 +2967,39 @@ const createTextMeasurementWorkerRpc = async () => {
2419
2967
  }
2420
2968
  };
2421
2969
 
2970
+ const createExtensionManagementWorkerRpc = async () => {
2971
+ try {
2972
+ const rpc = await create$3({
2973
+ commandMap: {},
2974
+ send: port => sendMessagePortToExtensionManagementWorker(port, 0)
2975
+ });
2976
+ return rpc;
2977
+ } catch (error) {
2978
+ throw new VError(error, `Failed to create extension management rpc`);
2979
+ }
2980
+ };
2981
+
2982
+ const initializeExtensionManagementWorker = async () => {
2983
+ try {
2984
+ const rpc = await createExtensionManagementWorkerRpc();
2985
+ set$3(rpc);
2986
+ } catch {
2987
+ // ignore
2988
+ }
2989
+ };
2990
+
2422
2991
  const initialize = async () => {
2423
- const [extensionHostRpc, textRpc] = await Promise.all([createExtensionHostRpc(), createTextMeasurementWorkerRpc()]);
2424
- set$3(extensionHostRpc);
2992
+ const [extensionHostRpc, textRpc] = await Promise.all([createExtensionHostRpc(), createTextMeasurementWorkerRpc(), initializeExtensionManagementWorker()]);
2993
+ set$4(extensionHostRpc);
2425
2994
  set$1(textRpc);
2426
2995
  };
2427
2996
 
2997
+ const getIndentRule = indent => {
2998
+ return `.Indent-${indent} {
2999
+ padding-left: ${indent}px;
3000
+ }`;
3001
+ };
3002
+
2428
3003
  const getUnique = items => {
2429
3004
  const seens = [];
2430
3005
  for (const item of items) {
@@ -2435,11 +3010,6 @@ const getUnique = items => {
2435
3010
  return seens;
2436
3011
  };
2437
3012
 
2438
- const getIndentRule = indent => {
2439
- return `.Indent-${indent} {
2440
- padding-left: ${indent}px;
2441
- }`;
2442
- };
2443
3013
  const renderCss = (oldState, newState) => {
2444
3014
  const {
2445
3015
  id,
@@ -2479,19 +3049,13 @@ const IconButton = 'IconButton';
2479
3049
  const InputBox = 'InputBox';
2480
3050
  const Label = 'Label';
2481
3051
  const LabelDetail = 'LabelDetail';
2482
- const MaskIcon = 'MaskIcon';
2483
- const MaskIconChevronDown = 'MaskIconChevronDown';
3052
+ const Message = 'Message';
2484
3053
  const SourceControl = 'SourceControl';
2485
3054
  const SourceControlButton = 'SourceControlButton';
2486
3055
  const SourceControlHeader = 'SourceControlHeader';
2487
3056
  const SourceControlItems = 'SourceControlItems';
2488
3057
  const SplitButton = 'SplitButton';
2489
3058
  const SplitButtonContent = 'SplitButtonContent';
2490
- const SplitButtonContentDisabled = 'SplitButtonContentDisabled';
2491
- const SplitButtonDisabled = 'SplitButtonDisabled';
2492
- const SplitButtonDropDown = 'SplitButtonDropDown';
2493
- const SplitButtonDropDownDisabled = 'SplitButtonDropDownDisabled';
2494
- const SplitButtonSeparator = 'SplitButtonSeparator';
2495
3059
  const StrikeThrough = 'StrikeThrough';
2496
3060
  const TreeItem = 'TreeItem';
2497
3061
  const Viewlet = 'Viewlet';
@@ -2505,9 +3069,34 @@ const HandleMouseOver = 7;
2505
3069
  const HandleMouseOverAt = 8;
2506
3070
  const HandleWheel = 9;
2507
3071
  const HandleClickAction = 10;
3072
+ const HandleClickSourceControlButton = 11;
2508
3073
 
2509
- const getSourceControlInputDom = inputPlaceholder => {
3074
+ const getSourceControlButtonVirtualDom = button => {
3075
+ const {
3076
+ id,
3077
+ label
3078
+ } = button;
2510
3079
  return [{
3080
+ childCount: 1,
3081
+ className: SplitButton,
3082
+ type: Div
3083
+ }, {
3084
+ childCount: 1,
3085
+ className: SplitButtonContent,
3086
+ name: label,
3087
+ onClick: HandleClickSourceControlButton,
3088
+ tabIndex: 0,
3089
+ title: id,
3090
+ type: Div
3091
+ }, text(label)];
3092
+ };
3093
+
3094
+ const getSourceControlButtonsVirtualDom = buttons => {
3095
+ return buttons.flatMap(getSourceControlButtonVirtualDom);
3096
+ };
3097
+
3098
+ const getSourceControlInputDom = (inputPlaceholder, inputMessage) => {
3099
+ const dom = [{
2511
3100
  ariaLabel: sourceControlInput(),
2512
3101
  autocapitalize: 'off',
2513
3102
  autocorrect: 'off',
@@ -2520,14 +3109,26 @@ const getSourceControlInputDom = inputPlaceholder => {
2520
3109
  spellcheck: false,
2521
3110
  type: TextArea
2522
3111
  }];
3112
+ if (inputMessage) {
3113
+ dom.push({
3114
+ childCount: 1,
3115
+ className: Message,
3116
+ type: Div
3117
+ }, {
3118
+ text: inputMessage,
3119
+ type: Text
3120
+ });
3121
+ }
3122
+ return dom;
2523
3123
  };
2524
3124
 
2525
- const getSourceControlHeaderVirtualDom = inputPlaceholder => {
3125
+ const getSourceControlHeaderVirtualDom = (inputPlaceholder, inputMessage) => {
3126
+ const inputDom = getSourceControlInputDom(inputPlaceholder, inputMessage);
2526
3127
  return [{
2527
- childCount: 1,
3128
+ childCount: inputMessage ? 2 : 1,
2528
3129
  className: SourceControlHeader,
2529
3130
  type: Div
2530
- }, ...getSourceControlInputDom(inputPlaceholder)];
3131
+ }, ...inputDom];
2531
3132
  };
2532
3133
 
2533
3134
  const className$1 = mergeClassNames(Badge, SourceControlBadge);
@@ -2537,14 +3138,14 @@ const parentNode = {
2537
3138
  type: Div
2538
3139
  };
2539
3140
  const getBadgeVirtualDom = count => {
2540
- return [parentNode, text(`${count}`)];
3141
+ return [parentNode, text(String(count))];
2541
3142
  };
2542
3143
 
2543
3144
  const getIconVirtualDom = (icon, type = Div) => {
2544
3145
  return {
2545
3146
  childCount: 0,
2546
3147
  className: `MaskIcon MaskIcon${icon}`,
2547
- role: None,
3148
+ role: None$1,
2548
3149
  type
2549
3150
  };
2550
3151
  };
@@ -2560,7 +3161,7 @@ const getButtonVirtualDom = button => {
2560
3161
  className: SourceControlButton,
2561
3162
  name: label,
2562
3163
  title: label,
2563
- type: Button$1
3164
+ type: Button$2
2564
3165
  }, getIconVirtualDom(icon, Span)];
2565
3166
  };
2566
3167
 
@@ -2632,7 +3233,7 @@ const getFileIconVirtualDom = icon => {
2632
3233
  return {
2633
3234
  childCount: 0,
2634
3235
  className: FileIcon,
2635
- role: None,
3236
+ role: None$1,
2636
3237
  src: icon,
2637
3238
  type: Img
2638
3239
  };
@@ -2721,45 +3322,15 @@ const getSourceControlListVirtualDom = items => {
2721
3322
  onClick: HandleClickAt,
2722
3323
  onPointerOut: HandleMouseOutAt,
2723
3324
  onPointerOver: HandleMouseOverAt,
2724
- role: Tree,
3325
+ role: Tree$1,
2725
3326
  type: Div
2726
3327
  }, ...items.flatMap(getSourceControlItemVirtualDom)];
2727
3328
  };
2728
3329
 
2729
- const getSplitButtonVirtualDom = (hasItems, splitButtonEnabled, buttonText) => {
2730
- if (!splitButtonEnabled || !hasItems) {
2731
- return [];
2732
- }
2733
- return [{
2734
- childCount: 3,
2735
- className: mergeClassNames(SplitButton, hasItems ? '' : SplitButtonDisabled),
2736
- type: Div
2737
- }, {
2738
- childCount: 1,
2739
- className: mergeClassNames(SplitButtonContent, hasItems ? '' : SplitButtonContentDisabled),
2740
- tabIndex: 0,
2741
- type: Div
2742
- }, text(buttonText), {
2743
- childCount: 0,
2744
- className: SplitButtonSeparator,
2745
- type: Div
2746
- }, {
2747
- childCount: 1,
2748
- className: mergeClassNames(SplitButtonDropDown, hasItems ? '' : SplitButtonDropDownDisabled),
2749
- tabIndex: 0,
2750
- type: Div
2751
- }, {
2752
- childCount: 0,
2753
- className: mergeClassNames(MaskIcon, MaskIconChevronDown),
2754
- type: Div
2755
- }];
2756
- };
2757
-
2758
3330
  const className = mergeClassNames(Viewlet, SourceControl);
2759
- const getSourceControlVirtualDom = (items, splitButtonEnabled, inputPlaceholder) => {
2760
- const hasItems = items.length > 0;
3331
+ const getSourceControlVirtualDom = (items, sourceControlButtons, inputPlaceholder, inputMessage) => {
2761
3332
  const dom = [{
2762
- childCount: splitButtonEnabled ? 3 : 2,
3333
+ childCount: 2 + sourceControlButtons.length,
2763
3334
  className: className,
2764
3335
  onContextMenu: HandleContextMenu,
2765
3336
  onMouseOver: HandleMouseOver,
@@ -2767,21 +3338,36 @@ const getSourceControlVirtualDom = (items, splitButtonEnabled, inputPlaceholder)
2767
3338
  onWheel: HandleWheel,
2768
3339
  tabIndex: 0,
2769
3340
  type: Div
2770
- }, ...getSourceControlHeaderVirtualDom(inputPlaceholder), ...getSplitButtonVirtualDom(hasItems, splitButtonEnabled, 'Commit'), ...getSourceControlListVirtualDom(items)];
3341
+ }, ...getSourceControlHeaderVirtualDom(inputPlaceholder, inputMessage), ...getSourceControlButtonsVirtualDom(sourceControlButtons), ...getSourceControlListVirtualDom(items)];
2771
3342
  return dom;
2772
3343
  };
2773
3344
 
2774
3345
  const renderItems = (oldState, newState) => {
2775
3346
  const {
2776
3347
  id,
3348
+ initial,
3349
+ inputMessage,
2777
3350
  inputPlaceholder,
2778
- splitButtonEnabled,
3351
+ sourceControlButtons,
2779
3352
  visibleItems
2780
3353
  } = newState;
2781
- const dom = getSourceControlVirtualDom(visibleItems, splitButtonEnabled, inputPlaceholder);
3354
+ if (initial) {
3355
+ return [SetDom2, id, []];
3356
+ }
3357
+ const dom = getSourceControlVirtualDom(visibleItems, sourceControlButtons, inputPlaceholder, inputMessage);
2782
3358
  return [SetDom2, id, dom];
2783
3359
  };
2784
3360
 
3361
+ const renderIncremental = (oldState, newState) => {
3362
+ const oldDom = renderItems(oldState, oldState)[2];
3363
+ const newDom = renderItems(newState, newState)[2];
3364
+ const patches = diffTree(oldDom, newDom);
3365
+ const {
3366
+ id
3367
+ } = newState;
3368
+ return ['Viewlet.setPatches', id, patches];
3369
+ };
3370
+
2785
3371
  const renderValue = (oldState, newState) => {
2786
3372
  const {
2787
3373
  id,
@@ -2796,6 +3382,8 @@ const getRenderer = diffType => {
2796
3382
  return renderCss;
2797
3383
  case RenderFocusContext:
2798
3384
  return renderFocusContext;
3385
+ case RenderIncremental:
3386
+ return renderIncremental;
2799
3387
  case RenderItems:
2800
3388
  return renderItems;
2801
3389
  case RenderValue:
@@ -2830,11 +3418,12 @@ const render2 = (uid, diffResult) => {
2830
3418
  const Button = 1;
2831
3419
 
2832
3420
  const Check = 'Check';
3421
+ const DebugAlt2 = 'DebugAlt2';
2833
3422
  const ListFlat = 'ListFlat';
2834
3423
  const Refresh = 'Refresh';
2835
3424
 
2836
- const getActions = () => {
2837
- return [{
3425
+ const getActions = state => {
3426
+ const actions = [{
2838
3427
  command: '',
2839
3428
  icon: ListFlat,
2840
3429
  id: viewAsTree$1(),
@@ -2853,6 +3442,16 @@ const getActions = () => {
2853
3442
  name: Refresh$1,
2854
3443
  type: Button
2855
3444
  }];
3445
+ if (state.showGenerateCommitMessageButton) {
3446
+ actions.splice(2, 0, {
3447
+ command: '',
3448
+ icon: DebugAlt2,
3449
+ id: generateCommitMessage(),
3450
+ name: GenerateCommitMessage,
3451
+ type: Button
3452
+ });
3453
+ }
3454
+ return actions;
2856
3455
  };
2857
3456
 
2858
3457
  const getActionButtonVirtualDom = action => {
@@ -2866,7 +3465,7 @@ const getActionButtonVirtualDom = action => {
2866
3465
  className: IconButton,
2867
3466
  name: label,
2868
3467
  title: id,
2869
- type: Button$1
3468
+ type: Button$2
2870
3469
  }, getIconVirtualDom(icon)];
2871
3470
  };
2872
3471
 
@@ -2897,7 +3496,7 @@ const getActionsVirtualDom = actions => {
2897
3496
  };
2898
3497
 
2899
3498
  const renderActions = state => {
2900
- const actions = getActions();
3499
+ const actions = getActions(state);
2901
3500
  const dom = getActionsVirtualDom(actions);
2902
3501
  return dom;
2903
3502
  };
@@ -2927,7 +3526,7 @@ const renderEventListeners = () => {
2927
3526
  params: ['handleInput', TargetValue]
2928
3527
  }, {
2929
3528
  name: HandleContextMenu,
2930
- params: ['handleContextMenu', Button$2, ClientX, ClientY],
3529
+ params: ['handleContextMenu', Button$1, ClientX, ClientY],
2931
3530
  preventDefault: true
2932
3531
  }, {
2933
3532
  name: HandleWheel,
@@ -2936,6 +3535,9 @@ const renderEventListeners = () => {
2936
3535
  }, {
2937
3536
  name: HandleClickAction,
2938
3537
  params: ['handleActionClick', TargetName]
3538
+ }, {
3539
+ name: HandleClickSourceControlButton,
3540
+ params: ['handleSourceControlButtonClick', TargetName]
2939
3541
  }];
2940
3542
  };
2941
3543
 
@@ -2996,12 +3598,14 @@ const commandMap = {
2996
3598
  'SourceControl.getKeyBindings': getKeyBindings,
2997
3599
  'SourceControl.getMenuEntries2': wrapGetter(getMenuEntries2),
2998
3600
  'SourceControl.getMenuIds': getMenuIds,
3601
+ 'SourceControl.getWorkspaceBadgeCount': getWorkspaceBadgeCount,
2999
3602
  'SourceControl.handleActionClick': wrapCommand(handleActionClick),
3000
3603
  'SourceControl.handleButtonClick': wrapCommand(handleButtonClick),
3001
3604
  'SourceControl.handleClickAt': wrapCommand(handleClickAt),
3002
3605
  'SourceControl.handleClickSourceControlButtons': wrapCommand(handleClickSourceControlButtons),
3003
3606
  'SourceControl.handleContextMenu': wrapCommand(handleContextMenu),
3004
3607
  'SourceControl.handleFocus': wrapCommand(handleInputFocus),
3608
+ 'SourceControl.handleGenerateCommitMessage': wrapCommand(handleGenerateCommitMessage),
3005
3609
  'SourceControl.handleInput': wrapCommand(handleInput),
3006
3610
  'SourceControl.handleInputBlur': wrapCommand(handleInputBlur),
3007
3611
  'SourceControl.handleMessagePort': handleMessagePort,
@@ -3009,6 +3613,7 @@ const commandMap = {
3009
3613
  'SourceControl.handleMouseOutAt': wrapCommand(handleMouseOutAt),
3010
3614
  'SourceControl.handleMouseOver': wrapCommand(handleMouseOver),
3011
3615
  'SourceControl.handleMouseOverAt': wrapCommand(handleMouseOverAt),
3616
+ 'SourceControl.handleSourceControlButtonClick': wrapCommand(handleSourceControlButtonClick),
3012
3617
  'SourceControl.handleWheel': wrapCommand(handleWheel),
3013
3618
  'SourceControl.handleWorkspaceRefresh': wrapCommand(handleWorkspaceRefresh),
3014
3619
  'SourceControl.loadContent': wrapCommand(loadContent),
@@ -3028,7 +3633,7 @@ const commandMap = {
3028
3633
 
3029
3634
  const listen = async () => {
3030
3635
  registerCommands(commandMap);
3031
- const rpc = await WebWorkerRpcClient.create({
3636
+ const rpc = await create$2({
3032
3637
  commandMap: commandMap
3033
3638
  });
3034
3639
  set$2(rpc);