Skip to content

Commit 9b0a25c

Browse files
committed
slide-to-confirm: added slide to confirm functionality
1 parent 1786cac commit 9b0a25c

File tree

3 files changed

+115
-33
lines changed

3 files changed

+115
-33
lines changed

src/App.vue

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -102,27 +102,27 @@
102102
</div>
103103
</div>
104104
<Transition name="fade">
105-
<div
106-
v-if="showBottomBarNow"
107-
class="z-[60] w-full h-12 bg-slate-600/50 absolute flex bottom-0 backdrop-blur-[2px] justify-between"
108-
>
109-
<MiniWidgetContainer
110-
:container="widgetStore.currentView.miniWidgetContainers[0]"
111-
:allow-editing="widgetStore.editingMode"
112-
align="start"
113-
/>
114-
<div />
115-
<MiniWidgetContainer
116-
:container="widgetStore.currentView.miniWidgetContainers[1]"
117-
:allow-editing="widgetStore.editingMode"
118-
align="center"
119-
/>
120-
<div />
121-
<MiniWidgetContainer
122-
:container="widgetStore.currentView.miniWidgetContainers[2]"
123-
:allow-editing="widgetStore.editingMode"
124-
align="end"
125-
/>
105+
<div v-if="showBottomBarNow" class="bottom-container">
106+
<SlideToConfirm />
107+
<div class="bottom-bar h-12">
108+
<MiniWidgetContainer
109+
:container="widgetStore.currentView.miniWidgetContainers[0]"
110+
:allow-editing="widgetStore.editingMode"
111+
align="start"
112+
/>
113+
<div />
114+
<MiniWidgetContainer
115+
:container="widgetStore.currentView.miniWidgetContainers[1]"
116+
:allow-editing="widgetStore.editingMode"
117+
align="center"
118+
/>
119+
<div />
120+
<MiniWidgetContainer
121+
:container="widgetStore.currentView.miniWidgetContainers[2]"
122+
:allow-editing="widgetStore.editingMode"
123+
align="end"
124+
/>
125+
</div>
126126
</div>
127127
</Transition>
128128
<router-view />
@@ -158,6 +158,7 @@ import { useMissionStore } from '@/stores/mission'
158158
import Dialog from './components/Dialog.vue'
159159
import EditMenu from './components/EditMenu.vue'
160160
import MiniWidgetContainer from './components/MiniWidgetContainer.vue'
161+
import SlideToConfirm from './components/SlideToConfirm.vue'
161162
import Alerter from './components/widgets/Alerter.vue'
162163
import { datalogger } from './libs/sensors-logging'
163164
import { useWidgetManagerStore } from './stores/widgetManager'
@@ -266,4 +267,20 @@ body.hide-cursor {
266267
opacity: 0;
267268
transform: translate(0, 100px);
268269
}
270+
.bottom-container {
271+
position: absolute;
272+
bottom: 0;
273+
width: 100%;
274+
display: flex;
275+
flex-direction: column;
276+
align-items: center;
277+
z-index: 60; /* Adjust z-index as needed */
278+
}
279+
280+
.bottom-bar {
281+
width: 100%;
282+
background: rgba(108, 117, 125, 0.5);
283+
display: flex;
284+
justify-content: space-between;
285+
}
269286
</style>

src/libs/slide-to-confirm.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { ref, watch } from 'vue' // Adjust this import based on your Vue version
2+
3+
// Reactive variables (if they are not provided from outside)
4+
export const showSlideToConfirm = ref(false)
5+
export const confirmed = ref(false)
6+
7+
/**
8+
* Calls the provided action function if the user confirms through the slide-to-confirm component.
9+
* @param {() => void} actionFunc - A function representing the action to be confirmed.
10+
* @returns {Promise<void>} A Promise that resolves if the action is successfully executed or rejects in case of cancellation or errors.
11+
*/
12+
export function slideToConfirm(actionFunc: () => void): Promise<void> {
13+
console.log('slideToConfirm')
14+
return new Promise((resolve, reject) => {
15+
// Show slide to confirm component
16+
showSlideToConfirm.value = true
17+
18+
// Watch for changes on confirmed and showSlideToConfirm variables
19+
const stopWatching = watch([confirmed, showSlideToConfirm], ([newConfirmed, newShowSlideToConfirm]) => {
20+
if (newConfirmed) {
21+
stopWatching()
22+
confirmed.value = false
23+
try {
24+
actionFunc()
25+
resolve()
26+
} catch (error) {
27+
reject(error)
28+
}
29+
} else if (!newShowSlideToConfirm) {
30+
stopWatching()
31+
reject(new Error('User cancelled the action'))
32+
}
33+
})
34+
})
35+
}

