feat(electron): add audio toggle to screen picker
All checks were successful
Build & Deploy / build (push) Successful in 55s
Build & Deploy / deploy (push) Successful in 6s
Build & Deploy / bump-version (push) Successful in 2s

The stream screen picker now shows a toggle switch to enable/disable
system audio capture (loopback). Defaults to on. Previously audio was
always included with no way to disable it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Daniel 2026-03-10 22:38:57 +01:00
parent 7fe9a16cd8
commit b8e4139a91

View file

@ -155,16 +155,31 @@ h2{font-size:16px;margin-bottom:12px;color:#ccc}
.item:hover{border-color:#7c5cff;transform:scale(1.03)}
.item img{width:100%;height:120px;object-fit:cover;display:block;background:#111}
.item .label{padding:8px 10px;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cancel-row{text-align:center;margin-top:14px}
.bottom-row{display:flex;align-items:center;justify-content:space-between;margin-top:14px;padding:0 4px}
.audio-toggle{display:flex;align-items:center;gap:8px;cursor:pointer;user-select:none}
.audio-toggle input{display:none}
.switch{width:36px;height:20px;background:#3a3a4e;border-radius:10px;position:relative;transition:background .2s}
.switch::after{content:'';position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#888;transition:transform .2s,background .2s}
.audio-toggle input:checked+.switch{background:#7c5cff}
.audio-toggle input:checked+.switch::after{transform:translateX(16px);background:#fff}
.audio-label{font-size:13px;color:#aaa}
.cancel-btn{background:#3a3a4e;color:#e0e0e0;border:none;padding:8px 24px;border-radius:6px;cursor:pointer;font-size:14px}
.cancel-btn:hover{background:#4a4a5e}
</style></head><body>
<h2>Bildschirm oder Fenster w\\u00e4hlen</h2>
<div class="grid" id="grid"></div>
<div class="cancel-row"><button class="cancel-btn" id="cancelBtn">Abbrechen</button></div>
<div class="bottom-row">
<label class="audio-toggle">
<input type="checkbox" id="audioToggle" checked>
<span class="switch"></span>
<span class="audio-label">\\uD83D\\uDD0A Audio mitstreamen</span>
</label>
<button class="cancel-btn" id="cancelBtn">Abbrechen</button>
</div>
<script>
const sources = ${JSON.stringify(sourceData)};
const grid = document.getElementById('grid');
const audioToggle = document.getElementById('audioToggle');
sources.forEach(s => {
const div = document.createElement('div');
div.className = 'item';
@ -176,7 +191,7 @@ sources.forEach(s => {
label.textContent = s.name;
div.appendChild(label);
div.addEventListener('click', () => {
require('electron').ipcRenderer.send('${PICKER_CHANNEL}', s.id);
require('electron').ipcRenderer.send('${PICKER_CHANNEL}', { id: s.id, audio: audioToggle.checked });
});
grid.appendChild(div);
});
@ -209,20 +224,22 @@ document.getElementById('cancelBtn').addEventListener('click', () => {
let resolved = false;
const onPickerResult = (_event, selectedId) => {
const onPickerResult = (_event, selection) => {
if (resolved) return;
resolved = true;
ipcMain.removeListener(PICKER_CHANNEL, onPickerResult);
picker.close();
try { fs.unlinkSync(tmpFile); } catch {}
if (!selectedId) {
if (!selection) {
callback({});
return;
}
const selectedId = typeof selection === 'string' ? selection : selection.id;
const withAudio = typeof selection === 'object' ? selection.audio : true;
const chosen = sources.find(s => s.id === selectedId);
if (chosen) {
callback({ video: chosen, audio: 'loopback' });
callback(withAudio ? { video: chosen, audio: 'loopback' } : { video: chosen });
} else {
callback({});
}