diff --git a/src/App.vue b/src/App.vue index af96575f4..37d407b72 100644 --- a/src/App.vue +++ b/src/App.vue @@ -102,27 +102,27 @@ -
- -
- -
- +
+ +
+ +
+ +
+ +
@@ -158,6 +158,7 @@ import { useMissionStore } from '@/stores/mission' import Dialog from './components/Dialog.vue' import EditMenu from './components/EditMenu.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 { useWidgetManagerStore } from './stores/widgetManager' @@ -266,4 +267,20 @@ body.hide-cursor { opacity: 0; transform: translate(0, 100px); } +.bottom-container { + position: absolute; + bottom: 0; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + z-index: 60; /* Adjust z-index as needed */ +} + +.bottom-bar { + width: 100%; + background: rgba(108, 117, 125, 0.5); + display: flex; + justify-content: space-between; +} diff --git a/src/libs/slide-to-confirm.ts b/src/libs/slide-to-confirm.ts new file mode 100644 index 000000000..0d80648e5 --- /dev/null +++ b/src/libs/slide-to-confirm.ts @@ -0,0 +1,35 @@ +import { ref, watch } from 'vue' // Adjust this import based on your Vue version + +// Reactive variables (if they are not provided from outside) +export const showSlideToConfirm = ref(false) +export const confirmed = ref(false) + +/** + * Calls the provided action function if the user confirms through the slide-to-confirm component. + * @param {() => void} actionFunc - A function representing the action to be confirmed. + * @returns {Promise} A Promise that resolves if the action is successfully executed or rejects in case of cancellation or errors. + */ +export function slideToConfirm(actionFunc: () => void): Promise { + console.log('slideToConfirm') + return new Promise((resolve, reject) => { + // Show slide to confirm component + showSlideToConfirm.value = true + + // Watch for changes on confirmed and showSlideToConfirm variables + const stopWatching = watch([confirmed, showSlideToConfirm], ([newConfirmed, newShowSlideToConfirm]) => { + if (newConfirmed) { + stopWatching() + confirmed.value = false + try { + actionFunc() + resolve() + } catch (error) { + reject(error) + } + } else if (!newShowSlideToConfirm) { + stopWatching() + reject(new Error('User cancelled the action')) + } + }) + }) +} diff --git a/src/stores/mainVehicle.ts b/src/stores/mainVehicle.ts index 7371ca8af..76d9d0031 100644 --- a/src/stores/mainVehicle.ts +++ b/src/stores/mainVehicle.ts @@ -14,6 +14,7 @@ import { registerActionCallback, } from '@/libs/joystick/protocols/cockpit-actions' import { MavlinkManualControlManager } from '@/libs/joystick/protocols/mavlink-manual-control' +import { slideToConfirm } from '@/libs/slide-to-confirm' import type { ArduPilot } from '@/libs/vehicle/ardupilot/ardupilot' import type { ArduPilotParameterSetData } from '@/libs/vehicle/ardupilot/types' import * as Protocol from '@/libs/vehicle/protocol/protocol' @@ -125,29 +126,52 @@ export const useMainVehicleStore = defineStore('main-vehicle', () => { /** * Arm the vehicle + * @returns { void } A Promise that resolves when arming is successful or rejects if an error occurs or the action is cancelled. */ - function arm(): void { - mainVehicle.value?.arm() + function arm(): Promise { + return slideToConfirm(() => { + if (!mainVehicle.value) { + throw new Error('action rejected or failed') + } + mainVehicle.value.arm() + }) } /** * Disarm the vehicle + * @returns { void } A Promise that resolves when disarming is successful or rejects if an error occurs or the action is cancelled. */ - function disarm(): void { - mainVehicle.value?.disarm() + function disarm(): Promise { + return slideToConfirm(() => { + if (!mainVehicle.value) { + throw new Error('action rejected or failed') + } + mainVehicle.value.disarm() + }) } /** - * Takeoff the vehicle + * Initiates the takeoff process, requiring user confirmation. + * @returns { void } A Promise that resolves when the takeoff is successful or rejects if an error occurs or the action is cancelled. */ - function takeoff(): void { - mainVehicle.value?.takeoff() + function takeoff(): Promise { + return slideToConfirm(() => { + if (!mainVehicle.value) { + throw new Error('action rejected or failed') + } + mainVehicle.value.takeoff() + }) } - /** * Land the vehicle + * @returns { void } A Promise that resolves when landing is successful or rejects if an error occurs or the action is cancelled. */ - function land(): void { - mainVehicle.value?.land() + function land(): Promise { + return slideToConfirm(() => { + if (!mainVehicle.value) { + throw new Error('action rejected or failed') + } + mainVehicle.value.land() + }) } /** @@ -159,6 +183,7 @@ export const useMainVehicleStore = defineStore('main-vehicle', () => { * @param { number } latitude Latitude in degrees * @param { number } longitude Longitude in degrees * @param { number } alt Altitude in meters + * @returns { void } A Promise that resolves when the vehicle reaches the waypoint or rejects if an error occurs or the action is cancelled. */ function goTo( hold: number, @@ -168,13 +193,18 @@ export const useMainVehicleStore = defineStore('main-vehicle', () => { latitude: number, longitude: number, alt: number - ): void { + ): Promise { const waypoint = new Coordinates() waypoint.latitude = latitude waypoint.altitude = alt waypoint.longitude = longitude - mainVehicle.value?.goTo(hold, acceptanceRadius, passRadius, yaw, waypoint) + return slideToConfirm(() => { + if (!mainVehicle.value) { + throw new Error('action rejected or failed') + } + mainVehicle.value.goTo(hold, acceptanceRadius, passRadius, yaw, waypoint) + }) } /**