fix: Improve plugin ui entry points, Fix chat scroll, fix notifications, fix user rights
This commit is contained in:
@@ -20,9 +20,10 @@ import type {
|
||||
} from '../../shared-kernel';
|
||||
import { RealtimeSessionFacade } from '../../core/realtime';
|
||||
import { UsersActions } from '../users/users.actions';
|
||||
import { selectCurrentUser } from '../users/users.selectors';
|
||||
import { selectAllUsers, selectCurrentUser } from '../users/users.selectors';
|
||||
import { RoomsActions } from './rooms.actions';
|
||||
import { selectCurrentRoom, selectSavedRooms } from './rooms.selectors';
|
||||
import { normalizeRoomAccessControl, resolveLegacyRole } from '../../domains/access-control';
|
||||
import {
|
||||
areRoomMembersEqual,
|
||||
findRoomMember,
|
||||
@@ -113,6 +114,40 @@ export class RoomMembersSyncEffects {
|
||||
)
|
||||
);
|
||||
|
||||
/** Keep active-room user roles derived from room access-control assignments. */
|
||||
syncAccessControlRolesIntoUsers$ = createEffect(() =>
|
||||
this.actions$.pipe(
|
||||
ofType(
|
||||
RoomsActions.createRoomSuccess,
|
||||
RoomsActions.joinRoomSuccess,
|
||||
RoomsActions.viewServerSuccess,
|
||||
RoomsActions.updateRoom
|
||||
),
|
||||
withLatestFrom(
|
||||
this.store.select(selectCurrentRoom),
|
||||
this.store.select(selectSavedRooms),
|
||||
this.store.select(selectAllUsers),
|
||||
this.store.select(selectCurrentUser)
|
||||
),
|
||||
mergeMap(([
|
||||
action,
|
||||
currentRoom,
|
||||
savedRooms,
|
||||
allUsers,
|
||||
currentUser
|
||||
]) => {
|
||||
const room = this.resolveRoleSyncRoom(action, currentRoom, savedRooms);
|
||||
|
||||
if (!room)
|
||||
return EMPTY;
|
||||
|
||||
const actions = this.createUserRoleSyncActions(room, allUsers, currentUser ?? null);
|
||||
|
||||
return actions.length > 0 ? actions : EMPTY;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
/** Update persisted room rosters when signaling presence changes arrive. */
|
||||
signalingPresenceIntoRoomMembers$ = createEffect(() =>
|
||||
this.webrtc.onSignalingMessage.pipe(
|
||||
@@ -342,6 +377,88 @@ export class RoomMembersSyncEffects {
|
||||
: [RoomsActions.updateRoom({ roomId: room.id, changes: { members } })];
|
||||
}
|
||||
|
||||
private resolveRoleSyncRoom(
|
||||
action:
|
||||
| ReturnType<typeof RoomsActions.createRoomSuccess>
|
||||
| ReturnType<typeof RoomsActions.joinRoomSuccess>
|
||||
| ReturnType<typeof RoomsActions.viewServerSuccess>
|
||||
| ReturnType<typeof RoomsActions.updateRoom>,
|
||||
currentRoom: Room | null,
|
||||
savedRooms: Room[]
|
||||
): Room | null {
|
||||
if ('room' in action) {
|
||||
return normalizeRoomAccessControl(action.room);
|
||||
}
|
||||
|
||||
if (currentRoom?.id !== action.roomId || !this.hasRoleRelevantRoomChanges(action.changes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const room = this.resolveRoom(action.roomId, currentRoom, savedRooms);
|
||||
|
||||
return room ? normalizeRoomAccessControl({ ...room, ...action.changes }) : null;
|
||||
}
|
||||
|
||||
private hasRoleRelevantRoomChanges(changes: Partial<Room>): boolean {
|
||||
return (
|
||||
Object.prototype.hasOwnProperty.call(changes, 'hostId') ||
|
||||
Object.prototype.hasOwnProperty.call(changes, 'members') ||
|
||||
Object.prototype.hasOwnProperty.call(changes, 'permissions') ||
|
||||
Object.prototype.hasOwnProperty.call(changes, 'roles') ||
|
||||
Object.prototype.hasOwnProperty.call(changes, 'roleAssignments') ||
|
||||
Object.prototype.hasOwnProperty.call(changes, 'channelPermissions') ||
|
||||
Object.prototype.hasOwnProperty.call(changes, 'slowModeInterval')
|
||||
);
|
||||
}
|
||||
|
||||
private createUserRoleSyncActions(room: Room, allUsers: User[], currentUser: User | null): Action[] {
|
||||
const usersById = new Map<string, User>();
|
||||
|
||||
for (const user of allUsers) {
|
||||
if (this.shouldSyncUserRoleForRoom(room, user, currentUser)) {
|
||||
usersById.set(user.id, user);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentUser) {
|
||||
usersById.set(currentUser.id, currentUser);
|
||||
}
|
||||
|
||||
return Array.from(usersById.values())
|
||||
.map((user) => ({
|
||||
user,
|
||||
role: resolveLegacyRole(room, user)
|
||||
}))
|
||||
.filter(({ user, role }) => user.role !== role)
|
||||
.map(({ user, role }) => UsersActions.updateUserRole({ userId: user.id,
|
||||
role }));
|
||||
}
|
||||
|
||||
private shouldSyncUserRoleForRoom(room: Room, user: User, currentUser: User | null): boolean {
|
||||
if (currentUser && user.id === currentUser.id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (room.hostId === user.id || room.hostId === user.oderId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Array.isArray(user.presenceServerIds) && user.presenceServerIds.includes(room.id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (findRoomMember(room.members ?? [], user.oderId || user.id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (room.roleAssignments ?? []).some((assignment) => (
|
||||
assignment.userId === user.id ||
|
||||
assignment.userId === user.oderId ||
|
||||
assignment.oderId === user.id ||
|
||||
assignment.oderId === user.oderId
|
||||
));
|
||||
}
|
||||
|
||||
private handleMemberRosterRequest(
|
||||
event: ChatEvent,
|
||||
currentRoom: Room | null,
|
||||
|
||||
Reference in New Issue
Block a user