diff --git a/app.json b/app.json index 479dce7..9e0fde5 100644 --- a/app.json +++ b/app.json @@ -1,6 +1,6 @@ { "runtime": { - "arguments": "--v=1 --inspect", + "arguments": "--v=1 --inspect --security-realm=demo", "version": "beta" }, "shortcut": { @@ -39,7 +39,7 @@ "minWidth": 354 }, "defaultViewOptions": { - "experimental": { + "_experimental": { "childWindows": true } }, diff --git a/js/constants.js b/js/constants.js new file mode 100644 index 0000000..e57d10c --- /dev/null +++ b/js/constants.js @@ -0,0 +1,11 @@ + +const CHART_URL = 'https://cdn.openfin.co/embed-web/chart.html'; +const TRADEVIEW_URL = 'https://www.tradingview.com/chart/?symbol=NASDAQ:AAPL'; +const NEWS_URL = 'https://www.google.com/search?q=INDEXDJX:+.DJI'; +const DOCS_URL = `https://cdn.openfin.co/docs/javascript/${fin.desktop.getVersion()}` +const URLS_ARRAY = [CHART_URL, TRADEVIEW_URL, NEWS_URL, DOCS_URL]; + +const LAYOUT_STORE_KEY = 'LayoutForm'; +const SNAPSHOT_STORE_KEY = 'SnapshotForm'; + +export { CHART_URL, TRADEVIEW_URL, NEWS_URL, URLS_ARRAY, LAYOUT_STORE_KEY, SNAPSHOT_STORE_KEY, DOCS_URL, }; \ No newline at end of file diff --git a/js/external-window-snapshot.js b/js/external-window-snapshot.js index c1d82a7..c18f178 100644 --- a/js/external-window-snapshot.js +++ b/js/external-window-snapshot.js @@ -21,7 +21,7 @@ async function getExternalWindowInfo(name, title) { } async function generateExternalWindowSnapshot(externalWins) { - return await Promise.all(externalWins.map(async (i) => await getExternalWindowInfo(i.name, i.title))); + return await Promise.all(externalWins.map(async (i) => await getExternalWindowInfo(i.name, i.title)).filter(e => !!e)); } async function restoreExternalWindowPositionAndState(info) { diff --git a/js/left-menu.js b/js/left-menu.js index 8460fcc..3830356 100644 --- a/js/left-menu.js +++ b/js/left-menu.js @@ -1,10 +1,8 @@ import { html, render } from 'https://unpkg.com/lit-html@1.0.0/lit-html.js'; import { getTemplates, getTemplateByName, onStoreUpdate } from './template-store.js'; import { CONTAINER_ID } from './platform-window.js'; - -const CHART_URL = 'https://cdn.openfin.co/embed-web/chart.html'; -const LAYOUT_STORE_KEY = 'LayoutForm'; -const SNAPSHOT_STORE_KEY = 'SnapshotForm'; +import { CHART_URL, LAYOUT_STORE_KEY, SNAPSHOT_STORE_KEY, TRADEVIEW_URL, DOCS_URL } from './constants.js'; +import { NEWS_URL } from './constants.js'; //Our Left Menu element @@ -21,12 +19,12 @@ class LeftMenu extends HTMLElement { processAffinity: 'ps_1' }, { - url: 'https://www.tradingview.com/chart/?symbol=NASDAQ:AAPL', + url: TRADEVIEW_URL, printName: 'TradeView', processAffinity: 'tv_1' }, { - url: 'https://www.google.com/search?q=INDEXDJX:+.DJI&stick=H4sIAAAAAAAAAONgecRozC3w8sc9YSmtSWtOXmNU4eIKzsgvd80rySypFBLjYoOyeKS4uDj0c_UNkgsry3kWsfJ5-rm4Rrh4RVgp6Ll4eQIAqJT5uUkAAAA&source=lnms&sa=X&ved=0ahUKEwii_NWT9fzoAhU3mHIEHWy3AWIQ_AUIDSgA&biw=1280&bih=1366&dpr=1', + url: NEWS_URL, printName: 'News', processAffinity: 'mw_1' }, @@ -36,7 +34,7 @@ class LeftMenu extends HTMLElement { processAffinity: 'cv_1' }, { - url: `https://cdn.openfin.co/docs/javascript/${fin.desktop.getVersion()}`, + url: DOCS_URL, printName: "Documentation", processAffinity: 'ps_1' } @@ -128,6 +126,7 @@ class LeftMenu extends HTMLElement { addView = async (printName) => { const viewOptions = this.appList.find(i => i.printName === printName); + viewOptions.detachOnClose = true; return fin.Platform.getCurrentSync().createView(viewOptions, fin.me.identity); } @@ -202,7 +201,7 @@ class LeftMenu extends HTMLElement { const contentUrl = res.headers.get('Location'); const { manifestUrl } = await fin.Application.getCurrentSync().getInfo(); - const startUrl = `https://openfin.github.io/start/?manifest=${encodeURIComponent(`${manifestUrl}?$$appManifestUrl=${contentUrl}`)}`; + const startUrl = `https://openfin.github.io/start/?manifest=${encodeURIComponent(`https://openfin.github.io/platform-api-project-seed/public.json?$$appManifestUrl=${contentUrl}`)}`; fin.System.openUrlWithBrowser(startUrl); } diff --git a/js/platform-provider.js b/js/platform-provider.js index 1bff0b2..9078186 100644 --- a/js/platform-provider.js +++ b/js/platform-provider.js @@ -1,4 +1,5 @@ import { generateExternalWindowSnapshot, restoreExternalWindowPositionAndState } from './external-window-snapshot.js'; +import { URLS_ARRAY } from './constants.js'; //We have customized our platform provider to keep track of a specific notepad window. //Look for the "my_platform_notes.txt" file and launch it in notepad or add another external window to this array @@ -13,9 +14,79 @@ const externalWindowsToTrack = [ } ]; +const pooledViews = {}; +const createPooledView = async (url) => { + console.log('about to create'); + const view = await fin.Platform.getCurrentSync().createView({ url, detachOnClose: true }, fin.me.identity); + pooledViews[url] = view.identity.name; +}; + +fin.Platform.getCurrentSync().once('platform-snapshot-applied', () => URLS_ARRAY.forEach(createPooledView)); + +function modifyContentItemName( + contentItem, + shouldReplace, + url +) { + const name = generateViewNameIfNeeded(contentItem.componentState.name, shouldReplace, url); + const newComponentState = { ...contentItem.componentState, name }; + return { ...contentItem, componentState: newComponentState }; +} + +function generateViewNameIfNeeded(name, shouldReplace, url) { + // either the view has no name OR it is being restored and has a generated name + if(shouldReplace && name.startsWith('internal-generated-view-')) { + console.log('replacing name'); + const name = pooledViews[url]; + setTimeout(() => createPooledView(url),1); + delete pooledViews[url]; + return name; + } + return name; +} + +function mapLayoutContentItems( + contentItems, + action +) { + return contentItems.reduce((res, contentItem) => { + let modifiedContentItemContent = contentItem.content; + const modifiedContentItem = contentItem.type === 'component' ? action(contentItem) : contentItem; + if (contentItem.content) { + modifiedContentItemContent = mapLayoutContentItems(contentItem.content, action); + } + return [...res, { ...modifiedContentItem, content: modifiedContentItemContent }]; + }, []); +} + fin.Platform.init({ overrideCallback: async (Provider) => { class Override extends Provider { + async createView(payload) { + const { opts } = payload; + if (!opts.name && pooledViews[opts.url]) { + console.log('replacing name'); + opts.name = pooledViews[opts.url]; + delete pooledViews[opts.url]; + setTimeout(() => createPooledView(opts.url),1); + } + return super.createView(payload); + } + + async createWindow(payload) { + if (payload.layout) { + payload.layout.content = mapLayoutContentItems( + payload.layout.content, + (contentItem) => + modifyContentItemName( + contentItem, + payload.reason !== 'tearout' && pooledViews[contentItem.componentState.url], + contentItem.componentState.url + ) + ); + } + super.createWindow(payload) + } async getSnapshot() { const snapshot = await super.getSnapshot(); @@ -32,7 +103,7 @@ fin.Platform.init({ const originalPromise = super.applySnapshot({ snapshot, options }); //if we have a section with external windows we will use it. - if (snapshot.externalWindows) { + if (snapshot.externalWindows && snapshot.externalWindows.length) { await Promise.all(snapshot.externalWindows.map(async (i) => await restoreExternalWindowPositionAndState(i))); }