@lvce-editor/main-area-worker 6.2.0 → 6.3.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.
@@ -2071,6 +2071,11 @@ const handleClickTab = async (state, groupIndexRaw, indexRaw) => {
2071
2071
  return selectTab(state, groupIndex, index);
2072
2072
  };
2073
2073
 
2074
+ const handleDoubleClick = async state => {
2075
+ // TODO: implement handleDoubleClick
2076
+ return state;
2077
+ };
2078
+
2074
2079
  const handleResize = async (state, x, y, width, height) => {
2075
2080
  number(x);
2076
2081
  number(y);
@@ -2636,6 +2641,18 @@ const createEmptyGroup = (state, uri, requestId) => {
2636
2641
  };
2637
2642
  };
2638
2643
 
2644
+ const getActiveTabId = state => {
2645
+ const {
2646
+ layout
2647
+ } = state;
2648
+ const {
2649
+ activeGroupId,
2650
+ groups
2651
+ } = layout;
2652
+ const activeGroup = groups.find(g => g.id === activeGroupId);
2653
+ return activeGroup?.activeTabId;
2654
+ };
2655
+
2639
2656
  const openTab = (state, groupId, tab) => {
2640
2657
  const newTab = 'id' in tab && tab.id !== undefined ? tab : {
2641
2658
  ...tab,
@@ -2668,6 +2685,110 @@ const openTab = (state, groupId, tab) => {
2668
2685
  };
2669
2686
  };
2670
2687
 
2688
+ const newFile = async state => {
2689
+ object(state);
2690
+ const {
2691
+ layout,
2692
+ uid
2693
+ } = state;
2694
+ const {
2695
+ activeGroupId,
2696
+ groups
2697
+ } = layout;
2698
+
2699
+ // Find the active group
2700
+ const activeGroup = activeGroupId === undefined ? groups.find(group => group.focused) : groups.find(group => group.id === activeGroupId);
2701
+
2702
+ // Prepare initial state
2703
+ let newState = state;
2704
+ let targetGroupId;
2705
+ if (activeGroup) {
2706
+ targetGroupId = activeGroup.id;
2707
+ } else {
2708
+ // No active group, create an empty one
2709
+ newState = createEmptyGroup(state, '');
2710
+ const updatedActiveGroupId = newState.layout.activeGroupId;
2711
+ if (!updatedActiveGroupId) {
2712
+ return state;
2713
+ }
2714
+ targetGroupId = updatedActiveGroupId;
2715
+
2716
+ // Remove the tab that createEmptyGroup created, we'll add our own
2717
+ newState = {
2718
+ ...newState,
2719
+ layout: {
2720
+ ...newState.layout,
2721
+ groups: newState.layout.groups.map(group => {
2722
+ if (group.id === targetGroupId) {
2723
+ return {
2724
+ ...group,
2725
+ activeTabId: undefined,
2726
+ tabs: []
2727
+ };
2728
+ }
2729
+ return group;
2730
+ })
2731
+ }
2732
+ };
2733
+ }
2734
+
2735
+ // Get previous active tab ID for viewlet switching
2736
+ getActiveTabId(newState);
2737
+
2738
+ // Create a new empty tab
2739
+ const tabId = create$1();
2740
+ const editorUid = create$1();
2741
+ const newTab = {
2742
+ editorType: 'text',
2743
+ editorUid,
2744
+ errorMessage: '',
2745
+ icon: '',
2746
+ id: tabId,
2747
+ isDirty: false,
2748
+ language: 'plaintext',
2749
+ loadingState: 'loading',
2750
+ title: 'Untitled'
2751
+ };
2752
+ const stateWithNewTab = openTab(newState, targetGroupId, newTab);
2753
+
2754
+ // Calculate bounds: use main area bounds minus tab height
2755
+ const bounds = {
2756
+ height: stateWithNewTab.height - stateWithNewTab.tabHeight,
2757
+ width: stateWithNewTab.width,
2758
+ x: stateWithNewTab.x,
2759
+ y: stateWithNewTab.y + stateWithNewTab.tabHeight
2760
+ };
2761
+ const stateWithViewlet = createViewletForTab(stateWithNewTab, tabId);
2762
+ let intermediateState = stateWithViewlet;
2763
+
2764
+ // Switch viewlet (detach old, attach new if ready)
2765
+ const {
2766
+ newState: switchedState
2767
+ } = switchViewlet(intermediateState);
2768
+ intermediateState = switchedState;
2769
+ set(uid, state, intermediateState);
2770
+
2771
+ // Get the tab to extract editorUid
2772
+ const tabWithViewlet = findTabById(intermediateState, tabId);
2773
+ if (!tabWithViewlet) {
2774
+ return intermediateState;
2775
+ }
2776
+ const {
2777
+ editorUid: actualEditorUid
2778
+ } = tabWithViewlet.tab;
2779
+ if (actualEditorUid === -1) {
2780
+ throw new Error(`invalid editorUid`);
2781
+ }
2782
+ await createViewlet('Editor', actualEditorUid, tabId, bounds, 'untitled:///1');
2783
+
2784
+ // After viewlet is created, get the latest state and mark it as ready
2785
+ const {
2786
+ newState: latestState
2787
+ } = get(uid);
2788
+ const readyState = handleViewletReady(latestState, actualEditorUid);
2789
+ return readyState;
2790
+ };
2791
+
2671
2792
  const ensureActiveGroup = (state, uri) => {
2672
2793
  // Find the active group (by activeGroupId or focused flag)
2673
2794
  const {
@@ -2748,18 +2869,6 @@ const focusEditorGroup = (state, groupId) => {
2748
2869
  };
2749
2870
  };
2750
2871
 
2751
- const getActiveTabId = state => {
2752
- const {
2753
- layout
2754
- } = state;
2755
- const {
2756
- activeGroupId,
2757
- groups
2758
- } = layout;
2759
- const activeGroup = groups.find(g => g.id === activeGroupId);
2760
- return activeGroup?.activeTabId;
2761
- };
2762
-
2763
2872
  const getOptionUriOptions = options => {
2764
2873
  let uri = '';
2765
2874
  if (typeof options === 'string') {
@@ -2826,13 +2935,12 @@ const openUri = async (state, options) => {
2826
2935
  return newState;
2827
2936
  }
2828
2937
 
2829
- // Calculate bounds: use main area bounds minus 35px for tab height
2830
- const TAB_HEIGHT = 35;
2938
+ // Calculate bounds: use main area bounds minus tab height
2831
2939
  const bounds = {
2832
- height: newState.height - TAB_HEIGHT,
2940
+ height: newState.height - newState.tabHeight,
2833
2941
  width: newState.width,
2834
2942
  x: newState.x,
2835
- y: newState.y + TAB_HEIGHT
2943
+ y: newState.y + newState.tabHeight
2836
2944
  };
2837
2945
  const stateWithViewlet = createViewletForTab(newState, tabId);
2838
2946
  let intermediateState1 = stateWithViewlet;
@@ -3339,8 +3447,9 @@ const renderEditorGroupActions = (group, groupIndex, splitButtonEnabled) => {
3339
3447
  const renderEditorGroupHeader = (group, groupIndex, splitButtonEnabled) => {
3340
3448
  const tabsChildCount = group.tabs.length;
3341
3449
  const actions = renderEditorGroupActions(group, groupIndex, splitButtonEnabled);
3450
+ const hasActions = actions.length > 0;
3342
3451
  return [{
3343
- childCount: actions.length > 0 ? 2 : 1,
3452
+ childCount: hasActions ? 2 : 1,
3344
3453
  className: 'EditorGroupHeader',
3345
3454
  role: 'none',
3346
3455
  type: Div
@@ -3471,6 +3580,10 @@ const getActiveTab = state => {
3471
3580
  };
3472
3581
  };
3473
3582
 
3583
+ const saveEditor = async editorUid => {
3584
+ await invoke('Editor.save', editorUid);
3585
+ };
3586
+
3474
3587
  const save = async state => {
3475
3588
  const activeTabData = getActiveTab(state);
3476
3589
  if (!activeTabData) {
@@ -3482,7 +3595,7 @@ const save = async state => {
3482
3595
  if (tab.loadingState === 'loading') {
3483
3596
  return state;
3484
3597
  }
3485
- await invoke('Editor.save', tab.editorUid);
3598
+ await saveEditor(tab.editorUid);
3486
3599
  if (!tab.isDirty) {
3487
3600
  return state;
3488
3601
  }
@@ -3495,8 +3608,26 @@ const saveState = state => {
3495
3608
  const {
3496
3609
  layout
3497
3610
  } = state;
3611
+
3612
+ // Filter out untitled editors from tabs
3613
+ const filteredGroups = layout.groups.map(group => ({
3614
+ ...group,
3615
+ tabs: group.tabs.filter(tab => !tab.uri?.startsWith('untitled://'))
3616
+ }))
3617
+ // Remove groups that become empty after filtering
3618
+ .filter(group => group.tabs.length > 0);
3619
+
3620
+ // Update activeGroupId if it points to a removed group
3621
+ const {
3622
+ activeGroupId: originalActiveGroupId
3623
+ } = layout;
3624
+ const activeGroupId = originalActiveGroupId !== undefined && !filteredGroups.some(g => g.id === originalActiveGroupId) ? undefined : originalActiveGroupId;
3498
3625
  return {
3499
- layout
3626
+ layout: {
3627
+ ...layout,
3628
+ activeGroupId,
3629
+ groups: filteredGroups
3630
+ }
3500
3631
  };
3501
3632
  };
3502
3633
 
@@ -3582,11 +3713,13 @@ const commandMap = {
3582
3713
  'MainArea.handleClickAction': wrapCommand(handleClickAction),
3583
3714
  'MainArea.handleClickCloseTab': wrapCommand(handleClickCloseTab),
3584
3715
  'MainArea.handleClickTab': wrapCommand(handleClickTab),
3716
+ 'MainArea.handleDoubleClick': wrapCommand(handleDoubleClick),
3585
3717
  'MainArea.handleResize': wrapCommand(handleResize),
3586
3718
  'MainArea.handleTabContextMenu': wrapCommand(handleTabContextMenu),
3587
3719
  'MainArea.handleWorkspaceChange': wrapCommand(handleWorkspaceChange),
3588
3720
  'MainArea.initialize': initialize,
3589
3721
  'MainArea.loadContent': wrapCommand(loadContent),
3722
+ 'MainArea.newFile': wrapCommand(newFile),
3590
3723
  'MainArea.openUri': wrapCommand(openUri),
3591
3724
  'MainArea.refresh': wrapCommand(refresh),
3592
3725
  'MainArea.render2': render2,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/main-area-worker",
3
- "version": "6.2.0",
3
+ "version": "6.3.0",
4
4
  "description": "Main Area Worker",
5
5
  "repository": {
6
6
  "type": "git",