@eclipse-lyra/core 0.7.5 → 0.7.7
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/api/index.js +28 -29
- package/dist/api/services.d.ts +0 -4
- package/dist/api/services.d.ts.map +1 -1
- package/dist/api/types.d.ts +1 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/components/fastviews.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/{app-switcher.d.ts → layout-switcher.d.ts} +5 -4
- package/dist/components/layout-switcher.d.ts.map +1 -0
- package/dist/{standard-layout-BSGa06lP.js → config-BiRvaEoO.js} +251 -462
- package/dist/config-BiRvaEoO.js.map +1 -0
- package/dist/contributions/default-layout-contributions.d.ts +1 -0
- package/dist/contributions/default-layout-contributions.d.ts.map +1 -0
- package/dist/contributions/index.d.ts.map +1 -1
- package/dist/core/apploader.d.ts +40 -30
- package/dist/core/apploader.d.ts.map +1 -1
- package/dist/core/constants.d.ts +1 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/contributionregistry.d.ts +10 -9
- package/dist/core/contributionregistry.d.ts.map +1 -1
- package/dist/core/editorregistry.d.ts +1 -1
- package/dist/core/editorregistry.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/icon-DN6fp0dg.js.map +1 -1
- package/dist/index.js +28 -29
- package/dist/parts/contextmenu.d.ts +1 -1
- package/dist/parts/index.js +1 -1
- package/dist/parts/resizable-grid.d.ts +1 -1
- package/dist/{resizable-grid-BRH3MyZK.js → resizable-grid-oWYRVx30.js} +322 -101
- package/dist/resizable-grid-oWYRVx30.js.map +1 -0
- package/dist/vite-plugin-resolve-deps.d.ts +18 -0
- package/dist/vite-plugin-resolve-deps.d.ts.map +1 -0
- package/dist/widgets/icon.d.ts +1 -1
- package/package.json +8 -1
- package/src/api/services.ts +0 -4
- package/src/api/types.ts +1 -1
- package/src/commands/global.ts +1 -1
- package/src/commands/version-info.ts +24 -10
- package/src/components/command.ts +2 -2
- package/src/components/index.ts +1 -1
- package/src/components/layout-switcher.ts +83 -0
- package/src/components/part-name.ts +1 -1
- package/src/components/tasks.ts +1 -1
- package/src/contributions/default-layout-contributions.ts +10 -0
- package/src/contributions/default-ui-contributions.ts +3 -3
- package/src/contributions/index.ts +1 -0
- package/src/contributions/marketplace-catalog-contributions.ts +1 -1
- package/src/core/apploader.ts +182 -99
- package/src/core/constants.ts +1 -0
- package/src/core/contributionregistry.ts +8 -10
- package/src/core/editorregistry.ts +4 -4
- package/src/core/index.ts +0 -1
- package/src/parts/contextmenu.ts +2 -2
- package/src/parts/toolbar.ts +3 -3
- package/src/vite-env.d.ts +9 -0
- package/src/vite-plugin-resolve-deps.ts +112 -0
- package/dist/components/app-selector.d.ts +0 -17
- package/dist/components/app-selector.d.ts.map +0 -1
- package/dist/components/app-switcher.d.ts.map +0 -1
- package/dist/core/app-host-config.d.ts +0 -7
- package/dist/core/app-host-config.d.ts.map +0 -1
- package/dist/core/packageinfoservice.d.ts +0 -16
- package/dist/core/packageinfoservice.d.ts.map +0 -1
- package/dist/resizable-grid-BRH3MyZK.js.map +0 -1
- package/dist/standard-layout-BSGa06lP.js.map +0 -1
- package/src/components/app-selector.ts +0 -233
- package/src/components/app-switcher.ts +0 -126
- package/src/core/app-host-config.ts +0 -23
- package/src/core/packageinfoservice.ts +0 -56
|
@@ -15,6 +15,7 @@ const TOOLBAR_BOTTOM = "app-toolbars-bottom";
|
|
|
15
15
|
const TOOLBAR_BOTTOM_CENTER = "app-toolbars-bottom-center";
|
|
16
16
|
const TOOLBAR_BOTTOM_END = "app-toolbars-bottom-end";
|
|
17
17
|
const SYSTEM_VIEWS = "system-views";
|
|
18
|
+
const SYSTEM_LAYOUTS = "system.layouts";
|
|
18
19
|
const EDITOR_AREA_MAIN = "editor-area-main";
|
|
19
20
|
const SIDEBAR_MAIN = "sidebar-main";
|
|
20
21
|
const SIDEBAR_MAIN_BOTTOM = "sidebar-main-bottom";
|
|
@@ -40,6 +41,7 @@ const constants = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
|
|
|
40
41
|
SIDEBAR_AUXILIARY,
|
|
41
42
|
SIDEBAR_MAIN,
|
|
42
43
|
SIDEBAR_MAIN_BOTTOM,
|
|
44
|
+
SYSTEM_LAYOUTS,
|
|
43
45
|
SYSTEM_VIEWS,
|
|
44
46
|
TOOLBAR_BOTTOM,
|
|
45
47
|
TOOLBAR_BOTTOM_CENTER,
|
|
@@ -275,7 +277,7 @@ class TaskService {
|
|
|
275
277
|
}
|
|
276
278
|
const taskService = new TaskService();
|
|
277
279
|
rootContext.put("taskService", taskService);
|
|
278
|
-
const logger$
|
|
280
|
+
const logger$3 = createLogger("EsmShService");
|
|
279
281
|
const _EsmShService = class _EsmShService {
|
|
280
282
|
isEsmShUrl(url) {
|
|
281
283
|
try {
|
|
@@ -492,7 +494,7 @@ const _EsmShService = class _EsmShService {
|
|
|
492
494
|
}
|
|
493
495
|
const parsed = this.parseSource(source);
|
|
494
496
|
if (!parsed) {
|
|
495
|
-
logger$
|
|
497
|
+
logger$3.warn(`Could not parse source identifier: ${source}`);
|
|
496
498
|
return source;
|
|
497
499
|
}
|
|
498
500
|
return this.buildEsmShUrl(parsed, options);
|
|
@@ -1193,7 +1195,7 @@ _LyraDialogContent.styles = [
|
|
|
1193
1195
|
`
|
|
1194
1196
|
];
|
|
1195
1197
|
let LyraDialogContent = _LyraDialogContent;
|
|
1196
|
-
const logger$
|
|
1198
|
+
const logger$2 = createLogger("DialogService");
|
|
1197
1199
|
const DIALOG_CONTRIBUTION_TARGET = "dialogs";
|
|
1198
1200
|
const OK_BUTTON = {
|
|
1199
1201
|
id: "ok",
|
|
@@ -1234,26 +1236,26 @@ class DialogService {
|
|
|
1234
1236
|
this.contributions.clear();
|
|
1235
1237
|
for (const contribution of contributions) {
|
|
1236
1238
|
if (!contribution.id) {
|
|
1237
|
-
logger$
|
|
1239
|
+
logger$2.warn("Dialog contribution missing id, skipping");
|
|
1238
1240
|
continue;
|
|
1239
1241
|
}
|
|
1240
1242
|
if (!contribution.component) {
|
|
1241
|
-
logger$
|
|
1243
|
+
logger$2.warn(`Dialog contribution "${contribution.id}" has no component function, skipping`);
|
|
1242
1244
|
continue;
|
|
1243
1245
|
}
|
|
1244
1246
|
if (!contribution.onButton) {
|
|
1245
|
-
logger$
|
|
1247
|
+
logger$2.warn(`Dialog contribution "${contribution.id}" has no onButton callback, skipping`);
|
|
1246
1248
|
continue;
|
|
1247
1249
|
}
|
|
1248
1250
|
this.contributions.set(contribution.id, contribution);
|
|
1249
|
-
logger$
|
|
1251
|
+
logger$2.debug(`Loaded dialog contribution: ${contribution.id}`);
|
|
1250
1252
|
}
|
|
1251
|
-
logger$
|
|
1253
|
+
logger$2.info(`Loaded ${this.contributions.size} dialog contributions`);
|
|
1252
1254
|
}
|
|
1253
1255
|
async open(dialogId, state2) {
|
|
1254
1256
|
const contribution = this.contributions.get(dialogId);
|
|
1255
1257
|
if (!contribution) {
|
|
1256
|
-
logger$
|
|
1258
|
+
logger$2.error(`Dialog "${dialogId}" not found`);
|
|
1257
1259
|
throw new Error(`Dialog "${dialogId}" not found`);
|
|
1258
1260
|
}
|
|
1259
1261
|
return new Promise((resolve) => {
|
|
@@ -1268,7 +1270,7 @@ class DialogService {
|
|
|
1268
1270
|
await dialogContentElement.dispose();
|
|
1269
1271
|
} catch (error) {
|
|
1270
1272
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1271
|
-
logger$
|
|
1273
|
+
logger$2.error(`Error disposing dialog content for "${dialogId}": ${errorMessage}`);
|
|
1272
1274
|
}
|
|
1273
1275
|
}
|
|
1274
1276
|
try {
|
|
@@ -1276,7 +1278,7 @@ class DialogService {
|
|
|
1276
1278
|
await contribution.onButton("close", result, stateWithClose);
|
|
1277
1279
|
} catch (error) {
|
|
1278
1280
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1279
|
-
logger$
|
|
1281
|
+
logger$2.error(`Error executing close callback for dialog "${dialogId}": ${errorMessage}`);
|
|
1280
1282
|
}
|
|
1281
1283
|
render(html``, container);
|
|
1282
1284
|
resolve();
|
|
@@ -1290,7 +1292,7 @@ class DialogService {
|
|
|
1290
1292
|
}
|
|
1291
1293
|
} catch (error) {
|
|
1292
1294
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1293
|
-
logger$
|
|
1295
|
+
logger$2.error(`Error executing button callback for dialog "${dialogId}": ${errorMessage}`);
|
|
1294
1296
|
cleanup();
|
|
1295
1297
|
}
|
|
1296
1298
|
};
|
|
@@ -1523,6 +1525,152 @@ class LyraPart extends LyraContainer {
|
|
|
1523
1525
|
__decorateClass$9([
|
|
1524
1526
|
property()
|
|
1525
1527
|
], LyraPart.prototype, "dirty");
|
|
1528
|
+
const logger$1 = createLogger("MarketplaceRegistry");
|
|
1529
|
+
const TOPIC_MARKETPLACE_CHANGED = "events/marketplaceregistry/changed";
|
|
1530
|
+
const KEY_CATALOG_URLS = "marketplace.catalogUrls";
|
|
1531
|
+
class MarketplaceRegistry {
|
|
1532
|
+
constructor() {
|
|
1533
|
+
this.catalogUrls = [];
|
|
1534
|
+
this.loadingPromises = /* @__PURE__ */ new Map();
|
|
1535
|
+
this.loadCatalogUrls().then(() => {
|
|
1536
|
+
this.refreshCatalogs().catch((err) => {
|
|
1537
|
+
logger$1.error(`Failed to refresh catalogs on init: ${err.message}`);
|
|
1538
|
+
});
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
async loadCatalogUrls() {
|
|
1542
|
+
try {
|
|
1543
|
+
const urls = await appSettings.get(KEY_CATALOG_URLS);
|
|
1544
|
+
this.catalogUrls = Array.isArray(urls) ? urls : [];
|
|
1545
|
+
logger$1.debug(`Loaded ${this.catalogUrls.length} catalog URLs`);
|
|
1546
|
+
} catch (error) {
|
|
1547
|
+
logger$1.error(`Failed to load catalog URLs: ${error}`);
|
|
1548
|
+
this.catalogUrls = [];
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
async saveCatalogUrls() {
|
|
1552
|
+
await appSettings.set(KEY_CATALOG_URLS, this.catalogUrls);
|
|
1553
|
+
publish(TOPIC_MARKETPLACE_CHANGED, { type: "catalogs", urls: this.catalogUrls });
|
|
1554
|
+
}
|
|
1555
|
+
async addCatalogUrl(url) {
|
|
1556
|
+
if (!this.isValidUrl(url)) {
|
|
1557
|
+
throw new Error(`Invalid catalog URL: ${url}`);
|
|
1558
|
+
}
|
|
1559
|
+
if (this.catalogUrls.includes(url)) {
|
|
1560
|
+
logger$1.debug(`Catalog URL already exists: ${url}`);
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
this.catalogUrls.push(url);
|
|
1564
|
+
await this.saveCatalogUrls();
|
|
1565
|
+
logger$1.info(`Added catalog URL: ${url}`);
|
|
1566
|
+
try {
|
|
1567
|
+
await this.refreshCatalogs();
|
|
1568
|
+
} catch (error) {
|
|
1569
|
+
logger$1.warn(`Failed to refresh catalogs immediately after adding: ${error}`);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
async removeCatalogUrl(url) {
|
|
1573
|
+
const index = this.catalogUrls.indexOf(url);
|
|
1574
|
+
if (index === -1) {
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1577
|
+
this.catalogUrls.splice(index, 1);
|
|
1578
|
+
await this.saveCatalogUrls();
|
|
1579
|
+
logger$1.info(`Removed catalog URL: ${url}`);
|
|
1580
|
+
}
|
|
1581
|
+
getCatalogUrls() {
|
|
1582
|
+
return [...this.catalogUrls];
|
|
1583
|
+
}
|
|
1584
|
+
isValidUrl(url) {
|
|
1585
|
+
try {
|
|
1586
|
+
const parsed = new URL(url);
|
|
1587
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
1588
|
+
} catch {
|
|
1589
|
+
return false;
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
async fetchCatalog(url) {
|
|
1593
|
+
const existingPromise = this.loadingPromises.get(url);
|
|
1594
|
+
if (existingPromise) {
|
|
1595
|
+
return existingPromise;
|
|
1596
|
+
}
|
|
1597
|
+
const fetchPromise = (async () => {
|
|
1598
|
+
try {
|
|
1599
|
+
logger$1.debug(`Fetching catalog from: ${url}`);
|
|
1600
|
+
const response = await fetch(url, {
|
|
1601
|
+
method: "GET",
|
|
1602
|
+
headers: {
|
|
1603
|
+
"Accept": "application/json"
|
|
1604
|
+
}
|
|
1605
|
+
});
|
|
1606
|
+
if (!response.ok) {
|
|
1607
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1608
|
+
}
|
|
1609
|
+
const data = await response.json();
|
|
1610
|
+
if (!data.extensions || !Array.isArray(data.extensions)) {
|
|
1611
|
+
throw new Error("Invalid catalog format: extensions array is required");
|
|
1612
|
+
}
|
|
1613
|
+
const catalog = {
|
|
1614
|
+
name: data.name,
|
|
1615
|
+
description: data.description,
|
|
1616
|
+
extensions: data.extensions || []
|
|
1617
|
+
};
|
|
1618
|
+
const extCount = catalog.extensions?.length || 0;
|
|
1619
|
+
logger$1.debug(`Successfully fetched catalog from ${url}: ${extCount} extensions`);
|
|
1620
|
+
return catalog;
|
|
1621
|
+
} catch (error) {
|
|
1622
|
+
logger$1.error(`Failed to fetch catalog from ${url}: ${error}`);
|
|
1623
|
+
throw error;
|
|
1624
|
+
} finally {
|
|
1625
|
+
this.loadingPromises.delete(url);
|
|
1626
|
+
}
|
|
1627
|
+
})();
|
|
1628
|
+
this.loadingPromises.set(url, fetchPromise);
|
|
1629
|
+
return fetchPromise;
|
|
1630
|
+
}
|
|
1631
|
+
async refreshCatalogs() {
|
|
1632
|
+
logger$1.info(`Refreshing ${this.catalogUrls.length} catalogs...`);
|
|
1633
|
+
const promises = this.catalogUrls.map(
|
|
1634
|
+
(url) => this.fetchCatalog(url).catch((error) => {
|
|
1635
|
+
logger$1.warn(`Failed to refresh catalog ${url}: ${error.message}`);
|
|
1636
|
+
return null;
|
|
1637
|
+
})
|
|
1638
|
+
);
|
|
1639
|
+
const catalogs = await Promise.allSettled(promises);
|
|
1640
|
+
catalogs.forEach((result, index) => {
|
|
1641
|
+
if (result.status === "fulfilled" && result.value) {
|
|
1642
|
+
const catalog = result.value;
|
|
1643
|
+
if (catalog.extensions) {
|
|
1644
|
+
catalog.extensions.forEach((marketplaceExt) => {
|
|
1645
|
+
if (!extensionRegistry.getExtensions().find((e) => e.id === marketplaceExt.id)) {
|
|
1646
|
+
const extension = {
|
|
1647
|
+
...marketplaceExt,
|
|
1648
|
+
external: true
|
|
1649
|
+
};
|
|
1650
|
+
extensionRegistry.registerExtension(extension);
|
|
1651
|
+
logger$1.debug(`Registered marketplace extension: ${marketplaceExt.id}`);
|
|
1652
|
+
}
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
});
|
|
1657
|
+
publish(TOPIC_MARKETPLACE_CHANGED, { type: "refreshed" });
|
|
1658
|
+
logger$1.info("Catalog refresh completed");
|
|
1659
|
+
}
|
|
1660
|
+
getMarketplaceExtension(extensionId) {
|
|
1661
|
+
const extension = extensionRegistry.getExtensions().find((e) => e.id === extensionId);
|
|
1662
|
+
if (extension && extension.external) {
|
|
1663
|
+
return extension;
|
|
1664
|
+
}
|
|
1665
|
+
return void 0;
|
|
1666
|
+
}
|
|
1667
|
+
isMarketplaceExtension(extensionId) {
|
|
1668
|
+
const extension = extensionRegistry.getExtensions().find((e) => e.id === extensionId);
|
|
1669
|
+
return extension !== void 0 && extension.external === true;
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
const marketplaceRegistry = new MarketplaceRegistry();
|
|
1673
|
+
rootContext.put("marketplaceRegistry", marketplaceRegistry);
|
|
1526
1674
|
const logger = createLogger("AppLoader");
|
|
1527
1675
|
function getErrorMessage(error) {
|
|
1528
1676
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -1564,13 +1712,27 @@ const _AppLoaderService = class _AppLoaderService {
|
|
|
1564
1712
|
* @param options - Optional configuration for registration and auto-starting
|
|
1565
1713
|
*/
|
|
1566
1714
|
registerApp(app, options) {
|
|
1567
|
-
if (
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1715
|
+
if (options?.hostConfig === true && typeof __RESOLVED_PACKAGE_INFO__ !== "undefined") {
|
|
1716
|
+
const resolved = __RESOLVED_PACKAGE_INFO__;
|
|
1717
|
+
if (app.name === void 0) app.name = resolved.name;
|
|
1718
|
+
if (app.version === void 0) app.version = resolved.version;
|
|
1719
|
+
if (app.description === void 0) app.description = resolved.description;
|
|
1720
|
+
if (app.dependencies === void 0) app.dependencies = resolved.dependencies;
|
|
1721
|
+
if (app.marketplaceCatalogUrls === void 0) app.marketplaceCatalogUrls = resolved.marketplaceCatalogUrls;
|
|
1722
|
+
}
|
|
1723
|
+
app.name = app.name ?? "app";
|
|
1724
|
+
app.version = app.version ?? "0.0.0";
|
|
1725
|
+
if (this.apps.has(app.name)) {
|
|
1726
|
+
logger.warn(`App '${app.name}' is already registered. Overwriting.`);
|
|
1727
|
+
}
|
|
1728
|
+
if (app.marketplaceCatalogUrls?.length) {
|
|
1729
|
+
app.marketplaceCatalogUrls.forEach((url) => marketplaceRegistry.addCatalogUrl(url).catch(() => {
|
|
1730
|
+
}));
|
|
1731
|
+
}
|
|
1732
|
+
this.apps.set(app.name, app);
|
|
1733
|
+
logger.info(`Registered app: ${app.name} v${app.version}`);
|
|
1734
|
+
if (options?.defaultAppName) {
|
|
1735
|
+
this.defaultAppName = options.defaultAppName;
|
|
1574
1736
|
}
|
|
1575
1737
|
if (options?.container) {
|
|
1576
1738
|
this.container = options.container;
|
|
@@ -1600,10 +1762,10 @@ const _AppLoaderService = class _AppLoaderService {
|
|
|
1600
1762
|
throw new Error(`Module at ${url} does not have a default export`);
|
|
1601
1763
|
}
|
|
1602
1764
|
const app = module.default;
|
|
1603
|
-
if (!app.
|
|
1604
|
-
throw new Error(`Module at ${url} does not export a valid AppDefinition`);
|
|
1765
|
+
if (!app.name || !app.version) {
|
|
1766
|
+
throw new Error(`Module at ${url} does not export a valid AppDefinition (name and version required)`);
|
|
1605
1767
|
}
|
|
1606
|
-
logger.info(`Successfully loaded app definition from URL: ${app.name}
|
|
1768
|
+
logger.info(`Successfully loaded app definition from URL: ${app.name}`);
|
|
1607
1769
|
return app;
|
|
1608
1770
|
} catch (error) {
|
|
1609
1771
|
logger.error(`Failed to load app from URL ${url}: ${getErrorMessage(error)}`);
|
|
@@ -1613,7 +1775,7 @@ const _AppLoaderService = class _AppLoaderService {
|
|
|
1613
1775
|
/**
|
|
1614
1776
|
* Start the application loader.
|
|
1615
1777
|
* Checks URL parameters for app=URL, loads that extension or app if found.
|
|
1616
|
-
* URL parameter has higher precedence than
|
|
1778
|
+
* URL parameter has higher precedence than defaultAppName.
|
|
1617
1779
|
* Then loads the default app or first registered app.
|
|
1618
1780
|
* This method is idempotent - calling it multiple times only starts once.
|
|
1619
1781
|
*/
|
|
@@ -1650,7 +1812,8 @@ const _AppLoaderService = class _AppLoaderService {
|
|
|
1650
1812
|
try {
|
|
1651
1813
|
const app = await this.loadAppFromUrl(appUrl);
|
|
1652
1814
|
this.registerApp(app);
|
|
1653
|
-
|
|
1815
|
+
if (!app.name) throw new Error("App from URL has no name after registration");
|
|
1816
|
+
await this.loadApp(app.name, this.container);
|
|
1654
1817
|
logger.info(`Successfully loaded app from URL: ${appUrl}`);
|
|
1655
1818
|
return;
|
|
1656
1819
|
} catch (appError) {
|
|
@@ -1673,17 +1836,25 @@ const _AppLoaderService = class _AppLoaderService {
|
|
|
1673
1836
|
}
|
|
1674
1837
|
await this.loadApp(appToLoad, this.container);
|
|
1675
1838
|
}
|
|
1839
|
+
/**
|
|
1840
|
+
* Resolve a path/URL segment to an app name (map key). Matches app.path, app.name, or name ending with /segment.
|
|
1841
|
+
*/
|
|
1842
|
+
findAppNameBySegment(segment) {
|
|
1843
|
+
if (this.apps.has(segment)) return segment;
|
|
1844
|
+
for (const app of this.apps.values()) {
|
|
1845
|
+
if (app.path === segment || app.name && app.name.endsWith("/" + segment)) return app.name ?? void 0;
|
|
1846
|
+
}
|
|
1847
|
+
return void 0;
|
|
1848
|
+
}
|
|
1676
1849
|
/**
|
|
1677
1850
|
* Load and initialize an application.
|
|
1678
|
-
*
|
|
1679
|
-
* @param appId - Application identifier (must be already registered)
|
|
1851
|
+
* @param appName - Application name (must be already registered)
|
|
1680
1852
|
* @param container - Optional DOM element to render into (if provided, auto-renders after loading)
|
|
1681
|
-
* @returns Promise that resolves when app is initialized and rendered
|
|
1682
1853
|
*/
|
|
1683
|
-
async loadApp(
|
|
1684
|
-
const app = this.apps.get(
|
|
1854
|
+
async loadApp(appName, container) {
|
|
1855
|
+
const app = this.apps.get(appName);
|
|
1685
1856
|
if (!app) {
|
|
1686
|
-
throw new Error(`App '${
|
|
1857
|
+
throw new Error(`App '${appName}' not found. Make sure it's registered.`);
|
|
1687
1858
|
}
|
|
1688
1859
|
logger.info(`Loading app: ${app.name}...`);
|
|
1689
1860
|
if (this.currentApp) {
|
|
@@ -1731,17 +1902,18 @@ const _AppLoaderService = class _AppLoaderService {
|
|
|
1731
1902
|
}
|
|
1732
1903
|
this.currentApp = app;
|
|
1733
1904
|
logger.info(`App ${app.name} loaded successfully`);
|
|
1905
|
+
this.preferredLayoutId = await this.getPreferredLayoutId();
|
|
1734
1906
|
this.updateDocumentMetadata(app);
|
|
1735
1907
|
if (container) {
|
|
1736
1908
|
this.renderApp(container);
|
|
1737
1909
|
}
|
|
1738
|
-
window.dispatchEvent(new CustomEvent("app-loaded", { detail: {
|
|
1910
|
+
window.dispatchEvent(new CustomEvent("app-loaded", { detail: { appName: app.name } }));
|
|
1739
1911
|
}
|
|
1740
1912
|
/**
|
|
1741
1913
|
* Updates document title and favicon from app metadata
|
|
1742
1914
|
*/
|
|
1743
1915
|
updateDocumentMetadata(app) {
|
|
1744
|
-
document.title = app.name;
|
|
1916
|
+
document.title = app.name ?? "";
|
|
1745
1917
|
if (app.metadata?.favicon) {
|
|
1746
1918
|
const faviconPath = app.metadata.favicon;
|
|
1747
1919
|
let link = document.querySelector("link[rel*='icon']");
|
|
@@ -1756,30 +1928,45 @@ const _AppLoaderService = class _AppLoaderService {
|
|
|
1756
1928
|
}
|
|
1757
1929
|
/**
|
|
1758
1930
|
* Render the current application to the DOM.
|
|
1759
|
-
*
|
|
1931
|
+
* Resolves the layout by layoutId (default 'standard'), renders its component, then calls layout.onShow if defined.
|
|
1932
|
+
*
|
|
1760
1933
|
* @param container - DOM element to render into
|
|
1761
1934
|
*/
|
|
1762
1935
|
renderApp(container) {
|
|
1763
1936
|
if (!this.currentApp) {
|
|
1764
1937
|
throw new Error("No app loaded. Call loadApp() first.");
|
|
1765
1938
|
}
|
|
1766
|
-
const
|
|
1939
|
+
const layoutId = this.preferredLayoutId ?? this.currentApp.layoutId ?? "standard";
|
|
1940
|
+
const layouts = contributionRegistry.getContributions(SYSTEM_LAYOUTS);
|
|
1941
|
+
let layout = layouts.find((c) => c.id === layoutId);
|
|
1942
|
+
if (!layout) {
|
|
1943
|
+
logger.warn(`Layout '${layoutId}' not found, falling back to 'standard'`);
|
|
1944
|
+
layout = layouts.find((c) => c.id === "standard");
|
|
1945
|
+
}
|
|
1946
|
+
if (!layout) {
|
|
1947
|
+
throw new Error(`No layout found for layoutId '${layoutId}' and no 'standard' layout registered.`);
|
|
1948
|
+
}
|
|
1949
|
+
const r = layout.component;
|
|
1950
|
+
container.innerHTML = "";
|
|
1767
1951
|
if (typeof r === "string") {
|
|
1768
|
-
|
|
1769
|
-
container.innerHTML = "";
|
|
1770
|
-
container.appendChild(el);
|
|
1952
|
+
container.appendChild(document.createElement(r));
|
|
1771
1953
|
} else if (r && typeof r === "object" && "tag" in r) {
|
|
1772
1954
|
const el = document.createElement(r.tag);
|
|
1773
1955
|
for (const [key, value] of Object.entries(r.attributes ?? {})) {
|
|
1774
1956
|
el.setAttribute(key, value);
|
|
1775
1957
|
}
|
|
1776
|
-
container.innerHTML = "";
|
|
1777
1958
|
container.appendChild(el);
|
|
1778
1959
|
} else if (typeof r === "function") {
|
|
1779
|
-
|
|
1780
|
-
render(template, container);
|
|
1960
|
+
render(r(), container);
|
|
1781
1961
|
} else {
|
|
1782
|
-
|
|
1962
|
+
throw new Error(`Layout '${layout.id}' has invalid component.`);
|
|
1963
|
+
}
|
|
1964
|
+
if (layout.onShow) {
|
|
1965
|
+
requestAnimationFrame(() => {
|
|
1966
|
+
void Promise.resolve(layout.onShow()).catch(
|
|
1967
|
+
(err) => logger.error(`Layout onShow failed for '${layout.id}': ${getErrorMessage(err)}`)
|
|
1968
|
+
);
|
|
1969
|
+
});
|
|
1783
1970
|
}
|
|
1784
1971
|
logger.info(`Rendered ${this.currentApp.name}`);
|
|
1785
1972
|
}
|
|
@@ -1815,74 +2002,110 @@ const _AppLoaderService = class _AppLoaderService {
|
|
|
1815
2002
|
}
|
|
1816
2003
|
try {
|
|
1817
2004
|
await appSettings.set(_AppLoaderService.PREFERRED_APP_KEY, appId);
|
|
1818
|
-
this.
|
|
2005
|
+
this.defaultAppName = appId;
|
|
1819
2006
|
logger.info(`Set preferred app to: ${appId}`);
|
|
1820
2007
|
} catch (error) {
|
|
1821
|
-
logger.error(`Failed to persist preferred app
|
|
2008
|
+
logger.error(`Failed to persist preferred app: ${getErrorMessage(error)}`);
|
|
2009
|
+
throw error;
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
getRegisteredLayouts() {
|
|
2013
|
+
return contributionRegistry.getContributions(SYSTEM_LAYOUTS);
|
|
2014
|
+
}
|
|
2015
|
+
getCurrentLayoutId() {
|
|
2016
|
+
return this.preferredLayoutId ?? this.currentApp?.layoutId ?? "standard";
|
|
2017
|
+
}
|
|
2018
|
+
async getPreferredLayoutId() {
|
|
2019
|
+
try {
|
|
2020
|
+
return await appSettings.get(_AppLoaderService.PREFERRED_LAYOUT_KEY);
|
|
2021
|
+
} catch (error) {
|
|
2022
|
+
logger.debug(`Failed to get preferred layout ID: ${getErrorMessage(error)}`);
|
|
2023
|
+
return void 0;
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
async setPreferredLayoutId(layoutId) {
|
|
2027
|
+
const layouts = this.getRegisteredLayouts();
|
|
2028
|
+
if (!layouts.some((l) => l.id === layoutId)) {
|
|
2029
|
+
throw new Error(`Layout '${layoutId}' not found.`);
|
|
2030
|
+
}
|
|
2031
|
+
try {
|
|
2032
|
+
await appSettings.set(_AppLoaderService.PREFERRED_LAYOUT_KEY, layoutId);
|
|
2033
|
+
this.preferredLayoutId = layoutId;
|
|
2034
|
+
logger.info(`Set preferred layout to: ${layoutId}`);
|
|
2035
|
+
if (this.currentApp && this.container) {
|
|
2036
|
+
this.renderApp(this.container);
|
|
2037
|
+
}
|
|
2038
|
+
window.dispatchEvent(new CustomEvent("layout-changed", { detail: { layoutId } }));
|
|
2039
|
+
} catch (error) {
|
|
2040
|
+
logger.error(`Failed to persist preferred layout: ${getErrorMessage(error)}`);
|
|
1822
2041
|
throw error;
|
|
1823
2042
|
}
|
|
1824
2043
|
}
|
|
1825
2044
|
/**
|
|
1826
2045
|
* Select which app to load based on priority:
|
|
1827
2046
|
* 1. appId URL parameter (?appId=...)
|
|
1828
|
-
* 2. App
|
|
1829
|
-
* 3. App
|
|
2047
|
+
* 2. App from current page URL path (/geospace)
|
|
2048
|
+
* 3. App from app URL parameter (?app=...)
|
|
1830
2049
|
* 4. App registered by extension
|
|
1831
|
-
* 5. Preferred app
|
|
1832
|
-
* 6. Default app
|
|
2050
|
+
* 5. Preferred app from settings
|
|
2051
|
+
* 6. Default app
|
|
1833
2052
|
* 7. First registered app
|
|
1834
2053
|
*/
|
|
1835
2054
|
async selectAppToLoad(options) {
|
|
1836
2055
|
const { appIdFromUrl, appIdFromPath, appIdFromAppUrl, appsBeforeExtension } = options;
|
|
1837
2056
|
if (appIdFromUrl) {
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
2057
|
+
const name = this.findAppNameBySegment(appIdFromUrl) ?? appIdFromUrl;
|
|
2058
|
+
if (this.apps.has(name)) {
|
|
2059
|
+
logger.info(`Loading app specified by URL parameter 'appId': ${name}`);
|
|
2060
|
+
return name;
|
|
1841
2061
|
}
|
|
1842
|
-
logger.warn(`App
|
|
2062
|
+
logger.warn(`App '${appIdFromUrl}' from URL parameter not found`);
|
|
1843
2063
|
}
|
|
1844
2064
|
if (appIdFromPath) {
|
|
1845
|
-
|
|
2065
|
+
const name = this.findAppNameBySegment(appIdFromPath);
|
|
2066
|
+
if (name) {
|
|
1846
2067
|
logger.info(`Loading app from URL path: ${appIdFromPath}`);
|
|
1847
|
-
return
|
|
2068
|
+
return name;
|
|
1848
2069
|
}
|
|
1849
|
-
logger.debug(`App
|
|
2070
|
+
logger.debug(`App for path '${appIdFromPath}' not found, continuing search`);
|
|
1850
2071
|
}
|
|
1851
2072
|
if (appIdFromAppUrl) {
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
2073
|
+
const name = this.findAppNameBySegment(appIdFromAppUrl) ?? appIdFromAppUrl;
|
|
2074
|
+
if (this.apps.has(name)) {
|
|
2075
|
+
logger.info(`Loading app using segment from app URL path: ${name}`);
|
|
2076
|
+
return name;
|
|
1855
2077
|
}
|
|
1856
2078
|
}
|
|
1857
2079
|
if (this.apps.size > appsBeforeExtension) {
|
|
1858
2080
|
const newlyRegisteredApps = Array.from(this.apps.values()).slice(appsBeforeExtension);
|
|
1859
2081
|
if (newlyRegisteredApps.length > 0) {
|
|
1860
2082
|
const app = newlyRegisteredApps[0];
|
|
1861
|
-
logger.info(`Loading app registered by extension: ${app.name}
|
|
1862
|
-
return app.
|
|
2083
|
+
logger.info(`Loading app registered by extension: ${app.name}`);
|
|
2084
|
+
return app.name;
|
|
1863
2085
|
}
|
|
1864
2086
|
}
|
|
1865
|
-
const
|
|
1866
|
-
if (
|
|
1867
|
-
logger.info(`Loading preferred app from settings: ${
|
|
1868
|
-
return
|
|
2087
|
+
const preferred = await this.getPreferredAppId();
|
|
2088
|
+
if (preferred && this.apps.has(preferred)) {
|
|
2089
|
+
logger.info(`Loading preferred app from settings: ${preferred}`);
|
|
2090
|
+
return preferred;
|
|
1869
2091
|
}
|
|
1870
|
-
if (this.
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
logger.warn(`Default app '${this.
|
|
2092
|
+
if (this.defaultAppName && this.apps.has(this.defaultAppName)) {
|
|
2093
|
+
return this.defaultAppName;
|
|
2094
|
+
}
|
|
2095
|
+
if (this.defaultAppName) {
|
|
2096
|
+
logger.warn(`Default app '${this.defaultAppName}' not found`);
|
|
1875
2097
|
}
|
|
1876
2098
|
const registeredApps = this.getRegisteredApps();
|
|
1877
2099
|
if (registeredApps.length > 0) {
|
|
1878
2100
|
const app = registeredApps[0];
|
|
1879
|
-
logger.info(`Loading first registered app: ${app.name}
|
|
1880
|
-
return app.
|
|
2101
|
+
logger.info(`Loading first registered app: ${app.name}`);
|
|
2102
|
+
return app.name;
|
|
1881
2103
|
}
|
|
1882
2104
|
return void 0;
|
|
1883
2105
|
}
|
|
1884
2106
|
};
|
|
1885
|
-
_AppLoaderService.PREFERRED_APP_KEY = "
|
|
2107
|
+
_AppLoaderService.PREFERRED_APP_KEY = "preferredAppName";
|
|
2108
|
+
_AppLoaderService.PREFERRED_LAYOUT_KEY = "preferredLayoutId";
|
|
1886
2109
|
let AppLoaderService = _AppLoaderService;
|
|
1887
2110
|
const appLoaderService = new AppLoaderService();
|
|
1888
2111
|
rootContext.put("appLoaderService", appLoaderService);
|
|
@@ -2501,7 +2724,7 @@ let LyraToolbar = class extends LyraElement {
|
|
|
2501
2724
|
this.contributions = [...wildcard, ...categoryMatches, ...specific];
|
|
2502
2725
|
}
|
|
2503
2726
|
isToolbarItem(contribution) {
|
|
2504
|
-
return "command" in contribution || "
|
|
2727
|
+
return "command" in contribution || "component" in contribution;
|
|
2505
2728
|
}
|
|
2506
2729
|
contributionCreator(contribution) {
|
|
2507
2730
|
if ("command" in contribution) {
|
|
@@ -2517,8 +2740,8 @@ let LyraToolbar = class extends LyraElement {
|
|
|
2517
2740
|
</wa-button>
|
|
2518
2741
|
`;
|
|
2519
2742
|
}
|
|
2520
|
-
if ("
|
|
2521
|
-
const contents = contribution.
|
|
2743
|
+
if ("component" in contribution) {
|
|
2744
|
+
const contents = contribution.component;
|
|
2522
2745
|
if (contents instanceof Function) {
|
|
2523
2746
|
return contents();
|
|
2524
2747
|
}
|
|
@@ -2678,9 +2901,9 @@ let LyraCommand = class extends LyraWidget {
|
|
|
2678
2901
|
</lyra-command>
|
|
2679
2902
|
`;
|
|
2680
2903
|
}
|
|
2681
|
-
if ("
|
|
2904
|
+
if ("component" in contribution) {
|
|
2682
2905
|
const htmlContribution = contribution;
|
|
2683
|
-
const contents = htmlContribution.
|
|
2906
|
+
const contents = htmlContribution.component;
|
|
2684
2907
|
if (contents instanceof Function) {
|
|
2685
2908
|
return contents();
|
|
2686
2909
|
}
|
|
@@ -2975,8 +3198,8 @@ let LyraContextMenu = class extends LyraElement {
|
|
|
2975
3198
|
${commandContribution.label}
|
|
2976
3199
|
</lyra-command>
|
|
2977
3200
|
`;
|
|
2978
|
-
} else if ("
|
|
2979
|
-
const contents = contribution.
|
|
3201
|
+
} else if ("component" in contribution) {
|
|
3202
|
+
const contents = contribution.component;
|
|
2980
3203
|
if (contents instanceof Function) {
|
|
2981
3204
|
return contents();
|
|
2982
3205
|
}
|
|
@@ -3775,7 +3998,6 @@ LyraResizableGrid = __decorateClass([
|
|
|
3775
3998
|
], LyraResizableGrid);
|
|
3776
3999
|
export {
|
|
3777
4000
|
COMMAND_SAVE as C,
|
|
3778
|
-
DIALOG_CONTRIBUTION_TARGET as D,
|
|
3779
4001
|
EDITOR_AREA_MAIN as E,
|
|
3780
4002
|
HIDE_DOT_RESOURCE as H,
|
|
3781
4003
|
LyraContainer as L,
|
|
@@ -3788,26 +4010,25 @@ export {
|
|
|
3788
4010
|
LyraPart as c,
|
|
3789
4011
|
SIDEBAR_MAIN as d,
|
|
3790
4012
|
SIDEBAR_MAIN_BOTTOM as e,
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
constants as z
|
|
4013
|
+
SYSTEM_LAYOUTS as f,
|
|
4014
|
+
SYSTEM_VIEWS as g,
|
|
4015
|
+
TOOLBAR_BOTTOM_CENTER as h,
|
|
4016
|
+
TOOLBAR_BOTTOM_END as i,
|
|
4017
|
+
TOOLBAR_MAIN as j,
|
|
4018
|
+
TOOLBAR_MAIN_CENTER as k,
|
|
4019
|
+
TOOLBAR_MAIN_RIGHT as l,
|
|
4020
|
+
TOPIC_SETTINGS_CHANGED as m,
|
|
4021
|
+
appLoaderService as n,
|
|
4022
|
+
appSettings as o,
|
|
4023
|
+
confirmDialog as p,
|
|
4024
|
+
esmShService as q,
|
|
4025
|
+
extensionRegistry as r,
|
|
4026
|
+
infoDialog as s,
|
|
4027
|
+
navigableInfoDialog as t,
|
|
4028
|
+
persistenceService as u,
|
|
4029
|
+
promptDialog as v,
|
|
4030
|
+
taskService as w,
|
|
4031
|
+
TOPIC_EXTENSIONS_CHANGED as x,
|
|
4032
|
+
constants as y
|
|
3812
4033
|
};
|
|
3813
|
-
//# sourceMappingURL=resizable-grid-
|
|
4034
|
+
//# sourceMappingURL=resizable-grid-oWYRVx30.js.map
|