src/stores/mainVehicle.ts

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
registerActionCallback,
1515
} from '@/libs/joystick/protocols/cockpit-actions'
1616
import { MavlinkManualControlManager } from '@/libs/joystick/protocols/mavlink-manual-control'
17+
import { slideToConfirm } from '@/libs/slide-to-confirm'
1718
import type { ArduPilot } from '@/libs/vehicle/ardupilot/ardupilot'
1819
import type { ArduPilotParameterSetData } from '@/libs/vehicle/ardupilot/types'
1920
import * as Protocol from '@/libs/vehicle/protocol/protocol'
@@ -125,29 +126,52 @@ export const useMainVehicleStore = defineStore('main-vehicle', () => {
125126

126127
/**
127128
* Arm the vehicle
129+
* @returns { void } A Promise that resolves when arming is successful or rejects if an error occurs or the action is cancelled.
128130
*/
129-
function arm(): void {
130-
mainVehicle.value?.arm()
131+
function arm(): Promise<void> {
132+
return slideToConfirm(() => {
133+
if (!mainVehicle.value) {
134+
throw new Error('action rejected or failed')
135+
}
136+
mainVehicle.value.arm()
137+
})
131138
}
132139

133140
/**
134141
* Disarm the vehicle
142+
* @returns { void } A Promise that resolves when disarming is successful or rejects if an error occurs or the action is cancelled.
135143
*/
136-
function disarm(): void {
137-
mainVehicle.value?.disarm()
144+
function disarm(): Promise<void> {
145+
return slideToConfirm(() => {
146+
if (!mainVehicle.value) {
147+
throw new Error('action rejected or failed')
148+
}
149+
mainVehicle.value.disarm()
150+
})
138151
}
139152
/**
140-
* Takeoff the vehicle
153+
* Initiates the takeoff process, requiring user confirmation.
154+
* @returns { void } A Promise that resolves when the takeoff is successful or rejects if an error occurs or the action is cancelled.
141155
*/
142-
function takeoff(): void {
143-
mainVehicle.value?.takeoff()
156+
function takeoff(): Promise<void> {
157+
return slideToConfirm(() => {
158+
if (!mainVehicle.value) {
159+
throw new Error('action rejected or failed')
160+
}
161+
mainVehicle.value.takeoff()
162+
})
144163
}
145-
146164
/**
147165
* Land the vehicle
166+
* @returns { void } A Promise that resolves when landing is successful or rejects if an error occurs or the action is cancelled.
148167
*/
149-
function land(): void {
150-
mainVehicle.value?.land()
168+
function land(): Promise<void> {
169+
return slideToConfirm(() => {
170+
if (!mainVehicle.value) {
171+
throw new Error('action rejected or failed')
172+
}
173+
mainVehicle.value.land()
174+
})
151175
}
152176

153177
/**
@@ -159,6 +183,7 @@ export const useMainVehicleStore = defineStore('main-vehicle', () => {
159183
* @param { number } latitude Latitude in degrees
160184
* @param { number } longitude Longitude in degrees
161185
* @param { number } alt Altitude in meters
186+
* @returns { void } A Promise that resolves when the vehicle reaches the waypoint or rejects if an error occurs or the action is cancelled.
162187
*/
163188
function goTo(
164189
hold: number,
@@ -168,13 +193,18 @@ export const useMainVehicleStore = defineStore('main-vehicle', () => {
168193
latitude: number,
169194
longitude: number,
170195
alt: number
171-
): void {
196+
): Promise<void> {
172197
const waypoint = new Coordinates()
173198
waypoint.latitude = latitude
174199
waypoint.altitude = alt
175200
waypoint.longitude = longitude
176201

177-
mainVehicle.value?.goTo(hold, acceptanceRadius, passRadius, yaw, waypoint)
202+
return slideToConfirm(() => {
203+
if (!mainVehicle.value) {
204+
throw new Error('action rejected or failed')
205+
}
206+
mainVehicle.value.goTo(hold, acceptanceRadius, passRadius, yaw, waypoint)
207+
})
178208
}
179209

180210
/**

0 commit comments

Comments
 (0)