mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-09 16:50:28 +03:00
Support room version 12 (#2399)
Some checks are pending
Deploy to Netlify (dev) / Deploy to Netlify (push) Waiting to run
Some checks are pending
Deploy to Netlify (dev) / Deploy to Netlify (push) Waiting to run
* WIP - support room version 12 * add room creators hook * revert changes from powerlevels * improve use room creators hook * add hook to get dm users * add options to add creators in create room/space * add member item component in member drawer * remove unused import * extract member drawer header component * get room creators as set only if room version support them * add room permissions hook * support room v12 creators power * make predecessor event id optional * add info about founders in permissions * allow to create infinite powers to room creators * allow everyone with permission to create infinite power * handle additional creators in room upgrade * add option to follow space tombstone
This commit is contained in:
parent
4d1ae4eafd
commit
f82cfead46
58 changed files with 1717 additions and 783 deletions
27
src/app/hooks/useDirectUsers.ts
Normal file
27
src/app/hooks/useDirectUsers.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { useMemo } from 'react';
|
||||
import { AccountDataEvent, MDirectContent } from '../../types/matrix/accountData';
|
||||
import { useAccountData } from './useAccountData';
|
||||
import { useAllJoinedRoomsSet, useGetRoom } from './useGetRoom';
|
||||
|
||||
export const useDirectUsers = (): string[] => {
|
||||
const directEvent = useAccountData(AccountDataEvent.Direct);
|
||||
const content = directEvent?.getContent<MDirectContent>();
|
||||
|
||||
const allJoinedRooms = useAllJoinedRoomsSet();
|
||||
const getRoom = useGetRoom(allJoinedRooms);
|
||||
|
||||
const users = useMemo(() => {
|
||||
if (typeof content !== 'object') return [];
|
||||
|
||||
const u = Object.keys(content).filter((userId) => {
|
||||
const rooms = content[userId];
|
||||
if (!Array.isArray(rooms)) return false;
|
||||
const hasDM = rooms.some((roomId) => typeof roomId === 'string' && !!getRoom(roomId));
|
||||
return hasDM;
|
||||
});
|
||||
|
||||
return u;
|
||||
}, [content, getRoom]);
|
||||
|
||||
return users;
|
||||
};
|
||||
28
src/app/hooks/useMemberPowerCompare.ts
Normal file
28
src/app/hooks/useMemberPowerCompare.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { useCallback } from 'react';
|
||||
import { IPowerLevels, readPowerLevel } from './usePowerLevels';
|
||||
|
||||
export const useMemberPowerCompare = (creators: Set<string>, powerLevels: IPowerLevels) => {
|
||||
/**
|
||||
* returns `true` if `userIdA` has more power than `userIdB`
|
||||
* returns `false` otherwise
|
||||
*/
|
||||
const hasMorePower = useCallback(
|
||||
(userIdA: string, userIdB: string): boolean => {
|
||||
const aIsCreator = creators.has(userIdA);
|
||||
const bIsCreator = creators.has(userIdB);
|
||||
if (aIsCreator && bIsCreator) return false;
|
||||
if (aIsCreator) return true;
|
||||
if (bIsCreator) return false;
|
||||
|
||||
const aPower = readPowerLevel.user(powerLevels, userIdA);
|
||||
const bPower = readPowerLevel.user(powerLevels, userIdB);
|
||||
|
||||
return aPower > bPower;
|
||||
},
|
||||
[creators, powerLevels]
|
||||
);
|
||||
|
||||
return {
|
||||
hasMorePower,
|
||||
};
|
||||
};
|
||||
87
src/app/hooks/useMemberPowerTag.ts
Normal file
87
src/app/hooks/useMemberPowerTag.ts
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import { useCallback, useMemo } from 'react';
|
||||
import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk';
|
||||
import { getPowerLevelTag, PowerLevelTags, usePowerLevelTags } from './usePowerLevelTags';
|
||||
import { IPowerLevels, readPowerLevel } from './usePowerLevels';
|
||||
import { MemberPowerTag, MemberPowerTagIcon } from '../../types/matrix/room';
|
||||
import { useRoomCreatorsTag } from './useRoomCreatorsTag';
|
||||
import { ThemeKind } from './useTheme';
|
||||
import { accessibleColor } from '../plugins/color';
|
||||
|
||||
export type GetMemberPowerTag = (userId: string) => MemberPowerTag;
|
||||
|
||||
export const useGetMemberPowerTag = (
|
||||
room: Room,
|
||||
creators: Set<string>,
|
||||
powerLevels: IPowerLevels
|
||||
) => {
|
||||
const creatorsTag = useRoomCreatorsTag();
|
||||
const powerLevelTags = usePowerLevelTags(room, powerLevels);
|
||||
|
||||
const getMemberPowerTag: GetMemberPowerTag = useCallback(
|
||||
(userId) => {
|
||||
if (creators.has(userId)) {
|
||||
return creatorsTag;
|
||||
}
|
||||
|
||||
const power = readPowerLevel.user(powerLevels, userId);
|
||||
return getPowerLevelTag(powerLevelTags, power);
|
||||
},
|
||||
[creators, creatorsTag, powerLevels, powerLevelTags]
|
||||
);
|
||||
|
||||
return getMemberPowerTag;
|
||||
};
|
||||
|
||||
export const getPowerTagIconSrc = (
|
||||
mx: MatrixClient,
|
||||
useAuthentication: boolean,
|
||||
icon: MemberPowerTagIcon
|
||||
): string | undefined =>
|
||||
icon?.key?.startsWith('mxc://')
|
||||
? mx.mxcUrlToHttp(icon.key, 96, 96, 'scale', undefined, undefined, useAuthentication) ?? '🌻'
|
||||
: icon?.key;
|
||||
|
||||
export const useAccessiblePowerTagColors = (
|
||||
themeKind: ThemeKind,
|
||||
creatorsTag: MemberPowerTag,
|
||||
powerLevelTags: PowerLevelTags
|
||||
): Map<string, string> => {
|
||||
const accessibleColors: Map<string, string> = useMemo(() => {
|
||||
const colors: Map<string, string> = new Map();
|
||||
if (creatorsTag.color) {
|
||||
colors.set(creatorsTag.color, accessibleColor(themeKind, creatorsTag.color));
|
||||
}
|
||||
|
||||
Object.values(powerLevelTags).forEach((tag) => {
|
||||
const { color } = tag;
|
||||
if (!color) return;
|
||||
|
||||
colors.set(color, accessibleColor(themeKind, color));
|
||||
});
|
||||
|
||||
return colors;
|
||||
}, [powerLevelTags, creatorsTag, themeKind]);
|
||||
|
||||
return accessibleColors;
|
||||
};
|
||||
|
||||
export const useFlattenPowerTagMembers = (
|
||||
members: RoomMember[],
|
||||
getTag: GetMemberPowerTag
|
||||
): Array<MemberPowerTag | RoomMember> => {
|
||||
const PLTagOrRoomMember = useMemo(() => {
|
||||
let prevTag: MemberPowerTag | undefined;
|
||||
const tagOrMember: Array<MemberPowerTag | RoomMember> = [];
|
||||
members.forEach((member) => {
|
||||
const tag = getTag(member.userId);
|
||||
if (tag !== prevTag) {
|
||||
prevTag = tag;
|
||||
tagOrMember.push(tag);
|
||||
}
|
||||
tagOrMember.push(member);
|
||||
});
|
||||
return tagOrMember;
|
||||
}, [members, getTag]);
|
||||
|
||||
return PLTagOrRoomMember;
|
||||
};
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { RoomMember } from 'matrix-js-sdk';
|
||||
import { useMemo } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
export const MemberSort = {
|
||||
Ascending: (a: RoomMember, b: RoomMember) =>
|
||||
|
|
@ -46,3 +46,20 @@ export const useMemberSort = (index: number, memberSort: MemberSortItem[]): Memb
|
|||
const item = memberSort[index] ?? memberSort[0];
|
||||
return item;
|
||||
};
|
||||
|
||||
export const useMemberPowerSort = (creators: Set<string>): MemberSortFn => {
|
||||
const sort: MemberSortFn = useCallback(
|
||||
(a, b) => {
|
||||
if (creators.has(a.userId) && creators.has(b.userId)) {
|
||||
return 0;
|
||||
}
|
||||
if (creators.has(a.userId)) return -1;
|
||||
if (creators.has(b.userId)) return 1;
|
||||
|
||||
return b.powerLevel - a.powerLevel;
|
||||
},
|
||||
[creators]
|
||||
);
|
||||
|
||||
return sort;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,29 +1,24 @@
|
|||
import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { Room } from 'matrix-js-sdk';
|
||||
import { useMemo } from 'react';
|
||||
import { IPowerLevels } from './usePowerLevels';
|
||||
import { useStateEvent } from './useStateEvent';
|
||||
import { StateEvent } from '../../types/matrix/room';
|
||||
import { IImageInfo } from '../../types/matrix/common';
|
||||
import { ThemeKind } from './useTheme';
|
||||
import { accessibleColor } from '../plugins/color';
|
||||
import { MemberPowerTag, StateEvent } from '../../types/matrix/room';
|
||||
|
||||
export type PowerLevelTagIcon = {
|
||||
key?: string;
|
||||
info?: IImageInfo;
|
||||
};
|
||||
export type PowerLevelTag = {
|
||||
name: string;
|
||||
color?: string;
|
||||
icon?: PowerLevelTagIcon;
|
||||
};
|
||||
export type PowerLevelTags = Record<number, MemberPowerTag>;
|
||||
|
||||
export type PowerLevelTags = Record<number, PowerLevelTag>;
|
||||
|
||||
export const powerSortFn = (a: number, b: number) => b - a;
|
||||
export const sortPowers = (powers: number[]): number[] => powers.sort(powerSortFn);
|
||||
const powerSortFn = (a: number, b: number) => b - a;
|
||||
const sortPowers = (powers: number[]): number[] => powers.sort(powerSortFn);
|
||||
|
||||
export const getPowers = (tags: PowerLevelTags): number[] => {
|
||||
const powers: number[] = Object.keys(tags).map((p) => parseInt(p, 10));
|
||||
const powers: number[] = Object.keys(tags)
|
||||
.map((p) => {
|
||||
const power = parseInt(p, 10);
|
||||
if (Number.isNaN(power)) {
|
||||
return undefined;
|
||||
}
|
||||
return power;
|
||||
})
|
||||
.filter((power) => typeof power === 'number');
|
||||
|
||||
return sortPowers(powers);
|
||||
};
|
||||
|
|
@ -55,8 +50,8 @@ const DEFAULT_TAGS: PowerLevelTags = {
|
|||
name: 'Goku',
|
||||
color: '#ff6a00',
|
||||
},
|
||||
102: {
|
||||
name: 'Goku Reborn',
|
||||
150: {
|
||||
name: 'Co-Founder',
|
||||
color: '#ff6a7f',
|
||||
},
|
||||
101: {
|
||||
|
|
@ -81,7 +76,7 @@ const DEFAULT_TAGS: PowerLevelTags = {
|
|||
},
|
||||
};
|
||||
|
||||
const generateFallbackTag = (powerLevelTags: PowerLevelTags, power: number): PowerLevelTag => {
|
||||
const generateFallbackTag = (powerLevelTags: PowerLevelTags, power: number): MemberPowerTag => {
|
||||
const highToLow = sortPowers(getPowers(powerLevelTags));
|
||||
|
||||
const tagPower = highToLow.find((p) => p < power);
|
||||
|
|
@ -92,12 +87,7 @@ const generateFallbackTag = (powerLevelTags: PowerLevelTags, power: number): Pow
|
|||
};
|
||||
};
|
||||
|
||||
export type GetPowerLevelTag = (powerLevel: number) => PowerLevelTag;
|
||||
|
||||
export const usePowerLevelTags = (
|
||||
room: Room,
|
||||
powerLevels: IPowerLevels
|
||||
): [PowerLevelTags, GetPowerLevelTag] => {
|
||||
export const usePowerLevelTags = (room: Room, powerLevels: IPowerLevels): PowerLevelTags => {
|
||||
const tagsEvent = useStateEvent(room, StateEvent.PowerLevelTags);
|
||||
|
||||
const powerLevelTags: PowerLevelTags = useMemo(() => {
|
||||
|
|
@ -114,66 +104,13 @@ export const usePowerLevelTags = (
|
|||
return powerToTags;
|
||||
}, [powerLevels, tagsEvent]);
|
||||
|
||||
const getTag: GetPowerLevelTag = useCallback(
|
||||
(power) => {
|
||||
const tag: PowerLevelTag | undefined = powerLevelTags[power];
|
||||
return tag ?? generateFallbackTag(DEFAULT_TAGS, power);
|
||||
},
|
||||
[powerLevelTags]
|
||||
);
|
||||
|
||||
return [powerLevelTags, getTag];
|
||||
return powerLevelTags;
|
||||
};
|
||||
|
||||
export const useFlattenPowerLevelTagMembers = (
|
||||
members: RoomMember[],
|
||||
getPowerLevel: (userId: string) => number,
|
||||
getTag: GetPowerLevelTag
|
||||
): Array<PowerLevelTag | RoomMember> => {
|
||||
const PLTagOrRoomMember = useMemo(() => {
|
||||
let prevTag: PowerLevelTag | undefined;
|
||||
const tagOrMember: Array<PowerLevelTag | RoomMember> = [];
|
||||
members.forEach((member) => {
|
||||
const memberPL = getPowerLevel(member.userId);
|
||||
const tag = getTag(memberPL);
|
||||
if (tag !== prevTag) {
|
||||
prevTag = tag;
|
||||
tagOrMember.push(tag);
|
||||
}
|
||||
tagOrMember.push(member);
|
||||
});
|
||||
return tagOrMember;
|
||||
}, [members, getTag, getPowerLevel]);
|
||||
|
||||
return PLTagOrRoomMember;
|
||||
};
|
||||
|
||||
export const getTagIconSrc = (
|
||||
mx: MatrixClient,
|
||||
useAuthentication: boolean,
|
||||
icon: PowerLevelTagIcon
|
||||
): string | undefined =>
|
||||
icon?.key?.startsWith('mxc://')
|
||||
? mx.mxcUrlToHttp(icon.key, 96, 96, 'scale', undefined, undefined, useAuthentication) ?? '🌻'
|
||||
: icon?.key;
|
||||
|
||||
export const useAccessibleTagColors = (
|
||||
themeKind: ThemeKind,
|
||||
powerLevelTags: PowerLevelTags
|
||||
): Map<string, string> => {
|
||||
const accessibleColors: Map<string, string> = useMemo(() => {
|
||||
const colors: Map<string, string> = new Map();
|
||||
|
||||
getPowers(powerLevelTags).forEach((power) => {
|
||||
const tag = powerLevelTags[power];
|
||||
const { color } = tag;
|
||||
if (!color) return;
|
||||
|
||||
colors.set(color, accessibleColor(themeKind, color));
|
||||
});
|
||||
|
||||
return colors;
|
||||
}, [powerLevelTags, themeKind]);
|
||||
|
||||
return accessibleColors;
|
||||
export const getPowerLevelTag = (
|
||||
powerLevelTags: PowerLevelTags,
|
||||
powerLevel: number
|
||||
): MemberPowerTag => {
|
||||
const tag: MemberPowerTag | undefined = powerLevelTags[powerLevel];
|
||||
return tag ?? generateFallbackTag(powerLevelTags, powerLevel);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -58,10 +58,11 @@ const fillMissingPowers = (powerLevels: IPowerLevels): IPowerLevels =>
|
|||
});
|
||||
|
||||
const getPowersLevelFromMatrixEvent = (mEvent?: MatrixEvent): IPowerLevels => {
|
||||
const pl = mEvent?.getContent<IPowerLevels>();
|
||||
if (!pl) return DEFAULT_POWER_LEVELS;
|
||||
const plContent = mEvent?.getContent<IPowerLevels>();
|
||||
|
||||
return fillMissingPowers(pl);
|
||||
const powerLevels = !plContent ? DEFAULT_POWER_LEVELS : fillMissingPowers(plContent);
|
||||
|
||||
return powerLevels;
|
||||
};
|
||||
|
||||
export function usePowerLevels(room: Room): IPowerLevels {
|
||||
|
|
@ -120,33 +121,8 @@ export const useRoomsPowerLevels = (rooms: Room[]): Map<string, IPowerLevels> =>
|
|||
return roomToPowerLevels;
|
||||
};
|
||||
|
||||
export type GetPowerLevel = (powerLevels: IPowerLevels, userId: string | undefined) => number;
|
||||
export type CanSend = (
|
||||
powerLevels: IPowerLevels,
|
||||
eventType: string | undefined,
|
||||
powerLevel: number
|
||||
) => boolean;
|
||||
export type CanDoAction = (
|
||||
powerLevels: IPowerLevels,
|
||||
action: PowerLevelActions,
|
||||
powerLevel: number
|
||||
) => boolean;
|
||||
export type CanDoNotificationAction = (
|
||||
powerLevels: IPowerLevels,
|
||||
action: PowerLevelNotificationsAction,
|
||||
powerLevel: number
|
||||
) => boolean;
|
||||
|
||||
export type PowerLevelsAPI = {
|
||||
getPowerLevel: GetPowerLevel;
|
||||
canSendEvent: CanSend;
|
||||
canSendStateEvent: CanSend;
|
||||
canDoAction: CanDoAction;
|
||||
canDoNotificationAction: CanDoNotificationAction;
|
||||
};
|
||||
|
||||
export type ReadPowerLevelAPI = {
|
||||
user: GetPowerLevel;
|
||||
user: (powerLevels: IPowerLevels, userId: string | undefined) => number;
|
||||
event: (powerLevels: IPowerLevels, eventType: string | undefined) => number;
|
||||
state: (powerLevels: IPowerLevels, eventType: string | undefined) => number;
|
||||
action: (powerLevels: IPowerLevels, action: PowerLevelActions) => number;
|
||||
|
|
@ -156,6 +132,7 @@ export type ReadPowerLevelAPI = {
|
|||
export const readPowerLevel: ReadPowerLevelAPI = {
|
||||
user: (powerLevels, userId) => {
|
||||
const { users_default: usersDefault, users } = powerLevels;
|
||||
|
||||
if (userId && users && typeof users[userId] === 'number') {
|
||||
return users[userId];
|
||||
}
|
||||
|
|
@ -191,63 +168,13 @@ export const readPowerLevel: ReadPowerLevelAPI = {
|
|||
},
|
||||
};
|
||||
|
||||
export const powerLevelAPI: PowerLevelsAPI = {
|
||||
getPowerLevel: (powerLevels, userId) => readPowerLevel.user(powerLevels, userId),
|
||||
canSendEvent: (powerLevels, eventType, powerLevel) => {
|
||||
const requiredPL = readPowerLevel.event(powerLevels, eventType);
|
||||
return powerLevel >= requiredPL;
|
||||
},
|
||||
canSendStateEvent: (powerLevels, eventType, powerLevel) => {
|
||||
const requiredPL = readPowerLevel.state(powerLevels, eventType);
|
||||
return powerLevel >= requiredPL;
|
||||
},
|
||||
canDoAction: (powerLevels, action, powerLevel) => {
|
||||
const requiredPL = readPowerLevel.action(powerLevels, action);
|
||||
return powerLevel >= requiredPL;
|
||||
},
|
||||
canDoNotificationAction: (powerLevels, action, powerLevel) => {
|
||||
const requiredPL = readPowerLevel.notification(powerLevels, action);
|
||||
return powerLevel >= requiredPL;
|
||||
},
|
||||
};
|
||||
|
||||
export const usePowerLevelsAPI = (powerLevels: IPowerLevels) => {
|
||||
const getPowerLevel = useCallback(
|
||||
(userId: string | undefined) => powerLevelAPI.getPowerLevel(powerLevels, userId),
|
||||
export const useGetMemberPowerLevel = (powerLevels: IPowerLevels) => {
|
||||
const callback = useCallback(
|
||||
(userId?: string): number => readPowerLevel.user(powerLevels, userId),
|
||||
[powerLevels]
|
||||
);
|
||||
|
||||
const canSendEvent = useCallback(
|
||||
(eventType: string | undefined, powerLevel: number) =>
|
||||
powerLevelAPI.canSendEvent(powerLevels, eventType, powerLevel),
|
||||
[powerLevels]
|
||||
);
|
||||
|
||||
const canSendStateEvent = useCallback(
|
||||
(eventType: string | undefined, powerLevel: number) =>
|
||||
powerLevelAPI.canSendStateEvent(powerLevels, eventType, powerLevel),
|
||||
[powerLevels]
|
||||
);
|
||||
|
||||
const canDoAction = useCallback(
|
||||
(action: PowerLevelActions, powerLevel: number) =>
|
||||
powerLevelAPI.canDoAction(powerLevels, action, powerLevel),
|
||||
[powerLevels]
|
||||
);
|
||||
|
||||
const canDoNotificationAction = useCallback(
|
||||
(action: PowerLevelNotificationsAction, powerLevel: number) =>
|
||||
powerLevelAPI.canDoNotificationAction(powerLevels, action, powerLevel),
|
||||
[powerLevels]
|
||||
);
|
||||
|
||||
return {
|
||||
getPowerLevel,
|
||||
canSendEvent,
|
||||
canSendStateEvent,
|
||||
canDoAction,
|
||||
canDoNotificationAction,
|
||||
};
|
||||
return callback;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
49
src/app/hooks/useRoomCreators.ts
Normal file
49
src/app/hooks/useRoomCreators.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import { MatrixClient, MatrixEvent, Room } from 'matrix-js-sdk';
|
||||
import { useMemo } from 'react';
|
||||
import { useStateEvent } from './useStateEvent';
|
||||
import { IRoomCreateContent, StateEvent } from '../../types/matrix/room';
|
||||
import { creatorsSupported } from '../utils/matrix';
|
||||
import { getStateEvent } from '../utils/room';
|
||||
|
||||
export const getRoomCreators = (createEvent: MatrixEvent): Set<string> => {
|
||||
const createContent = createEvent.getContent<IRoomCreateContent>();
|
||||
|
||||
const creators: Set<string> = new Set();
|
||||
|
||||
if (!creatorsSupported(createContent.room_version)) return creators;
|
||||
|
||||
if (createEvent.event.sender) {
|
||||
creators.add(createEvent.event.sender);
|
||||
}
|
||||
|
||||
if ('additional_creators' in createContent && Array.isArray(createContent.additional_creators)) {
|
||||
createContent.additional_creators.forEach((creator) => {
|
||||
if (typeof creator === 'string') {
|
||||
creators.add(creator);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return creators;
|
||||
};
|
||||
|
||||
export const useRoomCreators = (room: Room): Set<string> => {
|
||||
const createEvent = useStateEvent(room, StateEvent.RoomCreate);
|
||||
|
||||
const creators = useMemo(
|
||||
() => (createEvent ? getRoomCreators(createEvent) : new Set<string>()),
|
||||
[createEvent]
|
||||
);
|
||||
|
||||
return creators;
|
||||
};
|
||||
|
||||
export const getRoomCreatorsForRoomId = (mx: MatrixClient, roomId: string): Set<string> => {
|
||||
const room = mx.getRoom(roomId);
|
||||
if (!room) return new Set();
|
||||
|
||||
const createEvent = getStateEvent(room, StateEvent.RoomCreate);
|
||||
if (!createEvent) return new Set();
|
||||
|
||||
return getRoomCreators(createEvent);
|
||||
};
|
||||
8
src/app/hooks/useRoomCreatorsTag.ts
Normal file
8
src/app/hooks/useRoomCreatorsTag.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { MemberPowerTag } from '../../types/matrix/room';
|
||||
|
||||
const DEFAULT_TAG: MemberPowerTag = {
|
||||
name: 'Founder',
|
||||
color: '#0000ff',
|
||||
};
|
||||
|
||||
export const useRoomCreatorsTag = (): MemberPowerTag => DEFAULT_TAG;
|
||||
60
src/app/hooks/useRoomPermissions.ts
Normal file
60
src/app/hooks/useRoomPermissions.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import { useMemo } from 'react';
|
||||
import {
|
||||
IPowerLevels,
|
||||
PowerLevelActions,
|
||||
PowerLevelNotificationsAction,
|
||||
readPowerLevel,
|
||||
} from './usePowerLevels';
|
||||
|
||||
export type RoomPermissionsAPI = {
|
||||
event: (type: string, userId: string) => boolean;
|
||||
stateEvent: (type: string, userId: string) => boolean;
|
||||
action: (action: PowerLevelActions, userId: string) => boolean;
|
||||
notificationAction: (action: PowerLevelNotificationsAction, userId: string) => boolean;
|
||||
};
|
||||
|
||||
export const getRoomPermissionsAPI = (
|
||||
creators: Set<string>,
|
||||
powerLevels: IPowerLevels
|
||||
): RoomPermissionsAPI => {
|
||||
const api: RoomPermissionsAPI = {
|
||||
event: (type, userId) => {
|
||||
if (creators.has(userId)) return true;
|
||||
const userPower = readPowerLevel.user(powerLevels, userId);
|
||||
const requiredPL = readPowerLevel.event(powerLevels, type);
|
||||
return userPower >= requiredPL;
|
||||
},
|
||||
stateEvent: (type, userId) => {
|
||||
if (creators.has(userId)) return true;
|
||||
const userPower = readPowerLevel.user(powerLevels, userId);
|
||||
const requiredPL = readPowerLevel.state(powerLevels, type);
|
||||
return userPower >= requiredPL;
|
||||
},
|
||||
action: (action, userId) => {
|
||||
if (creators.has(userId)) return true;
|
||||
const userPower = readPowerLevel.user(powerLevels, userId);
|
||||
const requiredPL = readPowerLevel.action(powerLevels, action);
|
||||
return userPower >= requiredPL;
|
||||
},
|
||||
notificationAction: (action, userId) => {
|
||||
if (creators.has(userId)) return true;
|
||||
const userPower = readPowerLevel.user(powerLevels, userId);
|
||||
const requiredPL = readPowerLevel.notification(powerLevels, action);
|
||||
return userPower >= requiredPL;
|
||||
},
|
||||
};
|
||||
|
||||
return api;
|
||||
};
|
||||
|
||||
export const useRoomPermissions = (
|
||||
creators: Set<string>,
|
||||
powerLevels: IPowerLevels
|
||||
): RoomPermissionsAPI => {
|
||||
const api: RoomPermissionsAPI = useMemo(
|
||||
() => getRoomPermissionsAPI(creators, powerLevels),
|
||||
[creators, powerLevels]
|
||||
);
|
||||
|
||||
return api;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue