mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-09-16 07:42:27 +03:00
169 lines
4.9 KiB
TypeScript
169 lines
4.9 KiB
TypeScript
import { createContext, useCallback, useContext, useMemo } from 'react';
|
|
import { ConditionKind, IPushRules, MatrixClient, PushRuleKind } from 'matrix-js-sdk';
|
|
import { Icons, IconSrc } from 'folds';
|
|
import { AccountDataEvent } from '../../types/matrix/accountData';
|
|
import { useAccountData } from './useAccountData';
|
|
import { isRoomId } from '../utils/matrix';
|
|
import {
|
|
getNotificationMode,
|
|
getNotificationModeActions,
|
|
NotificationMode,
|
|
} from './useNotificationMode';
|
|
import { useAsyncCallback } from './useAsyncCallback';
|
|
import { useMatrixClient } from './useMatrixClient';
|
|
|
|
export type RoomsNotificationPreferences = {
|
|
mute: Set<string>;
|
|
specialMessages: Set<string>;
|
|
allMessages: Set<string>;
|
|
};
|
|
|
|
const RoomsNotificationPreferencesContext = createContext<RoomsNotificationPreferences | null>(
|
|
null
|
|
);
|
|
export const RoomsNotificationPreferencesProvider = RoomsNotificationPreferencesContext.Provider;
|
|
|
|
export const useRoomsNotificationPreferencesContext = (): RoomsNotificationPreferences => {
|
|
const preferences = useContext(RoomsNotificationPreferencesContext);
|
|
|
|
if (!preferences) {
|
|
throw new Error('No RoomsNotificationPreferences provided!');
|
|
}
|
|
|
|
return preferences;
|
|
};
|
|
|
|
export const useRoomsNotificationPreferences = (): RoomsNotificationPreferences => {
|
|
const pushRules = useAccountData(AccountDataEvent.PushRules)?.getContent<IPushRules>();
|
|
|
|
const preferences: RoomsNotificationPreferences = useMemo(() => {
|
|
const global = pushRules?.global;
|
|
const room = global?.room ?? [];
|
|
const override = global?.override ?? [];
|
|
|
|
const pref: RoomsNotificationPreferences = {
|
|
mute: new Set(),
|
|
specialMessages: new Set(),
|
|
allMessages: new Set(),
|
|
};
|
|
|
|
override.forEach((rule) => {
|
|
if (isRoomId(rule.rule_id) && getNotificationMode(rule.actions) === NotificationMode.OFF) {
|
|
pref.mute.add(rule.rule_id);
|
|
}
|
|
});
|
|
room.forEach((rule) => {
|
|
if (getNotificationMode(rule.actions) === NotificationMode.OFF) {
|
|
pref.specialMessages.add(rule.rule_id);
|
|
}
|
|
});
|
|
room.forEach((rule) => {
|
|
if (getNotificationMode(rule.actions) !== NotificationMode.OFF) {
|
|
pref.allMessages.add(rule.rule_id);
|
|
}
|
|
});
|
|
|
|
return pref;
|
|
}, [pushRules]);
|
|
|
|
return preferences;
|
|
};
|
|
|
|
export enum RoomNotificationMode {
|
|
Unset = 'Unset',
|
|
Mute = 'Mute',
|
|
SpecialMessages = 'SpecialMessages',
|
|
AllMessages = 'AllMessages',
|
|
}
|
|
|
|
export const getRoomNotificationMode = (
|
|
preferences: RoomsNotificationPreferences,
|
|
roomId: string
|
|
): RoomNotificationMode => {
|
|
if (preferences.mute.has(roomId)) {
|
|
return RoomNotificationMode.Mute;
|
|
}
|
|
if (preferences.specialMessages.has(roomId)) {
|
|
return RoomNotificationMode.SpecialMessages;
|
|
}
|
|
if (preferences.allMessages.has(roomId)) {
|
|
return RoomNotificationMode.AllMessages;
|
|
}
|
|
|
|
return RoomNotificationMode.Unset;
|
|
};
|
|
|
|
export const useRoomNotificationPreference = (
|
|
preferences: RoomsNotificationPreferences,
|
|
roomId: string
|
|
): RoomNotificationMode =>
|
|
useMemo(() => getRoomNotificationMode(preferences, roomId), [preferences, roomId]);
|
|
|
|
export const getRoomNotificationModeIcon = (mode?: RoomNotificationMode): IconSrc => {
|
|
if (mode === RoomNotificationMode.Mute) return Icons.BellMute;
|
|
if (mode === RoomNotificationMode.SpecialMessages) return Icons.BellPing;
|
|
if (mode === RoomNotificationMode.AllMessages) return Icons.BellRing;
|
|
|
|
return Icons.Bell;
|
|
};
|
|
|
|
export const setRoomNotificationPreference = async (
|
|
mx: MatrixClient,
|
|
roomId: string,
|
|
mode: RoomNotificationMode,
|
|
previousMode: RoomNotificationMode
|
|
): Promise<void> => {
|
|
// remove the old preference
|
|
if (
|
|
previousMode === RoomNotificationMode.AllMessages ||
|
|
previousMode === RoomNotificationMode.SpecialMessages
|
|
) {
|
|
await mx.deletePushRule('global', PushRuleKind.RoomSpecific, roomId);
|
|
}
|
|
if (previousMode === RoomNotificationMode.Mute) {
|
|
await mx.deletePushRule('global', PushRuleKind.Override, roomId);
|
|
}
|
|
|
|
// set new preference
|
|
if (mode === RoomNotificationMode.Unset) {
|
|
return;
|
|
}
|
|
|
|
if (mode === RoomNotificationMode.Mute) {
|
|
await mx.addPushRule('global', PushRuleKind.Override, roomId, {
|
|
conditions: [
|
|
{
|
|
kind: ConditionKind.EventMatch,
|
|
key: 'room_id',
|
|
pattern: roomId,
|
|
},
|
|
],
|
|
actions: getNotificationModeActions(NotificationMode.OFF),
|
|
});
|
|
return;
|
|
}
|
|
|
|
await mx.addPushRule('global', PushRuleKind.RoomSpecific, roomId, {
|
|
actions:
|
|
mode === RoomNotificationMode.AllMessages
|
|
? getNotificationModeActions(NotificationMode.NotifyLoud)
|
|
: getNotificationModeActions(NotificationMode.OFF),
|
|
});
|
|
};
|
|
|
|
export const useSetRoomNotificationPreference = (roomId: string) => {
|
|
const mx = useMatrixClient();
|
|
|
|
const [modeState, setMode] = useAsyncCallback(
|
|
useCallback(
|
|
(mode: RoomNotificationMode, previousMode: RoomNotificationMode) =>
|
|
setRoomNotificationPreference(mx, roomId, mode, previousMode),
|
|
[mx, roomId]
|
|
)
|
|
);
|
|
|
|
return {
|
|
modeState,
|
|
setMode,
|
|
};
|
|
};
|