mirror of
				https://github.com/cinnyapp/cinny.git
				synced 2025-11-04 06:20:28 +03:00 
			
		
		
		
	improve parent selection when opening a room (#2388)
when a room has more than one orphan parent, we will select parent which has highest number of special users who have special powers in selected room.
This commit is contained in:
		
							parent
							
								
									6b81401e2d
								
							
						
					
					
						commit
						fbd7e0a14b
					
				
					 2 changed files with 53 additions and 12 deletions
				
			
		| 
						 | 
				
			
			@ -9,7 +9,7 @@ import {
 | 
			
		|||
  getSpaceRoomPath,
 | 
			
		||||
} from '../pages/pathUtils';
 | 
			
		||||
import { useMatrixClient } from './useMatrixClient';
 | 
			
		||||
import { getOrphanParents } from '../utils/room';
 | 
			
		||||
import { getOrphanParents, guessPerfectParent } from '../utils/room';
 | 
			
		||||
import { roomToParentsAtom } from '../state/room/roomToParents';
 | 
			
		||||
import { mDirectAtom } from '../state/mDirectList';
 | 
			
		||||
import { useSelectedSpace } from './router/useSelectedSpace';
 | 
			
		||||
| 
						 | 
				
			
			@ -39,19 +39,19 @@ export const useRoomNavigate = () => {
 | 
			
		|||
 | 
			
		||||
      const orphanParents = openSpaceTimeline ? [roomId] : getOrphanParents(roomToParents, roomId);
 | 
			
		||||
      if (orphanParents.length > 0) {
 | 
			
		||||
        const pSpaceIdOrAlias = getCanonicalAliasOrRoomId(
 | 
			
		||||
          mx,
 | 
			
		||||
          spaceSelectedId && orphanParents.includes(spaceSelectedId)
 | 
			
		||||
            ? spaceSelectedId
 | 
			
		||||
            : orphanParents[0] // TODO: better orphan parent selection.
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (openSpaceTimeline) {
 | 
			
		||||
          navigate(getSpaceRoomPath(pSpaceIdOrAlias, roomId, eventId), opts);
 | 
			
		||||
          return;
 | 
			
		||||
        let parentSpace: string;
 | 
			
		||||
        if (spaceSelectedId && orphanParents.includes(spaceSelectedId)) {
 | 
			
		||||
          parentSpace = spaceSelectedId;
 | 
			
		||||
        } else {
 | 
			
		||||
          parentSpace = guessPerfectParent(mx, roomId, orphanParents) ?? orphanParents[0];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        navigate(getSpaceRoomPath(pSpaceIdOrAlias, roomIdOrAlias, eventId), opts);
 | 
			
		||||
        const pSpaceIdOrAlias = getCanonicalAliasOrRoomId(mx, parentSpace);
 | 
			
		||||
 | 
			
		||||
        navigate(
 | 
			
		||||
          getSpaceRoomPath(pSpaceIdOrAlias, openSpaceTimeline ? roomId : roomIdOrAlias, eventId),
 | 
			
		||||
          opts
 | 
			
		||||
        );
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import {
 | 
			
		|||
  EventTimelineSet,
 | 
			
		||||
  EventType,
 | 
			
		||||
  IMentions,
 | 
			
		||||
  IPowerLevelsContent,
 | 
			
		||||
  IPushRule,
 | 
			
		||||
  IPushRules,
 | 
			
		||||
  JoinRule,
 | 
			
		||||
| 
						 | 
				
			
			@ -473,3 +474,43 @@ export const bannedInRooms = (mx: MatrixClient, rooms: string[], otherUserId: st
 | 
			
		|||
    const banned = room.hasMembershipState(otherUserId, Membership.Ban);
 | 
			
		||||
    return banned;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
export const guessPerfectParent = (
 | 
			
		||||
  mx: MatrixClient,
 | 
			
		||||
  roomId: string,
 | 
			
		||||
  parents: string[]
 | 
			
		||||
): string | undefined => {
 | 
			
		||||
  if (parents.length === 1) {
 | 
			
		||||
    return parents[0];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const getSpecialUsers = (rId: string): string[] => {
 | 
			
		||||
    const r = mx.getRoom(rId);
 | 
			
		||||
    const powerLevels =
 | 
			
		||||
      r && getStateEvent(r, StateEvent.RoomPowerLevels)?.getContent<IPowerLevelsContent>();
 | 
			
		||||
 | 
			
		||||
    const { users_default: usersDefault, users } = powerLevels ?? {};
 | 
			
		||||
    if (typeof users !== 'object') return [];
 | 
			
		||||
 | 
			
		||||
    const defaultPower = typeof usersDefault === 'number' ? usersDefault : 0;
 | 
			
		||||
    return Object.keys(users).filter((userId) => users[userId] > defaultPower);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let perfectParent: string | undefined;
 | 
			
		||||
  let score = 0;
 | 
			
		||||
 | 
			
		||||
  const roomSpecialUsers = getSpecialUsers(roomId);
 | 
			
		||||
  parents.forEach((parentId) => {
 | 
			
		||||
    const parentSpecialUsers = getSpecialUsers(parentId);
 | 
			
		||||
    const matchedUsersCount = parentSpecialUsers.filter((userId) =>
 | 
			
		||||
      roomSpecialUsers.includes(userId)
 | 
			
		||||
    ).length;
 | 
			
		||||
 | 
			
		||||
    if (matchedUsersCount > score) {
 | 
			
		||||
      score = matchedUsersCount;
 | 
			
		||||
      perfectParent = parentId;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return perfectParent;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue