@ethora/chat-component-rn 26.10.7 → 26.10.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +3 -3
- package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/Message.js +16 -6
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js +16 -2
- package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/callActions.js +32 -2
- package/lib/commonjs/components/VideoCalls/callActions.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/systemCall.js +83 -0
- package/lib/commonjs/components/VideoCalls/systemCall.js.map +1 -0
- package/lib/commonjs/components/VideoCalls/useCallKeep.js +84 -69
- package/lib/commonjs/components/VideoCalls/useCallKeep.js.map +1 -1
- package/lib/commonjs/helpers/incomingCallFromPush.js +95 -21
- package/lib/commonjs/helpers/incomingCallFromPush.js.map +1 -1
- package/lib/commonjs/main.js +33 -0
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/networking/callTokenStanza.js +19 -1
- package/lib/commonjs/networking/callTokenStanza.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendMessageReaction.xmpp.js +22 -6
- package/lib/commonjs/networking/xmpp/sendMessageReaction.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/push/sealedPush.js +13 -2
- package/lib/commonjs/push/sealedPush.js.map +1 -1
- package/lib/commonjs/push/sealedPushTask.js +63 -18
- package/lib/commonjs/push/sealedPushTask.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/module/components/Menu/HeaderRoomListMenu.js +3 -3
- package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/module/components/MessageBubble/Message.js +16 -6
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/VideoCalls/VideoCallOverlay.js +17 -3
- package/lib/module/components/VideoCalls/VideoCallOverlay.js.map +1 -1
- package/lib/module/components/VideoCalls/callActions.js +29 -0
- package/lib/module/components/VideoCalls/callActions.js.map +1 -1
- package/lib/module/components/VideoCalls/systemCall.js +73 -0
- package/lib/module/components/VideoCalls/systemCall.js.map +1 -0
- package/lib/module/components/VideoCalls/useCallKeep.js +79 -68
- package/lib/module/components/VideoCalls/useCallKeep.js.map +1 -1
- package/lib/module/helpers/incomingCallFromPush.js +92 -22
- package/lib/module/helpers/incomingCallFromPush.js.map +1 -1
- package/lib/module/main.js +3 -0
- package/lib/module/main.js.map +1 -1
- package/lib/module/networking/callTokenStanza.js +19 -1
- package/lib/module/networking/callTokenStanza.js.map +1 -1
- package/lib/module/networking/xmpp/sendMessageReaction.xmpp.js +21 -6
- package/lib/module/networking/xmpp/sendMessageReaction.xmpp.js.map +1 -1
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/push/sealedPush.js +11 -1
- package/lib/module/push/sealedPush.js.map +1 -1
- package/lib/module/push/sealedPushTask.js +62 -18
- package/lib/module/push/sealedPushTask.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/VideoCallOverlay.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/callActions.d.ts +6 -0
- package/lib/typescript/components/VideoCalls/callActions.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/systemCall.d.ts +25 -0
- package/lib/typescript/components/VideoCalls/systemCall.d.ts.map +1 -0
- package/lib/typescript/components/VideoCalls/useCallKeep.d.ts +8 -23
- package/lib/typescript/components/VideoCalls/useCallKeep.d.ts.map +1 -1
- package/lib/typescript/helpers/incomingCallFromPush.d.ts +5 -13
- package/lib/typescript/helpers/incomingCallFromPush.d.ts.map +1 -1
- package/lib/typescript/main.d.ts +6 -1
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/networking/callTokenStanza.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendMessageReaction.xmpp.d.ts +13 -1
- package/lib/typescript/networking/xmpp/sendMessageReaction.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +2 -4
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/push/sealedPush.d.ts +6 -0
- package/lib/typescript/push/sealedPush.d.ts.map +1 -1
- package/lib/typescript/push/sealedPushTask.d.ts +31 -7
- package/lib/typescript/push/sealedPushTask.d.ts.map +1 -1
- package/lib/typescript/types/models/xmpp.model.d.ts +2 -4
- package/lib/typescript/types/models/xmpp.model.d.ts.map +1 -1
- package/lib/typescript/version.d.ts +1 -1
- package/package.json +1 -1
- package/plugins/notification-service/NotificationService.swift +105 -19
- package/plugins/withNotificationServiceExtension.js +44 -4
- package/src/components/Menu/HeaderRoomListMenu.tsx +13 -8
- package/src/components/MessageBubble/Message.tsx +16 -5
- package/src/components/VideoCalls/VideoCallOverlay.tsx +18 -2
- package/src/components/VideoCalls/callActions.ts +28 -0
- package/src/components/VideoCalls/systemCall.ts +109 -0
- package/src/components/VideoCalls/useCallKeep.ts +91 -101
- package/src/helpers/incomingCallFromPush.ts +97 -26
- package/src/main.ts +9 -1
- package/src/networking/callTokenStanza.ts +20 -1
- package/src/networking/xmpp/sendMessageReaction.xmpp.ts +38 -6
- package/src/networking/xmppClient.ts +2 -2
- package/src/push/sealedPush.ts +11 -0
- package/src/push/sealedPushTask.ts +95 -16
- package/src/types/models/xmpp.model.ts +2 -1
- package/src/version.ts +1 -1
|
@@ -310,6 +310,8 @@ const handleCallStateData = (
|
|
|
310
310
|
!!currentCall.callId &&
|
|
311
311
|
currentCall.callId === stanzaCallId;
|
|
312
312
|
|
|
313
|
+
if (stanzaCallId && currentCall.callId && !callIdMatches) {return;}
|
|
314
|
+
|
|
313
315
|
const isTerminalState =
|
|
314
316
|
state === 'ended' ||
|
|
315
317
|
state === 'declined' ||
|
|
@@ -381,7 +383,7 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
381
383
|
.split('/')[0]
|
|
382
384
|
.split('@')[0]
|
|
383
385
|
.trim();
|
|
384
|
-
handleCallStateData(
|
|
386
|
+
handleCallStateData(data, fromRoom);
|
|
385
387
|
|
|
386
388
|
// Server call-logs (carry callerXmppUsername / durationMs) should
|
|
387
389
|
// flow on to onRealtimeMessage / onMessageHistory where they become
|
|
@@ -394,6 +396,13 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
394
396
|
return true;
|
|
395
397
|
}
|
|
396
398
|
|
|
399
|
+
if (dataType === 'call-state-declined') {
|
|
400
|
+
handleCallStateData({
|
|
401
|
+
attrs: { ...data.attrs, state: 'declined' },
|
|
402
|
+
} as unknown as Element);
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
|
|
397
406
|
if (dataType === 'call-invite') {
|
|
398
407
|
const inviteKind = String(data.attrs?.kind || '').toLowerCase();
|
|
399
408
|
const normalized: 'audio' | 'video' =
|
|
@@ -528,6 +537,16 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
528
537
|
return true;
|
|
529
538
|
}
|
|
530
539
|
|
|
540
|
+
if (
|
|
541
|
+
callState.direction === 'incoming' &&
|
|
542
|
+
callState.phase !== 'idle' &&
|
|
543
|
+
!!callId &&
|
|
544
|
+
callState.callId === callId
|
|
545
|
+
) {
|
|
546
|
+
callTrace('drop call-token: call already known from push', { callId });
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
|
|
531
550
|
store.dispatch(
|
|
532
551
|
setIncomingCallToken({
|
|
533
552
|
roomJid,
|
|
@@ -1,18 +1,51 @@
|
|
|
1
1
|
import { Client, xml } from '@xmpp/client';
|
|
2
|
+
import { shouldEncrypt } from '../../e2ee/send';
|
|
3
|
+
|
|
4
|
+
export interface ReactionStanzaData {
|
|
5
|
+
firstName?: string;
|
|
6
|
+
lastName?: string;
|
|
7
|
+
photoURL?: string;
|
|
8
|
+
push?: boolean;
|
|
9
|
+
messageAuthor?: string;
|
|
10
|
+
messageText?: string;
|
|
11
|
+
isMediafile?: string;
|
|
12
|
+
mimetype?: string;
|
|
13
|
+
fileName?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const REACTION_MESSAGE_TEXT_MAX = 120;
|
|
2
17
|
|
|
3
18
|
export function sendMessageReaction(
|
|
4
19
|
client: Client,
|
|
5
20
|
messageId: string,
|
|
6
21
|
roomJid: string,
|
|
7
22
|
reactionsList: string[],
|
|
8
|
-
data:
|
|
9
|
-
reactionSymbol?: any,
|
|
23
|
+
data: ReactionStanzaData = {}
|
|
10
24
|
) {
|
|
11
25
|
const id = `message-reaction:${Date.now().toString()}`;
|
|
12
26
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
27
|
+
const push = Boolean(data.push) && reactionsList.length > 0;
|
|
28
|
+
const messageText =
|
|
29
|
+
push && !shouldEncrypt(roomJid)
|
|
30
|
+
? String(data.messageText ?? '').slice(0, REACTION_MESSAGE_TEXT_MAX)
|
|
31
|
+
: '';
|
|
32
|
+
|
|
33
|
+
const dataReaction: Record<string, string> = {
|
|
34
|
+
senderFirstName: data.firstName ?? '',
|
|
35
|
+
senderLastName: data.lastName ?? '',
|
|
36
|
+
senderJID: client.jid?.toString() ?? '',
|
|
37
|
+
roomJid,
|
|
38
|
+
...(data.photoURL ? { photoURL: data.photoURL } : {}),
|
|
39
|
+
...(push
|
|
40
|
+
? {
|
|
41
|
+
push: 'true',
|
|
42
|
+
messageAuthor: data.messageAuthor ?? '',
|
|
43
|
+
messageText,
|
|
44
|
+
isMediafile: data.isMediafile ?? '',
|
|
45
|
+
mimetype: data.mimetype ?? '',
|
|
46
|
+
fileName: data.fileName ?? '',
|
|
47
|
+
}
|
|
48
|
+
: {}),
|
|
16
49
|
};
|
|
17
50
|
|
|
18
51
|
const message = xml(
|
|
@@ -31,7 +64,6 @@ export function sendMessageReaction(
|
|
|
31
64
|
xmlns: 'urn:xmpp:reactions:0',
|
|
32
65
|
},
|
|
33
66
|
...reactionsList.map((reaction) => xml('reaction', {}, reaction ?? ''))
|
|
34
|
-
// xml('reaction', {}, reactionSymbol ?? '👋'),
|
|
35
67
|
),
|
|
36
68
|
xml('data', dataReaction),
|
|
37
69
|
xml('store', { xmlns: 'urn:xmpp:hints' })
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
HistoryPageCursor,
|
|
17
17
|
} from './xmpp/getHistory.xmpp';
|
|
18
18
|
import { sendTextMessage } from './xmpp/sendTextMessage.xmpp';
|
|
19
|
-
import { sendMessageReaction } from './xmpp/sendMessageReaction.xmpp';
|
|
19
|
+
import { sendMessageReaction, type ReactionStanzaData } from './xmpp/sendMessageReaction.xmpp';
|
|
20
20
|
import { sendReceivedReceipt } from './xmpp/sendReceivedReceipt.xmpp';
|
|
21
21
|
import { sendDisplayedMarker } from './xmpp/sendDisplayedMarker.xmpp';
|
|
22
22
|
import { sendTextMessageWithTranslateTag } from './xmpp/sendTextMessageWithTranslateTag.xmpp';
|
|
@@ -1646,7 +1646,7 @@ export class XmppClient {
|
|
|
1646
1646
|
messageId: string,
|
|
1647
1647
|
roomJid: string,
|
|
1648
1648
|
reactionsList: string[],
|
|
1649
|
-
data?:
|
|
1649
|
+
data?: ReactionStanzaData
|
|
1650
1650
|
) {
|
|
1651
1651
|
sendMessageReaction(
|
|
1652
1652
|
this.client,
|
package/src/push/sealedPush.ts
CHANGED
|
@@ -20,6 +20,8 @@ export interface SealedPushEnvelope {
|
|
|
20
20
|
msgID: string;
|
|
21
21
|
/** Recipient. */
|
|
22
22
|
userJid: string;
|
|
23
|
+
/** 'reaction' for a push about an emoji put on the user's message; absent for a message. */
|
|
24
|
+
type?: string;
|
|
23
25
|
/** Base64 of the sealed box; absent when the service could not seal. */
|
|
24
26
|
enc?: string;
|
|
25
27
|
}
|
|
@@ -35,8 +37,14 @@ export interface SealedPushContent {
|
|
|
35
37
|
msgID: string;
|
|
36
38
|
/** Sender avatar URL, '' when none. */
|
|
37
39
|
image: string;
|
|
40
|
+
/** 'reaction' with the emoji in `reaction`; absent for a message. */
|
|
41
|
+
type?: string;
|
|
42
|
+
reaction?: string;
|
|
38
43
|
}
|
|
39
44
|
|
|
45
|
+
export const isReactionPush = (envelope: Pick<SealedPushEnvelope, 'type'>): boolean =>
|
|
46
|
+
envelope.type === 'reaction';
|
|
47
|
+
|
|
40
48
|
export type SealedPushFailure =
|
|
41
49
|
/** No key on this device (never generated, or the store is not readable). */
|
|
42
50
|
| 'no-key'
|
|
@@ -68,6 +76,7 @@ export const sealedPushEnvelopeOf = (
|
|
|
68
76
|
jid: str(data.jid),
|
|
69
77
|
msgID: str(data.msgID),
|
|
70
78
|
userJid: str(data.userJid),
|
|
79
|
+
...(str(data.type) ? { type: str(data.type) } : {}),
|
|
71
80
|
...(enc ? { enc } : {}),
|
|
72
81
|
};
|
|
73
82
|
};
|
|
@@ -88,6 +97,8 @@ const parseContent = (plaintext: Uint8Array): SealedPushContent | null => {
|
|
|
88
97
|
chatJid: str(parsed.chatJid),
|
|
89
98
|
msgID: str(parsed.msgID),
|
|
90
99
|
image: str(parsed.image),
|
|
100
|
+
...(str(parsed.type) ? { type: str(parsed.type) } : {}),
|
|
101
|
+
...(str(parsed.reaction) ? { reaction: str(parsed.reaction) } : {}),
|
|
91
102
|
};
|
|
92
103
|
} catch {
|
|
93
104
|
return null;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { AppState, Platform } from 'react-native';
|
|
2
2
|
import { pushLog } from '../utils/devLogger';
|
|
3
|
+
import { isCallPush } from '../helpers/callPush';
|
|
3
4
|
import { loadPushSecretKey } from './pushKeyStore';
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
isReactionPush,
|
|
7
|
+
openSealedPush,
|
|
8
|
+
sealedPushEnvelopeOf,
|
|
9
|
+
type OpenSealedPushResult,
|
|
10
|
+
} from './sealedPush';
|
|
5
11
|
|
|
6
12
|
// Android half of encrypted pushes. A sealed push is data-only, so the OS
|
|
7
13
|
// shows nothing by itself: expo-notifications hands it to a background
|
|
@@ -18,12 +24,40 @@ export const SEALED_PUSH_TASK = 'ETHORA_SEALED_PUSH';
|
|
|
18
24
|
export interface SealedPushTaskOptions {
|
|
19
25
|
/** Android notification channel; the OS default channel when omitted. */
|
|
20
26
|
channelId?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Channel for a reaction to the user's message (a silent one, Telegram's
|
|
29
|
+
* way); `channelId` when omitted. Reactions carry no sound of their own
|
|
30
|
+
* either way.
|
|
31
|
+
*/
|
|
32
|
+
reactionChannelId?: string;
|
|
21
33
|
/** Shown when the box does not open (no key, another key, damaged). Default "New message". */
|
|
22
34
|
placeholderTitle?: string;
|
|
23
35
|
placeholderBody?: string;
|
|
36
|
+
/**
|
|
37
|
+
* An incoming-call push (data-only, high priority) while the app is not
|
|
38
|
+
* in the foreground; the host shows its own incoming-call notification
|
|
39
|
+
* (full-screen intent, Answer / Decline). Not called in the foreground,
|
|
40
|
+
* where the XMPP invite rings the in-app call screen.
|
|
41
|
+
*/
|
|
42
|
+
onCallPush?: (data: Record<string, unknown>) => void | Promise<void>;
|
|
43
|
+
onMessageShown?: (shown: ShownMessagePush) => void | Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ShownMessagePush {
|
|
47
|
+
identifier: string;
|
|
48
|
+
channelId?: string;
|
|
49
|
+
title: string;
|
|
50
|
+
body: string;
|
|
51
|
+
sender: string;
|
|
52
|
+
senderJid: string;
|
|
53
|
+
chat: string;
|
|
54
|
+
chatJid: string;
|
|
55
|
+
image: string;
|
|
56
|
+
reaction: boolean;
|
|
24
57
|
}
|
|
25
58
|
|
|
26
59
|
const PLACEHOLDER_TITLE = 'New message';
|
|
60
|
+
const PLACEHOLDER_REACTION_TITLE = 'New reaction';
|
|
27
61
|
|
|
28
62
|
let registered = false;
|
|
29
63
|
|
|
@@ -49,9 +83,9 @@ const loadNotifications = (): any => {
|
|
|
49
83
|
* itself, `data.dataString` carries the same as a JSON string on some
|
|
50
84
|
* versions, and a Firebase `RemoteMessage` keeps them under `data.data`.
|
|
51
85
|
*/
|
|
52
|
-
|
|
86
|
+
const pushDataCandidates = (payload: unknown): unknown[] => {
|
|
53
87
|
const root = payload && typeof payload === 'object' ? (payload as Record<string, unknown>) : null;
|
|
54
|
-
if (!root) {return
|
|
88
|
+
if (!root) {return [];}
|
|
55
89
|
const candidates: unknown[] = [root.data, root];
|
|
56
90
|
const data = root.data && typeof root.data === 'object' ? (root.data as Record<string, unknown>) : null;
|
|
57
91
|
if (data) {
|
|
@@ -64,30 +98,39 @@ export const sealedPushDataOf = (payload: unknown): Record<string, unknown> | nu
|
|
|
64
98
|
}
|
|
65
99
|
candidates.push(data.data);
|
|
66
100
|
}
|
|
67
|
-
|
|
68
|
-
if (sealedPushEnvelopeOf(candidate as Record<string, unknown>)) {
|
|
69
|
-
return candidate as Record<string, unknown>;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return null;
|
|
101
|
+
return candidates.filter((c) => c && typeof c === 'object');
|
|
73
102
|
};
|
|
74
103
|
|
|
104
|
+
export const sealedPushDataOf = (payload: unknown): Record<string, unknown> | null =>
|
|
105
|
+
(pushDataCandidates(payload).find((candidate) =>
|
|
106
|
+
sealedPushEnvelopeOf(candidate as Record<string, unknown>)
|
|
107
|
+
) as Record<string, unknown> | undefined) ?? null;
|
|
108
|
+
|
|
109
|
+
/** The call fields of an incoming-call push in the task payload, if it is one. */
|
|
110
|
+
export const callPushDataOf = (payload: unknown): Record<string, unknown> | null =>
|
|
111
|
+
(pushDataCandidates(payload).find((candidate) =>
|
|
112
|
+
isCallPush(candidate as Record<string, unknown>)
|
|
113
|
+
) as Record<string, unknown> | undefined) ?? null;
|
|
114
|
+
|
|
75
115
|
const notificationContent = (result: OpenSealedPushResult, options: SealedPushTaskOptions) => {
|
|
76
116
|
const { envelope } = result;
|
|
77
117
|
// What the tap handler (`handlePushPayload` through the host's response
|
|
78
118
|
// listener) needs: the same ids a plain push carries on `data`.
|
|
119
|
+
const reaction = isReactionPush(envelope);
|
|
79
120
|
const data = {
|
|
80
121
|
jid: envelope.jid,
|
|
81
122
|
msgID: envelope.msgID,
|
|
82
123
|
userJid: envelope.userJid,
|
|
83
124
|
sealed: true,
|
|
125
|
+
...(reaction ? { type: 'reaction' } : {}),
|
|
84
126
|
};
|
|
127
|
+
const sound = reaction ? false : 'default';
|
|
85
128
|
if (!result.ok) {
|
|
86
129
|
return {
|
|
87
|
-
title: options.placeholderTitle || PLACEHOLDER_TITLE,
|
|
130
|
+
title: options.placeholderTitle || (reaction ? PLACEHOLDER_REACTION_TITLE : PLACEHOLDER_TITLE),
|
|
88
131
|
...(options.placeholderBody ? { body: options.placeholderBody } : {}),
|
|
89
132
|
data,
|
|
90
|
-
sound
|
|
133
|
+
sound,
|
|
91
134
|
};
|
|
92
135
|
}
|
|
93
136
|
const { content } = result;
|
|
@@ -95,14 +138,16 @@ const notificationContent = (result: OpenSealedPushResult, options: SealedPushTa
|
|
|
95
138
|
title: content.title || content.sender || content.chat || PLACEHOLDER_TITLE,
|
|
96
139
|
body: content.body,
|
|
97
140
|
data: { ...data, chatJid: content.chatJid, senderJid: content.senderJid },
|
|
98
|
-
sound
|
|
141
|
+
sound,
|
|
99
142
|
};
|
|
100
143
|
};
|
|
101
144
|
|
|
102
145
|
/**
|
|
103
146
|
* Open a sealed push and show it. One notification per chat: the room JID
|
|
104
147
|
* is the identifier, so a newer message replaces the older one the way the
|
|
105
|
-
* service's collapse key does for plain pushes.
|
|
148
|
+
* service's collapse key does for plain pushes. A reaction has its own
|
|
149
|
+
* identifier per chat (and its own channel), so it never replaces the
|
|
150
|
+
* chat's new-message notification.
|
|
106
151
|
*/
|
|
107
152
|
export async function presentSealedPush(
|
|
108
153
|
data: Record<string, unknown>,
|
|
@@ -122,11 +167,34 @@ export async function presentSealedPush(
|
|
|
122
167
|
console.warn(`[push] sealed push kid=${envelope.kid} not opened (${result.reason}), showing the placeholder`);
|
|
123
168
|
pushLog('warn', `push: sealed push not opened (${result.reason}), showing the placeholder`);
|
|
124
169
|
}
|
|
170
|
+
const reaction = isReactionPush(envelope);
|
|
171
|
+
const base = envelope.jid || envelope.msgID || '';
|
|
172
|
+
const identifier = base ? (reaction ? `${base}#reaction` : base) : undefined;
|
|
173
|
+
const channelId = (reaction && options.reactionChannelId) || options.channelId;
|
|
174
|
+
const content = notificationContent(result, options);
|
|
125
175
|
await notifications.scheduleNotificationAsync({
|
|
126
|
-
identifier
|
|
127
|
-
content
|
|
128
|
-
trigger:
|
|
176
|
+
identifier,
|
|
177
|
+
content,
|
|
178
|
+
trigger: channelId ? { channelId } : null,
|
|
129
179
|
});
|
|
180
|
+
if (result.ok && result.content.image && identifier && options.onMessageShown) {
|
|
181
|
+
try {
|
|
182
|
+
await options.onMessageShown({
|
|
183
|
+
identifier,
|
|
184
|
+
channelId,
|
|
185
|
+
title: content.title,
|
|
186
|
+
body: content.body ?? '',
|
|
187
|
+
sender: result.content.sender,
|
|
188
|
+
senderJid: result.content.senderJid,
|
|
189
|
+
chat: result.content.chat,
|
|
190
|
+
chatJid: result.content.chatJid,
|
|
191
|
+
image: result.content.image,
|
|
192
|
+
reaction,
|
|
193
|
+
});
|
|
194
|
+
} catch (e) {
|
|
195
|
+
pushLog('warn', 'push: drawing the sender avatar failed', e);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
130
198
|
return result;
|
|
131
199
|
}
|
|
132
200
|
|
|
@@ -150,6 +218,17 @@ export function registerSealedPushTask(options: SealedPushTaskOptions = {}): boo
|
|
|
150
218
|
}
|
|
151
219
|
taskManager.defineTask(SEALED_PUSH_TASK, async ({ data, error }: { data: unknown; error: unknown }) => {
|
|
152
220
|
if (error) {return;}
|
|
221
|
+
const call = callPushDataOf(data);
|
|
222
|
+
if (call) {
|
|
223
|
+
if (AppState.currentState === 'active' || !options.onCallPush) {return;}
|
|
224
|
+
try {
|
|
225
|
+
console.log(`[push] incoming call push ${String(call.callId ?? '')}`);
|
|
226
|
+
await options.onCallPush(call);
|
|
227
|
+
} catch (e) {
|
|
228
|
+
pushLog('warn', 'push: showing an incoming call failed', e);
|
|
229
|
+
}
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
153
232
|
const map = sealedPushDataOf(data);
|
|
154
233
|
if (!map) {return;}
|
|
155
234
|
// In the foreground the room is live over XMPP; the host's
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// methods) rather than duplicating here.
|
|
6
6
|
|
|
7
7
|
import { Client } from '@xmpp/client';
|
|
8
|
+
import type { ReactionStanzaData } from '../../networking/xmpp/sendMessageReaction.xmpp';
|
|
8
9
|
import XmppClient, {
|
|
9
10
|
HistoryPage,
|
|
10
11
|
HistoryPageCursor,
|
|
@@ -153,7 +154,7 @@ export interface XmppClientInterface {
|
|
|
153
154
|
messageId: string,
|
|
154
155
|
roomJid: string,
|
|
155
156
|
reactionsList: string[],
|
|
156
|
-
data?:
|
|
157
|
+
data?: ReactionStanzaData
|
|
157
158
|
): void;
|
|
158
159
|
sendTextMessageWithTranslateTagStanza?(
|
|
159
160
|
roomJID: string,
|
package/src/version.ts
CHANGED