diff options
| author | yum <yum.food.vr@gmail.com> | 2025-05-30 21:31:05 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2025-05-30 21:31:05 -0700 |
| commit | 73de7cb2d8fb964e7f76ab55420e9bc331bf7bea (patch) | |
| tree | a99566ce36d6a82be627820d639a8af2b40c0672 /ui | |
| parent | 7fb9c575aea4d318e9c14b82174d1b323171b62b (diff) | |
More stuff
- add desktop and vr input threads
- add audio feedback for input
- add volume control for audio feedback
- add UI for custom chatbox/built in chatbox
- add ability to dismiss built in chatbox (sync empty messages)
- limit lines in python console
- limit length of each transcript
Diffstat (limited to 'ui')
| -rw-r--r-- | ui/config-schema.js | 11 | ||||
| -rw-r--r-- | ui/index.html | 50 | ||||
| -rw-r--r-- | ui/index.js | 16 | ||||
| -rw-r--r-- | ui/preload.js | 1 | ||||
| -rw-r--r-- | ui/renderer.js | 58 |
5 files changed, 133 insertions, 3 deletions
diff --git a/ui/config-schema.js b/ui/config-schema.js index b1108ff..6b11277 100644 --- a/ui/config-schema.js +++ b/ui/config-schema.js @@ -6,11 +6,15 @@ const CONFIG_SCHEMA = { model: { type: 'select', default: 'turbo' }, microphone: { type: 'number', default: 0 }, user_prompt: { type: 'text', default: 'Use proper punctuation and grammar. Prefer spelled out numbers like one, eleven, twenty, etc. Mm.' }, + keybind: { type: 'text', default: 'ctrl+alt+x' }, + button_hand: { type: 'select', default: 'right' }, + button_type: { type: 'select', default: 'b' }, // Number fields gpu_idx: { type: 'number', default: 0 }, max_speech_duration_s: { type: 'number', default: 10 }, - min_silence_duration_ms: { type: 'number', default: 250 }, + min_speech_duration_ms: { type: 'number', default: 250 }, + min_silence_duration_ms: { type: 'number', default: 100 }, reset_after_silence_s: { type: 'number', default: 15 }, transcription_loop_delay_ms: { type: 'number', default: 100 }, block_width: { type: 'number', default: 2 }, @@ -28,7 +32,10 @@ const CONFIG_SCHEMA = { enable_lowercase_filter: { type: 'boolean', default: 0 }, enable_uppercase_filter: { type: 'boolean', default: 0 }, enable_profanity_filter: { type: 'boolean', default: 0 }, - remove_trailing_period: { type: 'boolean', default: 0 } + remove_trailing_period: { type: 'boolean', default: 0 }, + reset_on_toggle: { type: 'boolean', default: 0 }, + enable_local_beep: { type: 'boolean', default: 1 }, + use_builtin: { type: 'boolean', default: 1 } }; // Helper to extract just the default values diff --git a/ui/index.html b/ui/index.html index 97da3d2..99e64dd 100644 --- a/ui/index.html +++ b/ui/index.html @@ -64,6 +64,31 @@ </button> </div> </div> + <div> + <label for="button_hand" class="form-label"> + VR Hand + </label> + <select id="button_hand" class="form-input"> + <option value="left">Left</option> + <option value="right">Right</option> + </select> + </div> + <div> + <label for="button_type" class="form-label"> + VR Button + </label> + <select id="button_type" class="form-input"> + <option value="a">A</option> + <option value="b">B</option> + <option value="thumbstick">Thumbstick</option> + </select> + </div> + <div class="col-span-2"> + <label for="keybind" class="form-label"> + Keyboard Binding + </label> + <input type="text" id="keybind" value="f24" class="form-input" placeholder="f24"> + </div> </div> </section> @@ -111,6 +136,10 @@ <input type="number" id="max_speech_duration_s" min="1" value="10" class="form-input"> </div> <div> + <label for="min_speech_duration_ms" class="form-label">Min Speech Duration (ms)</label> + <input type="number" id="min_speech_duration_ms" min="0" value="100" class="form-input"> + </div> + <div> <label for="min_silence_duration_ms" class="form-label">Min Silence Duration (ms)</label> <input type="number" id="min_silence_duration_ms" min="0" value="250" class="form-input"> </div> @@ -211,9 +240,30 @@ </div> </section> + <!-- Input Settings --> + <section class="config-section"> + <h2 class="section-title">Input Settings</h2> + <div class="space-y-4"> + <label for="reset_on_toggle" class="checkbox-label"> + <input type="checkbox" id="reset_on_toggle" class="mr-2"> + <span class="checkbox-text">Reset transcript on toggle</span> + </label> + <label for="enable_local_beep" class="checkbox-label"> + <input type="checkbox" id="enable_local_beep" checked class="mr-2"> + <span class="checkbox-text">Enable local beep sounds</span> + </label> + </div> + </section> + <!-- Display Settings --> <section class="config-section"> <h2 class="section-title">Custom Chatbox Settings</h2> + <div class="mb-4"> + <label for="use_builtin" class="checkbox-label"> + <input type="checkbox" id="use_builtin" class="mr-2"> + <span class="checkbox-text">Use built-in VRChat chatbox</span> + </label> + </div> <div class="grid grid-cols-2 gap-4"> <div> <label for="block_width" class="form-label">Block Width</label> diff --git a/ui/index.js b/ui/index.js index 7717c92..24a7e13 100644 --- a/ui/index.js +++ b/ui/index.js @@ -246,6 +246,21 @@ ipcMain.handle('reset-config', async () => { } }); +ipcMain.handle('deleteVenvIndicatorFile', async () => { + const venvMarkerPath = path.join(APP_ROOT, '.venv_is_set_up'); + try { + await fs.unlink(venvMarkerPath); + return { success: true, message: '.venv_is_set_up deleted successfully.' }; + } catch (error) { + if (error.code === 'ENOENT') { + return { success: true, message: '.venv_is_set_up not found.' }; + } + console.error('Error deleting .venv_is_set_up file:', error); + sendPythonOutput(`Error deleting .venv_is_set_up: ${error.message}`, 'stderr'); + throw error; + } +}); + // Generic function to ensure required files are present async function ensureRequiredFiles(config) { const { @@ -332,7 +347,6 @@ ipcMain.handle('install-requirements', async () => { // Check if venv is already set up try { await fs.access(venvMarkerPath); - sendPythonOutput('Virtual environment already set up, skipping installation', 'info'); return { success: true, message: 'Virtual environment already set up' }; } catch (error) { // Marker doesn't exist, proceed with setup diff --git a/ui/preload.js b/ui/preload.js index 35cc8d6..f2e0a81 100644 --- a/ui/preload.js +++ b/ui/preload.js @@ -6,6 +6,7 @@ contextBridge.exposeInMainWorld('electronAPI', { resetConfig: () => ipcRenderer.invoke('reset-config'), getMicrophones: () => ipcRenderer.invoke('get-microphones'), installRequirements: () => ipcRenderer.invoke('install-requirements'), + deleteVenvIndicatorFile: () => ipcRenderer.invoke('deleteVenvIndicatorFile'), resetVenv: () => ipcRenderer.invoke('reset-venv'), startProcess: () => ipcRenderer.invoke('start-process'), stopProcess: () => ipcRenderer.invoke('stop-process'), diff --git a/ui/renderer.js b/ui/renderer.js index 133a79b..2f4c8f1 100644 --- a/ui/renderer.js +++ b/ui/renderer.js @@ -162,11 +162,28 @@ function setFormValues(config) { } } + // Handle use_builtin toggle state + const useBuiltin = config.use_builtin === 1; + const customChatboxInputs = ['block_width', 'num_blocks', 'rows', 'cols']; + customChatboxInputs.forEach(inputId => { + const input = document.getElementById(inputId); + if (input) { + input.disabled = useBuiltin; + if (useBuiltin) { + input.classList.add('opacity-50', 'cursor-not-allowed'); + } else { + input.classList.remove('opacity-50', 'cursor-not-allowed'); + } + } + }); + isSettingValues = false; // Re-enable auto-save } // Console management const consoleContent = document.getElementById('console-content'); +const MAX_CONSOLE_LINES = 512; +let consoleLineCount = 0; function appendToConsole(message, type = 'stdout') { const timestamp = new Date().toLocaleTimeString(); @@ -183,6 +200,28 @@ function appendToConsole(message, type = 'stdout') { lineDiv.appendChild(messageSpan); consoleContent.appendChild(lineDiv); + consoleLineCount++; + + // Remove old lines if we exceed the limit + if (consoleLineCount > MAX_CONSOLE_LINES) { + // Calculate how many lines to remove (remove 10% to avoid frequent trimming) + const linesToRemove = Math.floor(MAX_CONSOLE_LINES * 0.1); + + // Remove the oldest lines + for (let i = 0; i < linesToRemove; i++) { + if (consoleContent.firstChild) { + consoleContent.removeChild(consoleContent.firstChild); + } + } + + consoleLineCount -= linesToRemove; + + // Add a notice that lines were trimmed + const trimNotice = document.createElement('div'); + trimNotice.className = 'console-info'; + trimNotice.innerHTML = '<span class="console-timestamp">[System] </span><span class="console-info">... older lines removed to maintain performance ...</span>'; + consoleContent.insertBefore(trimNotice, consoleContent.firstChild); + } // Auto-scroll to bottom const pythonConsole = document.getElementById('python-console'); @@ -316,11 +355,30 @@ function setupEventHandlers() { } }); + // Use builtin chatbox toggle + document.getElementById('use_builtin').addEventListener('change', (e) => { + const customChatboxInputs = ['block_width', 'num_blocks', 'rows', 'cols']; + const isBuiltin = e.target.checked; + + customChatboxInputs.forEach(inputId => { + const input = document.getElementById(inputId); + if (input) { + input.disabled = isBuiltin; + if (isBuiltin) { + input.classList.add('opacity-50', 'cursor-not-allowed'); + } else { + input.classList.remove('opacity-50', 'cursor-not-allowed'); + } + } + }); + }); + // Setup virtual environment document.getElementById('setup-venv').addEventListener('click', async () => { loadingOverlay.show('Setting up virtual environment - please wait...'); // Show overlay with custom message try { await buttonManager.withButtonLoading('setupVenv', async () => { + await window.electronAPI.deleteVenvIndicatorFile(); await handleAsyncAction('Install requirements', () => window.electronAPI.installRequirements()); }); } finally { |
