mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
feat(radio): hand the tuner slider's events to RadioControls through the store
RadioTuner binds the slider's pointer, key and value events in its template and calls RadioControls through the radio store; the drag, its slot and the pointer capture stay with RadioControls, unchanged.
This commit is contained in:
1 parent
7f7e66e793
commit
fa2dc9fc87
4 files changed
+72
-113
No files matched your search
+7
-6
@@ -58,12 +58,13 @@
|
|||||||
list renders. Street Level's fit and panorama filters and Recent Imagery's
|
list renders. Street Level's fit and panorama filters and Recent Imagery's
|
||||||
mode are `UiSegmented` too: the Street Level store's owner answers
|
mode are `UiSegmented` too: the Street Level store's owner answers
|
||||||
`setPano` and `setRenderMode`, and `RecentImageryReadout` takes
|
`setPano` and `setRenderMode`, and `RecentImageryReadout` takes
|
||||||
`onSetMode`. The Radio panel's and Cockpit's internet radio controls call
|
`onSetMode`. The Radio panel's and Cockpit's internet radio controls and
|
||||||
`RadioControls`, and the local RTL-SDR card's controls `LocalSdrControls`,
|
the tuner slider's events call `RadioControls`, and the local RTL-SDR
|
||||||
through the radio store's new `connect`/`act`; the card labels its gain
|
card's controls `LocalSdrControls`, through the radio store's new
|
||||||
options itself. `act` returns what the answering action returned. `syncScopeControls` (`./ui/display`) and
|
`connect`/`act`; the card labels its gain options itself. `act` returns
|
||||||
`shouldHideCollapsedRightPanels` (`./ui/layout`) are deprecated: the Display
|
what the answering action returned. `syncScopeControls` (`./ui/display`)
|
||||||
view and the rail now own what they did. `./ui/input` imports Vue
|
and `shouldHideCollapsedRightPanels` (`./ui/layout`) are deprecated: the
|
||||||
|
Display view and the rail now own what they did. `./ui/input` imports Vue
|
||||||
(samehkhamis).
|
(samehkhamis).
|
||||||
|
|
||||||
- `./ui/cctv` and `./ui/radio` import Vue and Pinia: their controllers
|
- `./ui/cctv` and `./ui/radio` import Vue and Pinia: their controllers
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ a feature supplying only its accent.
|
|||||||
the same way; fields a person edits take their value through
|
the same way; fields a person edits take their value through
|
||||||
`v-field-value`, which never writes a focused field;
|
`v-field-value`, which never writes a focused field;
|
||||||
`RadioTuner` renders the directory tuner, where RadioControls keeps the
|
`RadioTuner` renders the directory tuner, where RadioControls keeps the
|
||||||
drag and its slot and publishes the band, readouts, slider and needle,
|
drag and its slot, takes the slider's pointer, key and value events
|
||||||
|
through the store and publishes the band, readouts, slider and needle,
|
||||||
and the component lays out the tick tape against the dial's measured
|
and the component lays out the tick tape against the dial's measured
|
||||||
width and lays out the snapped needle before it drops the drag class;
|
width and lays out the snapped needle before it drops the drag class;
|
||||||
`ContextView` renders the mode switch and the nearby sites
|
`ContextView` renders the mode switch and the nearby sites
|
||||||
|
|||||||
+52
-101
@@ -382,7 +382,47 @@ export function bindRadioControls() {
|
|||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerListenerOptions,
|
||||||
);
|
);
|
||||||
// The Radio panel's and Cockpit's controls call these through the store.
|
const updateTunerFromPointer = (event) => {
|
||||||
|
const rect = this._radioTunerSlider?.getBoundingClientRect();
|
||||||
|
if (!rect || !this._radioTunerStations.length) return false;
|
||||||
|
const position = radioTunerPointerPosition(
|
||||||
|
event.clientX,
|
||||||
|
rect.left,
|
||||||
|
rect.width,
|
||||||
|
this._radioTunerStations.length,
|
||||||
|
);
|
||||||
|
if (position.stationIndex > this._radioTunerLastSlot)
|
||||||
|
this._radioTunerDragDirection = 1;
|
||||||
|
else if (position.stationIndex < this._radioTunerLastSlot)
|
||||||
|
this._radioTunerDragDirection = -1;
|
||||||
|
this._radioTunerLastSlot = position.stationIndex;
|
||||||
|
this._radioTunerCoordinate = position.coordinate;
|
||||||
|
showRadioTuner.call(this, { slot: position.stationIndex });
|
||||||
|
tunerPreview({ coordinate: position.coordinate });
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
const releaseNavigationBand = () => {
|
||||||
|
this._radioTunerBandPinnedForNavigation = false;
|
||||||
|
};
|
||||||
|
this.listen(
|
||||||
|
this.canvas,
|
||||||
|
'pointerdown',
|
||||||
|
releaseNavigationBand,
|
||||||
|
tunerListenerOptions,
|
||||||
|
);
|
||||||
|
this.listen(
|
||||||
|
this.canvas,
|
||||||
|
'wheel',
|
||||||
|
releaseNavigationBand,
|
||||||
|
tunerListenerOptions,
|
||||||
|
);
|
||||||
|
// The directory order is catalog/filter authority, not camera authority.
|
||||||
|
// Globe motion therefore never rebuilds or re-ranks the frequency band.
|
||||||
|
this._radioSelectedHandler = () =>
|
||||||
|
this.actions.setPanelCollapsed('radio-panel', false);
|
||||||
|
this.listen(document, 'gev:radio-selected', this._radioSelectedHandler);
|
||||||
|
// The Radio panel's and Cockpit's controls, and the tuner slider's events,
|
||||||
|
// call these through the store.
|
||||||
// Cockpit owns the Cesium camera even though it intentionally clears
|
// Cockpit owns the Cesium camera even though it intentionally clears
|
||||||
// viewer.trackedEntity, so its station steps pass `rotate: false`: they
|
// viewer.trackedEntity, so its station steps pass `rotate: false`: they
|
||||||
// must never start the map-view rotation/fallback flights that would
|
// must never start the map-view rotation/fallback flights that would
|
||||||
@@ -421,30 +461,7 @@ export function bindRadioControls() {
|
|||||||
showRadioVolume.call(this, value);
|
showRadioVolume.call(this, value);
|
||||||
this.actions.setParams({ volume: value / 100 }, { origin: 'user' });
|
this.actions.setParams({ volume: value / 100 }, { origin: 'user' });
|
||||||
},
|
},
|
||||||
});
|
tunerPointerDown: (event) => {
|
||||||
const updateTunerFromPointer = (event) => {
|
|
||||||
const rect = this._radioTunerSlider?.getBoundingClientRect();
|
|
||||||
if (!rect || !this._radioTunerStations.length) return false;
|
|
||||||
const position = radioTunerPointerPosition(
|
|
||||||
event.clientX,
|
|
||||||
rect.left,
|
|
||||||
rect.width,
|
|
||||||
this._radioTunerStations.length,
|
|
||||||
);
|
|
||||||
if (position.stationIndex > this._radioTunerLastSlot)
|
|
||||||
this._radioTunerDragDirection = 1;
|
|
||||||
else if (position.stationIndex < this._radioTunerLastSlot)
|
|
||||||
this._radioTunerDragDirection = -1;
|
|
||||||
this._radioTunerLastSlot = position.stationIndex;
|
|
||||||
this._radioTunerCoordinate = position.coordinate;
|
|
||||||
showRadioTuner.call(this, { slot: position.stationIndex });
|
|
||||||
tunerPreview({ coordinate: position.coordinate });
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'pointerdown',
|
|
||||||
(event) => {
|
|
||||||
if (!beginTuner()) return;
|
if (!beginTuner()) return;
|
||||||
this._radioTunerPointerId = event.pointerId;
|
this._radioTunerPointerId = event.pointerId;
|
||||||
this._radioTunerSlider.focus({ preventScroll: true });
|
this._radioTunerSlider.focus({ preventScroll: true });
|
||||||
@@ -456,12 +473,7 @@ export function bindRadioControls() {
|
|||||||
updateTunerFromPointer(event);
|
updateTunerFromPointer(event);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerPointerMove: (event) => {
|
||||||
);
|
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'pointermove',
|
|
||||||
(event) => {
|
|
||||||
if (
|
if (
|
||||||
!this._radioTunerDragging ||
|
!this._radioTunerDragging ||
|
||||||
this._radioTunerPointerId !== event.pointerId
|
this._radioTunerPointerId !== event.pointerId
|
||||||
@@ -470,12 +482,7 @@ export function bindRadioControls() {
|
|||||||
updateTunerFromPointer(event);
|
updateTunerFromPointer(event);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerInput: () => {
|
||||||
);
|
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'input',
|
|
||||||
() => {
|
|
||||||
if (this._radioTunerPointerId !== null || this._radioTunerKeyboardKey)
|
if (this._radioTunerPointerId !== null || this._radioTunerKeyboardKey)
|
||||||
return;
|
return;
|
||||||
// A drag the input starts begins from the selected station's slot.
|
// A drag the input starts begins from the selected station's slot.
|
||||||
@@ -496,21 +503,11 @@ export function bindRadioControls() {
|
|||||||
this._radioTunerCoordinate = inputSlot.stationIndex;
|
this._radioTunerCoordinate = inputSlot.stationIndex;
|
||||||
tunerPreview({ coordinate: this._radioTunerCoordinate });
|
tunerPreview({ coordinate: this._radioTunerCoordinate });
|
||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerChange: () => {
|
||||||
);
|
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'change',
|
|
||||||
() => {
|
|
||||||
if (this._radioTunerPointerId === null && !this._radioTunerKeyboardKey)
|
if (this._radioTunerPointerId === null && !this._radioTunerKeyboardKey)
|
||||||
finishTuner(true);
|
finishTuner(true);
|
||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerPointerUp: (event) => {
|
||||||
);
|
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'pointerup',
|
|
||||||
(event) => {
|
|
||||||
if (this._radioTunerPointerId !== event.pointerId) return;
|
if (this._radioTunerPointerId !== event.pointerId) return;
|
||||||
updateTunerFromPointer(event);
|
updateTunerFromPointer(event);
|
||||||
finishTuner(true);
|
finishTuner(true);
|
||||||
@@ -521,12 +518,7 @@ export function bindRadioControls() {
|
|||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerPointerCancel: (event) => {
|
||||||
);
|
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'pointercancel',
|
|
||||||
(event) => {
|
|
||||||
if (
|
if (
|
||||||
this._radioTunerPointerId !== null &&
|
this._radioTunerPointerId !== null &&
|
||||||
this._radioTunerPointerId !== event.pointerId
|
this._radioTunerPointerId !== event.pointerId
|
||||||
@@ -539,24 +531,14 @@ export function bindRadioControls() {
|
|||||||
}
|
}
|
||||||
finishTuner(false);
|
finishTuner(false);
|
||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerLostPointerCapture: (event) => {
|
||||||
);
|
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'lostpointercapture',
|
|
||||||
(event) => {
|
|
||||||
if (
|
if (
|
||||||
this._radioTunerDragging &&
|
this._radioTunerDragging &&
|
||||||
this._radioTunerPointerId === event.pointerId
|
this._radioTunerPointerId === event.pointerId
|
||||||
)
|
)
|
||||||
finishTuner(false);
|
finishTuner(false);
|
||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerKeyDown: (event) => {
|
||||||
);
|
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'keydown',
|
|
||||||
(event) => {
|
|
||||||
if (event.key === 'Escape' && this._radioTunerDragging) {
|
if (event.key === 'Escape' && this._radioTunerDragging) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
finishTuner(false);
|
finishTuner(false);
|
||||||
@@ -602,12 +584,7 @@ export function bindRadioControls() {
|
|||||||
showRadioTuner.call(this, { slot: slot.slot });
|
showRadioTuner.call(this, { slot: slot.slot });
|
||||||
tunerPreview({ coordinate: this._radioTunerCoordinate });
|
tunerPreview({ coordinate: this._radioTunerCoordinate });
|
||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerKeyUp: (event) => {
|
||||||
);
|
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'keyup',
|
|
||||||
(event) => {
|
|
||||||
if (
|
if (
|
||||||
!this._radioTunerKeyboardKey ||
|
!this._radioTunerKeyboardKey ||
|
||||||
event.key !== this._radioTunerKeyboardKey
|
event.key !== this._radioTunerKeyboardKey
|
||||||
@@ -616,32 +593,6 @@ export function bindRadioControls() {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
finishTuner(true);
|
finishTuner(true);
|
||||||
},
|
},
|
||||||
tunerListenerOptions,
|
tunerBlur: () => finishTuner(true),
|
||||||
);
|
});
|
||||||
this.listen(
|
|
||||||
this._radioTunerSlider,
|
|
||||||
'blur',
|
|
||||||
() => finishTuner(true),
|
|
||||||
tunerListenerOptions,
|
|
||||||
);
|
|
||||||
const releaseNavigationBand = () => {
|
|
||||||
this._radioTunerBandPinnedForNavigation = false;
|
|
||||||
};
|
|
||||||
this.listen(
|
|
||||||
this.canvas,
|
|
||||||
'pointerdown',
|
|
||||||
releaseNavigationBand,
|
|
||||||
tunerListenerOptions,
|
|
||||||
);
|
|
||||||
this.listen(
|
|
||||||
this.canvas,
|
|
||||||
'wheel',
|
|
||||||
releaseNavigationBand,
|
|
||||||
tunerListenerOptions,
|
|
||||||
);
|
|
||||||
// The directory order is catalog/filter authority, not camera authority.
|
|
||||||
// Globe motion therefore never rebuilds or re-ranks the frequency band.
|
|
||||||
this._radioSelectedHandler = () =>
|
|
||||||
this.actions.setPanelCollapsed('radio-panel', false);
|
|
||||||
this.listen(document, 'gev:radio-selected', this._radioSelectedHandler);
|
|
||||||
}
|
}
|
||||||
@@ -15,11 +15,15 @@ import { useRadioStore } from '../../stores/radio.js';
|
|||||||
|
|
||||||
// The Radio panel's directory tuner. RadioControls owns the drag and
|
// The Radio panel's directory tuner. RadioControls owns the drag and
|
||||||
// publishes the band, the readouts, the slider and where the needle sits;
|
// publishes the band, the readouts, the slider and where the needle sits;
|
||||||
// until it does, the tuner shows its initial markup. The tick tape is laid
|
// until it does, the tuner shows its initial markup. The slider hands its
|
||||||
// out here against the dial's width. A hidden dial measures 0 wide, so the
|
// pointer, key and value events to RadioControls through the store. The
|
||||||
// last real width is kept and no ticks are drawn before there is one: ticks
|
// tick tape is laid out here against the dial's width. A hidden dial
|
||||||
// laid out for no width would slide into place when the tuner appears.
|
// measures 0 wide, so the last real width is kept and no ticks are drawn
|
||||||
const { tuner } = storeToRefs(useRadioStore());
|
// before there is one: ticks laid out for no width would slide into place
|
||||||
|
// when the tuner appears.
|
||||||
|
const store = useRadioStore();
|
||||||
|
const { act } = store;
|
||||||
|
const { tuner } = storeToRefs(store);
|
||||||
const dial = useTemplateRef('dial');
|
const dial = useTemplateRef('dial');
|
||||||
const dialWidth = shallowRef(0);
|
const dialWidth = shallowRef(0);
|
||||||
let resizeObserver = null;
|
let resizeObserver = null;
|
||||||
@@ -68,6 +72,8 @@ const vTunerDragging = {
|
|||||||
<div class="radio-tuner-scale" aria-hidden="true" :style="tape && { '--radio-tuner-tick-pitch': `${tape.pitchPx}px` }"><span v-for="(tick, index) in tape?.ticks ?? []" :key="index" class="radio-tuner-tick" :class="{ 'is-current': tick.current }" :style="{ left: `${tick.xPx}px` }" :data-station-index="tick.stationIndex">{{ tick.label }}</span></div>
|
<div class="radio-tuner-scale" aria-hidden="true" :style="tape && { '--radio-tuner-tick-pitch': `${tape.pitchPx}px` }"><span v-for="(tick, index) in tape?.ticks ?? []" :key="index" class="radio-tuner-tick" :class="{ 'is-current': tick.current }" :style="{ left: `${tick.xPx}px` }" :data-station-index="tick.stationIndex">{{ tick.label }}</span></div>
|
||||||
<div id="radio-tuner-needle" class="radio-tuner-needle" aria-hidden="true"></div>
|
<div id="radio-tuner-needle" class="radio-tuner-needle" aria-hidden="true"></div>
|
||||||
<input id="radio-tuner-slider" type="range" min="0" :max="tuner ? tuner.max : 0" step="1" value="0" v-range-value="tuner ? tuner.slot : 0"
|
<input id="radio-tuner-slider" type="range" min="0" :max="tuner ? tuner.max : 0" step="1" value="0" v-range-value="tuner ? tuner.slot : 0"
|
||||||
|
@pointerdown="act('tunerPointerDown', $event)" @pointermove="act('tunerPointerMove', $event)" @pointerup="act('tunerPointerUp', $event)" @pointercancel="act('tunerPointerCancel', $event)" @lostpointercapture="act('tunerLostPointerCapture', $event)"
|
||||||
|
@keydown="act('tunerKeyDown', $event)" @keyup="act('tunerKeyUp', $event)" @input="act('tunerInput')" @change="act('tunerChange')" @blur="act('tunerBlur')"
|
||||||
aria-label="Tune available internet radio stations" :aria-valuetext="tuner?.valuetext ?? t('No station available')" :disabled="tuner ? !tuner.available : true" data-i18n-aria-label />
|
aria-label="Tune available internet radio stations" :aria-valuetext="tuner?.valuetext ?? t('No station available')" :disabled="tuner ? !tuner.available : true" data-i18n-aria-label />
|
||||||
</div>
|
</div>
|
||||||
<div class="radio-tuner-readout">
|
<div class="radio-tuner-readout">
|
||||||
|
|||||||
Reference in new issue
Block a user