From 2dcd6421ae1b62922f60daa0b9ba629600ccd599 Mon Sep 17 00:00:00 2001 From: Joao Mario Lago Date: Mon, 18 Mar 2024 11:02:28 -0300 Subject: [PATCH] libs: slide-to-confirm: Add hold to confirm * Add hold to confirm action to map action from controller to percentage of complete confirm action --- src/components/SlideToConfirm.vue | 9 +++++- src/libs/slide-to-confirm.ts | 48 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/components/SlideToConfirm.vue b/src/components/SlideToConfirm.vue index fb4038eaa..dfce6f6c9 100644 --- a/src/components/SlideToConfirm.vue +++ b/src/components/SlideToConfirm.vue @@ -3,6 +3,7 @@
import SlideUnlock from '@j2only/slide-unlock' -import { confirmationSliderText, confirmed, showSlideToConfirm, sliderText } from '@/libs/slide-to-confirm' +import { + confirmationSliderText, + confirmed, + showSlideToConfirm, + sliderPercentage, + sliderText, +} from '@/libs/slide-to-confirm' const onSlideConfirmed = (): void => { confirmed.value = true diff --git a/src/libs/slide-to-confirm.ts b/src/libs/slide-to-confirm.ts index 93b972192..4de427b27 100644 --- a/src/libs/slide-to-confirm.ts +++ b/src/libs/slide-to-confirm.ts @@ -2,8 +2,15 @@ import { ref, watch } from 'vue' import { useMissionStore } from '@/stores/mission' +import { + availableCockpitActions, + registerActionCallback, + unregisterActionCallback, +} from './joystick/protocols/cockpit-actions' + export const showSlideToConfirm = ref(false) export const sliderText = ref('Slide to Confirm') +export const sliderPercentage = ref(0) export const confirmationSliderText = ref('Action Confirm') export const confirmed = ref(false) @@ -38,6 +45,19 @@ export const eventCategoriesDefaultMapping: Record = Object.val {} ) +/** + * The maximum interval in milliseconds between the last call from a joystick action + * to be considered as a repeat action + * @type {number} + */ +const maxRepeatIntervalMs = 50 + +/** + * Time interval in ms needed to keep a repeat action pressed to be considered as a hold action + * @type {number} + */ +const holdActionTimeMs = 1000 + /** * Waits for user confirmation through the slide-to-confirm component. * @param {EventCategory} category - The category of the event that requires confirmation. @@ -55,6 +75,30 @@ export function slideToConfirm(category: EventCategory, text: string, confirmati return resolve(true) } + let holdToConfirmCallbackId: string | undefined + + if (missionStore.holdToConfirmEnabled) { + let lastConfirmCall = 0 + let totalPressedTime = 0 + + const onHoldConfirmCallback = (): void => { + const dt = Date.now() - lastConfirmCall + + // Reset total pressed time if user releases the button + if (dt > maxRepeatIntervalMs) { + totalPressedTime = 0 + sliderPercentage.value = 0 + } else { + totalPressedTime += dt + sliderPercentage.value = Math.min((totalPressedTime / holdActionTimeMs) * 100, 100) + } + + lastConfirmCall = Date.now() + } + + holdToConfirmCallbackId = registerActionCallback(availableCockpitActions.hold_to_confirm, onHoldConfirmCallback) + } + sliderText.value = text confirmationSliderText.value = confirmationText showSlideToConfirm.value = true @@ -68,6 +112,10 @@ export function slideToConfirm(category: EventCategory, text: string, confirmati stopWatching() resolve(false) } + + if (holdToConfirmCallbackId) { + unregisterActionCallback(holdToConfirmCallbackId) + } }) }) }