@lvce-editor/main-area-worker 1.11.0 → 1.12.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 +280 -43
- package/package.json +1 -1
|
@@ -1038,6 +1038,7 @@ const Button$1 = 1;
|
|
|
1038
1038
|
const Div = 4;
|
|
1039
1039
|
const Span = 8;
|
|
1040
1040
|
const Text = 12;
|
|
1041
|
+
const Img = 17;
|
|
1041
1042
|
const Pre = 51;
|
|
1042
1043
|
|
|
1043
1044
|
const Button = 'event.button';
|
|
@@ -1210,6 +1211,17 @@ const terminate = () => {
|
|
|
1210
1211
|
globalThis.close();
|
|
1211
1212
|
};
|
|
1212
1213
|
|
|
1214
|
+
const closeAll$1 = state => {
|
|
1215
|
+
return {
|
|
1216
|
+
...state,
|
|
1217
|
+
layout: {
|
|
1218
|
+
...state.layout,
|
|
1219
|
+
activeGroupId: undefined,
|
|
1220
|
+
groups: []
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
};
|
|
1224
|
+
|
|
1213
1225
|
const {
|
|
1214
1226
|
get,
|
|
1215
1227
|
getCommandIds,
|
|
@@ -1356,13 +1368,144 @@ const handleClickCloseTab = (state, rawGroupIndex, rawIndex) => {
|
|
|
1356
1368
|
return closeTab(state, groupId, tabId);
|
|
1357
1369
|
};
|
|
1358
1370
|
|
|
1359
|
-
const
|
|
1371
|
+
const FileSystemReadFile = 'ExtensionHostFileSystem.readFile';
|
|
1372
|
+
|
|
1373
|
+
// Counter for request IDs to handle race conditions
|
|
1374
|
+
let requestIdCounter = 0;
|
|
1375
|
+
const getNextRequestId = () => {
|
|
1376
|
+
return ++requestIdCounter;
|
|
1377
|
+
};
|
|
1378
|
+
const updateTab = (state, tabId, updates) => {
|
|
1379
|
+
const {
|
|
1380
|
+
layout
|
|
1381
|
+
} = state;
|
|
1382
|
+
const {
|
|
1383
|
+
groups
|
|
1384
|
+
} = layout;
|
|
1385
|
+
const updatedGroups = groups.map(group => {
|
|
1386
|
+
const tabIndex = group.tabs.findIndex(t => t.id === tabId);
|
|
1387
|
+
if (tabIndex === -1) {
|
|
1388
|
+
return group;
|
|
1389
|
+
}
|
|
1390
|
+
const updatedTabs = group.tabs.map((tab, index) => {
|
|
1391
|
+
if (index === tabIndex) {
|
|
1392
|
+
return {
|
|
1393
|
+
...tab,
|
|
1394
|
+
...updates
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
return tab;
|
|
1398
|
+
});
|
|
1399
|
+
return {
|
|
1400
|
+
...group,
|
|
1401
|
+
tabs: updatedTabs
|
|
1402
|
+
};
|
|
1403
|
+
});
|
|
1404
|
+
return {
|
|
1405
|
+
...state,
|
|
1406
|
+
layout: {
|
|
1407
|
+
...layout,
|
|
1408
|
+
groups: updatedGroups
|
|
1409
|
+
}
|
|
1410
|
+
};
|
|
1411
|
+
};
|
|
1412
|
+
const findTab = (state, tabId) => {
|
|
1360
1413
|
const {
|
|
1361
1414
|
layout
|
|
1362
1415
|
} = state;
|
|
1363
1416
|
const {
|
|
1364
1417
|
groups
|
|
1365
1418
|
} = layout;
|
|
1419
|
+
for (const group of groups) {
|
|
1420
|
+
const tab = group.tabs.find(t => t.id === tabId);
|
|
1421
|
+
if (tab) {
|
|
1422
|
+
return tab;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
return undefined;
|
|
1426
|
+
};
|
|
1427
|
+
const loadFileContent = async path => {
|
|
1428
|
+
// @ts-ignore
|
|
1429
|
+
const content = await invoke(FileSystemReadFile, path);
|
|
1430
|
+
return content;
|
|
1431
|
+
};
|
|
1432
|
+
const loadTabContentAsync = async (tabId, path, requestId, getLatestState) => {
|
|
1433
|
+
try {
|
|
1434
|
+
const content = await loadFileContent(path);
|
|
1435
|
+
|
|
1436
|
+
// Check for race condition: get the latest state and verify the request ID
|
|
1437
|
+
const latestState = getLatestState();
|
|
1438
|
+
const latestTab = findTab(latestState, tabId);
|
|
1439
|
+
|
|
1440
|
+
// If the tab no longer exists or a newer request was started, discard this result
|
|
1441
|
+
if (!latestTab || latestTab.loadRequestId !== requestId) {
|
|
1442
|
+
return latestState;
|
|
1443
|
+
}
|
|
1444
|
+
return updateTab(latestState, tabId, {
|
|
1445
|
+
content,
|
|
1446
|
+
errorMessage: undefined,
|
|
1447
|
+
loadingState: 'loaded'
|
|
1448
|
+
});
|
|
1449
|
+
} catch (error) {
|
|
1450
|
+
// Check for race condition before updating with error
|
|
1451
|
+
const latestState = getLatestState();
|
|
1452
|
+
const latestTab = findTab(latestState, tabId);
|
|
1453
|
+
if (!latestTab || latestTab.loadRequestId !== requestId) {
|
|
1454
|
+
return latestState;
|
|
1455
|
+
}
|
|
1456
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to load file content';
|
|
1457
|
+
return updateTab(latestState, tabId, {
|
|
1458
|
+
content: '',
|
|
1459
|
+
errorMessage,
|
|
1460
|
+
loadingState: 'error'
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
|
|
1465
|
+
const startContentLoading = (uid, tabId, path, requestId) => {
|
|
1466
|
+
const loadContent = async () => {
|
|
1467
|
+
try {
|
|
1468
|
+
const currentState = get(uid);
|
|
1469
|
+
if (!currentState) {
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
const getLatestState = () => get(uid) ?? currentState;
|
|
1473
|
+
const newState = await loadTabContentAsync(tabId, path, requestId, getLatestState);
|
|
1474
|
+
const oldState = get(uid);
|
|
1475
|
+
if (oldState) {
|
|
1476
|
+
set(uid, oldState, newState);
|
|
1477
|
+
}
|
|
1478
|
+
await invoke('Main.refresh');
|
|
1479
|
+
} catch {
|
|
1480
|
+
// Silently ignore errors - the tab may have been closed or the component unmounted
|
|
1481
|
+
}
|
|
1482
|
+
};
|
|
1483
|
+
void loadContent();
|
|
1484
|
+
};
|
|
1485
|
+
|
|
1486
|
+
const shouldLoadContent = tab => {
|
|
1487
|
+
// Load if:
|
|
1488
|
+
// - Has a path (file-based tab)
|
|
1489
|
+
// - Not already loaded or currently loading
|
|
1490
|
+
if (!tab.path) {
|
|
1491
|
+
return false;
|
|
1492
|
+
}
|
|
1493
|
+
if (tab.loadingState === 'loading') {
|
|
1494
|
+
return false;
|
|
1495
|
+
}
|
|
1496
|
+
if (tab.loadingState === 'loaded' && tab.content) {
|
|
1497
|
+
return false;
|
|
1498
|
+
}
|
|
1499
|
+
return true;
|
|
1500
|
+
};
|
|
1501
|
+
const selectTab = async (state, groupIndex, index) => {
|
|
1502
|
+
const {
|
|
1503
|
+
layout,
|
|
1504
|
+
uid
|
|
1505
|
+
} = state;
|
|
1506
|
+
const {
|
|
1507
|
+
groups
|
|
1508
|
+
} = layout;
|
|
1366
1509
|
|
|
1367
1510
|
// Validate indexes
|
|
1368
1511
|
if (groupIndex < 0 || groupIndex >= groups.length) {
|
|
@@ -1381,13 +1524,40 @@ const selectTab = async (state, groupIndex, index) => {
|
|
|
1381
1524
|
return state;
|
|
1382
1525
|
}
|
|
1383
1526
|
|
|
1527
|
+
// Check if we need to load content for the newly selected tab
|
|
1528
|
+
const needsLoading = shouldLoadContent(tab);
|
|
1529
|
+
const requestId = needsLoading ? getNextRequestId() : 0;
|
|
1530
|
+
|
|
1384
1531
|
// Update the groups array with the new active tab and active group
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1532
|
+
// Also set loading state if needed
|
|
1533
|
+
const updatedGroups = groups.map((g, i) => {
|
|
1534
|
+
if (i !== groupIndex) {
|
|
1535
|
+
return {
|
|
1536
|
+
...g,
|
|
1537
|
+
focused: false
|
|
1538
|
+
};
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
// This is the group being selected
|
|
1542
|
+
const updatedTabs = needsLoading ? g.tabs.map(t => {
|
|
1543
|
+
if (t.id === tabId) {
|
|
1544
|
+
return {
|
|
1545
|
+
...t,
|
|
1546
|
+
errorMessage: undefined,
|
|
1547
|
+
loadingState: 'loading',
|
|
1548
|
+
loadRequestId: requestId
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
return t;
|
|
1552
|
+
}) : g.tabs;
|
|
1553
|
+
return {
|
|
1554
|
+
...g,
|
|
1555
|
+
activeTabId: tabId,
|
|
1556
|
+
focused: true,
|
|
1557
|
+
tabs: updatedTabs
|
|
1558
|
+
};
|
|
1559
|
+
});
|
|
1560
|
+
const newState = {
|
|
1391
1561
|
...state,
|
|
1392
1562
|
layout: {
|
|
1393
1563
|
...layout,
|
|
@@ -1395,6 +1565,12 @@ const selectTab = async (state, groupIndex, index) => {
|
|
|
1395
1565
|
groups: updatedGroups
|
|
1396
1566
|
}
|
|
1397
1567
|
};
|
|
1568
|
+
|
|
1569
|
+
// Start loading content in the background if needed
|
|
1570
|
+
if (needsLoading && tab.path) {
|
|
1571
|
+
startContentLoading(uid, tabId, tab.path, requestId);
|
|
1572
|
+
}
|
|
1573
|
+
return newState;
|
|
1398
1574
|
};
|
|
1399
1575
|
|
|
1400
1576
|
const handleClickTab = async (state, groupIndexRaw, indexRaw) => {
|
|
@@ -1444,41 +1620,47 @@ const initialize = async () => {
|
|
|
1444
1620
|
set$2(rpc);
|
|
1445
1621
|
};
|
|
1446
1622
|
|
|
1623
|
+
let idCounter = 0;
|
|
1624
|
+
const create = () => {
|
|
1625
|
+
idCounter++;
|
|
1626
|
+
return idCounter;
|
|
1627
|
+
};
|
|
1628
|
+
|
|
1447
1629
|
const getTabs = async () => {
|
|
1448
1630
|
const tabs = [{
|
|
1449
1631
|
content: '',
|
|
1450
1632
|
editorType: 'text',
|
|
1451
|
-
id:
|
|
1633
|
+
id: create(),
|
|
1452
1634
|
isDirty: false,
|
|
1453
1635
|
title: 'tab 1'
|
|
1454
1636
|
}, {
|
|
1455
1637
|
content: '',
|
|
1456
1638
|
editorType: 'text',
|
|
1457
|
-
id:
|
|
1639
|
+
id: create(),
|
|
1458
1640
|
isDirty: false,
|
|
1459
1641
|
title: 'tab 2'
|
|
1460
1642
|
}, {
|
|
1461
1643
|
content: '',
|
|
1462
1644
|
editorType: 'text',
|
|
1463
|
-
id:
|
|
1645
|
+
id: create(),
|
|
1464
1646
|
isDirty: false,
|
|
1465
1647
|
title: 'tab 3'
|
|
1466
1648
|
}, {
|
|
1467
1649
|
content: '',
|
|
1468
1650
|
editorType: 'text',
|
|
1469
|
-
id:
|
|
1651
|
+
id: create(),
|
|
1470
1652
|
isDirty: false,
|
|
1471
1653
|
title: 'tab 4'
|
|
1472
1654
|
}, {
|
|
1473
1655
|
content: '',
|
|
1474
1656
|
editorType: 'text',
|
|
1475
|
-
id:
|
|
1657
|
+
id: create(),
|
|
1476
1658
|
isDirty: false,
|
|
1477
1659
|
title: 'tab 5'
|
|
1478
1660
|
}, {
|
|
1479
1661
|
content: '',
|
|
1480
1662
|
editorType: 'text',
|
|
1481
|
-
id:
|
|
1663
|
+
id: create(),
|
|
1482
1664
|
isDirty: false,
|
|
1483
1665
|
title: 'tab 6'
|
|
1484
1666
|
}];
|
|
@@ -1655,14 +1837,8 @@ const focusEditorGroup = (state, groupId) => {
|
|
|
1655
1837
|
};
|
|
1656
1838
|
};
|
|
1657
1839
|
|
|
1658
|
-
let idCounter = 0;
|
|
1659
|
-
const create = () => {
|
|
1660
|
-
idCounter++;
|
|
1661
|
-
return idCounter;
|
|
1662
|
-
};
|
|
1663
|
-
|
|
1664
1840
|
const openTab = (state, groupId, tab) => {
|
|
1665
|
-
const newTab = {
|
|
1841
|
+
const newTab = 'id' in tab && tab.id !== undefined ? tab : {
|
|
1666
1842
|
...tab,
|
|
1667
1843
|
id: create()
|
|
1668
1844
|
};
|
|
@@ -1757,7 +1933,8 @@ const openUri = async (state, options) => {
|
|
|
1757
1933
|
|
|
1758
1934
|
// Find the active group (by activeGroupId or focused flag)
|
|
1759
1935
|
const {
|
|
1760
|
-
layout
|
|
1936
|
+
layout,
|
|
1937
|
+
uid
|
|
1761
1938
|
} = state;
|
|
1762
1939
|
const {
|
|
1763
1940
|
activeGroupId,
|
|
@@ -1765,15 +1942,21 @@ const openUri = async (state, options) => {
|
|
|
1765
1942
|
} = layout;
|
|
1766
1943
|
const activeGroup = activeGroupId === undefined ? groups.find(group => group.focused) : groups.find(group => group.id === activeGroupId);
|
|
1767
1944
|
|
|
1945
|
+
// Generate a request ID for content loading
|
|
1946
|
+
const requestId = getNextRequestId();
|
|
1947
|
+
|
|
1768
1948
|
// If no active group exists, create one
|
|
1769
1949
|
if (!activeGroup) {
|
|
1770
1950
|
const groupId = create();
|
|
1771
1951
|
const title = getLabel(uri);
|
|
1952
|
+
const tabId = create();
|
|
1772
1953
|
const newTab = {
|
|
1773
1954
|
content: '',
|
|
1774
1955
|
editorType: 'text',
|
|
1775
|
-
id:
|
|
1956
|
+
id: tabId,
|
|
1776
1957
|
isDirty: false,
|
|
1958
|
+
loadingState: 'loading',
|
|
1959
|
+
loadRequestId: requestId,
|
|
1777
1960
|
path: uri,
|
|
1778
1961
|
title
|
|
1779
1962
|
};
|
|
@@ -1784,7 +1967,7 @@ const openUri = async (state, options) => {
|
|
|
1784
1967
|
size: 100,
|
|
1785
1968
|
tabs: [newTab]
|
|
1786
1969
|
};
|
|
1787
|
-
|
|
1970
|
+
const newState = {
|
|
1788
1971
|
...state,
|
|
1789
1972
|
layout: {
|
|
1790
1973
|
...layout,
|
|
@@ -1792,18 +1975,36 @@ const openUri = async (state, options) => {
|
|
|
1792
1975
|
groups: [...groups, newGroup]
|
|
1793
1976
|
}
|
|
1794
1977
|
};
|
|
1978
|
+
|
|
1979
|
+
// Start loading content
|
|
1980
|
+
startContentLoading(uid, tabId, uri, requestId);
|
|
1981
|
+
return newState;
|
|
1795
1982
|
}
|
|
1796
1983
|
|
|
1797
1984
|
// Create a new tab with the URI in the active group
|
|
1798
1985
|
const title = getLabel(uri);
|
|
1986
|
+
const tabId = create();
|
|
1799
1987
|
const newTab = {
|
|
1800
1988
|
content: '',
|
|
1801
1989
|
editorType: 'text',
|
|
1990
|
+
id: tabId,
|
|
1802
1991
|
isDirty: false,
|
|
1992
|
+
loadingState: 'loading',
|
|
1993
|
+
loadRequestId: requestId,
|
|
1803
1994
|
path: uri,
|
|
1804
1995
|
title
|
|
1805
1996
|
};
|
|
1806
|
-
|
|
1997
|
+
const newState = openTab(state, activeGroup.id, newTab);
|
|
1998
|
+
|
|
1999
|
+
// Start loading content
|
|
2000
|
+
startContentLoading(uid, tabId, uri, requestId);
|
|
2001
|
+
return newState;
|
|
2002
|
+
};
|
|
2003
|
+
|
|
2004
|
+
const refresh = state => {
|
|
2005
|
+
return {
|
|
2006
|
+
...state
|
|
2007
|
+
};
|
|
1807
2008
|
};
|
|
1808
2009
|
|
|
1809
2010
|
const text = data => {
|
|
@@ -1817,17 +2018,42 @@ const text = data => {
|
|
|
1817
2018
|
const CSS_CLASSES = {
|
|
1818
2019
|
EDITOR_GROUPS_CONTAINER: 'editor-groups-container'};
|
|
1819
2020
|
|
|
2021
|
+
const renderLoading = () => {
|
|
2022
|
+
return [{
|
|
2023
|
+
childCount: 1,
|
|
2024
|
+
className: 'TextEditor TextEditor--loading',
|
|
2025
|
+
type: Div
|
|
2026
|
+
}, {
|
|
2027
|
+
childCount: 1,
|
|
2028
|
+
className: 'EditorContent EditorContent--loading',
|
|
2029
|
+
type: Div
|
|
2030
|
+
}, text('Loading...')];
|
|
2031
|
+
};
|
|
2032
|
+
const renderError = errorMessage => {
|
|
2033
|
+
return [{
|
|
2034
|
+
childCount: 1,
|
|
2035
|
+
className: 'TextEditor TextEditor--error',
|
|
2036
|
+
type: Div
|
|
2037
|
+
}, {
|
|
2038
|
+
childCount: 1,
|
|
2039
|
+
className: 'EditorContent EditorContent--error',
|
|
2040
|
+
type: Div
|
|
2041
|
+
}, text(`Error: ${errorMessage}`)];
|
|
2042
|
+
};
|
|
2043
|
+
const renderContent = content => {
|
|
2044
|
+
return [{
|
|
2045
|
+
childCount: 1,
|
|
2046
|
+
className: 'TextEditor',
|
|
2047
|
+
type: Div
|
|
2048
|
+
}, {
|
|
2049
|
+
childCount: 1,
|
|
2050
|
+
className: 'EditorContent',
|
|
2051
|
+
type: Pre
|
|
2052
|
+
}, text(content)];
|
|
2053
|
+
};
|
|
1820
2054
|
const renderEditor = tab => {
|
|
1821
2055
|
if (!tab) {
|
|
1822
|
-
return
|
|
1823
|
-
childCount: 1,
|
|
1824
|
-
className: 'TextEditor',
|
|
1825
|
-
type: Div
|
|
1826
|
-
}, {
|
|
1827
|
-
childCount: 1,
|
|
1828
|
-
className: 'EditorContent',
|
|
1829
|
-
type: Pre
|
|
1830
|
-
}, text('')];
|
|
2056
|
+
return renderContent('');
|
|
1831
2057
|
}
|
|
1832
2058
|
if (tab.editorType === 'custom') {
|
|
1833
2059
|
return [{
|
|
@@ -1836,15 +2062,19 @@ const renderEditor = tab => {
|
|
|
1836
2062
|
type: Div
|
|
1837
2063
|
}, text(`Custom Editor: ${tab.customEditorId}`)];
|
|
1838
2064
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
2065
|
+
|
|
2066
|
+
// Handle loading state
|
|
2067
|
+
if (tab.loadingState === 'loading') {
|
|
2068
|
+
return renderLoading();
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
// Handle error state
|
|
2072
|
+
if (tab.loadingState === 'error' && tab.errorMessage) {
|
|
2073
|
+
return renderError(tab.errorMessage);
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
// Default: render content
|
|
2077
|
+
return renderContent(tab.content || '');
|
|
1848
2078
|
};
|
|
1849
2079
|
|
|
1850
2080
|
const HandleClick = 11;
|
|
@@ -1854,7 +2084,7 @@ const HandleTabContextMenu = 14;
|
|
|
1854
2084
|
|
|
1855
2085
|
const renderTab = (tab, isActive, tabIndex, groupIndex) => {
|
|
1856
2086
|
return [{
|
|
1857
|
-
childCount:
|
|
2087
|
+
childCount: 3,
|
|
1858
2088
|
className: isActive ? 'MainTab MainTabSelected' : 'MainTab',
|
|
1859
2089
|
'data-groupIndex': groupIndex,
|
|
1860
2090
|
'data-index': tabIndex,
|
|
@@ -1863,6 +2093,11 @@ const renderTab = (tab, isActive, tabIndex, groupIndex) => {
|
|
|
1863
2093
|
role: 'tab',
|
|
1864
2094
|
title: tab.path || tab.title,
|
|
1865
2095
|
type: Div
|
|
2096
|
+
}, {
|
|
2097
|
+
childCount: 0,
|
|
2098
|
+
className: 'TabIcon',
|
|
2099
|
+
src: 'icons/refresh.svg',
|
|
2100
|
+
type: Img
|
|
1866
2101
|
}, {
|
|
1867
2102
|
childCount: 1,
|
|
1868
2103
|
className: 'TabTitle',
|
|
@@ -1984,6 +2219,7 @@ const saveState = state => {
|
|
|
1984
2219
|
};
|
|
1985
2220
|
|
|
1986
2221
|
const commandMap = {
|
|
2222
|
+
'MainArea.closeAll': wrapCommand(closeAll$1),
|
|
1987
2223
|
'MainArea.create': create$1,
|
|
1988
2224
|
'MainArea.diff2': diff2,
|
|
1989
2225
|
'MainArea.getCommandIds': getCommandIds,
|
|
@@ -1996,6 +2232,7 @@ const commandMap = {
|
|
|
1996
2232
|
'MainArea.initialize': initialize,
|
|
1997
2233
|
'MainArea.loadContent': wrapCommand(loadContent),
|
|
1998
2234
|
'MainArea.openUri': wrapCommand(openUri),
|
|
2235
|
+
'MainArea.refresh': wrapCommand(refresh),
|
|
1999
2236
|
'MainArea.render2': render2,
|
|
2000
2237
|
'MainArea.renderEventListeners': renderEventListeners,
|
|
2001
2238
|
'MainArea.resize': wrapCommand(resize),
|