mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
fix: memoize selected conversation props to avoid unneeded rerenders
This commit is contained in:
parent
524debb307
commit
dc3e8450e9
|
@ -36,6 +36,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"start-prod": "cross-env NODE_ENV=production NODE_APP_INSTANCE=devprod$MULTI electron .",
|
||||
"start-dev": "cross-env NODE_ENV=development NODE_APP_INSTANCE=devprod$MULTI electron .",
|
||||
"build-everything": "yarn clean && yarn protobuf && yarn update-git-info && yarn sass && tsc && yarn build:workers",
|
||||
"build-everything:watch": "yarn clean && yarn protobuf && yarn update-git-info && yarn sass && yarn build:workers && tsc -w",
|
||||
"build:workers": "yarn worker:utils && yarn worker:libsession",
|
||||
|
|
|
@ -20,14 +20,6 @@ window.getEnvironment = () => config.environment;
|
|||
window.getVersion = () => config.version;
|
||||
window.getAppInstance = () => config.appInstance;
|
||||
|
||||
const { SessionPasswordPrompt } = require('./ts/components/SessionPasswordPrompt');
|
||||
|
||||
window.Signal = {
|
||||
Components: {
|
||||
SessionPasswordPrompt,
|
||||
},
|
||||
};
|
||||
|
||||
window.clearLocalData = async () => {
|
||||
window.log.info('reset database');
|
||||
ipcRenderer.send('resetDatabase');
|
||||
|
|
|
@ -17,12 +17,10 @@ import {
|
|||
import { StateType } from '../../state/reducer';
|
||||
import {
|
||||
getQuotedMessageToAnimate,
|
||||
getSelectedConversation,
|
||||
getSortedMessagesOfSelectedConversation,
|
||||
} from '../../state/selectors/conversations';
|
||||
import {
|
||||
getSelectedConversation,
|
||||
getSelectedConversationKey,
|
||||
} from '../../state/selectors/selectedConversation';
|
||||
import { getSelectedConversationKey } from '../../state/selectors/selectedConversation';
|
||||
import { SessionMessagesList } from './SessionMessagesList';
|
||||
import { TypingBubble } from './TypingBubble';
|
||||
import { ConversationMessageRequestButtons } from './MessageRequestButtons';
|
||||
|
|
|
@ -31,7 +31,11 @@ import { ToastUtils } from '../../../session/utils';
|
|||
import { ReduxConversationType } from '../../../state/ducks/conversations';
|
||||
import { removeAllStagedAttachmentsInConversation } from '../../../state/ducks/stagedAttachments';
|
||||
import { StateType } from '../../../state/reducer';
|
||||
import { getMentionsInput, getQuotedMessage } from '../../../state/selectors/conversations';
|
||||
import {
|
||||
getMentionsInput,
|
||||
getQuotedMessage,
|
||||
getSelectedConversation,
|
||||
} from '../../../state/selectors/conversations';
|
||||
import { AttachmentUtil } from '../../../util';
|
||||
import { Flex } from '../../basic/Flex';
|
||||
import { CaptionEditor } from '../../CaptionEditor';
|
||||
|
@ -53,7 +57,6 @@ import styled from 'styled-components';
|
|||
import { FixedBaseEmoji } from '../../../types/Reaction';
|
||||
import {
|
||||
getSelectedCanWrite,
|
||||
getSelectedConversation,
|
||||
getSelectedConversationKey,
|
||||
} from '../../../state/selectors/selectedConversation';
|
||||
import { SettingsKey } from '../../../data/settings-key';
|
||||
|
|
|
@ -497,35 +497,51 @@ async function getSeenMessagesByHashList(hashes: Array<string>): Promise<any> {
|
|||
}
|
||||
|
||||
async function removeAllMessagesInConversation(conversationId: string): Promise<void> {
|
||||
const startFunction = Date.now();
|
||||
let start = Date.now();
|
||||
const messages = await getLastMessagesByConversation(conversationId, 50, false);
|
||||
window.log.info(
|
||||
`removeAllMessagesInConversation ${conversationId} ${messages.length} took ${Date.now() -
|
||||
start}`
|
||||
);
|
||||
if (!messages.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: It's very important that these models are fully hydrated because
|
||||
// we need to delete all associated on-disk files along with the database delete.
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
let messages;
|
||||
do {
|
||||
// Yes, we really want the await in the loop. We're deleting 500 at a
|
||||
// time so we don't use too much memory.
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
messages = await getLastMessagesByConversation(conversationId, 1000, false);
|
||||
if (!messages.length) {
|
||||
return;
|
||||
}
|
||||
window.log.info(
|
||||
`removeAllMessagesInConversation getLastMessagesByConversation ${conversationId} ${
|
||||
messages.length
|
||||
} took ${Date.now() - start}ms`
|
||||
);
|
||||
|
||||
start = Date.now();
|
||||
for (let index = 0; index < messages.length; index++) {
|
||||
const message = messages.at(index);
|
||||
await message.cleanup();
|
||||
}
|
||||
window.log.info(
|
||||
`removeAllMessagesInConversation messages.cleanup() ${conversationId} took ${Date.now() -
|
||||
start}ms`
|
||||
);
|
||||
start = Date.now();
|
||||
// Note: It's very important that these models are fully hydrated because
|
||||
// we need to delete all associated on-disk files along with the database delete.
|
||||
const ids = messages.map(message => message.id);
|
||||
start = Date.now();
|
||||
for (let index = 0; index < messages.length; index++) {
|
||||
const message = messages.at(index);
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await message.cleanup();
|
||||
}
|
||||
window.log.info(
|
||||
`removeAllMessagesInConversation messages.cleanup() ${conversationId} took ${Date.now() -
|
||||
start}ms`
|
||||
);
|
||||
start = Date.now();
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await channels.removeMessagesByIds(ids);
|
||||
window.log.info(
|
||||
`removeAllMessagesInConversation: removeMessagesByIds ${conversationId} took ${Date.now() -
|
||||
start}ms`
|
||||
);
|
||||
} while (messages.length);
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await channels.removeAllMessagesInConversation(conversationId);
|
||||
window.log.info(
|
||||
`removeAllMessagesInConversation: ${conversationId} took ${Date.now() - start}ms`
|
||||
`removeAllMessagesInConversation: complete time ${conversationId} took ${Date.now() -
|
||||
startFunction}ms`
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -958,7 +958,6 @@ function removeMessagesByIds(ids: Array<string>, instance?: BetterSqlite3.Databa
|
|||
}
|
||||
const start = Date.now();
|
||||
|
||||
// TODO we might need to do the same thing as
|
||||
assertGlobalInstanceOrInstance(instance)
|
||||
.prepare(`DELETE FROM ${MESSAGES_TABLE} WHERE id IN ( ${ids.map(() => '?').join(', ')} );`)
|
||||
.run(ids);
|
||||
|
@ -974,11 +973,9 @@ function removeAllMessagesInConversation(
|
|||
}
|
||||
const inst = assertGlobalInstanceOrInstance(instance);
|
||||
|
||||
inst.transaction(() => {
|
||||
inst
|
||||
.prepare(`DELETE FROM ${MESSAGES_TABLE} WHERE conversationId = $conversationId`)
|
||||
.run({ conversationId });
|
||||
})();
|
||||
inst
|
||||
.prepare(`DELETE FROM ${MESSAGES_TABLE} WHERE conversationId = $conversationId`)
|
||||
.run({ conversationId });
|
||||
}
|
||||
|
||||
function getMessageIdsFromServerIds(serverIds: Array<string | number>, conversationId: string) {
|
||||
|
|
|
@ -31,7 +31,7 @@ import { getIntl } from './user';
|
|||
|
||||
import { filter, isEmpty, isNumber, pick, sortBy } from 'lodash';
|
||||
import { MessageReactsSelectorProps } from '../../components/conversation/message/message-content/MessageReactions';
|
||||
import { getSelectedConversation, getSelectedConversationKey } from './selectedConversation';
|
||||
import { getSelectedConversationKey } from './selectedConversation';
|
||||
import { getModeratorsOutsideRedux } from './sogsRoomInfo';
|
||||
|
||||
export const getConversations = (state: StateType): ConversationsStateType => state.conversations;
|
||||
|
@ -626,6 +626,17 @@ export const isFirstUnreadMessageIdAbove = createSelector(
|
|||
|
||||
const getMessageId = (_whatever: any, id: string | undefined) => id;
|
||||
|
||||
/**
|
||||
* A lot of our UI changes on the main panel need to happen quickly (composition box).
|
||||
*/
|
||||
export const getSelectedConversation = createSelector(
|
||||
getConversationLookup,
|
||||
getSelectedConversationKey,
|
||||
(lookup, selectedConvo) => {
|
||||
return selectedConvo ? lookup[selectedConvo] : undefined;
|
||||
}
|
||||
);
|
||||
|
||||
// tslint:disable: cyclomatic-complexity
|
||||
|
||||
export const getMessagePropsByMessageId = createSelector(
|
||||
|
|
|
@ -3,9 +3,9 @@ import { useSelector } from 'react-redux';
|
|||
import { ConversationTypeEnum, isOpenOrClosedGroup } from '../../models/conversationAttributes';
|
||||
import { PubKey } from '../../session/types';
|
||||
import { UserUtils } from '../../session/utils';
|
||||
import { ReduxConversationType } from '../ducks/conversations';
|
||||
import { StateType } from '../reducer';
|
||||
import { getCanWrite, getModerators, getSubscriberCount } from './sogsRoomInfo';
|
||||
import { getSelectedConversation } from './conversations';
|
||||
|
||||
/**
|
||||
* Returns the formatted text for notification setting.
|
||||
|
@ -58,11 +58,6 @@ export const getSelectedConversationKey = (state: StateType): string | undefined
|
|||
return state.conversations.selectedConversation;
|
||||
};
|
||||
|
||||
export const getSelectedConversation = (state: StateType): ReduxConversationType | undefined => {
|
||||
const selected = getSelectedConversationKey(state);
|
||||
return selected ? state.conversations.conversationLookup[selected] : undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the current conversation selected is a public group and false otherwise.
|
||||
*/
|
||||
|
|
|
@ -6,15 +6,13 @@ import { getHasOngoingCallWithFocusedConvo } from '../selectors/call';
|
|||
import {
|
||||
getIsSelectedConvoInitialLoadingInProgress,
|
||||
getLightBoxOptions,
|
||||
getSelectedConversation,
|
||||
getSelectedMessageIds,
|
||||
getSortedMessagesOfSelectedConversation,
|
||||
isMessageDetailView,
|
||||
isRightPanelShowing,
|
||||
} from '../selectors/conversations';
|
||||
import {
|
||||
getSelectedConversation,
|
||||
getSelectedConversationKey,
|
||||
} from '../selectors/selectedConversation';
|
||||
import { getSelectedConversationKey } from '../selectors/selectedConversation';
|
||||
import { getStagedAttachmentsForCurrentConversation } from '../selectors/stagedAttachments';
|
||||
import { getTheme } from '../selectors/theme';
|
||||
import { getOurNumber } from '../selectors/user';
|
||||
|
|
Loading…
Reference in a new issue