From 18f15615d4baac0624af49d0be0b6692923bc78d Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 20 Jul 2021 17:09:17 +1000 Subject: [PATCH 01/30] don't render messages that are already expired --- ts/components/session/conversation/SessionMessagesList.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ts/components/session/conversation/SessionMessagesList.tsx b/ts/components/session/conversation/SessionMessagesList.tsx index 922a40d31..3d3f460fd 100644 --- a/ts/components/session/conversation/SessionMessagesList.tsx +++ b/ts/components/session/conversation/SessionMessagesList.tsx @@ -318,6 +318,10 @@ export class SessionMessagesList extends React.Component { multiSelectMode: boolean, message: MessageModel ) { + if (messageProps.expirationTimestamp != null && messageProps.expirationTimestamp < Date.now()) { + return; + } + const selected = !!messageProps?.id && this.props.selectedMessages.includes(messageProps.id); messageProps.selected = selected; From e5615357f7cd28c772f4fbf5209e8b103aa519f2 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Thu, 22 Jul 2021 14:58:00 +1000 Subject: [PATCH 02/30] call setToExpire when expire timer is started to set expire_at property of message --- ts/components/session/conversation/SessionMessagesList.tsx | 4 ---- ts/models/message.ts | 5 +++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ts/components/session/conversation/SessionMessagesList.tsx b/ts/components/session/conversation/SessionMessagesList.tsx index 3d3f460fd..922a40d31 100644 --- a/ts/components/session/conversation/SessionMessagesList.tsx +++ b/ts/components/session/conversation/SessionMessagesList.tsx @@ -318,10 +318,6 @@ export class SessionMessagesList extends React.Component { multiSelectMode: boolean, message: MessageModel ) { - if (messageProps.expirationTimestamp != null && messageProps.expirationTimestamp < Date.now()) { - return; - } - const selected = !!messageProps?.id && this.props.selectedMessages.includes(messageProps.id); messageProps.selected = selected; diff --git a/ts/models/message.ts b/ts/models/message.ts index ec58ecf97..c755b8664 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -1058,6 +1058,7 @@ export class MessageModel extends Backbone.Model { if (this.get('expireTimer') && !this.get('expirationStartTimestamp')) { const expirationStartTimestamp = Math.min(Date.now(), readAt || Date.now()); this.set({ expirationStartTimestamp }); + this.setToExpire(false); } window.Whisper.Notifications.remove( @@ -1092,7 +1093,7 @@ export class MessageModel extends Backbone.Model { return msFromNow; } - public async setToExpire(force = false) { + public async setToExpire(commit = true, force = false) { if (this.isExpiring() && (force || !this.get('expires_at'))) { const start = this.get('expirationStartTimestamp'); const delta = this.get('expireTimer') * 1000; @@ -1103,7 +1104,7 @@ export class MessageModel extends Backbone.Model { this.set({ expires_at: expiresAt }); const id = this.get('id'); - if (id) { + if (id && commit) { await this.commit(); } From 6bbabce8e366ab3bf4b2722878cde726ab30bff0 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Thu, 22 Jul 2021 15:21:52 +1000 Subject: [PATCH 03/30] fix async issue --- ts/models/conversation.ts | 2 +- ts/models/message.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 7b879d0a4..10c826805 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -947,7 +947,7 @@ export class ConversationModel extends Backbone.Model { // Build the list of updated message models so we can mark them all as read on a single sqlite call for (const nowRead of oldUnreadNowRead) { - nowRead.markReadNoCommit(options.readAt); + await nowRead.markReadNoCommit(options.readAt); const errors = nowRead.get('errors'); read.push({ diff --git a/ts/models/message.ts b/ts/models/message.ts index c755b8664..f02675f3d 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -1045,20 +1045,20 @@ export class MessageModel extends Backbone.Model { } public async markRead(readAt: number) { - this.markReadNoCommit(readAt); + await this.markReadNoCommit(readAt); this.getConversation()?.markRead(this.attributes.received_at); await this.commit(); } - public markReadNoCommit(readAt: number) { + public async markReadNoCommit(readAt: number) { this.set({ unread: 0 }); if (this.get('expireTimer') && !this.get('expirationStartTimestamp')) { const expirationStartTimestamp = Math.min(Date.now(), readAt || Date.now()); this.set({ expirationStartTimestamp }); - this.setToExpire(false); + await this.setToExpire(false); } window.Whisper.Notifications.remove( From beca14982c99e40982fbf5c5cf00e8bc2447e89c Mon Sep 17 00:00:00 2001 From: Brice-W Date: Mon, 26 Jul 2021 10:43:12 +1000 Subject: [PATCH 04/30] manage expired nessage deletion in setExpired --- ts/components/conversation/Message.tsx | 16 +++++++++++++--- ts/data/data.ts | 17 ++++++++++++++--- ts/models/conversation.ts | 3 ++- ts/models/message.ts | 10 ++++++---- ts/models/messageType.ts | 7 +++++++ 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index dda2867bc..ffdd51a5d 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -28,16 +28,17 @@ import { isFileDangerous } from '../../util/isFileDangerous'; import _ from 'lodash'; import { animation, contextMenu, Item, Menu } from 'react-contexify'; import uuid from 'uuid'; -import { InView } from 'react-intersection-observer'; import { withTheme } from 'styled-components'; import { MessageMetadata } from './message/MessageMetadata'; import { PubKey } from '../../session/types'; +import { getConversationController } from '../../session/conversations'; import { MessageRegularProps } from '../../models/messageType'; import { addSenderAsModerator, removeSenderFromModerator, } from '../../interactions/messageInteractions'; import { updateUserDetailsModal } from '../../state/ducks/modalDialog'; +import { actions as conversationActions } from '../../state/ducks/conversations'; import { MessageInteraction } from '../../interactions'; import autoBind from 'auto-bind'; import { AudioPlayerWithEncryptedFile } from './H5AudioPlayer'; @@ -104,7 +105,7 @@ class MessageInner extends React.PureComponent { public checkExpired() { const now = Date.now(); - const { isExpired, expirationTimestamp, expirationLength } = this.props; + const { isExpired, expirationTimestamp, expirationLength, convoId, id } = this.props; if (!expirationTimestamp || !expirationLength) { return; @@ -118,10 +119,19 @@ class MessageInner extends React.PureComponent { expiring: true, }); - const setExpired = () => { + const setExpired = async () => { this.setState({ expired: true, }); + await window.Signal.Data.removeMessage(id); + window.inboxStore?.dispatch( + conversationActions.messageExpired({ + conversationKey: convoId, + messageId: id, + }) + ); + const convo = getConversationController().get(convoId); + convo.updateLastMessage(); }; this.expiredTimeout = setTimeout(setExpired, EXPIRED_DELAY); } diff --git a/ts/data/data.ts b/ts/data/data.ts index 77ca3175a..3bffa8818 100644 --- a/ts/data/data.ts +++ b/ts/data/data.ts @@ -637,7 +637,7 @@ export async function saveMessages(arrayOfMessages: Array): P } export async function removeMessage(id: string): Promise { - const message = await getMessageById(id); + const message = await getMessageById(id, true); // Note: It's important to have a fully database-hydrated model to delete here because // it needs to delete all associated on-disk files along with the database delete. @@ -659,11 +659,17 @@ export async function getMessageIdsFromServerIds( return channels.getMessageIdsFromServerIds(serverIds, conversationId); } -export async function getMessageById(id: string): Promise { +export async function getMessageById( + id: string, + skipTimerInit: boolean = false +): Promise { const message = await channels.getMessageById(id); if (!message) { return null; } + if (skipTimerInit) { + message.skipTimerInit = skipTimerInit; + } return new MessageModel(message); } @@ -748,13 +754,18 @@ export async function getUnreadCountByConversation(conversationId: string): Prom export async function getMessagesByConversation( conversationId: string, - { limit = 100, receivedAt = Number.MAX_VALUE, type = '%' } + { limit = 100, receivedAt = Number.MAX_VALUE, type = '%', skipTimerInit = false } ): Promise { const messages = await channels.getMessagesByConversation(conversationId, { limit, receivedAt, type, }); + if (skipTimerInit) { + for (const message of messages) { + message.skipTimerInit = skipTimerInit; + } + } return new MessageCollection(messages); } diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 10c826805..363b104d3 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -758,6 +758,7 @@ export class ConversationModel extends Backbone.Model { } const messages = await getMessagesByConversation(this.id, { limit: 1, + skipTimerInit: true, }); const lastMessageModel = messages.at(0); const lastMessageJSON = lastMessageModel ? lastMessageModel.toJSON() : null; @@ -947,7 +948,7 @@ export class ConversationModel extends Backbone.Model { // Build the list of updated message models so we can mark them all as read on a single sqlite call for (const nowRead of oldUnreadNowRead) { - await nowRead.markReadNoCommit(options.readAt); + nowRead.markReadNoCommit(options.readAt); const errors = nowRead.get('errors'); read.push({ diff --git a/ts/models/message.ts b/ts/models/message.ts index f02675f3d..41811e1d8 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -63,7 +63,9 @@ export class MessageModel extends Backbone.Model { } // this.on('expired', this.onExpired); - void this.setToExpire(); + if (!filledAttrs.skipTimerInit) { + void this.setToExpire(); + } autoBind(this); window.contextMenuShown = false; @@ -1045,20 +1047,20 @@ export class MessageModel extends Backbone.Model { } public async markRead(readAt: number) { - await this.markReadNoCommit(readAt); + this.markReadNoCommit(readAt); this.getConversation()?.markRead(this.attributes.received_at); await this.commit(); } - public async markReadNoCommit(readAt: number) { + public markReadNoCommit(readAt: number) { this.set({ unread: 0 }); if (this.get('expireTimer') && !this.get('expirationStartTimestamp')) { const expirationStartTimestamp = Math.min(Date.now(), readAt || Date.now()); this.set({ expirationStartTimestamp }); - await this.setToExpire(false); + //await this.setToExpire(false); } window.Whisper.Notifications.remove( diff --git a/ts/models/messageType.ts b/ts/models/messageType.ts index cf945bfaa..fbf1b6e41 100644 --- a/ts/models/messageType.ts +++ b/ts/models/messageType.ts @@ -101,6 +101,12 @@ export interface MessageAttributes { * We display a small message just below the message referenced */ dataExtractionNotification?: DataExtractionNotificationMsg; + + /** + * This is used to choose whether to initialize the timer or not in the MessageModel object. + * If false or undefined, timer will be in itialized. + */ + skipTimerInit?: boolean; } export interface DataExtractionNotificationMsg { @@ -165,6 +171,7 @@ export interface MessageAttributesOptionals { sync?: boolean; snippet?: any; direction?: any; + skipTimerInit?: boolean; } /** From 72868c10e5ab4b7a15727667906fb32210115d9e Mon Sep 17 00:00:00 2001 From: Brice-W Date: Mon, 26 Jul 2021 10:47:10 +1000 Subject: [PATCH 05/30] clean --- ts/models/message.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ts/models/message.ts b/ts/models/message.ts index 41811e1d8..493a62bae 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -1060,7 +1060,6 @@ export class MessageModel extends Backbone.Model { if (this.get('expireTimer') && !this.get('expirationStartTimestamp')) { const expirationStartTimestamp = Math.min(Date.now(), readAt || Date.now()); this.set({ expirationStartTimestamp }); - //await this.setToExpire(false); } window.Whisper.Notifications.remove( From d7eafb7e152e107a52ae2713af2a9eedbaf5dba6 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Mon, 26 Jul 2021 10:49:35 +1000 Subject: [PATCH 06/30] rollback changes --- ts/models/message.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/models/message.ts b/ts/models/message.ts index 493a62bae..893cd42cb 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -1094,7 +1094,7 @@ export class MessageModel extends Backbone.Model { return msFromNow; } - public async setToExpire(commit = true, force = false) { + public async setToExpire(force = false) { if (this.isExpiring() && (force || !this.get('expires_at'))) { const start = this.get('expirationStartTimestamp'); const delta = this.get('expireTimer') * 1000; @@ -1105,7 +1105,7 @@ export class MessageModel extends Backbone.Model { this.set({ expires_at: expiresAt }); const id = this.get('id'); - if (id && commit) { + if (id) { await this.commit(); } From 751d0b9348365680752faeefbe46ba84d7fdf391 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Mon, 26 Jul 2021 11:12:42 +1000 Subject: [PATCH 07/30] clearTimout call added to checkExpired to avoid multiple calls to setExpired --- ts/components/conversation/Message.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index ffdd51a5d..f6b606939 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -133,6 +133,9 @@ class MessageInner extends React.PureComponent { const convo = getConversationController().get(convoId); convo.updateLastMessage(); }; + // as 'checkExpired' is potentially called more than once (componentDidUpdate & componentDidMount), + // we need to clear the timeout call to 'setExpired' first to avoid multiple calls to 'setExpired'. + clearTimeout(this.expiredTimeout); this.expiredTimeout = setTimeout(setExpired, EXPIRED_DELAY); } } From dbf6a0183f2c63e9b5bb776ce4d4d68e697fa355 Mon Sep 17 00:00:00 2001 From: audric Date: Mon, 26 Jul 2021 11:30:53 +1000 Subject: [PATCH 08/30] remove unread top banner on scroll to bottom --- .../conversation/SessionMessagesListContainer.tsx | 9 +++++++-- ts/state/ducks/conversations.ts | 12 ++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ts/components/session/conversation/SessionMessagesListContainer.tsx b/ts/components/session/conversation/SessionMessagesListContainer.tsx index c7514d497..81adf29d3 100644 --- a/ts/components/session/conversation/SessionMessagesListContainer.tsx +++ b/ts/components/session/conversation/SessionMessagesListContainer.tsx @@ -6,6 +6,7 @@ import _ from 'lodash'; import { contextMenu } from 'react-contexify'; import { fetchMessagesForConversation, + markConversationFullyRead, quotedMessageToAnimate, ReduxConversationType, setNextMessageToPlay, @@ -173,7 +174,9 @@ class SessionMessagesListContainerInner extends React.Component { } if ((forceIsOnBottom || this.getScrollOffsetBottomPx() === 0) && isElectronWindowFocused()) { - void conversation.markRead(messagesProps[0].propsForMessage.receivedAt || 0); + void conversation.markRead(messagesProps[0].propsForMessage.receivedAt || 0).then(() => { + window.inboxStore?.dispatch(markConversationFullyRead(conversationKey)); + }); } } @@ -369,7 +372,9 @@ class SessionMessagesListContainerInner extends React.Component { const conversation = getConversationController().get(conversationKey); if (isElectronWindowFocused()) { - void conversation.markRead(messagesProps[0].propsForMessage.receivedAt || 0); + void conversation.markRead(messagesProps[0].propsForMessage.receivedAt || 0).then(() => { + window.inboxStore?.dispatch(markConversationFullyRead(conversationKey)); + }); } } diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index af5c3d219..0940c65b2 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -601,6 +601,17 @@ const conversationsSlice = createSlice({ return handleConversationReset(state, action); }, + markConversationFullyRead(state: ConversationsStateType, action: PayloadAction) { + if (state.selectedConversation !== action.payload) { + return state; + } + + return { + ...state, + firstUnreadMessageId: undefined, + }; + }, + openConversationExternal( state: ConversationsStateType, action: PayloadAction<{ @@ -711,6 +722,7 @@ export const { messageChanged, messagesChanged, openConversationExternal, + markConversationFullyRead, // layout stuff showMessageDetailsView, closeMessageDetailsView, From 54a2eef700df6d27e753507a6b49639d2c750c16 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Mon, 26 Jul 2021 15:11:20 +1000 Subject: [PATCH 09/30] change the way skipTimerInit is defined in MessageModel --- ts/interactions/conversationInteractions.ts | 2 +- ts/models/message.ts | 4 ++-- ts/models/messageType.ts | 7 ------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/ts/interactions/conversationInteractions.ts b/ts/interactions/conversationInteractions.ts index e9082230d..5b08d275f 100644 --- a/ts/interactions/conversationInteractions.ts +++ b/ts/interactions/conversationInteractions.ts @@ -439,7 +439,7 @@ export async function deleteMessagesById( askUserForConfirmation: boolean ) { const conversationModel = getConversationController().getOrThrow(conversationId); - const selectedMessages = _.compact(await Promise.all(messageIds.map(getMessageById))); + const selectedMessages = _.compact(await Promise.all(messageIds.map(m => getMessageById(m)))); const moreThanOne = selectedMessages.length > 1; diff --git a/ts/models/message.ts b/ts/models/message.ts index 4e0d11964..405fc0180 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -57,7 +57,7 @@ import { perfEnd, perfStart } from '../session/utils/Performance'; import { AttachmentTypeWithPath } from '../types/Attachment'; export class MessageModel extends Backbone.Model { - constructor(attributes: MessageAttributesOptionals) { + constructor(attributes: MessageAttributesOptionals & { skipTimerInit?: boolean }) { const filledAttrs = fillMessageAttributesWithDefaults(attributes); super(filledAttrs); @@ -76,7 +76,7 @@ export class MessageModel extends Backbone.Model { } // this.on('expired', this.onExpired); - if (!filledAttrs.skipTimerInit) { + if (!attributes.skipTimerInit) { void this.setToExpire(); } autoBind(this); diff --git a/ts/models/messageType.ts b/ts/models/messageType.ts index cfa14270e..353215118 100644 --- a/ts/models/messageType.ts +++ b/ts/models/messageType.ts @@ -102,12 +102,6 @@ export interface MessageAttributes { * We display a small message just below the message referenced */ dataExtractionNotification?: DataExtractionNotificationMsg; - - /** - * This is used to choose whether to initialize the timer or not in the MessageModel object. - * If false or undefined, timer will be in itialized. - */ - skipTimerInit?: boolean; } export interface DataExtractionNotificationMsg { @@ -173,7 +167,6 @@ export interface MessageAttributesOptionals { sync?: boolean; snippet?: any; direction?: any; - skipTimerInit?: boolean; } /** From e31b219bd4600c8c9e38429f9834f9e5175cced4 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Mon, 26 Jul 2021 15:46:36 +1000 Subject: [PATCH 10/30] fix --- ts/interactions/conversationInteractions.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ts/interactions/conversationInteractions.ts b/ts/interactions/conversationInteractions.ts index 5b08d275f..6a11be9e9 100644 --- a/ts/interactions/conversationInteractions.ts +++ b/ts/interactions/conversationInteractions.ts @@ -439,7 +439,9 @@ export async function deleteMessagesById( askUserForConfirmation: boolean ) { const conversationModel = getConversationController().getOrThrow(conversationId); - const selectedMessages = _.compact(await Promise.all(messageIds.map(m => getMessageById(m)))); + const selectedMessages = _.compact( + await Promise.all(messageIds.map(m => getMessageById(m, false))) + ); const moreThanOne = selectedMessages.length > 1; From 1054278a540b75700ec00fef65f2de060f3a3e9e Mon Sep 17 00:00:00 2001 From: audric Date: Tue, 27 Jul 2021 10:29:18 +1000 Subject: [PATCH 11/30] disable search in messages for now --- _locales/en/messages.json | 2 +- app/sql.js | 46 ++++++++++---------- ts/components/SearchResults.tsx | 4 +- ts/components/session/UserSearchDropdown.tsx | 9 ++-- ts/data/data.ts | 23 +--------- 5 files changed, 32 insertions(+), 52 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index d3084030f..15d48eebe 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -354,7 +354,7 @@ "beginYourSession": "Begin
your
Session.", "welcomeToYourSession": "Welcome to your Session", "newSession": "New Session", - "searchFor...": "Search for conversations, contacts, and messages", + "searchFor...": "Search for conversations or contacts", "enterSessionID": "Enter Session ID", "enterSessionIDOfRecipient": "Enter Session ID or ONS name of recipient", "usersCanShareTheir...": "Users can share their Session ID by going into their account settings and tapping \"Share Session ID\", or by sharing their QR code.", diff --git a/app/sql.js b/app/sql.js index d2b7a00b9..7ddb8a210 100644 --- a/app/sql.js +++ b/app/sql.js @@ -41,7 +41,6 @@ module.exports = { getAllOpenGroupV1Conversations, getAllOpenGroupV2Conversations, getPubkeysInPublicConversation, - getAllConversationIds, getAllGroupsInvolvingId, removeAllConversations, @@ -65,8 +64,6 @@ module.exports = { getMessageBySenderAndServerTimestamp, getMessageIdsFromServerIds, getMessageById, - getAllMessages, - getAllMessageIds, getMessagesBySentAt, getSeenMessagesByHashList, getLastHashBySnode, @@ -260,7 +257,7 @@ function openAndMigrateDatabase(filePath, key) { switchToWAL(db2); // Because foreign key support is not enabled by default! - db2.pragma('foreign_keys = ON'); + db2.pragma('foreign_keys = OFF'); return db2; } catch (error) { @@ -834,6 +831,7 @@ const LOKI_SCHEMA_VERSIONS = [ updateToLokiSchemaVersion12, updateToLokiSchemaVersion13, updateToLokiSchemaVersion14, + updateToLokiSchemaVersion15, ]; function updateToLokiSchemaVersion1(currentVersion, db) { @@ -1177,6 +1175,26 @@ function updateToLokiSchemaVersion14(currentVersion, db) { console.log(`updateToLokiSchemaVersion${targetVersion}: success!`); } +function updateToLokiSchemaVersion15(currentVersion, db) { + const targetVersion = 15; + if (currentVersion >= targetVersion) { + return; + } + console.log(`updateToLokiSchemaVersion${targetVersion}: starting...`); + + db.transaction(() => { + db.exec(` + DROP TABLE pairingAuthorisations; + DROP TABLE ${MESSAGES_FTS_TABLE}; + DROP TRIGGER messages_on_delete; + DROP TRIGGER messages_on_update; + `); + + writeLokiSchemaVersion(targetVersion, db); + })(); + console.log(`updateToLokiSchemaVersion${targetVersion}: success!`); +} + function writeLokiSchemaVersion(newVersion, db) { db.prepare( `INSERT INTO loki_schema( @@ -1287,7 +1305,8 @@ function initialize({ configDir, key, messages, passwordAttempt }) { // Clear any already deleted db entries on each app start. vacuumDatabase(db); - getMessageCount(); + const msgCount = getMessageCount(); + console.warn('total message count: ', msgCount); } catch (error) { if (passwordAttempt) { throw error; @@ -1612,13 +1631,6 @@ function getAllConversations() { return map(rows, row => jsonToObject(row.json)); } -function getAllConversationIds() { - const rows = globalInstance - .prepare(`SELECT id FROM ${CONVERSATIONS_TABLE} ORDER BY id ASC;`) - .all(); - return map(rows, row => row.id); -} - function getAllOpenGroupV1Conversations() { const rows = globalInstance .prepare( @@ -1992,16 +2004,6 @@ function getMessageById(id) { return jsonToObject(row.json); } -function getAllMessages() { - const rows = globalInstance.prepare(`SELECT json FROM ${MESSAGES_TABLE} ORDER BY id ASC;`).all(); - return map(rows, row => jsonToObject(row.json)); -} - -function getAllMessageIds() { - const rows = globalInstance.prepare(`SELECT id FROM ${MESSAGES_TABLE} ORDER BY id ASC;`).all(); - return map(rows, row => row.id); -} - function getMessageBySender({ source, sourceDevice, sentAt }) { const rows = globalInstance .prepare( diff --git a/ts/components/SearchResults.tsx b/ts/components/SearchResults.tsx index d0f2e8e9f..e00531b11 100644 --- a/ts/components/SearchResults.tsx +++ b/ts/components/SearchResults.tsx @@ -54,7 +54,7 @@ export const SearchResults = (props: SearchResultsProps) => { ) : null} - {haveMessages ? ( + {/* {haveMessages ? (
{hideMessagesHeader ? null : (
@@ -65,7 +65,7 @@ export const SearchResults = (props: SearchResultsProps) => { ))}
- ) : null} + ) : null} */}
); }; diff --git a/ts/components/session/UserSearchDropdown.tsx b/ts/components/session/UserSearchDropdown.tsx index 695307bec..30293e08a 100644 --- a/ts/components/session/UserSearchDropdown.tsx +++ b/ts/components/session/UserSearchDropdown.tsx @@ -5,6 +5,7 @@ import { SessionSearchInput } from './SessionSearchInput'; import { SearchResultsProps } from '../SearchResults'; import { DefaultTheme } from 'styled-components'; +import autoBind from 'auto-bind'; export interface Props { searchTerm: string; @@ -18,13 +19,9 @@ interface State { } export class UserSearchDropdown extends React.Component { - private readonly updateSearchBound: (searchedString: string) => void; - public constructor(props: Props) { super(props); - this.updateSearchBound = this.updateSearch.bind(this); - this.handleNavigation = this.handleNavigation.bind(this); - this.handleContactSelected = this.handleContactSelected.bind(this); + autoBind(this); this.state = { selectedContact: -1, }; @@ -64,7 +61,7 @@ export class UserSearchDropdown extends React.Component {
diff --git a/ts/data/data.ts b/ts/data/data.ts index 5d9c357f1..a6882607d 100644 --- a/ts/data/data.ts +++ b/ts/data/data.ts @@ -89,7 +89,6 @@ const channelsToMake = { removeConversation, getAllConversations, - getAllConversationIds, getAllOpenGroupV1Conversations, getPubkeysInPublicConversation, getAllGroupsInvolvingId, @@ -116,8 +115,6 @@ const channelsToMake = { getMessageBySenderAndServerTimestamp, getMessageIdsFromServerIds, getMessageById, - getAllMessages, - getAllMessageIds, getMessagesBySentAt, getExpiredMessages, getOutgoingWithoutExpiresAt, @@ -541,11 +538,6 @@ export async function getAllConversations(): Promise { return collection; } -export async function getAllConversationIds(): Promise> { - const ids = await channels.getAllConversationIds(); - return ids; -} - export async function getAllOpenGroupV1Conversations(): Promise { const conversations = await channels.getAllOpenGroupV1Conversations(); @@ -664,17 +656,6 @@ export async function getMessageById(id: string): Promise { return new MessageModel(message); } -// For testing only -export async function getAllMessages(): Promise { - const messages = await channels.getAllMessages(); - return new MessageCollection(messages); -} - -export async function getAllMessageIds(): Promise> { - const ids = await channels.getAllMessageIds(); - return ids; -} - export async function getMessageBySender({ source, sourceDevice, @@ -775,9 +756,8 @@ export async function removeAllMessagesInConversation(conversationId: string): P // time so we don't use too much memory. // eslint-disable-next-line no-await-in-loop messages = await getMessagesByConversation(conversationId, { - limit: 100, + limit: 500, }); - if (!messages.length) { return; } @@ -787,6 +767,7 @@ export async function removeAllMessagesInConversation(conversationId: string): P // 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 + await Promise.all(messages.map(message => message.cleanup())); // eslint-disable-next-line no-await-in-loop From 9c61defc0b618d0c8946af17050d389a5bdfedd1 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 27 Jul 2021 10:33:35 +1000 Subject: [PATCH 12/30] small update --- ts/components/conversation/Message.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 4fc803cf8..92df95024 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -194,7 +194,7 @@ class MessageInner extends React.PureComponent { }; // as 'checkExpired' is potentially called more than once (componentDidUpdate & componentDidMount), // we need to clear the timeout call to 'setExpired' first to avoid multiple calls to 'setExpired'. - clearTimeout(this.expiredTimeout); + global.clearTimeout(this.expiredTimeout); this.expiredTimeout = setTimeout(setExpired, EXPIRED_DELAY); } } From 4b8778d071806f6acdea08c38ce624f976f643b0 Mon Sep 17 00:00:00 2001 From: audric Date: Tue, 27 Jul 2021 11:16:23 +1000 Subject: [PATCH 13/30] fix markRead using timestamp of now when scroll to bottom --- app/sql.js | 1 - .../session/conversation/SessionMessagesListContainer.tsx | 4 ++-- ts/models/conversation.ts | 7 +++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/sql.js b/app/sql.js index 7ddb8a210..24d3a5fd7 100644 --- a/app/sql.js +++ b/app/sql.js @@ -1185,7 +1185,6 @@ function updateToLokiSchemaVersion15(currentVersion, db) { db.transaction(() => { db.exec(` DROP TABLE pairingAuthorisations; - DROP TABLE ${MESSAGES_FTS_TABLE}; DROP TRIGGER messages_on_delete; DROP TRIGGER messages_on_update; `); diff --git a/ts/components/session/conversation/SessionMessagesListContainer.tsx b/ts/components/session/conversation/SessionMessagesListContainer.tsx index 81adf29d3..f4c72bde0 100644 --- a/ts/components/session/conversation/SessionMessagesListContainer.tsx +++ b/ts/components/session/conversation/SessionMessagesListContainer.tsx @@ -174,7 +174,7 @@ class SessionMessagesListContainerInner extends React.Component { } if ((forceIsOnBottom || this.getScrollOffsetBottomPx() === 0) && isElectronWindowFocused()) { - void conversation.markRead(messagesProps[0].propsForMessage.receivedAt || 0).then(() => { + void conversation.markRead(Date.now()).then(() => { window.inboxStore?.dispatch(markConversationFullyRead(conversationKey)); }); } @@ -372,7 +372,7 @@ class SessionMessagesListContainerInner extends React.Component { const conversation = getConversationController().get(conversationKey); if (isElectronWindowFocused()) { - void conversation.markRead(messagesProps[0].propsForMessage.receivedAt || 0).then(() => { + void conversation.markRead(Date.now()).then(() => { window.inboxStore?.dispatch(markConversationFullyRead(conversationKey)); }); } diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 2bfb47f22..8d3edfab1 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -198,7 +198,10 @@ export class ConversationModel extends Backbone.Model { }); this.throttledNotify = _.debounce(this.notify, 500, { maxWait: 1000, trailing: true }); //start right away the function is called, and wait 1sec before calling it again - const markReadDebounced = _.debounce(this.markReadBouncy, 1000, { leading: true }); + const markReadDebounced = _.debounce(this.markReadBouncy, 1000, { + leading: true, + trailing: true, + }); // tslint:disable-next-line: no-async-without-await this.markRead = async (newestUnreadDate: number) => { const lastReadTimestamp = this.lastReadTimestamp; @@ -972,7 +975,7 @@ export class ConversationModel extends Backbone.Model { let allUnreadMessagesInConvo = (await this.getUnread()).models; const oldUnreadNowRead = allUnreadMessagesInConvo.filter( - (message: any) => message.get('received_at') <= newestUnreadDate + message => (message.get('received_at') as number) <= newestUnreadDate ); let read = []; From b89f55dd02f3341960cfbc012bf3672272a3aa6b Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 27 Jul 2021 12:01:11 +1000 Subject: [PATCH 14/30] update displayed buttons on groups --- ts/components/session/conversation/SessionRightPanel.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ts/components/session/conversation/SessionRightPanel.tsx b/ts/components/session/conversation/SessionRightPanel.tsx index 33bf1e699..972e0ecde 100644 --- a/ts/components/session/conversation/SessionRightPanel.tsx +++ b/ts/components/session/conversation/SessionRightPanel.tsx @@ -131,7 +131,7 @@ const HeaderItem = () => { name, } = selectedConversation; - const showInviteContacts = (isPublic || weAreAdmin) && !isKickedFromGroup && !isBlocked && !left; + const showInviteContacts = !isKickedFromGroup && !isBlocked && !left; const userName = name || profileName || phoneNumber; return ( @@ -249,9 +249,10 @@ export const SessionRightPanelWithDetails = () => { }; }); - const showUpdateGroupNameButton = weAreAdmin && !commonNoShow; + const showUpdateGroupNameButton = (!isPublic || isPublic && weAreAdmin) && !commonNoShow; const showAddRemoveModeratorsButton = weAreAdmin && !commonNoShow && isPublic; + const showUpdateGroupMembersButton = !isPublic && isGroup && !commonNoShow; const deleteConvoAction = isPublic From bfa68fc9b57b9215c0be9c1a705a612deeeab782 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 27 Jul 2021 12:05:49 +1000 Subject: [PATCH 15/30] add isGroup test --- ts/components/session/conversation/SessionRightPanel.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ts/components/session/conversation/SessionRightPanel.tsx b/ts/components/session/conversation/SessionRightPanel.tsx index 972e0ecde..30e47cb45 100644 --- a/ts/components/session/conversation/SessionRightPanel.tsx +++ b/ts/components/session/conversation/SessionRightPanel.tsx @@ -122,7 +122,7 @@ const HeaderItem = () => { avatarPath, isPublic, id, - weAreAdmin, + isGroup, isKickedFromGroup, profileName, phoneNumber, @@ -131,7 +131,7 @@ const HeaderItem = () => { name, } = selectedConversation; - const showInviteContacts = !isKickedFromGroup && !isBlocked && !left; + const showInviteContacts = isGroup && !isKickedFromGroup && !isBlocked && !left; const userName = name || profileName || phoneNumber; return ( @@ -249,7 +249,7 @@ export const SessionRightPanelWithDetails = () => { }; }); - const showUpdateGroupNameButton = (!isPublic || isPublic && weAreAdmin) && !commonNoShow; + const showUpdateGroupNameButton = isGroup && (!isPublic || isPublic && weAreAdmin) && !commonNoShow; const showAddRemoveModeratorsButton = weAreAdmin && !commonNoShow && isPublic; From 9f62d6577cc116409ebee59c19402109990d1c6b Mon Sep 17 00:00:00 2001 From: audric Date: Tue, 27 Jul 2021 13:19:48 +1000 Subject: [PATCH 16/30] remove unused accessKey derived from profileKey --- js/modules/crypto.js | 19 ------------------- ts/models/conversation.ts | 23 ----------------------- 2 files changed, 42 deletions(-) diff --git a/js/modules/crypto.js b/js/modules/crypto.js index e7b543372..445fb49db 100644 --- a/js/modules/crypto.js +++ b/js/modules/crypto.js @@ -9,7 +9,6 @@ module.exports = { concatenateBytes, constantTimeEqual, decryptSymmetric, - deriveAccessKey, encryptAesCtr, encryptSymmetric, getRandomBytes, @@ -27,13 +26,6 @@ function bytesFromString(string) { // High-level Operations -async function deriveAccessKey(profileKey) { - const iv = getZeroes(12); - const plaintext = getZeroes(16); - const accessKey = await _encrypt_aes_gcm(profileKey, iv, plaintext); - return _getFirstBytes(accessKey, 16); -} - const IV_LENGTH = 16; const MAC_LENGTH = 16; const NONCE_LENGTH = 16; @@ -141,17 +133,6 @@ async function encryptAesCtr(key, plaintext, counter) { return ciphertext; } -async function _encrypt_aes_gcm(key, iv, plaintext) { - const algorithm = { - name: 'AES-GCM', - iv, - }; - const extractable = false; - - const cryptoKey = await crypto.subtle.importKey('raw', key, algorithm, extractable, ['encrypt']); - return crypto.subtle.encrypt(algorithm, cryptoKey, plaintext); -} - // Utility function getRandomBytes(n) { diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index d28515b14..ab3c6f25e 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -92,7 +92,6 @@ export interface ConversationAttributes { profile?: any; profileAvatar?: any; profileKey?: string; - accessKey?: any; triggerNotificationsFor: ConversationNotificationSettingType; isTrustedForAttachmentDownload: boolean; isPinned: boolean; @@ -130,7 +129,6 @@ export interface ConversationAttributesOptionals { profile?: any; profileAvatar?: any; profileKey?: string; - accessKey?: any; triggerNotificationsFor?: ConversationNotificationSettingType; isTrustedForAttachmentDownload?: boolean; isPinned: boolean; @@ -1201,34 +1199,13 @@ export class ConversationModel extends Backbone.Model { if (this.get('profileKey') !== profileKey) { this.set({ profileKey, - accessKey: null, }); - await this.deriveAccessKeyIfNeeded(); await this.commit(); } } - public async deriveAccessKeyIfNeeded() { - const profileKey = this.get('profileKey'); - if (!profileKey) { - return; - } - if (this.get('accessKey')) { - return; - } - - try { - const profileKeyBuffer = fromBase64ToArrayBuffer(profileKey); - const accessKeyBuffer = await window.Signal.Crypto.deriveAccessKey(profileKeyBuffer); - const accessKey = fromArrayBufferToBase64(accessKeyBuffer); - this.set({ accessKey }); - } catch (e) { - window?.log?.warn(`Failed to derive access key for ${this.id}`); - } - } - public async upgradeMessages(messages: any) { // tslint:disable-next-line: one-variable-per-declaration for (let max = messages.length, i = 0; i < max; i += 1) { From a6aed4d7d147917bc986b6b438b204f366e1c202 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 27 Jul 2021 13:54:38 +1000 Subject: [PATCH 17/30] fix isAdmin to return the right value for closed groups --- ts/models/conversation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 2bfb47f22..5ccfa93bd 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -1110,7 +1110,7 @@ export class ConversationModel extends Backbone.Model { } public isAdmin(pubKey?: string) { - if (!this.isPublic()) { + if (!this.isPublic() && !this.isGroup()) { return false; } if (!pubKey) { From eb3851592cdc6e4d9def39097c1c1ebc66b13822 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 27 Jul 2021 14:02:22 +1000 Subject: [PATCH 18/30] lint --- ts/components/session/conversation/SessionRightPanel.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ts/components/session/conversation/SessionRightPanel.tsx b/ts/components/session/conversation/SessionRightPanel.tsx index 30e47cb45..192e29534 100644 --- a/ts/components/session/conversation/SessionRightPanel.tsx +++ b/ts/components/session/conversation/SessionRightPanel.tsx @@ -249,10 +249,9 @@ export const SessionRightPanelWithDetails = () => { }; }); - const showUpdateGroupNameButton = isGroup && (!isPublic || isPublic && weAreAdmin) && !commonNoShow; + const showUpdateGroupNameButton = + isGroup && (!isPublic || (isPublic && weAreAdmin)) && !commonNoShow; const showAddRemoveModeratorsButton = weAreAdmin && !commonNoShow && isPublic; - - const showUpdateGroupMembersButton = !isPublic && isGroup && !commonNoShow; const deleteConvoAction = isPublic From fce86989f0b3992cea3e94ca9fef1dada2b709c6 Mon Sep 17 00:00:00 2001 From: audric Date: Tue, 27 Jul 2021 16:41:15 +1000 Subject: [PATCH 19/30] make sure profileKey is a hex string in all convos --- js/modules/types/conversation.js | 56 --------------------- ts/interactions/conversationInteractions.ts | 15 +++--- ts/models/conversation.ts | 31 +++++++++--- ts/receiver/configMessage.ts | 5 -- ts/receiver/dataMessage.ts | 21 ++++---- ts/receiver/queuedJob.ts | 15 ++---- ts/receiver/receiver.ts | 36 ------------- ts/session/utils/User.ts | 7 +-- ts/session/utils/syncUtils.ts | 21 +++++--- 9 files changed, 69 insertions(+), 138 deletions(-) diff --git a/js/modules/types/conversation.js b/js/modules/types/conversation.js index cf2123151..fc66a6e7a 100644 --- a/js/modules/types/conversation.js +++ b/js/modules/types/conversation.js @@ -55,60 +55,6 @@ function buildAvatarUpdater({ field }) { } const maybeUpdateAvatar = buildAvatarUpdater({ field: 'avatar' }); -const maybeUpdateProfileAvatar = buildAvatarUpdater({ - field: 'profileAvatar', -}); - -async function upgradeToVersion2(conversation, options) { - if (conversation.version >= 2) { - return conversation; - } - - const { writeNewAttachmentData } = options; - if (!isFunction(writeNewAttachmentData)) { - throw new Error('Conversation.upgradeToVersion2: writeNewAttachmentData must be a function'); - } - - let { avatar, profileAvatar, profileKey } = conversation; - - if (avatar && avatar.data) { - avatar = { - hash: await computeHash(avatar.data), - path: await writeNewAttachmentData(avatar.data), - }; - } - - if (profileAvatar && profileAvatar.data) { - profileAvatar = { - hash: await computeHash(profileAvatar.data), - path: await writeNewAttachmentData(profileAvatar.data), - }; - } - - if (profileKey && profileKey.byteLength) { - profileKey = arrayBufferToBase64(profileKey); - } - - return { - ...conversation, - version: 2, - avatar, - profileAvatar, - profileKey, - }; -} - -async function migrateConversation(conversation, options = {}) { - if (!conversation) { - return conversation; - } - if (!isNumber(conversation.version)) { - // eslint-disable-next-line no-param-reassign - conversation.version = 1; - } - - return upgradeToVersion2(conversation, options); -} async function deleteExternalFiles(conversation, options = {}) { if (!conversation) { @@ -133,9 +79,7 @@ async function deleteExternalFiles(conversation, options = {}) { module.exports = { deleteExternalFiles, - migrateConversation, maybeUpdateAvatar, - maybeUpdateProfileAvatar, createLastMessageUpdate, arrayBufferToBase64, }; diff --git a/ts/interactions/conversationInteractions.ts b/ts/interactions/conversationInteractions.ts index 6a11be9e9..0e9fb3964 100644 --- a/ts/interactions/conversationInteractions.ts +++ b/ts/interactions/conversationInteractions.ts @@ -41,7 +41,7 @@ import { import { getDecryptedMediaUrl } from '../session/crypto/DecryptedAttachmentsManager'; import { IMAGE_JPEG } from '../types/MIME'; import { FSv2 } from '../fileserver'; -import { fromBase64ToArray, toHex } from '../session/utils/String'; +import { fromBase64ToArray, fromHexToArray, toHex } from '../session/utils/String'; import { SessionButtonColor } from '../components/session/SessionButton'; import { perfEnd, perfStart } from '../session/utils/Performance'; import { ReplyingToMessageProps } from '../components/session/conversation/SessionCompositionBox'; @@ -350,17 +350,21 @@ export async function uploadOurAvatar(newAvatarDecrypted?: ArrayBuffer) { return; } - let profileKey; + let profileKey: Uint8Array | null; let decryptedAvatarData; if (newAvatarDecrypted) { // Encrypt with a new key every time - profileKey = window.libsignal.crypto.getRandomBytes(32); + profileKey = window.libsignal.crypto.getRandomBytes(32) as Uint8Array; decryptedAvatarData = newAvatarDecrypted; } else { // this is a reupload. no need to generate a new profileKey - profileKey = window.textsecure.storage.get('profileKey'); + const ourConvoProfileKey = + getConversationController() + .get(UserUtils.getOurPubKeyStrFromCache()) + ?.get('profileKey') || null; + profileKey = ourConvoProfileKey ? fromHexToArray(ourConvoProfileKey) : null; if (!profileKey) { - window.log.info('our profileKey not found'); + window.log.info('our profileKey not found. Not reuploading our avatar'); return; } const currentAttachmentPath = ourConvo.getAvatarPath(); @@ -412,7 +416,6 @@ export async function uploadOurAvatar(newAvatarDecrypted?: ArrayBuffer) { const displayName = ourConvo.get('profileName'); // write the profileKey even if it did not change - window.storage.put('profileKey', profileKey); ourConvo.set({ profileKey: toHex(profileKey) }); // Replace our temporary image with the attachment pointer from the server: // this commits already diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index ab3c6f25e..9670791ab 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -20,7 +20,7 @@ import { saveMessages, updateConversation, } from '../../ts/data/data'; -import { fromArrayBufferToBase64, fromBase64ToArrayBuffer } from '../session/utils/String'; +import { fromArrayBufferToBase64, fromBase64ToArrayBuffer, toHex } from '../session/utils/String'; import { actions as conversationActions, conversationChanged, @@ -91,6 +91,9 @@ export interface ConversationAttributes { nickname?: string; profile?: any; profileAvatar?: any; + /** + * Consider this being a hex string if it set + */ profileKey?: string; triggerNotificationsFor: ConversationNotificationSettingType; isTrustedForAttachmentDownload: boolean; @@ -128,6 +131,9 @@ export interface ConversationAttributesOptionals { nickname?: string; profile?: any; profileAvatar?: any; + /** + * Consider this being a hex string if it set + */ profileKey?: string; triggerNotificationsFor?: ConversationNotificationSettingType; isTrustedForAttachmentDownload?: boolean; @@ -1194,15 +1200,28 @@ export class ConversationModel extends Backbone.Model { await this.commit(); } } - public async setProfileKey(profileKey: string) { + /** + * profileKey MUST be a hex string + * @param profileKey MUST be a hex string + */ + public async setProfileKey(profileKey?: Uint8Array, autoCommit = true) { + const re = /[0-9A-Fa-f]*/g; + + if (!profileKey) { + return; + } + + const profileKeyHex = toHex(profileKey); + // profileKey is a string so we can compare it directly - if (this.get('profileKey') !== profileKey) { + if (this.get('profileKey') !== profileKeyHex) { this.set({ - profileKey, + profileKey: profileKeyHex, }); - - await this.commit(); + if (autoCommit) { + await this.commit(); + } } } diff --git a/ts/receiver/configMessage.ts b/ts/receiver/configMessage.ts index 54ea9cc50..63590efcc 100644 --- a/ts/receiver/configMessage.ts +++ b/ts/receiver/configMessage.ts @@ -34,11 +34,6 @@ async function handleOurProfileUpdate( return; } - if (profileKey?.length) { - window?.log?.info('Saving our profileKey from configuration message'); - // TODO not sure why we keep our profileKey in storage AND in our conversaio - window.textsecure.storage.put('profileKey', profileKey); - } const lokiProfile = { displayName, profilePicture, diff --git a/ts/receiver/dataMessage.ts b/ts/receiver/dataMessage.ts index deacbe123..c82f78d55 100644 --- a/ts/receiver/dataMessage.ts +++ b/ts/receiver/dataMessage.ts @@ -20,11 +20,12 @@ import { } from '../../ts/data/data'; import { ConversationModel, ConversationTypeEnum } from '../models/conversation'; import { allowOnlyOneAtATime } from '../session/utils/Promise'; +import { toHex } from '../session/utils/String'; export async function updateProfileOneAtATime( conversation: ConversationModel, profile: SignalService.DataMessage.ILokiProfile, - profileKey: any + profileKey?: Uint8Array | null // was any ) { if (!conversation?.id) { window?.log?.warn('Cannot update profile with empty convoid'); @@ -39,13 +40,18 @@ export async function updateProfileOneAtATime( async function updateProfile( conversation: ConversationModel, profile: SignalService.DataMessage.ILokiProfile, - profileKey: any + profileKey?: Uint8Array | null // was any ) { const { dcodeIO, textsecure, Signal } = window; // Retain old values unless changed: const newProfile = conversation.get('profile') || {}; + if (!profileKey) { + window.log.warn("No need to try to update profile. We don't have a profile key"); + return; + } + newProfile.displayName = profile.displayName; if (profile.profilePicture) { @@ -79,7 +85,7 @@ async function updateProfile( }); // Only update the convo if the download and decrypt is a success conversation.set('avatarPointer', profile.profilePicture); - conversation.set('profileKey', profileKey); + conversation.set('profileKey', toHex(profileKey)); ({ path } = upgraded); } catch (e) { window?.log?.error(`Could not decrypt profile image: ${e}`); @@ -422,18 +428,15 @@ export const isDuplicate = ( async function handleProfileUpdate( profileKeyBuffer: Uint8Array, convoId: string, - convoType: ConversationTypeEnum, isIncoming: boolean ) { - const profileKey = StringUtils.decode(profileKeyBuffer, 'base64'); - if (!isIncoming) { // We update our own profileKey if it's different from what we have const ourNumber = UserUtils.getOurPubKeyStrFromCache(); const me = getConversationController().getOrCreate(ourNumber, ConversationTypeEnum.PRIVATE); // Will do the save for us if needed - await me.setProfileKey(profileKey); + await me.setProfileKey(profileKeyBuffer); } else { const sender = await getConversationController().getOrCreateAndWait( convoId, @@ -441,7 +444,7 @@ async function handleProfileUpdate( ); // Will do the save for us - await sender.setProfileKey(profileKey); + await sender.setProfileKey(profileKeyBuffer); } } @@ -582,7 +585,7 @@ export async function handleMessageEvent(event: MessageEvent): Promise { return; } if (message.profileKey?.length) { - await handleProfileUpdate(message.profileKey, conversationId, type, isIncoming); + await handleProfileUpdate(message.profileKey, conversationId, isIncoming); } const msg = createMessage(data, isIncoming); diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index 809025a57..940d1b3bc 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -204,16 +204,14 @@ function handleLinkPreviews(messageBody: string, messagePreview: any, message: M } async function processProfileKey( - source: string, conversation: ConversationModel, sendingDeviceConversation: ConversationModel, - profileKeyBuffer: Uint8Array + profileKeyBuffer?: Uint8Array ) { - const profileKey = StringUtils.decode(profileKeyBuffer, 'base64'); if (conversation.isPrivate()) { - await conversation.setProfileKey(profileKey); + await conversation.setProfileKey(profileKeyBuffer); } else { - await sendingDeviceConversation.setProfileKey(profileKey); + await sendingDeviceConversation.setProfileKey(profileKeyBuffer); } } @@ -360,12 +358,7 @@ async function handleRegularMessage( } if (dataMessage.profileKey) { - await processProfileKey( - source, - conversation, - sendingDeviceConversation, - dataMessage.profileKey - ); + await processProfileKey(conversation, sendingDeviceConversation, dataMessage.profileKey); } // we just received a message from that user so we reset the typing indicator for this convo diff --git a/ts/receiver/receiver.ts b/ts/receiver/receiver.ts index f41e3d05e..b2ad6aa5b 100644 --- a/ts/receiver/receiver.ts +++ b/ts/receiver/receiver.ts @@ -273,42 +273,6 @@ async function handleDecryptedEnvelope(envelope: EnvelopePlus, plaintext: ArrayB } } -/** - * Only used for opengroupv1 it seems. - * To be removed soon - */ -export async function handlePublicMessage(messageData: any) { - const { source } = messageData; - const { group, profile, profileKey } = messageData.message; - - const isMe = UserUtils.isUsFromCache(source); - - if (!isMe && profile) { - const conversation = await getConversationController().getOrCreateAndWait( - source, - ConversationTypeEnum.PRIVATE - ); - await updateProfileOneAtATime(conversation, profile, profileKey); - } - - const isPublicVisibleMessage = group && group.id && !!group.id.match(openGroupPrefixRegex); - - if (!isPublicVisibleMessage) { - throw new Error('handlePublicMessage Should only be called with public message groups'); - } - - const ev = { - // Public chat messages from ourselves should be outgoing - type: isMe ? 'sent' : 'message', - data: messageData, - confirm: () => { - /* do nothing */ - }, - }; - - await handleMessageEvent(ev); // open groups v1 -} - export async function handleOpenGroupV2Message( message: OpenGroupMessageV2, roomInfos: OpenGroupRequestCommonType diff --git a/ts/session/utils/User.ts b/ts/session/utils/User.ts index 38644b5fc..8cd1eb545 100644 --- a/ts/session/utils/User.ts +++ b/ts/session/utils/User.ts @@ -3,7 +3,7 @@ import { UserUtils } from '.'; import { getItemById } from '../../../ts/data/data'; import { KeyPair } from '../../../libtextsecure/libsignal-protocol'; import { PubKey } from '../types'; -import { toHex } from './String'; +import { fromHexToArray, toHex } from './String'; import { getConversationController } from '../conversations'; export type HexKeyPair = { @@ -97,14 +97,15 @@ export function getOurProfile(): OurLokiProfile | undefined { // in their primary device's conversation const ourNumber = window.storage.get('primaryDevicePubKey'); const ourConversation = getConversationController().get(ourNumber); - const profileKey = new Uint8Array(window.storage.get('profileKey')); + const ourProfileKeyHex = ourConversation.get('profileKey'); + const profileKeyAsBytes = ourProfileKeyHex ? fromHexToArray(ourProfileKeyHex) : null; const avatarPointer = ourConversation.get('avatarPointer'); const { displayName } = ourConversation.getLokiProfile(); return { displayName, avatarPointer, - profileKey: profileKey.length ? profileKey : null, + profileKey: profileKeyAsBytes?.length ? profileKeyAsBytes : null, }; } catch (e) { window?.log?.error(`Failed to get our profile: ${e}`); diff --git a/ts/session/utils/syncUtils.ts b/ts/session/utils/syncUtils.ts index a40be7046..affe3a963 100644 --- a/ts/session/utils/syncUtils.ts +++ b/ts/session/utils/syncUtils.ts @@ -14,7 +14,7 @@ import { ConfigurationMessageContact, } from '../messages/outgoing/controlMessage/ConfigurationMessage'; import { ConversationModel } from '../../models/conversation'; -import { fromBase64ToArray } from './String'; +import { fromBase64ToArray, fromHexToArray } from './String'; import { SignalService } from '../../protobuf'; import _ from 'lodash'; import { @@ -160,9 +160,14 @@ const getValidContacts = (convos: Array) => { const contacts = contactsModels.map(c => { try { - const profileKeyForContact = c.get('profileKey') - ? fromBase64ToArray(c.get('profileKey') as string) - : undefined; + const profileKey = c.get('profileKey'); + let profileKeyForContact; + if (typeof profileKey === 'string') { + profileKeyForContact = fromHexToArray(profileKey); + } else if (profileKey) { + console.warn('AUDRIC migration todo'); + debugger; + } return new ConfigurationMessageContact({ publicKey: c.id, @@ -189,8 +194,12 @@ export const getCurrentConfigurationMessage = async (convos: Array Date: Tue, 27 Jul 2021 16:41:46 +1000 Subject: [PATCH 20/30] fix a bug of attachment not loading in one to one chats --- js/modules/types/conversation.js | 2 +- ts/components/ConversationListItem.tsx | 1 - ts/components/conversation/Image.tsx | 1 + ts/hooks/useEncryptedFileFetch.ts | 3 ++- ts/session/utils/syncUtils.ts | 18 ++++++++++++++---- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/js/modules/types/conversation.js b/js/modules/types/conversation.js index fc66a6e7a..efca69dfd 100644 --- a/js/modules/types/conversation.js +++ b/js/modules/types/conversation.js @@ -1,6 +1,6 @@ /* global crypto */ -const { isFunction, isNumber } = require('lodash'); +const { isFunction } = require('lodash'); const { createLastMessageUpdate } = require('../../../ts/types/Conversation'); const { arrayBufferToBase64 } = require('../crypto'); diff --git a/ts/components/ConversationListItem.tsx b/ts/components/ConversationListItem.tsx index 9c8eff3cb..58938d68c 100644 --- a/ts/components/ConversationListItem.tsx +++ b/ts/components/ConversationListItem.tsx @@ -210,7 +210,6 @@ const AvatarItem = (props: { }; const ConversationListItem = (props: Props) => { - // console.warn('ConversationListItem', props.id.substr(-1), ': ', props); const { activeAt, unreadCount, diff --git a/ts/components/conversation/Image.tsx b/ts/components/conversation/Image.tsx index 1e0a5b087..1dd4f9a0e 100644 --- a/ts/components/conversation/Image.tsx +++ b/ts/components/conversation/Image.tsx @@ -62,6 +62,7 @@ export const Image = (props: Props) => { const role = canClick ? 'button' : undefined; const { loading, urlToLoad } = useEncryptedFileFetch(url, attachment.contentType); + // data will be url if loading is finished and '' if not const srcData = !loading ? urlToLoad : ''; diff --git a/ts/hooks/useEncryptedFileFetch.ts b/ts/hooks/useEncryptedFileFetch.ts index 0b3162980..b6912c742 100644 --- a/ts/hooks/useEncryptedFileFetch.ts +++ b/ts/hooks/useEncryptedFileFetch.ts @@ -19,12 +19,13 @@ export const useEncryptedFileFetch = (url: string, contentType: string) => { } useEffect(() => { + setLoading(true); + mountedRef.current = true; void fetchUrl(); return () => { mountedRef.current = false; }; }, [url]); - return { urlToLoad, loading }; }; diff --git a/ts/session/utils/syncUtils.ts b/ts/session/utils/syncUtils.ts index affe3a963..9947140ca 100644 --- a/ts/session/utils/syncUtils.ts +++ b/ts/session/utils/syncUtils.ts @@ -14,7 +14,7 @@ import { ConfigurationMessageContact, } from '../messages/outgoing/controlMessage/ConfigurationMessage'; import { ConversationModel } from '../../models/conversation'; -import { fromBase64ToArray, fromHexToArray } from './String'; +import { fromBase64ToArray, fromHexToArray, toHex } from './String'; import { SignalService } from '../../protobuf'; import _ from 'lodash'; import { @@ -163,10 +163,20 @@ const getValidContacts = (convos: Array) => { const profileKey = c.get('profileKey'); let profileKeyForContact; if (typeof profileKey === 'string') { - profileKeyForContact = fromHexToArray(profileKey); + // this will throw if the profileKey is not in hex. + try { + profileKeyForContact = fromHexToArray(profileKey); + } catch (e) { + profileKeyForContact = fromBase64ToArray(profileKey); + // if the line above does not fail, update the stored profileKey for this convo + void c.setProfileKey(profileKeyForContact); + } } else if (profileKey) { - console.warn('AUDRIC migration todo'); - debugger; + window.log.warn( + 'Got a profileKey for a contact in another format than string. Contact: ', + c.id + ); + return null; } return new ConfigurationMessageContact({ From bbac1923b25f14f8a32539b30d5d76f87c7a8b20 Mon Sep 17 00:00:00 2001 From: audric Date: Tue, 27 Jul 2021 17:12:21 +1000 Subject: [PATCH 21/30] bump version to 1.6.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e2869638..790ba6a51 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "session-desktop", "productName": "Session", "description": "Private messaging from your desktop", - "version": "1.6.7", + "version": "1.6.8", "license": "GPL-3.0", "author": { "name": "Loki Project", From 8414aa800de6e55c00ce91540401a4583e12365f Mon Sep 17 00:00:00 2001 From: audric Date: Wed, 28 Jul 2021 14:46:13 +1000 Subject: [PATCH 22/30] fix a bug not making profile name updates in opengroup --- ts/receiver/dataMessage.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/ts/receiver/dataMessage.ts b/ts/receiver/dataMessage.ts index c82f78d55..8e970a3ee 100644 --- a/ts/receiver/dataMessage.ts +++ b/ts/receiver/dataMessage.ts @@ -47,14 +47,9 @@ async function updateProfile( // Retain old values unless changed: const newProfile = conversation.get('profile') || {}; - if (!profileKey) { - window.log.warn("No need to try to update profile. We don't have a profile key"); - return; - } - newProfile.displayName = profile.displayName; - if (profile.profilePicture) { + if (profile.profilePicture && profileKey) { const prevPointer = conversation.get('avatarPointer'); const needsUpdate = !prevPointer || !_.isEqual(prevPointer, profile.profilePicture); @@ -97,7 +92,7 @@ async function updateProfile( return; } } - } else { + } else if (profileKey) { newProfile.avatar = null; } From 0d5e52678fca2c191adc9d155ae6a97bc6ce9288 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Wed, 28 Jul 2021 15:19:07 +1000 Subject: [PATCH 23/30] add link to Oxen website in the settings (right icon missing) --- ts/components/session/icon/Icons.tsx | 7 +++++++ ts/components/session/settings/SessionSettings.tsx | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/ts/components/session/icon/Icons.tsx b/ts/components/session/icon/Icons.tsx index 39a7ff3d8..918c8b3d2 100644 --- a/ts/components/session/icon/Icons.tsx +++ b/ts/components/session/icon/Icons.tsx @@ -23,6 +23,7 @@ export enum SessionIconType { Lock = 'lock', Microphone = 'microphone', Moon = 'moon', + Oxen = 'oxen', Pause = 'pause', Pencil = 'pencil', Pin = 'pin', @@ -213,6 +214,12 @@ export const icons = { viewBox: '0.5 0.5 22 22', ratio: 1, }, + [SessionIconType.Oxen]: { + path: + 'M18,4L20,8H17L15,4H13L15,8H12L10,4H8L10,8H7L5,4H4A2,2 0 0,0 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V4H18Z', + viewBox: '0 0 24 24', + ratio: 1, + }, [SessionIconType.Pause]: { path: 'M33,4.5v24c0,2.484-2.016,4.5-4.5,4.5h-24C2.016,33,0,30.984,0,28.5v-24C0,2.016,2.016,0,4.5,0h24 C30.984,0,33,2.016,33,4.5z', diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index 75bba036e..8b5d07e29 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -22,6 +22,7 @@ import { unblockConvoById } from '../../../interactions/conversationInteractions import { toggleAudioAutoplay } from '../../../state/ducks/userConfig'; import { sessionPassword } from '../../../state/ducks/modalDialog'; import { PasswordAction } from '../SessionPasswordModal'; +import { SessionIconButton, SessionIconSize, SessionIconType } from '../icon'; export enum SessionSettingCategory { Appearance = 'appearance', @@ -246,9 +247,17 @@ class SettingsViewInner extends React.Component { } public renderSessionInfo(): JSX.Element { + const openOxenWebsite = () => { + void shell.openExternal('https://oxen.io/'); + }; return (
v{window.versionInfo.version} + {window.versionInfo.commitHash}
); From 3995dbdeee8866500d511b0522f20b4b2bbf72d9 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Wed, 28 Jul 2021 16:45:46 +1000 Subject: [PATCH 24/30] oxen icon svg added --- ts/components/session/icon/Icons.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ts/components/session/icon/Icons.tsx b/ts/components/session/icon/Icons.tsx index 918c8b3d2..266181d3d 100644 --- a/ts/components/session/icon/Icons.tsx +++ b/ts/components/session/icon/Icons.tsx @@ -216,9 +216,9 @@ export const icons = { }, [SessionIconType.Oxen]: { path: - 'M18,4L20,8H17L15,4H13L15,8H12L10,4H8L10,8H7L5,4H4A2,2 0 0,0 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V4H18Z', - viewBox: '0 0 24 24', - ratio: 1, + 'M1033.9 1319.4h1v122h-1c-1.7-1.9-1.6-4.3-1.6-6.6v-108.7c0-2.4-.2-4.8 1.6-6.7zM773.4 1441.4c-21 0-42-.1-63 .1-4.2 0-6.9-1.4-9.2-4.6-10.2-14.5-16.9-30.2-18.5-48.2-2.3-24.5 4.9-45.8 19-65.4 1.9-2.7 4.3-4.1 7.9-4.1 42.3.1 84.6.2 127 0 4.5 0 5.8 1.4 5.5 5.7-.4 5.1-.3 10.3 0 15.5.3 4-1.1 5.1-5.1 5-22.8-.2-45.7-.1-68.5-.1-15 0-30 .1-45-.1-3.1 0-4.8 1-6 3.9-1.7 4-2.9 8.1-4.1 12.3-1.1 3.8 0 5 4 5 23.3-.1 46.7-.1 70-.1 13.3 0 26.7.1 40-.1 3.8-.1 5 1.1 4.8 4.8-.3 5.5-.3 11 0 16.5.3 4.5-1 6-5.7 5.9-33.8-.2-67.6-.1-101.5-.1-2.8 0-5.7.3-8.5-.1-3.8-.4-4.1 1.4-3.4 4.3 0 .2 0 .3.1.5 3 16.2 4.4 17.3 20.6 17.3 34.3 0 68.6.1 103-.1 4 0 5.7.9 5.4 5.2-.4 5.5-.3 11 0 16.5.2 3.6-1.2 4.5-4.6 4.5-21.6-.1-42.9 0-64.2 0zM397.2 1319.3c20 0 40 .1 60-.1 3.6 0 5.8 1.3 7.8 4.1 13.9 19.4 20.7 40.9 18.8 64.7-1.5 18.8-8.7 35.7-19.9 50.8-1.4 1.9-3.2 2.6-5.6 2.6-40.8-.1-81.6-.1-122.4 0-2.2 0-3.7-.7-5-2.5-11.5-14.8-18.2-31.4-20-50.1-2.2-21.7 3.6-41.4 14.7-59.7.2-.3.3-.6.5-.9 3.6-6.3 8-9.6 16.2-9.2 18.2.9 36.6.3 54.9.3zM1033.9 1319.4v121.9c-5.7 0-11.4-.3-17 .2-6.6.6-12-1.9-17-5.8-32.5-25.1-64.9-50.2-97.4-75.2-1.6-1.2-3.2-2.3-5.6-4.1v5.8c0 24.5-.1 49 .1 73.5 0 4.7-1.4 6-5.9 5.7-6.3-.4-12.7-.2-19 0-2.8.1-4.2-.6-4.2-3.8.1-38.2.1-76.3 0-114.5 0-3.2 1.3-3.9 4.2-3.9 6 .2 12 .1 18 .1 7.3 0 12.1 5.2 17.3 9.1 21.4 16.3 42.7 32.7 64 49.2 11.3 8.7 22.5 17.4 33.9 26.2 1.3-1.8.7-3.5.7-5.1 0-24.8.1-49.7-.1-74.5 0-3.9 1-5.3 5-5.1 7.6.5 15.3.3 23 .3zM488.8 1319.4c14.1 0 27-.1 39.9.1 4.3.1 7.9 2.6 11 5.3 12.9 11.2 25.9 22.3 38.7 33.7 2.7 2.4 4.6 1.8 6.9-.2 10.5-9.1 21.1-18.3 31.6-27.5 2.9-2.5 5.7-5.1 8.7-7.5 2.8-2.2 6.1-3.8 9.6-3.9 12.6-.2 25.2-.1 37.9-.1.1 2.1-1.4 2.8-2.5 3.7-13.3 11.5-26.7 23-40 34.5-7.9 6.8-15.8 13.7-23.8 20.5-2.5 2.1-1.5 3.5.4 5.1 10.1 8.6 20.2 17.3 30.3 26 12.2 10.5 24.4 21 37.5 32.2-14.2 0-27.4.4-40.6-.2-7.3-.3-11.7-6.5-16.9-10.9-10.8-9.1-21.4-18.5-32-27.8-2.4-2.1-4.5-2.3-7-.2-12.5 10.9-25.2 21.7-37.6 32.7-4.8 4.3-10 6.7-16.7 6.5-11.3-.3-22.7-.1-34.6-.1 4.5-5.4 9.8-9.2 14.6-13.5 13.3-11.8 26.9-23.2 40.4-34.8 3.9-3.3 7.8-6.7 11.8-9.9 2.6-2.1 2.6-3.5-.1-5.8-14-11.8-27.7-23.8-41.6-35.7-8.3-7-16.7-14.3-25.9-22.2zM153.9 1273.4c5.4 1.3 10.9 2.3 16.3 3.9 41.5 12.6 67.5 40.1 76.6 82.4 6.7 31.3-.6 60.2-19.9 85.5-18.2 23.9-42.5 37.5-72.4 41.2-27.9 3.4-53.1-3.5-75.7-19.9-24.1-17.5-37.8-41.4-42.8-70.6-.2-1-.1-2-1.1-2.6v-26c1.6-19.6 9.1-36.9 20.8-52.5 15.4-20.4 35.8-33.4 60.5-39.7 4.2-1.1 8.5-.7 12.7-1.8 8.3.1 16.6.1 25 .1zM142.8 1379.4c2.3 6 8.1 8.5 12.4 12.5 10.7 9.7 21.8 18.9 32.8 28.3 4.8 4.1 9.4 8.3 14.8 12.9H80.9c6.2-5.5 12-10.5 17.8-15.6 13.2-11.4 26.4-22.7 39.6-34.1 1.2-1.1 2.7-2.1 2.6-4 .7-.5 1.3-.5 1.9 0zM142.8 1379.4h-1.9c-12.9-11-25.7-22-38.6-33-7-6-14-12.1-21.6-18.7h122.5c-20.6 17.6-40.5 34.6-60.4 51.7zM397.2 1415.4c-14.2 0-28.3-.2-42.5.1-5.1.1-8-1.1-10.1-6.3-7.9-20.1-7.8-39.8 1-59.5 1.4-3.1 3.1-4.4 6.8-4.4 30 .2 60 .1 90 0 3.6 0 5.2 1.3 6.6 4.5 4.1 9.3 6.4 19 6.7 28.9.3 11.9-2.5 23.4-7.6 34.2-1.2 2.6-3.2 2.4-5.4 2.4-15.2.1-30.4.1-45.5.1zM153.9 1273.4c292.2 0 584.3 0 876.5-.1 3.7 0 4.7.8 4.6 4.6-.3 13.8-.1 27.7-.1 41.5-.4.4-.9.7-1.4.9-6.8 1-13.6.3-20.4.5-5.2.2-5.7.5-5.7 5.8 0 23.3 0 46.6-.1 70 0 2.7 1.2 6.5-1.8 7.7-2.5 1.1-4.6-2-6.7-3.6-31.9-24.6-64-49-95.8-73.8-6.7-5.3-13.9-6.3-22-6.1-13.3.4-11.7-1.3-11.7 11.8-.1 33.5 0 67 0 100.4 0 6.8.1 7 7 7 4.5 0 9 .1 13.5 0 5.1-.1 5.7-.6 5.7-5.8 0-23 0-46 .1-69 0-2.9-1.2-6.9 1.6-8.4 2.9-1.5 5.3 2 7.6 3.7 31.8 24.5 63.7 48.8 95.4 73.5 5.2 4 10.7 6.4 17.4 6.1 5.3-.3 10.7-.6 15.9.4.5.3 1 .6 1.4.9 0 15-.1 30 .1 45 0 2.5-.6 3.5-3.1 3-.5-.1-1 0-1.5 0-330.3 0-660.7 0-991 .1-3.7 0-4.6-.8-4.6-4.6.2-30.5.1-61 .1-91.5 3.4 1 2.6 4.3 3.1 6.6 3.1 16 9.4 30.6 19.2 43.5 18.3 24.2 42.6 38.3 72.8 41.7 30.1 3.5 56.7-4.8 79.9-24.2 21.4-17.9 33.4-40.9 36.9-68.7 6.6-53-29.2-105-84.8-115.9-2.8-.4-6.5.7-8.1-3zM128.9 1273.4c-2.8 1.6-6 1.5-9 2.2-20.6 4.6-38.6 14.1-53.5 28.9-16.7 16.7-26.7 36.9-30.5 60.2-.2 1-.1 2-1 2.6 0-30.3 0-60.5-.1-90.8 0-2.8.6-3.3 3.3-3.3 30.3.2 60.5.2 90.8.2zM107.2 0C48 0 0 48 0 107.2s48 107.2 107.2 107.2 107.2-48 107.2-107.2S166.4 0 107.2 0zM45.3 160.3l61.7-53.4 61.7 53.4H45.3zm61.7-53.5L45.3 53.4h123.4L107 106.8zM426.9 46H297.7s-22.6 25.2-22.4 60.9c.2 35.7 22.4 60.9 22.4 60.9h129s21.7-25.8 22.4-60.4C449.7 73 426.9 46 426.9 46zm-6 61.4c-.4 19.9-9.1 34.9-9.1 34.9h-99.3s-8.8-14.6-8.9-35.2c-.1-20.6 8.9-35.2 8.9-35.2h99.4s9.3 15.5 9 35.5zM454.3 46l70.6 60.9-70.6 60.9h38.4s6.7-.1 12.8-5.6c6.1-5.5 41.5-35.9 41.5-35.9l45.5 39.1s3 2.3 9.8 2.5 37.7 0 37.7 0L569.4 107 640 46h-38.3s-5.2-.9-12.7 5.5c-7.5 6.4-41.8 36.3-41.8 36.3l-44.7-38s-2.7-3.8-12.2-3.8c-9.5-.1-36 0-36 0zM806.8 71.9V46h-137s-22.6 25.2-22.4 60.9 22.4 60.9 22.4 60.9h137v-25.6H684.6s-5.4-8.9-7.8-22.6h120V92.9H677c2.5-12.8 7.6-21.1 7.6-21.1h122.2zM833.1 167.9V46h20.4s5.9-.2 10.7 3.4c4.7 3.6 107.4 82.5 107.4 82.5V46h28.3v121.8h-21.6s-5.6.4-10.3-3.4c-4.7-3.7-106.5-82-106.5-82v85.4l-28.4.1z', + viewBox: '0 0 1000 214.3', + ratio: 4, }, [SessionIconType.Pause]: { path: From b4477744ed1f804762afb16811db5b6d4aed10aa Mon Sep 17 00:00:00 2001 From: audric Date: Wed, 28 Jul 2021 17:25:20 +1000 Subject: [PATCH 25/30] fix login with password Fixes #1798 --- app/sql.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/sql.js b/app/sql.js index 24d3a5fd7..6e95708e5 100644 --- a/app/sql.js +++ b/app/sql.js @@ -153,7 +153,15 @@ function getSQLCipherIntegrityCheck(db) { function keyDatabase(db, key) { // https://www.zetetic.net/sqlcipher/sqlcipher-api/#key - db.pragma(`key = "x'${key}'"`); + // If the password isn't hex then we need to derive a key from it + + const deriveKey = HEX_KEY.test(key); + + const value = deriveKey ? `'${key}'` : `"x'${key}'"`; + + const pragramToRun = `key = ${value}`; + + db.pragma(pragramToRun); } function switchToWAL(db) { @@ -269,13 +277,7 @@ function openAndMigrateDatabase(filePath, key) { } } -const INVALID_KEY = /[^0-9A-Fa-f]/; function openAndSetUpSQLCipher(filePath, { key }) { - const match = INVALID_KEY.exec(key); - if (match) { - throw new Error(`setupSQLCipher: key '${key}' is not valid`); - } - return openAndMigrateDatabase(filePath, key); } From 68b62fa4c7ccd1c626bf3dcdda489fd5d9f950f9 Mon Sep 17 00:00:00 2001 From: audric Date: Wed, 28 Jul 2021 17:28:25 +1000 Subject: [PATCH 26/30] bump to 1.6.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 790ba6a51..dcb18ec7c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "session-desktop", "productName": "Session", "description": "Private messaging from your desktop", - "version": "1.6.8", + "version": "1.6.9", "license": "GPL-3.0", "author": { "name": "Loki Project", From 47e2f5726e5f77c2b14001a75ff1acf1d90aff34 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Thu, 29 Jul 2021 16:59:29 +1000 Subject: [PATCH 27/30] fix group key pair cache issue --- ts/receiver/closedGroups.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/receiver/closedGroups.ts b/ts/receiver/closedGroups.ts index 2f7305f85..a2a7f0c39 100644 --- a/ts/receiver/closedGroups.ts +++ b/ts/receiver/closedGroups.ts @@ -51,7 +51,7 @@ export async function getAllCachedECKeyPair(groupPubKey: string) { cacheOfClosedGroupKeyPairs.set(groupPubKey, keyPairsFound); } - return keyPairsFound; + return keyPairsFound.slice(); } /** From 99f862dd0f94d0ec65941126206e6cc3e511d10a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 30 Jul 2021 08:51:17 +1000 Subject: [PATCH 28/30] fix send link preview keep being shown Relates #1810 --- .../conversation/SessionCompositionBox.tsx | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/ts/components/session/conversation/SessionCompositionBox.tsx b/ts/components/session/conversation/SessionCompositionBox.tsx index 68c6d1a98..0f6c83c91 100644 --- a/ts/components/session/conversation/SessionCompositionBox.tsx +++ b/ts/components/session/conversation/SessionCompositionBox.tsx @@ -242,21 +242,23 @@ class SessionCompositionBoxInner extends React.Component { if (this.isURL(pastedText) && !window.getSettingValue('link-preview-setting', false)) { const alreadyDisplayedPopup = (await getItemById(hasLinkPreviewPopupBeenDisplayed))?.value || false; - window.inboxStore?.dispatch( - updateConfirmModal({ - shouldShowConfirm: - !window.getSettingValue('link-preview-setting') && !alreadyDisplayedPopup, - title: window.i18n('linkPreviewsTitle'), - message: window.i18n('linkPreviewsConfirmMessage'), - okTheme: SessionButtonColor.Danger, - onClickOk: () => { - window.setSettingValue('link-preview-setting', true); - }, - onClickClose: async () => { - await createOrUpdateItem({ id: hasLinkPreviewPopupBeenDisplayed, value: true }); - }, - }) - ); + if (!alreadyDisplayedPopup) { + window.inboxStore?.dispatch( + updateConfirmModal({ + shouldShowConfirm: + !window.getSettingValue('link-preview-setting') && !alreadyDisplayedPopup, + title: window.i18n('linkPreviewsTitle'), + message: window.i18n('linkPreviewsConfirmMessage'), + okTheme: SessionButtonColor.Danger, + onClickOk: () => { + window.setSettingValue('link-preview-setting', true); + }, + onClickClose: async () => { + await createOrUpdateItem({ id: hasLinkPreviewPopupBeenDisplayed, value: true }); + }, + }) + ); + } } } From 61277a5397c5ac90292be679ebd2491b8fec5d24 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 30 Jul 2021 08:55:46 +1000 Subject: [PATCH 29/30] fix replying to message focus composition box Relates #1808 --- ts/components/session/conversation/SessionCompositionBox.tsx | 5 +++++ ts/interactions/conversationInteractions.ts | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ts/components/session/conversation/SessionCompositionBox.tsx b/ts/components/session/conversation/SessionCompositionBox.tsx index 68c6d1a98..7bd0d0081 100644 --- a/ts/components/session/conversation/SessionCompositionBox.tsx +++ b/ts/components/session/conversation/SessionCompositionBox.tsx @@ -179,6 +179,11 @@ class SessionCompositionBoxInner extends React.Component { // if number of staged attachment changed, focus the composition box for a more natural UI this.focusCompositionBox(); } + + // focus the composition box when user clicks start to reply to a message + if (!_.isEqual(prevProps.quotedMessageProps, this.props.quotedMessageProps)) { + this.focusCompositionBox(); + } } public render() { diff --git a/ts/interactions/conversationInteractions.ts b/ts/interactions/conversationInteractions.ts index 0e9fb3964..d693dda3e 100644 --- a/ts/interactions/conversationInteractions.ts +++ b/ts/interactions/conversationInteractions.ts @@ -41,10 +41,9 @@ import { import { getDecryptedMediaUrl } from '../session/crypto/DecryptedAttachmentsManager'; import { IMAGE_JPEG } from '../types/MIME'; import { FSv2 } from '../fileserver'; -import { fromBase64ToArray, fromHexToArray, toHex } from '../session/utils/String'; +import { fromHexToArray, toHex } from '../session/utils/String'; import { SessionButtonColor } from '../components/session/SessionButton'; import { perfEnd, perfStart } from '../session/utils/Performance'; -import { ReplyingToMessageProps } from '../components/session/conversation/SessionCompositionBox'; export const getCompleteUrlForV2ConvoId = async (convoId: string) => { if (convoId.match(openGroupV2ConversationIdRegex)) { From 7c3182392bafcf2f01087d90a21634addd54049d Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 30 Jul 2021 09:07:18 +1000 Subject: [PATCH 30/30] bump electron-builder to 22.8.0 --- package.json | 2 +- yarn.lock | 320 ++++++++++++++++++++++++++++----------------------- 2 files changed, 176 insertions(+), 146 deletions(-) diff --git a/package.json b/package.json index dcb18ec7c..54d2c8ada 100644 --- a/package.json +++ b/package.json @@ -177,7 +177,7 @@ "css-loader": "^3.6.0", "dashdash": "1.14.1", "electron": "8.2.0", - "electron-builder": "22.3.6", + "electron-builder": "22.8.0", "electron-icon-maker": "0.0.3", "electron-notarize": "^0.2.0", "eslint": "4.14.0", diff --git a/yarn.lock b/yarn.lock index 7f71618c5..16f7c9d54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -175,13 +175,13 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@develar/schema-utils@~2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.1.0.tgz#eceb1695bfbed6f6bb84666d5d3abe5e1fd54e17" - integrity sha512-qjCqB4ctMig9Gz5bd6lkdFr3bO6arOdQqptdBSpF1ZpCnjofieCciEzkoS9ujY9cMGyllYSCSmBJ3x9OKHXzoA== +"@develar/schema-utils@~2.6.5": + version "2.6.5" + resolved "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.6.5.tgz#3ece22c5838402419a6e0425f85742b961d9b6c6" + integrity sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig== dependencies: - ajv "^6.1.0" - ajv-keywords "^3.1.0" + ajv "^6.12.0" + ajv-keywords "^3.4.1" "@discoveryjs/json-ext@^0.5.0": version "0.5.3" @@ -514,10 +514,10 @@ dependencies: "@types/node" "*" -"@types/fs-extra@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.0.tgz#1114834b53c3914806cd03b3304b37b3bd221a4d" - integrity sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg== +"@types/fs-extra@^9.0.1": + version "9.0.12" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.12.tgz#9b8f27973df8a7a3920e8461517ebf8a7d4fdfaf" + integrity sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw== dependencies: "@types/node" "*" @@ -877,10 +877,10 @@ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== -"@types/yargs@^15.0.4": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.4.tgz#7e5d0f8ca25e9d5849f2ea443cf7c402decd8299" - integrity sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg== +"@types/yargs@^15.0.5": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== dependencies: "@types/yargs-parser" "*" @@ -1245,7 +1245,7 @@ ajv@^5.3.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ajv@^6.0.1, ajv@^6.12.5: +ajv@^6.0.1, ajv@^6.12.0, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1367,37 +1367,37 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -app-builder-bin@3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.4.tgz#2caa9a95358e1f02b7fed5ac47613ab878328de2" - integrity sha512-Bta3I+OU64ePwvSdhpYyCj11XcR8VGdlPSINM87LPg0apCbprLu03zvnmnHRw/RvZB2RGAQ93Z8NO3JT3DbXdA== +app-builder-bin@3.5.9: + version "3.5.9" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.9.tgz#a3ac0c25286bac68357321cb2eaf7128b0bc0a4f" + integrity sha512-NSjtqZ3x2kYiDp3Qezsgukx/AUzKPr3Xgf9by4cYt05ILWGAptepeeu0Uv+7MO+41o6ujhLixTou8979JGg2Kg== -app-builder-lib@22.3.6, app-builder-lib@~22.3.6: - version "22.3.6" - resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.3.6.tgz#982c5be22664123a7535bc29624180371f8d5333" - integrity sha512-9TANMAFL7cFNuRB3cMc1BS5dBQzqY5RVEUD4VMZ0MYhFY/DM9+v2BvfY3Ef+7XSOzirA6p4TljAVz5ydIEdZFw== +app-builder-lib@22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.8.0.tgz#342a8976f50ae35cfd07412dbfd4f6c895b32eac" + integrity sha512-RGaIRjCUrqkmh6QOGsyekQPEOaVynHfmeh8JZuyUymFYUOFdzBbPamkA2nhBVBTkkgfjRHsxK7LhedFKPzvWEQ== dependencies: "7zip-bin" "~5.0.3" - "@develar/schema-utils" "~2.1.0" + "@develar/schema-utils" "~2.6.5" async-exit-hook "^2.0.1" bluebird-lst "^1.0.9" - builder-util "22.3.6" - builder-util-runtime "8.6.1" + builder-util "22.8.0" + builder-util-runtime "8.7.2" chromium-pickle-js "^0.2.0" debug "^4.1.1" - ejs "^3.0.1" - electron-publish "22.3.6" - fs-extra "^8.1.0" - hosted-git-info "^3.0.4" + ejs "^3.1.3" + electron-publish "22.8.0" + fs-extra "^9.0.1" + hosted-git-info "^3.0.5" is-ci "^2.0.0" - isbinaryfile "^4.0.4" - js-yaml "^3.13.1" + isbinaryfile "^4.0.6" + js-yaml "^3.14.0" lazy-val "^1.0.4" minimatch "^3.0.4" normalize-package-data "^2.5.0" - read-config-file "5.0.2" + read-config-file "6.0.0" sanitize-filename "^1.6.3" - semver "^7.1.3" + semver "^7.3.2" temp-file "^3.3.7" aproba@^1.0.3: @@ -1585,6 +1585,11 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async@0.9.x, async@~0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + async@^1.5.0, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -1597,11 +1602,6 @@ async@^2.0.0, async@^2.6.2: dependencies: lodash "^4.17.14" -async@~0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1976,14 +1976,6 @@ buffers@~0.1.1: resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s= -builder-util-runtime@8.6.1: - version "8.6.1" - resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.6.1.tgz#cf9a268fa51704de24f3c085aa8d1d1b3767d9ea" - integrity sha512-gwIUtMaICmc+e2EC3u3byXcwCyfhtG40LJRNnGfs8AYqacKl4ZLP50ab+uDttn7QAXe0LfMAuKz9v8bCODV0yg== - dependencies: - debug "^4.1.1" - sax "^1.2.4" - builder-util-runtime@8.6.2: version "8.6.2" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.6.2.tgz#8270e15b012d8d3b110f3e327b0fd8b0e07b1686" @@ -1992,23 +1984,31 @@ builder-util-runtime@8.6.2: debug "^4.1.1" sax "^1.2.4" -builder-util@22.3.6, builder-util@~22.3.6: - version "22.3.6" - resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.3.6.tgz#a1941eec1606cf079d94c1e474109949a39818a9" - integrity sha512-1fMRRouGzggUcPcy/ZR2NV8KZejwXPYNRD4vr/Ws/KvGQFNMTHA9VFscT7tGfOseQCLaLsa5C2gU5MOAiFx7AA== +builder-util-runtime@8.7.2: + version "8.7.2" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.2.tgz#d93afc71428a12789b437e13850e1fa7da956d72" + integrity sha512-xBqv+8bg6cfnzAQK1k3OGpfaHg+QkPgIgpEkXNhouZ0WiUkyZCftuRc2LYzQrLucFywpa14Xbc6+hTbpq83yRA== + dependencies: + debug "^4.1.1" + sax "^1.2.4" + +builder-util@22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.8.0.tgz#01684085d1f2370b1bd182f69cbd007426f63f64" + integrity sha512-H80P1JzVy3TGpi63x81epQDK24XalL034+jAZlrPb5IhLtYmnNNdxCCAVJvg3VjSISd73Y71O+uhqCxWpqbPHw== dependencies: "7zip-bin" "~5.0.3" "@types/debug" "^4.1.5" - "@types/fs-extra" "^8.1.0" - app-builder-bin "3.5.4" + "@types/fs-extra" "^9.0.1" + app-builder-bin "3.5.9" bluebird-lst "^1.0.9" - builder-util-runtime "8.6.1" - chalk "^3.0.0" + builder-util-runtime "8.7.2" + chalk "^4.1.0" debug "^4.1.1" - fs-extra "^8.1.0" + fs-extra "^9.0.1" is-ci "^2.0.0" - js-yaml "^3.13.1" - source-map-support "^0.5.16" + js-yaml "^3.14.0" + source-map-support "^0.5.19" stat-mode "^1.0.0" temp-file "^3.3.7" @@ -3104,17 +3104,16 @@ diff@^4.0.2: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -dmg-builder@22.3.6: - version "22.3.6" - resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.3.6.tgz#2affc0bfb29a49eb35c11d91e5bf7ba32c140fbc" - integrity sha512-pUrvvzkSZfaCIXofqNH+YJ0ajgi4DDe/ZjMiL/T1yKrRXK3v7sfmnbSzHY8V/WtimSgzsK1izFg/SBsfwFsZWw== +dmg-builder@22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.8.0.tgz#2b17127837ed444db3086317eda5cf8912f6e6a9" + integrity sha512-orePWjcrl97SYLA8F/6UUtbXJSoZCYu5KOP1lVqD4LOomr8bjGDyEVYZmZYcg5WqKmXucdmO6OpqgzH/aRMMuA== dependencies: - app-builder-lib "~22.3.6" - bluebird-lst "^1.0.9" - builder-util "~22.3.6" - fs-extra "^8.1.0" - iconv-lite "^0.5.1" - js-yaml "^3.13.1" + app-builder-lib "22.8.0" + builder-util "22.8.0" + fs-extra "^9.0.1" + iconv-lite "^0.6.2" + js-yaml "^3.14.0" sanitize-filename "^1.6.3" dns-equal@^1.0.0: @@ -3225,35 +3224,37 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -ejs@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.0.1.tgz#30c8f6ee9948502cc32e85c37a3f8b39b5a614a5" - integrity sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw== +ejs@^3.1.3: + version "3.1.6" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a" + integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw== + dependencies: + jake "^10.6.1" ejs@~2.5.6: version "2.5.9" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.9.tgz#7ba254582a560d267437109a68354112475b0ce5" integrity sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ== -electron-builder@22.3.6: - version "22.3.6" - resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.3.6.tgz#690667b5f70e27edc54a84442e9b2440dac51c28" - integrity sha512-W1fMEtAT7WOqetwTR2uCesMIqmnr8DHR9ZKYlHMxGxQt0jGaBX/gQHPf6+R8d2SQq2Bup6e1eE0xoeX3ixCfTw== +electron-builder@22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.8.0.tgz#d2c9fc5438c834e41fd794a271fca200165a3bad" + integrity sha512-dUv4F3srJouqxhWivtKqSoQP4Df6vYgjooGdzms+iYMTFi9f0b4LlEbr7kgsPvte8zAglee7VOGOODkCRJDkUQ== dependencies: - "@types/yargs" "^15.0.4" - app-builder-lib "22.3.6" + "@types/yargs" "^15.0.5" + app-builder-lib "22.8.0" bluebird-lst "^1.0.9" - builder-util "22.3.6" - builder-util-runtime "8.6.1" - chalk "^3.0.0" - dmg-builder "22.3.6" - fs-extra "^8.1.0" + builder-util "22.8.0" + builder-util-runtime "8.7.2" + chalk "^4.1.0" + dmg-builder "22.8.0" + fs-extra "^9.0.1" is-ci "^2.0.0" lazy-val "^1.0.4" - read-config-file "5.0.2" + read-config-file "6.0.0" sanitize-filename "^1.6.3" update-notifier "^4.1.0" - yargs "^15.1.0" + yargs "^15.3.1" electron-chromedriver@^8.0.0: version "8.0.0" @@ -3315,19 +3316,19 @@ electron-notarize@^0.2.0: debug "^4.1.1" fs-extra "^8.1.0" -electron-publish@22.3.6: - version "22.3.6" - resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.3.6.tgz#97500b832d5b281785882100d7c01dbf55dabd03" - integrity sha512-u4PW4ec4rPcdFUVMvL5OrqoYX8WLJHab8DtPkh/oZ2HPzGGX3eWnUvulIIJ4SUnesSYkbUcZd1RDYtfV52Q72w== +electron-publish@22.8.0: + version "22.8.0" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.8.0.tgz#7f410fe043abc5d3d896c4ee9eea7a43ea352c7d" + integrity sha512-uM0Zdi9hUqqGOrPj478v7toTvV1Kgto1w11rIiI168batiXAJvNLD8VZRfehOrZT0ibUyZlw8FtxoGCrjyHUOw== dependencies: - "@types/fs-extra" "^8.1.0" + "@types/fs-extra" "^9.0.1" bluebird-lst "^1.0.9" - builder-util "~22.3.6" - builder-util-runtime "8.6.1" - chalk "^3.0.0" - fs-extra "^8.1.0" + builder-util "22.8.0" + builder-util-runtime "8.7.2" + chalk "^4.1.0" + fs-extra "^9.0.1" lazy-val "^1.0.4" - mime "^2.4.4" + mime "^2.4.6" electron-to-chromium@^1.3.723: version "1.3.769" @@ -4059,6 +4060,13 @@ file-url@^2.0.0: resolved "https://registry.yarnpkg.com/file-url/-/file-url-2.0.2.tgz#e951784d79095127d3713029ab063f40818ca2ae" integrity sha1-6VF4TXkJUSfTcTApqwY/QIGMoq4= +filelist@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b" + integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ== + dependencies: + minimatch "^3.0.4" + filesize@3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" @@ -4249,6 +4257,16 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.0.1: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -4855,12 +4873,12 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -hosted-git-info@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.4.tgz#be4973eb1fd2737b11c9c7c19380739bb249f60d" - integrity sha512-4oT62d2jwSDBbLLFLZE+1vPuQ1h8p9wjrJ8Mqx5TjsyWmBMV5B13eJqn8pvluqubLf3cJPTfiYCIwNwDNmzScQ== +hosted-git-info@^3.0.5: + version "3.0.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.8.tgz#6e35d4cc87af2c5f816e4cb9ce350ba87a3f370d" + integrity sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw== dependencies: - lru-cache "^5.1.1" + lru-cache "^6.0.0" hosted-git-info@^4.0.1: version "4.0.2" @@ -5010,12 +5028,12 @@ iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.1.tgz#b2425d3c7b18f7219f2ca663d103bddb91718d64" - integrity sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q== +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: - safer-buffer ">= 2.1.2 < 3" + safer-buffer ">= 2.1.2 < 3.0.0" icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" @@ -5512,10 +5530,10 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isbinaryfile@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.4.tgz#6803f81a8944201c642b6e17da041e24deb78712" - integrity sha512-pEutbN134CzcjlLS1myKX/uxNjwU5eBVSprvkpv3+3dqhBHUZLIWJQowC40w5c0Zf19vBY8mrZl88y5J4RAPbQ== +isbinaryfile@^4.0.6: + version "4.0.8" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.8.tgz#5d34b94865bd4946633ecc78a026fc76c5b11fcf" + integrity sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w== isexe@^2.0.0: version "2.0.0" @@ -5539,6 +5557,16 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +jake@^10.6.1: + version "10.8.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" + integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A== + dependencies: + async "0.9.x" + chalk "^2.4.2" + filelist "^1.0.1" + minimatch "^3.0.4" + jest-worker@^27.0.2: version "27.0.6" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.6.tgz#a5fdb1e14ad34eb228cfe162d9f729cdbfa28aed" @@ -5608,6 +5636,14 @@ js-yaml@^3.13.1, js-yaml@^3.2.7: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.14.0: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^3.9.1: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" @@ -5701,10 +5737,10 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.2.tgz#43ef1f0af9835dd624751a6b7fa48874fb2d608e" - integrity sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ== +json5@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== dependencies: minimist "^1.2.5" @@ -6134,13 +6170,6 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -6334,6 +6363,11 @@ mime@^2.4.4: resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== +mime@^2.4.6: + version "2.5.2" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" + integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" @@ -7950,16 +7984,15 @@ read-chunk@^1.0.1: resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-1.0.1.tgz#5f68cab307e663f19993527d9b589cace4661194" integrity sha1-X2jKswfmY/GZk1J9m1icrORmEZQ= -read-config-file@5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-5.0.2.tgz#55e005e5a447a9ce5806358d7b22cb7cefb6436d" - integrity sha512-tVt1lsiSjs+FtL/vtfCivqtKR1UNk3BB3uPJQvJqkgtAYDvZjo0xyXFYSVmzaTcO+Jdi5G7O2K2vDV+p1M/oug== +read-config-file@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-6.0.0.tgz#224b5dca6a5bdc1fb19e63f89f342680efdb9299" + integrity sha512-PHjROSdpceKUmqS06wqwP92VrM46PZSTubmNIMJ5DrMwg1OgenSTSEHIkCa6TiOJ+y/J0xnG1fFwG3M+Oi1aNA== dependencies: dotenv "^8.2.0" dotenv-expand "^5.1.0" - fs-extra "^8.1.0" js-yaml "^3.13.1" - json5 "^2.1.1" + json5 "^2.1.2" lazy-val "^1.0.4" read-last-lines@1.3.0: @@ -8476,7 +8509,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -8858,15 +8891,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.16: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@~0.5.19: +source-map-support@^0.5.19, source-map-support@~0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -9855,6 +9880,11 @@ universalify@^1.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -10445,10 +10475,10 @@ yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.1: - version "18.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.1.tgz#bf7407b915427fc760fcbbccc6c82b4f0ffcbd37" - integrity sha512-KRHEsOM16IX7XuLnMOqImcPNbLVXMNHYAoFc3BKR8Ortl5gzDbtXvvEoGx9imk5E+X1VeNKNlcHr8B8vi+7ipA== +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -10481,10 +10511,10 @@ yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^15.1.0: - version "15.3.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" - integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== +yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" decamelize "^1.2.0" @@ -10496,7 +10526,7 @@ yargs@^15.1.0: string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^18.1.1" + yargs-parser "^18.1.2" yargs@^6.5.0: version "6.6.0"