feat: ask user for opengroup pruning on/off

pull/2325/head
Audric Ackermann 3 years ago
parent 695e867221
commit 3713e95a9f
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -138,9 +138,12 @@
"typingIndicatorsSettingTitle": "Typing Indicators", "typingIndicatorsSettingTitle": "Typing Indicators",
"zoomFactorSettingTitle": "Zoom Factor", "zoomFactorSettingTitle": "Zoom Factor",
"pruneSettingTitle": "Prune Old Open Group Messages", "pruneSettingTitle": "Prune Old Open Group Messages",
"pruneSettingDescription": "When Session starts, prune messages older than this from groups with > 2000 messages (0 = no pruning)", "pruneSettingDescription": "Prune messages older than 6 months from Open Groups on start",
"pruneSettingUnit": "month", "pruningOpengroupDialogTitle": "Open group pruning",
"pruneSettingUnits": "months", "pruningOpengroupDialogMessage": "Pruning old open group messages improves performance. Enable pruning for open group messages older than 6 months?",
"pruningOpengroupDialogSubMessage": "You can change this setting in the Session settings menu",
"enable": "Enable",
"keepDisabled": "Keep disabled",
"notificationSettingsDialog": "When messages arrive, display notifications that reveal...", "notificationSettingsDialog": "When messages arrive, display notifications that reveal...",
"disableNotifications": "Mute notifications", "disableNotifications": "Mute notifications",
"nameAndMessage": "Name and content", "nameAndMessage": "Name and content",

@ -86,6 +86,28 @@ window.getStartInTray = async () => {
}); });
}; };
window.getOpengroupPruning = async () => {
return new Promise(resolve => {
ipc.once('get-opengroup-pruning-response', (_event, value) => {
resolve(value);
});
ipc.send('get-opengroup-pruning');
});
};
window.setOpengroupPruning = async opengroupPruning =>
new Promise((resolve, reject) => {
ipc.once('set-opengroup-pruning-response', (_event, error) => {
if (error) {
reject(error);
return;
}
resolve();
return;
});
ipc.send('set-opengroup-pruning', opengroupPruning);
});
window._ = require('lodash'); window._ = require('lodash');
// We never do these in our code, so we'll prevent it everywhere // We never do these in our code, so we'll prevent it everywhere

