mirror of
https://github.com/colanode/colanode.git
synced 2025-12-29 00:25:03 +01:00
Improve message interactions tracking
This commit is contained in:
@@ -184,7 +184,8 @@ const createMessageInteractionsTable: Migration = {
|
||||
.addColumn('message_id', 'text', (col) => col.notNull())
|
||||
.addColumn('collaborator_id', 'text', (col) => col.notNull())
|
||||
.addColumn('root_id', 'text', (col) => col.notNull())
|
||||
.addColumn('seen_at', 'text')
|
||||
.addColumn('first_seen_at', 'text')
|
||||
.addColumn('last_seen_at', 'text')
|
||||
.addColumn('first_opened_at', 'text')
|
||||
.addColumn('last_opened_at', 'text')
|
||||
.addColumn('version', 'integer', (col) => col.notNull())
|
||||
|
||||
@@ -138,7 +138,8 @@ interface MessageInteractionTable {
|
||||
message_id: ColumnType<string, string, never>;
|
||||
collaborator_id: ColumnType<string, string, never>;
|
||||
root_id: ColumnType<string, string, string>;
|
||||
seen_at: ColumnType<string | null, string | null, string | null>;
|
||||
first_seen_at: ColumnType<string | null, string | null, string | null>;
|
||||
last_seen_at: ColumnType<string | null, string | null, string | null>;
|
||||
first_opened_at: ColumnType<string | null, string | null, string | null>;
|
||||
last_opened_at: ColumnType<string | null, string | null, string | null>;
|
||||
version: ColumnType<bigint, bigint, bigint>;
|
||||
|
||||
@@ -38,12 +38,23 @@ export class MessageMarkSeenMutationHandler
|
||||
.where('collaborator_id', '=', input.userId)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (existingInteraction && existingInteraction.seen_at !== null) {
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
if (existingInteraction) {
|
||||
const lastSeenAt = existingInteraction.last_seen_at;
|
||||
if (
|
||||
lastSeenAt &&
|
||||
lastSeenAt > new Date(Date.now() - 5 * 1000).toISOString()
|
||||
) {
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const lastSeenAt = new Date().toISOString();
|
||||
const firstSeenAt = existingInteraction
|
||||
? existingInteraction.first_seen_at
|
||||
: lastSeenAt;
|
||||
|
||||
const { createdInteraction, createdMutation } = await workspaceDatabase
|
||||
.transaction()
|
||||
.execute(async (trx) => {
|
||||
@@ -53,17 +64,16 @@ export class MessageMarkSeenMutationHandler
|
||||
.values({
|
||||
message_id: input.messageId,
|
||||
collaborator_id: input.userId,
|
||||
seen_at: new Date().toISOString(),
|
||||
first_seen_at: firstSeenAt,
|
||||
last_seen_at: lastSeenAt,
|
||||
version: 0n,
|
||||
root_id: message.root_id,
|
||||
})
|
||||
.onConflict((b) =>
|
||||
b
|
||||
.columns(['message_id', 'collaborator_id'])
|
||||
.doUpdateSet({
|
||||
seen_at: new Date().toISOString(),
|
||||
})
|
||||
.where('seen_at', 'is', null)
|
||||
b.columns(['message_id', 'collaborator_id']).doUpdateSet({
|
||||
first_seen_at: firstSeenAt,
|
||||
last_seen_at: lastSeenAt,
|
||||
})
|
||||
)
|
||||
.executeTakeFirst();
|
||||
|
||||
|
||||
@@ -268,16 +268,18 @@ class MessageService {
|
||||
message_id: messageInteraction.messageId,
|
||||
collaborator_id: messageInteraction.collaboratorId,
|
||||
root_id: messageInteraction.rootId,
|
||||
seen_at: messageInteraction.seenAt,
|
||||
last_opened_at: messageInteraction.lastOpenedAt,
|
||||
first_seen_at: messageInteraction.firstSeenAt,
|
||||
last_seen_at: messageInteraction.lastSeenAt,
|
||||
first_opened_at: messageInteraction.firstOpenedAt,
|
||||
last_opened_at: messageInteraction.lastOpenedAt,
|
||||
version,
|
||||
})
|
||||
.onConflict((b) =>
|
||||
b.columns(['message_id', 'collaborator_id']).doUpdateSet({
|
||||
seen_at: messageInteraction.seenAt,
|
||||
last_opened_at: messageInteraction.lastOpenedAt,
|
||||
first_seen_at: messageInteraction.firstSeenAt,
|
||||
last_seen_at: messageInteraction.lastSeenAt,
|
||||
first_opened_at: messageInteraction.firstOpenedAt,
|
||||
last_opened_at: messageInteraction.lastOpenedAt,
|
||||
version,
|
||||
})
|
||||
)
|
||||
|
||||
@@ -124,7 +124,7 @@ class RadarWorkspace {
|
||||
)
|
||||
.select(['message.id as message_id', 'message.entry_id as entry_id'])
|
||||
.where('message.created_by', '!=', this.workspace.userId)
|
||||
.where('message_interactions.seen_at', 'is', null)
|
||||
.where('message_interactions.last_seen_at', 'is', null)
|
||||
.where('entry_interactions.last_seen_at', 'is not', null)
|
||||
.whereRef('message.created_at', '>=', 'entry_interactions.first_seen_at')
|
||||
.execute();
|
||||
@@ -149,7 +149,7 @@ class RadarWorkspace {
|
||||
return;
|
||||
}
|
||||
|
||||
if (interaction.seenAt) {
|
||||
if (interaction.lastSeenAt) {
|
||||
const unreadMessage = this.unreadMessages.get(interaction.messageId);
|
||||
if (unreadMessage) {
|
||||
this.unreadMessages.delete(interaction.messageId);
|
||||
@@ -187,7 +187,7 @@ class RadarWorkspace {
|
||||
.where('collaborator_id', '=', this.workspace.userId)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (messageInteraction && messageInteraction.seen_at) {
|
||||
if (messageInteraction && messageInteraction.last_seen_at) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -345,7 +345,9 @@ export const mapMessageInteraction = (
|
||||
messageId: row.message_id,
|
||||
collaboratorId: row.collaborator_id,
|
||||
rootId: row.root_id,
|
||||
seenAt: row.seen_at,
|
||||
firstSeenAt: row.first_seen_at,
|
||||
lastSeenAt: row.last_seen_at,
|
||||
firstOpenedAt: row.first_opened_at,
|
||||
lastOpenedAt: row.last_opened_at,
|
||||
version: row.version,
|
||||
};
|
||||
|
||||
@@ -31,7 +31,9 @@ export type MessageInteraction = {
|
||||
messageId: string;
|
||||
collaboratorId: string;
|
||||
rootId: string;
|
||||
seenAt: string | null;
|
||||
firstSeenAt: string | null;
|
||||
lastSeenAt: string | null;
|
||||
firstOpenedAt: string | null;
|
||||
lastOpenedAt: string | null;
|
||||
version: bigint;
|
||||
};
|
||||
|
||||
@@ -506,7 +506,8 @@ const createMessageInteractionsTable: Migration = {
|
||||
.addColumn('collaborator_id', 'varchar(30)', (col) => col.notNull())
|
||||
.addColumn('root_id', 'varchar(30)', (col) => col.notNull())
|
||||
.addColumn('workspace_id', 'varchar(30)', (col) => col.notNull())
|
||||
.addColumn('seen_at', 'timestamptz')
|
||||
.addColumn('first_seen_at', 'timestamptz')
|
||||
.addColumn('last_seen_at', 'timestamptz')
|
||||
.addColumn('first_opened_at', 'timestamptz')
|
||||
.addColumn('last_opened_at', 'timestamptz')
|
||||
.addColumn('version', 'bigint', (col) =>
|
||||
|
||||
@@ -213,7 +213,8 @@ interface MessageInteractionTable {
|
||||
collaborator_id: ColumnType<string, string, never>;
|
||||
root_id: ColumnType<string, string, never>;
|
||||
workspace_id: ColumnType<string, string, never>;
|
||||
seen_at: ColumnType<Date | null, Date | null, Date | null>;
|
||||
first_seen_at: ColumnType<Date | null, Date | null, Date | null>;
|
||||
last_seen_at: ColumnType<Date | null, Date | null, Date | null>;
|
||||
first_opened_at: ColumnType<Date | null, Date | null, Date | null>;
|
||||
last_opened_at: ColumnType<Date | null, Date | null, Date | null>;
|
||||
version: ColumnType<bigint, never, never>;
|
||||
|
||||
@@ -345,25 +345,29 @@ class MessageService {
|
||||
|
||||
if (
|
||||
existingInteraction &&
|
||||
existingInteraction.seen_at !== null &&
|
||||
existingInteraction.seen_at <= new Date(mutation.data.seenAt)
|
||||
existingInteraction.last_seen_at !== null &&
|
||||
existingInteraction.last_seen_at >= new Date(mutation.data.seenAt)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const lastSeenAt = new Date(mutation.data.seenAt);
|
||||
const firstSeenAt = existingInteraction?.first_seen_at ?? lastSeenAt;
|
||||
const createdInteraction = await database
|
||||
.insertInto('message_interactions')
|
||||
.returningAll()
|
||||
.values({
|
||||
message_id: mutation.data.messageId,
|
||||
collaborator_id: user.id,
|
||||
seen_at: new Date(mutation.data.seenAt),
|
||||
first_seen_at: firstSeenAt,
|
||||
last_seen_at: lastSeenAt,
|
||||
root_id: root.id,
|
||||
workspace_id: root.workspace_id,
|
||||
})
|
||||
.onConflict((b) =>
|
||||
b.columns(['message_id', 'collaborator_id']).doUpdateSet({
|
||||
seen_at: new Date(mutation.data.seenAt),
|
||||
last_seen_at: lastSeenAt,
|
||||
first_seen_at: firstSeenAt,
|
||||
})
|
||||
)
|
||||
.executeTakeFirst();
|
||||
|
||||
@@ -60,7 +60,8 @@ export class MessageInteractionSynchronizer extends BaseSynchronizer<SyncMessage
|
||||
(messageInteraction) => ({
|
||||
messageId: messageInteraction.message_id,
|
||||
collaboratorId: messageInteraction.collaborator_id,
|
||||
seenAt: messageInteraction.seen_at?.toISOString() ?? null,
|
||||
firstSeenAt: messageInteraction.first_seen_at?.toISOString() ?? null,
|
||||
lastSeenAt: messageInteraction.last_seen_at?.toISOString() ?? null,
|
||||
firstOpenedAt:
|
||||
messageInteraction.first_opened_at?.toISOString() ?? null,
|
||||
lastOpenedAt: messageInteraction.last_opened_at?.toISOString() ?? null,
|
||||
|
||||
Reference in New Issue
Block a user