matrix-react-sdk
Version:
SDK for matrix.org using React
105 lines (97 loc) • 4.15 kB
text/typescript
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import { IPushRule, IPushRules, RuleId } from "matrix-js-sdk/src/matrix";
import { NotificationUtils } from "../../notifications";
import { RoomNotifState } from "../../RoomNotifs";
import { NotificationSettings } from "./NotificationSettings";
import { buildPushRuleMap } from "./PushRuleMap";
function shouldNotify(rules: (IPushRule | null | undefined | false)[]): boolean {
if (rules.length === 0) {
return true;
}
for (const rule of rules) {
if (rule === null || rule === undefined || rule === false || !rule.enabled) {
continue;
}
const actions = NotificationUtils.decodeActions(rule.actions);
if (actions !== null && actions.notify) {
return true;
}
}
return false;
}
function isMuted(rules: (IPushRule | null | undefined | false)[]): boolean {
if (rules.length === 0) {
return false;
}
for (const rule of rules) {
if (rule === null || rule === undefined || rule === false || !rule.enabled) {
continue;
}
const actions = NotificationUtils.decodeActions(rule.actions);
if (actions !== null && !actions.notify && actions.highlight !== true && actions.sound === undefined) {
return true;
}
}
return false;
}
function determineSound(rules: (IPushRule | null | undefined | false)[]): string | undefined {
for (const rule of rules) {
if (rule === null || rule === undefined || rule === false || !rule.enabled) {
continue;
}
const actions = NotificationUtils.decodeActions(rule.actions);
if (actions !== null && actions.notify && actions.sound !== undefined) {
return actions.sound;
}
}
return undefined;
}
export function toNotificationSettings(
pushRules: IPushRules,
supportsIntentionalMentions: boolean,
): NotificationSettings {
const standardRules = buildPushRuleMap(pushRules);
const contentRules = pushRules.global.content?.filter((rule) => !rule.rule_id.startsWith(".")) ?? [];
const dmRules = [standardRules.get(RuleId.DM), standardRules.get(RuleId.EncryptedDM)];
const roomRules = [standardRules.get(RuleId.Message), standardRules.get(RuleId.EncryptedMessage)];
return {
globalMute: standardRules.get(RuleId.Master)?.enabled ?? false,
defaultLevels: {
room: shouldNotify(roomRules) ? RoomNotifState.AllMessages : RoomNotifState.MentionsOnly,
dm: shouldNotify(dmRules) ? RoomNotifState.AllMessages : RoomNotifState.MentionsOnly,
},
sound: {
calls: determineSound([standardRules.get(RuleId.IncomingCall)]),
mentions: determineSound([
supportsIntentionalMentions && standardRules.get(RuleId.IsUserMention),
standardRules.get(RuleId.ContainsUserName),
standardRules.get(RuleId.ContainsDisplayName),
...contentRules,
]),
people: determineSound(dmRules),
},
activity: {
bot_notices: !isMuted([standardRules.get(RuleId.SuppressNotices)]),
invite: shouldNotify([standardRules.get(RuleId.InviteToSelf)]),
status_event: shouldNotify([standardRules.get(RuleId.MemberEvent), standardRules.get(RuleId.Tombstone)]),
},
mentions: {
user: shouldNotify([
supportsIntentionalMentions && standardRules.get(RuleId.IsUserMention),
standardRules.get(RuleId.ContainsUserName),
standardRules.get(RuleId.ContainsDisplayName),
]),
room: shouldNotify([
supportsIntentionalMentions && standardRules.get(RuleId.IsRoomMention),
standardRules.get(RuleId.AtRoomNotification),
]),
keywords: shouldNotify(contentRules),
},
keywords: contentRules.map((it) => it.pattern!),
};
}