diff --git a/core/src/components/show-plugin.js b/core/src/components/show-plugin.js index 9b37b2e7..b9e7e177 100644 --- a/core/src/components/show-plugin.js +++ b/core/src/components/show-plugin.js @@ -6,6 +6,10 @@ import { addPluginRoutes } from '../plugins/addPluginRoutes.js' import { repeat } from 'lit/directives/repeat.js'; import ShortUniqueId from 'short-unique-id'; import { setNewTab } from '../redux/app/app-actions.js' +import '@vaadin/icon' +import '@vaadin/icons' + + import '@vaadin/icon' import '@vaadin/icons' @@ -213,10 +217,14 @@ class ShowPlugin extends connect(store)(LitElement) { @@ -224,13 +232,19 @@ class ShowPlugin extends connect(store)(LitElement) { ${repeat(this.tabs, (tab) => tab.id, (tab, index) => html`
- + + this.changePage(val)}> + +
`)} ` @@ -239,6 +253,9 @@ class ShowPlugin extends connect(store)(LitElement) { removeTab(index) { // Remove tab from array this.tabs = this.tabs.filter((tab, tIndex) => tIndex !== index) + if (this.tabs.length !== 0) { + this.currentTab = 0 + } } createEpmlInstance(frame, index) { @@ -294,6 +311,7 @@ class ShowPlugin extends connect(store)(LitElement) { this.requestUpdate() } + if (changedProps.has('computerUrl')) { if (this.computedUrl !== 'about:blank') { this.loading = true @@ -301,6 +319,19 @@ class ShowPlugin extends connect(store)(LitElement) { } } + changePage(page) { + + const copiedTabs = [...this.tabs] + copiedTabs[this.currentTab] = { + ...copiedTabs[this.currentTab], + myPlugObj: page, + url: page.url + } + this.tabs = copiedTabs + + + } + stateChanged(state) { const split = state.app.url.split('/') const newRegisteredUrls = state.app.registeredUrls @@ -357,4 +388,196 @@ class ShowPlugin extends connect(store)(LitElement) { } } -window.customElements.define('show-plugin', ShowPlugin) \ No newline at end of file +window.customElements.define('show-plugin', ShowPlugin) + +class NavBar extends LitElement { + static get properties() { + return { + registeredUrls: { type: Array }, + changePage: { attribute: false }, + } + } + constructor() { + super() + this.registeredUrls = [] + + } + static styles = css` + .parent { + display: flex; + flex-direction: column; + align-items: center; + padding: 20px; + } + .navbar { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #f8f8f8; + padding: 10px 20px; + max-width: 750px; + width: 80%; + } + .navbar input { + font-size: 16px; + padding: 5px; + flex-grow: 1; + margin-right: 10px; + border: 1px solid #ddd; + } + .navbar button { + padding: 5px 10px; + background-color: #4CAF50; + color: white; + border: none; + cursor: pointer; + } + .navbar button:hover { + background-color: #45a049; + } + .app-list { + display: flex; + justify-content: space-around; + padding: 20px 0; + gap: 20px; + flex-wrap: wrap; + } + .app-list .app-icon { + text-align: center; + font-size: 24px; + width: 150px; + height: 150px; + background: white; + border-radius: 5px; + padding: 5px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 10px; + cursor: pointer; + } + .app-list .app-icon span { + display: block; + } + `; + + async extractComponents(url) { + if (!url.startsWith("qortal://")) { + return null; + } + + url = url.replace(/^(qortal\:\/\/)/, ""); + if (url.includes("/")) { + let parts = url.split("/"); + const service = parts[0].toUpperCase(); + parts.shift(); + const name = parts[0]; + parts.shift(); + let identifier; + + if (parts.length > 0) { + identifier = parts[0]; // Do not shift yet + // Check if a resource exists with this service, name and identifier combination + const myNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node]; + const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port; + let responseObj = await parentEpml.request('apiCall', { + url: `${nodeUrl}/arbitrary/resource/status/${service}/${name}/${identifier}?apiKey=${myNode.apiKey}}` + }) + + if (responseObj.totalChunkCount > 0) { + // Identifier exists, so don't include it in the path + parts.shift(); + } + else { + identifier = null; + } + } + + const path = parts.join("/"); + + const components = {}; + components["service"] = service; + components["name"] = name; + components["identifier"] = identifier; + components["path"] = path; + return components; + } + + return null; + } + + async getQuery(value) { + let newQuery = value; + if (newQuery.endsWith('/')) { + newQuery = newQuery.slice(0, -1); + } + const res = await this.extractComponents(newQuery) + if (!res) return + const { service, name, identifier, path } = res + let query = `?service=${service}` + if (name) { + query = query + `&name=${name}` + } + if (identifier) { + query = query + `&identifier=${identifier}` + } + if (path) { + query = query + `&path=${path}` + } + + this.changePage({ + + "url": "qapp", + "domain": "core", + "page": `qdn/browser/index.html${query}`, + "title": "Q-App", + "icon": "vaadin:desktop", + "menus": [], + "parent": false + + }) + } + + async handlePasteLink(e) { + const value = this.shadowRoot.getElementById('linkInput').value + this.getQuery(value) + } + + async _handleKeyDown(e) { + if (e.key === 'Enter') { + const value = this.shadowRoot.getElementById('linkInput').value + this.getQuery(value) + + } + } + + render() { + return html` +
+ +
+
+ + ${repeat(this.registeredUrls, (plugin) => plugin.url, (plugin, index) => html` +
{ + this.changePage(plugin) + }}> + + ${plugin.title} +
+ + `)} + + +
+
+
+ `; + } +} + +customElements.define('nav-bar', NavBar); \ No newline at end of file diff --git a/plugins/plugins/core/qdn/browser/browser.src.js b/plugins/plugins/core/qdn/browser/browser.src.js index ef110ef1..3441ad0a 100644 --- a/plugins/plugins/core/qdn/browser/browser.src.js +++ b/plugins/plugins/core/qdn/browser/browser.src.js @@ -112,6 +112,10 @@ class WebBrowser extends LitElement { font-size: 16px; background-color: var(--white); } + input { + outline: none + } + paper-progress { --paper-progress-active-color: var(--mdc-theme-primary); @@ -236,7 +240,75 @@ class WebBrowser extends LitElement { }) } + async extractComponents(url) { + if (!url.startsWith("qortal://")) { + return null; + } + + url = url.replace(/^(qortal\:\/\/)/, ""); + if (url.includes("/")) { + let parts = url.split("/"); + const service = parts[0].toUpperCase(); + parts.shift(); + const name = parts[0]; + parts.shift(); + let identifier; + + if (parts.length > 0) { + identifier = parts[0]; // Do not shift yet + // Check if a resource exists with this service, name and identifier combination + let responseObj = await parentEpml.request('apiCall', { + url: `/arbitrary/resource/status/${service}/${name}/${identifier}?apiKey=${this.getApiKey()}` + }) + + if (responseObj.totalChunkCount > 0) { + // Identifier exists, so don't include it in the path + parts.shift(); + } + else { + identifier = null; + } + } + + const path = parts.join("/"); + + const components = {}; + components["service"] = service; + components["name"] = name; + components["identifier"] = identifier; + components["path"] = path; + return components; + } + + return null; + } + + async _handleKeyDown(e) { + if (e.key === 'Enter') { + const value = e.target.value + let newQuery = value; + if (newQuery.endsWith('/')) { + newQuery = newQuery.slice(0, -1); + } + const res = await this.extractComponents(newQuery) + if (!res) return + const { service, name, identifier, path } = res + let query = `?service=${service}` + if (name) { + query = query + `&name=${name}` + } + if (identifier) { + query = query + `&identifier=${identifier}` + } + if (path) { + query = query + `&path=${path}` + } + window.location = window.location.origin + window.location.pathname + query + } + } + render() { + return html`
@@ -245,7 +317,7 @@ class WebBrowser extends LitElement { this.goForward()} title="${translate('browserpage.bchange1')}" class="address-bar-button">arrow_forward_ios this.refresh()} title="${translate('browserpage.bchange2')}" class="address-bar-button">refresh this.goBackToList()} title="${translate('browserpage.bchange3')}" class="address-bar-button">home - + ${this.renderFullScreen()} this.delete()} title="${translate('browserpage.bchange4')} ${this.service} ${this.name} ${translate('browserpage.bchange5')}" class="address-bar-button float-right">delete ${this.renderBlockUnblockButton()}