1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-08-09 10:22:46 +03:00

Update call notification push rule to match MSC3914 (#2781)

This commit is contained in:
Šimon Brandner
2022-10-21 17:17:34 +02:00
committed by GitHub
parent d9eac57e9c
commit a12e6185f9
3 changed files with 67 additions and 35 deletions

View File

@@ -163,6 +163,22 @@ describe('NotificationService', function() {
"enabled": true, "enabled": true,
"rule_id": ".m.rule.room_one_to_one", "rule_id": ".m.rule.room_one_to_one",
}, },
{
rule_id: ".org.matrix.msc3914.rule.room.call",
default: true,
enabled: true,
conditions: [
{
kind: "event_match",
key: "type",
pattern: "org.matrix.msc3401.call",
},
{
kind: "call_started",
},
],
actions: ["notify", { set_tweak: "sound", value: "default" }],
},
], ],
"room": [], "room": [],
"sender": [], "sender": [],
@@ -337,7 +353,11 @@ describe('NotificationService', function() {
}, testEvent)).toBe(true); }, testEvent)).toBe(true);
}); });
describe("performCustomEventHandling()", () => { describe("group call started push rule", () => {
beforeEach(() => {
matrixClient.pushRules!.global!.underride!.find(r => r.rule_id === ".m.rule.fallback")!.enabled = false;
});
const getActionsForEvent = (prevContent: IContent, content: IContent): IActionsObject => { const getActionsForEvent = (prevContent: IContent, content: IContent): IActionsObject => {
testEvent = utils.mkEvent({ testEvent = utils.mkEvent({
type: "org.matrix.msc3401.call", type: "org.matrix.msc3401.call",
@@ -353,15 +373,15 @@ describe('NotificationService', function() {
}; };
const assertDoesNotify = (actions: IActionsObject): void => { const assertDoesNotify = (actions: IActionsObject): void => {
expect(actions.notify).toBeTruthy(); expect(actions?.notify).toBeTruthy();
expect(actions.tweaks.sound).toBeTruthy(); expect(actions?.tweaks?.sound).toBeTruthy();
expect(actions.tweaks.highlight).toBeFalsy(); expect(actions?.tweaks?.highlight).toBeFalsy();
}; };
const assertDoesNotNotify = (actions: IActionsObject): void => { const assertDoesNotNotify = (actions: IActionsObject): void => {
expect(actions.notify).toBeFalsy(); expect(actions?.notify).toBeFalsy();
expect(actions.tweaks.sound).toBeFalsy(); expect(actions?.tweaks?.sound).toBeFalsy();
expect(actions.tweaks.highlight).toBeFalsy(); expect(actions?.tweaks?.highlight).toBeFalsy();
}; };
it.each( it.each(

View File

@@ -65,6 +65,8 @@ export enum ConditionKind {
ContainsDisplayName = "contains_display_name", ContainsDisplayName = "contains_display_name",
RoomMemberCount = "room_member_count", RoomMemberCount = "room_member_count",
SenderNotificationPermission = "sender_notification_permission", SenderNotificationPermission = "sender_notification_permission",
CallStarted = "call_started",
CallStartedPrefix = "org.matrix.msc3914.call_started",
} }
export interface IPushRuleCondition<N extends ConditionKind | string> { export interface IPushRuleCondition<N extends ConditionKind | string> {
@@ -90,12 +92,22 @@ export interface ISenderNotificationPermissionCondition
key: string; key: string;
} }
export interface ICallStartedCondition extends IPushRuleCondition<ConditionKind.CallStarted> {
// no additional fields
}
export interface ICallStartedPrefixCondition extends IPushRuleCondition<ConditionKind.CallStartedPrefix> {
// no additional fields
}
// XXX: custom conditions are possible but always fail, and break the typescript discriminated union so ignore them here // XXX: custom conditions are possible but always fail, and break the typescript discriminated union so ignore them here
// IPushRuleCondition<Exclude<string, ConditionKind>> unfortunately does not resolve this at the time of writing. // IPushRuleCondition<Exclude<string, ConditionKind>> unfortunately does not resolve this at the time of writing.
export type PushRuleCondition = IEventMatchCondition export type PushRuleCondition = IEventMatchCondition
| IContainsDisplayNameCondition | IContainsDisplayNameCondition
| IRoomMemberCountCondition | IRoomMemberCountCondition
| ISenderNotificationPermissionCondition; | ISenderNotificationPermissionCondition
| ICallStartedCondition
| ICallStartedPrefixCondition;
export enum PushRuleKind { export enum PushRuleKind {
Override = "override", Override = "override",

View File

@@ -21,6 +21,8 @@ import { MatrixEvent } from "./models/event";
import { import {
ConditionKind, ConditionKind,
IAnnotatedPushRule, IAnnotatedPushRule,
ICallStartedCondition,
ICallStartedPrefixCondition,
IContainsDisplayNameCondition, IContainsDisplayNameCondition,
IEventMatchCondition, IEventMatchCondition,
IPushRule, IPushRule,
@@ -92,8 +94,8 @@ const DEFAULT_OVERRIDE_RULES: IPushRule[] = [
actions: [], actions: [],
}, },
{ {
// For homeservers which don't support MSC3401 yet // For homeservers which don't support MSC3914 yet
rule_id: ".org.matrix.msc3401.rule.room.call", rule_id: ".org.matrix.msc3914.rule.room.call",
default: true, default: true,
enabled: true, enabled: true,
conditions: [ conditions: [
@@ -102,6 +104,9 @@ const DEFAULT_OVERRIDE_RULES: IPushRule[] = [
key: "type", key: "type",
pattern: "org.matrix.msc3401.call", pattern: "org.matrix.msc3401.call",
}, },
{
kind: ConditionKind.CallStarted,
},
], ],
actions: [PushRuleActionName.Notify, { set_tweak: TweakName.Sound, value: "default" }], actions: [PushRuleActionName.Notify, { set_tweak: TweakName.Sound, value: "default" }],
}, },
@@ -269,6 +274,9 @@ export class PushProcessor {
return this.eventFulfillsRoomMemberCountCondition(cond, ev); return this.eventFulfillsRoomMemberCountCondition(cond, ev);
case ConditionKind.SenderNotificationPermission: case ConditionKind.SenderNotificationPermission:
return this.eventFulfillsSenderNotifPermCondition(cond, ev); return this.eventFulfillsSenderNotifPermCondition(cond, ev);
case ConditionKind.CallStarted:
case ConditionKind.CallStartedPrefix:
return this.eventFulfillsCallStartedCondition(cond, ev);
} }
// unknown conditions: we previously matched all unknown conditions, // unknown conditions: we previously matched all unknown conditions,
@@ -383,6 +391,22 @@ export class PushProcessor {
return !!val.match(regex); return !!val.match(regex);
} }
private eventFulfillsCallStartedCondition(
_cond: ICallStartedCondition | ICallStartedPrefixCondition,
ev: MatrixEvent,
): boolean {
// Since servers don't support properly sending push notification
// about MSC3401 call events, we do the handling ourselves
return (
["m.ring", "m.prompt"].includes(ev.getContent()["m.intent"])
&& !("m.terminated" in ev.getContent())
&& (
(ev.getPrevContent()["m.terminated"] !== ev.getContent()["m.terminated"])
|| deepCompare(ev.getPrevContent(), {})
)
);
}
private createCachedRegex(prefix: string, glob: string, suffix: string): RegExp { private createCachedRegex(prefix: string, glob: string, suffix: string): RegExp {
if (PushProcessor.cachedGlobToRegex[glob]) { if (PushProcessor.cachedGlobToRegex[glob]) {
return PushProcessor.cachedGlobToRegex[glob]; return PushProcessor.cachedGlobToRegex[glob];
@@ -438,7 +462,7 @@ export class PushProcessor {
return {} as IActionsObject; return {} as IActionsObject;
} }
let actionObj = PushProcessor.actionListToActionsObject(rule.actions); const actionObj = PushProcessor.actionListToActionsObject(rule.actions);
// Some actions are implicit in some situations: we add those here // Some actions are implicit in some situations: we add those here
if (actionObj.tweaks.highlight === undefined) { if (actionObj.tweaks.highlight === undefined) {
@@ -447,30 +471,6 @@ export class PushProcessor {
actionObj.tweaks.highlight = (rule.kind == PushRuleKind.ContentSpecific); actionObj.tweaks.highlight = (rule.kind == PushRuleKind.ContentSpecific);
} }
actionObj = this.performCustomEventHandling(ev, actionObj);
return actionObj;
}
/**
* Some events require custom event handling e.g. due to missing server support
*/
private performCustomEventHandling(ev: MatrixEvent, actionObj: IActionsObject): IActionsObject {
switch (ev.getType()) {
case "m.call":
case "org.matrix.msc3401.call":
// Since servers don't support properly sending push notification
// about MSC3401 call events, we do the handling ourselves
if (
ev.getContent()["m.intent"] === "m.room"
|| ("m.terminated" in ev.getContent())
|| !("m.terminated" in ev.getPrevContent()) && !deepCompare(ev.getPrevContent(), {})
) {
actionObj.notify = false;
actionObj.tweaks = {};
}
}
return actionObj; return actionObj;
} }