mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
Keep Radio Next and Previous from starting playback before Play
The Next and Previous buttons cycled stations with the layer's default autoplay, so a first press started buffering a broadcaster stream even though the panel says audio connects only after Play. Stepping now only selects until a stream is loading, buffering or playing; once one is, playback follows the new station so the old broadcaster does not keep playing under the new label. The compact Next fallback scenario in qa-radio.mjs started from a stopped stream and relied on the old behaviour, so it now starts from a playing station. Fixes HAL-722 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c434664549
commit
1ef9be2248
3 files changed
+52
-2
No files matched your search
@@ -3820,7 +3820,15 @@ async function main() {
|
||||
radio.stopPlayback();
|
||||
Array.from({ length: gev.viewer.dataSources.length }, (_, index) => gev.viewer.dataSources.get(index))
|
||||
.find((item) => item.name === 'Radio stations').clustering.enabled = true;
|
||||
radio.selectStation('00000000-0000-4000-8000-000000000001', { autoplay: false, focus: false });
|
||||
// Next only carries playback once a stream is active (HAL-722), so the
|
||||
// fallback scenario starts from a playing station.
|
||||
radio.selectStation('00000000-0000-4000-8000-000000000001', { autoplay: true, focus: false });
|
||||
});
|
||||
await page.waitForFunction(() => window.__godsEyeView.dataManager.layers.get('radio').module.getUIState().audioState === 'playing');
|
||||
await page.evaluate(() => {
|
||||
const gev = window.__godsEyeView;
|
||||
const camera = gev.viewer.camera;
|
||||
const radio = gev.dataManager.layers.get('radio').module;
|
||||
const pool = gev.styleManager._radioControls._radioTunerPool;
|
||||
const selectedIndex = pool.findIndex((station) => station.id === radio.getUIState().selected?.id);
|
||||
window.__qaRadioExpectedPrimary = pool[(selectedIndex + 1) % pool.length];
|
||||
|
||||
@@ -338,9 +338,14 @@ export function bindRadioControls() {
|
||||
const pool = this._radioTunerPool.length
|
||||
? this._radioTunerPool
|
||||
: this._radioTunerStations;
|
||||
// Stepping only selects until the user has pressed Play; once a stream is
|
||||
// active it follows the selection so the old broadcaster does not keep
|
||||
// playing under a new station label.
|
||||
const { audioState } = this.radio.getUIState();
|
||||
const cycled = this.radio.cycleStation(direction, {
|
||||
rotate,
|
||||
stationIds: pool.map((station) => station.id),
|
||||
autoplay: ['loading', 'buffering', 'playing'].includes(audioState),
|
||||
origin: 'user',
|
||||
});
|
||||
if (!cycled) {
|
||||
|
||||
@@ -40,8 +40,11 @@ function fixture() {
|
||||
const panel = new Element();
|
||||
const enable = new Element();
|
||||
const next = new Element();
|
||||
const prev = new Element();
|
||||
const calls = [];
|
||||
const cycleOptions = [];
|
||||
const subscribers = [];
|
||||
const uiState = { audioState: 'stopped' };
|
||||
const radio = {
|
||||
subscribe(callback) {
|
||||
subscribers.push(callback);
|
||||
@@ -51,10 +54,12 @@ function fixture() {
|
||||
endTuning() {
|
||||
calls.push('endTuning');
|
||||
},
|
||||
cycleStation(direction) {
|
||||
cycleStation(direction, options) {
|
||||
calls.push(['cycle', direction]);
|
||||
cycleOptions.push(options);
|
||||
return true;
|
||||
},
|
||||
getUIState: () => uiState,
|
||||
};
|
||||
const actions = {
|
||||
isRegistered: () => true,
|
||||
@@ -73,6 +78,7 @@ function fixture() {
|
||||
_radioPanel: panel,
|
||||
_radioEnableBtn: enable,
|
||||
_radioNextBtn: next,
|
||||
_radioPrevBtn: prev,
|
||||
},
|
||||
radio,
|
||||
actions,
|
||||
@@ -82,8 +88,11 @@ function fixture() {
|
||||
controls,
|
||||
enable,
|
||||
next,
|
||||
prev,
|
||||
actions,
|
||||
calls,
|
||||
cycleOptions,
|
||||
uiState,
|
||||
subscribers,
|
||||
document,
|
||||
cleanup() {
|
||||
@@ -172,3 +181,31 @@ test('destruction releases an active tuner pointer after revoking listeners', ()
|
||||
f.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
test('Next and Previous select without playing until playback has started', () => {
|
||||
const f = fixture();
|
||||
try {
|
||||
f.controls.connect();
|
||||
for (const audioState of ['stopped', 'paused', 'error']) {
|
||||
f.uiState.audioState = audioState;
|
||||
f.next.dispatchEvent(new Event('click'));
|
||||
f.prev.dispatchEvent(new Event('click'));
|
||||
}
|
||||
assert.deepEqual(
|
||||
f.cycleOptions.map((options) => options.autoplay),
|
||||
[false, false, false, false, false, false],
|
||||
);
|
||||
f.cycleOptions.length = 0;
|
||||
for (const audioState of ['loading', 'buffering', 'playing']) {
|
||||
f.uiState.audioState = audioState;
|
||||
f.next.dispatchEvent(new Event('click'));
|
||||
f.prev.dispatchEvent(new Event('click'));
|
||||
}
|
||||
assert.deepEqual(
|
||||
f.cycleOptions.map((options) => options.autoplay),
|
||||
[true, true, true, true, true, true],
|
||||
);
|
||||
} finally {
|
||||
f.cleanup();
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user