fix: No longer displays edited on all messages and fix Disconnected from signaling server on multiple clients
All checks were successful
Queue Release Build / prepare (push) Successful in 19s
Deploy Web Apps / deploy (push) Successful in 8m19s
Queue Release Build / build-windows (push) Successful in 27m48s
Queue Release Build / build-linux (push) Successful in 47m35s
Queue Release Build / build-android (push) Successful in 21m15s
Queue Release Build / finalize (push) Successful in 2m30s
All checks were successful
Queue Release Build / prepare (push) Successful in 19s
Deploy Web Apps / deploy (push) Successful in 8m19s
Queue Release Build / build-windows (push) Successful in 27m48s
Queue Release Build / build-linux (push) Successful in 47m35s
Queue Release Build / build-android (push) Successful in 21m15s
Queue Release Build / finalize (push) Successful in 2m30s
This commit is contained in:
@@ -55,7 +55,21 @@ describe('message-revision.builder.rules', () => {
|
||||
expect(revision.content).toBe('edited');
|
||||
});
|
||||
|
||||
it('materializes message state from a revision', async () => {
|
||||
it('materializes create revisions without an editedAt label timestamp', async () => {
|
||||
const revision = await buildMessageRevision({
|
||||
message: createMessage(),
|
||||
type: 'create',
|
||||
actorId: 'user-1',
|
||||
editedAt: 1_000
|
||||
});
|
||||
const materialized = materializeMessageFromRevision(null, revision);
|
||||
|
||||
expect(materialized.timestamp).toBe(1_000);
|
||||
expect(materialized.editedAt).toBeUndefined();
|
||||
expect(materialized.revision).toBe(0);
|
||||
});
|
||||
|
||||
it('materializes message state from an edit revision', async () => {
|
||||
const revision = await buildMessageRevision({
|
||||
message: createMessage(),
|
||||
type: 'author-edit',
|
||||
@@ -67,6 +81,7 @@ describe('message-revision.builder.rules', () => {
|
||||
|
||||
expect(materialized.revision).toBe(1);
|
||||
expect(materialized.content).toBe('edited');
|
||||
expect(materialized.editedAt).toBe(2_000);
|
||||
expect(materialized.headHash).toBe(revision.headHash);
|
||||
});
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ export function materializeMessageFromRevision(
|
||||
senderId: revision.senderId,
|
||||
senderName: revision.senderName ?? base.senderName,
|
||||
content: revision.isDeleted ? DELETED_MESSAGE_CONTENT : (revision.content ?? base.content),
|
||||
editedAt: revision.editedAt,
|
||||
editedAt: revision.type === 'create' ? undefined : revision.editedAt,
|
||||
revision: revision.revision,
|
||||
headHash: revision.headHash,
|
||||
isDeleted: revision.isDeleted,
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import {
|
||||
describe,
|
||||
it,
|
||||
expect
|
||||
} from 'vitest';
|
||||
import type { Message } from '../../../../shared-kernel';
|
||||
import { shouldShowMessageEditedLabel } from './message.rules';
|
||||
|
||||
function createMessage(overrides: Partial<Message> = {}): Message {
|
||||
return {
|
||||
id: 'message-1',
|
||||
roomId: 'room-1',
|
||||
senderId: 'user-1',
|
||||
senderName: 'User 1',
|
||||
content: 'hello',
|
||||
timestamp: 1_000,
|
||||
reactions: [],
|
||||
isDeleted: false,
|
||||
...overrides
|
||||
};
|
||||
}
|
||||
|
||||
describe('message.rules', () => {
|
||||
describe('shouldShowMessageEditedLabel', () => {
|
||||
it('returns false for newly created messages without an edit revision', () => {
|
||||
expect(shouldShowMessageEditedLabel(createMessage())).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false when editedAt equals the original timestamp (legacy create rows)', () => {
|
||||
expect(shouldShowMessageEditedLabel(createMessage({
|
||||
editedAt: 1_000,
|
||||
timestamp: 1_000,
|
||||
revision: 0
|
||||
}))).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true when a message has an edit revision', () => {
|
||||
expect(shouldShowMessageEditedLabel(createMessage({
|
||||
editedAt: 2_000,
|
||||
revision: 1
|
||||
}))).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for legacy edited messages with editedAt after timestamp', () => {
|
||||
expect(shouldShowMessageEditedLabel(createMessage({
|
||||
editedAt: 2_000,
|
||||
timestamp: 1_000
|
||||
}))).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for deleted messages even when editedAt is set', () => {
|
||||
expect(shouldShowMessageEditedLabel(createMessage({
|
||||
editedAt: 2_000,
|
||||
revision: 1,
|
||||
isDeleted: true
|
||||
}))).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,10 +1,26 @@
|
||||
import { DELETED_MESSAGE_CONTENT, type Message } from '../../../../shared-kernel';
|
||||
import { getMessageRevision } from './message-integrity.rules';
|
||||
|
||||
/** Extracts the effective timestamp from a message (editedAt takes priority). */
|
||||
export function getMessageTimestamp(msg: Message): number {
|
||||
return msg.editedAt || msg.timestamp || 0;
|
||||
}
|
||||
|
||||
/** Whether the UI should show the "(edited)" label for a message. */
|
||||
export function shouldShowMessageEditedLabel(
|
||||
message: Pick<Message, 'editedAt' | 'timestamp' | 'revision' | 'isDeleted'>
|
||||
): boolean {
|
||||
if (message.isDeleted || message.editedAt === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getMessageRevision(message) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return typeof message.timestamp === 'number' && message.editedAt > message.timestamp;
|
||||
}
|
||||
|
||||
/** Computes the most recent timestamp across a batch of messages. */
|
||||
export function getLatestTimestamp(messages: Message[]): number {
|
||||
return messages.reduce((max, msg) => Math.max(max, getMessageTimestamp(msg)), 0);
|
||||
|
||||
Reference in New Issue
Block a user