@lvce-editor/main-area-worker 9.27.0 → 9.28.1
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 +750 -569
- package/package.json +1 -1
|
@@ -599,7 +599,14 @@ class IpcError extends VError {
|
|
|
599
599
|
const cause = new Error(message);
|
|
600
600
|
// @ts-ignore
|
|
601
601
|
cause.code = code;
|
|
602
|
-
|
|
602
|
+
if (stack) {
|
|
603
|
+
Object.defineProperty(cause, 'stack', {
|
|
604
|
+
configurable: true,
|
|
605
|
+
enumerable: false,
|
|
606
|
+
value: stack,
|
|
607
|
+
writable: true
|
|
608
|
+
});
|
|
609
|
+
}
|
|
603
610
|
super(cause, betterMessage);
|
|
604
611
|
} else {
|
|
605
612
|
super(betterMessage);
|
|
@@ -1898,700 +1905,769 @@ const closeTab = (state, groupId, tabId) => {
|
|
|
1898
1905
|
return withGroups(stateWithClosedTab, newGroups);
|
|
1899
1906
|
};
|
|
1900
1907
|
|
|
1901
|
-
const
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
const group = layout.groups.find(g => g.id === groupId);
|
|
1906
|
-
return group?.tabs.find(t => t.id === tabId);
|
|
1908
|
+
const handleAttach = async command => {
|
|
1909
|
+
// TODO find a better way to append editors
|
|
1910
|
+
const parentNodeSelector = '.editor-groups-container, .EditorGroup';
|
|
1911
|
+
await invoke('Layout.attachViewlet', parentNodeSelector, command.instanceId);
|
|
1907
1912
|
};
|
|
1908
1913
|
|
|
1909
|
-
const
|
|
1910
|
-
|
|
1914
|
+
const getTitle$1 = async editorUid => {
|
|
1915
|
+
try {
|
|
1916
|
+
const title = await invoke('Viewlet.getTitle', editorUid);
|
|
1917
|
+
return typeof title === 'string' && title ? title : undefined;
|
|
1918
|
+
} catch {
|
|
1919
|
+
return undefined;
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
const createViewlet = async (viewletModuleId, editorUid, tabId, bounds, uri) => {
|
|
1923
|
+
await invoke('Layout.createViewlet', viewletModuleId, editorUid, tabId, bounds, uri);
|
|
1924
|
+
return getTitle$1(editorUid);
|
|
1911
1925
|
};
|
|
1912
1926
|
|
|
1913
|
-
const
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1927
|
+
const {
|
|
1928
|
+
get,
|
|
1929
|
+
getCommandIds,
|
|
1930
|
+
getKeys: getKeys$1,
|
|
1931
|
+
registerCommands,
|
|
1932
|
+
set,
|
|
1933
|
+
wrapAsyncCommand,
|
|
1934
|
+
wrapGetter,
|
|
1935
|
+
wrapSerialAsyncCommand,
|
|
1936
|
+
wrapSerialCommand
|
|
1937
|
+
} = create$f();
|
|
1938
|
+
|
|
1939
|
+
const create$2 = () => {
|
|
1940
|
+
return Math.random();
|
|
1925
1941
|
};
|
|
1926
1942
|
|
|
1927
|
-
const
|
|
1943
|
+
const updateTab = (state, tabId, updates) => {
|
|
1928
1944
|
const {
|
|
1929
1945
|
layout
|
|
1930
1946
|
} = state;
|
|
1931
1947
|
const {
|
|
1932
1948
|
groups
|
|
1933
1949
|
} = layout;
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
const entries = state.layout.groups.flatMap((group, groupIndex) => {
|
|
1953
|
-
return group.tabs.map((tab, tabIndex) => ({
|
|
1954
|
-
group,
|
|
1955
|
-
groupIndex,
|
|
1956
|
-
tab,
|
|
1957
|
-
tabIndex
|
|
1958
|
-
}));
|
|
1950
|
+
const updatedGroups = groups.map(group => {
|
|
1951
|
+
const tabIndex = group.tabs.findIndex(t => t.id === tabId);
|
|
1952
|
+
if (tabIndex === -1) {
|
|
1953
|
+
return group;
|
|
1954
|
+
}
|
|
1955
|
+
const updatedTabs = group.tabs.map((tab, index) => {
|
|
1956
|
+
if (index === tabIndex) {
|
|
1957
|
+
return {
|
|
1958
|
+
...tab,
|
|
1959
|
+
...updates
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1962
|
+
return tab;
|
|
1963
|
+
});
|
|
1964
|
+
return {
|
|
1965
|
+
...group,
|
|
1966
|
+
tabs: updatedTabs
|
|
1967
|
+
};
|
|
1959
1968
|
});
|
|
1960
|
-
return
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
...group,
|
|
1968
|
-
size: baseSize + (index === groups.length - 1 ? remainder : 0)
|
|
1969
|
-
}));
|
|
1969
|
+
return {
|
|
1970
|
+
...state,
|
|
1971
|
+
layout: {
|
|
1972
|
+
...layout,
|
|
1973
|
+
groups: updatedGroups
|
|
1974
|
+
}
|
|
1975
|
+
};
|
|
1970
1976
|
};
|
|
1971
1977
|
|
|
1972
|
-
const
|
|
1973
|
-
if (Number.isNaN(groupId)) {
|
|
1974
|
-
return state;
|
|
1975
|
-
}
|
|
1978
|
+
const findTab = (state, tabId) => {
|
|
1976
1979
|
const {
|
|
1977
1980
|
layout
|
|
1978
1981
|
} = state;
|
|
1979
1982
|
const {
|
|
1980
|
-
activeGroupId,
|
|
1981
1983
|
groups
|
|
1982
1984
|
} = layout;
|
|
1983
|
-
const
|
|
1984
|
-
|
|
1985
|
-
|
|
1985
|
+
for (const group of groups) {
|
|
1986
|
+
const tab = group.tabs.find(t => t.id === tabId);
|
|
1987
|
+
if (tab) {
|
|
1988
|
+
return tab;
|
|
1989
|
+
}
|
|
1986
1990
|
}
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
+
return undefined;
|
|
1992
|
+
};
|
|
1993
|
+
const loadFileContent = async path => {
|
|
1994
|
+
const content = await readFile(path);
|
|
1995
|
+
return content;
|
|
1996
|
+
};
|
|
1997
|
+
const getLoadFileErrorMessage = error => {
|
|
1998
|
+
if (!(error instanceof Error)) {
|
|
1999
|
+
return 'Failed to load file content';
|
|
2000
|
+
}
|
|
2001
|
+
if (error.message.includes('EISDIR') || error.message.includes('illegal operation on a directory') || error.message.includes('is a directory')) {
|
|
2002
|
+
return 'Expected a file but received a folder';
|
|
2003
|
+
}
|
|
2004
|
+
return error.message;
|
|
1991
2005
|
};
|
|
2006
|
+
const loadTabContentAsync = async (tabId, path, requestId, getLatestState) => {
|
|
2007
|
+
try {
|
|
2008
|
+
await loadFileContent(path);
|
|
1992
2009
|
|
|
1993
|
-
|
|
1994
|
-
|
|
2010
|
+
// Check for race condition: get the latest state
|
|
2011
|
+
const latestState = getLatestState();
|
|
2012
|
+
const latestTab = findTab(latestState, tabId);
|
|
2013
|
+
|
|
2014
|
+
// If the tab no longer exists, discard this result
|
|
2015
|
+
if (!latestTab) {
|
|
2016
|
+
return latestState;
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
// If the tab is no longer in loading state, discard this result (newer request started)
|
|
2020
|
+
if (latestTab.loadingState !== 'loading') {
|
|
2021
|
+
return latestState;
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
// Assign editorUid if tab doesn't have one yet
|
|
2025
|
+
const editorUid = latestTab.editorUid === -1 ? create$2() : latestTab.editorUid;
|
|
2026
|
+
return updateTab(latestState, tabId, {
|
|
2027
|
+
editorUid,
|
|
2028
|
+
errorMessage: undefined,
|
|
2029
|
+
loadingState: 'loaded'
|
|
2030
|
+
});
|
|
2031
|
+
} catch (error) {
|
|
2032
|
+
// Check for race condition before updating with error
|
|
2033
|
+
const latestState = getLatestState();
|
|
2034
|
+
const latestTab = findTab(latestState, tabId);
|
|
2035
|
+
if (!latestTab) {
|
|
2036
|
+
return latestState;
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
// If the tab is no longer in loading state, discard this result (newer request started)
|
|
2040
|
+
if (latestTab.loadingState !== 'loading') {
|
|
2041
|
+
return latestState;
|
|
2042
|
+
}
|
|
2043
|
+
const errorMessage = getLoadFileErrorMessage(error);
|
|
2044
|
+
return updateTab(latestState, tabId, {
|
|
2045
|
+
errorMessage,
|
|
2046
|
+
loadingState: 'error'
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
1995
2049
|
};
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
if (!focusedGroup) {
|
|
2050
|
+
|
|
2051
|
+
/**
|
|
2052
|
+
* SAFE: Create viewlet for a tab (no visible side effects)
|
|
2053
|
+
* Can be called eagerly when tab is opened - the viewlet loads in the background.
|
|
2054
|
+
*/
|
|
2055
|
+
const createViewletForTab = (state, tabId, viewletModuleId, bounds) => {
|
|
2056
|
+
const tab = findTab(state, tabId);
|
|
2057
|
+
if (!tab) {
|
|
2005
2058
|
return state;
|
|
2006
2059
|
}
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
if (activeTabId === undefined) {
|
|
2060
|
+
|
|
2061
|
+
// If tab already has an editorUid or is loading/loaded, don't recreate
|
|
2062
|
+
if (tab.editorUid !== -1 || tab.loadingState === 'loading' || tab.loadingState === 'loaded') {
|
|
2011
2063
|
return state;
|
|
2012
2064
|
}
|
|
2013
|
-
|
|
2065
|
+
const editorUid = create$2();
|
|
2066
|
+
const newState = updateTab(state, tabId, {
|
|
2067
|
+
editorUid
|
|
2068
|
+
});
|
|
2069
|
+
return newState;
|
|
2014
2070
|
};
|
|
2015
2071
|
|
|
2016
|
-
|
|
2072
|
+
/**
|
|
2073
|
+
* Called when switching tabs.
|
|
2074
|
+
* With reference nodes, attachment/detachment is handled automatically by virtual DOM rendering.
|
|
2075
|
+
* No attach/detach commands needed - virtual DOM will render the correct reference at each position.
|
|
2076
|
+
*/
|
|
2077
|
+
const switchViewlet = (state, fromTabId, toTabId) => {
|
|
2078
|
+
// No commands needed - virtual DOM reference nodes handle attachment automatically
|
|
2079
|
+
// Virtual DOM will:
|
|
2080
|
+
// 1. Remove the old reference node from the previous active tab
|
|
2081
|
+
// 2. Add the new reference node for the now-active tab
|
|
2082
|
+
// This achieves the same effect as detach/attach without explicit commands
|
|
2083
|
+
|
|
2084
|
+
return {
|
|
2085
|
+
commands: [],
|
|
2086
|
+
newState: state
|
|
2087
|
+
};
|
|
2088
|
+
};
|
|
2089
|
+
|
|
2090
|
+
const findTabByEditorUid = (state, editorUid) => {
|
|
2017
2091
|
const {
|
|
2018
2092
|
layout
|
|
2019
2093
|
} = state;
|
|
2020
2094
|
const {
|
|
2021
|
-
activeGroupId,
|
|
2022
2095
|
groups
|
|
2023
2096
|
} = layout;
|
|
2024
|
-
const
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
if (!group) {
|
|
2030
|
-
return state;
|
|
2031
|
-
}
|
|
2032
|
-
const {
|
|
2033
|
-
activeTabId
|
|
2034
|
-
} = group;
|
|
2035
|
-
if (activeTabId === undefined) {
|
|
2036
|
-
return state;
|
|
2097
|
+
for (const group of groups) {
|
|
2098
|
+
const tab = group.tabs.find(t => t.editorUid === editorUid);
|
|
2099
|
+
if (tab) {
|
|
2100
|
+
return tab;
|
|
2101
|
+
}
|
|
2037
2102
|
}
|
|
2038
|
-
|
|
2039
|
-
group,
|
|
2040
|
-
groupIndex: groups.findIndex(g => g.id === targetGroupId),
|
|
2041
|
-
tab,
|
|
2042
|
-
tabIndex
|
|
2043
|
-
})).filter(entry => entry.tab.id !== activeTabId);
|
|
2044
|
-
const newGroups = groups.map(g => {
|
|
2045
|
-
if (g.id === targetGroupId) {
|
|
2046
|
-
const newTabs = g.tabs.filter(tab => tab.id === activeTabId);
|
|
2047
|
-
return {
|
|
2048
|
-
...g,
|
|
2049
|
-
activeTabId,
|
|
2050
|
-
isEmpty: newTabs.length === 0,
|
|
2051
|
-
tabs: newTabs
|
|
2052
|
-
};
|
|
2053
|
-
}
|
|
2054
|
-
return g;
|
|
2055
|
-
});
|
|
2056
|
-
return {
|
|
2057
|
-
...addClosedTabs(state, closedTabs),
|
|
2058
|
-
layout: {
|
|
2059
|
-
...layout,
|
|
2060
|
-
groups: newGroups
|
|
2061
|
-
}
|
|
2062
|
-
};
|
|
2103
|
+
return undefined;
|
|
2063
2104
|
};
|
|
2064
2105
|
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2106
|
+
/**
|
|
2107
|
+
* Called when renderer reports viewlet finished creating.
|
|
2108
|
+
* With reference nodes, attachment is handled automatically by virtual DOM rendering.
|
|
2109
|
+
* No commands needed - state update is sufficient.
|
|
2110
|
+
*/
|
|
2111
|
+
const handleViewletReady = (state, editorUid, title) => {
|
|
2112
|
+
if (editorUid === -1) {
|
|
2113
|
+
throw new Error('Invalid editorUid -1');
|
|
2071
2114
|
}
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2115
|
+
// Find the tab by viewletRequestId
|
|
2116
|
+
const tab = findTabByEditorUid(state, editorUid);
|
|
2117
|
+
if (!tab) {
|
|
2118
|
+
// Tab was closed, dispose viewlet
|
|
2119
|
+
return state;
|
|
2075
2120
|
}
|
|
2076
|
-
|
|
2121
|
+
|
|
2122
|
+
// Mark viewlet as ready and set instance id
|
|
2123
|
+
// Reference nodes will handle rendering at the correct position automatically
|
|
2124
|
+
const newState = updateTab(state, tab.id, {
|
|
2125
|
+
editorUid,
|
|
2126
|
+
loadingState: 'loaded',
|
|
2127
|
+
...(title && {
|
|
2128
|
+
title
|
|
2129
|
+
})
|
|
2130
|
+
});
|
|
2131
|
+
|
|
2132
|
+
// No attach commands needed - virtual DOM reference nodes handle positioning
|
|
2133
|
+
return newState;
|
|
2077
2134
|
};
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
const
|
|
2084
|
-
if (
|
|
2085
|
-
return
|
|
2135
|
+
|
|
2136
|
+
/**
|
|
2137
|
+
* Dispose viewlet when tab is closed.
|
|
2138
|
+
*/
|
|
2139
|
+
const disposeViewletForTab = (state, tabId) => {
|
|
2140
|
+
const tab = findTab(state, tabId);
|
|
2141
|
+
if (!tab || tab.editorUid === -1) {
|
|
2142
|
+
return {
|
|
2143
|
+
commands: [],
|
|
2144
|
+
newState: state
|
|
2145
|
+
};
|
|
2086
2146
|
}
|
|
2087
|
-
const
|
|
2147
|
+
const commands = [{
|
|
2148
|
+
instanceId: tab.editorUid,
|
|
2149
|
+
type: 'dispose'
|
|
2150
|
+
}];
|
|
2088
2151
|
return {
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
isEmpty: newTabs.length === 0,
|
|
2092
|
-
tabs: newTabs
|
|
2152
|
+
commands,
|
|
2153
|
+
newState: state
|
|
2093
2154
|
};
|
|
2094
2155
|
};
|
|
2095
|
-
|
|
2156
|
+
|
|
2157
|
+
const handleCreate = async command => {
|
|
2158
|
+
// Safe to call - no visible side effects
|
|
2159
|
+
|
|
2160
|
+
const title = await createViewlet(command.viewletModuleId, command.editorUid, command.tabId, command.bounds, command.uri || '');
|
|
2161
|
+
|
|
2162
|
+
// After viewlet is created, mark it as ready
|
|
2163
|
+
// Attachment is handled automatically by virtual DOM reference nodes
|
|
2096
2164
|
const {
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
tab,
|
|
2104
|
-
tabIndex
|
|
2105
|
-
})).filter(entry => !entry.tab.isDirty);
|
|
2106
|
-
});
|
|
2107
|
-
const newGroups = groups.map(closeSavedInGroup);
|
|
2108
|
-
return withGroups(addClosedTabs(state, closedTabs), newGroups);
|
|
2165
|
+
newState: state,
|
|
2166
|
+
oldState
|
|
2167
|
+
} = get(command.uid);
|
|
2168
|
+
const readyState = handleViewletReady(state, command.editorUid, title);
|
|
2169
|
+
set(command.uid, oldState, readyState);
|
|
2170
|
+
return readyState;
|
|
2109
2171
|
};
|
|
2110
2172
|
|
|
2111
|
-
const
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
const matchingTab = matchingGroup?.tabs.find(tab => tab.uri === uri);
|
|
2116
|
-
if (!matchingGroup || !matchingTab) {
|
|
2117
|
-
return undefined;
|
|
2118
|
-
}
|
|
2119
|
-
return closeTab(state, matchingGroup.id, matchingTab.id);
|
|
2173
|
+
const handleDetach = async command => {
|
|
2174
|
+
// Hides viewlet but keeps it alive
|
|
2175
|
+
|
|
2176
|
+
await invoke('Viewlet.detach', command.instanceId);
|
|
2120
2177
|
};
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
currentState = nextState;
|
|
2127
|
-
nextState = closeFirstTabByUri(currentState, uri);
|
|
2128
|
-
}
|
|
2129
|
-
}
|
|
2130
|
-
return currentState;
|
|
2178
|
+
|
|
2179
|
+
const handleDispose = async command => {
|
|
2180
|
+
// Fully destroys viewlet
|
|
2181
|
+
|
|
2182
|
+
await invoke('Viewlet.dispose', command.instanceId);
|
|
2131
2183
|
};
|
|
2132
2184
|
|
|
2133
|
-
const
|
|
2134
|
-
|
|
2185
|
+
const handleSetBounds = async command => {
|
|
2186
|
+
await invoke('Viewlet.setBounds', command.instanceId, command.bounds);
|
|
2135
2187
|
};
|
|
2136
2188
|
|
|
2137
|
-
const
|
|
2189
|
+
const executeViewletCommand = async command => {
|
|
2190
|
+
switch (command.type) {
|
|
2191
|
+
case 'attach':
|
|
2192
|
+
await handleAttach(command);
|
|
2193
|
+
return;
|
|
2194
|
+
case 'create':
|
|
2195
|
+
await handleCreate(command);
|
|
2196
|
+
return;
|
|
2197
|
+
case 'detach':
|
|
2198
|
+
await handleDetach(command);
|
|
2199
|
+
return;
|
|
2200
|
+
case 'dispose':
|
|
2201
|
+
await handleDispose(command);
|
|
2202
|
+
return;
|
|
2203
|
+
case 'setBounds':
|
|
2204
|
+
await handleSetBounds(command);
|
|
2205
|
+
return;
|
|
2206
|
+
}
|
|
2207
|
+
};
|
|
2208
|
+
const executeViewletCommands = async commands => {
|
|
2209
|
+
for (const command of commands) {
|
|
2210
|
+
await executeViewletCommand(command);
|
|
2211
|
+
}
|
|
2212
|
+
};
|
|
2213
|
+
|
|
2214
|
+
const findTabInState = (state, groupId, tabId) => {
|
|
2138
2215
|
const {
|
|
2139
2216
|
layout
|
|
2140
2217
|
} = state;
|
|
2141
|
-
const
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2218
|
+
const group = layout.groups.find(g => g.id === groupId);
|
|
2219
|
+
return group?.tabs.find(t => t.id === tabId);
|
|
2220
|
+
};
|
|
2221
|
+
|
|
2222
|
+
const closeTabWithViewlet = async (state, groupId, tabId) => {
|
|
2223
|
+
const tab = findTabInState(state, groupId, tabId);
|
|
2224
|
+
const commands = [];
|
|
2225
|
+
if (tab && tab.editorUid !== -1) {
|
|
2226
|
+
const {
|
|
2227
|
+
commands: disposeCommands
|
|
2228
|
+
} = disposeViewletForTab(state, tabId);
|
|
2229
|
+
commands.push(...disposeCommands);
|
|
2230
|
+
}
|
|
2231
|
+
const newState = closeTab(state, groupId, tabId);
|
|
2232
|
+
const group = state.layout.groups.find(g => g.id === groupId);
|
|
2233
|
+
const wasActiveTab = group?.activeTabId === tabId;
|
|
2234
|
+
if (wasActiveTab) {
|
|
2235
|
+
const newGroup = newState.layout.groups.find(g => g.id === groupId);
|
|
2236
|
+
const newActiveTabId = newGroup?.activeTabId;
|
|
2237
|
+
if (newActiveTabId !== undefined) {
|
|
2238
|
+
const {
|
|
2239
|
+
commands: switchCommands,
|
|
2240
|
+
newState: switchedState
|
|
2241
|
+
} = switchViewlet(newState);
|
|
2242
|
+
commands.push(...switchCommands);
|
|
2243
|
+
await executeViewletCommands(commands);
|
|
2244
|
+
return switchedState;
|
|
2245
|
+
}
|
|
2154
2246
|
}
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
return state;
|
|
2247
|
+
if (commands.length > 0) {
|
|
2248
|
+
await executeViewletCommands(commands);
|
|
2158
2249
|
}
|
|
2159
|
-
|
|
2160
|
-
|
|
2250
|
+
return newState;
|
|
2251
|
+
};
|
|
2252
|
+
|
|
2253
|
+
const saveEditor = async editorUid => {
|
|
2254
|
+
return invoke('Editor.save', editorUid);
|
|
2255
|
+
};
|
|
2256
|
+
|
|
2257
|
+
const closeTabAndSave = async (state, groupId, tabId) => {
|
|
2258
|
+
const tab = findTabInState(state, groupId, tabId);
|
|
2259
|
+
if (!tab) {
|
|
2161
2260
|
return state;
|
|
2162
2261
|
}
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
tab,
|
|
2168
|
-
tabIndex: activeTabIndex + index + 1
|
|
2169
|
-
}));
|
|
2170
|
-
const newGroups = groups.map(g => {
|
|
2171
|
-
if (g.id === groupId) {
|
|
2172
|
-
return {
|
|
2173
|
-
...g,
|
|
2174
|
-
isEmpty: newTabs.length === 0,
|
|
2175
|
-
tabs: newTabs
|
|
2176
|
-
};
|
|
2262
|
+
if (tab.editorUid !== -1 && tab.isDirty) {
|
|
2263
|
+
const editorState = await saveEditor(tab.editorUid);
|
|
2264
|
+
if (!editorState?.modified && tab.uri) {
|
|
2265
|
+
await handleModifiedStatusChange$1(tab.uri, false);
|
|
2177
2266
|
}
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2267
|
+
}
|
|
2268
|
+
if (tab.uri?.startsWith('simple-browser://')) {
|
|
2269
|
+
return closeTabWithViewlet(state, groupId, tabId);
|
|
2270
|
+
}
|
|
2271
|
+
return closeTab(state, groupId, tabId);
|
|
2181
2272
|
};
|
|
2182
2273
|
|
|
2183
|
-
const
|
|
2274
|
+
const getFocusedGroup = state => {
|
|
2184
2275
|
const {
|
|
2185
2276
|
layout
|
|
2186
2277
|
} = state;
|
|
2187
2278
|
const {
|
|
2188
2279
|
groups
|
|
2189
2280
|
} = layout;
|
|
2190
|
-
return groups.find(group => group.
|
|
2281
|
+
return groups.find(group => group.focused);
|
|
2191
2282
|
};
|
|
2192
2283
|
|
|
2193
|
-
const
|
|
2194
|
-
const
|
|
2195
|
-
|
|
2196
|
-
} = state.layout;
|
|
2197
|
-
const group = findGroupById(state, activeGroupId ?? 0);
|
|
2198
|
-
if (!group) {
|
|
2284
|
+
const closeActiveEditor = async state => {
|
|
2285
|
+
const focusedGroup = getFocusedGroup(state);
|
|
2286
|
+
if (!focusedGroup) {
|
|
2199
2287
|
return state;
|
|
2200
2288
|
}
|
|
2201
2289
|
const {
|
|
2202
2290
|
activeTabId
|
|
2203
|
-
} =
|
|
2291
|
+
} = focusedGroup;
|
|
2204
2292
|
if (activeTabId === undefined) {
|
|
2205
2293
|
return state;
|
|
2206
2294
|
}
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2295
|
+
return closeTabAndSave(state, focusedGroup.id, activeTabId);
|
|
2296
|
+
};
|
|
2297
|
+
|
|
2298
|
+
const disposeEditors = async editorUids => {
|
|
2299
|
+
// Dispose all child viewlets in the renderer worker
|
|
2300
|
+
for (const editorUid of editorUids) {
|
|
2301
|
+
try {
|
|
2302
|
+
await invoke('Viewlet.dispose', editorUid);
|
|
2303
|
+
} catch {
|
|
2304
|
+
// Silently ignore errors during disposal
|
|
2305
|
+
// Viewlet may already be disposed or renderer worker may not be available
|
|
2306
|
+
}
|
|
2210
2307
|
}
|
|
2211
|
-
await invoke('ElectronWindow.openNewWithUri', tab.uri);
|
|
2212
|
-
return state;
|
|
2213
2308
|
};
|
|
2214
2309
|
|
|
2215
|
-
const
|
|
2216
|
-
|
|
2217
|
-
await
|
|
2218
|
-
|
|
2310
|
+
const closeAll$1 = async state => {
|
|
2311
|
+
const editorUids = state.layout.groups.flatMap(group => group.tabs.map(tab => tab.editorUid)).filter(editorUid => editorUid !== -1);
|
|
2312
|
+
await disposeEditors(editorUids);
|
|
2313
|
+
const entries = state.layout.groups.flatMap((group, groupIndex) => {
|
|
2314
|
+
return group.tabs.map((tab, tabIndex) => ({
|
|
2315
|
+
group,
|
|
2316
|
+
groupIndex,
|
|
2317
|
+
tab,
|
|
2318
|
+
tabIndex
|
|
2319
|
+
}));
|
|
2320
|
+
});
|
|
2321
|
+
return withEmptyGroups(addClosedTabs(state, entries));
|
|
2219
2322
|
};
|
|
2220
2323
|
|
|
2221
|
-
const
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2324
|
+
const redistributeSizesWithRemainder = groups => {
|
|
2325
|
+
const baseSize = Math.floor(100 / groups.length);
|
|
2326
|
+
const remainder = 100 % groups.length;
|
|
2327
|
+
return groups.map((group, index) => ({
|
|
2328
|
+
...group,
|
|
2329
|
+
size: baseSize + (index === groups.length - 1 ? remainder : 0)
|
|
2330
|
+
}));
|
|
2227
2331
|
};
|
|
2228
2332
|
|
|
2229
|
-
const
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
return direction === Horizontal || direction === Vertical;
|
|
2233
|
-
};
|
|
2234
|
-
const normalizeLayoutDirection = direction => {
|
|
2235
|
-
if (isLayoutDirection(direction)) {
|
|
2236
|
-
return direction;
|
|
2237
|
-
}
|
|
2238
|
-
if (direction === 'horizontal') {
|
|
2239
|
-
return Horizontal;
|
|
2333
|
+
const closeEditorGroup$1 = (state, groupId) => {
|
|
2334
|
+
if (Number.isNaN(groupId)) {
|
|
2335
|
+
return state;
|
|
2240
2336
|
}
|
|
2241
|
-
|
|
2242
|
-
|
|
2337
|
+
const {
|
|
2338
|
+
layout
|
|
2339
|
+
} = state;
|
|
2340
|
+
const {
|
|
2341
|
+
activeGroupId,
|
|
2342
|
+
groups
|
|
2343
|
+
} = layout;
|
|
2344
|
+
const groupIndex = getGroupIndexById(state, groupId);
|
|
2345
|
+
if (groupIndex === -1 || groups.length <= 1) {
|
|
2346
|
+
return state;
|
|
2243
2347
|
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
get,
|
|
2249
|
-
getCommandIds,
|
|
2250
|
-
getKeys: getKeys$1,
|
|
2251
|
-
registerCommands,
|
|
2252
|
-
set,
|
|
2253
|
-
wrapAsyncCommand,
|
|
2254
|
-
wrapGetter,
|
|
2255
|
-
wrapSerialAsyncCommand,
|
|
2256
|
-
wrapSerialCommand
|
|
2257
|
-
} = create$f();
|
|
2258
|
-
|
|
2259
|
-
const create$2 = (uid, uri, x, y, width, height, platform, assetDir, tabHeight = 35) => {
|
|
2260
|
-
const state = {
|
|
2261
|
-
assetDir,
|
|
2262
|
-
closedTabs: [],
|
|
2263
|
-
fileIconCache: {},
|
|
2264
|
-
height,
|
|
2265
|
-
homeDirUri: '',
|
|
2266
|
-
iframes: [],
|
|
2267
|
-
initial: true,
|
|
2268
|
-
layout: {
|
|
2269
|
-
activeGroupId: undefined,
|
|
2270
|
-
direction: Horizontal,
|
|
2271
|
-
groups: []
|
|
2272
|
-
},
|
|
2273
|
-
maxOpenEditorGroups: Infinity,
|
|
2274
|
-
maxOpenEditors: Infinity,
|
|
2275
|
-
minGroupHeightPx: 80,
|
|
2276
|
-
minGroupWidthPx: 250,
|
|
2277
|
-
platform,
|
|
2278
|
-
splitButtonEnabled: false,
|
|
2279
|
-
tabHeight,
|
|
2280
|
-
uid,
|
|
2281
|
-
width,
|
|
2282
|
-
workspaceuri: uri,
|
|
2283
|
-
x,
|
|
2284
|
-
y
|
|
2285
|
-
};
|
|
2286
|
-
set(uid, state, state);
|
|
2287
|
-
};
|
|
2288
|
-
|
|
2289
|
-
const isEqual$1 = (oldState, newState) => {
|
|
2290
|
-
return false;
|
|
2348
|
+
const remainingGroups = groups.filter(group => group.id !== groupId);
|
|
2349
|
+
const redistributedGroups = redistributeSizesWithRemainder(remainingGroups);
|
|
2350
|
+
const newActiveGroupId = activeGroupId === groupId ? remainingGroups[0].id : activeGroupId;
|
|
2351
|
+
return withGroupsAndActiveGroup(state, redistributedGroups, newActiveGroupId);
|
|
2291
2352
|
};
|
|
2292
2353
|
|
|
2293
|
-
const
|
|
2294
|
-
return
|
|
2354
|
+
const isFocused = group => {
|
|
2355
|
+
return group.focused;
|
|
2295
2356
|
};
|
|
2296
|
-
|
|
2297
|
-
const
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
for (let i = 0; i < modules.length; i++) {
|
|
2307
|
-
const fn = modules[i];
|
|
2308
|
-
if (!fn(oldState, newState)) {
|
|
2309
|
-
diffResult.push(numbers[i]);
|
|
2310
|
-
}
|
|
2357
|
+
const closeFocusedTab = async state => {
|
|
2358
|
+
const {
|
|
2359
|
+
layout
|
|
2360
|
+
} = state;
|
|
2361
|
+
const {
|
|
2362
|
+
groups
|
|
2363
|
+
} = layout;
|
|
2364
|
+
const focusedGroup = groups.find(isFocused);
|
|
2365
|
+
if (!focusedGroup) {
|
|
2366
|
+
return state;
|
|
2311
2367
|
}
|
|
2312
|
-
return diffResult;
|
|
2313
|
-
};
|
|
2314
|
-
|
|
2315
|
-
const diff2 = uid => {
|
|
2316
2368
|
const {
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
return result;
|
|
2322
|
-
};
|
|
2323
|
-
|
|
2324
|
-
const handleAttach = async command => {
|
|
2325
|
-
// TODO find a better way to append editors
|
|
2326
|
-
const parentNodeSelector = '.editor-groups-container, .EditorGroup';
|
|
2327
|
-
await invoke('Layout.attachViewlet', parentNodeSelector, command.instanceId);
|
|
2328
|
-
};
|
|
2329
|
-
|
|
2330
|
-
const getTitle$1 = async editorUid => {
|
|
2331
|
-
try {
|
|
2332
|
-
const title = await invoke('Viewlet.getTitle', editorUid);
|
|
2333
|
-
return typeof title === 'string' && title ? title : undefined;
|
|
2334
|
-
} catch {
|
|
2335
|
-
return undefined;
|
|
2369
|
+
activeTabId
|
|
2370
|
+
} = focusedGroup;
|
|
2371
|
+
if (activeTabId === undefined) {
|
|
2372
|
+
return state;
|
|
2336
2373
|
}
|
|
2337
|
-
|
|
2338
|
-
const createViewlet = async (viewletModuleId, editorUid, tabId, bounds, uri) => {
|
|
2339
|
-
await invoke('Layout.createViewlet', viewletModuleId, editorUid, tabId, bounds, uri);
|
|
2340
|
-
return getTitle$1(editorUid);
|
|
2341
|
-
};
|
|
2342
|
-
|
|
2343
|
-
const create$1 = () => {
|
|
2344
|
-
return Math.random();
|
|
2374
|
+
return closeTabAndSave(state, focusedGroup.id, activeTabId);
|
|
2345
2375
|
};
|
|
2346
2376
|
|
|
2347
|
-
const
|
|
2377
|
+
const closeOtherTabs = (state, groupId) => {
|
|
2348
2378
|
const {
|
|
2349
2379
|
layout
|
|
2350
2380
|
} = state;
|
|
2351
2381
|
const {
|
|
2382
|
+
activeGroupId,
|
|
2352
2383
|
groups
|
|
2353
2384
|
} = layout;
|
|
2354
|
-
const
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2385
|
+
const targetGroupId = groupId ?? activeGroupId;
|
|
2386
|
+
if (targetGroupId === undefined) {
|
|
2387
|
+
return state;
|
|
2388
|
+
}
|
|
2389
|
+
const group = groups.find(g => g.id === targetGroupId);
|
|
2390
|
+
if (!group) {
|
|
2391
|
+
return state;
|
|
2392
|
+
}
|
|
2393
|
+
const {
|
|
2394
|
+
activeTabId
|
|
2395
|
+
} = group;
|
|
2396
|
+
if (activeTabId === undefined) {
|
|
2397
|
+
return state;
|
|
2398
|
+
}
|
|
2399
|
+
const closedTabs = group.tabs.map((tab, tabIndex) => ({
|
|
2400
|
+
group,
|
|
2401
|
+
groupIndex: groups.findIndex(g => g.id === targetGroupId),
|
|
2402
|
+
tab,
|
|
2403
|
+
tabIndex
|
|
2404
|
+
})).filter(entry => entry.tab.id !== activeTabId);
|
|
2405
|
+
const newGroups = groups.map(g => {
|
|
2406
|
+
if (g.id === targetGroupId) {
|
|
2407
|
+
const newTabs = g.tabs.filter(tab => tab.id === activeTabId);
|
|
2408
|
+
return {
|
|
2409
|
+
...g,
|
|
2410
|
+
activeTabId,
|
|
2411
|
+
isEmpty: newTabs.length === 0,
|
|
2412
|
+
tabs: newTabs
|
|
2413
|
+
};
|
|
2358
2414
|
}
|
|
2359
|
-
|
|
2360
|
-
if (index === tabIndex) {
|
|
2361
|
-
return {
|
|
2362
|
-
...tab,
|
|
2363
|
-
...updates
|
|
2364
|
-
};
|
|
2365
|
-
}
|
|
2366
|
-
return tab;
|
|
2367
|
-
});
|
|
2368
|
-
return {
|
|
2369
|
-
...group,
|
|
2370
|
-
tabs: updatedTabs
|
|
2371
|
-
};
|
|
2415
|
+
return g;
|
|
2372
2416
|
});
|
|
2373
2417
|
return {
|
|
2374
|
-
...state,
|
|
2418
|
+
...addClosedTabs(state, closedTabs),
|
|
2375
2419
|
layout: {
|
|
2376
2420
|
...layout,
|
|
2377
|
-
groups:
|
|
2421
|
+
groups: newGroups
|
|
2378
2422
|
}
|
|
2379
2423
|
};
|
|
2380
2424
|
};
|
|
2381
2425
|
|
|
2382
|
-
const
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
}
|
|
2426
|
+
const getNextActiveTabId = (tabs, newTabs, activeTabId) => {
|
|
2427
|
+
if (activeTabId === undefined) {
|
|
2428
|
+
return undefined;
|
|
2429
|
+
}
|
|
2430
|
+
if (newTabs.some(tab => tab.id === activeTabId)) {
|
|
2431
|
+
return activeTabId;
|
|
2432
|
+
}
|
|
2433
|
+
const activeTabIndex = tabs.findIndex(tab => tab.id === activeTabId);
|
|
2434
|
+
if (activeTabIndex === -1 || newTabs.length === 0) {
|
|
2435
|
+
return undefined;
|
|
2436
|
+
}
|
|
2437
|
+
return newTabs[Math.min(activeTabIndex, newTabs.length - 1)].id;
|
|
2438
|
+
};
|
|
2439
|
+
const closeSavedInGroup = group => {
|
|
2386
2440
|
const {
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
}
|
|
2441
|
+
activeTabId,
|
|
2442
|
+
tabs
|
|
2443
|
+
} = group;
|
|
2444
|
+
const newTabs = tabs.filter(tab => tab.isDirty);
|
|
2445
|
+
if (newTabs.length === tabs.length) {
|
|
2446
|
+
return group;
|
|
2394
2447
|
}
|
|
2395
|
-
|
|
2448
|
+
const newActiveTabId = getNextActiveTabId(tabs, newTabs, activeTabId);
|
|
2449
|
+
return {
|
|
2450
|
+
...group,
|
|
2451
|
+
activeTabId: newActiveTabId,
|
|
2452
|
+
isEmpty: newTabs.length === 0,
|
|
2453
|
+
tabs: newTabs
|
|
2454
|
+
};
|
|
2396
2455
|
};
|
|
2397
|
-
const
|
|
2398
|
-
const
|
|
2399
|
-
|
|
2456
|
+
const closeSaved$1 = state => {
|
|
2457
|
+
const {
|
|
2458
|
+
groups
|
|
2459
|
+
} = state.layout;
|
|
2460
|
+
const closedTabs = groups.flatMap((group, groupIndex) => {
|
|
2461
|
+
return group.tabs.map((tab, tabIndex) => ({
|
|
2462
|
+
group,
|
|
2463
|
+
groupIndex,
|
|
2464
|
+
tab,
|
|
2465
|
+
tabIndex
|
|
2466
|
+
})).filter(entry => !entry.tab.isDirty);
|
|
2467
|
+
});
|
|
2468
|
+
const newGroups = groups.map(closeSavedInGroup);
|
|
2469
|
+
return withGroups(addClosedTabs(state, closedTabs), newGroups);
|
|
2400
2470
|
};
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2471
|
+
|
|
2472
|
+
const closeFirstTabByUri = (state, uri) => {
|
|
2473
|
+
const matchingGroup = state.layout.groups.find(group => {
|
|
2474
|
+
return group.tabs.some(tab => tab.uri === uri);
|
|
2475
|
+
});
|
|
2476
|
+
const matchingTab = matchingGroup?.tabs.find(tab => tab.uri === uri);
|
|
2477
|
+
if (!matchingGroup || !matchingTab) {
|
|
2478
|
+
return undefined;
|
|
2407
2479
|
}
|
|
2408
|
-
return
|
|
2480
|
+
return closeTab(state, matchingGroup.id, matchingTab.id);
|
|
2409
2481
|
};
|
|
2410
|
-
const
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
// If the tab no longer exists, discard this result
|
|
2419
|
-
if (!latestTab) {
|
|
2420
|
-
return latestState;
|
|
2421
|
-
}
|
|
2422
|
-
|
|
2423
|
-
// If the tab is no longer in loading state, discard this result (newer request started)
|
|
2424
|
-
if (latestTab.loadingState !== 'loading') {
|
|
2425
|
-
return latestState;
|
|
2426
|
-
}
|
|
2427
|
-
|
|
2428
|
-
// Assign editorUid if tab doesn't have one yet
|
|
2429
|
-
const editorUid = latestTab.editorUid === -1 ? create$1() : latestTab.editorUid;
|
|
2430
|
-
return updateTab(latestState, tabId, {
|
|
2431
|
-
editorUid,
|
|
2432
|
-
errorMessage: undefined,
|
|
2433
|
-
loadingState: 'loaded'
|
|
2434
|
-
});
|
|
2435
|
-
} catch (error) {
|
|
2436
|
-
// Check for race condition before updating with error
|
|
2437
|
-
const latestState = getLatestState();
|
|
2438
|
-
const latestTab = findTab(latestState, tabId);
|
|
2439
|
-
if (!latestTab) {
|
|
2440
|
-
return latestState;
|
|
2441
|
-
}
|
|
2442
|
-
|
|
2443
|
-
// If the tab is no longer in loading state, discard this result (newer request started)
|
|
2444
|
-
if (latestTab.loadingState !== 'loading') {
|
|
2445
|
-
return latestState;
|
|
2482
|
+
const closeTabsByUris = (state, uris) => {
|
|
2483
|
+
let currentState = state;
|
|
2484
|
+
for (const uri of uris) {
|
|
2485
|
+
let nextState = closeFirstTabByUri(currentState, uri);
|
|
2486
|
+
while (nextState) {
|
|
2487
|
+
currentState = nextState;
|
|
2488
|
+
nextState = closeFirstTabByUri(currentState, uri);
|
|
2446
2489
|
}
|
|
2447
|
-
const errorMessage = getLoadFileErrorMessage(error);
|
|
2448
|
-
return updateTab(latestState, tabId, {
|
|
2449
|
-
errorMessage,
|
|
2450
|
-
loadingState: 'error'
|
|
2451
|
-
});
|
|
2452
2490
|
}
|
|
2491
|
+
return currentState;
|
|
2453
2492
|
};
|
|
2454
2493
|
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
const
|
|
2460
|
-
const
|
|
2461
|
-
|
|
2494
|
+
const getGroupById = (state, groupId) => {
|
|
2495
|
+
return state.layout.groups.find(group => group.id === groupId);
|
|
2496
|
+
};
|
|
2497
|
+
|
|
2498
|
+
const closeTabsRight = (state, groupId) => {
|
|
2499
|
+
const {
|
|
2500
|
+
layout
|
|
2501
|
+
} = state;
|
|
2502
|
+
const {
|
|
2503
|
+
groups
|
|
2504
|
+
} = layout;
|
|
2505
|
+
const group = getGroupById(state, groupId);
|
|
2506
|
+
if (!group) {
|
|
2462
2507
|
return state;
|
|
2463
2508
|
}
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2509
|
+
const {
|
|
2510
|
+
activeTabId,
|
|
2511
|
+
tabs
|
|
2512
|
+
} = group;
|
|
2513
|
+
if (activeTabId === undefined) {
|
|
2467
2514
|
return state;
|
|
2468
2515
|
}
|
|
2469
|
-
const
|
|
2470
|
-
|
|
2471
|
-
|
|
2516
|
+
const activeTabIndex = tabs.findIndex(tab => tab.id === activeTabId);
|
|
2517
|
+
if (activeTabIndex === -1) {
|
|
2518
|
+
return state;
|
|
2519
|
+
}
|
|
2520
|
+
const newTabs = tabs.slice(0, activeTabIndex + 1);
|
|
2521
|
+
if (newTabs.length === tabs.length) {
|
|
2522
|
+
return state;
|
|
2523
|
+
}
|
|
2524
|
+
const groupIndex = groups.findIndex(g => g.id === groupId);
|
|
2525
|
+
const closedTabs = tabs.slice(activeTabIndex + 1).map((tab, index) => ({
|
|
2526
|
+
group,
|
|
2527
|
+
groupIndex,
|
|
2528
|
+
tab,
|
|
2529
|
+
tabIndex: activeTabIndex + index + 1
|
|
2530
|
+
}));
|
|
2531
|
+
const newGroups = groups.map(g => {
|
|
2532
|
+
if (g.id === groupId) {
|
|
2533
|
+
return {
|
|
2534
|
+
...g,
|
|
2535
|
+
isEmpty: newTabs.length === 0,
|
|
2536
|
+
tabs: newTabs
|
|
2537
|
+
};
|
|
2538
|
+
}
|
|
2539
|
+
return g;
|
|
2472
2540
|
});
|
|
2473
|
-
return
|
|
2474
|
-
};
|
|
2475
|
-
|
|
2476
|
-
/**
|
|
2477
|
-
* Called when switching tabs.
|
|
2478
|
-
* With reference nodes, attachment/detachment is handled automatically by virtual DOM rendering.
|
|
2479
|
-
* No attach/detach commands needed - virtual DOM will render the correct reference at each position.
|
|
2480
|
-
*/
|
|
2481
|
-
const switchViewlet = (state, fromTabId, toTabId) => {
|
|
2482
|
-
// No commands needed - virtual DOM reference nodes handle attachment automatically
|
|
2483
|
-
// Virtual DOM will:
|
|
2484
|
-
// 1. Remove the old reference node from the previous active tab
|
|
2485
|
-
// 2. Add the new reference node for the now-active tab
|
|
2486
|
-
// This achieves the same effect as detach/attach without explicit commands
|
|
2487
|
-
|
|
2488
|
-
return {
|
|
2489
|
-
commands: [],
|
|
2490
|
-
newState: state
|
|
2491
|
-
};
|
|
2541
|
+
return withGroups(addClosedTabs(state, closedTabs), newGroups);
|
|
2492
2542
|
};
|
|
2493
2543
|
|
|
2494
|
-
const
|
|
2544
|
+
const findGroupById = (state, groupId) => {
|
|
2495
2545
|
const {
|
|
2496
2546
|
layout
|
|
2497
2547
|
} = state;
|
|
2498
2548
|
const {
|
|
2499
2549
|
groups
|
|
2500
2550
|
} = layout;
|
|
2501
|
-
|
|
2502
|
-
const tab = group.tabs.find(t => t.editorUid === editorUid);
|
|
2503
|
-
if (tab) {
|
|
2504
|
-
return tab;
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2507
|
-
return undefined;
|
|
2551
|
+
return groups.find(group => group.id === groupId);
|
|
2508
2552
|
};
|
|
2509
2553
|
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
throw new Error('Invalid editorUid -1');
|
|
2554
|
+
const copyIntoNewWindow$1 = async state => {
|
|
2555
|
+
const {
|
|
2556
|
+
activeGroupId
|
|
2557
|
+
} = state.layout;
|
|
2558
|
+
const group = findGroupById(state, activeGroupId ?? 0);
|
|
2559
|
+
if (!group) {
|
|
2560
|
+
return state;
|
|
2518
2561
|
}
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2562
|
+
const {
|
|
2563
|
+
activeTabId
|
|
2564
|
+
} = group;
|
|
2565
|
+
if (activeTabId === undefined) {
|
|
2523
2566
|
return state;
|
|
2524
2567
|
}
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
...(title && {
|
|
2532
|
-
title
|
|
2533
|
-
})
|
|
2534
|
-
});
|
|
2535
|
-
|
|
2536
|
-
// No attach commands needed - virtual DOM reference nodes handle positioning
|
|
2537
|
-
return newState;
|
|
2568
|
+
const tab = group.tabs.find(tab => tab.id === activeTabId);
|
|
2569
|
+
if (!tab?.uri) {
|
|
2570
|
+
return state;
|
|
2571
|
+
}
|
|
2572
|
+
await invoke('ElectronWindow.openNewWithUri', tab.uri);
|
|
2573
|
+
return state;
|
|
2538
2574
|
};
|
|
2539
2575
|
|
|
2540
|
-
const
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
// After viewlet is created, mark it as ready
|
|
2546
|
-
// Attachment is handled automatically by virtual DOM reference nodes
|
|
2547
|
-
const {
|
|
2548
|
-
newState: state,
|
|
2549
|
-
oldState
|
|
2550
|
-
} = get(command.uid);
|
|
2551
|
-
const readyState = handleViewletReady(state, command.editorUid, title);
|
|
2552
|
-
set(command.uid, oldState, readyState);
|
|
2553
|
-
return readyState;
|
|
2576
|
+
const copyPath$1 = async (state, path) => {
|
|
2577
|
+
string(path);
|
|
2578
|
+
await writeClipBoardText(path);
|
|
2579
|
+
return state;
|
|
2554
2580
|
};
|
|
2555
2581
|
|
|
2556
|
-
const
|
|
2557
|
-
|
|
2582
|
+
const copyRelativePath$1 = async (state, path) => {
|
|
2583
|
+
string(path);
|
|
2584
|
+
// TODO use clipboard worker
|
|
2585
|
+
const relativePath = await invoke('Workspace.pathBaseName', path);
|
|
2586
|
+
await invoke('ClipBoard.writeText', relativePath);
|
|
2587
|
+
return state;
|
|
2588
|
+
};
|
|
2558
2589
|
|
|
2559
|
-
|
|
2590
|
+
const Horizontal = 1;
|
|
2591
|
+
const Vertical = 2;
|
|
2592
|
+
const isLayoutDirection = direction => {
|
|
2593
|
+
return direction === Horizontal || direction === Vertical;
|
|
2594
|
+
};
|
|
2595
|
+
const normalizeLayoutDirection = direction => {
|
|
2596
|
+
if (isLayoutDirection(direction)) {
|
|
2597
|
+
return direction;
|
|
2598
|
+
}
|
|
2599
|
+
if (direction === 'horizontal') {
|
|
2600
|
+
return Horizontal;
|
|
2601
|
+
}
|
|
2602
|
+
if (direction === 'vertical') {
|
|
2603
|
+
return Vertical;
|
|
2604
|
+
}
|
|
2605
|
+
return undefined;
|
|
2560
2606
|
};
|
|
2561
2607
|
|
|
2562
|
-
const
|
|
2563
|
-
|
|
2608
|
+
const create$1 = (uid, uri, x, y, width, height, platform, assetDir, tabHeight = 35) => {
|
|
2609
|
+
const state = {
|
|
2610
|
+
assetDir,
|
|
2611
|
+
closedTabs: [],
|
|
2612
|
+
fileIconCache: {},
|
|
2613
|
+
height,
|
|
2614
|
+
homeDirUri: '',
|
|
2615
|
+
iframes: [],
|
|
2616
|
+
initial: true,
|
|
2617
|
+
layout: {
|
|
2618
|
+
activeGroupId: undefined,
|
|
2619
|
+
direction: Horizontal,
|
|
2620
|
+
groups: []
|
|
2621
|
+
},
|
|
2622
|
+
maxOpenEditorGroups: Infinity,
|
|
2623
|
+
maxOpenEditors: Infinity,
|
|
2624
|
+
minGroupHeightPx: 80,
|
|
2625
|
+
minGroupWidthPx: 250,
|
|
2626
|
+
platform,
|
|
2627
|
+
splitButtonEnabled: false,
|
|
2628
|
+
tabHeight,
|
|
2629
|
+
uid,
|
|
2630
|
+
width,
|
|
2631
|
+
workspaceuri: uri,
|
|
2632
|
+
x,
|
|
2633
|
+
y
|
|
2634
|
+
};
|
|
2635
|
+
set(uid, state, state);
|
|
2636
|
+
};
|
|
2564
2637
|
|
|
2565
|
-
|
|
2638
|
+
const isEqual$1 = (oldState, newState) => {
|
|
2639
|
+
return false;
|
|
2566
2640
|
};
|
|
2567
2641
|
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2642
|
+
const isEqual = (oldState, newState) => {
|
|
2643
|
+
return oldState.layout === newState.layout;
|
|
2570
2644
|
};
|
|
2571
2645
|
|
|
2572
|
-
const
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
case 'setBounds':
|
|
2587
|
-
await handleSetBounds(command);
|
|
2588
|
-
return;
|
|
2646
|
+
const RenderItems = 4;
|
|
2647
|
+
const RenderCss = 10;
|
|
2648
|
+
const RenderIncremental = 11;
|
|
2649
|
+
|
|
2650
|
+
const modules = [isEqual, isEqual$1];
|
|
2651
|
+
const numbers = [RenderIncremental, RenderCss];
|
|
2652
|
+
|
|
2653
|
+
const diff = (oldState, newState) => {
|
|
2654
|
+
const diffResult = [];
|
|
2655
|
+
for (let i = 0; i < modules.length; i++) {
|
|
2656
|
+
const fn = modules[i];
|
|
2657
|
+
if (!fn(oldState, newState)) {
|
|
2658
|
+
diffResult.push(numbers[i]);
|
|
2659
|
+
}
|
|
2589
2660
|
}
|
|
2661
|
+
return diffResult;
|
|
2590
2662
|
};
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2663
|
+
|
|
2664
|
+
const diff2 = uid => {
|
|
2665
|
+
const {
|
|
2666
|
+
newState,
|
|
2667
|
+
oldState
|
|
2668
|
+
} = get(uid);
|
|
2669
|
+
const result = diff(oldState, newState);
|
|
2670
|
+
return result;
|
|
2595
2671
|
};
|
|
2596
2672
|
|
|
2597
2673
|
const requestIdState = {
|
|
@@ -2609,6 +2685,7 @@ const getEditorInputEditorType = editorInput => {
|
|
|
2609
2685
|
case 'process-explorer':
|
|
2610
2686
|
case 'running-extensions':
|
|
2611
2687
|
case 'video':
|
|
2688
|
+
case 'webview':
|
|
2612
2689
|
return 'custom';
|
|
2613
2690
|
case 'editor':
|
|
2614
2691
|
return 'text';
|
|
@@ -2622,6 +2699,7 @@ const getEditorInputUri = editorInput => {
|
|
|
2622
2699
|
case 'editor':
|
|
2623
2700
|
case 'image':
|
|
2624
2701
|
case 'video':
|
|
2702
|
+
case 'webview':
|
|
2625
2703
|
return editorInput.uri;
|
|
2626
2704
|
case 'extension-detail-view':
|
|
2627
2705
|
return `extension-detail://${editorInput.extensionId}`;
|
|
@@ -2726,6 +2804,9 @@ const getNormalizedEditorInput = tab => {
|
|
|
2726
2804
|
editorInput: tabEditorInput,
|
|
2727
2805
|
uri: tabUri
|
|
2728
2806
|
} = tab ?? {};
|
|
2807
|
+
if (tabEditorInput?.type === 'editor' && tabEditorInput.forceText || tabEditorInput?.type === 'webview') {
|
|
2808
|
+
return tabEditorInput;
|
|
2809
|
+
}
|
|
2729
2810
|
let uri;
|
|
2730
2811
|
if (typeof tabUri === 'string') {
|
|
2731
2812
|
uri = tabUri;
|
|
@@ -2854,11 +2935,11 @@ const getSelectedTabBounds = state => {
|
|
|
2854
2935
|
};
|
|
2855
2936
|
};
|
|
2856
2937
|
|
|
2857
|
-
const getViewletModuleId$1 = async uri => {
|
|
2938
|
+
const getViewletModuleId$1 = async (uri, opener) => {
|
|
2858
2939
|
// Query RendererWorker for viewlet module ID (optional, may fail in tests)
|
|
2859
2940
|
let viewletModuleId;
|
|
2860
2941
|
try {
|
|
2861
|
-
viewletModuleId = await invoke('Layout.getModuleId', uri);
|
|
2942
|
+
viewletModuleId = opener === undefined ? await invoke('Layout.getModuleId', uri) : await invoke('Layout.getModuleId', uri, opener);
|
|
2862
2943
|
} catch {
|
|
2863
2944
|
// Viewlet creation is optional - silently ignore if RendererWorker isn't available
|
|
2864
2945
|
}
|
|
@@ -2877,15 +2958,18 @@ const getViewletModuleIdForEditorInput = async editorInput => {
|
|
|
2877
2958
|
case 'diff-editor':
|
|
2878
2959
|
return DiffEditor;
|
|
2879
2960
|
case 'editor':
|
|
2961
|
+
return editorInput.forceText ? EditorText : getViewletModuleId$1(editorInput.uri);
|
|
2962
|
+
case 'extension-detail-view':
|
|
2963
|
+
return ExtensionDetail;
|
|
2880
2964
|
case 'image':
|
|
2881
2965
|
case 'video':
|
|
2882
2966
|
return getViewletModuleId$1(editorInput.uri);
|
|
2883
|
-
case 'extension-detail-view':
|
|
2884
|
-
return ExtensionDetail;
|
|
2885
2967
|
case 'process-explorer':
|
|
2886
2968
|
return ProcessExplorer;
|
|
2887
2969
|
case 'running-extensions':
|
|
2888
2970
|
return RunningExtensions;
|
|
2971
|
+
case 'webview':
|
|
2972
|
+
return getViewletModuleId$1(editorInput.uri, editorInput.providerId);
|
|
2889
2973
|
}
|
|
2890
2974
|
};
|
|
2891
2975
|
|
|
@@ -3434,6 +3518,7 @@ const getEditorInputTitle = editorInput => {
|
|
|
3434
3518
|
case 'editor':
|
|
3435
3519
|
case 'image':
|
|
3436
3520
|
case 'video':
|
|
3521
|
+
case 'webview':
|
|
3437
3522
|
return getLabel(editorInput.uri);
|
|
3438
3523
|
case 'extension-detail-view':
|
|
3439
3524
|
return editorInput.extensionId;
|
|
@@ -3485,9 +3570,9 @@ const createEmptyGroup$1 = (state, uri, requestId, preview = false, title = getL
|
|
|
3485
3570
|
const {
|
|
3486
3571
|
groups
|
|
3487
3572
|
} = layout;
|
|
3488
|
-
const groupId = create$
|
|
3489
|
-
const tabId = create$
|
|
3490
|
-
const editorUid = create$
|
|
3573
|
+
const groupId = create$2();
|
|
3574
|
+
const tabId = create$2();
|
|
3575
|
+
const editorUid = create$2();
|
|
3491
3576
|
const newTab = {
|
|
3492
3577
|
editorInput,
|
|
3493
3578
|
editorType,
|
|
@@ -3528,7 +3613,7 @@ const openTab = (state, groupId, tab) => {
|
|
|
3528
3613
|
};
|
|
3529
3614
|
const newTab = 'id' in normalizedTab && normalizedTab.id !== undefined ? normalizedTab : {
|
|
3530
3615
|
...normalizedTab,
|
|
3531
|
-
id: create$
|
|
3616
|
+
id: create$2()
|
|
3532
3617
|
};
|
|
3533
3618
|
const {
|
|
3534
3619
|
layout
|
|
@@ -3615,8 +3700,8 @@ const ensureActiveGroup = (state, uri, preview = false, title = getLabel(uri), e
|
|
|
3615
3700
|
}
|
|
3616
3701
|
|
|
3617
3702
|
// Create a new tab with the URI in the active group
|
|
3618
|
-
const tabId = create$
|
|
3619
|
-
const editorUid = create$
|
|
3703
|
+
const tabId = create$2();
|
|
3704
|
+
const editorUid = create$2();
|
|
3620
3705
|
const newTab = {
|
|
3621
3706
|
editorInput,
|
|
3622
3707
|
editorType,
|
|
@@ -4149,7 +4234,7 @@ const splitEditorGroup$1 = (state, groupId, direction) => {
|
|
|
4149
4234
|
if (!sourceGroup) {
|
|
4150
4235
|
return state;
|
|
4151
4236
|
}
|
|
4152
|
-
const newGroupId = create$
|
|
4237
|
+
const newGroupId = create$2();
|
|
4153
4238
|
const splitLayoutDirection = getSplitLayoutDirection(direction);
|
|
4154
4239
|
const baseNewGroup = {
|
|
4155
4240
|
activeTabId: undefined,
|
|
@@ -4366,8 +4451,8 @@ const newFile = async state => {
|
|
|
4366
4451
|
getActiveTabId(newState);
|
|
4367
4452
|
|
|
4368
4453
|
// Create a new empty tab
|
|
4369
|
-
const tabId = create$
|
|
4370
|
-
const editorUid = create$
|
|
4454
|
+
const tabId = create$2();
|
|
4455
|
+
const editorUid = create$2();
|
|
4371
4456
|
const newTab = {
|
|
4372
4457
|
editorType: 'text',
|
|
4373
4458
|
editorUid,
|
|
@@ -4861,7 +4946,7 @@ const createViewlets = async (layout, viewletModuleIds, bounds) => {
|
|
|
4861
4946
|
for (const group of layout.groups) {
|
|
4862
4947
|
const activeTab = group.tabs.find(tab => tab.id === group.activeTabId);
|
|
4863
4948
|
if (activeTab && viewletModuleIds[activeTab.id]) {
|
|
4864
|
-
const editorUid = activeTab.editorUid === -1 ? create$
|
|
4949
|
+
const editorUid = activeTab.editorUid === -1 ? create$2() : activeTab.editorUid;
|
|
4865
4950
|
editorUids[activeTab.id] = editorUid;
|
|
4866
4951
|
const title = await createViewlet(viewletModuleIds[activeTab.id], editorUid, activeTab.id, bounds, activeTab.uri);
|
|
4867
4952
|
if (title) {
|
|
@@ -5049,15 +5134,15 @@ const getMenuEntryArgs = groupId => {
|
|
|
5049
5134
|
};
|
|
5050
5135
|
|
|
5051
5136
|
const emptyObject = {};
|
|
5052
|
-
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
|
|
5053
5137
|
const i18nString = (key, placeholders = emptyObject) => {
|
|
5054
5138
|
if (placeholders === emptyObject) {
|
|
5055
5139
|
return key;
|
|
5056
5140
|
}
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5141
|
+
let result = key;
|
|
5142
|
+
for (const [placeholder, replacement] of Object.entries(placeholders)) {
|
|
5143
|
+
result = result.split(`{${placeholder}}`).join(String(replacement));
|
|
5144
|
+
}
|
|
5145
|
+
return result;
|
|
5061
5146
|
};
|
|
5062
5147
|
|
|
5063
5148
|
const Close = 'Close';
|
|
@@ -5141,7 +5226,7 @@ const copyPath = () => {
|
|
|
5141
5226
|
const copyRelativePath = () => {
|
|
5142
5227
|
return i18nString(CopyRelativePath);
|
|
5143
5228
|
};
|
|
5144
|
-
const reopenEditorWith = () => {
|
|
5229
|
+
const reopenEditorWith$1 = () => {
|
|
5145
5230
|
return i18nString(ReopenEditorWith);
|
|
5146
5231
|
};
|
|
5147
5232
|
const share = () => {
|
|
@@ -5308,10 +5393,10 @@ const getMenuEntries$1 = state => {
|
|
|
5308
5393
|
id: 'copyRelativePath',
|
|
5309
5394
|
label: copyRelativePath()
|
|
5310
5395
|
}, menuEntrySeparator, {
|
|
5311
|
-
command: '',
|
|
5396
|
+
command: 'Main.reopenEditorWith',
|
|
5312
5397
|
flags: None,
|
|
5313
5398
|
id: 'reopenEditorWith',
|
|
5314
|
-
label: reopenEditorWith()
|
|
5399
|
+
label: reopenEditorWith$1()
|
|
5315
5400
|
}, menuEntrySeparator, {
|
|
5316
5401
|
command: '',
|
|
5317
5402
|
flags: None,
|
|
@@ -6396,6 +6481,101 @@ const renderEventListeners = () => {
|
|
|
6396
6481
|
}];
|
|
6397
6482
|
};
|
|
6398
6483
|
|
|
6484
|
+
const getViewProviderEntries = async uri => {
|
|
6485
|
+
const textEditorEntry = {
|
|
6486
|
+
id: 'editor',
|
|
6487
|
+
label: 'Text Editor',
|
|
6488
|
+
type: 'editor'
|
|
6489
|
+
};
|
|
6490
|
+
try {
|
|
6491
|
+
const providers = await invoke('WebView.getWebViews');
|
|
6492
|
+
const matchingProviders = providers.filter(provider => provider?.id && provider.selector?.some(selector => uri.endsWith(selector)));
|
|
6493
|
+
return [textEditorEntry, ...matchingProviders.map(provider => {
|
|
6494
|
+
const titleElement = provider.elements?.find(element => element.type === 'title');
|
|
6495
|
+
return {
|
|
6496
|
+
id: provider.id,
|
|
6497
|
+
label: provider.name || provider.title || titleElement?.value || provider.id,
|
|
6498
|
+
type: 'webview'
|
|
6499
|
+
};
|
|
6500
|
+
})];
|
|
6501
|
+
} catch {
|
|
6502
|
+
return [textEditorEntry];
|
|
6503
|
+
}
|
|
6504
|
+
};
|
|
6505
|
+
const reopenEditorWith = async context => {
|
|
6506
|
+
const initialState = context.getState();
|
|
6507
|
+
const {
|
|
6508
|
+
activeGroupId,
|
|
6509
|
+
groups
|
|
6510
|
+
} = initialState.layout;
|
|
6511
|
+
const activeGroup = groups.find(group => group.id === activeGroupId);
|
|
6512
|
+
const initialTab = activeGroup?.tabs.find(tab => tab.id === activeGroup.activeTabId);
|
|
6513
|
+
if (!initialTab?.uri) {
|
|
6514
|
+
return;
|
|
6515
|
+
}
|
|
6516
|
+
const entries = await getViewProviderEntries(initialTab.uri);
|
|
6517
|
+
const items = entries.map(entry => ({
|
|
6518
|
+
description: '',
|
|
6519
|
+
label: entry.label,
|
|
6520
|
+
value: entry
|
|
6521
|
+
}));
|
|
6522
|
+
const selected = await invoke('ExtensionHostQuickPick.showQuickPick', {
|
|
6523
|
+
items,
|
|
6524
|
+
placeholder: 'Select Editor'
|
|
6525
|
+
});
|
|
6526
|
+
if (!selected) {
|
|
6527
|
+
return;
|
|
6528
|
+
}
|
|
6529
|
+
const editorInput = selected.type === 'editor' ? {
|
|
6530
|
+
forceText: true,
|
|
6531
|
+
type: 'editor',
|
|
6532
|
+
uri: initialTab.uri
|
|
6533
|
+
} : {
|
|
6534
|
+
providerId: selected.id,
|
|
6535
|
+
type: 'webview',
|
|
6536
|
+
uri: initialTab.uri
|
|
6537
|
+
};
|
|
6538
|
+
const viewletModuleId = await getViewletModuleIdForEditorInput(editorInput);
|
|
6539
|
+
if (!viewletModuleId) {
|
|
6540
|
+
return;
|
|
6541
|
+
}
|
|
6542
|
+
const latestState = context.getState();
|
|
6543
|
+
const latestTab = findTabById(latestState, initialTab.id);
|
|
6544
|
+
if (!latestTab) {
|
|
6545
|
+
return;
|
|
6546
|
+
}
|
|
6547
|
+
const oldEditorUid = latestTab.tab.editorUid;
|
|
6548
|
+
const resetState = updateTab(latestState, initialTab.id, {
|
|
6549
|
+
editorInput,
|
|
6550
|
+
editorType: getEditorInputEditorType(editorInput),
|
|
6551
|
+
editorUid: -1,
|
|
6552
|
+
errorMessage: undefined,
|
|
6553
|
+
loadingState: undefined
|
|
6554
|
+
});
|
|
6555
|
+
const bounds = {
|
|
6556
|
+
height: resetState.height - resetState.tabHeight,
|
|
6557
|
+
width: resetState.width,
|
|
6558
|
+
x: resetState.x,
|
|
6559
|
+
y: resetState.y + resetState.tabHeight
|
|
6560
|
+
};
|
|
6561
|
+
const stateWithViewlet = createViewletForTab(resetState, initialTab.id);
|
|
6562
|
+
await context.updateState(() => stateWithViewlet);
|
|
6563
|
+
const tabWithViewlet = findTabById(stateWithViewlet, initialTab.id);
|
|
6564
|
+
if (!tabWithViewlet || tabWithViewlet.tab.editorUid === -1) {
|
|
6565
|
+
return;
|
|
6566
|
+
}
|
|
6567
|
+
const renderedTitle = await createViewlet(viewletModuleId, tabWithViewlet.tab.editorUid, initialTab.id, bounds, initialTab.uri);
|
|
6568
|
+
const readyState = handleViewletReady(context.getState(), tabWithViewlet.tab.editorUid, renderedTitle);
|
|
6569
|
+
await context.updateState(() => readyState);
|
|
6570
|
+
if (oldEditorUid !== -1) {
|
|
6571
|
+
try {
|
|
6572
|
+
await invoke('Viewlet.dispose', oldEditorUid);
|
|
6573
|
+
} catch {
|
|
6574
|
+
// Reopening should still proceed if the previous viewlet was already disposed.
|
|
6575
|
+
}
|
|
6576
|
+
}
|
|
6577
|
+
};
|
|
6578
|
+
|
|
6399
6579
|
const getLatestStoredState = (uid, fallbackState, referenceTabId, referenceTabUri, allowMissingReference = false) => {
|
|
6400
6580
|
const stateFromStore = get(uid);
|
|
6401
6581
|
if (!stateFromStore) {
|
|
@@ -6500,7 +6680,7 @@ const createEmptyGroup = () => {
|
|
|
6500
6680
|
return {
|
|
6501
6681
|
activeTabId: undefined,
|
|
6502
6682
|
focused: false,
|
|
6503
|
-
id: create$
|
|
6683
|
+
id: create$2(),
|
|
6504
6684
|
isEmpty: true,
|
|
6505
6685
|
size: 100,
|
|
6506
6686
|
tabs: []
|
|
@@ -6675,7 +6855,7 @@ const splitDown = (state, groupId) => {
|
|
|
6675
6855
|
|
|
6676
6856
|
// If there are no groups, create an initial empty group first
|
|
6677
6857
|
if (groups.length === 0) {
|
|
6678
|
-
const initialGroupId = create$
|
|
6858
|
+
const initialGroupId = create$2();
|
|
6679
6859
|
const initialGroup = {
|
|
6680
6860
|
activeTabId: undefined,
|
|
6681
6861
|
focused: true,
|
|
@@ -6710,7 +6890,7 @@ const splitLeft = (state, groupId) => {
|
|
|
6710
6890
|
groups
|
|
6711
6891
|
} = layout;
|
|
6712
6892
|
if (groups.length === 0) {
|
|
6713
|
-
const initialGroupId = create$
|
|
6893
|
+
const initialGroupId = create$2();
|
|
6714
6894
|
const initialGroup = {
|
|
6715
6895
|
activeTabId: undefined,
|
|
6716
6896
|
focused: true,
|
|
@@ -6744,7 +6924,7 @@ const splitRight = (state, groupId) => {
|
|
|
6744
6924
|
|
|
6745
6925
|
// If there are no groups, create an initial empty group first
|
|
6746
6926
|
if (groups.length === 0) {
|
|
6747
|
-
const initialGroupId = create$
|
|
6927
|
+
const initialGroupId = create$2();
|
|
6748
6928
|
const initialGroup = {
|
|
6749
6929
|
activeTabId: undefined,
|
|
6750
6930
|
focused: true,
|
|
@@ -6775,7 +6955,7 @@ const splitUp = (state, groupId) => {
|
|
|
6775
6955
|
groups
|
|
6776
6956
|
} = layout;
|
|
6777
6957
|
if (groups.length === 0) {
|
|
6778
|
-
const initialGroupId = create$
|
|
6958
|
+
const initialGroupId = create$2();
|
|
6779
6959
|
const initialGroup = {
|
|
6780
6960
|
activeTabId: undefined,
|
|
6781
6961
|
focused: true,
|
|
@@ -6838,7 +7018,7 @@ const commandMap = {
|
|
|
6838
7018
|
'MainArea.copyIntoNewWindow': wrapSerialCommand(copyIntoNewWindow$1),
|
|
6839
7019
|
'MainArea.copyPath': wrapSerialCommand(copyPath$1),
|
|
6840
7020
|
'MainArea.copyRelativePath': wrapSerialCommand(copyRelativePath$1),
|
|
6841
|
-
'MainArea.create': create$
|
|
7021
|
+
'MainArea.create': create$1,
|
|
6842
7022
|
'MainArea.diff2': diff2,
|
|
6843
7023
|
'MainArea.flipEditorLayout': wrapSerialCommand(flipLayout),
|
|
6844
7024
|
'MainArea.focusNext': wrapSerialCommand(focusNextTab),
|
|
@@ -6878,6 +7058,7 @@ const commandMap = {
|
|
|
6878
7058
|
'MainArea.refresh': wrapSerialCommand(refresh),
|
|
6879
7059
|
'MainArea.render2': render2,
|
|
6880
7060
|
'MainArea.renderEventListeners': renderEventListeners,
|
|
7061
|
+
'MainArea.reopenEditorWith': wrapSerialAsyncCommand(reopenEditorWith),
|
|
6881
7062
|
'MainArea.resize': wrapGetter(handleResize),
|
|
6882
7063
|
'MainArea.restoreClosedTab': wrapSerialCommand(restoreClosedTab),
|
|
6883
7064
|
'MainArea.save': wrapSerialCommand(save),
|