feat: enhance incoming call notification logic to track seen calls and filter fresh calls
This commit is contained in:
@@ -102,6 +102,7 @@ export function IncomingCallNotification() {
|
||||
const { activeCall, startCall } = useCall();
|
||||
const [incomingCall, setIncomingCall] = useState<IncomingCall | null>(null);
|
||||
const [declinedRooms, setDeclinedRooms] = useState<Set<string>>(new Set());
|
||||
const [seenCalls, setSeenCalls] = useState<Map<string, number>>(new Map());
|
||||
|
||||
/**
|
||||
* Checks all rooms for incoming calls
|
||||
@@ -118,15 +119,25 @@ export function IncomingCallNotification() {
|
||||
|
||||
// Check all joined rooms for calls
|
||||
const rooms = mx.getRooms();
|
||||
const now = Date.now();
|
||||
const MAX_CALL_AGE = 10000; // 10 seconds
|
||||
|
||||
// Find the first room with an incoming call
|
||||
const incomingRoom = rooms.find((room) => {
|
||||
// Only monitor DMs and small groups
|
||||
if (!isDirectOrSmallGroup(room)) return false;
|
||||
// Only monitor 1-1 DMs (exactly 2 members)
|
||||
if (room.getJoinedMemberCount() !== 2) return false;
|
||||
// Skip rooms we've declined
|
||||
if (declinedRooms.has(room.roomId)) return false;
|
||||
const { members } = getOtherCallMembersWithTime(room, myUserId);
|
||||
return members.length > 0;
|
||||
const { members, earliestTime } = getOtherCallMembersWithTime(room, myUserId);
|
||||
if (members.length === 0) return false;
|
||||
|
||||
// Skip if we've already seen this exact call session
|
||||
const lastSeenTime = seenCalls.get(room.roomId);
|
||||
if (lastSeenTime && lastSeenTime === earliestTime) return false;
|
||||
|
||||
// Only show if the call is fresh (less than 10 seconds old)
|
||||
const callAge = now - earliestTime;
|
||||
return callAge < MAX_CALL_AGE;
|
||||
});
|
||||
|
||||
if (incomingRoom) {
|
||||
@@ -140,28 +151,33 @@ export function IncomingCallNotification() {
|
||||
} else {
|
||||
setIncomingCall(null);
|
||||
}
|
||||
}, [mx, activeCall, declinedRooms]);
|
||||
}, [mx, activeCall, declinedRooms, seenCalls]);
|
||||
|
||||
/**
|
||||
* Handles state events for call member changes
|
||||
*/
|
||||
const handleStateEvent = useCallback((event: MatrixEvent) => {
|
||||
if (event.getType() === CALL_MEMBER_EVENT_TYPE) {
|
||||
// Clear declined status if call ended in that room
|
||||
// Clear declined status and seen calls if call ended in that room
|
||||
const roomId = event.getRoomId();
|
||||
if (roomId && declinedRooms.has(roomId)) {
|
||||
if (roomId) {
|
||||
const room = mx.getRoom(roomId);
|
||||
if (room) {
|
||||
const myUserId = mx.getUserId();
|
||||
if (myUserId) {
|
||||
const members = getOtherCallMembers(room, myUserId);
|
||||
if (members.length === 0) {
|
||||
// Call ended, remove from declined
|
||||
// Call ended, clear tracking
|
||||
setDeclinedRooms((prev) => {
|
||||
const newSet = new Set(prev);
|
||||
newSet.delete(roomId);
|
||||
return newSet;
|
||||
});
|
||||
setSeenCalls((prev) => {
|
||||
const newMap = new Map(prev);
|
||||
newMap.delete(roomId);
|
||||
return newMap;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,9 +199,12 @@ export function IncomingCallNotification() {
|
||||
}, [mx, handleStateEvent, checkForIncomingCalls]);
|
||||
|
||||
// Play/stop dialing sound based on incoming call state
|
||||
// Only play sound if call started less than 15 seconds ago
|
||||
// Mark call as seen when displayed
|
||||
useEffect(() => {
|
||||
if (incomingCall) {
|
||||
// Mark this call as seen so we don't notify again
|
||||
setSeenCalls((prev) => new Map(prev).set(incomingCall.roomId, incomingCall.startTime));
|
||||
|
||||
const callAge = Date.now() - incomingCall.startTime;
|
||||
const MAX_CALL_AGE_FOR_SOUND = 15000; // 15 seconds
|
||||
|
||||
@@ -212,6 +231,7 @@ export function IncomingCallNotification() {
|
||||
if (!incomingCall) return;
|
||||
|
||||
getCallSounds().stopDialingLoop();
|
||||
setSeenCalls((prev) => new Map(prev).set(incomingCall.roomId, incomingCall.startTime));
|
||||
try {
|
||||
await startCall(incomingCall.roomId, CallType.Voice);
|
||||
} catch (error) {
|
||||
@@ -226,6 +246,7 @@ export function IncomingCallNotification() {
|
||||
if (!incomingCall) return;
|
||||
|
||||
getCallSounds().stopDialingLoop();
|
||||
setSeenCalls((prev) => new Map(prev).set(incomingCall.roomId, incomingCall.startTime));
|
||||
setDeclinedRooms((prev) => new Set(prev).add(incomingCall.roomId));
|
||||
setIncomingCall(null);
|
||||
}, [incomingCall]);
|
||||
@@ -237,6 +258,7 @@ export function IncomingCallNotification() {
|
||||
|
||||
const room = mx.getRoom(incomingCall.roomId);
|
||||
const firstCaller = incomingCall.callerIds[0];
|
||||
const isGroupCall = room ? room.getJoinedMemberCount() > 2 : false;
|
||||
|
||||
/**
|
||||
* Gets the display name for a user
|
||||
@@ -287,10 +309,12 @@ export function IncomingCallNotification() {
|
||||
</span>
|
||||
)}
|
||||
</Text>
|
||||
<Text size="T200" className={css.RoomName}>
|
||||
<Icon size="100" src={Icons.Phone} />
|
||||
<span>Calling from {incomingCall.roomName}</span>
|
||||
</Text>
|
||||
{!isGroupCall && (
|
||||
<Text size="T200" className={css.RoomName}>
|
||||
<Icon size="100" src={Icons.Phone} />
|
||||
<span>Calling from {incomingCall.roomName}</span>
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user