feat: Add webcam basic support

This commit is contained in:
2026-03-30 03:10:44 +02:00
parent 727059fb52
commit b7d4bf20e3
40 changed files with 1042 additions and 296 deletions

View File

@@ -1067,6 +1067,8 @@ export class RoomsEffects {
return this.handleVoiceChannelMove(event, currentRoom, savedRooms, currentUser ?? null);
case 'screen-state':
return currentRoom ? this.handleVoiceOrScreenState(event, allUsers, currentUser ?? null, 'screen') : EMPTY;
case 'camera-state':
return currentRoom ? this.handleVoiceOrScreenState(event, allUsers, currentUser ?? null, 'camera') : EMPTY;
case 'server-state-request':
return this.handleServerStateRequest(event, currentRoom, savedRooms);
case 'server-state-full':
@@ -1091,7 +1093,12 @@ export class RoomsEffects {
)
);
private handleVoiceOrScreenState(event: ChatEvent, allUsers: User[], currentUser: User | null, kind: 'voice' | 'screen') {
private handleVoiceOrScreenState(
event: ChatEvent,
allUsers: User[],
currentUser: User | null,
kind: 'voice' | 'screen' | 'camera'
) {
const userId: string | undefined = event.fromPeerId ?? event.oderId;
if (!userId)
@@ -1157,10 +1164,35 @@ export class RoomsEffects {
voiceState: vs }));
}
// screen-state
const isSharing = event.isScreenSharing as boolean | undefined;
if (kind === 'screen') {
const isSharing = event.isScreenSharing as boolean | undefined;
if (isSharing === undefined)
if (isSharing === undefined)
return EMPTY;
if (!userExists) {
return of(
UsersActions.userJoined({
user: buildSignalingUser(
{ oderId: userId,
displayName: event.displayName || 'User' },
{ screenShareState: { isSharing } }
)
})
);
}
return of(
UsersActions.updateScreenShareState({
userId,
screenShareState: { isSharing }
})
);
}
const isCameraEnabled = event.isCameraEnabled as boolean | undefined;
if (isCameraEnabled === undefined)
return EMPTY;
if (!userExists) {
@@ -1169,16 +1201,16 @@ export class RoomsEffects {
user: buildSignalingUser(
{ oderId: userId,
displayName: event.displayName || 'User' },
{ screenShareState: { isSharing } }
{ cameraState: { isEnabled: isCameraEnabled } }
)
})
);
}
return of(
UsersActions.updateScreenShareState({
UsersActions.updateCameraState({
userId,
screenShareState: { isSharing }
cameraState: { isEnabled: isCameraEnabled }
})
);
}

View File

@@ -10,7 +10,8 @@ import {
User,
BanEntry,
VoiceState,
ScreenShareState
ScreenShareState,
CameraState
} from '../../shared-kernel';
export const UsersActions = createActionGroup({
@@ -52,6 +53,7 @@ export const UsersActions = createActionGroup({
'Update Host': props<{ userId: string }>(),
'Update Voice State': props<{ userId: string; voiceState: Partial<VoiceState> }>(),
'Update Screen Share State': props<{ userId: string; screenShareState: Partial<ScreenShareState> }>()
'Update Screen Share State': props<{ userId: string; screenShareState: Partial<ScreenShareState> }>(),
'Update Camera State': props<{ userId: string; cameraState: Partial<CameraState> }>()
}
});

View File

@@ -212,6 +212,23 @@ export const usersReducer = createReducer(
state
);
}),
on(UsersActions.updateCameraState, (state, { userId, cameraState }) => {
const prev = state.entities[userId]?.cameraState || {
isEnabled: false
};
return usersAdapter.updateOne(
{
id: userId,
changes: {
cameraState: {
isEnabled: cameraState.isEnabled ?? prev.isEnabled
}
}
},
state
);
}),
on(UsersActions.syncUsers, (state, { users }) =>
usersAdapter.upsertMany(users, state)
),