From acc5b1345e6875181d9c86e15473151547602e94 Mon Sep 17 00:00:00 2001 From: Neil Enns Date: Wed, 21 Aug 2024 09:46:53 -0700 Subject: [PATCH] Make long press trigger a reset Fixes #250 --- src/actions/atisLetter.ts | 19 ++++++-- src/actions/stationStatus.ts | 22 +++++++--- src/actions/trackAudioStatus.ts | 17 ++++++-- src/managers/action.ts | 77 +++++++++++++++++++++++++-------- src/utils/constants.ts | 5 +++ 5 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 src/utils/constants.ts diff --git a/src/actions/atisLetter.ts b/src/actions/atisLetter.ts index e621fb3..14be960 100644 --- a/src/actions/atisLetter.ts +++ b/src/actions/atisLetter.ts @@ -1,18 +1,21 @@ import { action, DidReceiveSettingsEvent, - KeyDownEvent, + KeyUpEvent, SingletonAction, WillAppearEvent, WillDisappearEvent, } from "@elgato/streamdeck"; import actionManager from "@managers/action"; +import { LONG_PRESS_THRESHOLD } from "@utils/constants"; @action({ UUID: "com.neil-enns.trackaudio.atisletter" }) /** * Represents the status of a TrackAudio station */ export class AtisLetter extends SingletonAction { + private _keyDownStart = 0; + // When the action is added to a profile it gets saved in the ActionManager // instance for use elsewhere in the code. The default title is also set // to something useful. @@ -35,8 +38,18 @@ export class AtisLetter extends SingletonAction { actionManager.updateAtisLetter(ev.action, ev.payload.settings); } - onKeyDown(ev: KeyDownEvent): Promise | void { - actionManager.atisLetterKeyDown(ev.action); + onKeyDown(): Promise | void { + this._keyDownStart = Date.now(); + } + + onKeyUp(ev: KeyUpEvent): Promise | void { + const pressLength = Date.now() - this._keyDownStart; + + if (pressLength > LONG_PRESS_THRESHOLD) { + actionManager.atisLetterLongPress(ev.action.id); + } else { + actionManager.atisLetterShortPress(ev.action.id); + } } } diff --git a/src/actions/stationStatus.ts b/src/actions/stationStatus.ts index 90603cf..f30205a 100644 --- a/src/actions/stationStatus.ts +++ b/src/actions/stationStatus.ts @@ -2,18 +2,21 @@ import { ListenTo } from "@controllers/stationStatus"; import { action, DidReceiveSettingsEvent, - KeyDownEvent, + KeyUpEvent, SingletonAction, WillAppearEvent, WillDisappearEvent, } from "@elgato/streamdeck"; import actionManager from "@managers/action"; +import { LONG_PRESS_THRESHOLD } from "@utils/constants"; @action({ UUID: "com.neil-enns.trackaudio.stationstatus" }) /** * Represents the status of a TrackAudio station */ export class StationStatus extends SingletonAction { + private _keyDownStart = 0; + // When the action is added to a profile it gets saved in the ActionManager // instance for use elsewhere in the code. The default title is also set // to something useful. @@ -36,11 +39,18 @@ export class StationStatus extends SingletonAction { actionManager.updateStation(ev.action, ev.payload.settings); } - // When the key is pressed send the request to toggle the current action to the ActionManager. - // That will take care of figuing out the frequency and listenTo value and sending - // the appropriate message to TrackAudio via a websocket. - onKeyDown(ev: KeyDownEvent): void | Promise { - actionManager.toggleFrequency(ev.action.id); + onKeyDown(): void | Promise { + this._keyDownStart = Date.now(); + } + + onKeyUp(ev: KeyUpEvent): Promise | void { + const pressLength = Date.now() - this._keyDownStart; + + if (pressLength > LONG_PRESS_THRESHOLD) { + actionManager.stationStatusLongPress(ev.action.id); + } else { + actionManager.stationStatusShortPress(ev.action.id); + } } } diff --git a/src/actions/trackAudioStatus.ts b/src/actions/trackAudioStatus.ts index cf432b2..72ebd0a 100644 --- a/src/actions/trackAudioStatus.ts +++ b/src/actions/trackAudioStatus.ts @@ -1,18 +1,21 @@ import { action, DidReceiveSettingsEvent, - KeyDownEvent, + KeyUpEvent, SingletonAction, WillAppearEvent, WillDisappearEvent, } from "@elgato/streamdeck"; import actionManager from "@managers/action"; +import { LONG_PRESS_THRESHOLD } from "@utils/constants"; @action({ UUID: "com.neil-enns.trackaudio.trackaudiostatus" }) /** * Represents the status of the websocket connection to TrackAudio */ export class TrackAudioStatus extends SingletonAction { + private _keyDownStart = 0; + // When the action is added to a profile it gets saved in the ActionManager // instance for use elsewhere in the code. onWillAppear( @@ -34,8 +37,16 @@ export class TrackAudioStatus extends SingletonAction actionManager.updateTrackAudioStatus(ev.action, ev.payload.settings); } - onKeyDown(ev: KeyDownEvent): Promise | void { - actionManager.trackAudioStatusKeyDown(ev.action); + onKeyDown(): Promise | void { + this._keyDownStart = Date.now(); + } + + onKeyUp(ev: KeyUpEvent): Promise | void { + const pressLength = Date.now() - this._keyDownStart; + + if (pressLength > LONG_PRESS_THRESHOLD) { + actionManager.trackAudioStatusLongPress(ev.action); + } } } diff --git a/src/managers/action.ts b/src/managers/action.ts index 2448d41..e9b83fd 100644 --- a/src/managers/action.ts +++ b/src/managers/action.ts @@ -133,12 +133,37 @@ class ActionManager extends EventEmitter { this.emit("actionAdded", controller); } + /** + * Called when a station status action has a long press. Resets the + * station status and refreshses its state. + * @param actionId The ID of the action that had the long press + */ + public stationStatusLongPress(actionId: string) { + const savedAction = this.getStationStatusControllers().find( + (entry) => entry.action.id === actionId + ); + + if (!savedAction) { + return; + } + + savedAction.reset(); + trackAudioManager.refreshStationState(savedAction.callsign); + + savedAction.action.showOk().catch((error: unknown) => { + handleAsyncException( + "Unable to show OK on station status button:", + error + ); + }); + } + /** * Called when a TrackAudio status action keydown event is triggered. * Forces a refresh of the TrackAudio status. * @param action The action */ - public trackAudioStatusKeyDown(action: Action): void { + public trackAudioStatusLongPress(action: Action) { this.resetAll(); trackAudioManager.refreshVoiceConnectedState(); // This also causes a refresh of the station states @@ -151,30 +176,41 @@ class ActionManager extends EventEmitter { } /** - * Called when an ATIS letter action keydown event is triggered. If the - * action is in the isUpdated state then it clears the state. If the - * station is not in the isUpdated state then forces a VATSIM data refresh. - * @param action The action + * Called when an ATIS letter action has a short press. Clears the state. + * @param actionId The ID of the action that had the short press */ - public atisLetterKeyDown(action: Action): void { + public atisLetterShortPress(actionId: string) { const savedAction = this.getAtisLetterControllers().find( - (entry) => entry.action.id === action.id + (entry) => entry.action.id === actionId ); if (!savedAction) { return; } - if (savedAction.isUpdated) { - savedAction.isUpdated = false; - } else { - savedAction.action.showOk().catch((error: unknown) => { - handleAsyncException("Unable to show OK on ATIS button:", error); - }); - vatsimManager.refresh(); - } + savedAction.isUpdated = false; } + /** + * Called when an ATIS letter action has a long press. Refreshses the ATIS. + * @param actionId The ID of the action that had the long press + */ + public atisLetterLongPress(actionId: string) { + const savedAction = this.getAtisLetterControllers().find( + (entry) => entry.action.id === actionId + ); + + if (!savedAction) { + return; + } + + savedAction.reset(); + vatsimManager.refresh(); + + savedAction.action.showOk().catch((error: unknown) => { + handleAsyncException("Unable to show OK on ATIS button:", error); + }); + } /** * Resets the ATIS letter on all ATIS letter actions to undefined. */ @@ -588,11 +624,14 @@ class ActionManager extends EventEmitter { } /** - * Toggles the tx, rx, xc, or spkr state of a frequency bound to a StreamDeck action. - * @param id The action id to toggle the state of + * Handles a short press of a station status action. Toggles the + * the tx, rx, xc, or spkr state of a frequency bound to a StreamDeck action. + * @param actionId The action id to toggle the state of */ - public toggleFrequency(id: string): void { - const foundAction = this.actions.find((entry) => entry.action.id === id); + public stationStatusShortPress(actionId: string): void { + const foundAction = this.actions.find( + (entry) => entry.action.id === actionId + ); if (!foundAction || !isStationStatusController(foundAction)) { return; diff --git a/src/utils/constants.ts b/src/utils/constants.ts new file mode 100644 index 0000000..99f7d52 --- /dev/null +++ b/src/utils/constants.ts @@ -0,0 +1,5 @@ +/** + * The length of time in ms that has to pass for an action press to + * count as a long press. + */ +export const LONG_PRESS_THRESHOLD = 500;