mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
Merge branch 'main' into german/hal-623-hud-summary-locale
This commit is contained in:
30 files changed
+765
-163
No files matched your search
@@ -2227,7 +2227,11 @@ export async function controlRadio(
|
||||
if (!radioActionIsCurrent(options)) return cancelled(summarize);
|
||||
const prepared = state.selected
|
||||
? true
|
||||
: radio.cycleStation?.(1, { focus: false, autoplay: false });
|
||||
: radio.cycleStation?.(1, {
|
||||
focus: false,
|
||||
autoplay: false,
|
||||
fallback: true,
|
||||
});
|
||||
return {
|
||||
ok: Boolean(prepared),
|
||||
action: 'control_radio',
|
||||
@@ -2251,6 +2255,7 @@ export async function controlRadio(
|
||||
const selected = radio.cycleStation?.(action === 'next' ? 1 : -1, {
|
||||
focus: false,
|
||||
autoplay: false,
|
||||
fallback: true,
|
||||
});
|
||||
return {
|
||||
ok: Boolean(selected),
|
||||
|
||||
@@ -1905,7 +1905,7 @@ test('voice Radio resolves Austin and exposes semantic selection, volume, pause,
|
||||
assert.equal(result.radioAction, 'play');
|
||||
assert.equal(result.stationId, 'nearest');
|
||||
assert.equal('station' in result, false);
|
||||
assert.deepEqual(calls.at(-1), ['cycle', 1, { focus: false, autoplay: false }]);
|
||||
assert.deepEqual(calls.at(-1), ['cycle', 1, { focus: false, autoplay: false, fallback: true }]);
|
||||
|
||||
for (const invalidCoordinates of [
|
||||
{ latitude: null, longitude: null },
|
||||
|
||||
@@ -591,41 +591,50 @@ test('replacement input invalidates an in-flight Radio preflight immediately', (
|
||||
assert.equal(controller.radioHandoffEpoch, priorEpoch + 1);
|
||||
});
|
||||
|
||||
test('direct Radio pause or stop cancels a pending voice handoff', async () => {
|
||||
const order = [];
|
||||
let playbackControl = null;
|
||||
const ui = createTestVoiceUi();
|
||||
const controller = new GevRealtimeController({
|
||||
ui,
|
||||
runner: async () => ({ ok: true }),
|
||||
radioLayer: {
|
||||
subscribePlaybackControls(listener) {
|
||||
playbackControl = listener;
|
||||
return () => { playbackControl = null; };
|
||||
for (const [name, control, message] of [
|
||||
['direct Radio pause or stop cancels a pending voice handoff', 'stop', 'the explicit stop remains authoritative'],
|
||||
[
|
||||
'a direct Radio Next that does not play cancels a pending voice handoff',
|
||||
{ action: 'select', origin: 'user', attemptId: null },
|
||||
'the user selection is not overridden by voice playback',
|
||||
],
|
||||
]) {
|
||||
test(name, async () => {
|
||||
const order = [];
|
||||
let playbackControl = null;
|
||||
const ui = createTestVoiceUi();
|
||||
const controller = new GevRealtimeController({
|
||||
ui,
|
||||
runner: async () => ({ ok: true }),
|
||||
radioLayer: {
|
||||
subscribePlaybackControls(listener) {
|
||||
playbackControl = listener;
|
||||
return () => { playbackControl = null; };
|
||||
},
|
||||
playForVoice: async () => {
|
||||
order.push('radio-play');
|
||||
return true;
|
||||
},
|
||||
stopPlayback: () => order.push('radio-stop'),
|
||||
},
|
||||
playForVoice: async () => {
|
||||
order.push('radio-play');
|
||||
return true;
|
||||
},
|
||||
stopPlayback: () => order.push('radio-stop'),
|
||||
},
|
||||
});
|
||||
controller.debugLog = () => {};
|
||||
controller.dc = {
|
||||
readyState: 'open',
|
||||
send() {},
|
||||
close() { order.push('voice-stop'); },
|
||||
};
|
||||
controller.pendingRadioPlaybackResult = { ok: true, radioPlaybackRequested: true };
|
||||
});
|
||||
controller.debugLog = () => {};
|
||||
controller.dc = {
|
||||
readyState: 'open',
|
||||
send() {},
|
||||
close() { order.push('voice-stop'); },
|
||||
};
|
||||
controller.pendingRadioPlaybackResult = { ok: true, radioPlaybackRequested: true };
|
||||
|
||||
playbackControl('stop');
|
||||
await controller.handleRealtimeEvent({
|
||||
data: JSON.stringify({ type: 'response.done', response: { status: 'completed' } }),
|
||||
});
|
||||
playbackControl(control);
|
||||
await controller.handleRealtimeEvent({
|
||||
data: JSON.stringify({ type: 'response.done', response: { status: 'completed' } }),
|
||||
});
|
||||
|
||||
assert.equal(controller.pendingRadioPlaybackResult, null);
|
||||
assert.deepEqual(order, [], 'the explicit stop remains authoritative');
|
||||
});
|
||||
assert.equal(controller.pendingRadioPlaybackResult, null);
|
||||
assert.deepEqual(order, [], message);
|
||||
});
|
||||
}
|
||||
|
||||
test('confirmed manual Radio playback closes active voice without stopping Radio', () => {
|
||||
const order = [];
|
||||
|
||||
@@ -65,7 +65,7 @@ export class RealtimeRadio {
|
||||
: control || {};
|
||||
if (
|
||||
event.origin === 'user' &&
|
||||
(event.action === 'pause' || event.action === 'stop')
|
||||
['pause', 'stop', 'select'].includes(event.action)
|
||||
) {
|
||||
this.cancelRadioHandoff();
|
||||
} else if (
|
||||
|
||||
Reference in new issue
Block a user