Fix and simplify screen sharing

This commit is contained in:
Robin
2025-11-12 15:02:19 -05:00
parent 27b76b4b1d
commit a62d8368a1
3 changed files with 28 additions and 63 deletions

View File

@@ -734,8 +734,7 @@ export const InCallView: FC<InCallViewProps> = ({
<ShareScreenButton <ShareScreenButton
key="share_screen" key="share_screen"
className={styles.shareScreen} className={styles.shareScreen}
disabled={sharingScreen === undefined} enabled={sharingScreen}
enabled={sharingScreen === true}
onClick={vm.toggleScreenSharing} onClick={vm.toggleScreenSharing}
onTouchEnd={onControlsTouchEnd} onTouchEnd={onControlsTouchEnd}
data-testid="incall_screenshare" data-testid="incall_screenshare"

View File

@@ -1275,8 +1275,7 @@ export class CallViewModel {
public readonly sharingScreen$ = this.localMembership.sharingScreen$; public readonly sharingScreen$ = this.localMembership.sharingScreen$;
/** /**
* Callback for toggling screen sharing. If null, screen sharing is not * Callback to toggle screen sharing. If null, screen sharing is not possible.
* available.
*/ */
// reassigned here to make it publicly accessible // reassigned here to make it publicly accessible
public readonly toggleScreenSharing = public readonly toggleScreenSharing =

View File

@@ -25,14 +25,11 @@ import {
combineLatest, combineLatest,
fromEvent, fromEvent,
map, map,
NEVER,
type Observable, type Observable,
of, of,
scan, scan,
startWith, startWith,
switchMap, switchMap,
take,
takeWhile,
} from "rxjs"; } from "rxjs";
import { logger } from "matrix-js-sdk/lib/logger"; import { logger } from "matrix-js-sdk/lib/logger";
@@ -144,8 +141,10 @@ export const createLocalMembership$ = ({
startTracks: () => Behavior<LocalTrack[]>; startTracks: () => Behavior<LocalTrack[]>;
requestDisconnect: () => Observable<LocalMemberLivekitState> | null; requestDisconnect: () => Observable<LocalMemberLivekitState> | null;
connectionState: LocalMemberConnectionState; connectionState: LocalMemberConnectionState;
// Use null here since behavior cannot be initialised with undefined. sharingScreen$: Behavior<boolean>;
sharingScreen$: Behavior<boolean | null>; /**
* Callback to toggle screen sharing. If null, screen sharing is not possible.
*/
toggleScreenSharing: (() => void) | null; toggleScreenSharing: (() => void) | null;
participant$: Behavior<LocalParticipant | null>; participant$: Behavior<LocalParticipant | null>;
connection$: Behavior<Connection | null>; connection$: Behavior<Connection | null>;
@@ -453,72 +452,40 @@ export const createLocalMembership$ = ({
}); });
/** /**
* Returns undefined if scrennSharing is not yet ready. * Whether the user is currently sharing their screen.
*/ */
const sharingScreen$ = scope.behavior( const sharingScreen$ = scope.behavior(
connection$.pipe( connection$.pipe(
switchMap((c) => { switchMap((c) =>
if (!c) return of(null); c === null
if (c.state$.value.state === "ConnectedToLkRoom") ? of(false)
return observeSharingScreen$(c.livekitRoom.localParticipant); : observeSharingScreen$(c.livekitRoom.localParticipant),
return of(false); ),
}),
), ),
null,
); );
const toggleScreenSharing = const toggleScreenSharing =
"getDisplayMedia" in (navigator.mediaDevices ?? {}) && "getDisplayMedia" in (navigator.mediaDevices ?? {}) &&
!getUrlParams().hideScreensharing !getUrlParams().hideScreensharing
? (): void => ? (): void =>
// If a connection is ready... // If a connection is ready, toggle screen sharing.
void connection$ // We deliberately do nothing in the case of a null connection because
.pipe( // it looks nice for the call control buttons to all become available
// I dont see why we need this. isnt the check later on superseeding it? // at once upon joining the call, rather than introducing a disabled
takeWhile( // state. The user can just click again.
(c) => c !== null && c.state$.value.state !== "FailedToStart", // We also allow screen sharing to be toggled even if the connection
), // is still initializing or publishing tracks, because there's no
switchMap((c) => // technical reason to disallow this. LiveKit will publish if it can.
c?.state$.value.state === "ConnectedToLkRoom" ? of(c) : NEVER, void connection$.value?.livekitRoom.localParticipant
), .setScreenShareEnabled(!sharingScreen$.value, {
take(1), audio: true,
scope.bind(), selfBrowserSurface: "include",
) surfaceSwitching: "include",
// ...toggle screen sharing. systemAudio: "include",
.subscribe( })
(c) => .catch(logger.error)
void c.livekitRoom.localParticipant
.setScreenShareEnabled(!sharingScreen$.value, {
audio: true,
selfBrowserSurface: "include",
surfaceSwitching: "include",
systemAudio: "include",
})
.catch(logger.error),
)
: null; : null;
// we do not need all the auto waiting since we can just check via sharingScreen$.value !== undefined
let alternativeScreenshareToggle: (() => void) | null = null;
if (
"getDisplayMedia" in (navigator.mediaDevices ?? {}) &&
!getUrlParams().hideScreensharing
) {
alternativeScreenshareToggle = (): void =>
void connection$.value?.livekitRoom.localParticipant
.setScreenShareEnabled(!sharingScreen$.value, {
audio: true,
selfBrowserSurface: "include",
surfaceSwitching: "include",
systemAudio: "include",
})
.catch(logger.error);
}
logger.log(
"alternativeScreenshareToggle so that it is used",
alternativeScreenshareToggle,
);
const participant$ = scope.behavior( const participant$ = scope.behavior(
connection$.pipe(map((c) => c?.livekitRoom.localParticipant ?? null)), connection$.pipe(map((c) => c?.livekitRoom.localParticipant ?? null)),
); );