diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 18917c9..617cccf 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -4,7 +4,7 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -import { app, desktopCapturer, dialog, ipcMain, session, shell } from "electron"; +import { app, dialog, ipcMain, session, shell } from "electron"; import { existsSync, readFileSync, watch } from "fs"; import { open, readFile } from "fs/promises"; import { join } from "path"; @@ -75,8 +75,6 @@ ipcMain.handle(IpcEvents.SPELLCHECK_SET_LANGUAGES, (_, languages: string[]) => { if (applicable.length) ses.setSpellCheckerLanguages(applicable); }); -ipcMain.handle(IpcEvents.CAPTURER_GET_SOURCES, (_, options) => desktopCapturer.getSources(options)); - ipcMain.handle(IpcEvents.SELECT_VENCORD_DIR, async () => { const res = await dialog.showOpenDialog(mainWin!, { properties: ["openDirectory"] diff --git a/src/main/screenShare.ts b/src/main/screenShare.ts index d0bdc1e..b2ab69e 100644 --- a/src/main/screenShare.ts +++ b/src/main/screenShare.ts @@ -4,9 +4,22 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -import { desktopCapturer, session } from "electron"; +import { desktopCapturer, ipcMain, session, Streams } from "electron"; +import type { StreamPick } from "renderer/components/ScreenSharePicker"; +import { IpcEvents } from "shared/IpcEvents"; export function registerScreenShareHandler() { + ipcMain.handle(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, async (_, id: string) => { + const sources = await desktopCapturer.getSources({ + types: ["window", "screen"], + thumbnailSize: { + width: 1920, + height: 1080 + } + }); + return sources.find(s => s.id === id)?.thumbnail.toDataURL(); + }); + session.defaultSession.setDisplayMediaRequestHandler(async (request, callback) => { const sources = await desktopCapturer.getSources({ types: ["window", "screen"], @@ -24,17 +37,19 @@ export function registerScreenShareHandler() { const choice = await request.frame .executeJavaScript(`VencordDesktop.Components.ScreenShare.openScreenSharePicker(${JSON.stringify(data)})`) - .catch(() => "cancelled"); + .then(e => e as StreamPick) + .catch(() => null); - if (choice === "cancelled") { - callback({}); - return; - } + if (!choice) return callback({}); - const source = sources.find(s => s.id === choice); - callback({ - video: source, - audio: "loopback" - }); + const source = sources.find(s => s.id === choice.id); + if (!source) return callback({}); + + const streams: Streams = { + video: source + }; + if (choice.audio) streams.audio = "loopback"; + + callback(streams); }); } diff --git a/src/preload/VencordDesktopNative.ts b/src/preload/VencordDesktopNative.ts index 61dd2a0..2e56324 100644 --- a/src/preload/VencordDesktopNative.ts +++ b/src/preload/VencordDesktopNative.ts @@ -4,7 +4,6 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -import type { DesktopCapturerSource, SourcesOptions } from "electron"; import type { Settings } from "shared/settings"; import type { LiteralUnion } from "type-fest"; @@ -37,13 +36,6 @@ export const VencordDesktopNative = { focus: () => invoke(IpcEvents.FOCUS) }, capturer: { - getSources: async (options?: SourcesOptions) => { - const res = await invoke(IpcEvents.CAPTURER_GET_SOURCES, options); - return res.map(({ id, name, thumbnail }) => ({ - id, - name, - url: thumbnail.toDataURL() - })); - } + getLargeThumbnail: (id: string) => invoke(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id) } }; diff --git a/src/renderer/components/ScreenSharePicker.tsx b/src/renderer/components/ScreenSharePicker.tsx index bea0e7c..876c181 100644 --- a/src/renderer/components/ScreenSharePicker.tsx +++ b/src/renderer/components/ScreenSharePicker.tsx @@ -6,9 +6,9 @@ import "./screenSharePicker.css"; -import { Modals, openModal } from "@vencord/types/utils"; +import { closeModal, Modals, openModal, useAwaiter } from "@vencord/types/utils"; import { Button, Card, Forms, Switch, Text, useState } from "@vencord/types/webpack/common"; -import { Dispatch, SetStateAction } from "react"; +import type { Dispatch, SetStateAction } from "react"; const StreamResolutions = ["720", "1080", "1440", "Source"] as const; const StreamFps = ["15", "30", "60"] as const; @@ -22,6 +22,10 @@ interface StreamSettings { audio: boolean; } +export interface StreamPick extends StreamSettings { + id: string; +} + interface Source { id: string; name: string; @@ -29,18 +33,26 @@ interface Source { } export function openScreenSharePicker(screens: Source[]) { - return new Promise((resolve, reject) => { - openModal(props => ( - { - props.onClose(); - reject(new Error("Aborted")); - }} - /> - )); + return new Promise((resolve, reject) => { + const key = openModal( + props => ( + { + props.onClose(); + reject("Aborted"); + }} + /> + ), + { + onCloseRequest() { + closeModal(key); + reject("Aborted"); + } + } + ); }); } @@ -68,11 +80,16 @@ function StreamSettings({ settings: StreamSettings; setSettings: Dispatch>; }) { + const [thumb] = useAwaiter(() => VencordDesktopNative.capturer.getLargeThumbnail(source.id), { + fallbackValue: source.url, + deps: [source.id] + }); + return (
What you're streaming - + {source.name} @@ -85,7 +102,7 @@ function StreamSettings({
{StreamResolutions.map(res => (