Files
cinny/src/app/hooks/usePowerLevels.ts
T

110 lines
3.1 KiB
TypeScript
Raw Normal View History

2023-06-12 21:15:23 +10:00
import { Room } from 'matrix-js-sdk';
2023-10-06 13:44:06 +11:00
import { createContext, useCallback, useContext } from 'react';
2023-06-12 21:15:23 +10:00
import { useStateEvent } from './useStateEvent';
import { StateEvent } from '../../types/matrix/room';
2023-10-06 13:44:06 +11:00
export type PowerLevelActions = 'invite' | 'redact' | 'kick' | 'ban' | 'historical';
2023-06-12 21:15:23 +10:00
enum DefaultPowerLevels {
usersDefault = 0,
stateDefault = 50,
eventsDefault = 0,
invite = 0,
redact = 50,
kick = 50,
ban = 50,
historical = 0,
}
interface IPowerLevels {
users_default?: number;
state_default?: number;
events_default?: number;
historical?: number;
invite?: number;
redact?: number;
kick?: number;
ban?: number;
events?: Record<string, number>;
users?: Record<string, number>;
notifications?: Record<string, number>;
}
2023-10-06 13:44:06 +11:00
export type GetPowerLevel = (userId: string) => number;
export type CanSend = (eventType: string | undefined, powerLevel: number) => boolean;
export type CanDoAction = (action: PowerLevelActions, powerLevel: number) => boolean;
export type PowerLevelsAPI = {
getPowerLevel: GetPowerLevel;
canSendEvent: CanSend;
canSendStateEvent: CanSend;
canDoAction: CanDoAction;
};
export function usePowerLevels(room: Room): PowerLevelsAPI {
2023-06-12 21:15:23 +10:00
const powerLevelsEvent = useStateEvent(room, StateEvent.RoomPowerLevels);
const powerLevels: IPowerLevels = powerLevelsEvent?.getContent() ?? DefaultPowerLevels;
2023-10-06 13:44:06 +11:00
const getPowerLevel: GetPowerLevel = useCallback(
(userId) => {
2023-06-12 21:15:23 +10:00
const { users_default: usersDefault, users } = powerLevels;
if (users && typeof users[userId] === 'number') {
return users[userId];
}
return usersDefault ?? DefaultPowerLevels.usersDefault;
},
[powerLevels]
);
2023-10-06 13:44:06 +11:00
const canSendEvent: CanSend = useCallback(
(eventType, powerLevel) => {
2023-06-12 21:15:23 +10:00
const { events, events_default: eventsDefault } = powerLevels;
2023-06-28 17:27:28 +05:30
if (events && eventType && typeof events[eventType] === 'number') {
2023-06-12 21:15:23 +10:00
return powerLevel >= events[eventType];
}
return powerLevel >= (eventsDefault ?? DefaultPowerLevels.eventsDefault);
},
[powerLevels]
);
2023-10-06 13:44:06 +11:00
const canSendStateEvent: CanSend = useCallback(
(eventType, powerLevel) => {
2023-06-12 21:15:23 +10:00
const { events, state_default: stateDefault } = powerLevels;
if (events && eventType && typeof events[eventType] === 'number') {
return powerLevel >= events[eventType];
}
return powerLevel >= (stateDefault ?? DefaultPowerLevels.stateDefault);
},
[powerLevels]
);
2023-10-06 13:44:06 +11:00
const canDoAction: CanDoAction = useCallback(
(action, powerLevel) => {
2023-06-12 21:15:23 +10:00
const requiredPL = powerLevels[action];
if (typeof requiredPL === 'number') {
return powerLevel >= requiredPL;
}
return powerLevel >= DefaultPowerLevels[action];
},
[powerLevels]
);
return {
getPowerLevel,
canSendEvent,
canSendStateEvent,
canDoAction,
};
}
2023-10-06 13:44:06 +11:00
export const PowerLevelsContext = createContext<PowerLevelsAPI | null>(null);
export const PowerLevelsContextProvider = PowerLevelsContext.Provider;
export const usePowerLevelsAPI = (): PowerLevelsAPI => {
const api = useContext(PowerLevelsContext);
if (!api) throw new Error('PowerLevelContext is not initialized!');
return api;
};