@ -551,7 +551,9 @@ label {
&-main-message { &-main-message {
font-size: $session-font-md; font-size: $session-font-md;
line-height: 1.5;
} }
&-sub-message { &-sub-message {
text-align: center; text-align: center;
margin-top: 20px; margin-top: 20px;

@ -30,7 +30,11 @@ import { cleanUpOldDecryptedMedias } from '../../session/crypto/DecryptedAttachm
import { DURATION } from '../../session/constants'; import { DURATION } from '../../session/constants';
import { conversationChanged, conversationRemoved } from '../../state/ducks/conversations'; import { conversationChanged, conversationRemoved } from '../../state/ducks/conversations';
import { editProfileModal, onionPathModal } from '../../state/ducks/modalDialog'; import {
editProfileModal,
onionPathModal,
updateConfirmModal,
} from '../../state/ducks/modalDialog';
import { uploadOurAvatar } from '../../interactions/conversationInteractions'; import { uploadOurAvatar } from '../../interactions/conversationInteractions';
import { ModalContainer } from '../dialog/ModalContainer'; import { ModalContainer } from '../dialog/ModalContainer';
import { debounce, isEmpty, isString } from 'lodash'; import { debounce, isEmpty, isString } from 'lodash';
@ -54,6 +58,9 @@ import { getLatestDesktopReleaseFileToFsV2 } from '../../session/apis/file_serve
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import { UserUtils } from '../../session/utils'; import { UserUtils } from '../../session/utils';
import { Storage } from '../../util/storage';
import { SettingsKey } from '../../data/settings-key';
const Section = (props: { type: SectionType }) => { const Section = (props: { type: SectionType }) => {
const ourNumber = useSelector(getOurNumber); const ourNumber = useSelector(getOurNumber);
const unreadMessageCount = useSelector(getUnreadMessageCount); const unreadMessageCount = useSelector(getUnreadMessageCount);
@ -251,6 +258,8 @@ const doAppStartUp = () => {
void loadDefaultRooms(); void loadDefaultRooms();
debounce(triggerAvatarReUploadIfNeeded, 200); debounce(triggerAvatarReUploadIfNeeded, 200);
void askEnablingOpengroupPruningIfNeeded();
}; };
const CallContainer = () => { const CallContainer = () => {
@ -279,6 +288,36 @@ async function fetchReleaseFromFSAndUpdateMain() {
} }
} }
async function askEnablingOpengroupPruningIfNeeded() {
if (Storage.get(SettingsKey.settingsOpengroupPruning) === undefined) {
const setSettingsAndCloseDialog = async (valueToSetPruningTo: boolean) => {
window.setSettingValue(SettingsKey.settingsOpengroupPruning, valueToSetPruningTo);
await window.setOpengroupPruning(valueToSetPruningTo);
window.inboxStore?.dispatch(updateConfirmModal(null));
};
window.inboxStore?.dispatch(
updateConfirmModal({
onClickOk: async () => {
await setSettingsAndCloseDialog(true);
},
onClickClose: async () => {
await setSettingsAndCloseDialog(false);
},
onClickCancel: async () => {
await setSettingsAndCloseDialog(false);
},
title: window.i18n('pruningOpengroupDialogTitle'),
message: window.i18n('pruningOpengroupDialogMessage'),
messageSub: window.i18n('pruningOpengroupDialogSubMessage'),
okText: window.i18n('enable'),
cancelText: window.i18n('keepDisabled'),
})
);
return;
}
// otherwise nothing to do. the settings is already on or off, but as expected by the user
}
/** /**
* ActionsPanel is the far left banner (not the left pane). * ActionsPanel is the far left banner (not the left pane).
* The panel with buttons to switch between the message/contact/settings/theme views * The panel with buttons to switch between the message/contact/settings/theme views

@ -1,36 +0,0 @@
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 (
<SessionSettingsItemWrapper title={window.i18n('pruneSettingTitle')} description={window.i18n('pruneSettingDescription')} inline={false}>
<div className="slider-wrapper">
<Slider
dots={true}
step={1}
min={0}
max={12}
defaultValue={currentValueFromSettings}
onAfterChange={handleSlider}
/>
<div className="slider-info">
<p>{currentValueFromSettings} {currentValueFromSettings === 1 ? window.i18n('pruneSettingUnit') : window.i18n('pruneSettingUnits')}</p>
</div>
</div>
</SessionSettingsItemWrapper>
);
};

@ -4,6 +4,7 @@ import { useDispatch, useSelector } from 'react-redux';
// tslint:disable-next-line: no-submodule-imports // tslint:disable-next-line: no-submodule-imports
import useUpdate from 'react-use/lib/useUpdate'; import useUpdate from 'react-use/lib/useUpdate';
import { createOrUpdateItem, hasLinkPreviewPopupBeenDisplayed } from '../../../data/data'; import { createOrUpdateItem, hasLinkPreviewPopupBeenDisplayed } from '../../../data/data';
import { SettingsKey } from '../../../data/settings-key';
import { ToastUtils } from '../../../session/utils'; import { ToastUtils } from '../../../session/utils';
import { updateConfirmModal } from '../../../state/ducks/modalDialog'; import { updateConfirmModal } from '../../../state/ducks/modalDialog';
import { toggleAudioAutoplay } from '../../../state/ducks/userConfig'; import { toggleAudioAutoplay } from '../../../state/ducks/userConfig';
@ -13,11 +14,10 @@ import { SessionButtonColor } from '../../basic/SessionButton';
import { SessionSettingButtonItem, SessionToggleWithDescription } from '../SessionSettingListItem'; import { SessionSettingButtonItem, SessionToggleWithDescription } from '../SessionSettingListItem';
import { ZoomingSessionSlider } from '../ZoomingSessionSlider'; import { ZoomingSessionSlider } from '../ZoomingSessionSlider';
import { PruningSessionSlider } from '../PruningSessionSlider';
async function toggleLinkPreviews() { async function toggleLinkPreviews() {
const newValue = !window.getSettingValue('link-preview-setting'); const newValue = !window.getSettingValue(SettingsKey.settingsLinkPreview);
window.setSettingValue('link-preview-setting', newValue); window.setSettingValue(SettingsKey.settingsLinkPreview, newValue);
if (!newValue) { if (!newValue) {
await createOrUpdateItem({ id: hasLinkPreviewPopupBeenDisplayed, value: false }); await createOrUpdateItem({ id: hasLinkPreviewPopupBeenDisplayed, value: false });
} else { } else {
@ -36,7 +36,7 @@ async function toggleStartInTray() {
const newValue = !(await window.getStartInTray()); const newValue = !(await window.getStartInTray());
// make sure to write it here too, as this is the value used on the UI to mark the toggle as true/false // make sure to write it here too, as this is the value used on the UI to mark the toggle as true/false
window.setSettingValue('start-in-tray-setting', newValue); window.setSettingValue(SettingsKey.settingsStartInTray, newValue);
await window.setStartInTray(newValue); await window.setStartInTray(newValue);
if (!newValue) { if (!newValue) {
ToastUtils.pushRestartNeeded(); ToastUtils.pushRestartNeeded();
@ -46,11 +46,6 @@ async function toggleStartInTray() {
} }
} }
const settingsMenuBar = 'hide-menu-bar';
const settingsSpellCheck = 'spell-check';
const settingsLinkPreview = 'link-preview-setting';
const settingsStartInTray = 'start-in-tray-setting';
export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null }) => { export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const forceUpdate = useUpdate(); const forceUpdate = useUpdate();
@ -58,17 +53,17 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null
if (props.hasPassword !== null) { if (props.hasPassword !== null) {
const isHideMenuBarActive = const isHideMenuBarActive =
window.getSettingValue(settingsMenuBar) === undefined window.getSettingValue(SettingsKey.settingsMenuBar) === undefined
? true ? true
: window.getSettingValue(settingsMenuBar); : window.getSettingValue(SettingsKey.settingsMenuBar);
const isSpellCheckActive = const isSpellCheckActive =
window.getSettingValue(settingsSpellCheck) === undefined window.getSettingValue(SettingsKey.settingsSpellCheck) === undefined
? true ? true
: window.getSettingValue(settingsSpellCheck); : window.getSettingValue(SettingsKey.settingsSpellCheck);
const isLinkPreviewsOn = Boolean(window.getSettingValue(settingsLinkPreview)); const isLinkPreviewsOn = Boolean(window.getSettingValue(SettingsKey.settingsLinkPreview));
const isStartInTrayActive = Boolean(window.getSettingValue(settingsStartInTray)); const isStartInTrayActive = Boolean(window.getSettingValue(SettingsKey.settingsStartInTray));
return ( return (
<> <>
@ -120,7 +115,7 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null
description={window.i18n('audioMessageAutoplayDescription')} description={window.i18n('audioMessageAutoplayDescription')}
active={audioAutoPlay} active={audioAutoPlay}
/> />
<PruningSessionSlider />
<ZoomingSessionSlider /> <ZoomingSessionSlider />
<SessionSettingButtonItem <SessionSettingButtonItem
title={window.i18n('surveyTitle')} title={window.i18n('surveyTitle')}

@ -3,7 +3,7 @@ import { useDispatch, useSelector } from 'react-redux';
// tslint:disable-next-line: no-submodule-imports // tslint:disable-next-line: no-submodule-imports
import useUpdate from 'react-use/lib/useUpdate'; import useUpdate from 'react-use/lib/useUpdate';
import { SettingsKey } from '../../../data/settings-key'; import { SettingsKey } from '../../../data/settings-key';
import { CallManager } from '../../../session/utils'; import { CallManager, ToastUtils } from '../../../session/utils';
import { sessionPassword, updateConfirmModal } from '../../../state/ducks/modalDialog'; import { sessionPassword, updateConfirmModal } from '../../../state/ducks/modalDialog';
import { toggleMessageRequests } from '../../../state/ducks/userConfig'; import { toggleMessageRequests } from '../../../state/ducks/userConfig';
import { getHideMessageRequestBanner } from '../../../state/selectors/userConfig'; import { getHideMessageRequestBanner } from '../../../state/selectors/userConfig';
@ -50,13 +50,28 @@ function displayPasswordModal(
); );
} }
async function toggleOpengroupPruning() {
try {
const newValue = !(await window.getOpengroupPruning());
// make sure to write it here too, as this is the value used on the UI to mark the toggle as true/false
window.setSettingValue(SettingsKey.settingsOpengroupPruning, newValue);
await window.setOpengroupPruning(newValue);
ToastUtils.pushRestartNeeded();
} catch (e) {
window.log.warn('toggleOpengroupPruning change error:', e);
}
}
export const SettingsCategoryPrivacy = (props: { export const SettingsCategoryPrivacy = (props: {
hasPassword: boolean | null; hasPassword: boolean | null;
onPasswordUpdated: (action: string) => void; onPasswordUpdated: (action: string) => void;
}) => { }) => {
const forceUpdate = useUpdate(); const forceUpdate = useUpdate();
const dispatch = useDispatch(); const dispatch = useDispatch();
const isOpengroupPruningEnabled = Boolean(
window.getSettingValue(SettingsKey.settingsOpengroupPruning)
);
if (props.hasPassword !== null) { if (props.hasPassword !== null) {
return ( return (
<> <>
@ -117,6 +132,15 @@ export const SettingsCategoryPrivacy = (props: {
description={window.i18n('hideRequestBannerDescription')} description={window.i18n('hideRequestBannerDescription')}
active={useSelector(getHideMessageRequestBanner)} active={useSelector(getHideMessageRequestBanner)}
/> />
<SessionToggleWithDescription
onClickToggle={async () => {
await toggleOpengroupPruning();
forceUpdate();
}}
title={window.i18n('pruneSettingTitle')}
description={window.i18n('pruneSettingDescription')}
active={isOpengroupPruningEnabled}
/>
{!props.hasPassword && ( {!props.hasPassword && (
<SessionSettingButtonItem <SessionSettingButtonItem
title={window.i18n('setAccountPasswordTitle')} title={window.i18n('setAccountPasswordTitle')}

@ -2,4 +2,19 @@ const settingsReadReceipt = 'read-receipt-setting';
const settingsTypingIndicator = 'typing-indicators-setting'; const settingsTypingIndicator = 'typing-indicators-setting';
const settingsAutoUpdate = 'auto-update'; const settingsAutoUpdate = 'auto-update';
export const SettingsKey = { settingsReadReceipt, settingsTypingIndicator, settingsAutoUpdate }; const settingsMenuBar = 'hide-menu-bar';
const settingsSpellCheck = 'spell-check';
const settingsLinkPreview = 'link-preview-setting';
const settingsStartInTray = 'start-in-tray-setting';
const settingsOpengroupPruning = 'prune-setting';
export const SettingsKey = {
settingsReadReceipt,
settingsTypingIndicator,
settingsAutoUpdate,
settingsMenuBar,
settingsSpellCheck,
settingsLinkPreview,
settingsStartInTray,
settingsOpengroupPruning,
};

@ -98,16 +98,6 @@ async function getSpellCheckSetting() {
return json.value; return json.value;
} }
async function getPruneSetting() {
const json = sqlNode.getItemById('prune-setting');
// Default to `6` if setting doesn't exist yet
if (!json) {
return 6;
}
return json.value;
}
function showWindow() { function showWindow() {
if (!mainWindow) { if (!mainWindow) {
return; return;
@ -760,11 +750,10 @@ async function showMainWindow(sqlKey: string, passwordAttempt = false) {
messages: locale.messages, messages: locale.messages,
passwordAttempt, passwordAttempt,
}); });
const pruneSetting = await getPruneSetting();
appStartInitialSpellcheckSetting = await getSpellCheckSetting(); appStartInitialSpellcheckSetting = await getSpellCheckSetting();
sqlChannels.initializeSqlChannel(); sqlChannels.initializeSqlChannel();
sqlNode.cleanUpOldOpengroups(pruneSetting); sqlNode.cleanUpOldOpengroups();
await initAttachmentsChannel({ await initAttachmentsChannel({
userDataPath, userDataPath,
@ -939,6 +928,7 @@ ipc.on('password-window-login', async (event, passPhrase) => {
sendResponse(localisedError || 'Invalid password'); sendResponse(localisedError || 'Invalid password');
} }
}); });
ipc.on('start-in-tray-on-start', (event, newValue) => { ipc.on('start-in-tray-on-start', (event, newValue) => {
try { try {
userConfig.set('startInTray', newValue); userConfig.set('startInTray', newValue);
@ -967,6 +957,24 @@ ipc.on('get-start-in-tray', event => {
} }
}); });
ipc.on('get-opengroup-pruning', event => {
try {
const val = userConfig.get('opengroupPruning');
event.sender.send('get-opengroup-pruning-response', val);
} catch (e) {
event.sender.send('get-opengroup-pruning-response', false);
}
});
ipc.on('set-opengroup-pruning', (event, newValue) => {
try {
userConfig.set('opengroupPruning', newValue);
event.sender.send('set-opengroup-pruning-response', null);
} catch (e) {
event.sender.send('set-opengroup-pruning-response', e);
}
});
ipc.on('set-password', async (event, passPhrase, oldPhrase) => { ipc.on('set-password', async (event, passPhrase, oldPhrase) => {
const sendResponse = (response: string | undefined) => { const sendResponse = (response: string | undefined) => {
event.sender.send('set-password-response', response); event.sender.send('set-password-response', response);

@ -1550,6 +1550,8 @@ async function initializeSql({
console.info('total message count before cleaning: ', getMessageCount()); console.info('total message count before cleaning: ', getMessageCount());
console.info('total conversation count before cleaning: ', getConversationCount()); console.info('total conversation count before cleaning: ', getConversationCount());
cleanUpOldOpengroups();
cleanUpUnusedNodeForKeyEntries(); cleanUpUnusedNodeForKeyEntries();
printDbStats(); printDbStats();
@ -3404,17 +3406,32 @@ function cleanUpMessagesJson() {
console.info(`cleanUpMessagesJson took ${Date.now() - start}ms`); console.info(`cleanUpMessagesJson took ${Date.now() - start}ms`);
} }
function cleanUpOldOpengroups(pruneSetting: number) { function cleanUpOldOpengroups() {
const ourNumber = getItemById('number_id'); const ourNumber = getItemById('number_id');
if (!ourNumber || !ourNumber.value) { if (!ourNumber || !ourNumber.value) {
console.info('cleanUpOldOpengroups: ourNumber is not set'); console.info('cleanUpOldOpengroups: ourNumber is not set');
return; return;
} }
const pruneSetting = getItemById('prune-setting')?.value;
if (pruneSetting === undefined) {
console.info(
'Prune settings is undefined, skipping cleanUpOldOpengroups but we will need to ask user'
);
return;
}
if (!pruneSetting) {
console.info('Prune setting not enabled, skipping cleanUpOldOpengroups');
return;
}
const v2Convos = getAllOpenGroupV2Conversations(); const v2Convos = getAllOpenGroupV2Conversations();
if (!v2Convos || !v2Convos.length) { if (!v2Convos || !v2Convos.length) {
console.info('cleanUpOldOpengroups: v2Convos is empty'); console.info('cleanUpOldOpengroups: v2Convos is empty');
return; return;
} }
// For each opengroups, if it has more than 1000 messages, we remove all the messages older than 2 months. // For each opengroups, if it has more than 1000 messages, we remove all the messages older than 2 months.
// So this does not limit the size of opengroup history to 1000 messages but to 2 months. // So this does not limit the size of opengroup history to 1000 messages but to 2 months.
// This is the only way we can cleanup conversations objects from users which just sent messages a while ago and with whom we never interacted. // This is the only way we can cleanup conversations objects from users which just sent messages a while ago and with whom we never interacted.
@ -3428,46 +3445,42 @@ function cleanUpOldOpengroups(pruneSetting: number) {
db.transaction(() => { db.transaction(() => {
dropFtsAndTriggers(db); dropFtsAndTriggers(db);
if (pruneSetting !== 0) { v2Convos.forEach(convo => {
v2Convos.forEach(convo => { const convoId = convo.id;
const convoId = convo.id; const messagesInConvoBefore = getMessagesCountByConversation(convoId);
const messagesInConvoBefore = getMessagesCountByConversation(convoId);
if (messagesInConvoBefore >= maxMessagePerOpengroupConvo) {
if (messagesInConvoBefore >= maxMessagePerOpengroupConvo) { const minute = 1000 * 60;
const minute = 1000 * 60; const sixMonths = minute * 60 * 24 * 30 * 6;
const userDefinedMonths = minute * 60 * 24 * 30 * pruneSetting; const limitTimestamp = Date.now() - sixMonths;
const messagesTimestampToRemove = Date.now() - userDefinedMonths; const countToRemove = assertGlobalInstance()
const countToRemove = assertGlobalInstance() .prepare(
.prepare( `SELECT count(*) from ${MESSAGES_TABLE} WHERE serverTimestamp <= $serverTimestamp AND conversationId = $conversationId;`
`SELECT count(*) from ${MESSAGES_TABLE} WHERE serverTimestamp <= $serverTimestamp AND conversationId = $conversationId;` )
) .get({ conversationId: convoId, serverTimestamp: limitTimestamp })['count(*)'];
.get({ conversationId: convoId, serverTimestamp: Date.now() - userDefinedMonths })['count(*)']; const start = Date.now();
const start = Date.now();
assertGlobalInstance()
assertGlobalInstance() .prepare(
.prepare( `
`
DELETE FROM ${MESSAGES_TABLE} WHERE serverTimestamp <= $serverTimestamp AND conversationId = $conversationId` DELETE FROM ${MESSAGES_TABLE} WHERE serverTimestamp <= $serverTimestamp AND conversationId = $conversationId`
) )
.run({ conversationId: convoId, serverTimestamp: messagesTimestampToRemove }); // delete messages older than the user-specified age. .run({ conversationId: convoId, serverTimestamp: limitTimestamp }); // delete messages older than 6 months ago.
const messagesInConvoAfter = getMessagesCountByConversation(convoId); const messagesInConvoAfter = getMessagesCountByConversation(convoId);
console.info( console.info(
`Cleaning ${countToRemove} messages older than ${pruneSetting} months in public convo: ${convoId} took ${Date.now() - `Cleaning ${countToRemove} messages older than 6 months in public convo: ${convoId} took ${Date.now() -
start}ms. Old message count: ${messagesInConvoBefore}, new message count: ${messagesInConvoAfter}` start}ms. Old message count: ${messagesInConvoBefore}, new message count: ${messagesInConvoAfter}`
); );
const unreadCount = getUnreadCountByConversation(convoId); const unreadCount = getUnreadCountByConversation(convoId);
const convoProps = getConversationById(convoId); const convoProps = getConversationById(convoId);
if (convoProps) { if (convoProps) {
convoProps.unreadCount = unreadCount; convoProps.unreadCount = unreadCount;
updateConversation(convoProps); 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 // 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. // those are the conversation of the old members in the opengroups we just cleaned.

@ -7,6 +7,7 @@ export type LocalizerKeys =
| 'startedACall' | 'startedACall'
| 'mainMenuWindow' | 'mainMenuWindow'
| 'unblocked' | 'unblocked'
| 'keepDisabled'
| 'userAddedToModerators' | 'userAddedToModerators'
| 'to' | 'to'
| 'sent' | 'sent'
@ -14,7 +15,9 @@ export type LocalizerKeys =
| 'closedGroupInviteFailMessage' | 'closedGroupInviteFailMessage'
| 'noContactsForGroup' | 'noContactsForGroup'
| 'linkVisitWarningMessage' | 'linkVisitWarningMessage'
| 'messageRequestAcceptedOurs'
| 'anonymous' | 'anonymous'
| 'youHaveANewFriendRequest'
| 'viewMenuZoomOut' | 'viewMenuZoomOut'
| 'dialogClearAllDataDeletionFailedDesc' | 'dialogClearAllDataDeletionFailedDesc'
| 'timerOption_10_seconds_abbreviated' | 'timerOption_10_seconds_abbreviated'
@ -22,9 +25,11 @@ export type LocalizerKeys =
| 'connectToServerFail' | 'connectToServerFail'
| 'disableNotifications' | 'disableNotifications'
| 'publicChatExists' | 'publicChatExists'
| 'noMediaUntilApproved'
| 'passwordViewTitle' | 'passwordViewTitle'
| 'joinOpenGroupAfterInvitationConfirmationTitle' | 'joinOpenGroupAfterInvitationConfirmationTitle'
| 'notificationMostRecentFrom' | 'notificationMostRecentFrom'
| 'messageRequestAccepted'
| 'timerOption_5_minutes' | 'timerOption_5_minutes'
| 'linkPreviewsConfirmMessage' | 'linkPreviewsConfirmMessage'
| 'notificationMostRecent' | 'notificationMostRecent'
@ -44,7 +49,6 @@ export type LocalizerKeys =
| 'viewMenuToggleDevTools' | 'viewMenuToggleDevTools'
| 'fileSizeWarning' | 'fileSizeWarning'
| 'openGroupURL' | 'openGroupURL'
| 'hideRequestBannerDescription'
| 'hideMenuBarDescription' | 'hideMenuBarDescription'
| 'pickClosedGroupMember' | 'pickClosedGroupMember'
| 'ByUsingThisService...' | 'ByUsingThisService...'
@ -54,6 +58,7 @@ export type LocalizerKeys =
| 'typingAlt' | 'typingAlt'
| 'orJoinOneOfThese' | 'orJoinOneOfThese'
| 'members' | 'members'
| 'noMessageRequestsPending'
| 'sendRecoveryPhraseMessage' | 'sendRecoveryPhraseMessage'
| 'timerOption_1_hour' | 'timerOption_1_hour'
| 'youGotKickedFromGroup' | 'youGotKickedFromGroup'
@ -68,8 +73,10 @@ export type LocalizerKeys =
| 'addModerators' | 'addModerators'
| 'sessionMessenger' | 'sessionMessenger'
| 'today' | 'today'
| 'mustBeApproved'
| 'appMenuHideOthers' | 'appMenuHideOthers'
| 'sendFailed' | 'sendFailed'
| 'openMessageRequestInbox'
| 'enterPassword' | 'enterPassword'
| 'enterSessionIDOfRecipient' | 'enterSessionIDOfRecipient'
| 'dialogClearAllDataDeletionFailedMultiple' | 'dialogClearAllDataDeletionFailedMultiple'
@ -81,6 +88,7 @@ export type LocalizerKeys =
| 'requestsSubtitle' | 'requestsSubtitle'
| 'closedGroupInviteSuccessTitle' | 'closedGroupInviteSuccessTitle'
| 'accept' | 'accept'
| 'hideBanner'
| 'setPasswordTitle' | 'setPasswordTitle'
| 'editMenuUndo' | 'editMenuUndo'
| 'pinConversation' | 'pinConversation'
@ -94,6 +102,7 @@ export type LocalizerKeys =
| 'autoUpdateNewVersionInstructions' | 'autoUpdateNewVersionInstructions'
| 'appMenuUnhide' | 'appMenuUnhide'
| 'timerOption_30_minutes_abbreviated' | 'timerOption_30_minutes_abbreviated'
| 'pruneSettingDescription'
| 'voiceMessage' | 'voiceMessage'
| 'changePasswordTitle' | 'changePasswordTitle'
| 'copyMessage' | 'copyMessage'
@ -101,12 +110,11 @@ export type LocalizerKeys =
| 'deleteJustForMe' | 'deleteJustForMe'
| 'changeAccountPasswordTitle' | 'changeAccountPasswordTitle'
| 'onionPathIndicatorDescription' | 'onionPathIndicatorDescription'
| 'timestamp_s' | 'pruningOpengroupDialogSubMessage'
| 'mediaPermissionsTitle' | 'mediaPermissionsTitle'
| 'replyingToMessage' | 'replyingToMessage'
| 'welcomeToYourSession' | 'welcomeToYourSession'
| 'editMenuCopy' | 'editMenuCopy'
| 'timestamp_m'
| 'leftTheGroup' | 'leftTheGroup'
| 'timerOption_30_minutes' | 'timerOption_30_minutes'
| 'nameOnly' | 'nameOnly'
@ -116,6 +124,7 @@ export type LocalizerKeys =
| 'inviteContacts' | 'inviteContacts'
| 'callMediaPermissionsTitle' | 'callMediaPermissionsTitle'
| 'blocked' | 'blocked'
| 'hideRequestBannerDescription'
| 'noBlockedContacts' | 'noBlockedContacts'
| 'leaveGroupConfirmation' | 'leaveGroupConfirmation'
| 'banUserAndDeleteAll' | 'banUserAndDeleteAll'
@ -162,10 +171,6 @@ export type LocalizerKeys =
| 'copySessionID' | 'copySessionID'
| 'timerOption_0_seconds' | 'timerOption_0_seconds'
| 'zoomFactorSettingTitle' | 'zoomFactorSettingTitle'
| 'pruneSettingTitle'
| 'pruneSettingDescription'
| 'pruneSettingUnit'
| 'pruneSettingUnits'
| 'unableToCall' | 'unableToCall'
| 'callMissedTitle' | 'callMissedTitle'
| 'done' | 'done'
@ -201,6 +206,7 @@ export type LocalizerKeys =
| 'viewMenuResetZoom' | 'viewMenuResetZoom'
| 'startInTrayDescription' | 'startInTrayDescription'
| 'groupNamePlaceholder' | 'groupNamePlaceholder'
| 'messageRequestPending'
| 'stagedPreviewThumbnail' | 'stagedPreviewThumbnail'
| 'helpUsTranslateSession' | 'helpUsTranslateSession'
| 'editMenuDeleteGroup' | 'editMenuDeleteGroup'
@ -212,6 +218,7 @@ export type LocalizerKeys =
| 'closedGroupInviteFailMessagePlural' | 'closedGroupInviteFailMessagePlural'
| 'noAudioInputFound' | 'noAudioInputFound'
| 'timerOption_10_seconds' | 'timerOption_10_seconds'
| 'openMessageRequestInboxDescription'
| 'noteToSelf' | 'noteToSelf'
| 'failedToAddAsModerator' | 'failedToAddAsModerator'
| 'disabledDisappearingMessages' | 'disabledDisappearingMessages'
@ -223,7 +230,6 @@ export type LocalizerKeys =
| 'displayName' | 'displayName'
| 'invalidSessionId' | 'invalidSessionId'
| 'audioPermissionNeeded' | 'audioPermissionNeeded'
| 'timestamp_h'
| 'add' | 'add'
| 'messageRequests' | 'messageRequests'
| 'show' | 'show'
@ -232,6 +238,7 @@ export type LocalizerKeys =
| 'goToSupportPage' | 'goToSupportPage'
| 'passwordsDoNotMatch' | 'passwordsDoNotMatch'
| 'createClosedGroupNamePrompt' | 'createClosedGroupNamePrompt'
| 'pruningOpengroupDialogMessage'
| 'audioMessageAutoplayDescription' | 'audioMessageAutoplayDescription'
| 'leaveAndRemoveForEveryone' | 'leaveAndRemoveForEveryone'
| 'previewThumbnail' | 'previewThumbnail'
@ -240,9 +247,9 @@ export type LocalizerKeys =
| 'editMenuDeleteContact' | 'editMenuDeleteContact'
| 'hideMenuBarTitle' | 'hideMenuBarTitle'
| 'imageCaptionIconAlt' | 'imageCaptionIconAlt'
| 'clearAll'
| 'sendRecoveryPhraseTitle' | 'sendRecoveryPhraseTitle'
| 'multipleJoinedTheGroup' | 'multipleJoinedTheGroup'
| 'messageRequestAcceptedOursNoName'
| 'databaseError' | 'databaseError'
| 'resend' | 'resend'
| 'copiedToClipboard' | 'copiedToClipboard'
@ -252,6 +259,7 @@ export type LocalizerKeys =
| 'unableToLoadAttachment' | 'unableToLoadAttachment'
| 'cameraPermissionNeededTitle' | 'cameraPermissionNeededTitle'
| 'editMenuRedo' | 'editMenuRedo'
| 'hideRequestBanner'
| 'changeNicknameMessage' | 'changeNicknameMessage'
| 'close' | 'close'
| 'deleteMessageQuestion' | 'deleteMessageQuestion'
@ -262,6 +270,7 @@ export type LocalizerKeys =
| 'getStarted' | 'getStarted'
| 'unblockUser' | 'unblockUser'
| 'blockUser' | 'blockUser'
| 'clearAllConfirmationTitle'
| 'trustThisContactDialogTitle' | 'trustThisContactDialogTitle'
| 'received' | 'received'
| 'trimDatabaseConfirmationBody' | 'trimDatabaseConfirmationBody'
@ -280,6 +289,7 @@ export type LocalizerKeys =
| 'timerOption_6_hours_abbreviated' | 'timerOption_6_hours_abbreviated'
| 'timerOption_1_week_abbreviated' | 'timerOption_1_week_abbreviated'
| 'timerSetTo' | 'timerSetTo'
| 'enable'
| 'notificationSubtitle' | 'notificationSubtitle'
| 'youChangedTheTimer' | 'youChangedTheTimer'
| 'updatedTheGroup' | 'updatedTheGroup'
@ -292,8 +302,10 @@ export type LocalizerKeys =
| 'noSearchResults' | 'noSearchResults'
| 'changeNickname' | 'changeNickname'
| 'userUnbanned' | 'userUnbanned'
| 'respondingToRequestWarning'
| 'error' | 'error'
| 'clearAllData' | 'clearAllData'
| 'pruningOpengroupDialogTitle'
| 'contactAvatarAlt' | 'contactAvatarAlt'
| 'disappearingMessages' | 'disappearingMessages'
| 'autoUpdateNewVersionTitle' | 'autoUpdateNewVersionTitle'
@ -332,6 +344,7 @@ export type LocalizerKeys =
| 'markAllAsRead' | 'markAllAsRead'
| 'failedResolveOns' | 'failedResolveOns'
| 'showDebugLog' | 'showDebugLog'
| 'declineRequestMessage'
| 'autoUpdateDownloadButtonLabel' | 'autoUpdateDownloadButtonLabel'
| 'dialogClearAllDataDeletionFailedTitleQuestion' | 'dialogClearAllDataDeletionFailedTitleQuestion'
| 'autoUpdateDownloadInstructions' | 'autoUpdateDownloadInstructions'
@ -357,6 +370,7 @@ export type LocalizerKeys =
| 'learnMore' | 'learnMore'
| 'passwordCharacterError' | 'passwordCharacterError'
| 'autoUpdateSettingTitle' | 'autoUpdateSettingTitle'
| 'documentsEmptyState'
| 'deleteForEveryone' | 'deleteForEveryone'
| 'createSessionID' | 'createSessionID'
| 'multipleLeftTheGroup' | 'multipleLeftTheGroup'
@ -380,9 +394,11 @@ export type LocalizerKeys =
| 'callMediaPermissionsDialogContent' | 'callMediaPermissionsDialogContent'
| 'timerOption_1_day_abbreviated' | 'timerOption_1_day_abbreviated'
| 'about' | 'about'
| 'clearAllConfirmationBody'
| 'ok' | 'ok'
| 'multipleKickedFromTheGroup' | 'multipleKickedFromTheGroup'
| 'trimDatabase' | 'trimDatabase'
| 'clearAll'
| 'recoveryPhraseSavePromptMain' | 'recoveryPhraseSavePromptMain'
| 'editMenuPaste' | 'editMenuPaste'
| 'areYouSureDeleteDeviceOnly' | 'areYouSureDeleteDeviceOnly'
@ -425,7 +441,7 @@ export type LocalizerKeys =
| 'recoveryPhrase' | 'recoveryPhrase'
| 'newMessages' | 'newMessages'
| 'you' | 'you'
| 'documentsEmptyState' | 'pruneSettingTitle'
| 'unbanUser' | 'unbanUser'
| 'notificationForConvo_mentions_only' | 'notificationForConvo_mentions_only'
| 'trustThisContactDialogDescription' | 'trustThisContactDialogDescription'
@ -433,22 +449,4 @@ export type LocalizerKeys =
| 'searchFor...' | 'searchFor...'
| 'joinedTheGroup' | 'joinedTheGroup'
| 'editGroupName' | 'editGroupName'
| 'trimDatabase'
| 'trimDatabaseDescription'
| 'trimDatabaseConfirmationBody'
| 'respondingToRequestWarning'
| 'messageRequestPending'
| 'messageRequestAccepted'
| 'messageRequestAcceptedOurs'
| 'messageRequestAcceptedOursNoName'
| 'declineRequestMessage'
| 'openMessageRequestInbox'
| 'hideRequestBanner'
| 'noMessageRequestsPending'
| 'noMediaUntilApproved'
| 'mustBeApproved'
| 'youHaveANewFriendRequest'
| 'clearAllConfirmationTitle'
| 'clearAllConfirmationBody'
| 'hideBanner'
| 'reportIssue'; | 'reportIssue';

@ -164,6 +164,10 @@ async function createAccount(identityKeyPair: any) {
// Enable typing indicators by default // Enable typing indicators by default
await Storage.put(SettingsKey.settingsTypingIndicator, false); await Storage.put(SettingsKey.settingsTypingIndicator, false);
// opengroups pruning in ON by default on new accounts, but you can change that from the settings
await Storage.put(SettingsKey.settingsOpengroupPruning, true);
await window.setOpengroupPruning(true);
await setLocalPubKey(pubKeyString); await setLocalPubKey(pubKeyString);
} }

2
ts/window.d.ts vendored

@ -91,6 +91,8 @@ declare global {
confirmationDialog: any; confirmationDialog: any;
setStartInTray: (val: boolean) => Promise<void>; setStartInTray: (val: boolean) => Promise<void>;
getStartInTray: () => Promise<boolean>; getStartInTray: () => Promise<boolean>;
getOpengroupPruning: () => Promise<boolean>;
setOpengroupPruning: (val: boolean) => Promise<void>;
closeAbout: () => void; closeAbout: () => void;
getAutoUpdateEnabled: () => boolean; getAutoUpdateEnabled: () => boolean;
setAutoUpdateEnabled: (enabled: boolean) => void; setAutoUpdateEnabled: (enabled: boolean) => void;

Loading…
Cancel
Save