mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
fix(voice): keep the voice preferences in reach from chat Settings
With Voice Preview off the voice panel never opens on its own, and chat Settings hid the voice preferences, so the Preview toggle, inactivity timeout and model tier could not be reached by pointer. Chat Settings now show them below the chat options, still in chat's frame and without the voice tabs.
This commit is contained in:
1 parent
4f4af9c4e0
commit
829db19f60
4 files changed
+71
-8
No files matched your search
@@ -1242,14 +1242,20 @@ body[data-assistant-docked='true'] #right-context-rail {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Settings opened from chat: same frame as chat, chat options only. */
|
||||
/* Settings opened from chat: same frame as chat, chat options first, then
|
||||
the voice preferences, the only pointer route to them while Preview is off. */
|
||||
#command-dock
|
||||
#gev-voice-control
|
||||
#gev-voice-panel[data-context='chat']
|
||||
:is(.gev-voice-panel-tabs, .gev-panel-layout, #gev-settings-voice),
|
||||
:is(.gev-voice-panel-tabs, .gev-panel-layout),
|
||||
#gev-voice-panel:not([data-context='chat']) #gev-settings-chat {
|
||||
display: none;
|
||||
}
|
||||
#gev-voice-panel[data-context='chat'] #gev-settings-voice {
|
||||
margin-top: 0.75rem;
|
||||
padding-top: 0.75rem;
|
||||
border-top: 1px solid var(--glass-border);
|
||||
}
|
||||
#gev-voice-control
|
||||
#gev-voice-panel[data-context='chat'][data-placement='compact']:not(
|
||||
[data-minimized]
|
||||
|
||||
@@ -125,6 +125,10 @@ const frameStyle = (panel) => ({
|
||||
<UiSelect id="gev-voice-provider" class="gev-field" :aria-label="t('AI Provider')" :title="view.provider.title" :model-value="view.provider.value" @update:model-value="emit('provider-change', $event)"><option v-for="option in view.provider.options" :key="option.value" :value="option.value">{{ option.label }}</option></UiSelect>
|
||||
</label>
|
||||
<p class="gev-voice-settings-note">{{ t('The selected AI provider is shared by voice and chat.') }}</p>
|
||||
<div id="gev-settings-chat">
|
||||
<label class="gev-voice-preference gev-voice-preference-toggle"><input id="gev-chat-quick" type="checkbox" v-checked="view.chat.quickChecked" @change="emit('chat-quick-change', $event.target.checked)" /><span>{{ t('Show quick commands') }}</span></label>
|
||||
<p>{{ t('Chat replies are silent. No microphone access is needed.') }}</p>
|
||||
</div>
|
||||
<div id="gev-settings-voice">
|
||||
<label class="gev-voice-preference gev-voice-preference-toggle"><input id="gev-voice-preview-enabled" type="checkbox" aria-describedby="gev-voice-preview-note" v-checked="view.preferences.previewChecked" @change="emit('preview-change', $event.target.checked)" /><span>{{ t('Show Voice Preview') }}</span></label>
|
||||
<p id="gev-voice-preview-note" class="gev-voice-settings-note">{{ view.preferences.previewNote }}</p>
|
||||
@@ -152,10 +156,6 @@ const frameStyle = (panel) => ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="gev-settings-chat">
|
||||
<label class="gev-voice-preference gev-voice-preference-toggle"><input id="gev-chat-quick" type="checkbox" v-checked="view.chat.quickChecked" @change="emit('chat-quick-change', $event.target.checked)" /><span>{{ t('Show quick commands') }}</span></label>
|
||||
<p>{{ t('Chat replies are silent. No microphone access is needed.') }}</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import '../../testSupport/registerDom.mjs';
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { createPinia } from 'pinia';
|
||||
import { createVoiceControl } from '../control.js';
|
||||
import { useVoiceStore } from '../../ui/stores/voice.js';
|
||||
@@ -1007,6 +1008,61 @@ test('chat Settings keep chat context until the panel closes', async (t) => {
|
||||
assert.equal(f.ui.state.chat.backVisible, false);
|
||||
});
|
||||
|
||||
// Shown once neither the element nor an ancestor is hidden by the page's
|
||||
// chat stylesheet or a hidden attribute.
|
||||
function shown(selector) {
|
||||
for (let node = $(selector); node?.nodeType === 1; node = node.parentElement)
|
||||
if (node.hidden || globalThis.getComputedStyle(node).display === 'none')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
test('with Preview off, chat Settings reach the voice preferences', async (t) => {
|
||||
const style = globalThis.document.createElement('style');
|
||||
style.textContent = readFileSync(
|
||||
new URL('../../ui/styles/ai-chat.css', import.meta.url),
|
||||
'utf8',
|
||||
);
|
||||
globalThis.document.head.append(style);
|
||||
t.after(() => style.remove());
|
||||
const f = mounted(t, { view: true });
|
||||
// The control renders into the command dock, as the page does.
|
||||
globalThis.document.body.firstElementChild.id = 'command-dock';
|
||||
f.ui.emit('preview-change', false);
|
||||
f.commands.voicePanel.close();
|
||||
await f.settle();
|
||||
$('#gev-chat-button').click();
|
||||
await f.settle();
|
||||
$('#gev-voice-settings-button').click();
|
||||
await f.settle();
|
||||
assert.equal(f.ui.state.voicePanel.context, 'chat');
|
||||
for (const selector of [
|
||||
'#gev-settings-chat',
|
||||
'#gev-settings-voice',
|
||||
'#gev-voice-preview-enabled',
|
||||
'#gev-voice-timeout-select',
|
||||
])
|
||||
assert.equal(shown(selector), true, selector);
|
||||
// Chat's frame keeps the voice tabs and dock layout buttons away.
|
||||
assert.equal(shown('.gev-voice-panel-tabs'), false);
|
||||
const preview = $('#gev-voice-preview-enabled');
|
||||
preview.checked = true;
|
||||
preview.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
assert.equal(f.commands.getVoicePreferences().previewEnabled, true);
|
||||
const timeout = $('#gev-voice-timeout-select');
|
||||
timeout.value = '10';
|
||||
timeout.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
assert.equal(f.commands.getVoicePreferences().minutes, 10);
|
||||
f.ui.update('tier', { hidden: false });
|
||||
await f.settle();
|
||||
assert.equal(shown('#gev-voice-tier'), true);
|
||||
let tiers = 0;
|
||||
t.after(f.ui.on('tier', () => tiers++));
|
||||
$('#gev-voice-tier').click();
|
||||
assert.equal(tiers, 1);
|
||||
assert.equal(f.ui.state.voicePanel.context, 'chat', 'still chat Settings');
|
||||
});
|
||||
|
||||
test('chat Settings keep only the quick commands preference', async (t) => {
|
||||
const f = mounted(t, { view: true });
|
||||
await f.settle();
|
||||
|
||||
Reference in new issue
Block a user