feat: signal server tag

This commit is contained in:
2026-06-05 06:16:02 +02:00
parent 6865147e8f
commit bf4e6891d1
69 changed files with 2808 additions and 1269 deletions
@@ -11,12 +11,11 @@ import {
import type { ChatAttachmentMeta, CustomEmoji } from '../../shared-kernel';
import { getStoredCurrentUserId } from '../../core/storage/current-user-storage';
import type { RoomMessageStats } from './database.service';
import { applyBrowserDatabaseSchema, BROWSER_DATABASE_VERSION } from './browser-database-schema';
/** IndexedDB database name for the MetoYou application. */
const DATABASE_NAME = 'metoyou';
const ANONYMOUS_DATABASE_SCOPE = 'anonymous';
/** IndexedDB schema version - bump when adding/changing object stores. */
const DATABASE_VERSION = 3;
/** Names of every object store used by the application. */
const STORE_MESSAGES = 'messages';
const STORE_USERS = 'users';
@@ -432,10 +431,26 @@ export class BrowserDatabaseService {
private openDatabase(databaseName: string): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const request = indexedDB.open(databaseName, DATABASE_VERSION);
const request = indexedDB.open(databaseName, BROWSER_DATABASE_VERSION);
request.onerror = () => reject(request.error);
request.onupgradeneeded = () => this.setupSchema(request.result);
request.onupgradeneeded = (event) => {
const upgradeTransaction = (event.target as IDBOpenDBRequest).transaction;
if (!upgradeTransaction) {
reject(new Error('IndexedDB upgrade transaction is unavailable'));
return;
}
try {
applyBrowserDatabaseSchema(request.result, upgradeTransaction);
} catch (error) {
upgradeTransaction.abort();
reject(error);
}
};
request.onsuccess = () => resolve(request.result);
});
}
@@ -446,58 +461,6 @@ export class BrowserDatabaseService {
this.activeDatabaseName = null;
}
private setupSchema(database: IDBDatabase): void {
const messagesStore = this.ensureStore(database, STORE_MESSAGES, { keyPath: 'id' });
this.ensureIndex(messagesStore, 'roomId', 'roomId');
this.ensureIndex(messagesStore, 'timestamp', 'timestamp');
this.ensureStore(database, STORE_USERS, { keyPath: 'id' });
const roomsStore = this.ensureStore(database, STORE_ROOMS, { keyPath: 'id' });
this.ensureIndex(roomsStore, 'timestamp', 'timestamp');
const reactionsStore = this.ensureStore(database, STORE_REACTIONS, { keyPath: 'id' });
this.ensureIndex(reactionsStore, 'messageId', 'messageId');
this.ensureIndex(reactionsStore, 'userId', 'userId');
const bansStore = this.ensureStore(database, STORE_BANS, { keyPath: 'oderId' });
this.ensureIndex(bansStore, 'roomId', 'roomId');
this.ensureIndex(bansStore, 'expiresAt', 'expiresAt');
this.ensureStore(database, STORE_META, { keyPath: 'id' });
const attachmentsStore = this.ensureStore(database, STORE_ATTACHMENTS, { keyPath: 'id' });
this.ensureIndex(attachmentsStore, 'messageId', 'messageId');
const customEmojisStore = this.ensureStore(database, STORE_CUSTOM_EMOJIS, { keyPath: 'id' });
this.ensureIndex(customEmojisStore, 'updatedAt', 'updatedAt');
this.ensureIndex(customEmojisStore, 'creatorUserId', 'creatorUserId');
}
private ensureStore(
database: IDBDatabase,
name: string,
options?: IDBObjectStoreParameters
): IDBObjectStore {
if (database.objectStoreNames.contains(name)) {
return (database.transaction(name, 'readonly') as IDBTransaction).objectStore(name);
}
return database.createObjectStore(name, options);
}
private ensureIndex(store: IDBObjectStore, name: string, keyPath: string): void {
if (!store.indexNames.contains(name)) {
store.createIndex(name, keyPath, { unique: false });
}
}
private createTransaction(
storeNames: string | string[],
mode: IDBTransactionMode