fix: solve small pm chat ui issues

unwrap the pill
fix the fetching images in pm not auto download
This commit is contained in:
2026-05-25 17:17:32 +02:00
parent 1259645706
commit 161f57f52e
28 changed files with 697 additions and 82 deletions

View File

@@ -44,6 +44,7 @@ export class DirectCallService {
private readonly users = this.store.selectSignal(selectAllUsers);
private readonly sessionsSignal = signal<DirectCallSession[]>([]);
private readonly mobileOverlayCallId = signal<string | null>(null);
private readonly pendingIncomingCallEvents: DirectCallEventPayload[] = [];
readonly sessions = computed(() => this.sessionsSignal());
readonly activeSessions = computed(() => this.sessions().filter((session) => session.status !== 'ended'));
@@ -85,6 +86,18 @@ export class DirectCallService {
}
});
effect(() => {
if (!this.currentUserId() || this.pendingIncomingCallEvents.length === 0) {
return;
}
const pendingEvents = this.pendingIncomingCallEvents.splice(0);
for (const payload of pendingEvents) {
void this.handleIncomingCallEvent(payload);
}
});
effect(() => {
const session = this.currentSession();
@@ -159,7 +172,7 @@ export class DirectCallService {
}
const existing = this.sessionById(conversation.id);
const session = existing ?? this.createSession({
const session = existing && existing.status !== 'ended' ? existing : this.createSession({
callId: conversation.id,
conversationId: conversation.id,
createdAt: Date.now(),
@@ -171,6 +184,14 @@ export class DirectCallService {
this.upsertSession(session);
this.currentSession.set(session);
await this.directMessages.recordCallStarted(
session.conversationId,
meParticipant,
Object.values(session.participants).map((participant) => participant.profile),
session.createdAt
);
await this.joinCall(session.callId, false);
this.sendCallEvent(peerParticipant.userId, 'ring', session);
await this.openCallView(session.callId);
@@ -236,6 +257,8 @@ export class DirectCallService {
}
declineIncomingCall(callId: string): void {
this.audio.stop(AppSound.Call);
const session = this.sessionById(callId);
if (!session || session.status === 'ended') {
@@ -253,8 +276,6 @@ export class DirectCallService {
status: 'ended' as const
};
this.audio.stop(AppSound.Call);
if (meId) {
this.broadcastCallEvent('leave', session);
}
@@ -385,18 +406,29 @@ export class DirectCallService {
}
private async handleIncomingCallEvent(payload: DirectCallEventPayload): Promise<void> {
const currentUserIds = this.currentUserIds();
const meId = this.currentUserId();
if (!meId || payload.sender.userId === meId) {
if (!meId) {
this.pendingIncomingCallEvents.push(payload);
return;
}
if (!this.callPayloadIncludesParticipant(payload, meId)) {
if (currentUserIds.has(payload.sender.userId)) {
return;
}
if (!this.callPayloadIncludesAnyParticipant(payload, currentUserIds)) {
return;
}
const participants = this.callParticipantsFromPayload(payload);
const existing = this.sessionById(payload.callId);
if (this.isStaleRingForEndedSession(payload, existing)) {
return;
}
const incomingSession = this.createSession({
callId: payload.callId,
conversationId: payload.conversationId,
@@ -424,14 +456,22 @@ export class DirectCallService {
if (payload.action === 'ring') {
await this.ensureCallConversation(session);
await this.directMessages.recordCallStarted(
session.conversationId,
payload.sender,
Object.values(session.participants).map((participant) => participant.profile),
session.createdAt
);
if (this.shouldAlertIncomingCall(session)) {
const latestSession = this.sessionById(session.callId);
if (latestSession && this.shouldPlayIncomingCallAlert(latestSession)) {
this.audio.playLoop(AppSound.Call);
} else {
this.audio.stop(AppSound.Call);
}
if (this.shouldAlertIncomingCall(session)) {
if (latestSession && this.shouldPlayIncomingCallAlert(latestSession)) {
await this.showIncomingNotification(payload.sender.displayName, payload.callId);
}
@@ -475,6 +515,14 @@ export class DirectCallService {
this.upsertSession(session);
this.currentSession.set(session);
await this.directMessages.recordCallStarted(
session.conversationId,
meParticipant,
Object.values(session.participants).map((participant) => participant.profile),
session.createdAt
);
await this.joinCall(session.callId, false);
this.broadcastCallEvent('ring', this.sessionById(session.callId) ?? session);
await this.router.navigate(['/call', session.callId]);
@@ -711,9 +759,15 @@ export class DirectCallService {
]);
}
private callPayloadIncludesParticipant(payload: DirectCallEventPayload, participantId: string): boolean {
return payload.participantIds.includes(participantId)
|| (payload.participants ?? []).some((participant) => participant.userId === participantId);
private callPayloadIncludesAnyParticipant(payload: DirectCallEventPayload, participantIds: Set<string>): boolean {
return payload.participantIds.some((participantId) => participantIds.has(participantId))
|| (payload.participants ?? []).some((participant) => participantIds.has(participant.userId));
}
private isStaleRingForEndedSession(payload: DirectCallEventPayload, existing: DirectCallSession | null): boolean {
return payload.action === 'ring'
&& existing?.status === 'ended'
&& payload.createdAt <= existing.createdAt;
}
private groupConversationTitle(session: DirectCallSession): string {
@@ -867,6 +921,10 @@ export class DirectCallService {
return session.status !== 'connected' && !this.isDoNotDisturb();
}
private shouldPlayIncomingCallAlert(session: DirectCallSession): boolean {
return this.shouldAlertIncomingCall(session) && this.incomingCall()?.callId === session.callId;
}
private isDoNotDisturb(): boolean {
return this.currentUser()?.status === 'busy';
}
@@ -923,6 +981,25 @@ export class DirectCallService {
return user ? this.userKey(user) : null;
}
private currentUserIds(): Set<string> {
const ids = new Set<string>();
const user = this.currentUser();
if (user?.id) {
ids.add(user.id);
}
if (user?.oderId) {
ids.add(user.oderId);
}
if (user?.peerId) {
ids.add(user.peerId);
}
return ids;
}
private requireCurrentUser(): User {
const user = this.currentUser();