Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a2f18e3d5 |
Generated
+4
-4
@@ -81,7 +81,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "4.13.0",
|
||||
"@lotusguild/element-call-embedded": "0.25.0-lotus.23",
|
||||
"@lotusguild/element-call-embedded": "0.25.0-lotus.22",
|
||||
"@playwright/test": "1.63.0",
|
||||
"@rollup/plugin-inject": "5.0.5",
|
||||
"@rollup/plugin-wasm": "6.2.2",
|
||||
@@ -2695,9 +2695,9 @@
|
||||
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
||||
},
|
||||
"node_modules/@lotusguild/element-call-embedded": {
|
||||
"version": "0.25.0-lotus.23",
|
||||
"resolved": "https://code.lotusguild.org/api/packages/LotusGuild/npm/%40lotusguild%2Felement-call-embedded/-/0.25.0-lotus.23/element-call-embedded-0.25.0-lotus.23.tgz",
|
||||
"integrity": "sha512-vRmcWeJcU0Accyl2x3mqNEzrIe8djE5BekyYbYOSCsMflC98rZgD1mO7KOe7bA1cX7gparRf6sAt1fotHoU+bA==",
|
||||
"version": "0.25.0-lotus.22",
|
||||
"resolved": "https://code.lotusguild.org/api/packages/LotusGuild/npm/%40lotusguild%2Felement-call-embedded/-/0.25.0-lotus.22/element-call-embedded-0.25.0-lotus.22.tgz",
|
||||
"integrity": "sha512-AimDKZA4xUKEEyl2XUFUSUDl03tBKFv88T/3igKyH2VqNSPMGnqcQJC5HXIkHLTWrOmg8kLcJ//FFbqlUZiLcA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@matrix-org/matrix-sdk-crypto-wasm": {
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "4.13.0",
|
||||
"@lotusguild/element-call-embedded": "0.25.0-lotus.23",
|
||||
"@lotusguild/element-call-embedded": "0.25.0-lotus.22",
|
||||
"@playwright/test": "1.63.0",
|
||||
"@rollup/plugin-inject": "5.0.5",
|
||||
"@rollup/plugin-wasm": "6.2.2",
|
||||
|
||||
@@ -17,6 +17,8 @@ import {
|
||||
CALL_SESSION_HEARTBEAT_MS,
|
||||
clearCallSession,
|
||||
decideRejoin,
|
||||
othersInCall,
|
||||
rejoinToastBody,
|
||||
readCallSession,
|
||||
writeCallSession,
|
||||
} from '../utils/callRejoin';
|
||||
@@ -112,6 +114,27 @@ export function useCallRejoin(embed: CallEmbed | undefined, joined: boolean): vo
|
||||
};
|
||||
dismissToast(TOAST_ID);
|
||||
clearCallSession();
|
||||
// [Gitea #302] A DM call the other person has since left is over;
|
||||
// starting it again would ring them, so just say so.
|
||||
const dm = l.directs.has(room.roomId);
|
||||
if (
|
||||
dm &&
|
||||
!othersInCall(
|
||||
session.memberships.map((m) => m.userId ?? ''),
|
||||
mx.getUserId() ?? '',
|
||||
)
|
||||
) {
|
||||
// Own id: clicking a toast removes it by id after its onClick runs.
|
||||
setToast({
|
||||
id: `${TOAST_ID}-ended`,
|
||||
iconSrc: Icons.Phone,
|
||||
displayName: 'Call ended',
|
||||
body: `${room.name ?? 'They'} already left the call.`,
|
||||
roomName: room.name ?? '',
|
||||
roomId: room.roomId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
(l.directs.has(room.roomId) ? l.startDmCall : l.startRoomCall)(room, pref);
|
||||
} catch {
|
||||
@@ -133,6 +156,7 @@ export function useCallRejoin(embed: CallEmbed | undefined, joined: boolean): vo
|
||||
.filter((m) => m.userId === mx.getUserId())
|
||||
.map((m) => m.deviceId),
|
||||
memberCount: memberships.length,
|
||||
dm: latest.current.directs.has(room.roomId),
|
||||
});
|
||||
// The RTC session fills in a moment after sync; keep waiting while it is
|
||||
// empty unless this is the final (timed-out) look.
|
||||
@@ -152,7 +176,7 @@ export function useCallRejoin(embed: CallEmbed | undefined, joined: boolean): vo
|
||||
id: TOAST_ID,
|
||||
iconSrc: Icons.Phone,
|
||||
displayName: 'Rejoin voice?',
|
||||
body: `You were in the call in ${room.name ?? 'a room'} before the restart. Tap to rejoin.`,
|
||||
body: rejoinToastBody(room.name, latest.current.directs.has(room.roomId)),
|
||||
roomName: room.name ?? '',
|
||||
roomId: room.roomId,
|
||||
sticky: true,
|
||||
|
||||
@@ -31,7 +31,6 @@ import { verifyDenoiseAssets } from './denoiseSmokeCheck';
|
||||
import { canDelegateCapability } from './utils';
|
||||
import { getCallPageUrl } from './callPageUrl';
|
||||
import { restrictWidgetMessages } from '../widgetTransport';
|
||||
import { isRingableRoom } from '../../utils/callRing';
|
||||
|
||||
// Maximum time to wait for the embedded Element Call iframe to progress from
|
||||
// initial load to a ready/joined state. If it hasn't by then, we assume the
|
||||
@@ -252,18 +251,8 @@ export class CallEmbed {
|
||||
verifyDenoiseAssets(denoiseModel).catch(() => undefined);
|
||||
}
|
||||
|
||||
// [Gitea #295] Only ask Element Call to notify where a call can ring at all
|
||||
// (DMs, invite-only groups outside a space). In a voice channel or space
|
||||
// room the notification carries an @room mention, so every member got a
|
||||
// highlighted ping (and phone push) whenever a moderator hopped in, and
|
||||
// other clients showed it as a missed call.
|
||||
// `none` needs element-call-embedded ≥ 0.25.0-lotus.23 (older builds ignore it).
|
||||
if (CallEmbed.startingCall(intent)) {
|
||||
let notify = 'none';
|
||||
if (isRingableRoom(room, CallEmbed.dmCall(intent))) {
|
||||
notify = CallEmbed.dmCall(intent) ? 'ring' : 'notification';
|
||||
}
|
||||
params.append('sendNotificationType', notify);
|
||||
params.append('sendNotificationType', CallEmbed.dmCall(intent) ? 'ring' : 'notification');
|
||||
}
|
||||
|
||||
// [Gitea #43] On its own origin when config.json sets elementCallUrl.
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { CALL_REJOIN_MAX_AGE_MS, decideRejoin, RejoinContext } from './callRejoin';
|
||||
import {
|
||||
CALL_REJOIN_MAX_AGE_MS,
|
||||
decideRejoin,
|
||||
othersInCall,
|
||||
rejoinToastBody,
|
||||
RejoinContext,
|
||||
} from './callRejoin';
|
||||
|
||||
const base: RejoinContext = {
|
||||
record: {
|
||||
@@ -54,3 +60,21 @@ describe('decideRejoin', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('decideRejoin: DM calls are never auto-rejoined, only offered (#302)', () => {
|
||||
assert.deepEqual(decideRejoin({ ...base, mode: 'auto', dm: true }), {
|
||||
action: 'ask',
|
||||
roomId: '!r',
|
||||
});
|
||||
assert.deepEqual(decideRejoin({ ...base, mode: 'auto' }), { action: 'auto', roomId: '!r' });
|
||||
});
|
||||
|
||||
it('rejoinToastBody and othersInCall (#302)', () => {
|
||||
assert.equal(
|
||||
rejoinToastBody('Bob Builder', true),
|
||||
'You were in a call with Bob Builder before the restart. Tap to rejoin.',
|
||||
);
|
||||
assert.match(rejoinToastBody('Voice Lounge', false), /in the call in Voice Lounge/);
|
||||
assert.equal(othersInCall(['@me:x'], '@me:x'), false);
|
||||
assert.equal(othersInCall(['@me:x', '@bob:x'], '@me:x'), true);
|
||||
});
|
||||
|
||||
@@ -67,6 +67,8 @@ export type RejoinContext = {
|
||||
ownMemberDevices: string[];
|
||||
/** Number of call memberships in the room, ours included. */
|
||||
memberCount: number;
|
||||
/** A DM call: rejoining one may ring the other person. */
|
||||
dm?: boolean;
|
||||
};
|
||||
|
||||
export type RejoinDecision = { action: 'none' } | { action: 'ask' | 'auto'; roomId: string };
|
||||
@@ -83,5 +85,18 @@ export function decideRejoin(ctx: RejoinContext): RejoinDecision {
|
||||
// Nobody there any more (our own stale membership doesn't count).
|
||||
const others = ctx.memberCount - ctx.ownMemberDevices.length;
|
||||
if (others <= 0) return { action: 'none' };
|
||||
// [Gitea #302] Never rejoin a DM call on our own: if the other person has
|
||||
// just left, starting it again would ring them. Ask instead.
|
||||
if (ctx.dm && mode === 'auto') return { action: 'ask', roomId: record.roomId };
|
||||
return { action: mode, roomId: record.roomId };
|
||||
}
|
||||
|
||||
/** Pure: whether anyone but us is still in the call (by call membership). */
|
||||
export const othersInCall = (memberUserIds: string[], myUserId: string): boolean =>
|
||||
memberUserIds.some((u) => u !== myUserId);
|
||||
|
||||
/** The rejoin toast's text; DMs name the person rather than "the call in <room>". */
|
||||
export const rejoinToastBody = (roomName: string | undefined, dm: boolean): string =>
|
||||
dm
|
||||
? `You were in a call with ${roomName ?? 'them'} before the restart. Tap to rejoin.`
|
||||
: `You were in the call in ${roomName ?? 'a room'} before the restart. Tap to rejoin.`;
|
||||
|
||||
Reference in New Issue
Block a user