feat: add file import and prompt() methods for API key entry in OBS
OBS Browser Source lacks clipboard support, making it impractical to enter long API keys. Add two workarounds: "Import from File" reads a key from a .txt file via the native file picker, and "Paste Key" uses window.prompt() where OS-level paste should work. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
49
js/controls.js
vendored
49
js/controls.js
vendored
@@ -194,6 +194,42 @@ function initControls(manager, wsClient, components) {
|
||||
localStorage.setItem(STORAGE_API_KEY, apiKeyInput.value.trim());
|
||||
});
|
||||
|
||||
const importKeyBtn = document.getElementById('import-key-btn');
|
||||
const importKeyFile = /** @type {HTMLInputElement | null} */ (
|
||||
document.getElementById('import-key-file')
|
||||
);
|
||||
const promptKeyBtn = document.getElementById('prompt-key-btn');
|
||||
|
||||
function applyImportedKey(key) {
|
||||
if (!apiKeyInput) return;
|
||||
apiKeyInput.value = key;
|
||||
localStorage.setItem(STORAGE_API_KEY, key);
|
||||
}
|
||||
|
||||
if (importKeyBtn && importKeyFile) {
|
||||
importKeyBtn.addEventListener('click', () => {
|
||||
importKeyFile.value = '';
|
||||
importKeyFile.click();
|
||||
});
|
||||
importKeyFile.addEventListener('change', () => {
|
||||
const file = importKeyFile.files && importKeyFile.files[0];
|
||||
if (!file) return;
|
||||
var reader = new FileReader();
|
||||
reader.onload = function () {
|
||||
var text = typeof reader.result === 'string' ? reader.result.trim() : '';
|
||||
if (text) applyImportedKey(text);
|
||||
};
|
||||
reader.readAsText(file);
|
||||
});
|
||||
}
|
||||
|
||||
if (promptKeyBtn) {
|
||||
promptKeyBtn.addEventListener('click', () => {
|
||||
var key = window.prompt('Paste or type your API key:');
|
||||
if (key && key.trim()) applyImportedKey(key.trim());
|
||||
});
|
||||
}
|
||||
|
||||
const volumeSlider = document.getElementById('volume-slider');
|
||||
const volumeValue = document.getElementById('volume-value');
|
||||
const themeSound = /** @type {HTMLAudioElement | null} */ (
|
||||
@@ -340,22 +376,25 @@ function initConnectionStatusHandler() {
|
||||
const wsDisconnectRow = document.getElementById('ws-disconnect-row');
|
||||
const apiUrlInput = document.getElementById('api-url-input');
|
||||
const apiKeyInput = document.getElementById('api-key-input');
|
||||
const importKeyBtn = document.getElementById('import-key-btn');
|
||||
const promptKeyBtn = document.getElementById('prompt-key-btn');
|
||||
|
||||
return (state, message) => {
|
||||
if (wsStatusDot) wsStatusDot.className = `status-dot ${state}`;
|
||||
if (wsStatusText) wsStatusText.textContent = message ?? String(state);
|
||||
|
||||
if (state === 'connected') {
|
||||
var isConnected = state === 'connected';
|
||||
if (isConnected) {
|
||||
if (wsConnectBtn) wsConnectBtn.style.display = 'none';
|
||||
if (wsDisconnectRow) wsDisconnectRow.style.display = 'flex';
|
||||
if (apiUrlInput) apiUrlInput.disabled = true;
|
||||
if (apiKeyInput) apiKeyInput.disabled = true;
|
||||
} else {
|
||||
if (wsConnectBtn) wsConnectBtn.style.display = 'block';
|
||||
if (wsDisconnectRow) wsDisconnectRow.style.display = 'none';
|
||||
if (apiUrlInput) apiUrlInput.disabled = false;
|
||||
if (apiKeyInput) apiKeyInput.disabled = false;
|
||||
}
|
||||
if (apiUrlInput) apiUrlInput.disabled = isConnected;
|
||||
if (apiKeyInput) apiKeyInput.disabled = isConnected;
|
||||
if (importKeyBtn) importKeyBtn.disabled = isConnected;
|
||||
if (promptKeyBtn) promptKeyBtn.disabled = isConnected;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -764,6 +764,11 @@
|
||||
<div class="control-row">
|
||||
<input type="password" id="api-key-input" placeholder="Enter API key">
|
||||
</div>
|
||||
<div class="control-row" style="gap: 6px;">
|
||||
<button id="import-key-btn" title="Import API key from a .txt file">Import from File</button>
|
||||
<button id="prompt-key-btn" title="Enter API key via dialog (paste works)">Paste Key</button>
|
||||
<input type="file" id="import-key-file" accept=".txt,.key" style="display: none;">
|
||||
</div>
|
||||
<div class="control-row">
|
||||
<button id="ws-connect-btn">Connect</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user