mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
Bring back the tuner-release and connecting-label Radio fixes
Restore the two fixes the previous commit moved out: - A tuner release onto a station the directory dropped mid-drag stops the stream the drag paused, publishing one state with the gesture's origin, so the button reads PLAY and a voice handoff is cancelled. - The transport buttons offer Pause while a stream connects, matching what a click does. Their tests now use the shared Radio layer harness.
This commit is contained in:
1 parent
a55450e2e7
commit
5ed86200e5
5 files changed
+81
-4
No files matched your search
@@ -1,2 +1,4 @@
|
||||
- Radio Next and Previous no longer start a broadcaster stream before Play is
|
||||
pressed; while a stream plays, it follows the new station (gekh, #1474).
|
||||
pressed; while a stream plays, it follows the new station. Play reads Pause
|
||||
while a stream connects, and a tuner release onto a station the directory
|
||||
dropped no longer leaves a Resume for another station (gekh, #1474).
|
||||
@@ -4774,7 +4774,8 @@ result reads enabled state from the manager and audio state from the Radio
|
||||
module. Voice Pause is a playback-only no-op while the layer is disabled; it
|
||||
never enables Radio and reports a fulfilled-false pause as failure. A
|
||||
newer-response or user-origin Stop still cancels stale handoff work, as do a
|
||||
user Pause and a user Previous/Next that only selects another station.
|
||||
user Pause, a user Previous/Next that only selects another station, and a tuner
|
||||
release onto a station the directory no longer has.
|
||||
Only a newer user turn or session teardown aborts the complete active-tool set.
|
||||
A cancelled turn cannot publish a late Radio playback request. Dedicated Radio
|
||||
controls and generic layer-visibility commands both forward cancellation.
|
||||
|
||||
@@ -192,3 +192,72 @@ test('only a user step to another station tells voice to drop its prepared playb
|
||||
assert.deepEqual(controls.map(({ action, origin }) => [action, origin]), [['select', 'user']]);
|
||||
});
|
||||
});
|
||||
|
||||
test('an unavailable tuner release stops the paused stream once, and Play still falls back', async () => {
|
||||
setLocale('en');
|
||||
const failing = [];
|
||||
await withLayer(failing, async ({ playUrls, catalog }) => {
|
||||
radioLayer.selectStation(ids[2], { autoplay: true, origin: 'user' });
|
||||
await settle();
|
||||
assert.equal(radioLayer.beginTuning(), true);
|
||||
radioLayer.previewTuningStation(ids[1], { rotate: false });
|
||||
// A directory refresh changes the station under the needle mid-drag.
|
||||
catalog.rows = stations.map((row) => row.id === ids[1]
|
||||
? { ...row, streamUrl: 'https://radio.example.com/b2.mp3' }
|
||||
: row);
|
||||
catalog.generation = 2;
|
||||
await radioLayer.update();
|
||||
const states = [];
|
||||
const controls = [];
|
||||
const unsubscribe = radioLayer.subscribe((state) => states.push(state));
|
||||
const unsubscribeControls = radioLayer.subscribePlaybackControls((event) => controls.push(event));
|
||||
states.length = 0;
|
||||
try {
|
||||
assert.equal(radioLayer.commitTuningStation(ids[1], { origin: 'user' }).reason, 'station-unavailable');
|
||||
} finally {
|
||||
unsubscribe();
|
||||
unsubscribeControls();
|
||||
}
|
||||
assert.equal(states.length, 1);
|
||||
assert.equal(states[0].tuningUnavailableStationId, ids[1]);
|
||||
assert.deepEqual(controls.map(({ action, origin }) => [action, origin]), [['stop', 'user']]);
|
||||
const state = radioLayer.getUIState();
|
||||
assert.equal(state.selected, null);
|
||||
assert.equal(state.audioState, 'stopped');
|
||||
assert.equal(state.playingStationId, null);
|
||||
assert.equal(render(state).button, 'PLAY');
|
||||
playUrls.length = 0;
|
||||
// Play picks the nearest station; its broadcaster fails.
|
||||
const play = globalThis.Audio.prototype.play;
|
||||
globalThis.Audio.prototype.play = function playFirstFails() {
|
||||
if (!failing.length) failing.push(this.src);
|
||||
return play.call(this);
|
||||
};
|
||||
try {
|
||||
await radioLayer.togglePlayback({ origin: 'user' });
|
||||
await settle();
|
||||
await settle();
|
||||
} finally {
|
||||
globalThis.Audio.prototype.play = play;
|
||||
}
|
||||
assert.equal(playUrls.length, 2);
|
||||
assert.equal(radioLayer.getUIState().audioState, 'playing');
|
||||
});
|
||||
});
|
||||
|
||||
test('while a stream connects the transport buttons offer Pause, because a click pauses', () => {
|
||||
setLocale('en');
|
||||
const shown = render({
|
||||
enabled: true,
|
||||
audioState: 'loading',
|
||||
audioError: null,
|
||||
selected: { id: 'a', name: 'Station A' },
|
||||
selectedIndex: 0,
|
||||
filteredCount: 1,
|
||||
stationCount: 1,
|
||||
volume: 1,
|
||||
});
|
||||
assert.equal(shown.status, 'Connecting directly to broadcaster…');
|
||||
assert.equal(shown.button, 'PAUSE');
|
||||
assert.equal(shown.cockpit, 'Ⅱ');
|
||||
});
|
||||
@@ -179,7 +179,10 @@ export function createTuning({ state: layerState, services, parts, source }) {
|
||||
layerState._selectionGeneration += 1;
|
||||
parts.tuningNoise.clearRadioTuningNoise({ emit: false });
|
||||
layerState._tuningUnavailableStationId = stationId;
|
||||
parts.presentation.emitState();
|
||||
// The drag paused the previous stream; with no selection left, Resume
|
||||
// could only start the nearest station, so release it. Stop publishes
|
||||
// the state, and as the user's gesture it cancels a voice handoff.
|
||||
parts.playback.stopRadioPlayback({ origin });
|
||||
return Object.freeze({
|
||||
ok: false,
|
||||
reason: 'station-unavailable',
|
||||
|
||||
@@ -20,7 +20,9 @@ export function renderRadioState(state) {
|
||||
const interactive = enabled && !transitioning && !uncertain;
|
||||
const selected = state.selected || null;
|
||||
const hasStations = state.filteredCount > 0;
|
||||
const activePlayback = ['playing', 'buffering'].includes(state.audioState);
|
||||
const activePlayback = ['loading', 'buffering', 'playing'].includes(
|
||||
state.audioState,
|
||||
);
|
||||
document
|
||||
.getElementById('title-bar')
|
||||
?.classList.toggle('radio-broadcasting', state.audioState === 'playing');
|
||||
|
||||
Reference in new issue
Block a user