-
Notifications
You must be signed in to change notification settings - Fork 50
Initial Implementation of Slide to Confirm #689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ddb98c7
a98e8a7
1786cac
9b0a25c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| <template> | ||
| <div v-if="showSlideToConfirm"> | ||
| <div class="flex items-center space-x-4 mb-3"> | ||
| <slide-unlock | ||
| ref="vueslideunlock" | ||
| :auto-width="false" | ||
| :circle="true" | ||
| :disabled="false" | ||
| :noanimate="false" | ||
| :width="400" | ||
| :height="50" | ||
| text="slide to confirm" | ||
| success-text="action confirmed" | ||
| name="slideunlock" | ||
| class="slide-unlock" | ||
| @completed="onSlideConfirmed()" | ||
| /> | ||
| <button class="w-12 h-12 flex items-center justify-center rounded-full bg-white text-gray" @click="cancelAction"> | ||
| X | ||
| </button> | ||
| </div> | ||
| </div> | ||
| </template> | ||
|
|
||
| <script setup lang="ts"> | ||
| import SlideUnlock from 'vue-slide-unlock' | ||
|
|
||
| import { confirmed, showSlideToConfirm } from '@/libs/slide-to-confirm' | ||
|
|
||
| const onSlideConfirmed = (): void => { | ||
| showSlideToConfirm.value = false | ||
| confirmed.value = true | ||
| console.log('Slide confirmed!') | ||
| } | ||
|
|
||
| const cancelAction = (): void => { | ||
| showSlideToConfirm.value = false | ||
| confirmed.value = false | ||
| console.log('Slide canceled!') | ||
| } | ||
| </script> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<void>} A Promise that resolves if the action is successfully executed or rejects in case of cancellation or errors. | ||
| */ | ||
| export function slideToConfirm(actionFunc: () => void): Promise<void> { | ||
| 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')) | ||
| } | ||
| }) | ||
| }) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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<void> { | ||
| return slideToConfirm(() => { | ||
| if (!mainVehicle.value) { | ||
| throw new Error('action rejected or failed') | ||
| } | ||
| mainVehicle.value.arm() | ||
| }) | ||
|
Comment on lines
-129
to
+137
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although this logic is fine and we can proceed with it, I have a suggestion of a slight different one that seems to be less intrusive in the code: async function arm(): Promise<void> {
if (!mainVehicle.value) throw new Error('No vehicle available to be armed.')
const slideConfirmed = await slideToConfirm('Slide to arm', 10000)
if (slideConfirmed) {
mainVehicle.value.arm()
return
}
console.error('No confirmation for arming action received')
}This way we don't have to pass the whole success code (in this case it's only
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this also makes sense. I will change. Thanks for all the great feedback!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I forgot to do this. let me know if you would like me to make that change. If I do, do you think I should reset that commit make the change and recommit, or would it be better to make a separate commit to make that change?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be cool, but at the same time it would be an improvement, so you can add it to a following commit, so you don't have to recommit everything, or we can settle with how it is right now and allow this part to be improved on a future PR, without hurries. I'm fine with both, so let me know what you prefer.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After giving it another look, I think it would take me a little bit of time to refactor. If you are ok with it I think I would like to leave it how it is for now. 🙂
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No problem! |
||
| } | ||
|
|
||
| /** | ||
| * 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<void> { | ||
| 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<void> { | ||
| 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<void> { | ||
| 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<void> { | ||
| 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) | ||
| }) | ||
| } | ||
|
|
||
| /** | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.