mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-25 07:16:02 +00:00
fix(linux/wayland): address PR review feedback
- electron/main.ts: treat missing sourceId on linux as portal sentinel so the request handler never calls getSources() (which itself opens an extra portal dialog) on fresh sessions. - useScreenRecorder.ts: persist the synthesized portal sentinel via selectSource() so main has the source set before getDisplayMedia. Extract acquireLinuxPortalStream() helper to dedupe the three duplicated getDisplayMedia constraint blocks. - LaunchWindow.tsx: hide the screen-source selector button (and its separator) on Linux so users cannot trigger an extra portal dialog via the dropdown.
This commit is contained in:
+6
-1
@@ -900,8 +900,13 @@ app.whenReady().then(async () => {
|
||||
// is set we skip getSources entirely and hand back a synthetic
|
||||
// source id; Chromium then opens the portal once to actually
|
||||
// resolve the capture.
|
||||
// Default to the sentinel on Linux when no source has been
|
||||
// pre-selected (e.g. fresh session where the renderer skipped the
|
||||
// source picker entirely). This avoids calling getSources() which
|
||||
// would itself trigger an extra portal dialog.
|
||||
const isLinuxPortalSentinel =
|
||||
process.platform === "linux" && sourceId === "screen:linux-portal";
|
||||
process.platform === "linux" &&
|
||||
(sourceId === "screen:linux-portal" || !sourceId);
|
||||
if (isLinuxPortalSentinel) {
|
||||
callback({ video: { id: "screen:0:0", name: "Entire screen" } });
|
||||
return;
|
||||
|
||||
@@ -1093,23 +1093,27 @@ export function LaunchWindow() {
|
||||
|
||||
const idleControls = (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
className={`${styles.screenSel} ${styles.electronNoDrag}`}
|
||||
onClick={() => toggleDropdown("sources")}
|
||||
title={selectedSource}
|
||||
>
|
||||
<Monitor size={16} />
|
||||
<ContentClamp className={styles.sourceLabel} truncateLength={36}>
|
||||
{selectedSource}
|
||||
</ContentClamp>
|
||||
<ChevronUp
|
||||
size={10}
|
||||
className={`text-[#6b6b78] ml-0.5 transition-transform duration-200 ${activeDropdown === "sources" ? "" : "rotate-180"}`}
|
||||
/>
|
||||
</button>
|
||||
{platform !== "linux" && (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
className={`${styles.screenSel} ${styles.electronNoDrag}`}
|
||||
onClick={() => toggleDropdown("sources")}
|
||||
title={selectedSource}
|
||||
>
|
||||
<Monitor size={16} />
|
||||
<ContentClamp className={styles.sourceLabel} truncateLength={36}>
|
||||
{selectedSource}
|
||||
</ContentClamp>
|
||||
<ChevronUp
|
||||
size={10}
|
||||
className={`text-[#6b6b78] ml-0.5 transition-transform duration-200 ${activeDropdown === "sources" ? "" : "rotate-180"}`}
|
||||
/>
|
||||
</button>
|
||||
|
||||
<Separator />
|
||||
<Separator />
|
||||
</>
|
||||
)}
|
||||
|
||||
<IconButton
|
||||
onClick={toggleMicrophone}
|
||||
|
||||
@@ -846,6 +846,16 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
alert("Please select a source to record");
|
||||
return;
|
||||
}
|
||||
// Persist the synthetic Linux portal sentinel to main so that the
|
||||
// setDisplayMediaRequestHandler can short-circuit getSources() and
|
||||
// avoid triggering an extra portal dialog.
|
||||
if (!existingSource && selectedSource.id === "screen:linux-portal") {
|
||||
try {
|
||||
await window.electronAPI.selectSource(selectedSource);
|
||||
} catch (err) {
|
||||
console.warn("Failed to persist Linux portal sentinel source:", err);
|
||||
}
|
||||
}
|
||||
|
||||
const permissionsReady = await preparePermissions();
|
||||
if (!permissionsReady) {
|
||||
@@ -1031,22 +1041,24 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
if (wantsAudioCapture) {
|
||||
let screenMediaStream: MediaStream;
|
||||
const useLinuxPortal = selectedSource.id === "screen:linux-portal";
|
||||
const acquireLinuxPortalStream = (withAudio: boolean) =>
|
||||
mediaDevices.getDisplayMedia({
|
||||
audio: withAudio,
|
||||
video: {
|
||||
displaySurface: "monitor",
|
||||
width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH },
|
||||
height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT },
|
||||
frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE },
|
||||
cursor: "never",
|
||||
},
|
||||
selfBrowserSurface: "exclude",
|
||||
surfaceSwitching: "exclude",
|
||||
});
|
||||
|
||||
if (systemAudioEnabled) {
|
||||
try {
|
||||
screenMediaStream = useLinuxPortal
|
||||
? await mediaDevices.getDisplayMedia({
|
||||
audio: true,
|
||||
video: {
|
||||
displaySurface: "monitor",
|
||||
width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH },
|
||||
height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT },
|
||||
frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE },
|
||||
cursor: "never",
|
||||
},
|
||||
selfBrowserSurface: "exclude",
|
||||
surfaceSwitching: "exclude",
|
||||
})
|
||||
? await acquireLinuxPortalStream(true)
|
||||
: await mediaDevices.getUserMedia({
|
||||
audio: {
|
||||
mandatory: {
|
||||
@@ -1065,18 +1077,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
"System audio is not available for this source. Recording will continue without system audio.",
|
||||
);
|
||||
screenMediaStream = useLinuxPortal
|
||||
? await mediaDevices.getDisplayMedia({
|
||||
audio: false,
|
||||
video: {
|
||||
displaySurface: "monitor",
|
||||
width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH },
|
||||
height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT },
|
||||
frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE },
|
||||
cursor: "never",
|
||||
},
|
||||
selfBrowserSurface: "exclude",
|
||||
surfaceSwitching: "exclude",
|
||||
})
|
||||
? await acquireLinuxPortalStream(false)
|
||||
: await mediaDevices.getUserMedia({
|
||||
audio: false,
|
||||
video: browserScreenVideoConstraints,
|
||||
@@ -1084,18 +1085,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
|
||||
}
|
||||
} else {
|
||||
screenMediaStream = useLinuxPortal
|
||||
? await mediaDevices.getDisplayMedia({
|
||||
audio: false,
|
||||
video: {
|
||||
displaySurface: "monitor",
|
||||
width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH },
|
||||
height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT },
|
||||
frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE },
|
||||
cursor: "never",
|
||||
},
|
||||
selfBrowserSurface: "exclude",
|
||||
surfaceSwitching: "exclude",
|
||||
})
|
||||
? await acquireLinuxPortalStream(false)
|
||||
: await mediaDevices.getUserMedia({
|
||||
audio: false,
|
||||
video: browserScreenVideoConstraints,
|
||||
|
||||
Reference in New Issue
Block a user