summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/config-schema.js11
-rw-r--r--ui/index.html50
-rw-r--r--ui/index.js16
-rw-r--r--ui/preload.js1
-rw-r--r--ui/renderer.js58
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 {