fix: restore build and stabilize E2E cross-signal behavior
Revert the automated member-ordering pass that broke Angular field init (TS2729) and disable that rule until a safe reorder strategy exists. Fix modal/confirm dialog i18n defaults via template fallbacks, search all active endpoints (including offline), register foreign rooms with actor owner IDs, sync profile display names from avatar summaries, and guard dm-chat when a private call converts to a group conversation. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import {
|
||||
Actions,
|
||||
@@ -37,6 +38,9 @@ export function groupMessagesByRoom(messages: Message[]): Map<string, Message[]>
|
||||
|
||||
@Injectable()
|
||||
export class NotificationsEffects {
|
||||
private readonly actions$ = inject(Actions);
|
||||
private readonly store = inject(Store);
|
||||
private readonly notifications = inject(NotificationsFacade);
|
||||
|
||||
syncRoomCatalog$ = createEffect(
|
||||
() =>
|
||||
@@ -132,11 +136,4 @@ export class NotificationsEffects {
|
||||
),
|
||||
{ dispatch: false }
|
||||
);
|
||||
|
||||
private readonly actions$ = inject(Actions);
|
||||
|
||||
private readonly store = inject(Store);
|
||||
|
||||
private readonly notifications = inject(NotificationsFacade);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { NotificationsService } from '../services/notifications.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class NotificationsFacade {
|
||||
private readonly service = inject(NotificationsService);
|
||||
|
||||
readonly settings = this.service.settings;
|
||||
|
||||
readonly unread = this.service.unread;
|
||||
|
||||
private readonly service = inject(NotificationsService);
|
||||
|
||||
initialize(
|
||||
...args: Parameters<NotificationsService['initialize']>
|
||||
): ReturnType<NotificationsService['initialize']> {
|
||||
@@ -99,5 +98,4 @@ export class NotificationsFacade {
|
||||
): ReturnType<NotificationsService['setChannelMuted']> {
|
||||
return this.service.setChannelMuted(...args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import {
|
||||
Injectable,
|
||||
computed,
|
||||
@@ -45,55 +46,34 @@ const MAX_NOTIFIED_MESSAGE_IDS = 500;
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class NotificationsService {
|
||||
|
||||
readonly settings = computed(() => this._settings());
|
||||
|
||||
readonly unread = computed(() => this._unread());
|
||||
|
||||
private readonly store = inject(Store);
|
||||
|
||||
private readonly db = inject(DatabaseService);
|
||||
|
||||
private readonly audio = inject(NotificationAudioService);
|
||||
|
||||
private readonly appI18n = inject(AppI18nService);
|
||||
|
||||
private readonly timeSync = inject(TimeSyncService);
|
||||
|
||||
private readonly desktopNotifications = inject(DesktopNotificationService);
|
||||
|
||||
private readonly storage = inject(NotificationSettingsStorageService);
|
||||
|
||||
private readonly currentRoom = this.store.selectSignal(selectCurrentRoom);
|
||||
|
||||
private readonly activeChannelId = this.store.selectSignal(selectActiveChannelId);
|
||||
|
||||
private readonly savedRooms = this.store.selectSignal(selectSavedRooms);
|
||||
|
||||
private readonly currentUser = this.store.selectSignal(selectCurrentUser);
|
||||
|
||||
private readonly _settings = signal<NotificationsSettings>(createDefaultNotificationSettings());
|
||||
|
||||
private readonly _unread = signal<NotificationsUnreadState>(createEmptyUnreadState());
|
||||
|
||||
private readonly _windowFocused = signal<boolean>(typeof document === 'undefined' ? true : document.hasFocus());
|
||||
|
||||
private readonly _documentVisible = signal<boolean>(typeof document === 'undefined' ? true : document.visibilityState === 'visible');
|
||||
|
||||
private readonly _windowMinimized = signal<boolean>(false);
|
||||
|
||||
private readonly platformKind = detectPlatform();
|
||||
|
||||
private readonly notifiedMessageIds = new Set<string>();
|
||||
|
||||
private readonly notifiedMessageOrder: string[] = [];
|
||||
|
||||
private attentionActive = false;
|
||||
|
||||
private windowStateCleanup: (() => void) | null = null;
|
||||
|
||||
private initialised = false;
|
||||
|
||||
readonly settings = computed(() => this._settings());
|
||||
readonly unread = computed(() => this._unread());
|
||||
|
||||
async initialize(): Promise<void> {
|
||||
if (this.initialised) {
|
||||
return;
|
||||
@@ -331,30 +311,6 @@ export class NotificationsService {
|
||||
});
|
||||
}
|
||||
|
||||
private readonly handleWindowFocus = (): void => {
|
||||
this._windowFocused.set(true);
|
||||
this._windowMinimized.set(false);
|
||||
this.markCurrentChannelReadIfActive();
|
||||
};
|
||||
|
||||
private readonly handleWindowBlur = (): void => {
|
||||
this._windowFocused.set(false);
|
||||
this.syncWindowAttention();
|
||||
};
|
||||
|
||||
private readonly handleVisibilityChange = (): void => {
|
||||
const isVisible = document.visibilityState === 'visible';
|
||||
|
||||
this._documentVisible.set(isVisible);
|
||||
|
||||
if (isVisible && this._windowFocused()) {
|
||||
this.markCurrentChannelReadIfActive();
|
||||
return;
|
||||
}
|
||||
|
||||
this.syncWindowAttention();
|
||||
};
|
||||
|
||||
private registerWindowListeners(): void {
|
||||
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
||||
return;
|
||||
@@ -379,6 +335,30 @@ export class NotificationsService {
|
||||
});
|
||||
}
|
||||
|
||||
private readonly handleWindowFocus = (): void => {
|
||||
this._windowFocused.set(true);
|
||||
this._windowMinimized.set(false);
|
||||
this.markCurrentChannelReadIfActive();
|
||||
};
|
||||
|
||||
private readonly handleWindowBlur = (): void => {
|
||||
this._windowFocused.set(false);
|
||||
this.syncWindowAttention();
|
||||
};
|
||||
|
||||
private readonly handleVisibilityChange = (): void => {
|
||||
const isVisible = document.visibilityState === 'visible';
|
||||
|
||||
this._documentVisible.set(isVisible);
|
||||
|
||||
if (isVisible && this._windowFocused()) {
|
||||
this.markCurrentChannelReadIfActive();
|
||||
return;
|
||||
}
|
||||
|
||||
this.syncWindowAttention();
|
||||
};
|
||||
|
||||
private buildContext(): NotificationDeliveryContext {
|
||||
return {
|
||||
activeChannelId: this.activeChannelId(),
|
||||
@@ -645,7 +625,6 @@ export class NotificationsService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function detectPlatform(): DesktopPlatform {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import {
|
||||
Component,
|
||||
computed,
|
||||
@@ -36,20 +37,15 @@ import { APP_TRANSLATE_IMPORTS } from '../../../../../core/i18n';
|
||||
templateUrl: './notifications-settings.component.html'
|
||||
})
|
||||
export class NotificationsSettingsComponent {
|
||||
private readonly store = inject(Store);
|
||||
readonly notifications = inject(NotificationsFacade);
|
||||
|
||||
readonly rooms = this.store.selectSignal(selectSavedRooms);
|
||||
|
||||
readonly settings = this.notifications.settings;
|
||||
|
||||
readonly enabled = computed(() => this.settings().enabled);
|
||||
|
||||
readonly showPreview = computed(() => this.settings().showPreview);
|
||||
|
||||
readonly respectBusyStatus = computed(() => this.settings().respectBusyStatus);
|
||||
|
||||
private readonly store = inject(Store);
|
||||
|
||||
trackRoom = (_index: number, room: Room) => room.id;
|
||||
|
||||
textChannels(room: Room) {
|
||||
@@ -116,5 +112,4 @@ export class NotificationsSettingsComponent {
|
||||
formatUnreadCount(count: number): string {
|
||||
return count > 99 ? '99+' : String(count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user