@lvce-editor/main-area-worker 9.64.3 → 9.66.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.
@@ -662,6 +662,23 @@ const restoreMessageError = (error, _currentStack) => {
662
662
  }
663
663
  return restoredError;
664
664
  };
665
+ const getFallbackMessage = error => {
666
+ if (error && typeof error.message === 'string' && error.message) {
667
+ return error.message;
668
+ }
669
+ if (error && error.data) {
670
+ return getFallbackMessage(error.data);
671
+ }
672
+ const stringified = String(error);
673
+ if (stringified !== '[object Object]') {
674
+ return stringified;
675
+ }
676
+ try {
677
+ return JSON.stringify(error);
678
+ } catch {
679
+ return stringified;
680
+ }
681
+ };
665
682
  const restoreJsonRpcError = error => {
666
683
  const currentStack = getCurrentStack();
667
684
  if (error && error instanceof Error) {
@@ -670,13 +687,13 @@ const restoreJsonRpcError = error => {
670
687
  if (error && error.code && error.code === MethodNotFound) {
671
688
  return restoreMethodNotFoundError(error, currentStack);
672
689
  }
690
+ if (error && error.error) {
691
+ return restoreJsonRpcError(error.error);
692
+ }
673
693
  if (error && error.message) {
674
694
  return restoreMessageError(error);
675
695
  }
676
- if (typeof error === 'string') {
677
- return new Error(`JsonRpc Error: ${error}`);
678
- }
679
- return new Error(`JsonRpc Error: ${error}`);
696
+ return new Error(`JsonRpc Error: ${getFallbackMessage(error)}`);
680
697
  };
681
698
  const unwrapJsonRpcResult = responseMessage => {
682
699
  if ('error' in responseMessage) {
@@ -1465,8 +1482,8 @@ const {
1465
1482
  invoke: invoke$5,
1466
1483
  set: set$5
1467
1484
  } = create$3(DragAndDropWorker);
1468
- const getDroppedUrisByDropId = async (dropId, isElectron) => {
1469
- return invoke$5('DragAndDrop.getDroppedUrisByDropId', dropId, isElectron);
1485
+ const getDroppedItemsByDropId = async (dropId, isElectron) => {
1486
+ return invoke$5('DragAndDrop.getDroppedItemsByDropId', dropId, isElectron);
1470
1487
  };
1471
1488
 
1472
1489
  const {
@@ -1628,7 +1645,7 @@ const addClosedTabs = (state, entries) => {
1628
1645
  if (entries.length === 0) {
1629
1646
  return state;
1630
1647
  }
1631
- void add(state.uid, entries);
1648
+ void add(state.uid, entries.filter(entry => !entry.tab.terminal));
1632
1649
  return state;
1633
1650
  };
1634
1651
 
@@ -1786,7 +1803,7 @@ const getActiveFileUri = state => {
1786
1803
  } = layout;
1787
1804
  const activeGroup = groups.find(group => group.id === activeGroupId);
1788
1805
  const activeTab = activeGroup?.tabs.find(tab => tab.id === activeGroup.activeTabId);
1789
- if (!activeTab) {
1806
+ if (!activeTab || activeTab.terminal) {
1790
1807
  return '';
1791
1808
  }
1792
1809
  if (typeof activeTab.uri === 'string') {
@@ -1821,7 +1838,7 @@ const getActiveTab = state => {
1821
1838
 
1822
1839
  const hasActiveTextEditor = state => {
1823
1840
  const activeTab = getActiveTab(state);
1824
- return activeTab?.tab.editorInput?.type === 'editor';
1841
+ return !activeTab?.tab.terminal && activeTab?.tab.editorInput?.type === 'editor';
1825
1842
  };
1826
1843
 
1827
1844
  const notifyActiveEditorChange = async (oldState, newState) => {
@@ -2818,11 +2835,12 @@ const focus = async state => {
2818
2835
  if (typeof editorUid !== 'number' || editorUid < 0) {
2819
2836
  return state;
2820
2837
  }
2838
+ const selector = activeTab?.tab.terminal ? '.xterm-helper-textarea' : '[name="editor"]';
2821
2839
  if (isConnected()) {
2822
- await invoke('Viewlet.focusSelector', editorUid, '[name="editor"]');
2823
- await invoke('Viewlet.focusSelectorAfterRender', editorUid, '[name="editor"]');
2840
+ await invoke('Viewlet.focusSelector', editorUid, selector);
2841
+ await invoke('Viewlet.focusSelectorAfterRender', editorUid, selector);
2824
2842
  } else {
2825
- await invoke$2('Viewlet.focusSelector', editorUid, '[name="editor"]');
2843
+ await invoke$2('Viewlet.focusSelector', editorUid, selector);
2826
2844
  }
2827
2845
  return state;
2828
2846
  };
@@ -5005,7 +5023,7 @@ const getMaxFileSize = async () => {
5005
5023
  return defaultMaxFileSizeMb * bytesPerMegabyte;
5006
5024
  };
5007
5025
  const getLargeFileSize = async (editorInput, forceOpen = false, applicationId) => {
5008
- if (editorInput.type !== 'editor' || forceOpen || !editorInput.uri.startsWith('file://')) {
5026
+ if (editorInput.type !== 'editor' || forceOpen) {
5009
5027
  return undefined;
5010
5028
  }
5011
5029
  try {
@@ -5468,6 +5486,15 @@ const shouldRetryExistingTab = (existingTab, editorInput, forceOpen) => {
5468
5486
  }
5469
5487
  return existingTab.tab.loadingState === 'error' || forceOpen && existingTab.tab.loadingState === 'large' || editorInput.type === 'editor' && editorInput.forceText === true && existingTab.tab.editorInput?.type === 'binary';
5470
5488
  };
5489
+ const getViewletArgs = options => {
5490
+ if (options.forceOpen !== true || options.editorInput.type !== 'editor') {
5491
+ return options.args;
5492
+ }
5493
+ return [{
5494
+ ...options.args?.[0],
5495
+ largeFile: true
5496
+ }, ...(options.args?.slice(1) || [])];
5497
+ };
5471
5498
  const openInputWithContext = async (context, options) => {
5472
5499
  const state = context.getState();
5473
5500
  object(state);
@@ -5557,7 +5584,8 @@ const openInputWithContext = async (context, options) => {
5557
5584
  if (editorUid === -1) {
5558
5585
  throw new Error('invalid editorUid');
5559
5586
  }
5560
- await createViewletContent(viewletModuleId, editorUid, tabId, bounds, uri, options.args, state.applicationId);
5587
+ const args = getViewletArgs(options);
5588
+ await createViewletContent(viewletModuleId, editorUid, tabId, bounds, uri, args, state.applicationId);
5561
5589
  const latestState = context.getState();
5562
5590
  let readyState = handleViewletReady(latestState, editorUid);
5563
5591
  await context.updateState(() => readyState);
@@ -6399,6 +6427,114 @@ const resetPointerDown = state => {
6399
6427
  };
6400
6428
  };
6401
6429
 
6430
+ const parseTerminalDrag = strings => {
6431
+ const value = strings.find(item => item.startsWith('lvce-terminal:'));
6432
+ if (!value) {
6433
+ return undefined;
6434
+ }
6435
+ try {
6436
+ const data = JSON.parse(value.slice('lvce-terminal:'.length));
6437
+ if (Number.isSafeInteger(data.sourceUid) && data.sourceUid > 0 && Number.isSafeInteger(data.terminalUid) && data.terminalUid > 0) {
6438
+ return data;
6439
+ }
6440
+ } catch {
6441
+ // Foreign or malformed drag data is not a terminal transfer.
6442
+ }
6443
+ return undefined;
6444
+ };
6445
+ const receiveTerminal = async (context, drag, targetGroupId) => {
6446
+ const initial = context.getState();
6447
+ const descriptor = await invoke$2('TerminalTransfer.takePanelTerminal', initial.uid, drag.sourceUid, drag.terminalUid);
6448
+ if (!descriptor) {
6449
+ return;
6450
+ }
6451
+ let tabId = -1;
6452
+ try {
6453
+ let state = context.getState();
6454
+ if (targetGroupId !== undefined) {
6455
+ state = focusEditorGroup(state, targetGroupId);
6456
+ }
6457
+ // Pin an existing preview so adoption never replaces and leaks its viewlet.
6458
+ const activeId = getActiveTabId(state);
6459
+ if (activeId !== undefined) {
6460
+ state = updateTab(state, activeId, {
6461
+ isPreview: false
6462
+ });
6463
+ }
6464
+ state = ensureActiveGroup(state, `terminal://${drag.terminalUid}`, false, descriptor.label);
6465
+ tabId = getActiveTabId(state);
6466
+ state = updateTab(state, tabId, {
6467
+ editorUid: drag.terminalUid,
6468
+ icon: descriptor.icon,
6469
+ loadingState: 'loaded',
6470
+ terminal: true
6471
+ });
6472
+ const location = findTabById(state, tabId);
6473
+ const bounds = getSelectedTabBounds(state, location.groupId);
6474
+ await invoke$2('TerminalTransfer.resize', drag.terminalUid, bounds);
6475
+ await context.updateState(() => state);
6476
+ await invoke$1(state.applicationId, 'Layout.renderMainAreaPending', state.uid);
6477
+ await focus(state);
6478
+ await invoke$2('TerminalTransfer.commit', drag.terminalUid, initial.uid);
6479
+ } catch (error) {
6480
+ if (tabId !== -1) {
6481
+ await context.updateState(state => {
6482
+ const location = findTabById(state, tabId);
6483
+ return location ? closeTab(state, location.groupId, tabId) : state;
6484
+ });
6485
+ }
6486
+ try {
6487
+ await invoke$1(initial.applicationId, 'Layout.renderMainAreaPending', initial.uid);
6488
+ } finally {
6489
+ await invoke$2('TerminalTransfer.rollback', drag.terminalUid);
6490
+ }
6491
+ throw error;
6492
+ }
6493
+ };
6494
+ const releaseTerminal = async (context, terminalUid, panelUid) => {
6495
+ const state = context.getState();
6496
+ const group = state.layout.groups.find(item => item.tabs.some(tab => tab.terminal && tab.editorUid === terminalUid));
6497
+ const tab = group?.tabs.find(item => item.terminal && item.editorUid === terminalUid);
6498
+ if (!group || !tab) {
6499
+ return;
6500
+ }
6501
+ const accepted = await invoke$2('TerminalTransfer.beginPanelTransfer', state.uid, panelUid, terminalUid);
6502
+ if (!accepted) {
6503
+ return;
6504
+ }
6505
+ try {
6506
+ await context.updateState(latest => closeTab(latest, group.id, tab.id));
6507
+ // Remove the old reference before reparenting the live DOM node.
6508
+ await invoke$1(state.applicationId, 'Layout.renderMainAreaPending', state.uid);
6509
+ await invoke$2('TerminalTransfer.attachPanelTerminal', state.uid, panelUid, terminalUid, tab.title, tab.icon);
6510
+ } catch (error) {
6511
+ const live = await invoke$2('TerminalTransfer.cancelPanelTransfer', terminalUid);
6512
+ if (live) {
6513
+ await context.updateState(latest => ({
6514
+ ...latest,
6515
+ layout: state.layout
6516
+ }));
6517
+ await invoke$1(state.applicationId, 'Layout.renderMainAreaPending', state.uid);
6518
+ }
6519
+ throw error;
6520
+ }
6521
+ };
6522
+ const handleTerminalExit = (state, terminalUid) => {
6523
+ const group = state.layout.groups.find(item => item.tabs.some(tab => tab.terminal && tab.editorUid === terminalUid));
6524
+ const tab = group?.tabs.find(item => item.terminal && item.editorUid === terminalUid);
6525
+ return group && tab ? closeTab(state, group.id, tab.id) : state;
6526
+ };
6527
+ const handlePanelDrop = async (context, panelUid, dropId) => {
6528
+ const {
6529
+ strings
6530
+ } = await getDroppedItemsByDropId(dropId, false);
6531
+ const drag = parseTerminalDrag(strings);
6532
+ if (drag?.sourceUid !== context.getState().uid) {
6533
+ return;
6534
+ }
6535
+ await releaseTerminal(context, drag.terminalUid, panelUid);
6536
+ };
6537
+
6402
6538
  const openUrisWithContext = async (context, uris, reuseExisting = true) => {
6403
6539
  for (const uri of uris) {
6404
6540
  await openUriWithContext(context, {
@@ -6737,7 +6873,23 @@ const handleDrop = async (context, dropId) => {
6737
6873
  platform
6738
6874
  } = context.getState();
6739
6875
  const isElectron = platform === Electron;
6740
- const uris = await getDroppedUrisByDropId(dropId, isElectron);
6876
+ const {
6877
+ strings,
6878
+ uris
6879
+ } = await getDroppedItemsByDropId(dropId, isElectron);
6880
+ const terminal = parseTerminalDrag(strings);
6881
+ if (terminal) {
6882
+ if (terminal.sourceUid === initialState.uid) {
6883
+ const source = initialState.layout.groups.find(group => group.tabs.some(tab => tab.terminal && tab.editorUid === terminal.terminalUid));
6884
+ const tab = source?.tabs.find(item => item.terminal && item.editorUid === terminal.terminalUid);
6885
+ if (source && tab) {
6886
+ await context.updateState(state => resetPointerDown(applyTabDrop(state, source.id, tab.id, splitDirection, tabDropIndicator?.groupId ?? targetGroupId, tabDropIndicator?.index)));
6887
+ }
6888
+ } else {
6889
+ await receiveTerminal(context, terminal, tabDropIndicator?.groupId ?? targetGroupId);
6890
+ }
6891
+ return;
6892
+ }
6741
6893
  if (draggedTab?.uri && uris.length === 1 && normalizeUri(uris[0]) === normalizeUri(draggedTab.uri)) {
6742
6894
  const tabTargetGroupId = tabDropIndicator?.groupId ?? targetGroupId;
6743
6895
  const tabTargetIndex = tabDropIndicator?.index;
@@ -8274,12 +8426,28 @@ const renderDragData = (oldState, newState) => {
8274
8426
  groups
8275
8427
  } = layout;
8276
8428
  if (pointerDownGroupIndex === -1 || pointerDownTabIndex === -1) {
8277
- return [];
8429
+ const oldTab = oldState.layout.groups[oldState.pointerDownGroupIndex]?.tabs[oldState.pointerDownTabIndex];
8430
+ return oldTab?.terminal ? ['Viewlet.setDragData', uid, {
8431
+ items: [],
8432
+ label: ''
8433
+ }] : [];
8278
8434
  }
8279
8435
  const tab = groups[pointerDownGroupIndex]?.tabs[pointerDownTabIndex];
8280
8436
  if (!tab?.uri) {
8281
8437
  return [];
8282
8438
  }
8439
+ if (tab.terminal) {
8440
+ return ['Viewlet.setDragData', uid, {
8441
+ items: [{
8442
+ data: `lvce-terminal:${JSON.stringify({
8443
+ sourceUid: uid,
8444
+ terminalUid: tab.editorUid
8445
+ })}`,
8446
+ type: 'application/x-lvce-terminal'
8447
+ }],
8448
+ label: tab.title
8449
+ }];
8450
+ }
8283
8451
  const data = ensureUri(tab.uri);
8284
8452
  return ['Viewlet.setDragData', uid, {
8285
8453
  items: [{
@@ -8641,7 +8809,7 @@ const getSavedTab = tab => {
8641
8809
  };
8642
8810
  const getFilteredGroups = groups => {
8643
8811
  return groups.map(group => {
8644
- const tabs = group.tabs.filter(tab => !tab.uri?.startsWith('untitled://')).map(getSavedTab);
8812
+ const tabs = group.tabs.filter(tab => !tab.terminal && !tab.uri?.startsWith('untitled://')).map(getSavedTab);
8645
8813
  const activeTabId = tabs.some(tab => tab.id === group.activeTabId) ? group.activeTabId : tabs[0]?.id ?? -1;
8646
8814
  return {
8647
8815
  ...group,
@@ -9010,6 +9178,7 @@ const commandMap = {
9010
9178
  'MainArea.handleIconThemeChange': wrapSerialCommand(handleIconThemeChange),
9011
9179
  'MainArea.handleMessagePort': handleDirectMessagePort,
9012
9180
  'MainArea.handleModifiedStatusChange': wrapAsyncCommand(handleModifiedStatusChangeWithContext),
9181
+ 'MainArea.handlePanelDrop': wrapSerialAsyncCommand(handlePanelDrop),
9013
9182
  'MainArea.handleResize': resize,
9014
9183
  'MainArea.handleSashCornerPointerDown': wrapSerialCommand(handleSashCornerPointerDown),
9015
9184
  'MainArea.handleSashCornerPointerMove': wrapSerialCommand(handleSashCornerPointerMove),
@@ -9023,6 +9192,7 @@ const commandMap = {
9023
9192
  'MainArea.handleTabMouseUp': wrapSerialCommand(resetPointerDown),
9024
9193
  'MainArea.handleTabsDragOver': wrapSerialCommand(handleTabsDragOver),
9025
9194
  'MainArea.handleTabsWheel': wrapSerialCommand(handleTabsWheel),
9195
+ 'MainArea.handleTerminalExit': wrapSerialCommand(handleTerminalExit),
9026
9196
  'MainArea.handleTestWorkerMessagePort': handleTestWorkerMessagePort,
9027
9197
  'MainArea.handleUriChange': wrapAsyncCommand(handleUriChangeWithContext),
9028
9198
  'MainArea.handleWorkspaceChange': wrapSerialCommand(handleWorkspaceChange),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/main-area-worker",
3
- "version": "9.64.3",
3
+ "version": "9.66.0",
4
4
  "description": "Main Area Worker",
5
5
  "repository": {
6
6
  "type": "git",