feat: Update how messages load and sync, allow plugins to import messages
All checks were successful
Queue Release Build / prepare (push) Successful in 23s
Deploy Web Apps / deploy (push) Successful in 7m36s
Queue Release Build / build-windows (push) Successful in 28m3s
Queue Release Build / build-linux (push) Successful in 44m14s
Queue Release Build / finalize (push) Successful in 39s
All checks were successful
Queue Release Build / prepare (push) Successful in 23s
Deploy Web Apps / deploy (push) Successful in 7m36s
Queue Release Build / build-windows (push) Successful in 28m3s
Queue Release Build / build-linux (push) Successful in 44m14s
Queue Release Build / finalize (push) Successful in 39s
This commit is contained in:
@@ -57,7 +57,7 @@ The persisted `rooms` store is a local cache of room metadata. Channel topology
|
||||
|
||||
### Browser (IndexedDB)
|
||||
|
||||
All operations run inside IndexedDB transactions in the renderer thread. The browser backend resolves the active database name from the logged-in user, reusing a legacy shared database only when it already belongs to that same account. Queries like `getMessages` pull all messages for a room via the `roomId` index, sort them by timestamp in JS, then apply limit/offset. Deleted messages are normalised on read (content replaced with a sentinel string).
|
||||
All operations run inside IndexedDB transactions in the renderer thread. The browser backend resolves the active database name from the logged-in user, reusing a legacy shared database only when it already belongs to that same account. Queries like `getMessages` pull all messages for a room via the `roomId` index, optionally filter to a text channel, sort them by timestamp in JS, then apply limit/offset. Deleted messages are normalised on read (content replaced with a sentinel string).
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
@@ -66,11 +66,11 @@ sequenceDiagram
|
||||
participant BDB as BrowserDatabaseService
|
||||
participant IDB as IndexedDB
|
||||
|
||||
Eff->>DB: getMessages(roomId, 50)
|
||||
DB->>BDB: getMessages(roomId, 50)
|
||||
Eff->>DB: getMessages(roomId, 50, 0, channelId?)
|
||||
DB->>BDB: getMessages(roomId, 50, 0, channelId?)
|
||||
BDB->>IDB: tx.objectStore("messages")<br/>.index("roomId").getAll(roomId)
|
||||
IDB-->>BDB: Message[]
|
||||
Note over BDB: Sort by timestamp, slice, normalise
|
||||
Note over BDB: Optional channel filter, sort, slice, normalise
|
||||
BDB-->>DB: Message[]
|
||||
DB-->>Eff: Message[]
|
||||
```
|
||||
|
||||
@@ -70,12 +70,28 @@ export class BrowserDatabaseService {
|
||||
* @param roomId - Target room.
|
||||
* @param limit - Maximum number of messages to return.
|
||||
* @param offset - Number of newer messages to skip (for pagination).
|
||||
* @param channelId - Optional channel scope; 'general' includes null/empty.
|
||||
* @param beforeTimestamp - Optional cursor; only messages strictly older
|
||||
* than this timestamp are returned. Used for
|
||||
* scroll-up history pagination.
|
||||
*/
|
||||
async getMessages(roomId: string, limit = 100, offset = 0): Promise<Message[]> {
|
||||
async getMessages(
|
||||
roomId: string,
|
||||
limit = 100,
|
||||
offset = 0,
|
||||
channelId?: string,
|
||||
beforeTimestamp?: number
|
||||
): Promise<Message[]> {
|
||||
const allRoomMessages = await this.getAllFromIndex<Message>(
|
||||
STORE_MESSAGES, 'roomId', roomId
|
||||
);
|
||||
const sortedMessages = allRoomMessages.sort((first, second) => first.timestamp - second.timestamp);
|
||||
const scopedMessages = channelId
|
||||
? allRoomMessages.filter((message) => (message.channelId || 'general') === channelId)
|
||||
: allRoomMessages;
|
||||
const cursorFiltered = beforeTimestamp === undefined
|
||||
? scopedMessages
|
||||
: scopedMessages.filter((message) => message.timestamp < beforeTimestamp);
|
||||
const sortedMessages = cursorFiltered.sort((first, second) => first.timestamp - second.timestamp);
|
||||
const endIndex = Math.max(sortedMessages.length - offset, 0);
|
||||
const startIndex = Math.max(endIndex - limit, 0);
|
||||
const messages = sortedMessages.slice(startIndex, endIndex);
|
||||
|
||||
@@ -49,8 +49,19 @@ export class DatabaseService {
|
||||
/** Persist a single chat message. */
|
||||
saveMessage(message: Message) { return this.backend.saveMessage(message); }
|
||||
|
||||
/** Retrieve the latest messages for a room with optional pagination. */
|
||||
getMessages(roomId: string, limit = 100, offset = 0) { return this.backend.getMessages(roomId, limit, offset); }
|
||||
/** Retrieve the latest messages for a room or channel with optional pagination.
|
||||
*
|
||||
* When `beforeTimestamp` is provided, only messages strictly older than that
|
||||
* timestamp are returned. This is how scroll-up history loading paginates
|
||||
* backwards through the DB without holding the whole history in memory.
|
||||
*/
|
||||
getMessages(
|
||||
roomId: string,
|
||||
limit = 100,
|
||||
offset = 0,
|
||||
channelId?: string,
|
||||
beforeTimestamp?: number
|
||||
) { return this.backend.getMessages(roomId, limit, offset, channelId, beforeTimestamp); }
|
||||
|
||||
/** Retrieve messages newer than a given timestamp for a room. */
|
||||
getMessagesSince(roomId: string, sinceTimestamp: number) { return this.backend.getMessagesSince(roomId, sinceTimestamp); }
|
||||
|
||||
@@ -42,9 +42,21 @@ export class ElectronDatabaseService {
|
||||
* @param roomId - Target room.
|
||||
* @param limit - Maximum number of messages to return.
|
||||
* @param offset - Number of newer messages to skip (for pagination).
|
||||
* @param channelId - Optional channel scope; 'general' includes null/empty.
|
||||
* @param beforeTimestamp - Optional cursor; only messages strictly older
|
||||
* than this timestamp are returned (scroll-up paging).
|
||||
*/
|
||||
getMessages(roomId: string, limit = 100, offset = 0): Promise<Message[]> {
|
||||
return this.api.query<Message[]>({ type: 'get-messages', payload: { roomId, limit, offset } });
|
||||
getMessages(
|
||||
roomId: string,
|
||||
limit = 100,
|
||||
offset = 0,
|
||||
channelId?: string,
|
||||
beforeTimestamp?: number
|
||||
): Promise<Message[]> {
|
||||
return this.api.query<Message[]>({
|
||||
type: 'get-messages',
|
||||
payload: { roomId, limit, offset, channelId, beforeTimestamp }
|
||||
});
|
||||
}
|
||||
|
||||
getMessagesSince(roomId: string, sinceTimestamp: number): Promise<Message[]> {
|
||||
|
||||
Reference in New Issue
Block a user