feat: Discord widget — embedded Discord web with voice + screen share - #118
Merged
Merged
Conversation
Embeds the real discord.com web app in an Electron <webview> on a dedicated persist:discord partition — servers, DMs, replying, voice channels, and screen share with an in-widget source picker, with zero API keys or Discord app setup (official APIs can't do user-account features; self-bots risk a ToS ban). Main-side plumbing (apps/main/src/discord.ts): clean-Chrome UA on the partition, permission request+check handlers scoped to *.discord.com, setDisplayMediaRequestHandler -> desktopCapturer picker over discord:* IPC (Windows-only loopback system audio), and an app-wide will-attach-webview guard (https discord.com only, preload/node stripped) now that webviewTag is enabled on the main + popout windows. WidgetShell grows an opt-in keepMounted prop: collapsing Discord hides the body in an h-0 wrapper instead of unmounting, so voice keeps running (display:none would kill the guest). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
<webview>on a dedicatedpersist:discordpartition — servers, DMs & group chats, replying, voice channels, and screen sharing with an in-widget screens/windows picker. Zero setup: no Discord application, no keys — log in once inside the widget; the session survives restarts.Main-process plumbing (
apps/main/src/discord.ts)persist:discordsession: full clean-Chrome UA (theNishboard/xapp token alone trips Discord's unsupported-browser wall) + permission request and check handlers (Discord gates notifications on the syncNotification.permissionread), scoped to*.discord.com.setDisplayMediaRequestHandler→desktopCapturersources cross as data-URI thumbnails (discord:screenshare-*IPC, subscribe-while-mounted lifecycle, 60s deny timeout). Windows-only system audio viaaudio: 'loopback'; macOS shares video-only.webviewTag: trueon main + popout windows, gated by an app-widewill-attach-webviewguard (https*.discord.comsrc only, URL-parsed — lookalike hosts rejected; preload/nodeIntegration stripped). Guestwindow.open/off-site navigations open the system browser.Renderer
(N), Home/Reload/Sign-out header actions (sign-out clears the partition after an in-body confirm).WidgetShellgrows opt-inkeepMounted: collapsing Discord hides the body in anh-0 overflow-hiddenwrapper instead of unmounting — voice keeps running (display:nonekills a webview guest).mac.extendInfomic/camera usage strings (TCC would silently deny voice).Tests
apps/main/src/discord.test.ts: UA shape, URL allowlist (incl.discord.com.evil.comrejection), permission matrix, capturer-source serialization.apps/renderer/.../lib.test.ts: title-badge parsing. Electron stub grewsession/desktopCapturer/app.on.pnpm test/typecheck/lintgreen; dev boot smoke-tested.Known caveats (documented in CLAUDE.md)
(N)title prefix).Manual verification checklist (needs a logged-in account)
🤖 Generated with Claude Code