diff --git a/app/app.js b/app/app.js index eb0a52c..476979d 100644 --- a/app/app.js +++ b/app/app.js @@ -1,14 +1,15 @@ //@license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3 -import Vue from 'nativescript-vue' +import { createApp, registerElement } from 'nativescript-vue' import { FontIcon, fonticon } from '@nativescript-community/fonticon'; -import BottomSheetPlugin from '@nativescript-community/ui-material-bottomsheet/vue'; +import { BottomSheetPlugin } from '@nativescript-community/ui-material-bottomsheet/vue3'; +import { install as installBottomSheet } from "@nativescript-community/ui-material-bottomsheet"; import CanvasSVG from '@nativescript-community/ui-svg/vue'; import ButtonPlugin from '@nativescript-community/ui-material-button/vue'; -import WebViewPlugin from '@nativescript-community/ui-webview/vue'; +import WebView from '@nativescript-community/ui-webview/vue'; import { CheckBox } from '@nstudio/nativescript-checkbox'; -import CollectionView from '@nativescript-community/ui-collectionview/vue'; +import CollectionView from '@nativescript-community/ui-collectionview/vue3'; import RipplePlugin from '@nativescript-community/ui-material-ripple/vue'; import { ImageCacheIt } from '@triniwiz/nativescript-image-cache-it'; @@ -20,25 +21,17 @@ import { initializeTracing } from './app-trace'; initializeTracing(); ImageCacheIt.enableAutoMM(); +// Install BottomSheet plugin +installBottomSheet(); + FontIcon.paths = { 'fa': './assets/css/Font-Awesome.css', }; FontIcon.loadCssSync(); -Vue.filter('fonticon', fonticon); - -import { install } from "@nativescript-community/ui-material-bottomsheet"; -install(); -Vue.use(BottomSheetPlugin); - -Vue.use(CanvasSVG); -Vue.use(ButtonPlugin); -Vue.use(WebViewPlugin); -Vue.use(CollectionView); -Vue.use(RipplePlugin); -Vue.registerElement('HTMLLabel', () => require('@nativescript-community/ui-label').Label); -Vue.registerElement('ImageCacheIt', () => require('@triniwiz/nativescript-image-cache-it').ImageCacheIt); -Vue.registerElement( +registerElement('HTMLLabel', () => require('@nativescript-community/ui-label').Label); +registerElement('ImageCacheIt', () => require('@triniwiz/nativescript-image-cache-it').ImageCacheIt); +registerElement( 'CheckBox', () => CheckBox, { @@ -49,9 +42,18 @@ Vue.registerElement( } ); -Vue.config.silent = false; +const app = createApp(Main); + +app.config.globalProperties.$filters = { + fonticon: fonticon +}; + +app.use(store); +app.use(WebView); +app.use(CollectionView); +app.use(CanvasSVG); +app.use(ButtonPlugin); +app.use(RipplePlugin); +app.use(BottomSheetPlugin); -new Vue({ - render: (h) => h('frame', [h(Main)]), - store -}).$start() +app.start(); diff --git a/app/components/AppControlPanel/AppControlListView.vue b/app/components/AppControlPanel/AppControlListView.vue new file mode 100644 index 0000000..977d0fc --- /dev/null +++ b/app/components/AppControlPanel/AppControlListView.vue @@ -0,0 +1,393 @@ +//@license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3 + + + + + + diff --git a/app/components/AppControlPanel/AppControlPanel.vue b/app/components/AppControlPanel/AppControlPanel.vue index 6455a09..254ea65 100644 --- a/app/components/AppControlPanel/AppControlPanel.vue +++ b/app/components/AppControlPanel/AppControlPanel.vue @@ -5,6 +5,7 @@ class="app-control-panel" width="100%" height="100%" + :minHeight="screenHeight / 2" rows="auto, auto, *" columns="*"> @@ -23,7 +24,7 @@ rippleColor="#ffffff" class="fa app-control-button" :class="{ 'app-control-button--active': isPanelOpen && (activeButton === 'quick' || activeButton === null) }" - :text="'fa-bars' | fonticon" + :text="$filters.fonticon('fa-bars')" @tap="handleControlButtonTap('quick', $event)" @pan="handleControlButtonPan('quick', $event)" /> @@ -35,7 +36,7 @@ rippleColor="#ffffff" class="fa app-control-button" :class="{ 'app-control-button--active': isPanelOpen && activeButton === 'search' }" - :text="'fa-search' | fonticon" + :text="$filters.fonticon('fa-search')" @tap="handleControlButtonTap('search', $event)" @pan="handleControlButtonPan('search', $event)" /> @@ -46,7 +47,7 @@ variant="flat" rippleColor="#ffffff" class="fa app-control-button" - :text="locationButtonIcon | fonticon" + :text="$filters.fonticon(locationButtonIcon)" @tap="onLocate" /> @@ -57,7 +58,7 @@ rippleColor="#ffffff" class="fa app-control-button" :class="{ 'app-control-button--active': isPanelOpen && activeButton === 'layers' }" - :text="'fa-layer-group' | fonticon" + :text="$filters.fonticon('fa-layer-group')" @tap="handleControlButtonTap('layers', $event)" @pan="handleControlButtonPan('layers', $event)" /> @@ -65,28 +66,19 @@ - - - - - - - - - + - - diff --git a/app/components/AppControlPanel/components/QuickAccessView.vue b/app/components/AppControlPanel/components/QuickAccessView.vue deleted file mode 100644 index b107a6f..0000000 --- a/app/components/AppControlPanel/components/QuickAccessView.vue +++ /dev/null @@ -1,185 +0,0 @@ -//@license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3 - - - - - - diff --git a/app/components/AppControlPanel/components/SearchView.vue b/app/components/AppControlPanel/components/SearchView.vue deleted file mode 100644 index 2b13952..0000000 --- a/app/components/AppControlPanel/components/SearchView.vue +++ /dev/null @@ -1,15 +0,0 @@ -//@license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3 - - - - - - diff --git a/app/components/AppControlPanel/services/controlPanelDataService.js b/app/components/AppControlPanel/services/controlPanelDataService.js new file mode 100644 index 0000000..4099d49 --- /dev/null +++ b/app/components/AppControlPanel/services/controlPanelDataService.js @@ -0,0 +1,145 @@ +//@license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3 + +export class ControlPanelDataService { + static generateListData(activeButton, store) { + switch(activeButton) { + case 'quick': + case null: + return this.getQuickAccessData(store); + case 'layers': + return this.getLayersData(store); + case 'search': + return this.getSearchData(store); + default: + return this.getQuickAccessData(store); + } + } + + static getQuickAccessData(store) { + const data = [ + { + type: 'action-buttons-group', + id: 'action-buttons', + buttons: [ + { id: 'settings', icon: 'fa-tools', text: 'Settings' }, + { id: 'plugins', icon: 'fa-toolbox', text: 'Plugins' }, + { id: 'debug', icon: 'fa-terminal', text: 'Debug' }, + { id: 'reload', icon: 'fa-redo', text: 'Reload IITC' } + ] + } + ]; + + // Add navigation items from store + const filteredPanes = this.getFilteredPanes(store.state.navigation.panes); + filteredPanes.forEach(pane => { + data.push({ + type: 'navigation-item', + id: pane.name, + icon: pane.icon, + text: pane.label + }); + }); + + return data; + } + + static getLayersData(store) { + const data = []; + + // Add select fields group if there are highlighters or base layers + const highlightersList = store.state.map.highlightersList; + const baseLayersList = store.state.map.baseLayersList; + + if ((highlightersList && highlightersList.length > 0) || (baseLayersList && baseLayersList.length > 0)) { + data.push({ + type: 'select-fields-group', + id: 'select-fields', + fields: [ + { + type: 'highlighter', + label: 'Highlighter', + items: highlightersList, + selectedValue: store.state.map.highlighterSelected, + visible: highlightersList && highlightersList.length > 0 + }, + { + type: 'base-layer', + label: 'Base layer', + items: baseLayersList, + selectedIndex: store.state.map.baseLayerSelected, + visible: baseLayersList && baseLayersList.length > 0 + } + ] + }); + } + + // Add portal icons group (first 9 overlay layers) + const overlayLayers = store.state.map.overlayLayers; + if (overlayLayers && overlayLayers.length > 0) { + data.push({ + type: 'portal-icons-group', + id: 'portal-icons', + portals: overlayLayers.slice(0, 9).map((layer, index) => ({ + ...layer, + index + })) + }); + + // Add switch items for remaining layers + const switchItems = this.generateSwitchItems(overlayLayers); + data.push(...switchItems); + } + + return data; + } + + static getSearchData(store) { + // Search view is currently empty + return []; + } + + static generateSwitchItems(overlayLayers) { + const filteredLayers = overlayLayers + .map((layer, index) => ({ ...layer, index })) + .filter(layer => layer.index > 8); + + const items = []; + + // First 4 items as pairs (2 per row) + const pairedItems = filteredLayers.slice(0, 4); + for (let i = 0; i < pairedItems.length; i += 2) { + const pair = pairedItems.slice(i, i + 2); + if (pair.length === 2) { + items.push({ + type: 'switch-pair', + id: `switch-pair-${i/2}`, + items: pair + }); + } else if (pair.length === 1) { + items.push({ + type: 'switch-single', + id: `switch-single-${pair[0].index}`, + item: pair[0] + }); + } + } + + // Remaining items as single switches + const singleItems = filteredLayers.slice(4); + singleItems.forEach(item => { + items.push({ + type: 'switch-single', + id: `switch-single-${item.index}`, + item + }); + }); + + return items; + } + + static getFilteredPanes(panes) { + const START_EXCLUDE = 3; + const END_EXCLUDE = 5; + return panes.filter((_, index) => index < START_EXCLUDE || index >= END_EXCLUDE); + } +} \ No newline at end of file diff --git a/app/components/AppWebView.vue b/app/components/AppWebView.vue index 53fbd41..4464aa8 100644 --- a/app/components/AppWebView.vue +++ b/app/components/AppWebView.vue @@ -173,7 +173,7 @@ export default { }); }, - beforeDestroy() { + beforeUnmount() { this.store_unsubscribe(); } }; diff --git a/app/components/BaseWebView.vue b/app/components/BaseWebView.vue index 8ed4e46..298d59c 100644 --- a/app/components/BaseWebView.vue +++ b/app/components/BaseWebView.vue @@ -1,7 +1,7 @@ //@license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3 diff --git a/app/components/DebugConsole/mixins/touchInteraction.js b/app/components/DebugConsole/mixins/touchInteraction.js index ac91b78..62fa9a9 100644 --- a/app/components/DebugConsole/mixins/touchInteraction.js +++ b/app/components/DebugConsole/mixins/touchInteraction.js @@ -130,7 +130,7 @@ export default { }, // Cleanup when component is destroyed - beforeDestroy() { + beforeUnmount() { this.resetTouchState(); } }; diff --git a/app/components/Main.vue b/app/components/Main.vue index 90882ef..df2d10a 100644 --- a/app/components/Main.vue +++ b/app/components/Main.vue @@ -1,7 +1,8 @@ //@license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3