Skip to content

Commit

Permalink
App: Implement main menu for new glass UI
Browse files Browse the repository at this point in the history
Signed-off-by: Arturo Manzoli <[email protected]>
  • Loading branch information
ArturoManzoli committed Jun 4, 2024
1 parent 4364eb0 commit 9e275cd
Showing 1 changed file with 172 additions and 80 deletions.
252 changes: 172 additions & 80 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,48 +1,91 @@
<template>
<v-app>
<v-main>
<Dialog v-model:show="showMainMenu">
<div class="flex flex-col items-center justify-around">
<v-btn
v-if="route.name === 'widgets-view'"
prepend-icon="mdi-pencil"
class="w-full m-1 text-white action-button bg-slate-500 hover:bg-slate-400"
@click="widgetStore.editingMode = !widgetStore.editingMode"
>
Edit mode
</v-btn>
<v-btn
v-if="route.name !== 'widgets-view'"
prepend-icon="mdi-send"
class="w-full m-1 text-white action-button bg-slate-500 hover:bg-slate-400"
to="/"
>
Flight
</v-btn>
<v-btn
v-if="route.name !== 'Mission planning'"
prepend-icon="mdi-map-marker-radius"
class="w-full m-1 text-white action-button bg-slate-500 hover:bg-slate-400"
to="/mission-planning"
>
Mission planning
</v-btn>
<v-btn
prepend-icon="mdi-cog"
class="w-full m-1 text-white action-button bg-slate-500 hover:bg-slate-400"
@click="showConfigurationMenu = true"
>
Configuration
</v-btn>
<v-btn
:prepend-icon="fullScreenToggleIcon"
class="w-full m-1 text-white action-button bg-slate-500 hover:bg-slate-400"
@click="toggleFullscreen"
>
{{ isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen' }}
</v-btn>
</div>
</Dialog>
<div v-if="showMainMenu" ref="mainMenu" class="left-menu" :class="{ 'slide-in': isSlidingIn }">
<GlassButton
v-if="route.name === 'widgets-view'"
label="Edit Mode"
:selected="widgetStore.editingMode"
:label-class="menuLabelSize"
variant="round"
:width="buttonSize"
icon="mdi-pencil"
icon-class="2xl:ml-[3px] xl:ml-[2px] lg:ml-[1px] md:ml-[1px] sm:ml-[1px] ml-[1px]"
:disabled="false"
@click="
() => {
widgetStore.editingMode = !widgetStore.editingMode
closeMainMenu()
}
"
/>
<GlassButton
v-if="route.name !== 'widgets-view'"
label="Flight"
:label-class="menuLabelSize"
variant="round"
:width="buttonSize"
icon="mdi-send"
:disabled="false"
:selected="$route.name === 'Flight'"
@click="
() => {
$router.push('/')
closeMainMenu()
}
"
/>
<GlassButton
v-if="route.name !== 'Mission planning'"
label="Mission Planning"
:label-class="menuLabelSize"
variant="round"
icon="mdi-map-marker-radius"
icon-class="2xl:ml-[3px] xl:ml-[2px] lg:ml-[2.5px] md:ml-[1px] sm:ml-[1px] ml-[1px]"
:width="buttonSize"
:disabled="false"
:selected="$route.name === 'Mission planning'"
@click="
() => {
$router.push('/mission-planning')
closeMainMenu()
}
"
/>
<GlassButton
label="Configuration"
:label-class="menuLabelSize"
icon="mdi-cog"
icon-class="2xl:mt-[2px] 2xl:ml-[2px] xl:mt-[1.5px] xl:ml-[1px] lg:mt-[2px] lg:ml-[2px] md:mt-[1px] md:ml-[1px] sm:mt-[0.5px] sm:ml-[1px] mt-[1px] ml-[1px]"
variant="round"
:width="buttonSize"
:disabled="false"
:selected="showConfigurationMenu"
@click="
() => {
showConfigurationMenu = true
closeMainMenu()
}
"
/>
<GlassButton
:label="isFullscreen ? 'Exit Fullscreen' : 'Enter Fullscreen'"
:label-class="menuLabelSize"
:icon="fullScreenToggleIcon"
icon-class="2xl:mt-[1px] 2xl:ml-[3px] xl:mt-[1px] xl:ml-[2px] lg:mt-[2px] lg:ml-[3px] md:mt-[1px] md:ml-[1px] sm:mt-[1px] sm:ml-[1px] mt-[1px] ml-[1px]"
variant="round"
:width="buttonSize"
:disabled="false"
:selected="false"
@click="
() => {
toggleFullscreen()
closeMainMenu()
}
"
/>
</div>

<teleport to="body">
<v-dialog v-model="showConfigurationMenu" transition="dialog-bottom-transition" width="100%" height="100%">
<ConfigurationMenu />
Expand Down Expand Up @@ -72,7 +115,7 @@
<div id="mainTopBar" class="bar top-bar">
<button
class="flex items-center justify-center h-full aspect-square top-bar-hamburger"
@click="openMainMenu()"
@click="toggleMainMenu()"
>
<span class="text-3xl transition-all mdi mdi-menu text-slate-300 hover:text-slate-50" />
</button>
Expand Down Expand Up @@ -143,14 +186,7 @@
import { onClickOutside, useDebounceFn, useFullscreen, useTimestamp } from '@vueuse/core'
import { format } from 'date-fns'
import Swal from 'sweetalert2'
import {
// type AsyncComponentLoader,
computed,
onBeforeUnmount,
// defineAsyncComponent,
ref,
watch,
} from 'vue'
import { computed, onBeforeUnmount, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import ConfigurationMenu from '@/components/ConfigurationMenu.vue'
Expand All @@ -163,54 +199,70 @@ import {
import { useMissionStore } from '@/stores/mission'
import AltitudeSlider from './components/AltitudeSlider.vue'
import Dialog from './components/Dialog.vue'
import EditMenu from './components/EditMenu.vue'
import GlassButton from './components/GlassButton.vue'
import MiniWidgetContainer from './components/MiniWidgetContainer.vue'
import SlideToConfirm from './components/SlideToConfirm.vue'
import Alerter from './components/widgets/Alerter.vue'
import { datalogger } from './libs/sensors-logging'
import { useAppInterfaceStore } from './stores/appInterface'
import { useMainVehicleStore } from './stores/mainVehicle'
import { useWidgetManagerStore } from './stores/widgetManager'
const widgetStore = useWidgetManagerStore()
const vehicleStore = useMainVehicleStore()
const responsiveStore = useAppInterfaceStore()
const showConfigurationMenu = ref(false)
// Main menu
const showMainMenu = ref(false)
const isSlidingIn = ref(false)
const isSlidingOut = ref(false)
// When a isVehicleArmed change its value a watcher call Swal.close, this flag is
// used to avoid closing others Swal instances instead of the one intended
let requestDisarmConfirmationPopup = false
const openMainMenu = (): void => {
if (!vehicleStore.isArmed) {
showMainMenu.value = true
return
}
requestDisarmConfirmationPopup = true
Swal.fire({
title: 'Be careful',
text: 'The vehicle is currently armed, it is not recommended to open the main menu.',
icon: 'warning',
showCancelButton: true,
showConfirmButton: true,
cancelButtonText: 'Continue anyway',
confirmButtonText: 'Disarm vehicle',
}).then((result) => {
// Opens the main menu only after disarming by the slider is confirmed
if (result.isConfirmed && vehicleStore.isArmed) {
vehicleStore.disarm().then(() => {
showMainMenu.value = true
})
} else if (result.dismiss === Swal.DismissReason.cancel) {
showMainMenu.value = true
}
requestDisarmConfirmationPopup = false
})
const toggleMainMenu = useDebounceFn(() => {
if (!isSlidingIn.value) {
isSlidingIn.value = true
showMainMenu.value = !showMainMenu.value
setTimeout(
() => {
isSlidingIn.value = false
},
showMainMenu.value ? 1500 : 50
)
}
}, 200)
const closeMainMenu = (): void => {
if (showMainMenu.value) {
isSlidingOut.value = true
setTimeout(() => {
showMainMenu.value = false
isSlidingOut.value = false
}, 300) // Duration of slide-out animation
}
}
const buttonSize = computed(() => {
if (responsiveStore.is2xl) return 60
if (responsiveStore.isXl) return 55
if (responsiveStore.isLg) return 50
if (responsiveStore.isMd) return 45
if (responsiveStore.isSm) return 30
return 25
})
const menuLabelSize = computed(() => {
if (responsiveStore.is2xl) return 'text-[16px]'
if (responsiveStore.isXl) return 'text-[15px]'
if (responsiveStore.isLg) return 'text-[14px]'
if (responsiveStore.isMd) return 'text-[12px]'
if (responsiveStore.isSm) return 'text-[10px]'
return 'text-[10px]'
})
const isVehicleArmed = computed(() => vehicleStore.isArmed)
watch(isVehicleArmed, (isArmed) => {
if (requestDisarmConfirmationPopup && !isArmed) {
Expand Down Expand Up @@ -287,14 +339,50 @@ body {
/* Removes the scrollbar */
overflow: hidden !important;
}
body.hide-cursor {
cursor: none;
}
.left-menu {
position: fixed;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
@apply 2xl:w-[130px] 2xl:h-[600px] xl:w-[121px] xl:h-[559px] lg:w-[102px] lg:h-[472px] md:w-[95px] md:h-[438px] sm:w-[78px] sm:h-[359px];
padding-top: 5px;
border-radius: 0 20px 20px 0;
border: 1px #cbcbcb33 solid;
border-left: none;
top: 50%;
left: 0;
transform: translateY(-50%);
background-color: #4f4f4f33;
backdrop-filter: blur(15px);
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.3);
z-index: 1000;
}
@keyframes slideInLeft {
from {
transform: translateX(-100%) translateY(-50%);
}
to {
transform: translateX(0) translateY(-50%);
}
}
.slide-in {
animation: slideInLeft 300ms ease forwards;
}
.router-view {
width: 100%;
height: 100%;
position: relative;
}
.main-view {
transition: all 0.2s;
width: 100%;
Expand All @@ -303,11 +391,13 @@ body.hide-cursor {
right: 0%;
top: 0%;
}
.main-view.edit-mode {
transform: scale(0.8);
right: -10%;
top: -10%;
}
.swal2-container {
z-index: 10000;
}
Expand All @@ -316,19 +406,21 @@ body.hide-cursor {
.fade-leave-active {
transition: all 0.3s cubic-bezier(0.55, 0, 0.1, 1);
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translate(0, 100px);
}
.bottom-container {
position: absolute;
bottom: v-bind('currentBottomBarHeightPixels');
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
z-index: 60; /* Adjust z-index as needed */
z-index: 60;
}
.bar {
Expand Down

0 comments on commit 9e275cd

Please sign in to comment.