@lvce-editor/main-area-worker 4.0.0 → 5.0.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 +454 -132
- package/package.json +1 -1
|
@@ -102,14 +102,15 @@ const {
|
|
|
102
102
|
get: get$2,
|
|
103
103
|
getCommandIds,
|
|
104
104
|
registerCommands,
|
|
105
|
-
set: set$
|
|
105
|
+
set: set$4,
|
|
106
106
|
wrapCommand,
|
|
107
107
|
wrapGetter
|
|
108
108
|
} = create$7();
|
|
109
109
|
|
|
110
|
-
const create$6 = (uid, uri, x, y, width, height, platform, assetDir) => {
|
|
110
|
+
const create$6 = (uid, uri, x, y, width, height, platform, assetDir, tabHeight = 35) => {
|
|
111
111
|
const state = {
|
|
112
112
|
assetDir,
|
|
113
|
+
fileIconCache: {},
|
|
113
114
|
height,
|
|
114
115
|
layout: {
|
|
115
116
|
activeGroupId: undefined,
|
|
@@ -117,12 +118,13 @@ const create$6 = (uid, uri, x, y, width, height, platform, assetDir) => {
|
|
|
117
118
|
groups: []
|
|
118
119
|
},
|
|
119
120
|
platform,
|
|
121
|
+
tabHeight,
|
|
120
122
|
uid,
|
|
121
123
|
width,
|
|
122
124
|
x,
|
|
123
125
|
y
|
|
124
126
|
};
|
|
125
|
-
set$
|
|
127
|
+
set$4(uid, state, state);
|
|
126
128
|
};
|
|
127
129
|
|
|
128
130
|
const isEqual = (oldState, newState) => {
|
|
@@ -154,14 +156,7 @@ const diff2 = uid => {
|
|
|
154
156
|
return result;
|
|
155
157
|
};
|
|
156
158
|
|
|
157
|
-
const Button$1 =
|
|
158
|
-
const Div = 4;
|
|
159
|
-
const Span = 8;
|
|
160
|
-
const Text = 12;
|
|
161
|
-
const Img = 17;
|
|
162
|
-
const Pre = 51;
|
|
163
|
-
|
|
164
|
-
const Button = 'event.button';
|
|
159
|
+
const Button$1 = 'event.button';
|
|
165
160
|
const ClientX = 'event.clientX';
|
|
166
161
|
const ClientY = 'event.clientY';
|
|
167
162
|
const TargetName = 'event.target.name';
|
|
@@ -171,9 +166,6 @@ const Tab = 13;
|
|
|
171
166
|
const Separator = 1;
|
|
172
167
|
const None = 0;
|
|
173
168
|
|
|
174
|
-
const ExtensionHostWorker = 44;
|
|
175
|
-
const RendererWorker = 1;
|
|
176
|
-
|
|
177
169
|
const SetDom2 = 'Viewlet.setDom2';
|
|
178
170
|
|
|
179
171
|
const getMenuIds = () => {
|
|
@@ -187,6 +179,10 @@ const handleClick = async (state, name) => {
|
|
|
187
179
|
return state;
|
|
188
180
|
};
|
|
189
181
|
|
|
182
|
+
const ExtensionHostWorker = 44;
|
|
183
|
+
const IconThemeWorker = 7009;
|
|
184
|
+
const RendererWorker = 1;
|
|
185
|
+
|
|
190
186
|
const normalizeLine = line => {
|
|
191
187
|
if (line.startsWith('Error: ')) {
|
|
192
188
|
return line.slice('Error: '.length);
|
|
@@ -1152,6 +1148,53 @@ const listen$1 = async (module, options) => {
|
|
|
1152
1148
|
const ipc = module.wrap(rawIpc);
|
|
1153
1149
|
return ipc;
|
|
1154
1150
|
};
|
|
1151
|
+
|
|
1152
|
+
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
1153
|
+
|
|
1154
|
+
const createSharedLazyRpc = factory => {
|
|
1155
|
+
let rpcPromise;
|
|
1156
|
+
const getOrCreate = () => {
|
|
1157
|
+
if (!rpcPromise) {
|
|
1158
|
+
rpcPromise = factory();
|
|
1159
|
+
}
|
|
1160
|
+
return rpcPromise;
|
|
1161
|
+
};
|
|
1162
|
+
return {
|
|
1163
|
+
async dispose() {
|
|
1164
|
+
const rpc = await getOrCreate();
|
|
1165
|
+
await rpc.dispose();
|
|
1166
|
+
},
|
|
1167
|
+
async invoke(method, ...params) {
|
|
1168
|
+
const rpc = await getOrCreate();
|
|
1169
|
+
return rpc.invoke(method, ...params);
|
|
1170
|
+
},
|
|
1171
|
+
async invokeAndTransfer(method, ...params) {
|
|
1172
|
+
const rpc = await getOrCreate();
|
|
1173
|
+
return rpc.invokeAndTransfer(method, ...params);
|
|
1174
|
+
},
|
|
1175
|
+
async send(method, ...params) {
|
|
1176
|
+
const rpc = await getOrCreate();
|
|
1177
|
+
rpc.send(method, ...params);
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
1180
|
+
};
|
|
1181
|
+
const create$j = async ({
|
|
1182
|
+
commandMap,
|
|
1183
|
+
isMessagePortOpen,
|
|
1184
|
+
send
|
|
1185
|
+
}) => {
|
|
1186
|
+
return createSharedLazyRpc(() => {
|
|
1187
|
+
return create$3({
|
|
1188
|
+
commandMap,
|
|
1189
|
+
isMessagePortOpen,
|
|
1190
|
+
send
|
|
1191
|
+
});
|
|
1192
|
+
});
|
|
1193
|
+
};
|
|
1194
|
+
const LazyTransferMessagePortRpcParent = {
|
|
1195
|
+
__proto__: null,
|
|
1196
|
+
create: create$j
|
|
1197
|
+
};
|
|
1155
1198
|
const create$5 = async ({
|
|
1156
1199
|
commandMap,
|
|
1157
1200
|
isMessagePortOpen = true,
|
|
@@ -1224,7 +1267,7 @@ const createMockRpc = ({
|
|
|
1224
1267
|
};
|
|
1225
1268
|
|
|
1226
1269
|
const rpcs = Object.create(null);
|
|
1227
|
-
const set$
|
|
1270
|
+
const set$3 = (id, rpc) => {
|
|
1228
1271
|
rpcs[id] = rpc;
|
|
1229
1272
|
};
|
|
1230
1273
|
const get = id => {
|
|
@@ -1257,7 +1300,7 @@ const create$1 = rpcId => {
|
|
|
1257
1300
|
const mockRpc = createMockRpc({
|
|
1258
1301
|
commandMap
|
|
1259
1302
|
});
|
|
1260
|
-
set$
|
|
1303
|
+
set$3(rpcId, mockRpc);
|
|
1261
1304
|
// @ts-ignore
|
|
1262
1305
|
mockRpc[Symbol.dispose] = () => {
|
|
1263
1306
|
remove(rpcId);
|
|
@@ -1266,15 +1309,24 @@ const create$1 = rpcId => {
|
|
|
1266
1309
|
return mockRpc;
|
|
1267
1310
|
},
|
|
1268
1311
|
set(rpc) {
|
|
1269
|
-
set$
|
|
1312
|
+
set$3(rpcId, rpc);
|
|
1270
1313
|
}
|
|
1271
1314
|
};
|
|
1272
1315
|
};
|
|
1273
1316
|
|
|
1274
1317
|
const {
|
|
1275
|
-
set: set$
|
|
1318
|
+
set: set$2
|
|
1276
1319
|
} = create$1(ExtensionHostWorker);
|
|
1277
1320
|
|
|
1321
|
+
const {
|
|
1322
|
+
invoke: invoke$1,
|
|
1323
|
+
set: set$1
|
|
1324
|
+
} = create$1(IconThemeWorker);
|
|
1325
|
+
const getIcons = async iconRequests => {
|
|
1326
|
+
// @ts-ignore
|
|
1327
|
+
return invoke$1('IconTheme.getIcons', iconRequests);
|
|
1328
|
+
};
|
|
1329
|
+
|
|
1278
1330
|
const {
|
|
1279
1331
|
invoke,
|
|
1280
1332
|
invokeAndTransfer,
|
|
@@ -1288,6 +1340,11 @@ const showContextMenu2 = async (uid, menuId, x, y, args) => {
|
|
|
1288
1340
|
// @ts-ignore
|
|
1289
1341
|
await invoke('ContextMenu.show2', uid, menuId, x, y, args);
|
|
1290
1342
|
};
|
|
1343
|
+
const sendMessagePortToIconThemeWorker = async (port, rpcId) => {
|
|
1344
|
+
const command = 'IconTheme.handleMessagePort';
|
|
1345
|
+
// @ts-ignore
|
|
1346
|
+
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToIconThemeWorker', port, command, rpcId);
|
|
1347
|
+
};
|
|
1291
1348
|
const sendMessagePortToExtensionHostWorker$1 = async (port, rpcId = 0) => {
|
|
1292
1349
|
const command = 'HandleMessagePort.handleMessagePort2';
|
|
1293
1350
|
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, command, rpcId);
|
|
@@ -1498,7 +1555,7 @@ const handleCreate = async command => {
|
|
|
1498
1555
|
oldState
|
|
1499
1556
|
} = get$2(command.uid);
|
|
1500
1557
|
const readyState = handleViewletReady(state, command.editorUid);
|
|
1501
|
-
set$
|
|
1558
|
+
set$4(command.uid, oldState, readyState);
|
|
1502
1559
|
return readyState;
|
|
1503
1560
|
};
|
|
1504
1561
|
|
|
@@ -1624,6 +1681,30 @@ const handleClickCloseTab = (state, rawGroupIndex, rawIndex) => {
|
|
|
1624
1681
|
return closeTab(state, groupId, tabId);
|
|
1625
1682
|
};
|
|
1626
1683
|
|
|
1684
|
+
const createViewlet = async (viewletModuleId, editorUid, tabId, bounds, uri) => {
|
|
1685
|
+
// @ts-ignore
|
|
1686
|
+
await invoke('Layout.createViewlet', viewletModuleId, editorUid, tabId, bounds, uri);
|
|
1687
|
+
};
|
|
1688
|
+
|
|
1689
|
+
const findTabById = (state, tabId) => {
|
|
1690
|
+
const {
|
|
1691
|
+
layout
|
|
1692
|
+
} = state;
|
|
1693
|
+
const {
|
|
1694
|
+
groups
|
|
1695
|
+
} = layout;
|
|
1696
|
+
for (const group of groups) {
|
|
1697
|
+
const tab = group.tabs.find(t => t.id === tabId);
|
|
1698
|
+
if (tab) {
|
|
1699
|
+
return {
|
|
1700
|
+
groupId: group.id,
|
|
1701
|
+
tab
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
return undefined;
|
|
1706
|
+
};
|
|
1707
|
+
|
|
1627
1708
|
// Counter for request IDs to handle race conditions
|
|
1628
1709
|
let requestIdCounter = 0;
|
|
1629
1710
|
const getNextRequestId = () => {
|
|
@@ -1635,7 +1716,7 @@ const startContentLoading = async (oldState, state, tabId, path, requestId) => {
|
|
|
1635
1716
|
const getLatestState = () => {
|
|
1636
1717
|
return get$2(state.uid).newState;
|
|
1637
1718
|
};
|
|
1638
|
-
set$
|
|
1719
|
+
set$4(state.uid, oldState, state);
|
|
1639
1720
|
const newState = await loadTabContentAsync(tabId, path, requestId, getLatestState);
|
|
1640
1721
|
return newState;
|
|
1641
1722
|
} catch {
|
|
@@ -1765,12 +1846,43 @@ const selectTab = async (state, groupIndex, index) => {
|
|
|
1765
1846
|
};
|
|
1766
1847
|
const createdState = createViewletForTab(newState, tabId, viewletModuleId, bounds);
|
|
1767
1848
|
newState = createdState;
|
|
1849
|
+
|
|
1850
|
+
// Store updated state before creating viewlet
|
|
1851
|
+
set$4(uid, state, newState);
|
|
1852
|
+
|
|
1853
|
+
// Execute viewlet commands if any
|
|
1854
|
+
if (switchCommands.length > 0) {
|
|
1855
|
+
await executeViewletCommands(switchCommands);
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
// Get the tab to extract editorUid for viewlet creation
|
|
1859
|
+
const tabWithViewlet = findTabById(newState, tabId);
|
|
1860
|
+
if (tabWithViewlet) {
|
|
1861
|
+
const {
|
|
1862
|
+
editorUid
|
|
1863
|
+
} = tabWithViewlet.tab;
|
|
1864
|
+
if (editorUid !== -1 && newTab.uri) {
|
|
1865
|
+
// Create the actual viewlet instance
|
|
1866
|
+
await createViewlet(viewletModuleId, editorUid, tabId, bounds, newTab.uri);
|
|
1867
|
+
|
|
1868
|
+
// Mark viewlet as ready
|
|
1869
|
+
newState = handleViewletReady(newState, editorUid);
|
|
1870
|
+
set$4(uid, state, newState);
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
// Start loading content in the background if needed
|
|
1875
|
+
if (needsLoading && tab.uri) {
|
|
1876
|
+
const latestState = await startContentLoading(state, newState, tabId, tab.uri, requestId);
|
|
1877
|
+
return latestState;
|
|
1878
|
+
}
|
|
1879
|
+
return newState;
|
|
1768
1880
|
}
|
|
1769
1881
|
} catch {
|
|
1770
1882
|
// Viewlet creation is optional - silently ignore if RendererWorker isn't available
|
|
1771
1883
|
}
|
|
1772
1884
|
}
|
|
1773
|
-
set$
|
|
1885
|
+
set$4(uid, state, newState);
|
|
1774
1886
|
|
|
1775
1887
|
// Execute viewlet commands if any
|
|
1776
1888
|
if (switchCommands.length > 0) {
|
|
@@ -1829,12 +1941,7 @@ const createExtensionHostRpc = async () => {
|
|
|
1829
1941
|
|
|
1830
1942
|
const initialize = async () => {
|
|
1831
1943
|
const rpc = await createExtensionHostRpc();
|
|
1832
|
-
set$
|
|
1833
|
-
};
|
|
1834
|
-
|
|
1835
|
-
const createViewlet = async (viewletModuleId, editorUid, tabId, bounds, uri) => {
|
|
1836
|
-
// @ts-ignore
|
|
1837
|
-
await invoke('Layout.createViewlet', viewletModuleId, editorUid, tabId, bounds, uri);
|
|
1944
|
+
set$2(rpc);
|
|
1838
1945
|
};
|
|
1839
1946
|
|
|
1840
1947
|
const getMaxIdFromLayout = layout => {
|
|
@@ -1852,18 +1959,6 @@ const getMaxIdFromLayout = layout => {
|
|
|
1852
1959
|
return maxId;
|
|
1853
1960
|
};
|
|
1854
1961
|
|
|
1855
|
-
const getViewletModuleId = async uri => {
|
|
1856
|
-
// Query RendererWorker for viewlet module ID (optional, may fail in tests)
|
|
1857
|
-
let viewletModuleId;
|
|
1858
|
-
try {
|
|
1859
|
-
// @ts-ignore
|
|
1860
|
-
viewletModuleId = await invoke('Layout.getModuleId', uri);
|
|
1861
|
-
} catch {
|
|
1862
|
-
// Viewlet creation is optional - silently ignore if RendererWorker isn't available
|
|
1863
|
-
}
|
|
1864
|
-
return viewletModuleId;
|
|
1865
|
-
};
|
|
1866
|
-
|
|
1867
1962
|
const isValidTab = tab => {
|
|
1868
1963
|
return tab && typeof tab.id === 'number' && typeof tab.title === 'string' && typeof tab.content === 'string' && typeof tab.isDirty === 'boolean' && (tab.editorType === 'text' || tab.editorType === 'custom') && (tab.editorType !== 'custom' || typeof tab.customEditorId === 'string');
|
|
1869
1964
|
};
|
|
@@ -1908,71 +2003,254 @@ const tryRestoreLayout = savedState => {
|
|
|
1908
2003
|
return layout;
|
|
1909
2004
|
};
|
|
1910
2005
|
|
|
2006
|
+
const getIconsCached = (dirents, fileIconCache) => {
|
|
2007
|
+
return dirents.map(dirent => fileIconCache[dirent]);
|
|
2008
|
+
};
|
|
2009
|
+
|
|
2010
|
+
const getBasename$1 = uri => {
|
|
2011
|
+
const lastSlashIndex = uri.lastIndexOf('/');
|
|
2012
|
+
if (lastSlashIndex === -1) {
|
|
2013
|
+
return uri;
|
|
2014
|
+
}
|
|
2015
|
+
return uri.slice(lastSlashIndex + 1);
|
|
2016
|
+
};
|
|
2017
|
+
const getMissingTabs = (tabs, fileIconCache) => {
|
|
2018
|
+
const missingTabs = [];
|
|
2019
|
+
for (const tab of tabs) {
|
|
2020
|
+
if (tab.uri && !(tab.uri in fileIconCache)) {
|
|
2021
|
+
missingTabs.push(tab);
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
return missingTabs;
|
|
2025
|
+
};
|
|
2026
|
+
const tabToIconRequest = tab => {
|
|
2027
|
+
const uri = tab.uri || '';
|
|
2028
|
+
return {
|
|
2029
|
+
name: getBasename$1(uri),
|
|
2030
|
+
path: uri,
|
|
2031
|
+
type: 0 // file type
|
|
2032
|
+
};
|
|
2033
|
+
};
|
|
2034
|
+
const getMissingIconRequestsForTabs = (tabs, fileIconCache) => {
|
|
2035
|
+
const missingRequests = getMissingTabs(tabs, fileIconCache);
|
|
2036
|
+
const iconRequests = missingRequests.map(tabToIconRequest);
|
|
2037
|
+
return iconRequests;
|
|
2038
|
+
};
|
|
2039
|
+
|
|
2040
|
+
const Directory = 3;
|
|
2041
|
+
const DirectoryExpanded = 4;
|
|
2042
|
+
|
|
2043
|
+
const getSimpleIconRequestType = direntType => {
|
|
2044
|
+
if (direntType === Directory || direntType === DirectoryExpanded) {
|
|
2045
|
+
return 2;
|
|
2046
|
+
}
|
|
2047
|
+
return 1;
|
|
2048
|
+
};
|
|
2049
|
+
|
|
2050
|
+
const toSimpleIconRequest = request => {
|
|
2051
|
+
return {
|
|
2052
|
+
name: request.name,
|
|
2053
|
+
type: getSimpleIconRequestType(request.type)
|
|
2054
|
+
};
|
|
2055
|
+
};
|
|
2056
|
+
|
|
2057
|
+
const requestFileIcons = async requests => {
|
|
2058
|
+
if (requests.length === 0) {
|
|
2059
|
+
return [];
|
|
2060
|
+
}
|
|
2061
|
+
const simpleRequests = requests.map(toSimpleIconRequest);
|
|
2062
|
+
const icons = await getIcons(simpleRequests);
|
|
2063
|
+
return icons;
|
|
2064
|
+
};
|
|
2065
|
+
|
|
2066
|
+
const updateIconCache = (iconCache, missingRequests, newIcons) => {
|
|
2067
|
+
if (missingRequests.length === 0) {
|
|
2068
|
+
return iconCache;
|
|
2069
|
+
}
|
|
2070
|
+
const newFileIconCache = {
|
|
2071
|
+
...iconCache
|
|
2072
|
+
};
|
|
2073
|
+
for (let i = 0; i < missingRequests.length; i++) {
|
|
2074
|
+
const request = missingRequests[i];
|
|
2075
|
+
const icon = newIcons[i];
|
|
2076
|
+
newFileIconCache[request.path] = icon;
|
|
2077
|
+
}
|
|
2078
|
+
return newFileIconCache;
|
|
2079
|
+
};
|
|
2080
|
+
|
|
2081
|
+
const getFileIconsForTabs = async (tabs, fileIconCache) => {
|
|
2082
|
+
const missingRequests = getMissingIconRequestsForTabs(tabs, fileIconCache);
|
|
2083
|
+
const newIcons = await requestFileIcons(missingRequests);
|
|
2084
|
+
const newFileIconCache = updateIconCache(fileIconCache, missingRequests, newIcons);
|
|
2085
|
+
const tabUris = tabs.map(tab => tab.uri || '');
|
|
2086
|
+
const icons = getIconsCached(tabUris, newFileIconCache);
|
|
2087
|
+
return {
|
|
2088
|
+
icons,
|
|
2089
|
+
newFileIconCache
|
|
2090
|
+
};
|
|
2091
|
+
};
|
|
2092
|
+
|
|
2093
|
+
const getAllTabs = layout => {
|
|
2094
|
+
const allTabs = [];
|
|
2095
|
+
for (const group of layout.groups) {
|
|
2096
|
+
allTabs.push(...group.tabs);
|
|
2097
|
+
}
|
|
2098
|
+
return allTabs;
|
|
2099
|
+
};
|
|
2100
|
+
|
|
2101
|
+
const loadFileIcons = async state => {
|
|
2102
|
+
try {
|
|
2103
|
+
const allTabs = getAllTabs(state.layout);
|
|
2104
|
+
const {
|
|
2105
|
+
newFileIconCache
|
|
2106
|
+
} = await getFileIconsForTabs(allTabs, state.fileIconCache);
|
|
2107
|
+
|
|
2108
|
+
// Update tabs with their icons
|
|
2109
|
+
const updatedLayout = {
|
|
2110
|
+
...state.layout,
|
|
2111
|
+
groups: state.layout.groups.map(group => ({
|
|
2112
|
+
...group,
|
|
2113
|
+
tabs: group.tabs.map(tab => ({
|
|
2114
|
+
...tab,
|
|
2115
|
+
icon: newFileIconCache[tab.uri || '']
|
|
2116
|
+
}))
|
|
2117
|
+
}))
|
|
2118
|
+
};
|
|
2119
|
+
return {
|
|
2120
|
+
fileIconCache: newFileIconCache,
|
|
2121
|
+
updatedLayout
|
|
2122
|
+
};
|
|
2123
|
+
} catch {
|
|
2124
|
+
// If icon request fails, continue without icons
|
|
2125
|
+
return {
|
|
2126
|
+
fileIconCache: state.fileIconCache,
|
|
2127
|
+
updatedLayout: state.layout
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2130
|
+
};
|
|
2131
|
+
|
|
2132
|
+
const getViewletModuleId = async uri => {
|
|
2133
|
+
// Query RendererWorker for viewlet module ID (optional, may fail in tests)
|
|
2134
|
+
let viewletModuleId;
|
|
2135
|
+
try {
|
|
2136
|
+
// @ts-ignore
|
|
2137
|
+
viewletModuleId = await invoke('Layout.getModuleId', uri);
|
|
2138
|
+
} catch {
|
|
2139
|
+
// Viewlet creation is optional - silently ignore if RendererWorker isn't available
|
|
2140
|
+
}
|
|
2141
|
+
return viewletModuleId;
|
|
2142
|
+
};
|
|
2143
|
+
|
|
2144
|
+
const TAB_HEIGHT = 35;
|
|
2145
|
+
|
|
2146
|
+
// Get viewlet module IDs for active tabs in each group
|
|
2147
|
+
const getViewletModuleIds = async layout => {
|
|
2148
|
+
const viewletModuleIds = {};
|
|
2149
|
+
for (const group of layout.groups) {
|
|
2150
|
+
const activeTab = group.tabs.find(tab => tab.id === group.activeTabId);
|
|
2151
|
+
if (activeTab && activeTab.uri) {
|
|
2152
|
+
const viewletModuleId = await getViewletModuleId(activeTab.uri);
|
|
2153
|
+
if (viewletModuleId) {
|
|
2154
|
+
viewletModuleIds[activeTab.id] = viewletModuleId;
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
return viewletModuleIds;
|
|
2159
|
+
};
|
|
2160
|
+
|
|
2161
|
+
// Create viewlets for the active tabs
|
|
2162
|
+
const createViewlets = async (layout, viewletModuleIds, bounds) => {
|
|
2163
|
+
const editorUids = {};
|
|
2164
|
+
for (const group of layout.groups) {
|
|
2165
|
+
const activeTab = group.tabs.find(tab => tab.id === group.activeTabId);
|
|
2166
|
+
if (activeTab && viewletModuleIds[activeTab.id]) {
|
|
2167
|
+
const editorUid = activeTab.editorUid === -1 ? create() : activeTab.editorUid;
|
|
2168
|
+
editorUids[activeTab.id] = editorUid;
|
|
2169
|
+
await createViewlet(viewletModuleIds[activeTab.id], editorUid, activeTab.id, bounds, activeTab.uri);
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
return editorUids;
|
|
2173
|
+
};
|
|
2174
|
+
|
|
2175
|
+
// Update tabs with editor UIDs
|
|
2176
|
+
const updateTabs = (state, editorUids) => {
|
|
2177
|
+
const updatedGroups = state.layout.groups.map(group => {
|
|
2178
|
+
return {
|
|
2179
|
+
...group,
|
|
2180
|
+
tabs: group.tabs.map(tab => {
|
|
2181
|
+
if (editorUids[tab.id]) {
|
|
2182
|
+
return {
|
|
2183
|
+
...tab,
|
|
2184
|
+
editorUid: editorUids[tab.id]
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2187
|
+
return tab;
|
|
2188
|
+
})
|
|
2189
|
+
};
|
|
2190
|
+
});
|
|
2191
|
+
return {
|
|
2192
|
+
...state,
|
|
2193
|
+
layout: {
|
|
2194
|
+
...state.layout,
|
|
2195
|
+
groups: updatedGroups
|
|
2196
|
+
}
|
|
2197
|
+
};
|
|
2198
|
+
};
|
|
2199
|
+
const restoreAndCreateEditors = async (state, restoredLayout) => {
|
|
2200
|
+
let newState = {
|
|
2201
|
+
...state,
|
|
2202
|
+
layout: restoredLayout
|
|
2203
|
+
};
|
|
2204
|
+
const bounds = {
|
|
2205
|
+
height: newState.height - TAB_HEIGHT,
|
|
2206
|
+
width: newState.width,
|
|
2207
|
+
x: newState.x,
|
|
2208
|
+
y: newState.y + TAB_HEIGHT
|
|
2209
|
+
};
|
|
2210
|
+
|
|
2211
|
+
// Get viewlet module IDs for all active tabs
|
|
2212
|
+
const viewletModuleIds = await getViewletModuleIds(newState.layout);
|
|
2213
|
+
|
|
2214
|
+
// Create viewlets and get editor UIDs
|
|
2215
|
+
const editorUids = await createViewlets(newState.layout, viewletModuleIds, bounds);
|
|
2216
|
+
|
|
2217
|
+
// Update tabs with editor UIDs
|
|
2218
|
+
newState = updateTabs(newState, editorUids);
|
|
2219
|
+
|
|
2220
|
+
// Create viewlets in the lifecycle and mark them as ready
|
|
2221
|
+
for (const group of newState.layout.groups) {
|
|
2222
|
+
const activeTab = group.tabs.find(tab => tab.id === group.activeTabId);
|
|
2223
|
+
if (activeTab && viewletModuleIds[activeTab.id]) {
|
|
2224
|
+
const editorUid = editorUids[activeTab.id];
|
|
2225
|
+
newState = createViewletForTab(newState, activeTab.id);
|
|
2226
|
+
newState = handleViewletReady(newState, editorUid);
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
return newState;
|
|
2230
|
+
};
|
|
2231
|
+
|
|
1911
2232
|
const loadContent = async (state, savedState) => {
|
|
1912
2233
|
const restoredLayout = tryRestoreLayout(savedState);
|
|
1913
2234
|
if (restoredLayout) {
|
|
1914
2235
|
const maxId = getMaxIdFromLayout(restoredLayout);
|
|
1915
2236
|
setMinId(maxId);
|
|
1916
|
-
let newState = {
|
|
1917
|
-
...state,
|
|
1918
|
-
layout: restoredLayout
|
|
1919
|
-
};
|
|
1920
|
-
|
|
1921
|
-
// Create viewlets only for active tabs in each group
|
|
1922
|
-
const TAB_HEIGHT = 35;
|
|
1923
|
-
const bounds = {
|
|
1924
|
-
height: newState.height - TAB_HEIGHT,
|
|
1925
|
-
width: newState.width,
|
|
1926
|
-
x: newState.x,
|
|
1927
|
-
y: newState.y + TAB_HEIGHT
|
|
1928
|
-
};
|
|
1929
|
-
for (const group of restoredLayout.groups) {
|
|
1930
|
-
// Find the active tab in this group
|
|
1931
|
-
const activeTab = group.tabs.find(tab => tab.id === group.activeTabId);
|
|
1932
|
-
if (activeTab && activeTab.uri) {
|
|
1933
|
-
const viewletModuleId = await getViewletModuleId(activeTab.uri);
|
|
1934
|
-
if (viewletModuleId) {
|
|
1935
|
-
// Ensure the tab has an editorUid
|
|
1936
|
-
const editorUid = activeTab.editorUid === -1 ? create() : activeTab.editorUid;
|
|
1937
|
-
|
|
1938
|
-
// Create viewlet for the tab
|
|
1939
|
-
newState = createViewletForTab(newState, activeTab.id);
|
|
1940
|
-
|
|
1941
|
-
// Update the tab with the editorUid in the state
|
|
1942
|
-
const updatedGroups = newState.layout.groups.map(g => {
|
|
1943
|
-
if (g.id !== group.id) {
|
|
1944
|
-
return g;
|
|
1945
|
-
}
|
|
1946
|
-
return {
|
|
1947
|
-
...g,
|
|
1948
|
-
tabs: g.tabs.map(t => {
|
|
1949
|
-
if (t.id !== activeTab.id) {
|
|
1950
|
-
return t;
|
|
1951
|
-
}
|
|
1952
|
-
return {
|
|
1953
|
-
...t,
|
|
1954
|
-
editorUid
|
|
1955
|
-
};
|
|
1956
|
-
})
|
|
1957
|
-
};
|
|
1958
|
-
});
|
|
1959
|
-
newState = {
|
|
1960
|
-
...newState,
|
|
1961
|
-
layout: {
|
|
1962
|
-
...newState.layout,
|
|
1963
|
-
groups: updatedGroups
|
|
1964
|
-
}
|
|
1965
|
-
};
|
|
1966
2237
|
|
|
1967
|
-
|
|
1968
|
-
|
|
2238
|
+
// Restore and create editors
|
|
2239
|
+
const editorState = await restoreAndCreateEditors(state, restoredLayout);
|
|
1969
2240
|
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
}
|
|
1975
|
-
|
|
2241
|
+
// Load file icons with the updated editor state
|
|
2242
|
+
const {
|
|
2243
|
+
fileIconCache,
|
|
2244
|
+
updatedLayout
|
|
2245
|
+
} = await loadFileIcons(editorState);
|
|
2246
|
+
|
|
2247
|
+
// Merge the results
|
|
2248
|
+
const finalState = {
|
|
2249
|
+
...editorState,
|
|
2250
|
+
fileIconCache,
|
|
2251
|
+
layout: updatedLayout
|
|
2252
|
+
};
|
|
2253
|
+
return finalState;
|
|
1976
2254
|
}
|
|
1977
2255
|
return {
|
|
1978
2256
|
...state,
|
|
@@ -2125,6 +2403,7 @@ const createEmptyGroup = (state, uri, requestId) => {
|
|
|
2125
2403
|
editorType: 'text',
|
|
2126
2404
|
editorUid,
|
|
2127
2405
|
errorMessage: '',
|
|
2406
|
+
icon: '',
|
|
2128
2407
|
id: tabId,
|
|
2129
2408
|
isDirty: false,
|
|
2130
2409
|
language: '',
|
|
@@ -2205,6 +2484,7 @@ const ensureActiveGroup = (state, uri) => {
|
|
|
2205
2484
|
editorType: 'text',
|
|
2206
2485
|
editorUid,
|
|
2207
2486
|
errorMessage: '',
|
|
2487
|
+
icon: '',
|
|
2208
2488
|
id: tabId,
|
|
2209
2489
|
isDirty: false,
|
|
2210
2490
|
language: '',
|
|
@@ -2219,25 +2499,6 @@ const ensureActiveGroup = (state, uri) => {
|
|
|
2219
2499
|
return newState;
|
|
2220
2500
|
};
|
|
2221
2501
|
|
|
2222
|
-
const findTabById = (state, tabId) => {
|
|
2223
|
-
const {
|
|
2224
|
-
layout
|
|
2225
|
-
} = state;
|
|
2226
|
-
const {
|
|
2227
|
-
groups
|
|
2228
|
-
} = layout;
|
|
2229
|
-
for (const group of groups) {
|
|
2230
|
-
const tab = group.tabs.find(t => t.id === tabId);
|
|
2231
|
-
if (tab) {
|
|
2232
|
-
return {
|
|
2233
|
-
groupId: group.id,
|
|
2234
|
-
tab
|
|
2235
|
-
};
|
|
2236
|
-
}
|
|
2237
|
-
}
|
|
2238
|
-
return undefined;
|
|
2239
|
-
};
|
|
2240
|
-
|
|
2241
2502
|
const findTabByUri = (state, uri) => {
|
|
2242
2503
|
const {
|
|
2243
2504
|
layout
|
|
@@ -2372,7 +2633,7 @@ const openUri = async (state, options) => {
|
|
|
2372
2633
|
newState: switchedState
|
|
2373
2634
|
} = switchViewlet(intermediateState1);
|
|
2374
2635
|
intermediateState1 = switchedState;
|
|
2375
|
-
set$
|
|
2636
|
+
set$4(uid, state, intermediateState1);
|
|
2376
2637
|
|
|
2377
2638
|
// @ts-ignore
|
|
2378
2639
|
|
|
@@ -2397,6 +2658,36 @@ const openUri = async (state, options) => {
|
|
|
2397
2658
|
|
|
2398
2659
|
// Attachment is handled automatically by virtual DOM reference nodes
|
|
2399
2660
|
const readyState = handleViewletReady(latestState, editorUid);
|
|
2661
|
+
|
|
2662
|
+
// Request file icon for the newly opened tab
|
|
2663
|
+
try {
|
|
2664
|
+
const newTab = findTabById(readyState, tabId);
|
|
2665
|
+
if (newTab && newTab.tab.uri) {
|
|
2666
|
+
const {
|
|
2667
|
+
newFileIconCache
|
|
2668
|
+
} = await getFileIconsForTabs([newTab.tab], readyState.fileIconCache);
|
|
2669
|
+
const icon = newFileIconCache[newTab.tab.uri] || '';
|
|
2670
|
+
|
|
2671
|
+
// Update the tab with the icon
|
|
2672
|
+
const stateWithIcon = {
|
|
2673
|
+
...readyState,
|
|
2674
|
+
fileIconCache: newFileIconCache,
|
|
2675
|
+
layout: {
|
|
2676
|
+
...readyState.layout,
|
|
2677
|
+
groups: readyState.layout.groups.map(group => ({
|
|
2678
|
+
...group,
|
|
2679
|
+
tabs: group.tabs.map(tab => tab.id === tabId ? {
|
|
2680
|
+
...tab,
|
|
2681
|
+
icon
|
|
2682
|
+
} : tab)
|
|
2683
|
+
}))
|
|
2684
|
+
}
|
|
2685
|
+
};
|
|
2686
|
+
return stateWithIcon;
|
|
2687
|
+
}
|
|
2688
|
+
} catch {
|
|
2689
|
+
// If icon request fails, continue without icon
|
|
2690
|
+
}
|
|
2400
2691
|
return readyState;
|
|
2401
2692
|
};
|
|
2402
2693
|
|
|
@@ -2406,6 +2697,13 @@ const refresh = state => {
|
|
|
2406
2697
|
};
|
|
2407
2698
|
};
|
|
2408
2699
|
|
|
2700
|
+
const Button = 1;
|
|
2701
|
+
const Div = 4;
|
|
2702
|
+
const Span = 8;
|
|
2703
|
+
const Text = 12;
|
|
2704
|
+
const Img = 17;
|
|
2705
|
+
const Pre = 51;
|
|
2706
|
+
|
|
2409
2707
|
const text = data => {
|
|
2410
2708
|
return {
|
|
2411
2709
|
childCount: 0,
|
|
@@ -2417,17 +2715,18 @@ const text = data => {
|
|
|
2417
2715
|
const CSS_CLASSES = {
|
|
2418
2716
|
EDITOR_GROUPS_CONTAINER: 'editor-groups-container'};
|
|
2419
2717
|
|
|
2420
|
-
const
|
|
2718
|
+
const renderContent = content => {
|
|
2421
2719
|
return [{
|
|
2422
2720
|
childCount: 1,
|
|
2423
|
-
className: 'TextEditor
|
|
2721
|
+
className: 'TextEditor',
|
|
2424
2722
|
type: Div
|
|
2425
2723
|
}, {
|
|
2426
2724
|
childCount: 1,
|
|
2427
|
-
className: 'EditorContent
|
|
2428
|
-
type:
|
|
2429
|
-
}, text(
|
|
2725
|
+
className: 'EditorContent',
|
|
2726
|
+
type: Pre
|
|
2727
|
+
}, text(content)];
|
|
2430
2728
|
};
|
|
2729
|
+
|
|
2431
2730
|
const renderError = errorMessage => {
|
|
2432
2731
|
return [{
|
|
2433
2732
|
childCount: 1,
|
|
@@ -2439,17 +2738,19 @@ const renderError = errorMessage => {
|
|
|
2439
2738
|
type: Div
|
|
2440
2739
|
}, text(`Error: ${errorMessage}`)];
|
|
2441
2740
|
};
|
|
2442
|
-
|
|
2741
|
+
|
|
2742
|
+
const renderLoading = () => {
|
|
2443
2743
|
return [{
|
|
2444
2744
|
childCount: 1,
|
|
2445
|
-
className: 'TextEditor',
|
|
2745
|
+
className: 'TextEditor TextEditor--loading',
|
|
2446
2746
|
type: Div
|
|
2447
2747
|
}, {
|
|
2448
2748
|
childCount: 1,
|
|
2449
|
-
className: 'EditorContent',
|
|
2450
|
-
type:
|
|
2451
|
-
}, text(
|
|
2749
|
+
className: 'EditorContent EditorContent--loading',
|
|
2750
|
+
type: Div
|
|
2751
|
+
}, text('Loading...')];
|
|
2452
2752
|
};
|
|
2753
|
+
|
|
2453
2754
|
const renderViewletReference = tab => {
|
|
2454
2755
|
return [{
|
|
2455
2756
|
childCount: 0,
|
|
@@ -2458,6 +2759,7 @@ const renderViewletReference = tab => {
|
|
|
2458
2759
|
uid: tab.editorUid
|
|
2459
2760
|
}];
|
|
2460
2761
|
};
|
|
2762
|
+
|
|
2461
2763
|
const renderEditor = tab => {
|
|
2462
2764
|
if (!tab) {
|
|
2463
2765
|
// Keep backward compatible behavior: render empty content
|
|
@@ -2504,7 +2806,7 @@ const renderTab = (tab, isActive, tabIndex, groupIndex) => {
|
|
|
2504
2806
|
}, {
|
|
2505
2807
|
childCount: 0,
|
|
2506
2808
|
className: 'TabIcon',
|
|
2507
|
-
src:
|
|
2809
|
+
src: tab.icon,
|
|
2508
2810
|
type: Img
|
|
2509
2811
|
}, {
|
|
2510
2812
|
childCount: 1,
|
|
@@ -2516,7 +2818,7 @@ const renderTab = (tab, isActive, tabIndex, groupIndex) => {
|
|
|
2516
2818
|
'data-groupIndex': groupIndex,
|
|
2517
2819
|
'data-index': tabIndex,
|
|
2518
2820
|
onClick: HandleClickClose,
|
|
2519
|
-
type: Button
|
|
2821
|
+
type: Button
|
|
2520
2822
|
}, text('×')];
|
|
2521
2823
|
};
|
|
2522
2824
|
|
|
@@ -2588,7 +2890,7 @@ const render2 = (uid, diffResult) => {
|
|
|
2588
2890
|
newState,
|
|
2589
2891
|
oldState
|
|
2590
2892
|
} = get$2(uid);
|
|
2591
|
-
set$
|
|
2893
|
+
set$4(uid, newState, newState);
|
|
2592
2894
|
const commands = applyRender(oldState, newState, diffResult);
|
|
2593
2895
|
return commands;
|
|
2594
2896
|
};
|
|
@@ -2605,7 +2907,7 @@ const renderEventListeners = () => {
|
|
|
2605
2907
|
params: ['handleClickTab', 'event.target.dataset.groupIndex', 'event.target.dataset.index']
|
|
2606
2908
|
}, {
|
|
2607
2909
|
name: HandleTabContextMenu,
|
|
2608
|
-
params: ['handleTabContextMenu', Button, ClientX, ClientY],
|
|
2910
|
+
params: ['handleTabContextMenu', Button$1, ClientX, ClientY],
|
|
2609
2911
|
preventDefault: true
|
|
2610
2912
|
}];
|
|
2611
2913
|
};
|
|
@@ -2649,6 +2951,26 @@ const commandMap = {
|
|
|
2649
2951
|
'MainArea.terminate': terminate
|
|
2650
2952
|
};
|
|
2651
2953
|
|
|
2954
|
+
const send = port => {
|
|
2955
|
+
return sendMessagePortToIconThemeWorker(port, 0);
|
|
2956
|
+
};
|
|
2957
|
+
const createIconThemeWorkerRpc = async () => {
|
|
2958
|
+
try {
|
|
2959
|
+
const rpc = await LazyTransferMessagePortRpcParent.create({
|
|
2960
|
+
commandMap: {},
|
|
2961
|
+
send
|
|
2962
|
+
});
|
|
2963
|
+
return rpc;
|
|
2964
|
+
} catch (error) {
|
|
2965
|
+
throw new VError(error, `Failed to create icon theme worker rpc`);
|
|
2966
|
+
}
|
|
2967
|
+
};
|
|
2968
|
+
|
|
2969
|
+
const initializeIconThemeWorker = async () => {
|
|
2970
|
+
const rpc = await createIconThemeWorkerRpc();
|
|
2971
|
+
set$1(rpc);
|
|
2972
|
+
};
|
|
2973
|
+
|
|
2652
2974
|
const initializeRendererWorker = async () => {
|
|
2653
2975
|
const rpc = await WebWorkerRpcClient.create({
|
|
2654
2976
|
commandMap: commandMap
|
|
@@ -2658,7 +2980,7 @@ const initializeRendererWorker = async () => {
|
|
|
2658
2980
|
|
|
2659
2981
|
const listen = async () => {
|
|
2660
2982
|
registerCommands(commandMap);
|
|
2661
|
-
await initializeRendererWorker();
|
|
2983
|
+
await Promise.all([initializeRendererWorker(), initializeIconThemeWorker()]);
|
|
2662
2984
|
};
|
|
2663
2985
|
|
|
2664
2986
|
const main$2 = async () => {
|