convert to functional component. Tweak colors for search results. Fix search result header incorrect color. Addressing PR comments from previous search branch. Experimenting trimming approaches.

pull/2139/head
warrickct 3 years ago
parent 3f4db67c1b
commit 804c9a56b9

@ -464,5 +464,6 @@
"startedACall": "You called $name$",
"answeredACall": "Call with $name$",
"trimDatabase": "Trim Database",
"trimDatabaseDescription": "Reduces your message database size to your last 10,000 messages."
"trimDatabaseDescription": "Reduces your message database size to your last 10,000 messages.",
"trimDatabaseConfirmationBody": "Are you sure you want to delete your $deleteAmount$ oldest received messages?"
}

@ -7,6 +7,7 @@ const { redactAll } = require('../js/modules/privacy');
const { remove: removeUserConfig } = require('./user_config');
const { map, isString, fromPairs, forEach, last, isEmpty, isObject, isNumber } = require('lodash');
const { requestSnodesForPubkey } = require('../ts/session/apis/snode_api/SNodeAPI');
/* eslint-disable camelcase */
@ -2283,29 +2284,144 @@ function getFirstUnreadMessageIdInConversation(conversationId) {
/**
* Deletes all but the 10,000 last received messages.
*/
function trimMessages() {
globalInstance
function trimMessages(limit) {
// METHOD 1 Start - Seems to take to long and freeze
// const convoCount = globalInstance
// .prepare(
// `
// SELECT COUNT(*) FROM ${MESSAGES_TABLE}
// WHERE conversationId = $conversationId
// `
// )
// .all({
// conversationId,
// });
// if (convoCount < limit) {
// console.log(`Skipping conversation: ${conversationId}`);
// return;
// } else {
// console.count('convo surpassed limit');
// }
// globalInstance
// .prepare(
// `
// DELETE FROM ${MESSAGES_TABLE}
// WHERE conversationId = $conversationId
// AND id NOT IN (
// SELECT id FROM ${MESSAGES_TABLE}
// WHERE conversationId = $conversationId
// ORDER BY received_at DESC
// LIMIT $limit
// );
// `
// )
// .run({
// conversationId,
// limit,
// });
// METHOD 1 END
// METHOD 2 Start
const messages = globalInstance
.prepare(
`
DELETE FROM ${MESSAGES_TABLE}
WHERE id NOT IN (
SELECT id FROM ${MESSAGES_TABLE}
ORDER BY received_at DESC
LIMIT 10000
);
`
)
.run();
SELECT id, conversationId FROM ${MESSAGES_TABLE}
const rows = globalInstance
.prepare(
`SELECT * FROM ${MESSAGES_TABLE}
ORDER BY received_at DESC;`
CREATE VIRTUAL TABLE IF NOT EXISTS temp_deletion
id STRING PRIMARY KEY ASC
`
)
.all();
return rows;
// return map(rows, row => jsonToObject(row.json));
let idsToDelete = [];
const convoCountLookup = {};
for (let index = 0; index < messages.length; index++) {
const { conversationId, id } = messages[index];
console.log(`run ${index} - convoId: ${conversationId}, messageId: ${id}`);
if (!convoCountLookup[conversationId]) {
convoCountLookup[conversationId] = 1;
} else {
convoCountLookup[conversationId]++;
if (convoCountLookup[conversationId] > limit) {
idsToDelete.push(id);
}
}
}
// Ideally should be able to do WHERE id IN (x, y, z) with an array of IDs
// the array might need to be chunked as well for performance
const idSlice = [...idsToDelete].slice(0, 30);
idSlice.forEach(id => {
globalInstance
.prepare(
`
DELETE FROM ${MESSAGES_TABLE}
WHERE id = $idSlice
`
)
.run({
idSlice,
});
});
// Method 2 End
// Method 3 start - Audric's suggestion
// const largeConvos = globalInstance
// .prepare(
// `
// SELECT conversationId, count(id) FROM ${MESSAGES_TABLE}
// GROUP BY conversationId
// HAVING COUNT(id) > 1000
// `
// )
// .all();
// console.log({ largeConvos });
// // finding 1000th msg timestamp
// largeConvos.forEach(convo => {
// const convoId = convo.conversationId;
// console.log({ convoId });
// const lastMsg = globalInstance
// .prepare(
// `
// SELECT received_at, sent_at FROM ${MESSAGES_TABLE}
// WHERE conversationId = $convoId
// ORDER BY received_at DESC
// LIMIT 1
// OFFSET 999
// `
// )
// .all({
// convoId,
// });
// // use timestamp with lesserThan as conditional for deletion
// console.log({ lastMsg });
// const timestamp = lastMsg[0].received_at;
// if (timestamp) {
// console.log({ timestamp, convoId });
// globalInstance
// .prepare(
// `
// DELETE FROM ${MESSAGES_TABLE}
// WHERE conversationId = $convoId
// AND received_at < $timestamp
// `
// )
// .run({
// timestamp,
// convoId,
// });
// }
// });
}
function getMessagesBySentAt(sentAt) {

@ -1455,7 +1455,7 @@
.module-search-results {
overflow-y: auto;
max-height: 100%;
color: white;
color: var(--color-text);
}
.module-search-results__conversations-header {
@ -1547,7 +1547,7 @@
white-space: nowrap;
text-overflow: ellipsis;
color: var(--color-text-subtle);
color: var(--color-text);
}
.module-message-search-result__header__timestamp {
@ -1581,7 +1581,7 @@
font-size: 13px;
color: $color-gray-60;
color: var(--color-text-subtle);
max-height: 3.6em;

@ -0,0 +1,85 @@
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 }) => (
<AddNewLines key={key} text={text} />
);
const renderEmoji = ({
text,
key,
sizeClass,
renderNonEmoji,
}: {
text: string;
key: number;
sizeClass?: SizeClassType;
renderNonEmoji: RenderTextCallbackType;
}) => <Emojify key={key} text={text} sizeClass={sizeClass} renderNonEmoji={renderNonEmoji} />;
export const MessageBodyHighlight = (props: Props) => {
const { text } = props;
const results: Array<JSX.Element> = [];
const FIND_BEGIN_END = /<<left>>(.+?)<<right>>/g;
let match = FIND_BEGIN_END.exec(text);
let last = 0;
let count = 1;
if (!match) {
return <MessageBody disableJumbomoji={true} disableLinks={true} text={text} />;
}
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(
<span className="module-message-body__highlight" key={count++}>
{renderEmoji({
text: toHighlight,
sizeClass,
key: count++,
renderNonEmoji: renderNewLines,
})}
</span>
);
// @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}</>;
};

@ -1,87 +0,0 @@
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 }) => (
<AddNewLines key={key} text={text} />
);
const renderEmoji = ({
text,
key,
sizeClass,
renderNonEmoji,
}: {
text: string;
key: number;
sizeClass?: SizeClassType;
renderNonEmoji: RenderTextCallbackType;
}) => <Emojify key={key} text={text} sizeClass={sizeClass} renderNonEmoji={renderNonEmoji} />;
export class MessageBodyHighlight extends React.Component<Props> {
public render() {
const { text } = this.props;
const results: Array<any> = [];
const FIND_BEGIN_END = /<<left>>(.+?)<<right>>/g;
let match = FIND_BEGIN_END.exec(text);
let last = 0;
let count = 1;
if (!match) {
return <MessageBody disableJumbomoji={true} disableLinks={true} text={text} />;
}
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(
<span className="module-message-body__highlight" key={count++}>
{renderEmoji({
text: toHighlight,
sizeClass,
key: count++,
renderNonEmoji: renderNewLines,
})}
</span>
);
// @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;
}
}

@ -10,7 +10,7 @@ import {
import { ContactName } from '../conversation/ContactName';
import { Avatar, AvatarSize } from '../avatar/Avatar';
import { Timestamp } from '../conversation/Timestamp';
import { MessageBodyHighlight } from '../basic/MessageBodyHighlist';
import { MessageBodyHighlight } from '../basic/MessageBodyHighlight';
type PropsHousekeeping = {
isSelected?: boolean;
@ -29,7 +29,7 @@ export type PropsForSearchResults = {
receivedAt?: number;
};
type Props = PropsForSearchResults & PropsHousekeeping;
export type MessageResultProps = PropsForSearchResults & PropsHousekeeping;
const FromName = (props: { source: string; destination: string }) => {
const { source, destination } = props;
@ -64,7 +64,6 @@ const From = (props: { source: string; destination: string }) => {
const ourKey = getOurPubKeyStrFromCache();
// TODO: ww maybe add useConversationUsername hook within contact name
if (destination !== ourKey) {
return (
<div className="module-message-search-result__header__from">
@ -84,7 +83,7 @@ const AvatarItem = (props: { source: string }) => {
return <Avatar size={AvatarSize.S} pubkey={source} />;
};
export const MessageSearchResult = (props: Props) => {
export const MessageSearchResult = (props: MessageResultProps) => {
const {
isSelected,
id,
@ -96,6 +95,8 @@ export const MessageSearchResult = (props: Props) => {
direction,
} = props;
// Some messages miss a source or destination. Doing checks to see if the fields can be derived from other sources.
// E.g. if the source is missing but the message is outgoing, the source will be our pubkey
const sourceOrDestinationDerivable =
(destination && direction === MessageDirection.outgoing) ||
!destination ||

@ -3,13 +3,12 @@ import {
ConversationListItemProps,
MemoConversationListItemWithDetails,
} from '../leftpane/conversation-list-item/ConversationListItem';
import { MessageSearchResult } from './MessageSearchResults';
import { MessageResultProps, MessageSearchResult } from './MessageSearchResults';
export type SearchResultsProps = {
contacts: Array<ConversationListItemProps>;
conversations: Array<ConversationListItemProps>;
// TODO: ww add proper typing
messages: Array<any>;
messages: Array<MessageResultProps>;
hideMessagesHeader: boolean;
searchTerm: string;
};

@ -143,8 +143,6 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null
title={window.i18n('trimDatabase')}
description={window.i18n('trimDatabaseDescription')}
onClick={async () => {
console.warn('trim the database to last 10k messages');
const msgCount = await getMessageCount();
const deleteAmount = Math.max(msgCount - 10000, 0);
@ -156,7 +154,7 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null
onClickClose: () => {
updateConfirmModal(null);
},
message: `Are you sure you want to delete your ${deleteAmount} oldest received messages?`,
message: window.i18n('trimDatabaseConfirmationBody', [`${deleteAmount}`]),
})
);
}}

@ -822,8 +822,7 @@ export async function removeAllMessagesInConversation(conversationId: string): P
}
export async function trimMessages(): Promise<void> {
const count = await channels.trimMessages();
console.warn({ count });
await channels.trimMessages(1000);
return;
}

@ -29,8 +29,7 @@ type SearchResultsPayloadType = {
conversations: Array<string>;
contacts: Array<string>;
// TODO: ww typing
messages?: Array<any>;
messages?: Array<string>;
};
type SearchResultsKickoffActionType = {

@ -464,4 +464,5 @@ export type LocalizerKeys =
| 'editGroupName'
| 'trimDatabase'
| 'trimDatabaseDescription'
| 'trimDatabaseConfirmationBody'
| 'reportIssue';

Loading…
Cancel
Save