diff --git a/_locales/en/messages.json b/_locales/en/messages.json index af3f62d7d..6750a6e39 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -137,6 +137,10 @@ "typingIndicatorsSettingDescription": "See and share when messages are being typed (applies to all sessions).", "typingIndicatorsSettingTitle": "Typing Indicators", "zoomFactorSettingTitle": "Zoom Factor", + "pruneSettingTitle": "Prune Old Open Group Messages", + "pruneSettingDescription": "When Session starts, prune messages older than this from groups with > 2000 messages (0 = no pruning)", + "pruneSettingUnit": "month", + "pruneSettingUnits": "months", "notificationSettingsDialog": "When messages arrive, display notifications that reveal...", "disableNotifications": "Mute notifications", "nameAndMessage": "Name and content", diff --git a/ts/components/settings/PruningSessionSlider.tsx b/ts/components/settings/PruningSessionSlider.tsx new file mode 100644 index 000000000..fad195771 --- /dev/null +++ b/ts/components/settings/PruningSessionSlider.tsx @@ -0,0 +1,36 @@ +import Slider from 'rc-slider'; +import React from 'react'; +// tslint:disable-next-line: no-submodule-imports +import useUpdate from 'react-use/lib/useUpdate'; +import { SessionSettingsItemWrapper } from './SessionSettingListItem'; +import { ToastUtils } from '../../session/utils'; + +export const PruningSessionSlider = (props: { onSliderChange?: (value: number) => void }) => { + const forceUpdate = useUpdate(); + const handleSlider = (valueToForward: number) => { + props?.onSliderChange?.(valueToForward); + window.setSettingValue('prune-setting', valueToForward); + ToastUtils.pushRestartNeeded(); + forceUpdate(); + }; + const currentValueFromSettings = window.getSettingValue('prune-setting') || 0; + + return ( + +
+ + +
+

{currentValueFromSettings} {currentValueFromSettings === 1 ? window.i18n('pruneSettingUnit') : window.i18n('pruneSettingUnits')}

+
+
+
+ ); +}; diff --git a/ts/components/settings/section/CategoryAppearance.tsx b/ts/components/settings/section/CategoryAppearance.tsx index 39e1b237b..d14b21d6d 100644 --- a/ts/components/settings/section/CategoryAppearance.tsx +++ b/ts/components/settings/section/CategoryAppearance.tsx @@ -13,6 +13,7 @@ import { SessionButtonColor } from '../../basic/SessionButton'; import { SessionSettingButtonItem, SessionToggleWithDescription } from '../SessionSettingListItem'; import { ZoomingSessionSlider } from '../ZoomingSessionSlider'; +import { PruningSessionSlider } from '../PruningSessionSlider'; async function toggleLinkPreviews() { const newValue = !window.getSettingValue('link-preview-setting'); @@ -119,6 +120,7 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null description={window.i18n('audioMessageAutoplayDescription')} active={audioAutoPlay} /> + { dropFtsAndTriggers(db); - v2Convos.forEach(convo => { - const convoId = convo.id; - const messagesInConvoBefore = getMessagesCountByConversation(convoId); - - if (messagesInConvoBefore >= maxMessagePerOpengroupConvo) { - const minute = 1000 * 60; - const sixMonths = minute * 60 * 24 * 30 * 6; - const messagesTimestampToRemove = Date.now() - sixMonths; - const countToRemove = assertGlobalInstance() - .prepare( - `SELECT count(*) from ${MESSAGES_TABLE} WHERE serverTimestamp <= $serverTimestamp AND conversationId = $conversationId;` - ) - .get({ conversationId: convoId, serverTimestamp: Date.now() - sixMonths })['count(*)']; - const start = Date.now(); - - assertGlobalInstance() - .prepare( - ` - DELETE FROM ${MESSAGES_TABLE} WHERE serverTimestamp <= $serverTimestamp AND conversationId = $conversationId` - ) - .run({ conversationId: convoId, serverTimestamp: messagesTimestampToRemove }); // delete messages older than sixMonths - const messagesInConvoAfter = getMessagesCountByConversation(convoId); - - console.info( - `Cleaning ${countToRemove} messages older than 6 months in public convo: ${convoId} took ${Date.now() - - start}ms. Old message count: ${messagesInConvoBefore}, new message count: ${messagesInConvoAfter}` - ); - - const unreadCount = getUnreadCountByConversation(convoId); - const convoProps = getConversationById(convoId); - if (convoProps) { - convoProps.unreadCount = unreadCount; - updateConversation(convoProps); + if (pruneSetting !== 0) { + v2Convos.forEach(convo => { + const convoId = convo.id; + const messagesInConvoBefore = getMessagesCountByConversation(convoId); + + if (messagesInConvoBefore >= maxMessagePerOpengroupConvo) { + const minute = 1000 * 60; + const userDefinedMonths = minute * 60 * 24 * 30 * pruneSetting; + const messagesTimestampToRemove = Date.now() - userDefinedMonths; + const countToRemove = assertGlobalInstance() + .prepare( + `SELECT count(*) from ${MESSAGES_TABLE} WHERE serverTimestamp <= $serverTimestamp AND conversationId = $conversationId;` + ) + .get({ conversationId: convoId, serverTimestamp: Date.now() - userDefinedMonths })['count(*)']; + const start = Date.now(); + + assertGlobalInstance() + .prepare( + ` + DELETE FROM ${MESSAGES_TABLE} WHERE serverTimestamp <= $serverTimestamp AND conversationId = $conversationId` + ) + .run({ conversationId: convoId, serverTimestamp: messagesTimestampToRemove }); // delete messages older than the user-specified age. + const messagesInConvoAfter = getMessagesCountByConversation(convoId); + + console.info( + `Cleaning ${countToRemove} messages older than ${pruneSetting} months in public convo: ${convoId} took ${Date.now() - + start}ms. Old message count: ${messagesInConvoBefore}, new message count: ${messagesInConvoAfter}` + ); + + const unreadCount = getUnreadCountByConversation(convoId); + const convoProps = getConversationById(convoId); + if (convoProps) { + convoProps.unreadCount = unreadCount; + updateConversation(convoProps); + } } - } - }); + }); + } else { + console.info('Skipping cleaning messages in public convos.'); + }; // now, we might have a bunch of private conversation, without any interaction and no messages // those are the conversation of the old members in the opengroups we just cleaned. @@ -3680,6 +3683,7 @@ export const sqlNode = { getPubkeysInPublicConversation, getAllGroupsInvolvingId, removeAllConversations, + cleanUpOldOpengroups, searchConversations, searchMessages, diff --git a/ts/types/LocalizerKeys.ts b/ts/types/LocalizerKeys.ts index 412e6c60d..ebbf75f96 100644 --- a/ts/types/LocalizerKeys.ts +++ b/ts/types/LocalizerKeys.ts @@ -162,6 +162,10 @@ export type LocalizerKeys = | 'copySessionID' | 'timerOption_0_seconds' | 'zoomFactorSettingTitle' + | 'pruneSettingTitle' + | 'pruneSettingDescription' + | 'pruneSettingUnit' + | 'pruneSettingUnits' | 'unableToCall' | 'callMissedTitle' | 'done'