click oin @ bring to latest mention

pull/2158/head
Audric Ackermann 3 years ago
parent 036d3827ab
commit 1efe6ca728
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -74,6 +74,7 @@ module.exports = {
getLastMessagesByConversation, getLastMessagesByConversation,
getOldestMessageInConversation, getOldestMessageInConversation,
getFirstUnreadMessageIdInConversation, getFirstUnreadMessageIdInConversation,
getFirstUnreadMessageWithMention,
hasConversationOutgoingMessage, hasConversationOutgoingMessage,
trimMessages, trimMessages,
fillWithTestData, fillWithTestData,
@ -2279,7 +2280,7 @@ const orderByClause = 'ORDER BY COALESCE(serverTimestamp, sent_at, received_at)
const orderByClauseASC = 'ORDER BY COALESCE(serverTimestamp, sent_at, received_at) ASC'; const orderByClauseASC = 'ORDER BY COALESCE(serverTimestamp, sent_at, received_at) ASC';
function getMessagesByConversation(conversationId, { messageId = null } = {}) { function getMessagesByConversation(conversationId, { messageId = null } = {}) {
const absLimit = 20; const absLimit = 30;
// If messageId is given it means we are opening the conversation to that specific messageId, // If messageId is given it means we are opening the conversation to that specific messageId,
// or that we just scrolled to it by a quote click and needs to load around it. // or that we just scrolled to it by a quote click and needs to load around it.
// If messageId is null, it means we are just opening the convo to the last unread message, or at the bottom // If messageId is null, it means we are just opening the convo to the last unread message, or at the bottom
@ -2420,6 +2421,35 @@ function getFirstUnreadMessageIdInConversation(conversationId) {
return rows[0].id; return rows[0].id;
} }
function getFirstUnreadMessageWithMention(conversationId, ourpubkey) {
if (!ourpubkey || !ourpubkey.length) {
throw new Error('getFirstUnreadMessageWithMention needs our pubkey but nothing was given');
}
const likeMatch = `%@${ourpubkey}%`;
const rows = globalInstance
.prepare(
`
SELECT id, json FROM ${MESSAGES_TABLE} WHERE
conversationId = $conversationId AND
unread = $unread AND
body LIKE $likeMatch
ORDER BY serverTimestamp ASC, serverId ASC, sent_at ASC, received_at ASC
LIMIT 1;
`
)
.all({
conversationId,
unread: 1,
likeMatch,
});
if (rows.length === 0) {
return undefined;
}
return rows[0].id;
}
/** /**
* Deletes all but the 10,000 last received messages. * Deletes all but the 10,000 last received messages.
*/ */

@ -74,28 +74,3 @@
.module-conversation-list-item--mentioned-us { .module-conversation-list-item--mentioned-us {
border-left: 4px solid $session-color-green !important; border-left: 4px solid $session-color-green !important;
} }
.at-symbol {
background-color: var(--color-accent);
color: $color-black;
text-align: center;
margin-top: 0px;
margin-bottom: 0px;
padding-top: 1px;
padding-inline-start: 3px;
padding-inline-end: 3px;
position: static;
margin-inline-start: 5px;
font-weight: 300;
font-size: 11px;
letter-spacing: 0.25px;
height: 16px;
min-width: 16px;
border-radius: 8px;
box-shadow: 0px 0px 0px 1px $color-dark-85;
}

@ -1,8 +1,14 @@
import classNames from 'classnames'; import classNames from 'classnames';
import React, { useContext } from 'react'; import React, { useCallback, useContext } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { getFirstUnreadMessageWithMention } from '../../../data/data';
import { useConversationPropsById, useIsPinned } from '../../../hooks/useParamSelector'; import { useConversationPropsById, useIsPinned } from '../../../hooks/useParamSelector';
import { UserUtils } from '../../../session/utils';
import {
openConversationToSpecificMessage,
openConversationWithMessages,
} from '../../../state/ducks/conversations';
import { SectionType } from '../../../state/ducks/section'; import { SectionType } from '../../../state/ducks/section';
import { isSearching } from '../../../state/selectors/search'; import { isSearching } from '../../../state/selectors/search';
import { getFocusedSection } from '../../../state/selectors/section'; import { getFocusedSection } from '../../../state/selectors/section';
@ -74,12 +80,72 @@ const ListItemIcons = () => {
); );
}; };
const MentionAtSymbol = styled.span`
background-color: var(--color-accent);
color: black;
text-align: center;
margin-top: 0px;
margin-bottom: 0px;
padding-top: 1px;
padding-inline-start: 3px;
padding-inline-end: 3px;
position: static;
margin-inline-start: 5px;
font-weight: 300;
font-size: 11px;
letter-spacing: 0.25px;
height: 16px;
min-width: 16px;
border-radius: 8px;
/* transition: filter 0.25s linear; */
cursor: pointer;
:hover {
filter: grayscale(0.7);
}
`;
export const ConversationListItemHeaderItem = () => { export const ConversationListItemHeaderItem = () => {
const conversationId = useContext(ContextConversationId); const conversationId = useContext(ContextConversationId);
const isSearchingMode = useSelector(isSearching); const isSearchingMode = useSelector(isSearching);
const convoProps = useHeaderItemProps(conversationId); const convoProps = useHeaderItemProps(conversationId);
const openConvoToLastMention = useCallback(
async (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
e.preventDefault();
// mousedown is invoked sooner than onClick, but for both right and left click
if (e.button === 0) {
const oldestMessageUnreadWithMention =
(await getFirstUnreadMessageWithMention(
conversationId,
UserUtils.getOurPubKeyStrFromCache()
)) || null;
if (oldestMessageUnreadWithMention) {
await openConversationToSpecificMessage({
conversationKey: conversationId,
messageIdToNavigateTo: oldestMessageUnreadWithMention,
shouldHighlightMessage: true,
});
} else {
window.log.info('cannot open to latest mention as no unread mention are found');
await openConversationWithMessages({
conversationKey: conversationId,
messageId: null,
});
}
}
},
[conversationId]
);
if (!convoProps) { if (!convoProps) {
return null; return null;
} }
@ -88,7 +154,11 @@ export const ConversationListItemHeaderItem = () => {
let atSymbol = null; let atSymbol = null;
let unreadCountDiv = null; let unreadCountDiv = null;
if (unreadCount > 0) { if (unreadCount > 0) {
atSymbol = mentionedUs ? <p className="at-symbol">@</p> : null; atSymbol = mentionedUs ? (
<MentionAtSymbol title="Open to latest mention" onMouseDown={openConvoToLastMention}>
@
</MentionAtSymbol>
) : null;
unreadCountDiv = <p className="module-conversation-list-item__unread-count">{unreadCount}</p>; unreadCountDiv = <p className="module-conversation-list-item__unread-count">{unreadCount}</p>;
} }

@ -130,6 +130,7 @@ const channelsToMake = {
getLastMessagesByConversation, getLastMessagesByConversation,
getOldestMessageInConversation, getOldestMessageInConversation,
getFirstUnreadMessageIdInConversation, getFirstUnreadMessageIdInConversation,
getFirstUnreadMessageWithMention,
hasConversationOutgoingMessage, hasConversationOutgoingMessage,
getSeenMessagesByHashList, getSeenMessagesByHashList,
getLastHashBySnode, getLastHashBySnode,
@ -838,6 +839,13 @@ export async function getFirstUnreadMessageIdInConversation(
return channels.getFirstUnreadMessageIdInConversation(conversationId); return channels.getFirstUnreadMessageIdInConversation(conversationId);
} }
export async function getFirstUnreadMessageWithMention(
conversationId: string,
ourPubkey: string
): Promise<string | undefined> {
return channels.getFirstUnreadMessageWithMention(conversationId, ourPubkey);
}
export async function hasConversationOutgoingMessage(conversationId: string): Promise<boolean> { export async function hasConversationOutgoingMessage(conversationId: string): Promise<boolean> {
return channels.hasConversationOutgoingMessage(conversationId); return channels.hasConversationOutgoingMessage(conversationId);
} }

@ -19,7 +19,7 @@ import {
} from './messageType'; } from './messageType';
import autoBind from 'auto-bind'; import autoBind from 'auto-bind';
import { saveMessage } from '../../ts/data/data'; import { getFirstUnreadMessageWithMention, saveMessage } from '../../ts/data/data';
import { ConversationModel, ConversationTypeEnum } from './conversation'; import { ConversationModel, ConversationTypeEnum } from './conversation';
import { import {
FindAndFormatContactType, FindAndFormatContactType,
@ -1030,7 +1030,17 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
if (convo) { if (convo) {
const beforeUnread = convo.get('unreadCount'); const beforeUnread = convo.get('unreadCount');
const unreadCount = await convo.getUnreadCount(); const unreadCount = await convo.getUnreadCount();
if (beforeUnread !== unreadCount) {
const nextMentionedUs = await getFirstUnreadMessageWithMention(
convo.id,
UserUtils.getOurPubKeyStrFromCache()
);
let mentionedUsChange = false;
if (convo.get('mentionedUs') && !nextMentionedUs) {
convo.set('mentionedUs', false);
mentionedUsChange = true;
}
if (beforeUnread !== unreadCount || mentionedUsChange) {
convo.set({ unreadCount }); convo.set({ unreadCount });
await convo.commit(); await convo.commit();
} }

Loading…
Cancel
Save