From 374d5a66190aafdd670325df34fc0948cdd30d92 Mon Sep 17 00:00:00 2001 From: warrickct Date: Wed, 22 Dec 2021 11:20:29 +1100 Subject: [PATCH 1/5] Global search partially functioning, added basic functions for load testing performance. --- _locales/en/messages.json | 4 +- app/sql.js | 191 ++++++++++++++++++ stylesheets/_modules.scss | 2 +- ts/components/basic/MessageBodyHighlist.tsx | 87 ++++++++ ts/components/search/MessageSearchResults.tsx | 144 +++++++++++++ ts/components/search/SearchResults.tsx | 12 +- .../settings/section/CategoryAppearance.tsx | 48 ++++- ts/data/data.ts | 81 +++++++- ts/models/messageType.ts | 5 + ts/state/ducks/search.ts | 14 +- ts/state/selectors/search.ts | 28 ++- ts/types/LocalizerKeys.ts | 2 + 12 files changed, 600 insertions(+), 18 deletions(-) create mode 100644 ts/components/basic/MessageBodyHighlist.tsx create mode 100644 ts/components/search/MessageSearchResults.tsx diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 45580ed3f..916bfda27 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -460,5 +460,7 @@ "callMediaPermissionsDialogContent": "The current implementation of voice/video calls will expose your IP address to the Oxen Foundation servers and the calling/called user.", "menuCall": "Call", "startedACall": "You called $name$", - "answeredACall": "Call with $name$" + "answeredACall": "Call with $name$", + "trimDatabase": "Trim Database", + "trimDatabaseDescription": "Reduces your message database size to your last 10,000 messages." } diff --git a/app/sql.js b/app/sql.js index d4b20e0db..8733a2717 100644 --- a/app/sql.js +++ b/app/sql.js @@ -836,6 +836,7 @@ const LOKI_SCHEMA_VERSIONS = [ updateToLokiSchemaVersion15, updateToLokiSchemaVersion16, updateToLokiSchemaVersion17, + updateToLokiSchemaVersion18, ]; function updateToLokiSchemaVersion1(currentVersion, db) { @@ -1251,6 +1252,63 @@ function updateToLokiSchemaVersion17(currentVersion, db) { console.log(`updateToLokiSchemaVersion${targetVersion}: success!`); } +function updateToLokiSchemaVersion18(currentVersion, db) { + const targetVersion = 18; + if (currentVersion >= targetVersion) { + return; + } + console.log(`updateToLokiSchemaVersion${targetVersion}: starting...`); + + // Dropping all pre-existing schema relating to message searching. + // Recreating the full text search and related triggers + db.transaction(() => { + db.exec(` + DROP TRIGGER IF EXISTS messages_on_insert; + DROP TRIGGER IF EXISTS messages_on_delete; + DROP TRIGGER IF EXISTS messages_on_update; + DROP TABLE IF EXISTS ${MESSAGES_FTS_TABLE}; + `); + + writeLokiSchemaVersion(targetVersion, db); + })(); + + db.transaction(() => { + db.exec(` + -- Then we create our full-text search table and populate it + CREATE VIRTUAL TABLE ${MESSAGES_FTS_TABLE} + USING fts5(id UNINDEXED, body); + INSERT INTO ${MESSAGES_FTS_TABLE}(id, body) + SELECT id, body FROM ${MESSAGES_TABLE}; + -- Then we set up triggers to keep the full-text search table up to date + CREATE TRIGGER messages_on_insert AFTER INSERT ON ${MESSAGES_TABLE} BEGIN + INSERT INTO ${MESSAGES_FTS_TABLE} ( + id, + body + ) VALUES ( + new.id, + new.body + ); + END; + CREATE TRIGGER messages_on_delete AFTER DELETE ON ${MESSAGES_TABLE} BEGIN + DELETE FROM ${MESSAGES_FTS_TABLE} WHERE id = old.id; + END; + CREATE TRIGGER messages_on_update AFTER UPDATE ON ${MESSAGES_TABLE} BEGIN + DELETE FROM ${MESSAGES_FTS_TABLE} WHERE id = old.id; + INSERT INTO ${MESSAGES_FTS_TABLE}( + id, + body + ) VALUES ( + new.id, + new.body + ); + END; + `); + + writeLokiSchemaVersion(targetVersion, db); + })(); + console.log(`updateToLokiSchemaVersion${targetVersion}: success!`); +} + function writeLokiSchemaVersion(newVersion, db) { db.prepare( `INSERT INTO loki_schema( @@ -2220,6 +2278,34 @@ function getFirstUnreadMessageIdInConversation(conversationId) { return rows[0].id; } +/** + * Deletes all but the 10,000 last received messages. + */ +function trimMessages() { + globalInstance + .prepare( + ` + DELETE FROM ${MESSAGES_TABLE} + WHERE id NOT IN ( + SELECT id FROM ${MESSAGES_TABLE} + ORDER BY received_at DESC + LIMIT 10000 + ); + ` + ) + .run(); + + const rows = globalInstance + .prepare( + `SELECT * FROM ${MESSAGES_TABLE} + ORDER BY received_at DESC;` + ) + .all(); + + return rows; + // return map(rows, row => jsonToObject(row.json)); +} + function getMessagesBySentAt(sentAt) { const rows = globalInstance .prepare( @@ -2921,3 +3007,108 @@ function removeOneOpenGroupV1Message() { return toRemoveCount - 1; } + +/** + * Only using this for development. Populate conversation and message tables. + * @param {*} numConvosToAdd + * @param {*} numMsgsToAdd + */ +function fillWithTestData(numConvosToAdd, numMsgsToAdd) { + const convoBeforeCount = globalInstance + .prepare(`SELECT count(*) from ${CONVERSATIONS_TABLE};`) + .get()['count(*)']; + + const lipsum = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis ac ornare lorem, non suscipit purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse cursus aliquet velit a dignissim. Integer at nisi sed velit consequat dictum. Phasellus congue tellus ante. Ut rutrum hendrerit dapibus. Fusce luctus, ante nec interdum molestie, purus urna volutpat turpis, eget mattis lectus velit at velit. Praesent vel tellus turpis. Praesent eget purus at nisl blandit pharetra. Cras dapibus sem vitae rutrum dapibus. Vivamus vitae mi ante. Donec aliquam porta nibh, vel scelerisque orci condimentum sed. Proin in mattis ipsum, ac euismod sem. Donec malesuada sem nisl, at vehicula ante efficitur sed. Curabitur in sapien eros. Morbi tempor ante ut metus scelerisque condimentum. Integer sit amet tempus nulla. Vivamus imperdiet dui ac luctus vulputate. Sed a accumsan risus. Nulla facilisi. Nulla mauris dui, luctus in sagittis at, sodales id mauris. Integer efficitur viverra ex, ut dignissim eros tincidunt placerat. Sed facilisis gravida mauris in luctus. Fusce dapibus, est vitae tincidunt eleifend, justo odio porta dui, sed ultrices mi arcu vitae ante. Mauris ut libero erat. Nam ut mi quis ante tincidunt facilisis sit amet id enim. Vestibulum in molestie mi. In ac felis est. Vestibulum vel blandit ex. Morbi vitae viverra augue. Ut turpis quam, cursus quis ex a, convallis ullamcorper purus. Nam eget libero arcu. Integer fermentum enim nunc, non consequat urna fermentum condimentum. Nulla vitae malesuada est. Donec imperdiet tortor interdum malesuada feugiat. Integer pulvinar dui ex, eget tristique arcu mattis at. Nam eu neque eget mauris varius suscipit. Quisque ac enim vitae mauris laoreet congue nec sed justo. Curabitur fermentum quam eget est tincidunt, at faucibus lacus maximus. Donec auctor enim dolor, faucibus egestas diam consectetur sed. Donec eget rutrum arcu, at tempus mi. Fusce quis volutpat sapien. In aliquet fringilla purus. Ut eu nunc non augue lacinia ultrices at eget tortor. Maecenas pulvinar odio sit amet purus elementum, a vehicula lorem maximus. Pellentesque eu lorem magna. Vestibulum ut facilisis lorem. Proin et enim cursus, vulputate neque sit amet, posuere enim. Praesent faucibus tellus vel mi tincidunt, nec malesuada nibh malesuada. In laoreet sapien vitae aliquet sollicitudin.'; + + const msgBeforeCount = globalInstance.prepare(`SELECT count(*) from ${MESSAGES_TABLE};`).get()[ + 'count(*)' + ]; + + console.warn('==== fillWithTestData ===='); + console.warn({ + convoBeforeCount, + msgBeforeCount, + convoToAdd: numConvosToAdd, + msgToAdd: numMsgsToAdd, + }); + + const convosIdsAdded = []; + // eslint-disable-next-line no-plusplus + for (let index = 0; index < numConvosToAdd; index++) { + const activeAt = Date.now() - index; + const id = Date.now() - 1000 * index; + const convoObjToAdd = { + active_at: activeAt, + members: [], + profileName: `${activeAt}`, + name: `${activeAt}`, + id: `05${id}`, + type: 'group', + }; + convosIdsAdded.push(id); + try { + saveConversation(convoObjToAdd); + // eslint-disable-next-line no-empty + } catch (e) {} + } + console.warn('convosIdsAdded', convosIdsAdded); + // eslint-disable-next-line no-plusplus + for (let index = 0; index < numMsgsToAdd; index++) { + const activeAt = Date.now() - index; + const id = Date.now() - 1000 * index; + + const lipsumStartIdx = Math.floor(Math.random() * lipsum.length); + const lipsumLength = Math.floor(Math.random() * lipsum.length - lipsumStartIdx); + const fakeBodyText = lipsum.substring(lipsumStartIdx, lipsumStartIdx + lipsumLength); + + const convoId = convosIdsAdded[Math.floor(Math.random() * convosIdsAdded.length)]; + const msgObjToAdd = { + // body: `fake body ${activeAt}`, + body: `fakeMsgIdx-spongebob-${index} ${fakeBodyText} ${activeAt}`, + conversationId: `${convoId}`, + // eslint-disable-next-line camelcase + expires_at: 0, + hasAttachments: 0, + hasFileAttachments: 0, + hasVisualMediaAttachments: 0, + id: `${id}`, + serverId: 0, + serverTimestamp: 0, + // eslint-disable-next-line camelcase + received_at: Date.now(), + schemaVersion: 5, + sent: 0, + // eslint-disable-next-line camelcase + sent_at: Date.now(), + source: `${convoId}`, + sourceDevice: 1, + type: '%', + unread: 1, + expireTimer: 0, + expirationStartTimestamp: 0, + }; + + if (convoId % 10 === 0) { + console.info('uyo , convoId ', { index, convoId }); + } + + try { + saveMessage(msgObjToAdd); + // eslint-disable-next-line no-empty + } catch (e) { + console.warn(e); + } + } + + const convoAfterCount = globalInstance + .prepare(`SELECT count(*) from ${CONVERSATIONS_TABLE};`) + .get()['count(*)']; + + const msgAfterCount = globalInstance.prepare(`SELECT count(*) from ${MESSAGES_TABLE};`).get()[ + 'count(*)' + ]; + + console.warn({ convoAfterCount, msgAfterCount }); + return convosIdsAdded; +} diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 95ae355e8..b30249321 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -1547,7 +1547,7 @@ white-space: nowrap; text-overflow: ellipsis; - color: $color-gray-90; + color: var(--color-text-subtle); } .module-message-search-result__header__timestamp { diff --git a/ts/components/basic/MessageBodyHighlist.tsx b/ts/components/basic/MessageBodyHighlist.tsx new file mode 100644 index 000000000..520cff140 --- /dev/null +++ b/ts/components/basic/MessageBodyHighlist.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { RenderTextCallbackType } from '../../types/Util'; +import { SizeClassType } from '../../util/emoji'; +import { AddNewLines } from '../conversation/AddNewLines'; +import { Emojify } from '../conversation/Emojify'; +import { MessageBody } from '../conversation/message/message-content/MessageBody'; + +interface Props { + text: string; +} + +const renderNewLines: RenderTextCallbackType = ({ text, key }) => ( + +); + +const renderEmoji = ({ + text, + key, + sizeClass, + renderNonEmoji, +}: { + text: string; + key: number; + sizeClass?: SizeClassType; + renderNonEmoji: RenderTextCallbackType; +}) => ; + +export class MessageBodyHighlight extends React.Component { + public render() { + const { text } = this.props; + const results: Array = []; + const FIND_BEGIN_END = /<>(.+?)<>/g; + + let match = FIND_BEGIN_END.exec(text); + let last = 0; + let count = 1; + + if (!match) { + return ; + } + + const sizeClass = ''; + + while (match) { + if (last < match.index) { + const beforeText = text.slice(last, match.index); + results.push( + renderEmoji({ + text: beforeText, + sizeClass, + key: count++, + renderNonEmoji: renderNewLines, + }) + ); + } + + const [, toHighlight] = match; + results.push( + + {renderEmoji({ + text: toHighlight, + sizeClass, + key: count++, + renderNonEmoji: renderNewLines, + })} + + ); + + // @ts-ignore + last = FIND_BEGIN_END.lastIndex; + match = FIND_BEGIN_END.exec(text); + } + + if (last < text.length) { + results.push( + renderEmoji({ + text: text.slice(last), + sizeClass, + key: count++, + renderNonEmoji: renderNewLines, + }) + ); + } + + return results; + } +} diff --git a/ts/components/search/MessageSearchResults.tsx b/ts/components/search/MessageSearchResults.tsx new file mode 100644 index 000000000..6d645166d --- /dev/null +++ b/ts/components/search/MessageSearchResults.tsx @@ -0,0 +1,144 @@ +import React from 'react'; +import classNames from 'classnames'; + +import { MessageDirection } from '../../models/messageType'; +import { getOurPubKeyStrFromCache } from '../../session/utils/User'; +import { + FindAndFormatContactType, + openConversationWithMessages, +} from '../../state/ducks/conversations'; +import { ContactName } from '../conversation/ContactName'; +import { Avatar, AvatarSize } from '../avatar/Avatar'; +import { Timestamp } from '../conversation/Timestamp'; +import { MessageBodyHighlight } from '../basic/MessageBodyHighlist'; + +type PropsHousekeeping = { + isSelected?: boolean; +}; + +export type PropsForSearchResults = { + from: FindAndFormatContactType; + to: FindAndFormatContactType; + id: string; + conversationId: string; + destination: string; + source: string; + + direction?: string; + snippet?: string; //not sure about the type of snippet + receivedAt?: number; +}; + +type Props = PropsForSearchResults & PropsHousekeeping; + +const FromName = (props: { source: string; destination: string }) => { + const { source, destination } = props; + + const isNoteToSelf = destination === getOurPubKeyStrFromCache() && source === destination; + + if (isNoteToSelf) { + return ( + + {window.i18n('noteToSelf')} + + ); + } + + if (source === getOurPubKeyStrFromCache()) { + return {window.i18n('you')}; + } + + return ( + // tslint:disable: use-simple-attributes + + ); +}; + +const From = (props: { source: string; destination: string }) => { + const { source, destination } = props; + const fromName = ; + + const ourKey = getOurPubKeyStrFromCache(); + + // TODO: ww maybe add useConversationUsername hook within contact name + if (destination !== ourKey) { + return ( +
+ {fromName} {window.i18n('to')} + + + +
+ ); + } + + return
{fromName}
; +}; + +const AvatarItem = (props: { source: string }) => { + const { source } = props; + return ; +}; + +export const MessageSearchResult = (props: Props) => { + const { + isSelected, + id, + conversationId, + receivedAt, + snippet, + destination, + source, + direction, + } = props; + + const sourceOrDestinationDerivable = + (destination && direction === MessageDirection.outgoing) || + !destination || + !source || + (source && direction === MessageDirection.incoming); + + if (!sourceOrDestinationDerivable) { + return null; + } + + const effectiveSource = + !source && direction === MessageDirection.outgoing ? getOurPubKeyStrFromCache() : source; + const effectiveDestination = + !destination && direction === MessageDirection.incoming + ? getOurPubKeyStrFromCache() + : destination; + + return ( +
{ + openConversationWithMessages({ + conversationKey: conversationId, + messageId: id, + }); + }} + className={classNames( + 'module-message-search-result', + isSelected ? 'module-message-search-result--is-selected' : null + )} + > + +
+
+ +
+ +
+
+
+ +
+
+
+ ); +}; diff --git a/ts/components/search/SearchResults.tsx b/ts/components/search/SearchResults.tsx index 2d81e98dc..8a0b08e5c 100644 --- a/ts/components/search/SearchResults.tsx +++ b/ts/components/search/SearchResults.tsx @@ -3,10 +3,13 @@ import { ConversationListItemProps, MemoConversationListItemWithDetails, } from '../leftpane/conversation-list-item/ConversationListItem'; +import { MessageSearchResult } from './MessageSearchResults'; export type SearchResultsProps = { contacts: Array; conversations: Array; + // TODO: ww add proper typing + messages: Array; hideMessagesHeader: boolean; searchTerm: string; }; @@ -23,11 +26,12 @@ const ContactsItem = (props: { header: string; items: Array { - const { conversations, contacts, searchTerm } = props; + const { conversations, contacts, messages, searchTerm, hideMessagesHeader } = props; const haveConversations = conversations && conversations.length; const haveContacts = contacts && contacts.length; - const noResults = !haveConversations && !haveContacts; + const haveMessages = messages && messages.length; + const noResults = !haveConversations && !haveContacts && !haveMessages; return (
@@ -50,7 +54,7 @@ export const SearchResults = (props: SearchResultsProps) => { ) : null} - {/* {haveMessages ? ( + {haveMessages ? (
{hideMessagesHeader ? null : (
@@ -61,7 +65,7 @@ export const SearchResults = (props: SearchResultsProps) => { ))}
- ) : null} */} + ) : null}
); }; diff --git a/ts/components/settings/section/CategoryAppearance.tsx b/ts/components/settings/section/CategoryAppearance.tsx index c21ef9161..81d6e34e0 100644 --- a/ts/components/settings/section/CategoryAppearance.tsx +++ b/ts/components/settings/section/CategoryAppearance.tsx @@ -3,7 +3,15 @@ import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; // tslint:disable-next-line: no-submodule-imports import useUpdate from 'react-use/lib/useUpdate'; -import { createOrUpdateItem, hasLinkPreviewPopupBeenDisplayed } from '../../../data/data'; +import { + createOrUpdateItem, + fillWithTestData, + fillWithTestData2, + // fillWithTestData2, + getMessageCount, + hasLinkPreviewPopupBeenDisplayed, + trimMessages, +} from '../../../data/data'; import { ToastUtils } from '../../../session/utils'; import { updateConfirmModal } from '../../../state/ducks/modalDialog'; import { toggleAudioAutoplay } from '../../../state/ducks/userConfig'; @@ -131,6 +139,30 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null buttonColor={SessionButtonColor.Primary} buttonText={window.i18n('translation')} /> + { + console.warn('trim the database to last 10k messages'); + + const msgCount = await getMessageCount(); + const deleteAmount = Math.max(msgCount - 10000, 0); + + dispatch( + updateConfirmModal({ + onClickOk: () => { + void trimMessages(); + }, + onClickClose: () => { + updateConfirmModal(null); + }, + message: `Are you sure you want to delete your ${deleteAmount} oldest received messages?`, + }) + ); + }} + buttonColor={SessionButtonColor.Primary} + buttonText={window.i18n('trimDatabase')} + /> { ipcRenderer.send('show-debug-log'); @@ -138,6 +170,20 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null buttonColor={SessionButtonColor.Primary} buttonText={window.i18n('showDebugLog')} /> + { + fillWithTestData(100, 2000000); + }} + buttonColor={SessionButtonColor.Primary} + buttonText={'Spam fill DB'} + /> + { + fillWithTestData2(100, 1000); + }} + buttonColor={SessionButtonColor.Primary} + buttonText={'Spam fill DB using cached'} + /> ); } diff --git a/ts/data/data.ts b/ts/data/data.ts index e5cc48e59..2e7c76825 100644 --- a/ts/data/data.ts +++ b/ts/data/data.ts @@ -3,10 +3,15 @@ import { ipcRenderer } from 'electron'; // tslint:disable: no-require-imports no-var-requires one-variable-per-declaration no-void-expression import _ from 'lodash'; -import { ConversationCollection, ConversationModel } from '../models/conversation'; +import { + ConversationCollection, + ConversationModel, + ConversationTypeEnum, +} from '../models/conversation'; import { MessageCollection, MessageModel } from '../models/message'; -import { MessageAttributes } from '../models/messageType'; +import { MessageAttributes, MessageDirection } from '../models/messageType'; import { HexKeyPair } from '../receiver/keypairs'; +import { getConversationController } from '../session/conversations'; import { getSodium } from '../session/crypto'; import { PubKey } from '../session/types'; import { fromArrayBufferToBase64, fromBase64ToArrayBuffer } from '../session/utils/String'; @@ -109,6 +114,7 @@ const channelsToMake = { removeAllMessagesInConversation, + getMessageCount, getMessageBySender, getMessageBySenderAndServerTimestamp, getMessageBySenderAndTimestamp, @@ -123,6 +129,7 @@ const channelsToMake = { hasConversationOutgoingMessage, getSeenMessagesByHashList, getLastHashBySnode, + trimMessages, getUnprocessedCount, getAllUnprocessed, @@ -156,6 +163,9 @@ const channelsToMake = { removeAllClosedGroupEncryptionKeyPairs, removeOneOpenGroupV1Message, + // dev performance testing + fillWithTestData, + // open group v2 ...channelstoMakeOpenGroupV2, }; @@ -191,8 +201,12 @@ export function init() { }); } -// When IPC arguments are prepared for the cross-process send, they are JSON.stringified. -// We can't send ArrayBuffers or BigNumbers (what we get from proto library for dates). +/** + * When IPC arguments are prepared for the cross-process send, they are JSON.stringified. + * We can't send ArrayBuffers or BigNumbers (what we get from proto library for dates). + * @param data + * @returns + */ function _cleanData(data: any): any { const keys = Object.keys(data); @@ -758,6 +772,13 @@ export async function getMessagesByConversation( return new MessageCollection(messages); } +/** + * @returns Returns count of all messages in the database + */ +export async function getMessageCount() { + return await channels.getMessageCount(); +} + export async function getFirstUnreadMessageIdInConversation( conversationId: string ): Promise { @@ -801,6 +822,12 @@ export async function removeAllMessagesInConversation(conversationId: string): P } while (messages.length > 0); } +export async function trimMessages(): Promise { + const count = await channels.trimMessages(); + console.warn({ count }); + return; +} + export async function getMessagesBySentAt(sentAt: number): Promise { const messages = await channels.getMessagesBySentAt(sentAt); return new MessageCollection(messages); @@ -964,3 +991,49 @@ export async function updateSnodePoolOnDb(snodesAsJsonString: string): Promise { return channels.removeOneOpenGroupV1Message(); } + +/** + * Generates fake conversations and distributes messages amongst the conversations randomly + * @param numConvosToAdd Amount of fake conversations to generate + * @param numMsgsToAdd Number of fake messages to generate + */ +export async function fillWithTestData( + numConvosToAdd: number, + numMsgsToAdd: number +): Promise { + if (!channels.fillWithTestData) { + return; + } + const ids = await channels.fillWithTestData(numConvosToAdd, numMsgsToAdd); + ids.map(async (id: string) => { + const convo = getConversationController().get(id); + const convoMsg = 'x'; + convo.set('lastMessage', convoMsg); + }); +} + +export const fillWithTestData2 = async (convs: number, msgs: number) => { + const newConvos = []; + for (let convsAddedCount = 0; convsAddedCount < convs; convsAddedCount++) { + const convoId = Date.now() + convsAddedCount + ''; + const newConvo = await getConversationController().getOrCreateAndWait( + convoId, + ConversationTypeEnum.PRIVATE + ); + newConvos.push(newConvo); + } + + for (let msgsAddedCount = 0; msgsAddedCount < msgs; msgsAddedCount++) { + if (msgsAddedCount % 100 == 0) { + console.warn(msgsAddedCount); + } + const convoToChoose = newConvos[Math.floor(Math.random() * newConvos.length)]; + convoToChoose.addSingleMessage({ + source: convoToChoose.id, + type: MessageDirection.outgoing, + conversationId: convoToChoose.id, + body: 'spongebob ' + new Date().toString(), + direction: Math.random() > 0.5 ? 'outgoing' : 'incoming', + }); + } +}; diff --git a/ts/models/messageType.ts b/ts/models/messageType.ts index b2455de9b..bf79517ec 100644 --- a/ts/models/messageType.ts +++ b/ts/models/messageType.ts @@ -118,6 +118,11 @@ export interface DataExtractionNotificationMsg { referencedAttachmentTimestamp: number; // the attachment timestamp he screenshot } +export enum MessageDirection { + outgoing = 'outgoing', + incoming = 'incoming', +} + export type PropsForDataExtractionNotification = DataExtractionNotificationMsg & { name: string; messageId: string; diff --git a/ts/state/ducks/search.ts b/ts/state/ducks/search.ts index 38ab06d4d..7a48f859b 100644 --- a/ts/state/ducks/search.ts +++ b/ts/state/ducks/search.ts @@ -16,6 +16,10 @@ export type SearchStateType = { // For conversations we store just the id, and pull conversation props in the selector conversations: Array; contacts: Array; + + // TODO: ww typing + messages?: Array; + messagesLookup?: any; }; // Actions @@ -24,6 +28,9 @@ type SearchResultsPayloadType = { normalizedPhoneNumber?: string; conversations: Array; contacts: Array; + + // TODO: ww typing + messages?: Array; }; type SearchResultsKickoffActionType = { @@ -94,6 +101,7 @@ async function doSearch(query: string, options: SearchOptions): Promise }); export const getSearchResults = createSelector( - [getSearch, getConversationLookup, getSelectedConversationKey], - (state: SearchStateType, lookup: ConversationLookupType, selectedConversation?: string) => { + [getSearch, getConversationLookup, getSelectedConversationKey, getSelectedMessage], + ( + searchState: SearchStateType, + lookup: ConversationLookupType, + selectedConversation?: string, + selectedMessage?: string + ) => { + console.warn({ state: searchState }); return { contacts: compact( - state.contacts.map(id => { + searchState.contacts.map(id => { const value = lookup[id]; if (value && id === selectedConversation) { @@ -41,7 +47,7 @@ export const getSearchResults = createSelector( }) ), conversations: compact( - state.conversations.map(id => { + searchState.conversations.map(id => { const value = lookup[id]; // Don't return anything when activeAt is unset (i.e. no current conversations with this user) @@ -60,9 +66,21 @@ export const getSearchResults = createSelector( return value; }) ), + messages: compact( + searchState.messages?.map(message => { + if (message.id === selectedMessage) { + return { + ...message, + isSelected: true, + }; + } + + return message; + }) + ), hideMessagesHeader: false, - searchTerm: state.query, + searchTerm: searchState.query, }; } ); diff --git a/ts/types/LocalizerKeys.ts b/ts/types/LocalizerKeys.ts index 18945b0c3..218956f2a 100644 --- a/ts/types/LocalizerKeys.ts +++ b/ts/types/LocalizerKeys.ts @@ -460,4 +460,6 @@ export type LocalizerKeys = | 'searchFor...' | 'joinedTheGroup' | 'editGroupName' + | 'trimDatabase' + | 'trimDatabaseDescription' | 'reportIssue'; From 2122214ee45283e5b16470570fd6d845bc9ccd58 Mon Sep 17 00:00:00 2001 From: warrickct Date: Wed, 22 Dec 2021 11:27:53 +1100 Subject: [PATCH 2/5] Fixed contact names not showing for search results --- ts/components/conversation/ContactName.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ts/components/conversation/ContactName.tsx b/ts/components/conversation/ContactName.tsx index f906a91cf..1a58b0666 100644 --- a/ts/components/conversation/ContactName.tsx +++ b/ts/components/conversation/ContactName.tsx @@ -2,6 +2,7 @@ import React from 'react'; import classNames from 'classnames'; import { Emojify } from './Emojify'; +import { useConversationUsername } from '../../hooks/useParamSelector'; type Props = { pubkey: string; @@ -17,13 +18,15 @@ export const ContactName = (props: Props) => { const { pubkey, name, profileName, module, boldProfileName, compact, shouldShowPubkey } = props; const prefix = module ? module : 'module-contact-name'; - const shouldShowProfile = Boolean(profileName || name); + const convoName = useConversationUsername(pubkey); + + const shouldShowProfile = Boolean(convoName || profileName || name); const styles = (boldProfileName ? { fontWeight: 'bold', } : {}) as React.CSSProperties; - const textProfile = profileName || name || window.i18n('anonymous'); + const textProfile = profileName || name || convoName || window.i18n('anonymous'); const profileElement = shouldShowProfile ? ( From 7846891359c608e78fc14a3042a9d0c18ab54383 Mon Sep 17 00:00:00 2001 From: warrickct Date: Wed, 22 Dec 2021 13:48:19 +1100 Subject: [PATCH 3/5] Fix linting errors --- app/sql.js | 36 ++++++++++++++++++- ts/components/search/MessageSearchResults.tsx | 4 +-- .../settings/section/CategoryAppearance.tsx | 4 +-- ts/data/data.ts | 17 ++++----- 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/app/sql.js b/app/sql.js index 8733a2717..14abeeba1 100644 --- a/app/sql.js +++ b/app/sql.js @@ -73,6 +73,8 @@ module.exports = { getMessagesByConversation, getFirstUnreadMessageIdInConversation, hasConversationOutgoingMessage, + trimMessages, + fillWithTestData, getUnprocessedCount, getAllUnprocessed, @@ -3019,7 +3021,39 @@ function fillWithTestData(numConvosToAdd, numMsgsToAdd) { .get()['count(*)']; const lipsum = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis ac ornare lorem, non suscipit purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse cursus aliquet velit a dignissim. Integer at nisi sed velit consequat dictum. Phasellus congue tellus ante. Ut rutrum hendrerit dapibus. Fusce luctus, ante nec interdum molestie, purus urna volutpat turpis, eget mattis lectus velit at velit. Praesent vel tellus turpis. Praesent eget purus at nisl blandit pharetra. Cras dapibus sem vitae rutrum dapibus. Vivamus vitae mi ante. Donec aliquam porta nibh, vel scelerisque orci condimentum sed. Proin in mattis ipsum, ac euismod sem. Donec malesuada sem nisl, at vehicula ante efficitur sed. Curabitur in sapien eros. Morbi tempor ante ut metus scelerisque condimentum. Integer sit amet tempus nulla. Vivamus imperdiet dui ac luctus vulputate. Sed a accumsan risus. Nulla facilisi. Nulla mauris dui, luctus in sagittis at, sodales id mauris. Integer efficitur viverra ex, ut dignissim eros tincidunt placerat. Sed facilisis gravida mauris in luctus. Fusce dapibus, est vitae tincidunt eleifend, justo odio porta dui, sed ultrices mi arcu vitae ante. Mauris ut libero erat. Nam ut mi quis ante tincidunt facilisis sit amet id enim. Vestibulum in molestie mi. In ac felis est. Vestibulum vel blandit ex. Morbi vitae viverra augue. Ut turpis quam, cursus quis ex a, convallis ullamcorper purus. Nam eget libero arcu. Integer fermentum enim nunc, non consequat urna fermentum condimentum. Nulla vitae malesuada est. Donec imperdiet tortor interdum malesuada feugiat. Integer pulvinar dui ex, eget tristique arcu mattis at. Nam eu neque eget mauris varius suscipit. Quisque ac enim vitae mauris laoreet congue nec sed justo. Curabitur fermentum quam eget est tincidunt, at faucibus lacus maximus. Donec auctor enim dolor, faucibus egestas diam consectetur sed. Donec eget rutrum arcu, at tempus mi. Fusce quis volutpat sapien. In aliquet fringilla purus. Ut eu nunc non augue lacinia ultrices at eget tortor. Maecenas pulvinar odio sit amet purus elementum, a vehicula lorem maximus. Pellentesque eu lorem magna. Vestibulum ut facilisis lorem. Proin et enim cursus, vulputate neque sit amet, posuere enim. Praesent faucibus tellus vel mi tincidunt, nec malesuada nibh malesuada. In laoreet sapien vitae aliquet sollicitudin.'; + // eslint:disable-next-line max-line-length + `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis ac ornare lorem, + non suscipit purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Suspendisse cursus aliquet velit a dignissim. Integer at nisi sed velit consequat + dictum. Phasellus congue tellus ante. Ut rutrum hendrerit dapibus. Fusce + luctus, ante nec interdum molestie, purus urna volutpat turpis, eget mattis + lectus velit at velit. Praesent vel tellus turpis. Praesent eget purus at + nisl blandit pharetra. Cras dapibus sem vitae rutrum dapibus. Vivamus vitae mi + ante. Donec aliquam porta nibh, vel scelerisque orci condimentum sed. + Proin in mattis ipsum, ac euismod sem. Donec malesuada sem nisl, at + vehicula ante efficitur sed. Curabitur in sapien eros. Morbi tempor ante ut + metus scelerisque condimentum. Integer sit amet tempus nulla. Vivamus + imperdiet dui ac luctus vulputate. Sed a accumsan risus. Nulla facilisi. + Nulla mauris dui, luctus in sagittis at, sodales id mauris. Integer efficitur + viverra ex, ut dignissim eros tincidunt placerat. Sed facilisis gravida + mauris in luctus . Fusce dapibus, est vitae tincidunt eleifend, justo + odio porta dui, sed ultrices mi arcu vitae ante. Mauris ut libero + erat. Nam ut mi quis ante tincidunt facilisis sit amet id enim. + Vestibulum in molestie mi. In ac felis est. Vestibulum vel blandit ex. Morbi vitae + viverra augue . Ut turpis quam, cursus quis ex a, convallis + ullamcorper purus. Nam eget libero arcu. Integer fermentum enim nunc, non consequat urna + fermentum condimentum. Nulla vitae malesuada est. Donec imperdiet tortor interdum + malesuada feugiat. Integer pulvinar dui ex, eget tristique arcu mattis at. Nam eu neque + eget mauris varius suscipit. Quisque ac enim vitae mauris laoreet congue nec sed + justo. Curabitur fermentum quam eget est tincidunt, at faucibus lacus maximus. Donec + auctor enim dolor, faucibus egestas diam consectetur sed. Donec eget rutrum arcu, at + tempus mi. Fusce quis volutpat sapien. In aliquet fringilla purus. Ut eu nunc non + augue lacinia ultrices at eget tortor. Maecenas pulvinar odio sit amet purus + elementum, a vehicula lorem maximus. Pellentesque eu lorem magna. Vestibulum ut facilisis + lorem. Proin et enim cursus, vulputate neque sit amet, posuere enim. Praesent + faucibus tellus vel mi tincidunt, nec malesuada nibh malesuada. In laoreet sapien vitae + aliquet sollicitudin. + `; const msgBeforeCount = globalInstance.prepare(`SELECT count(*) from ${MESSAGES_TABLE};`).get()[ 'count(*)' diff --git a/ts/components/search/MessageSearchResults.tsx b/ts/components/search/MessageSearchResults.tsx index 6d645166d..198d69223 100644 --- a/ts/components/search/MessageSearchResults.tsx +++ b/ts/components/search/MessageSearchResults.tsx @@ -116,8 +116,8 @@ export const MessageSearchResult = (props: Props) => { return (
{ - openConversationWithMessages({ + onClick={async () => { + await openConversationWithMessages({ conversationKey: conversationId, messageId: id, }); diff --git a/ts/components/settings/section/CategoryAppearance.tsx b/ts/components/settings/section/CategoryAppearance.tsx index 81d6e34e0..8bac7a476 100644 --- a/ts/components/settings/section/CategoryAppearance.tsx +++ b/ts/components/settings/section/CategoryAppearance.tsx @@ -172,14 +172,14 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null /> { - fillWithTestData(100, 2000000); + await fillWithTestData(100, 2000000); }} buttonColor={SessionButtonColor.Primary} buttonText={'Spam fill DB'} /> { - fillWithTestData2(100, 1000); + await fillWithTestData2(100, 1000); }} buttonColor={SessionButtonColor.Primary} buttonText={'Spam fill DB using cached'} diff --git a/ts/data/data.ts b/ts/data/data.ts index 2e7c76825..410865fa0 100644 --- a/ts/data/data.ts +++ b/ts/data/data.ts @@ -204,8 +204,7 @@ export function init() { /** * When IPC arguments are prepared for the cross-process send, they are JSON.stringified. * We can't send ArrayBuffers or BigNumbers (what we get from proto library for dates). - * @param data - * @returns + * @param data - data to be cleaned */ function _cleanData(data: any): any { const keys = Object.keys(data); @@ -776,7 +775,7 @@ export async function getMessagesByConversation( * @returns Returns count of all messages in the database */ export async function getMessageCount() { - return await channels.getMessageCount(); + return channels.getMessageCount(); } export async function getFirstUnreadMessageIdInConversation( @@ -1005,7 +1004,7 @@ export async function fillWithTestData( return; } const ids = await channels.fillWithTestData(numConvosToAdd, numMsgsToAdd); - ids.map(async (id: string) => { + ids.map((id: string) => { const convo = getConversationController().get(id); const convoMsg = 'x'; convo.set('lastMessage', convoMsg); @@ -1015,7 +1014,7 @@ export async function fillWithTestData( export const fillWithTestData2 = async (convs: number, msgs: number) => { const newConvos = []; for (let convsAddedCount = 0; convsAddedCount < convs; convsAddedCount++) { - const convoId = Date.now() + convsAddedCount + ''; + const convoId = `${Date.now()} + ${convsAddedCount}`; const newConvo = await getConversationController().getOrCreateAndWait( convoId, ConversationTypeEnum.PRIVATE @@ -1024,15 +1023,17 @@ export const fillWithTestData2 = async (convs: number, msgs: number) => { } for (let msgsAddedCount = 0; msgsAddedCount < msgs; msgsAddedCount++) { - if (msgsAddedCount % 100 == 0) { + if (msgsAddedCount % 100 === 0) { console.warn(msgsAddedCount); } + // tslint:disable: insecure-random const convoToChoose = newConvos[Math.floor(Math.random() * newConvos.length)]; - convoToChoose.addSingleMessage({ + await convoToChoose.addSingleMessage({ source: convoToChoose.id, type: MessageDirection.outgoing, conversationId: convoToChoose.id, - body: 'spongebob ' + new Date().toString(), + body: `spongebob ${new Date().toString()}`, + // tslint:disable: insecure-random direction: Math.random() > 0.5 ? 'outgoing' : 'incoming', }); } From 4349b699cb2bd16fdc567abcb08c61340b0924a8 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 7 Jan 2022 10:32:58 +1100 Subject: [PATCH 4/5] remove schemaVersion field and logic from message object --- app/sql.js | 33 +++++++++--- ts/components/search/MessageSearchResults.tsx | 3 ++ ts/components/search/SearchResults.tsx | 3 +- ts/data/data.ts | 1 + ts/models/conversation.ts | 48 ++++++----------- ts/models/message.ts | 7 --- ts/models/messageType.ts | 3 -- ts/receiver/queuedJob.ts | 4 -- ts/state/ducks/conversations.ts | 54 ++++++++++++++----- ts/state/ducks/search.ts | 9 ++-- ts/types/Attachment.ts | 9 ---- 11 files changed, 93 insertions(+), 81 deletions(-) diff --git a/app/sql.js b/app/sql.js index 14abeeba1..b45e9a9be 100644 --- a/app/sql.js +++ b/app/sql.js @@ -839,6 +839,7 @@ const LOKI_SCHEMA_VERSIONS = [ updateToLokiSchemaVersion16, updateToLokiSchemaVersion17, updateToLokiSchemaVersion18, + updateToLokiSchemaVersion19, ]; function updateToLokiSchemaVersion1(currentVersion, db) { @@ -1311,6 +1312,29 @@ function updateToLokiSchemaVersion18(currentVersion, db) { console.log(`updateToLokiSchemaVersion${targetVersion}: success!`); } +function updateToLokiSchemaVersion19(currentVersion, db) { + const targetVersion = 19; + if (currentVersion >= targetVersion) { + return; + } + console.log(`updateToLokiSchemaVersion${targetVersion}: starting...`); + + db.transaction(() => { + db.exec(` + DROP INDEX messages_schemaVersion; + ALTER TABLE ${MESSAGES_TABLE} DROP COLUMN schemaVersion; + `); + // this is way to slow for now... + // db.exec(` + // UPDATE ${MESSAGES_TABLE} SET + // json = json_remove(json, '$.schemaVersion') + // `); + writeLokiSchemaVersion(targetVersion, db); + })(); + + console.log(`updateToLokiSchemaVersion${targetVersion}: success!`); +} + function writeLokiSchemaVersion(newVersion, db) { db.prepare( `INSERT INTO loki_schema( @@ -1901,7 +1925,6 @@ function saveMessage(data) { serverTimestamp, // eslint-disable-next-line camelcase received_at, - schemaVersion, sent, // eslint-disable-next-line camelcase sent_at, @@ -1936,7 +1959,6 @@ function saveMessage(data) { hasFileAttachments, hasVisualMediaAttachments, received_at, - schemaVersion, sent, sent_at, source, @@ -1961,7 +1983,6 @@ function saveMessage(data) { hasFileAttachments, hasVisualMediaAttachments, received_at, - schemaVersion, sent, sent_at, source, @@ -1982,7 +2003,6 @@ function saveMessage(data) { $hasFileAttachments, $hasVisualMediaAttachments, $received_at, - $schemaVersion, $sent, $sent_at, $source, @@ -3034,11 +3054,11 @@ function fillWithTestData(numConvosToAdd, numMsgsToAdd) { vehicula ante efficitur sed. Curabitur in sapien eros. Morbi tempor ante ut metus scelerisque condimentum. Integer sit amet tempus nulla. Vivamus imperdiet dui ac luctus vulputate. Sed a accumsan risus. Nulla facilisi. - Nulla mauris dui, luctus in sagittis at, sodales id mauris. Integer efficitur + Nulla mauris dui, luctus in sagittis at, sodales id mauris. Integer efficitur viverra ex, ut dignissim eros tincidunt placerat. Sed facilisis gravida mauris in luctus . Fusce dapibus, est vitae tincidunt eleifend, justo odio porta dui, sed ultrices mi arcu vitae ante. Mauris ut libero - erat. Nam ut mi quis ante tincidunt facilisis sit amet id enim. + erat. Nam ut mi quis ante tincidunt facilisis sit amet id enim. Vestibulum in molestie mi. In ac felis est. Vestibulum vel blandit ex. Morbi vitae viverra augue . Ut turpis quam, cursus quis ex a, convallis ullamcorper purus. Nam eget libero arcu. Integer fermentum enim nunc, non consequat urna @@ -3111,7 +3131,6 @@ function fillWithTestData(numConvosToAdd, numMsgsToAdd) { serverTimestamp: 0, // eslint-disable-next-line camelcase received_at: Date.now(), - schemaVersion: 5, sent: 0, // eslint-disable-next-line camelcase sent_at: Date.now(), diff --git a/ts/components/search/MessageSearchResults.tsx b/ts/components/search/MessageSearchResults.tsx index 198d69223..9a2b1a987 100644 --- a/ts/components/search/MessageSearchResults.tsx +++ b/ts/components/search/MessageSearchResults.tsx @@ -96,6 +96,8 @@ export const MessageSearchResult = (props: Props) => { direction, } = props; + console.info('rendering search result message ', id); + const sourceOrDestinationDerivable = (destination && direction === MessageDirection.outgoing) || !destination || @@ -115,6 +117,7 @@ export const MessageSearchResult = (props: Props) => { return (
{ await openConversationWithMessages({ diff --git a/ts/components/search/SearchResults.tsx b/ts/components/search/SearchResults.tsx index 8a0b08e5c..a5e67425d 100644 --- a/ts/components/search/SearchResults.tsx +++ b/ts/components/search/SearchResults.tsx @@ -32,6 +32,7 @@ export const SearchResults = (props: SearchResultsProps) => { const haveContacts = contacts && contacts.length; const haveMessages = messages && messages.length; const noResults = !haveConversations && !haveContacts && !haveMessages; + console.info('SearchResults ', messages?.length); return (
@@ -62,7 +63,7 @@ export const SearchResults = (props: SearchResultsProps) => {
)} {messages.map(message => ( - + ))}
) : null} diff --git a/ts/data/data.ts b/ts/data/data.ts index 410865fa0..3b8b8c293 100644 --- a/ts/data/data.ts +++ b/ts/data/data.ts @@ -588,6 +588,7 @@ export async function searchConversations(query: string): Promise> { export async function searchMessages(query: string, { limit }: any = {}): Promise> { const messages = await channels.searchMessages(query, { limit }); + console.warn('searched message', messages); return messages; } diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 0f478b3e3..2d8d4df43 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -23,6 +23,7 @@ import { toHex } from '../session/utils/String'; import { actions as conversationActions, conversationChanged, + conversationsChanged, LastMessageStatusType, MessageModelPropsWithoutConvoProps, ReduxConversationType, @@ -204,10 +205,7 @@ export class ConversationModel extends Backbone.Model { trailing: true, leading: true, }); - this.triggerUIRefresh = _.throttle(this.triggerUIRefresh, 1000, { - trailing: true, - leading: true, - }); + this.throttledNotify = _.debounce(this.notify, 500, { maxWait: 5000, trailing: true }); //start right away the function is called, and wait 1sec before calling it again const markReadDebounced = _.debounce(this.markReadBouncy, 1000, { @@ -915,14 +913,8 @@ export class ConversationModel extends Backbone.Model { } public triggerUIRefresh() { - window.inboxStore?.dispatch( - conversationChanged({ - id: this.id, - data: { - ...this.getConversationModelProps(), - }, - }) - ); + updatesToDispatch.set(this.id, this.getConversationModelProps()); + trotthledAllConversationsDispatch(); } public async commit() { @@ -1253,26 +1245,6 @@ export class ConversationModel extends Backbone.Model { } } - public async upgradeMessages(messages: any) { - // tslint:disable-next-line: one-variable-per-declaration - for (let max = messages.length, i = 0; i < max; i += 1) { - const message = messages.at(i); - const { attributes } = message; - const { schemaVersion } = attributes; - - if (schemaVersion < window.Signal.Types.Message.VERSION_NEEDED_FOR_DISPLAY) { - // Yep, we really do want to wait for each of these - // eslint-disable-next-line no-await-in-loop - const { upgradeMessageSchema } = window.Signal.Migrations; - - const upgradedMessage = await upgradeMessageSchema(attributes); - message.set(upgradedMessage); - // eslint-disable-next-line no-await-in-loop - await upgradedMessage.commit(); - } - } - } - public hasMember(pubkey: string) { return _.includes(this.get('members'), pubkey); } @@ -1665,6 +1637,18 @@ export class ConversationModel extends Backbone.Model { } } +const trotthledAllConversationsDispatch = _.throttle(() => { + if (updatesToDispatch.size === 0) { + return; + } + console.warn('updatesToDispatch.size ', updatesToDispatch.size); + window.inboxStore?.dispatch(conversationsChanged([...updatesToDispatch.values()])); + + updatesToDispatch.clear(); +}, 500); + +const updatesToDispatch: Map = new Map(); + export class ConversationCollection extends Backbone.Collection { constructor(models?: Array) { super(models); diff --git a/ts/models/message.ts b/ts/models/message.ts index 6d2b36037..a4c03bb5d 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -75,13 +75,6 @@ export class MessageModel extends Backbone.Model { const filledAttrs = fillMessageAttributesWithDefaults(attributes); super(filledAttrs); - this.set( - window.Signal.Types.Message.initializeSchemaVersion({ - message: filledAttrs, - logger: window.log, - }) - ); - if (!this.attributes.id) { throw new Error('A message always needs to have an id.'); } diff --git a/ts/models/messageType.ts b/ts/models/messageType.ts index bf79517ec..d11d59c37 100644 --- a/ts/models/messageType.ts +++ b/ts/models/messageType.ts @@ -33,7 +33,6 @@ export interface MessageAttributes { hasAttachments: boolean; hasFileAttachments: boolean; hasVisualMediaAttachments: boolean; - schemaVersion: number; expirationTimerUpdate?: { expireTimer: number; source: string; @@ -163,7 +162,6 @@ export interface MessageAttributesOptionals { hasAttachments?: boolean; hasFileAttachments?: boolean; hasVisualMediaAttachments?: boolean; - schemaVersion?: number; expirationTimerUpdate?: { expireTimer: number; source: string; @@ -204,7 +202,6 @@ export const fillMessageAttributesWithDefaults = ( const defaulted = _.defaults(optAttributes, { expireTimer: 0, // disabled id: uuidv4(), - schemaVersion: window.Signal.Types.Message.CURRENT_SCHEMA_VERSION, unread: 0, // if nothing is set, this message is considered read }); // this is just to cleanup a bit the db. delivered and delivered_to were removed, so everytime we load a message diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index f3915ddb2..f18a2b871 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -18,9 +18,6 @@ function contentTypeSupported(type: string): boolean { // tslint:disable-next-line: cyclomatic-complexity async function copyFromQuotedMessage(msg: MessageModel, quote?: Quote): Promise { - const { upgradeMessageSchema } = window.Signal.Migrations; - const { Message: TypedMessage, Errors } = window.Signal.Types; - if (!quote) { return; } @@ -217,7 +214,6 @@ async function handleRegularMessage( hasFileAttachments: dataMessage.hasFileAttachments, hasVisualMediaAttachments: dataMessage.hasVisualMediaAttachments, quote: dataMessage.quote, - schemaVersion: dataMessage.schemaVersion, attachments: dataMessage.attachments, body: dataMessage.body, conversationId: conversation.id, diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index d19a83231..b1b2521f9 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -567,23 +567,25 @@ const conversationsSlice = createSlice({ }> ) { const { payload } = action; - const { id, data } = payload; - const { conversationLookup, selectedConversation } = state; + return applyConversationChanged(state, payload); + }, + conversationsChanged( + state: ConversationsStateType, + action: PayloadAction> + ) { + const { payload } = action; - const existing = conversationLookup[id]; - // In the change case we only modify the lookup if we already had that conversation - if (!existing) { - return state; + let updatedState = state; + if (payload.length) { + payload.forEach(convoProps => { + updatedState = applyConversationChanged(updatedState, { + id: convoProps.id, + data: convoProps, + }); + }); } - return { - ...state, - selectedConversation, - conversationLookup: { - ...conversationLookup, - [id]: data, - }, - }; + return updatedState; }, conversationRemoved(state: ConversationsStateType, action: PayloadAction) { @@ -784,12 +786,36 @@ const conversationsSlice = createSlice({ }, }); +function applyConversationChanged( + state: ConversationsStateType, + payload: { id: string; data: ReduxConversationType } +) { + const { id, data } = payload; + const { conversationLookup, selectedConversation } = state; + + const existing = conversationLookup[id]; + // In the change case we only modify the lookup if we already had that conversation + if (!existing) { + return state; + } + + return { + ...state, + selectedConversation, + conversationLookup: { + ...conversationLookup, + [id]: data, + }, + }; +} + // destructures export const { actions, reducer } = conversationsSlice; export const { // conversation and messages list conversationAdded, conversationChanged, + conversationsChanged, conversationRemoved, removeAllConversations, messageExpired, diff --git a/ts/state/ducks/search.ts b/ts/state/ducks/search.ts index 7a48f859b..4289313eb 100644 --- a/ts/state/ducks/search.ts +++ b/ts/state/ducks/search.ts @@ -5,6 +5,7 @@ import { searchConversations, searchMessages } from '../../../ts/data/data'; import { ReduxConversationType } from './conversations'; import { PubKey } from '../../session/types'; import { ConversationTypeEnum } from '../../models/conversation'; +import _ from 'lodash'; // State @@ -82,8 +83,8 @@ async function doSearch(query: string, options: SearchOptions): Promise message !== undefined); - + let filteredMessages = _.compact(messages); + console.warn('before filteredMessages ', filteredMessages); if (isAdvancedQuery) { let senderFilter: Array = []; if (advancedSearchOptions.from && advancedSearchOptions.from.length > 0) { @@ -95,7 +96,7 @@ async function doSearch(query: string, options: SearchOptions): Promise; interface AttachmentSchemaVersion3 { From 6992305e27e34290b46731614614694bc563954a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 7 Jan 2022 10:53:44 +1100 Subject: [PATCH 5/5] cleanup last commit --- ts/components/search/MessageSearchResults.tsx | 2 -- ts/components/search/SearchResults.tsx | 1 - ts/state/ducks/search.ts | 4 +--- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ts/components/search/MessageSearchResults.tsx b/ts/components/search/MessageSearchResults.tsx index 9a2b1a987..4f52ee20e 100644 --- a/ts/components/search/MessageSearchResults.tsx +++ b/ts/components/search/MessageSearchResults.tsx @@ -96,8 +96,6 @@ export const MessageSearchResult = (props: Props) => { direction, } = props; - console.info('rendering search result message ', id); - const sourceOrDestinationDerivable = (destination && direction === MessageDirection.outgoing) || !destination || diff --git a/ts/components/search/SearchResults.tsx b/ts/components/search/SearchResults.tsx index a5e67425d..88d96c35e 100644 --- a/ts/components/search/SearchResults.tsx +++ b/ts/components/search/SearchResults.tsx @@ -32,7 +32,6 @@ export const SearchResults = (props: SearchResultsProps) => { const haveContacts = contacts && contacts.length; const haveMessages = messages && messages.length; const noResults = !haveConversations && !haveContacts && !haveMessages; - console.info('SearchResults ', messages?.length); return (
diff --git a/ts/state/ducks/search.ts b/ts/state/ducks/search.ts index 4289313eb..6347aa9bd 100644 --- a/ts/state/ducks/search.ts +++ b/ts/state/ducks/search.ts @@ -84,7 +84,7 @@ async function doSearch(query: string, options: SearchOptions): Promise = []; if (advancedSearchOptions.from && advancedSearchOptions.from.length > 0) { @@ -96,7 +96,6 @@ async function doSearch(query: string, options: SearchOptions): Promise