feat: added lastMessageId to convo model to uniquely identify a lastMessage

pull/2789/head
William Grant 2 years ago
parent 30b486c80e
commit de614109d0

@ -27,7 +27,8 @@ export const InteractionItem = (props: InteractionItemProps) => {
const isGroup = !useIsPrivate(conversationId); const isGroup = !useIsPrivate(conversationId);
const isCommunity = useIsPublic(conversationId); const isCommunity = useIsPublic(conversationId);
const [storedLastMessage, setStoredLastMessage] = useState(lastMessage?.text); const [storedLastMessageId, setStoredLastMessageId] = useState(lastMessage?.id);
const [storedLastMessageText, setStoredLastMessageText] = useState(lastMessage?.text);
// NOTE we want to reset the interaction state when the last message changes // NOTE we want to reset the interaction state when the last message changes
useEffect(() => { useEffect(() => {
@ -35,23 +36,24 @@ export const InteractionItem = (props: InteractionItemProps) => {
const convo = getConversationController().get(conversationId); const convo = getConversationController().get(conversationId);
window.log.debug( window.log.debug(
`WIP: storedLastMessage "${storedLastMessage}" convo.get('lastMessage') "${convo.get( `WIP: storedLastMessageId "${storedLastMessageId}" convo.get('lastMessageId') "${convo.get(
'lastMessage' 'lastMessageId'
)}'` )}' lastMessageId ${JSON.stringify(lastMessage)}`
); );
if (storedLastMessage !== convo.get('lastMessage')) { if (storedLastMessageId !== convo.get('lastMessageId')) {
setStoredLastMessage(convo.get('lastMessage')); setStoredLastMessageId(convo.get('lastMessageId'));
setStoredLastMessageText(convo.get('lastMessage'));
void clearConversationInteractionState({ conversationId }); void clearConversationInteractionState({ conversationId });
} }
} }
}, [conversationId, interactionStatus, lastMessage?.text]); }, [conversationId, interactionStatus, lastMessage?.id]);
if (isEmpty(conversationId) || isEmpty(interactionType) || isEmpty(interactionStatus)) { if (isEmpty(conversationId) || isEmpty(interactionType) || isEmpty(interactionStatus)) {
return null; return null;
} }
let text = storedLastMessage || ''; let text = storedLastMessageText || '';
switch (interactionType) { switch (interactionType) {
case ConversationInteractionType.Leave: case ConversationInteractionType.Leave:
const failText = isCommunity const failText = isCommunity

@ -426,6 +426,7 @@ export async function deleteAllMessagesByConvoIdNoConfirmation(conversationId: s
// conversation still appears on the conversation list but is empty // conversation still appears on the conversation list but is empty
conversation.set({ conversation.set({
lastMessage: null, lastMessage: null,
lastMessageId: null,
}); });
await conversation.commit(); await conversation.commit();

@ -389,9 +389,11 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
// -- Handle the last message status, if present -- // -- Handle the last message status, if present --
const lastMessageText = this.get('lastMessage'); const lastMessageText = this.get('lastMessage');
if (lastMessageText && lastMessageText.length) { if (lastMessageText && lastMessageText.length) {
const lastMessageId = this.get('lastMessageId');
const lastMessageStatus = this.get('lastMessageStatus'); const lastMessageStatus = this.get('lastMessageStatus');
toRet.lastMessage = { toRet.lastMessage = {
id: lastMessageId,
status: lastMessageStatus, status: lastMessageStatus,
text: lastMessageText, text: lastMessageText,
}; };
@ -753,6 +755,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
this.set({ this.set({
lastMessage: messageModel.getNotificationText(), lastMessage: messageModel.getNotificationText(),
lastMessageId: messageModel.get('id'),
lastMessageStatus: 'sending', lastMessageStatus: 'sending',
active_at: networkTimestamp, active_at: networkTimestamp,
}); });
@ -1853,6 +1856,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
return; return;
} }
const lastMessageModel = messages.at(0); const lastMessageModel = messages.at(0);
const lastMessageId = lastMessageModel.get('id');
const lastMessageStatus = lastMessageModel.getMessagePropStatus() || undefined; const lastMessageStatus = lastMessageModel.getMessagePropStatus() || undefined;
const lastMessageNotificationText = lastMessageModel.getNotificationText() || undefined; const lastMessageNotificationText = lastMessageModel.getNotificationText() || undefined;
// we just want to set the `status` to `undefined` if there are no `lastMessageNotificationText` // we just want to set the `status` to `undefined` if there are no `lastMessageNotificationText`
@ -1860,17 +1864,21 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
!!lastMessageNotificationText && !isEmpty(lastMessageNotificationText) !!lastMessageNotificationText && !isEmpty(lastMessageNotificationText)
? { ? {
lastMessage: lastMessageNotificationText || '', lastMessage: lastMessageNotificationText || '',
lastMessageId,
lastMessageStatus, lastMessageStatus,
} }
: { lastMessage: '', lastMessageStatus: undefined }; : { lastMessage: '', lastMessageId: '', lastMessageStatus: undefined };
const existingLastMessageAttribute = this.get('lastMessage'); const existingLastMessageAttribute = this.get('lastMessage');
const existingLastMessageId = this.get('lastMessageId');
const existingLastMessageStatus = this.get('lastMessageStatus'); const existingLastMessageStatus = this.get('lastMessageStatus');
if ( if (
lastMessageUpdate.lastMessage !== existingLastMessageAttribute || lastMessageUpdate.lastMessage !== existingLastMessageAttribute ||
lastMessageUpdate.lastMessageStatus !== existingLastMessageStatus lastMessageUpdate.lastMessageStatus !== existingLastMessageStatus ||
lastMessageUpdate.lastMessageId !== existingLastMessageId
) { ) {
if ( if (
lastMessageUpdate.lastMessageId === existingLastMessageId &&
lastMessageUpdate.lastMessageStatus === existingLastMessageStatus && lastMessageUpdate.lastMessageStatus === existingLastMessageStatus &&
lastMessageUpdate.lastMessage && lastMessageUpdate.lastMessage &&
lastMessageUpdate.lastMessage.length > 40 && lastMessageUpdate.lastMessage.length > 40 &&

@ -59,7 +59,6 @@ export interface ConversationAttributes {
// 0 means inactive (undefined and null too but we try to get rid of them and only have 0 = inactive) // 0 means inactive (undefined and null too but we try to get rid of them and only have 0 = inactive)
active_at: number; // this field is the one used to sort conversations in the left pane from most recent active_at: number; // this field is the one used to sort conversations in the left pane from most recent
lastMessageStatus: LastMessageStatusType;
/** /**
* lastMessage is actually just a preview of the last message text, shortened to 60 chars. * lastMessage is actually just a preview of the last message text, shortened to 60 chars.
* This is to avoid filling the redux store with a huge last message when it's only used in the * This is to avoid filling the redux store with a huge last message when it's only used in the
@ -67,6 +66,8 @@ export interface ConversationAttributes {
* The shortening is made in sql.ts directly. * The shortening is made in sql.ts directly.
*/ */
lastMessage: string | null; lastMessage: string | null;
lastMessageId: string | null;
lastMessageStatus: LastMessageStatusType;
avatarImageId?: number; // avatar imageID is currently used only for sogs. It's the fileID of the image uploaded and set as the sogs avatar (not only sogs I think, but our profile too?) avatarImageId?: number; // avatar imageID is currently used only for sogs. It's the fileID of the image uploaded and set as the sogs avatar (not only sogs I think, but our profile too?)
@ -129,8 +130,9 @@ export const fillConvoAttributesWithDefaults = (
expireTimer: 0, expireTimer: 0,
active_at: 0, active_at: 0,
lastMessageStatus: undefined,
lastMessage: null, lastMessage: null,
lastMessageId: null,
lastMessageStatus: undefined,
triggerNotificationsFor: 'all', // if the settings is not set in the db, this is the default triggerNotificationsFor: 'all', // if the settings is not set in the db, this is the default

@ -58,6 +58,7 @@ const allowedKeysFormatRowOfConversation = [
'isKickedFromGroup', 'isKickedFromGroup',
'left', 'left',
'lastMessage', 'lastMessage',
'lastMessageId',
'lastMessageStatus', 'lastMessageStatus',
'triggerNotificationsFor', 'triggerNotificationsFor',
'unreadCount', 'unreadCount',
@ -138,6 +139,10 @@ export function formatRowOfConversation(
convo.lastMessage = null; convo.lastMessage = null;
} }
if (!convo.lastMessageId) {
convo.lastMessageId = null;
}
if (!convo.lastMessageStatus) { if (!convo.lastMessageStatus) {
convo.lastMessageStatus = undefined; convo.lastMessageStatus = undefined;
} }
@ -178,6 +183,7 @@ const allowedKeysOfConversationAttributes = [
'isKickedFromGroup', 'isKickedFromGroup',
'left', 'left',
'lastMessage', 'lastMessage',
'lastMessageId',
'lastMessageStatus', 'lastMessageStatus',
'triggerNotificationsFor', 'triggerNotificationsFor',
'lastJoinedTimestamp', 'lastJoinedTimestamp',

@ -1846,6 +1846,8 @@ function updateToSessionSchemaVersion32(currentVersion: number, db: BetterSqlite
db.prepare(`ALTER TABLE ${CONVERSATIONS_TABLE} ADD COLUMN interactionStatus TEXT;`).run(); db.prepare(`ALTER TABLE ${CONVERSATIONS_TABLE} ADD COLUMN interactionStatus TEXT;`).run();
db.prepare(`ALTER TABLE ${CONVERSATIONS_TABLE} ADD COLUMN lastMessageId TEXT;`).run();
writeSessionSchemaVersion(targetVersion, db); writeSessionSchemaVersion(targetVersion, db);
})(); })();

@ -427,8 +427,9 @@ function saveConversation(data: ConversationAttributes): SaveConversationReturn
zombies, zombies,
left, left,
expireTimer, expireTimer,
lastMessageStatus,
lastMessage, lastMessage,
lastMessageId,
lastMessageStatus,
lastJoinedTimestamp, lastJoinedTimestamp,
groupAdmins, groupAdmins,
isKickedFromGroup, isKickedFromGroup,
@ -477,8 +478,9 @@ function saveConversation(data: ConversationAttributes): SaveConversationReturn
zombies: zombies && zombies.length ? arrayStrToJson(zombies) : '[]', zombies: zombies && zombies.length ? arrayStrToJson(zombies) : '[]',
left: toSqliteBoolean(left), left: toSqliteBoolean(left),
expireTimer, expireTimer,
lastMessageStatus,
lastMessage: shortenedLastMessage, lastMessage: shortenedLastMessage,
lastMessageId,
lastMessageStatus,
lastJoinedTimestamp, lastJoinedTimestamp,
groupAdmins: groupAdmins && groupAdmins.length ? arrayStrToJson(groupAdmins) : '[]', groupAdmins: groupAdmins && groupAdmins.length ? arrayStrToJson(groupAdmins) : '[]',

@ -276,6 +276,7 @@ async function handleRegularMessage(
conversation.set({ conversation.set({
active_at: message.get('sent_at'), active_at: message.get('sent_at'),
lastMessage: message.getNotificationText(), lastMessage: message.getNotificationText(),
lastMessageId: message.get('id'),
}); });
// a new message was received for that conversation. If it was not it should not be hidden anymore // a new message was received for that conversation. If it was not it should not be hidden anymore
await conversation.unhideIfNeeded(false); await conversation.unhideIfNeeded(false);

@ -217,6 +217,7 @@ export type PropsForMessageWithConvoProps = PropsForMessageWithoutConvoProps & {
}; };
export type LastMessageType = { export type LastMessageType = {
id: string | null;
status: LastMessageStatusType; status: LastMessageStatusType;
text: string | null; text: string | null;
}; };

Loading…
Cancel
Save