@lvce-editor/main-area-worker 6.6.0 → 6.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mainAreaWorkerMain.js +355 -179
- package/package.json +1 -1
|
@@ -1718,157 +1718,6 @@ const diff2 = uid => {
|
|
|
1718
1718
|
return result;
|
|
1719
1719
|
};
|
|
1720
1720
|
|
|
1721
|
-
const getMenuIds = () => {
|
|
1722
|
-
return [Tab];
|
|
1723
|
-
};
|
|
1724
|
-
|
|
1725
|
-
const handleClick = async (state, name) => {
|
|
1726
|
-
if (!name) {
|
|
1727
|
-
return state;
|
|
1728
|
-
}
|
|
1729
|
-
return state;
|
|
1730
|
-
};
|
|
1731
|
-
|
|
1732
|
-
const closeEditorGroup = (state, groupId) => {
|
|
1733
|
-
const {
|
|
1734
|
-
layout
|
|
1735
|
-
} = state;
|
|
1736
|
-
const {
|
|
1737
|
-
activeGroupId,
|
|
1738
|
-
groups
|
|
1739
|
-
} = layout;
|
|
1740
|
-
const groupIndex = groups.findIndex(group => group.id === groupId);
|
|
1741
|
-
if (groupIndex === -1 || groups.length <= 1) {
|
|
1742
|
-
return state;
|
|
1743
|
-
}
|
|
1744
|
-
const remainingGroups = groups.filter(group => group.id !== groupId);
|
|
1745
|
-
const baseSize = Math.floor(100 / remainingGroups.length);
|
|
1746
|
-
const remainder = 100 % remainingGroups.length;
|
|
1747
|
-
const redistributedGroups = remainingGroups.map((group, index) => ({
|
|
1748
|
-
...group,
|
|
1749
|
-
size: baseSize + (index === remainingGroups.length - 1 ? remainder : 0)
|
|
1750
|
-
}));
|
|
1751
|
-
const newActiveGroupId = activeGroupId === groupId ? remainingGroups[0].id : activeGroupId;
|
|
1752
|
-
return {
|
|
1753
|
-
...state,
|
|
1754
|
-
layout: {
|
|
1755
|
-
...layout,
|
|
1756
|
-
activeGroupId: newActiveGroupId,
|
|
1757
|
-
groups: redistributedGroups
|
|
1758
|
-
}
|
|
1759
|
-
};
|
|
1760
|
-
};
|
|
1761
|
-
|
|
1762
|
-
const getActiveGroup = (groups, activeGroupId) => {
|
|
1763
|
-
return groups.find(g => g.id === activeGroupId);
|
|
1764
|
-
};
|
|
1765
|
-
|
|
1766
|
-
const Left = 'left';
|
|
1767
|
-
const Right = 'right';
|
|
1768
|
-
|
|
1769
|
-
const splitEditorGroup$1 = (state, groupId, direction) => {
|
|
1770
|
-
const {
|
|
1771
|
-
layout
|
|
1772
|
-
} = state;
|
|
1773
|
-
const {
|
|
1774
|
-
groups
|
|
1775
|
-
} = layout;
|
|
1776
|
-
const sourceGroup = groups.find(group => group.id === groupId);
|
|
1777
|
-
if (!sourceGroup) {
|
|
1778
|
-
return state;
|
|
1779
|
-
}
|
|
1780
|
-
const newGroupId = create$1();
|
|
1781
|
-
const isHorizontalSplit = direction === Left || direction === Right;
|
|
1782
|
-
const newLayoutDirection = isHorizontalSplit ? 'horizontal' : 'vertical';
|
|
1783
|
-
const updatedGroups = groups.map(group => {
|
|
1784
|
-
if (group.id === groupId) {
|
|
1785
|
-
return {
|
|
1786
|
-
...group,
|
|
1787
|
-
focused: false,
|
|
1788
|
-
size: 50
|
|
1789
|
-
};
|
|
1790
|
-
}
|
|
1791
|
-
return group;
|
|
1792
|
-
});
|
|
1793
|
-
const newGroup = {
|
|
1794
|
-
activeTabId: undefined,
|
|
1795
|
-
focused: true,
|
|
1796
|
-
id: newGroupId,
|
|
1797
|
-
isEmpty: true,
|
|
1798
|
-
size: 50,
|
|
1799
|
-
tabs: []
|
|
1800
|
-
};
|
|
1801
|
-
let reorderedGroups;
|
|
1802
|
-
if (direction === Right || direction === 'down') {
|
|
1803
|
-
reorderedGroups = [...updatedGroups, newGroup];
|
|
1804
|
-
} else {
|
|
1805
|
-
const sourceIndex = updatedGroups.findIndex(group => group.id === groupId);
|
|
1806
|
-
reorderedGroups = [...updatedGroups.slice(0, sourceIndex), newGroup, ...updatedGroups.slice(sourceIndex)];
|
|
1807
|
-
}
|
|
1808
|
-
return {
|
|
1809
|
-
...state,
|
|
1810
|
-
layout: {
|
|
1811
|
-
activeGroupId: newGroupId,
|
|
1812
|
-
direction: newLayoutDirection,
|
|
1813
|
-
groups: reorderedGroups
|
|
1814
|
-
}
|
|
1815
|
-
};
|
|
1816
|
-
};
|
|
1817
|
-
|
|
1818
|
-
const handleClickAction = async (state, action, rawGroupId) => {
|
|
1819
|
-
if (!action) {
|
|
1820
|
-
return state;
|
|
1821
|
-
}
|
|
1822
|
-
if (state.layout.activeGroupId === undefined) {
|
|
1823
|
-
return state;
|
|
1824
|
-
}
|
|
1825
|
-
const activeGroup = getActiveGroup(state.layout.groups, state.layout.activeGroupId);
|
|
1826
|
-
if (!activeGroup) {
|
|
1827
|
-
return state;
|
|
1828
|
-
}
|
|
1829
|
-
switch (action) {
|
|
1830
|
-
case 'close-group':
|
|
1831
|
-
if (rawGroupId) {
|
|
1832
|
-
const groupId = Number.parseInt(rawGroupId, 10);
|
|
1833
|
-
if (!Number.isNaN(groupId)) {
|
|
1834
|
-
return closeEditorGroup(state, groupId);
|
|
1835
|
-
}
|
|
1836
|
-
}
|
|
1837
|
-
return state;
|
|
1838
|
-
case 'split-right':
|
|
1839
|
-
return splitEditorGroup$1(state, activeGroup.id, Right);
|
|
1840
|
-
default:
|
|
1841
|
-
return state;
|
|
1842
|
-
}
|
|
1843
|
-
};
|
|
1844
|
-
|
|
1845
|
-
const handleClickCloseTab = (state, rawGroupIndex, rawIndex) => {
|
|
1846
|
-
if (!rawGroupIndex || !rawIndex) {
|
|
1847
|
-
return state;
|
|
1848
|
-
}
|
|
1849
|
-
const groupIndex = Number.parseInt(rawGroupIndex);
|
|
1850
|
-
const index = Number.parseInt(rawIndex);
|
|
1851
|
-
const {
|
|
1852
|
-
layout
|
|
1853
|
-
} = state;
|
|
1854
|
-
const {
|
|
1855
|
-
groups
|
|
1856
|
-
} = layout;
|
|
1857
|
-
|
|
1858
|
-
// Validate indexes
|
|
1859
|
-
if (groupIndex < 0 || groupIndex >= groups.length) {
|
|
1860
|
-
return state;
|
|
1861
|
-
}
|
|
1862
|
-
const group = groups[groupIndex];
|
|
1863
|
-
if (index < 0 || index >= group.tabs.length) {
|
|
1864
|
-
return state;
|
|
1865
|
-
}
|
|
1866
|
-
const tab = group.tabs[index];
|
|
1867
|
-
const groupId = group.id;
|
|
1868
|
-
const tabId = tab.id;
|
|
1869
|
-
return closeTab(state, groupId, tabId);
|
|
1870
|
-
};
|
|
1871
|
-
|
|
1872
1721
|
const createViewlet = async (viewletModuleId, editorUid, tabId, bounds, uri) => {
|
|
1873
1722
|
await invoke('Layout.createViewlet', viewletModuleId, editorUid, tabId, bounds, uri);
|
|
1874
1723
|
};
|
|
@@ -2080,6 +1929,225 @@ const selectTab = async (state, groupIndex, index) => {
|
|
|
2080
1929
|
return newState;
|
|
2081
1930
|
};
|
|
2082
1931
|
|
|
1932
|
+
const focusNextTab = async state => {
|
|
1933
|
+
const {
|
|
1934
|
+
layout
|
|
1935
|
+
} = state;
|
|
1936
|
+
const {
|
|
1937
|
+
activeGroupId,
|
|
1938
|
+
groups
|
|
1939
|
+
} = layout;
|
|
1940
|
+
|
|
1941
|
+
// Find the active group
|
|
1942
|
+
const activeGroup = groups.find(g => g.id === activeGroupId);
|
|
1943
|
+
if (!activeGroup || activeGroup.isEmpty) {
|
|
1944
|
+
return state;
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
// Find the index of the active group
|
|
1948
|
+
const activeGroupIndex = groups.findIndex(g => g.id === activeGroupId);
|
|
1949
|
+
if (activeGroupIndex === -1) {
|
|
1950
|
+
return state;
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
// Find the current active tab index
|
|
1954
|
+
const activeTabIndex = activeGroup.tabs.findIndex(t => t.id === activeGroup.activeTabId);
|
|
1955
|
+
if (activeTabIndex === -1) {
|
|
1956
|
+
return state;
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
// If not at the last tab, select the next tab
|
|
1960
|
+
if (activeTabIndex < activeGroup.tabs.length - 1) {
|
|
1961
|
+
return selectTab(state, activeGroupIndex, activeTabIndex + 1);
|
|
1962
|
+
}
|
|
1963
|
+
return state;
|
|
1964
|
+
};
|
|
1965
|
+
|
|
1966
|
+
const focusPreviousTab = async state => {
|
|
1967
|
+
const {
|
|
1968
|
+
layout
|
|
1969
|
+
} = state;
|
|
1970
|
+
const {
|
|
1971
|
+
activeGroupId,
|
|
1972
|
+
groups
|
|
1973
|
+
} = layout;
|
|
1974
|
+
|
|
1975
|
+
// Find the active group
|
|
1976
|
+
const activeGroup = groups.find(g => g.id === activeGroupId);
|
|
1977
|
+
if (!activeGroup || activeGroup.isEmpty) {
|
|
1978
|
+
return state;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
// Find the index of the active group
|
|
1982
|
+
const activeGroupIndex = groups.findIndex(g => g.id === activeGroupId);
|
|
1983
|
+
if (activeGroupIndex === -1) {
|
|
1984
|
+
return state;
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
// Find the current active tab index
|
|
1988
|
+
const activeTabIndex = activeGroup.tabs.findIndex(t => t.id === activeGroup.activeTabId);
|
|
1989
|
+
if (activeTabIndex === -1) {
|
|
1990
|
+
return state;
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
// If not at the first tab, select the previous tab
|
|
1994
|
+
if (activeTabIndex > 0) {
|
|
1995
|
+
return selectTab(state, activeGroupIndex, activeTabIndex - 1);
|
|
1996
|
+
}
|
|
1997
|
+
return state;
|
|
1998
|
+
};
|
|
1999
|
+
|
|
2000
|
+
const getMenuIds = () => {
|
|
2001
|
+
return [Tab];
|
|
2002
|
+
};
|
|
2003
|
+
|
|
2004
|
+
const handleClick = async (state, name) => {
|
|
2005
|
+
if (!name) {
|
|
2006
|
+
return state;
|
|
2007
|
+
}
|
|
2008
|
+
return state;
|
|
2009
|
+
};
|
|
2010
|
+
|
|
2011
|
+
const closeEditorGroup = (state, groupId) => {
|
|
2012
|
+
const {
|
|
2013
|
+
layout
|
|
2014
|
+
} = state;
|
|
2015
|
+
const {
|
|
2016
|
+
activeGroupId,
|
|
2017
|
+
groups
|
|
2018
|
+
} = layout;
|
|
2019
|
+
const groupIndex = groups.findIndex(group => group.id === groupId);
|
|
2020
|
+
if (groupIndex === -1 || groups.length <= 1) {
|
|
2021
|
+
return state;
|
|
2022
|
+
}
|
|
2023
|
+
const remainingGroups = groups.filter(group => group.id !== groupId);
|
|
2024
|
+
const baseSize = Math.floor(100 / remainingGroups.length);
|
|
2025
|
+
const remainder = 100 % remainingGroups.length;
|
|
2026
|
+
const redistributedGroups = remainingGroups.map((group, index) => ({
|
|
2027
|
+
...group,
|
|
2028
|
+
size: baseSize + (index === remainingGroups.length - 1 ? remainder : 0)
|
|
2029
|
+
}));
|
|
2030
|
+
const newActiveGroupId = activeGroupId === groupId ? remainingGroups[0].id : activeGroupId;
|
|
2031
|
+
return {
|
|
2032
|
+
...state,
|
|
2033
|
+
layout: {
|
|
2034
|
+
...layout,
|
|
2035
|
+
activeGroupId: newActiveGroupId,
|
|
2036
|
+
groups: redistributedGroups
|
|
2037
|
+
}
|
|
2038
|
+
};
|
|
2039
|
+
};
|
|
2040
|
+
|
|
2041
|
+
const getActiveGroup = (groups, activeGroupId) => {
|
|
2042
|
+
return groups.find(g => g.id === activeGroupId);
|
|
2043
|
+
};
|
|
2044
|
+
|
|
2045
|
+
const Left = 'left';
|
|
2046
|
+
const Right = 'right';
|
|
2047
|
+
|
|
2048
|
+
const splitEditorGroup$1 = (state, groupId, direction) => {
|
|
2049
|
+
const {
|
|
2050
|
+
layout
|
|
2051
|
+
} = state;
|
|
2052
|
+
const {
|
|
2053
|
+
groups
|
|
2054
|
+
} = layout;
|
|
2055
|
+
const sourceGroup = groups.find(group => group.id === groupId);
|
|
2056
|
+
if (!sourceGroup) {
|
|
2057
|
+
return state;
|
|
2058
|
+
}
|
|
2059
|
+
const newGroupId = create$1();
|
|
2060
|
+
const isHorizontalSplit = direction === Left || direction === Right;
|
|
2061
|
+
const newLayoutDirection = isHorizontalSplit ? 'horizontal' : 'vertical';
|
|
2062
|
+
const updatedGroups = groups.map(group => {
|
|
2063
|
+
if (group.id === groupId) {
|
|
2064
|
+
return {
|
|
2065
|
+
...group,
|
|
2066
|
+
focused: false,
|
|
2067
|
+
size: 50
|
|
2068
|
+
};
|
|
2069
|
+
}
|
|
2070
|
+
return group;
|
|
2071
|
+
});
|
|
2072
|
+
const newGroup = {
|
|
2073
|
+
activeTabId: undefined,
|
|
2074
|
+
focused: true,
|
|
2075
|
+
id: newGroupId,
|
|
2076
|
+
isEmpty: true,
|
|
2077
|
+
size: 50,
|
|
2078
|
+
tabs: []
|
|
2079
|
+
};
|
|
2080
|
+
let reorderedGroups;
|
|
2081
|
+
if (direction === Right || direction === 'down') {
|
|
2082
|
+
reorderedGroups = [...updatedGroups, newGroup];
|
|
2083
|
+
} else {
|
|
2084
|
+
const sourceIndex = updatedGroups.findIndex(group => group.id === groupId);
|
|
2085
|
+
reorderedGroups = [...updatedGroups.slice(0, sourceIndex), newGroup, ...updatedGroups.slice(sourceIndex)];
|
|
2086
|
+
}
|
|
2087
|
+
return {
|
|
2088
|
+
...state,
|
|
2089
|
+
layout: {
|
|
2090
|
+
activeGroupId: newGroupId,
|
|
2091
|
+
direction: newLayoutDirection,
|
|
2092
|
+
groups: reorderedGroups
|
|
2093
|
+
}
|
|
2094
|
+
};
|
|
2095
|
+
};
|
|
2096
|
+
|
|
2097
|
+
const handleClickAction = async (state, action, rawGroupId) => {
|
|
2098
|
+
if (!action) {
|
|
2099
|
+
return state;
|
|
2100
|
+
}
|
|
2101
|
+
if (state.layout.activeGroupId === undefined) {
|
|
2102
|
+
return state;
|
|
2103
|
+
}
|
|
2104
|
+
const activeGroup = getActiveGroup(state.layout.groups, state.layout.activeGroupId);
|
|
2105
|
+
if (!activeGroup) {
|
|
2106
|
+
return state;
|
|
2107
|
+
}
|
|
2108
|
+
switch (action) {
|
|
2109
|
+
case 'close-group':
|
|
2110
|
+
if (rawGroupId) {
|
|
2111
|
+
const groupId = Number.parseInt(rawGroupId, 10);
|
|
2112
|
+
if (!Number.isNaN(groupId)) {
|
|
2113
|
+
return closeEditorGroup(state, groupId);
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
return state;
|
|
2117
|
+
case 'split-right':
|
|
2118
|
+
return splitEditorGroup$1(state, activeGroup.id, Right);
|
|
2119
|
+
default:
|
|
2120
|
+
return state;
|
|
2121
|
+
}
|
|
2122
|
+
};
|
|
2123
|
+
|
|
2124
|
+
const handleClickCloseTab = (state, rawGroupIndex, rawIndex) => {
|
|
2125
|
+
if (!rawGroupIndex || !rawIndex) {
|
|
2126
|
+
return state;
|
|
2127
|
+
}
|
|
2128
|
+
const groupIndex = Number.parseInt(rawGroupIndex);
|
|
2129
|
+
const index = Number.parseInt(rawIndex);
|
|
2130
|
+
const {
|
|
2131
|
+
layout
|
|
2132
|
+
} = state;
|
|
2133
|
+
const {
|
|
2134
|
+
groups
|
|
2135
|
+
} = layout;
|
|
2136
|
+
|
|
2137
|
+
// Validate indexes
|
|
2138
|
+
if (groupIndex < 0 || groupIndex >= groups.length) {
|
|
2139
|
+
return state;
|
|
2140
|
+
}
|
|
2141
|
+
const group = groups[groupIndex];
|
|
2142
|
+
if (index < 0 || index >= group.tabs.length) {
|
|
2143
|
+
return state;
|
|
2144
|
+
}
|
|
2145
|
+
const tab = group.tabs[index];
|
|
2146
|
+
const groupId = group.id;
|
|
2147
|
+
const tabId = tab.id;
|
|
2148
|
+
return closeTab(state, groupId, tabId);
|
|
2149
|
+
};
|
|
2150
|
+
|
|
2083
2151
|
const handleClickTab = async (state, groupIndexRaw, indexRaw) => {
|
|
2084
2152
|
if (!groupIndexRaw || !indexRaw) {
|
|
2085
2153
|
return state;
|
|
@@ -2094,6 +2162,36 @@ const handleDoubleClick = async state => {
|
|
|
2094
2162
|
return state;
|
|
2095
2163
|
};
|
|
2096
2164
|
|
|
2165
|
+
const handleModifiedStatusChange = (state, uri, newStatus) => {
|
|
2166
|
+
const {
|
|
2167
|
+
layout
|
|
2168
|
+
} = state;
|
|
2169
|
+
const {
|
|
2170
|
+
groups
|
|
2171
|
+
} = layout;
|
|
2172
|
+
const updatedGroups = groups.map(group => {
|
|
2173
|
+
return {
|
|
2174
|
+
...group,
|
|
2175
|
+
tabs: group.tabs.map(tab => {
|
|
2176
|
+
if (tab.uri === uri) {
|
|
2177
|
+
return {
|
|
2178
|
+
...tab,
|
|
2179
|
+
isDirty: newStatus
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2182
|
+
return tab;
|
|
2183
|
+
})
|
|
2184
|
+
};
|
|
2185
|
+
});
|
|
2186
|
+
return {
|
|
2187
|
+
...state,
|
|
2188
|
+
layout: {
|
|
2189
|
+
...layout,
|
|
2190
|
+
groups: updatedGroups
|
|
2191
|
+
}
|
|
2192
|
+
};
|
|
2193
|
+
};
|
|
2194
|
+
|
|
2097
2195
|
const handleResize = async (state, x, y, width, height) => {
|
|
2098
2196
|
number(x);
|
|
2099
2197
|
number(y);
|
|
@@ -2976,7 +3074,7 @@ const openUri = async (state, options) => {
|
|
|
2976
3074
|
} = state;
|
|
2977
3075
|
const uri = getOptionUriOptions(options);
|
|
2978
3076
|
|
|
2979
|
-
// Check if a tab with this URI already exists
|
|
3077
|
+
// Check if a tab with this URI already exists in the passed-in state
|
|
2980
3078
|
const existingTab = findTabByUri(state, uri);
|
|
2981
3079
|
if (existingTab) {
|
|
2982
3080
|
// Tab exists, switch to it and focus its group
|
|
@@ -2986,22 +3084,56 @@ const openUri = async (state, options) => {
|
|
|
2986
3084
|
|
|
2987
3085
|
// Get previous active tab ID for viewlet switching
|
|
2988
3086
|
getActiveTabId(state);
|
|
2989
|
-
|
|
3087
|
+
|
|
3088
|
+
// Check if there's existing state in the global store
|
|
3089
|
+
const stateFromStore = get(uid);
|
|
3090
|
+
let currentState;
|
|
3091
|
+
if (stateFromStore) {
|
|
3092
|
+
const storedState = stateFromStore.newState;
|
|
3093
|
+
// Use the stored state if it has more tabs than the passed-in state
|
|
3094
|
+
// (indicating concurrent calls have already added tabs)
|
|
3095
|
+
// Otherwise use the passed-in state (test setup with initial data)
|
|
3096
|
+
const storedTabCount = storedState.layout.groups.reduce((sum, g) => sum + g.tabs.length, 0);
|
|
3097
|
+
const passedTabCount = state.layout.groups.reduce((sum, g) => sum + g.tabs.length, 0);
|
|
3098
|
+
if (storedTabCount > passedTabCount) {
|
|
3099
|
+
// Stored state has more tabs - concurrent calls have added tabs
|
|
3100
|
+
currentState = storedState;
|
|
3101
|
+
} else {
|
|
3102
|
+
// Passed-in state has same or more tabs, use it (likely fresh test setup)
|
|
3103
|
+
currentState = state;
|
|
3104
|
+
set(uid, state, state);
|
|
3105
|
+
}
|
|
3106
|
+
} else {
|
|
3107
|
+
// No state in store yet, register the passed-in state
|
|
3108
|
+
currentState = state;
|
|
3109
|
+
set(uid, state, state);
|
|
3110
|
+
}
|
|
3111
|
+
|
|
3112
|
+
// Add tab to state BEFORE any async calls to prevent race conditions
|
|
3113
|
+
const newState = ensureActiveGroup(currentState, uri);
|
|
2990
3114
|
const tabId = getActiveTabId(newState);
|
|
3115
|
+
|
|
3116
|
+
// Save state immediately after adding tab
|
|
3117
|
+
set(uid, currentState, newState);
|
|
2991
3118
|
const viewletModuleId = await getViewletModuleId(uri);
|
|
3119
|
+
|
|
3120
|
+
// After async call, get the latest state to account for any concurrent changes
|
|
3121
|
+
const {
|
|
3122
|
+
newState: stateAfterModuleId
|
|
3123
|
+
} = get(uid);
|
|
2992
3124
|
if (!viewletModuleId) {
|
|
2993
3125
|
// TODO display some kind of errro that editor couldn't be opened
|
|
2994
|
-
return
|
|
3126
|
+
return stateAfterModuleId;
|
|
2995
3127
|
}
|
|
2996
3128
|
|
|
2997
3129
|
// Calculate bounds: use main area bounds minus tab height
|
|
2998
3130
|
const bounds = {
|
|
2999
|
-
height:
|
|
3000
|
-
width:
|
|
3001
|
-
x:
|
|
3002
|
-
y:
|
|
3131
|
+
height: stateAfterModuleId.height - stateAfterModuleId.tabHeight,
|
|
3132
|
+
width: stateAfterModuleId.width,
|
|
3133
|
+
x: stateAfterModuleId.x,
|
|
3134
|
+
y: stateAfterModuleId.y + stateAfterModuleId.tabHeight
|
|
3003
3135
|
};
|
|
3004
|
-
const stateWithViewlet = createViewletForTab(
|
|
3136
|
+
const stateWithViewlet = createViewletForTab(stateAfterModuleId, tabId);
|
|
3005
3137
|
let intermediateState1 = stateWithViewlet;
|
|
3006
3138
|
|
|
3007
3139
|
// Switch viewlet (detach old, attach new if ready)
|
|
@@ -3009,7 +3141,7 @@ const openUri = async (state, options) => {
|
|
|
3009
3141
|
newState: switchedState
|
|
3010
3142
|
} = switchViewlet(intermediateState1);
|
|
3011
3143
|
intermediateState1 = switchedState;
|
|
3012
|
-
set(uid,
|
|
3144
|
+
set(uid, stateWithViewlet, intermediateState1);
|
|
3013
3145
|
|
|
3014
3146
|
// Get the tab to extract editorUid
|
|
3015
3147
|
const tabWithViewlet = findTabById(intermediateState1, tabId);
|
|
@@ -3033,6 +3165,9 @@ const openUri = async (state, options) => {
|
|
|
3033
3165
|
// Attachment is handled automatically by virtual DOM reference nodes
|
|
3034
3166
|
const readyState = handleViewletReady(latestState, editorUid);
|
|
3035
3167
|
|
|
3168
|
+
// Save state before async icon request
|
|
3169
|
+
set(uid, intermediateState1, readyState);
|
|
3170
|
+
|
|
3036
3171
|
// Request file icon for the newly opened tab
|
|
3037
3172
|
try {
|
|
3038
3173
|
const newTab = findTabById(readyState, tabId);
|
|
@@ -3040,15 +3175,20 @@ const openUri = async (state, options) => {
|
|
|
3040
3175
|
const {
|
|
3041
3176
|
newFileIconCache
|
|
3042
3177
|
} = await getFileIconsForTabs([newTab.tab], readyState.fileIconCache);
|
|
3178
|
+
|
|
3179
|
+
// After async call, get the latest state again
|
|
3180
|
+
const {
|
|
3181
|
+
newState: stateBeforeIconUpdate
|
|
3182
|
+
} = get(uid);
|
|
3043
3183
|
const icon = newFileIconCache[newTab.tab.uri] || '';
|
|
3044
3184
|
|
|
3045
|
-
// Update the tab with the icon
|
|
3185
|
+
// Update the tab with the icon in the latest state
|
|
3046
3186
|
const stateWithIcon = {
|
|
3047
|
-
...
|
|
3187
|
+
...stateBeforeIconUpdate,
|
|
3048
3188
|
fileIconCache: newFileIconCache,
|
|
3049
3189
|
layout: {
|
|
3050
|
-
...
|
|
3051
|
-
groups:
|
|
3190
|
+
...stateBeforeIconUpdate.layout,
|
|
3191
|
+
groups: stateBeforeIconUpdate.layout.groups.map(group => ({
|
|
3052
3192
|
...group,
|
|
3053
3193
|
tabs: group.tabs.map(tab => tab.id === tabId ? {
|
|
3054
3194
|
...tab,
|
|
@@ -3057,12 +3197,20 @@ const openUri = async (state, options) => {
|
|
|
3057
3197
|
}))
|
|
3058
3198
|
}
|
|
3059
3199
|
};
|
|
3200
|
+
|
|
3201
|
+
// Save the state with icon update so concurrent calls can see it
|
|
3202
|
+
set(uid, stateBeforeIconUpdate, stateWithIcon);
|
|
3060
3203
|
return stateWithIcon;
|
|
3061
3204
|
}
|
|
3062
3205
|
} catch {
|
|
3063
3206
|
// If icon request fails, continue without icon
|
|
3064
3207
|
}
|
|
3065
|
-
|
|
3208
|
+
|
|
3209
|
+
// Get final latest state
|
|
3210
|
+
const {
|
|
3211
|
+
newState: finalState
|
|
3212
|
+
} = get(uid);
|
|
3213
|
+
return finalState;
|
|
3066
3214
|
};
|
|
3067
3215
|
|
|
3068
3216
|
const refresh = state => {
|
|
@@ -3437,11 +3585,48 @@ const HandleClickClose = 12;
|
|
|
3437
3585
|
const HandleClickTab = 13;
|
|
3438
3586
|
const HandleTabContextMenu = 14;
|
|
3439
3587
|
|
|
3588
|
+
const renderTabActions = (isDirty, tabIndex, groupIndex) => {
|
|
3589
|
+
if (isDirty) {
|
|
3590
|
+
return [{
|
|
3591
|
+
childCount: 1,
|
|
3592
|
+
className: 'EditorTabCloseButton',
|
|
3593
|
+
'data-groupIndex': groupIndex,
|
|
3594
|
+
'data-index': tabIndex,
|
|
3595
|
+
type: Div
|
|
3596
|
+
}, {
|
|
3597
|
+
childCount: 0,
|
|
3598
|
+
className: 'MaskIcon MaskIconCircleFilled',
|
|
3599
|
+
type: Div
|
|
3600
|
+
}];
|
|
3601
|
+
}
|
|
3602
|
+
return [{
|
|
3603
|
+
'aria-label': 'Close',
|
|
3604
|
+
childCount: 1,
|
|
3605
|
+
className: 'EditorTabCloseButton',
|
|
3606
|
+
'data-groupIndex': groupIndex,
|
|
3607
|
+
'data-index': tabIndex,
|
|
3608
|
+
onClick: HandleClickClose,
|
|
3609
|
+
type: Button$1
|
|
3610
|
+
}, {
|
|
3611
|
+
childCount: 0,
|
|
3612
|
+
className: 'MaskIcon MaskIconClose',
|
|
3613
|
+
type: Div
|
|
3614
|
+
}];
|
|
3615
|
+
};
|
|
3616
|
+
|
|
3440
3617
|
const renderTab = (tab, isActive, tabIndex, groupIndex) => {
|
|
3618
|
+
const closeButtonNodes = renderTabActions(tab.isDirty, tabIndex, groupIndex);
|
|
3619
|
+
let className = 'MainTab';
|
|
3620
|
+
if (isActive) {
|
|
3621
|
+
className += ' MainTabSelected';
|
|
3622
|
+
}
|
|
3623
|
+
if (tab.isDirty) {
|
|
3624
|
+
className += ' MainTabModified';
|
|
3625
|
+
}
|
|
3441
3626
|
return [{
|
|
3442
3627
|
'aria-selected': isActive,
|
|
3443
3628
|
childCount: 3,
|
|
3444
|
-
className
|
|
3629
|
+
className,
|
|
3445
3630
|
'data-groupIndex': groupIndex,
|
|
3446
3631
|
'data-index': tabIndex,
|
|
3447
3632
|
onClick: HandleClickTab,
|
|
@@ -3459,19 +3644,7 @@ const renderTab = (tab, isActive, tabIndex, groupIndex) => {
|
|
|
3459
3644
|
childCount: 1,
|
|
3460
3645
|
className: 'TabTitle',
|
|
3461
3646
|
type: Span
|
|
3462
|
-
}, text(tab.
|
|
3463
|
-
'aria-label': 'Close',
|
|
3464
|
-
childCount: 1,
|
|
3465
|
-
className: 'EditorTabCloseButton',
|
|
3466
|
-
'data-groupIndex': groupIndex,
|
|
3467
|
-
'data-index': tabIndex,
|
|
3468
|
-
onClick: HandleClickClose,
|
|
3469
|
-
type: Button$1
|
|
3470
|
-
}, {
|
|
3471
|
-
childCount: 0,
|
|
3472
|
-
className: 'MaskIcon MaskIconClose',
|
|
3473
|
-
type: Div
|
|
3474
|
-
}];
|
|
3647
|
+
}, text(tab.title), ...closeButtonNodes];
|
|
3475
3648
|
};
|
|
3476
3649
|
|
|
3477
3650
|
const getTabsVirtualDom = (group, groupIndex, tabsChildCount) => {
|
|
@@ -3767,6 +3940,8 @@ const commandMap = {
|
|
|
3767
3940
|
'MainArea.closeFocusedTab': wrapCommand(closeFocusedTab),
|
|
3768
3941
|
'MainArea.create': create,
|
|
3769
3942
|
'MainArea.diff2': diff2,
|
|
3943
|
+
'MainArea.focusNextTab': wrapCommand(focusNextTab),
|
|
3944
|
+
'MainArea.focusPreviousTab': wrapCommand(focusPreviousTab),
|
|
3770
3945
|
'MainArea.getCommandIds': getCommandIds,
|
|
3771
3946
|
'MainArea.getMenuEntries': wrapGetter(getMenuEntries),
|
|
3772
3947
|
'MainArea.getMenuIds': getMenuIds,
|
|
@@ -3775,6 +3950,7 @@ const commandMap = {
|
|
|
3775
3950
|
'MainArea.handleClickCloseTab': wrapCommand(handleClickCloseTab),
|
|
3776
3951
|
'MainArea.handleClickTab': wrapCommand(handleClickTab),
|
|
3777
3952
|
'MainArea.handleDoubleClick': wrapCommand(handleDoubleClick),
|
|
3953
|
+
'MainArea.handleModifiedStatusChange': wrapCommand(handleModifiedStatusChange),
|
|
3778
3954
|
'MainArea.handleResize': wrapCommand(handleResize),
|
|
3779
3955
|
'MainArea.handleTabContextMenu': wrapCommand(handleTabContextMenu),
|
|
3780
3956
|
'MainArea.handleUriChange': wrapCommand(handleUriChange),
|