From ca80d41c6b75a55c902bd3f31e45dabc6fed58d7 Mon Sep 17 00:00:00 2001 From: Theodore Kruczek Date: Sun, 4 Aug 2024 10:52:01 -0400 Subject: [PATCH] feat: :sparkles: add settings sub-menu to plugins --- public/css/style.css | 21 +++++ src/lib/click-and-drag.ts | 9 +- src/plugins/KeepTrackPlugin.ts | 109 +++++++++++++++++++++-- src/plugins/sensor/look-angles-plugin.ts | 89 +++++++++--------- src/singletons/uiManager.ts | 2 +- src/types/declaration.d.ts | 1 + 6 files changed, 178 insertions(+), 53 deletions(-) diff --git a/public/css/style.css b/public/css/style.css index ebd715345..d6a5c0170 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -755,6 +755,7 @@ ul { left: 0px; transition: all 1s ease-in-out; transform: translateX(-100%); + background: var(--colorTertiaryDarken2); } input[type='checkbox'].css-checkbox { @@ -1552,6 +1553,26 @@ footer { padding: 0px 5px; } +.side-menu-settings { + position: relative; + height: 100%; + border-width: 0px 5px 0px 0px; + border-color: var(--colorTertiaryDarken3); + border-style: solid; + background: var(--colorTertiaryDarken2); + color: white; + width: 100%; + top: 0px; + bottom: 0px; + overflow: auto; + z-index: 10; + padding: 0px 10px; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + gap: 10px; +} + .ui-slider { width: 160px !important; } diff --git a/src/lib/click-and-drag.ts b/src/lib/click-and-drag.ts index 83777cd08..bc2c6e49f 100644 --- a/src/lib/click-and-drag.ts +++ b/src/lib/click-and-drag.ts @@ -15,6 +15,7 @@ export const clickAndDragWidth = (el: HTMLElement | null, options: clickDragOpti width = width < minWidth ? minWidth : width; width = width > maxWidth ? maxWidth : width; el.style.width = `${width}px`; + el.style.display = 'block'; settingsManager.isDragging = false; @@ -22,7 +23,7 @@ export const clickAndDragWidth = (el: HTMLElement | null, options: clickDragOpti // create new element on right edge const edgeEl = createElWidth_(el); - addEventsWidth_(edgeEl, el, width, minWidth, maxWidth); + addEventsWidth_(edgeEl, el, width, minWidth, maxWidth, options.attachedElement); } }; @@ -38,7 +39,7 @@ export const clickAndDragHeight = (el: HTMLElement, maxHeight?: number, callback addEventsHeight_(edgeEl, el, callback, maxHeight); }; -const addEventsWidth_ = (edgeEl: HTMLDivElement, el: HTMLElement, width: number, minWidth: number, maxWidth: number) => { +const addEventsWidth_ = (edgeEl: HTMLDivElement, el: HTMLElement, width: number, minWidth: number, maxWidth: number, attachedElement?: HTMLElement) => { let startX: number; let startWidth: number; @@ -70,6 +71,10 @@ const addEventsWidth_ = (edgeEl: HTMLDivElement, el: HTMLElement, width: number, width = width < minWidth ? minWidth : width; width = width > maxWidth ? maxWidth : width; el.style.width = `${width}px`; + + if (attachedElement) { + attachedElement.style.left = `${el.getBoundingClientRect().right}px`; + } }); } }); diff --git a/src/plugins/KeepTrackPlugin.ts b/src/plugins/KeepTrackPlugin.ts index 12d29ba89..524018029 100644 --- a/src/plugins/KeepTrackPlugin.ts +++ b/src/plugins/KeepTrackPlugin.ts @@ -9,11 +9,13 @@ import { shake } from '../lib/shake'; import { slideInRight, slideOutLeft } from '../lib/slide'; import { errorManagerInstance } from '../singletons/errorManager'; import { SelectSatManager } from './select-sat-manager/select-sat-manager'; +import { SoundNames } from './sounds/SoundNames'; export interface clickDragOptions { isDraggable?: boolean; minWidth?: number; maxWidth?: number; + attachedElement?: HTMLElement; } /** @@ -66,11 +68,26 @@ export class KeepTrackPlugin { */ sideMenuElementName: string; + /** + * The title of the side menu. + * @example 'Countries Menu' + */ + sideMenuTitle: string; + /** * The html to use for the side menu. */ sideMenuElementHtml: string; + /** + * The html to use for the side menu's attached settings menu. + */ + sideMenuSettingsHtml: string; + + /** + * Whether the side menu settings are open. + */ + isSideMenuSettingsOpen: boolean = false; /** * The title of the help dialog. * @example 'Countries Menu' @@ -216,11 +233,65 @@ export class KeepTrackPlugin { } if (this.sideMenuElementName && this.sideMenuElementHtml) { - this.addSideMenu(this.sideMenuElementHtml); + if (this.sideMenuSettingsHtml) { + const settingsBtn = `${this.sideMenuElementName}-settings-btn`; + const sideMenuHtmlWrapped = keepTrackApi.html` +
+
+
+
${this.sideMenuTitle}
+ +
+
  • + ${this.sideMenuElementHtml} +
    +
    `; + + this.addSideMenu(sideMenuHtmlWrapped); + } else { + this.addSideMenu(this.sideMenuElementHtml); + } } else if (this.sideMenuElementName || this.sideMenuElementHtml) { throw new Error(`${this.PLUGIN_NAME} side menu element name and html must both be defined.`); } + if (this.sideMenuSettingsHtml) { + const sideMenuHtmlWrapped = keepTrackApi.html` +
    +
    +
    + ${this.sideMenuSettingsHtml} +
    +
    + `; + + this.addSideMenu(sideMenuHtmlWrapped); + + keepTrackApi.register({ + event: KeepTrackApiEvents.uiManagerInit, + cbName: this.PLUGIN_NAME, + cb: () => { + getEl(`${this.sideMenuElementName}-settings-btn`).addEventListener('click', () => { + keepTrackApi.getSoundManager().play(SoundNames.CLICK); + if (this.isSideMenuSettingsOpen) { + this.closeSettingsMenu(); + getEl(`${this.sideMenuElementName}-settings-btn`).style.color = 'var(--statusDarkStandby)'; + } else { + this.openSettingsMenu(); + getEl(`${this.sideMenuElementName}-settings-btn`).style.color = 'var(--statusDarkNormal)'; + } + }); + }, + }); + } + if (this.submitCallback) { this.registerSubmitButtonClicked(this.submitCallback); } @@ -286,7 +357,11 @@ export class KeepTrackPlugin { } if (this.sideMenuElementName) { - this.registerHideSideMenu(this.bottomIconElementName, this.sideMenuElementName); + this.registerHideSideMenu(this.bottomIconElementName, this.closeSideMenu.bind(this)); + } + + if (this.sideMenuSettingsHtml) { + this.registerHideSideMenu(this.bottomIconElementName, this.closeSettingsMenu.bind(this)); } if (this.rmbCallback) { @@ -562,8 +637,27 @@ export class KeepTrackPlugin { slideInRight(getEl(this.sideMenuElementName), 1000); } + openSettingsMenu() { + const settingsMenuElement = getEl(`${this.sideMenuElementName}-settings`); + const sideMenuElement = getEl(this.sideMenuElementName); + + if (settingsMenuElement) { + this.isSideMenuSettingsOpen = true; + settingsMenuElement.style.left = `${sideMenuElement.getBoundingClientRect().right}px`; + slideInRight(settingsMenuElement, 1000); + } + } + closeSideMenu() { - slideOutLeft(getEl(this.sideMenuElementName), 1000); + const settingsMenuElement = getEl(`${this.sideMenuElementName}`); + + slideOutLeft(settingsMenuElement, 1000); + } + + closeSettingsMenu() { + this.isSideMenuSettingsOpen = false; + getEl(`${this.sideMenuElementName}-settings-btn`).style.color = 'var(--statusDarkStandby)'; + slideOutLeft(getEl(`${this.sideMenuElementName}-settings`), 1500, null, -300); } registerSubmitButtonClicked(callback: () => void = null) { @@ -593,6 +687,9 @@ export class KeepTrackPlugin { event: KeepTrackApiEvents.uiManagerFinal, cbName: this.PLUGIN_NAME, cb: () => { + if (this.sideMenuSettingsHtml) { + opts.attachedElement = getEl(`${this.sideMenuElementName}-settings`); + } clickAndDragWidth(getEl(this.sideMenuElementName), opts); }, }); @@ -622,14 +719,14 @@ export class KeepTrackPlugin { /** * Registers a callback function to hide the side menu and deselect the bottom icon element. * @param bottomIconElementName The name of the bottom icon element to deselect. - * @param sideMenuElementName The name of the side menu element to hide. + * @param slideCb The callback function to run when the side menu is hidden. */ - registerHideSideMenu(bottomIconElementName: string, sideMenuElementName: string): void { + registerHideSideMenu(bottomIconElementName: string, slideCb: () => void): void { keepTrackApi.register({ event: KeepTrackApiEvents.hideSideMenus, cbName: this.PLUGIN_NAME, cb: (): void => { - slideOutLeft(getEl(sideMenuElementName), 1000); + slideCb(); getEl(bottomIconElementName).classList.remove(KeepTrackPlugin.iconSelectedClassString); this.isMenuButtonActive = false; }, diff --git a/src/plugins/sensor/look-angles-plugin.ts b/src/plugins/sensor/look-angles-plugin.ts index e1a51e118..a41ebcbce 100644 --- a/src/plugins/sensor/look-angles-plugin.ts +++ b/src/plugins/sensor/look-angles-plugin.ts @@ -12,27 +12,26 @@ import { KeepTrackPlugin, clickDragOptions } from '../KeepTrackPlugin'; import { SelectSatManager } from '../select-sat-manager/select-sat-manager'; import { SoundNames } from '../sounds/SoundNames'; export class LookAnglesPlugin extends KeepTrackPlugin { - static PLUGIN_NAME = 'Look Angles'; dependencies = [SelectSatManager.PLUGIN_NAME]; private selectSatManager_: SelectSatManager; constructor() { - super(LookAnglesPlugin.PLUGIN_NAME); + super(LookAnglesPlugin.name); this.selectSatManager_ = keepTrackApi.getPlugin(SelectSatManager); } /** * Flag to determine if the look angles should only show rise and set times */ - private isRiseSetLookangles_ = true; + private isRiseSetOnly_ = true; /** * The interval between each line of look angles */ - private lookanglesInterval_ = 30; + private angleCalculationInterval_ = 30; /** - * The length of the look angles + * The length of time to calculate look angles for */ - private lookanglesLength_ = 2; + private lengthOfLookAngles_ = 2; /** * The last look angles array */ @@ -68,38 +67,40 @@ export class LookAnglesPlugin extends KeepTrackPlugin { The search range can be modified by changing the length and interval options.`; sideMenuElementName: string = 'look-angles-menu'; + sideMenuTitle: string = 'Sensor Look Angles'; sideMenuElementHtml: string = keepTrackApi.html` -
    -
    -
    -
    Sensor Look Angles
    -
    -
    -
    Look Angles Settings
    -
    - -
    -
    - - -
    -
    - - -
    -
    -
    -
    -
    -
    - -
    -
    -
    +
    +
    +
    + +
    +
    +
    +
    +
    `; + sideMenuSettingsHtml = keepTrackApi.html` +
    + +
    +
    +
    + + +
    +
    +
    +
    + + +
    `; addHtml(): void { @@ -109,12 +110,12 @@ export class LookAnglesPlugin extends KeepTrackPlugin { cbName: this.PLUGIN_NAME, cb: () => { getEl('look-angles-length').addEventListener('change', () => { - this.lookanglesLength_ = parseFloat((getEl('look-angles-length')).value); + this.lengthOfLookAngles_ = parseFloat((getEl('look-angles-length')).value); this.refreshSideMenuData_(); }); getEl('look-angles-interval').addEventListener('change', () => { - this.lookanglesInterval_ = parseInt((getEl('look-angles-interval')).value); + this.angleCalculationInterval_ = parseInt((getEl('look-angles-interval')).value); this.refreshSideMenuData_(); }); @@ -207,15 +208,15 @@ export class LookAnglesPlugin extends KeepTrackPlugin { * const orbitalPeriod = MINUTES_PER_DAY / ((satrec.no * MINUTES_PER_DAY) / TAU); // Seconds in a day divided by mean motion * Use custom interval unless doing rise/set lookangles - then use 1 second */ - const lookanglesInterval = this.isRiseSetLookangles_ ? 1 : this.lookanglesInterval_; + const lookanglesInterval = this.isRiseSetOnly_ ? 1 : this.angleCalculationInterval_; const looksArray = []; let offset = 0; - for (let i = 0; i < this.lookanglesLength_ * 24 * 60 * 60; i += lookanglesInterval) { + for (let i = 0; i < this.lengthOfLookAngles_ * 24 * 60 * 60; i += lookanglesInterval) { offset = i * 1000; // Offset in seconds (msec * 1000) const now = timeManagerInstance.getOffsetTimeObj(offset); - const looksPass = SensorMath.getTearData(now, sat.satrec, sensors, this.isRiseSetLookangles_); + const looksPass = SensorMath.getTearData(now, sat.satrec, sensors, this.isRiseSetOnly_); if (looksPass.time !== '') { looksArray.push(looksPass); // Update the table with looks for this 5 second chunk and then increase table counter by 1 @@ -302,9 +303,9 @@ export class LookAnglesPlugin extends KeepTrackPlugin { isRiseSetChecked ??= (getEl('settings-riseset')).checked; if (isRiseSetChecked) { - this.isRiseSetLookangles_ = true; + this.isRiseSetOnly_ = true; } else { - this.isRiseSetLookangles_ = false; + this.isRiseSetOnly_ = false; } this.refreshSideMenuData_(); } diff --git a/src/singletons/uiManager.ts b/src/singletons/uiManager.ts index ccb7e8446..a900afb70 100644 --- a/src/singletons/uiManager.ts +++ b/src/singletons/uiManager.ts @@ -87,7 +87,7 @@ export class UiManager { setTimeout(() => { document.querySelectorAll('img').forEach((img: any) => { - if (img.src && !img.src.includes('.png') && !img.src.includes('.jpg')) { + if (img.src && !img.src.includes('.svg') && !img.src.includes('.png') && !img.src.includes('.jpg')) { img.src = img.attributes.delayedsrc?.value; } }); diff --git a/src/types/declaration.d.ts b/src/types/declaration.d.ts index 0eb04369c..197acdc69 100644 --- a/src/types/declaration.d.ts +++ b/src/types/declaration.d.ts @@ -25,6 +25,7 @@ declare global { module '*.css'; module '*.jpg'; module '*.png'; + module '*.svg'; declare module '*.mp3'; declare module '*.wav'; declare module '*.flac';