278 lines
7.3 KiB
Vue
278 lines
7.3 KiB
Vue
<template>
|
|
<div id="app-content" class="uk-margin-remove uk-padding-remove uk-height-1-1" uk-grid>
|
|
<!-- Initialisation modals -->
|
|
<calibrationWizard ref="calibrationWizard" @onClose="enterApp()"></calibrationWizard>
|
|
<!-- Vertical tab bar -->
|
|
<div id="switcher-left-container">
|
|
<div
|
|
id="switcher-left"
|
|
class="uk-flex uk-flex-column uk-padding-remove uk-width-auto uk-height-1-1 uk-text-center"
|
|
>
|
|
<!-- For each top tab -->
|
|
<template v-for="(item, index) in topTabs">
|
|
<!-- Render the tab icon -->
|
|
<tabIcon
|
|
:id="item.id + '-tab-icon'"
|
|
:key="item.id + '-tab-icon'"
|
|
:tab-i-d="item.id"
|
|
:require-connection="true"
|
|
:current-tab="currentTab"
|
|
:class="item.class"
|
|
@set-tab="setTab"
|
|
>
|
|
<img
|
|
v-if="item.iconURL"
|
|
style="filter: grayscale(100%); width: 22px; margin-top: 5px; margin-bottom: 8px"
|
|
:src="item.iconURL"
|
|
/>
|
|
<span v-if="!item.iconURL" class="material-symbols-outlined">
|
|
{{ item.icon }}
|
|
</span>
|
|
</tabIcon>
|
|
<!-- Add a divider if item.divide is true -->
|
|
<hr v-if="item.divide" :key="'tab-divider-' + index" />
|
|
</template>
|
|
|
|
<hr id="extension-tab-divider" />
|
|
|
|
<!-- For each bottom tab -->
|
|
<template v-for="(item, index) in bottomTabs">
|
|
<!-- Render the tab icon -->
|
|
<tabIcon
|
|
:id="item.id + '-tab-icon'"
|
|
:key="item.id + '-tab-icon'"
|
|
:tab-i-d="item.id"
|
|
:require-connection="true"
|
|
:current-tab="currentTab"
|
|
:class="item.class"
|
|
@set-tab="setTab"
|
|
>
|
|
<span class="material-symbols-outlined">{{ item.icon }}</span>
|
|
</tabIcon>
|
|
<!-- Add a divider if item.divide is true -->
|
|
<hr v-if="item.divide" :key="'tab-divider-' + index" />
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Corresponding vertical tab content -->
|
|
<div
|
|
id="container-left"
|
|
ref="containerLeft"
|
|
class="uk-padding-remove uk-height-1-1 uk-width-expand"
|
|
>
|
|
<tabContent
|
|
v-for="item in allTabs"
|
|
:id="item.id + '-tab-content'"
|
|
:key="item.id + '-tab-content'"
|
|
:tab-i-d="item.id"
|
|
:require-connection="true"
|
|
:current-tab="currentTab"
|
|
>
|
|
<component :is="item.component" @scrollTop="scrollToTop"></component>
|
|
</tabContent>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
// Import generic components
|
|
import tabIcon from "./genericComponents/tabIcon";
|
|
import tabContent from "./genericComponents/tabContent";
|
|
|
|
// Import new content components
|
|
import controlContent from "./tabContentComponents/controlContent.vue";
|
|
import slideScanContent from "./tabContentComponents/slideScanContent.vue";
|
|
import backgroundDetectContent from "./tabContentComponents/backgroundDetectContent.vue";
|
|
import viewContent from "./tabContentComponents/viewContent.vue";
|
|
import settingsContent from "./tabContentComponents/settingsContent.vue";
|
|
import aboutContent from "./tabContentComponents/aboutContent.vue";
|
|
import loggingContent from "./tabContentComponents/loggingContent.vue";
|
|
import powerContent from "./tabContentComponents/powerContent.vue";
|
|
|
|
// Import modal components for device initialisation
|
|
import calibrationWizard from "./modalComponents/calibrationWizard.vue";
|
|
import TabIcon from "./genericComponents/tabIcon.vue";
|
|
import ScanListContent from "./tabContentComponents/scanListContent.vue";
|
|
|
|
// Export main app
|
|
export default {
|
|
name: "AppContent",
|
|
|
|
components: {
|
|
tabIcon,
|
|
tabContent,
|
|
controlContent,
|
|
slideScanContent,
|
|
viewContent,
|
|
settingsContent,
|
|
calibrationWizard,
|
|
aboutContent,
|
|
loggingContent,
|
|
TabIcon,
|
|
powerContent,
|
|
},
|
|
data: function () {
|
|
return {
|
|
currentTab: "view",
|
|
bottomTabs: [
|
|
{
|
|
id: "settings",
|
|
icon: "settings",
|
|
component: settingsContent,
|
|
class: "uk-margin-auto-top",
|
|
},
|
|
{
|
|
id: "logging",
|
|
icon: "assignment_late",
|
|
component: loggingContent,
|
|
},
|
|
{
|
|
id: "about",
|
|
icon: "info",
|
|
component: aboutContent,
|
|
},
|
|
{
|
|
id: "power",
|
|
icon: "power_settings_new",
|
|
component: powerContent,
|
|
},
|
|
],
|
|
};
|
|
},
|
|
|
|
computed: {
|
|
tabOrder: function () {
|
|
var ind = [];
|
|
for (const tab of this.topTabs) {
|
|
ind.push(tab.id);
|
|
}
|
|
for (const tab of this.bottomTabs) {
|
|
ind.push(tab.id);
|
|
}
|
|
return ind;
|
|
},
|
|
|
|
topTabs: function () {
|
|
let tabs = [
|
|
{
|
|
id: "view",
|
|
icon: "visibility",
|
|
component: viewContent,
|
|
},
|
|
{
|
|
id: "control",
|
|
icon: "gamepad",
|
|
component: controlContent,
|
|
},
|
|
{
|
|
id: "background detect",
|
|
icon: "background_replace",
|
|
component: backgroundDetectContent,
|
|
},
|
|
{
|
|
id: "slide scan",
|
|
icon: "settings_overscan",
|
|
component: slideScanContent,
|
|
},
|
|
{
|
|
id: "scan list",
|
|
icon: "photo_library",
|
|
component: ScanListContent,
|
|
},
|
|
];
|
|
if (!this.$store.state.galleryEnabled) {
|
|
tabs = tabs.filter((tab) => tab.id != "gallery");
|
|
}
|
|
return tabs;
|
|
},
|
|
allTabs() {
|
|
return [...this.topTabs, ...this.bottomTabs];
|
|
},
|
|
currentTabIndex: function () {
|
|
return this.tabOrder.indexOf(this.currentTab);
|
|
},
|
|
},
|
|
|
|
mounted() {
|
|
// A global signal listener to switch tab
|
|
this.$root.$on("globalSwitchTab", (tabID) => {
|
|
this.currentTab = tabID;
|
|
});
|
|
// A global signal listener to increment tab
|
|
this.$root.$on("globalIncrementTab", () => {
|
|
this.incrementTabBy(1);
|
|
});
|
|
// A global signal listener to decrement tab
|
|
this.$root.$on("globalDecrementTab", () => {
|
|
this.incrementTabBy(-1);
|
|
});
|
|
if (this.$store.getters.ready) {
|
|
this.startModals();
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
setTab: function (event, tab) {
|
|
if (!(this.currentTab == tab)) {
|
|
this.currentTab = tab;
|
|
}
|
|
},
|
|
incrementTabBy: function (n) {
|
|
const newIndex =
|
|
(((this.currentTabIndex + n) % this.tabOrder.length) + this.tabOrder.length) %
|
|
this.tabOrder.length;
|
|
const newId = this.tabOrder[newIndex];
|
|
this.currentTab = newId;
|
|
},
|
|
startModals: function () {
|
|
this.$refs.calibrationWizard.show_if_needed();
|
|
},
|
|
enterApp: function () {
|
|
// Stuff to do once connected and all init modals are finished
|
|
},
|
|
scrollToTop() {
|
|
this.$refs.containerLeft.scrollTo({ top: 0 });
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
.window-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
#component-left {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
#container-left {
|
|
overflow: auto;
|
|
background-color: rgba(180, 180, 180, 0.025);
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
#switcher-left {
|
|
width: 85px;
|
|
padding-top: 2px !important;
|
|
}
|
|
|
|
#switcher-left-container {
|
|
margin: 0;
|
|
padding: 0;
|
|
overflow-x: hidden;
|
|
overflow-y: auto;
|
|
height: 100%;
|
|
background-color: rgba(180, 180, 180, 0.1);
|
|
border-width: 0 1px 0 0;
|
|
border-style: solid;
|
|
border-color: rgba(180, 180, 180, 0.25);
|
|
}
|
|
|
|
#switcher-left a {
|
|
padding: 10px 8px;
|
|
}
|
|
</style>
|