Parallelize SQL queries
This commit is contained in:
parent
86b4da1ec2
commit
c64762858e
178 changed files with 3377 additions and 3618 deletions
|
@ -2513,18 +2513,6 @@ Signal Desktop makes use of the following open source projects.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
## p-props
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
## p-queue
|
## p-queue
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
|
@ -68,11 +68,11 @@ async function cleanupOrphanedAttachments({
|
||||||
}: CleanupOrphanedAttachmentsOptionsType): Promise<void> {
|
}: CleanupOrphanedAttachmentsOptionsType): Promise<void> {
|
||||||
await deleteAllBadges({
|
await deleteAllBadges({
|
||||||
userDataPath,
|
userDataPath,
|
||||||
pathsToKeep: await sql.sqlCall('getAllBadgeImageFileLocalPaths'),
|
pathsToKeep: await sql.sqlRead('getAllBadgeImageFileLocalPaths'),
|
||||||
});
|
});
|
||||||
|
|
||||||
const allStickers = await getAllStickers(userDataPath);
|
const allStickers = await getAllStickers(userDataPath);
|
||||||
const orphanedStickers = await sql.sqlCall(
|
const orphanedStickers = await sql.sqlWrite(
|
||||||
'removeKnownStickers',
|
'removeKnownStickers',
|
||||||
allStickers
|
allStickers
|
||||||
);
|
);
|
||||||
|
@ -82,7 +82,7 @@ async function cleanupOrphanedAttachments({
|
||||||
});
|
});
|
||||||
|
|
||||||
const allDraftAttachments = await getAllDraftAttachments(userDataPath);
|
const allDraftAttachments = await getAllDraftAttachments(userDataPath);
|
||||||
const orphanedDraftAttachments = await sql.sqlCall(
|
const orphanedDraftAttachments = await sql.sqlWrite(
|
||||||
'removeKnownDraftAttachments',
|
'removeKnownDraftAttachments',
|
||||||
allDraftAttachments
|
allDraftAttachments
|
||||||
);
|
);
|
||||||
|
@ -100,7 +100,7 @@ async function cleanupOrphanedAttachments({
|
||||||
);
|
);
|
||||||
|
|
||||||
{
|
{
|
||||||
const attachments: ReadonlyArray<string> = await sql.sqlCall(
|
const attachments: ReadonlyArray<string> = await sql.sqlRead(
|
||||||
'getKnownConversationAttachments'
|
'getKnownConversationAttachments'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ function deleteOrphanedAttachments({
|
||||||
let attachments: ReadonlyArray<string>;
|
let attachments: ReadonlyArray<string>;
|
||||||
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
({ attachments, cursor } = await sql.sqlCall(
|
({ attachments, cursor } = await sql.sqlRead(
|
||||||
'getKnownMessageAttachments',
|
'getKnownMessageAttachments',
|
||||||
cursor
|
cursor
|
||||||
));
|
));
|
||||||
|
@ -166,7 +166,7 @@ function deleteOrphanedAttachments({
|
||||||
} while (cursor !== undefined && !cursor.done);
|
} while (cursor !== undefined && !cursor.done);
|
||||||
} finally {
|
} finally {
|
||||||
if (cursor !== undefined) {
|
if (cursor !== undefined) {
|
||||||
await sql.sqlCall('finishGetKnownMessageAttachments', cursor);
|
await sql.sqlRead('finishGetKnownMessageAttachments', cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
app/main.ts
16
app/main.ts
|
@ -396,14 +396,14 @@ async function getLocaleOverrideSetting(): Promise<string | null> {
|
||||||
|
|
||||||
const zoomFactorService = new ZoomFactorService({
|
const zoomFactorService = new ZoomFactorService({
|
||||||
async getZoomFactorSetting() {
|
async getZoomFactorSetting() {
|
||||||
const item = await sql.sqlCall('getItemById', 'zoomFactor');
|
const item = await sql.sqlRead('getItemById', 'zoomFactor');
|
||||||
if (typeof item?.value !== 'number') {
|
if (typeof item?.value !== 'number') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return item.value;
|
return item.value;
|
||||||
},
|
},
|
||||||
async setZoomFactorSetting(zoomFactor) {
|
async setZoomFactorSetting(zoomFactor) {
|
||||||
await sql.sqlCall('createOrUpdateItem', {
|
await sql.sqlWrite('createOrUpdateItem', {
|
||||||
id: 'zoomFactor',
|
id: 'zoomFactor',
|
||||||
value: zoomFactor,
|
value: zoomFactor,
|
||||||
});
|
});
|
||||||
|
@ -1433,8 +1433,8 @@ async function showSettingsWindow() {
|
||||||
|
|
||||||
async function getIsLinked() {
|
async function getIsLinked() {
|
||||||
try {
|
try {
|
||||||
const number = await sql.sqlCall('getItemById', 'number_id');
|
const number = await sql.sqlRead('getItemById', 'number_id');
|
||||||
const password = await sql.sqlCall('getItemById', 'password');
|
const password = await sql.sqlRead('getItemById', 'password');
|
||||||
return Boolean(number && password);
|
return Boolean(number && password);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1686,7 +1686,7 @@ async function initializeSQL(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// This should be the first awaited call in this function, otherwise
|
// This should be the first awaited call in this function, otherwise
|
||||||
// `sql.sqlCall` will throw an uninitialized error instead of waiting for
|
// `sql.sqlRead` will throw an uninitialized error instead of waiting for
|
||||||
// init to finish.
|
// init to finish.
|
||||||
await sql.initialize({
|
await sql.initialize({
|
||||||
appVersion: app.getVersion(),
|
appVersion: app.getVersion(),
|
||||||
|
@ -2154,10 +2154,10 @@ app.on('ready', async () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const IDB_KEY = 'indexeddb-delete-needed';
|
const IDB_KEY = 'indexeddb-delete-needed';
|
||||||
const item = await sql.sqlCall('getItemById', IDB_KEY);
|
const item = await sql.sqlRead('getItemById', IDB_KEY);
|
||||||
if (item && item.value) {
|
if (item && item.value) {
|
||||||
await sql.sqlCall('removeIndexedDBFiles');
|
await sql.sqlWrite('removeIndexedDBFiles');
|
||||||
await sql.sqlCall('removeItemById', IDB_KEY);
|
await sql.sqlWrite('removeItemById', IDB_KEY);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
getLogger().error(
|
getLogger().error(
|
||||||
|
|
|
@ -7,14 +7,22 @@ import type { MainSQL } from '../ts/sql/main';
|
||||||
import { remove as removeUserConfig } from './user_config';
|
import { remove as removeUserConfig } from './user_config';
|
||||||
import { remove as removeEphemeralConfig } from './ephemeral_config';
|
import { remove as removeEphemeralConfig } from './ephemeral_config';
|
||||||
|
|
||||||
let sql: Pick<MainSQL, 'sqlCall'> | undefined;
|
let sql:
|
||||||
|
| Pick<
|
||||||
|
MainSQL,
|
||||||
|
'sqlRead' | 'sqlWrite' | 'pauseWriteAccess' | 'resumeWriteAccess'
|
||||||
|
>
|
||||||
|
| undefined;
|
||||||
|
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
|
|
||||||
const SQL_CHANNEL_KEY = 'sql-channel';
|
const SQL_READ_KEY = 'sql-channel:read';
|
||||||
|
const SQL_WRITE_KEY = 'sql-channel:write';
|
||||||
const ERASE_SQL_KEY = 'erase-sql-key';
|
const ERASE_SQL_KEY = 'erase-sql-key';
|
||||||
|
const PAUSE_WRITE_ACCESS = 'pause-sql-writes';
|
||||||
|
const RESUME_WRITE_ACCESS = 'resume-sql-writes';
|
||||||
|
|
||||||
export function initialize(mainSQL: Pick<MainSQL, 'sqlCall'>): void {
|
export function initialize(mainSQL: typeof sql): void {
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
throw new Error('sqlChannels: already initialized!');
|
throw new Error('sqlChannels: already initialized!');
|
||||||
}
|
}
|
||||||
|
@ -22,15 +30,36 @@ export function initialize(mainSQL: Pick<MainSQL, 'sqlCall'>): void {
|
||||||
|
|
||||||
sql = mainSQL;
|
sql = mainSQL;
|
||||||
|
|
||||||
ipcMain.handle(SQL_CHANNEL_KEY, (_event, callName, ...args) => {
|
ipcMain.handle(SQL_READ_KEY, (_event, callName, ...args) => {
|
||||||
if (!sql) {
|
if (!sql) {
|
||||||
throw new Error(`${SQL_CHANNEL_KEY}: Not yet initialized!`);
|
throw new Error(`${SQL_READ_KEY}: Not yet initialized!`);
|
||||||
}
|
}
|
||||||
return sql.sqlCall(callName, ...args);
|
return sql.sqlRead(callName, ...args);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(SQL_WRITE_KEY, (_event, callName, ...args) => {
|
||||||
|
if (!sql) {
|
||||||
|
throw new Error(`${SQL_WRITE_KEY}: Not yet initialized!`);
|
||||||
|
}
|
||||||
|
return sql.sqlWrite(callName, ...args);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle(ERASE_SQL_KEY, () => {
|
ipcMain.handle(ERASE_SQL_KEY, () => {
|
||||||
removeUserConfig();
|
removeUserConfig();
|
||||||
removeEphemeralConfig();
|
removeEphemeralConfig();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(PAUSE_WRITE_ACCESS, () => {
|
||||||
|
if (!sql) {
|
||||||
|
throw new Error(`${PAUSE_WRITE_ACCESS}: Not yet initialized!`);
|
||||||
|
}
|
||||||
|
return sql.pauseWriteAccess();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(RESUME_WRITE_ACCESS, () => {
|
||||||
|
if (!sql) {
|
||||||
|
throw new Error(`${PAUSE_WRITE_ACCESS}: Not yet initialized!`);
|
||||||
|
}
|
||||||
|
return sql.resumeWriteAccess();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
32
package-lock.json
generated
32
package-lock.json
generated
|
@ -70,7 +70,6 @@
|
||||||
"nop": "1.0.0",
|
"nop": "1.0.0",
|
||||||
"normalize-path": "3.0.0",
|
"normalize-path": "3.0.0",
|
||||||
"p-map": "2.1.0",
|
"p-map": "2.1.0",
|
||||||
"p-props": "4.0.0",
|
|
||||||
"p-queue": "6.6.2",
|
"p-queue": "6.6.2",
|
||||||
"p-timeout": "4.1.0",
|
"p-timeout": "4.1.0",
|
||||||
"parchment": "1.1.4",
|
"parchment": "1.1.4",
|
||||||
|
@ -12652,6 +12651,7 @@
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz",
|
||||||
"integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==",
|
"integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clean-stack": "^2.0.0",
|
"clean-stack": "^2.0.0",
|
||||||
"indent-string": "^4.0.0"
|
"indent-string": "^4.0.0"
|
||||||
|
@ -15491,6 +15491,7 @@
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||||
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
|
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
|
||||||
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
|
@ -22852,6 +22853,7 @@
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
||||||
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
|
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
|
||||||
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
|
@ -28836,34 +28838,6 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/p-props": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-props/-/p-props-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-3iKFbPdoPG7Ne3cMA53JnjPsTMaIzE9gxKZnvKJJivTAeqLEZPBu6zfi6DYq9AsH1nYycWmo3sWCNI8Kz6T2Zg==",
|
|
||||||
"dependencies": {
|
|
||||||
"p-map": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/p-props/node_modules/p-map": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"aggregate-error": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/p-queue": {
|
"node_modules/p-queue": {
|
||||||
"version": "6.6.2",
|
"version": "6.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
|
||||||
|
|
|
@ -152,7 +152,6 @@
|
||||||
"nop": "1.0.0",
|
"nop": "1.0.0",
|
||||||
"normalize-path": "3.0.0",
|
"normalize-path": "3.0.0",
|
||||||
"p-map": "2.1.0",
|
"p-map": "2.1.0",
|
||||||
"p-props": "4.0.0",
|
|
||||||
"p-queue": "6.6.2",
|
"p-queue": "6.6.2",
|
||||||
"p-timeout": "4.1.0",
|
"p-timeout": "4.1.0",
|
||||||
"parchment": "1.1.4",
|
"parchment": "1.1.4",
|
||||||
|
|
10
test/test.js
10
test/test.js
|
@ -8,14 +8,6 @@
|
||||||
mocha.setup('bdd');
|
mocha.setup('bdd');
|
||||||
mocha.setup({ timeout: 10000 });
|
mocha.setup({ timeout: 10000 });
|
||||||
|
|
||||||
function deleteIndexedDB() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const idbReq = indexedDB.deleteDatabase('test');
|
|
||||||
idbReq.onsuccess = resolve;
|
|
||||||
idbReq.error = reject;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.Events = {
|
window.Events = {
|
||||||
getThemeSetting: () => 'light',
|
getThemeSetting: () => 'light',
|
||||||
};
|
};
|
||||||
|
@ -23,8 +15,6 @@ window.Events = {
|
||||||
/* Delete the database before running any tests */
|
/* Delete the database before running any tests */
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await window.testUtilities.initialize();
|
await window.testUtilities.initialize();
|
||||||
await deleteIndexedDB();
|
|
||||||
await window.Signal.Data.removeAll();
|
|
||||||
await window.storage.fetch();
|
await window.storage.fetch();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
3
ts/CI.ts
3
ts/CI.ts
|
@ -7,7 +7,7 @@ import type { IPCResponse as ChallengeResponseType } from './challenge';
|
||||||
import type { MessageAttributesType } from './model-types.d';
|
import type { MessageAttributesType } from './model-types.d';
|
||||||
import * as log from './logging/log';
|
import * as log from './logging/log';
|
||||||
import { explodePromise } from './util/explodePromise';
|
import { explodePromise } from './util/explodePromise';
|
||||||
import { ipcInvoke } from './sql/channels';
|
import { AccessType, ipcInvoke } from './sql/channels';
|
||||||
import { backupsService } from './services/backups';
|
import { backupsService } from './services/backups';
|
||||||
import { SECOND } from './util/durations';
|
import { SECOND } from './util/durations';
|
||||||
import { isSignalRoute } from './util/signalRoutes';
|
import { isSignalRoute } from './util/signalRoutes';
|
||||||
|
@ -128,6 +128,7 @@ export function getCI({ deviceName, backupData }: GetCIOptionsType): CIType {
|
||||||
|
|
||||||
async function getMessagesBySentAt(sentAt: number) {
|
async function getMessagesBySentAt(sentAt: number) {
|
||||||
const messages = await ipcInvoke<ReadonlyArray<MessageAttributesType>>(
|
const messages = await ipcInvoke<ReadonlyArray<MessageAttributesType>>(
|
||||||
|
AccessType.Read,
|
||||||
'getMessagesBySentAt',
|
'getMessagesBySentAt',
|
||||||
[sentAt]
|
[sentAt]
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { v4 as uuid } from 'uuid';
|
||||||
import { incrementMessageCounter } from '../util/incrementMessageCounter';
|
import { incrementMessageCounter } from '../util/incrementMessageCounter';
|
||||||
import { ReadStatus } from '../messages/MessageReadStatus';
|
import { ReadStatus } from '../messages/MessageReadStatus';
|
||||||
import { SendStatus } from '../messages/MessageSendState';
|
import { SendStatus } from '../messages/MessageSendState';
|
||||||
|
import { DataWriter } from '../sql/Client';
|
||||||
import { BodyRange } from '../types/BodyRange';
|
import { BodyRange } from '../types/BodyRange';
|
||||||
import { strictAssert } from '../util/assert';
|
import { strictAssert } from '../util/assert';
|
||||||
import { MINUTE } from '../util/durations';
|
import { MINUTE } from '../util/durations';
|
||||||
|
@ -86,13 +87,13 @@ export async function populateConversationWithMessages({
|
||||||
timestamp += 1;
|
timestamp += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
await window.Signal.Data.saveMessages(messages, {
|
await DataWriter.saveMessages(messages, {
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
ourAci,
|
ourAci,
|
||||||
});
|
});
|
||||||
|
|
||||||
conversation.set('active_at', Date.now());
|
conversation.set('active_at', Date.now());
|
||||||
await window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
log.info(`${logId}: populating conversation complete`);
|
log.info(`${logId}: populating conversation complete`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import type {
|
||||||
} from './model-types.d';
|
} from './model-types.d';
|
||||||
import type { ConversationModel } from './models/conversations';
|
import type { ConversationModel } from './models/conversations';
|
||||||
|
|
||||||
import dataInterface from './sql/Client';
|
import { DataReader, DataWriter } from './sql/Client';
|
||||||
import * as log from './logging/log';
|
import * as log from './logging/log';
|
||||||
import * as Errors from './types/errors';
|
import * as Errors from './types/errors';
|
||||||
import { getAuthorId } from './messages/helpers';
|
import { getAuthorId } from './messages/helpers';
|
||||||
|
@ -127,11 +127,15 @@ const {
|
||||||
getAllConversations,
|
getAllConversations,
|
||||||
getAllGroupsInvolvingServiceId,
|
getAllGroupsInvolvingServiceId,
|
||||||
getMessagesBySentAt,
|
getMessagesBySentAt,
|
||||||
|
} = DataReader;
|
||||||
|
|
||||||
|
const {
|
||||||
migrateConversationMessages,
|
migrateConversationMessages,
|
||||||
removeConversation,
|
removeConversation,
|
||||||
saveConversation,
|
saveConversation,
|
||||||
updateConversation,
|
updateConversation,
|
||||||
} = dataInterface;
|
updateConversations,
|
||||||
|
} = DataWriter;
|
||||||
|
|
||||||
// We have to run this in background.js, after all backbone models and collections on
|
// We have to run this in background.js, after all backbone models and collections on
|
||||||
// Whisper.* have been created. Once those are in typescript we can use more reasonable
|
// Whisper.* have been created. Once those are in typescript we can use more reasonable
|
||||||
|
@ -443,12 +447,12 @@ export class ConversationController {
|
||||||
conversation.set({
|
conversation.set({
|
||||||
profileAvatar: { hash: SIGNAL_AVATAR_PATH, path: SIGNAL_AVATAR_PATH },
|
profileAvatar: { hash: SIGNAL_AVATAR_PATH, path: SIGNAL_AVATAR_PATH },
|
||||||
});
|
});
|
||||||
updateConversation(conversation.attributes);
|
await updateConversation(conversation.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conversation.get('profileName')) {
|
if (!conversation.get('profileName')) {
|
||||||
conversation.set({ profileName: 'Signal' });
|
conversation.set({ profileName: 'Signal' });
|
||||||
updateConversation(conversation.attributes);
|
await updateConversation(conversation.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._signalConversationId = conversation.id;
|
this._signalConversationId = conversation.id;
|
||||||
|
@ -934,7 +938,7 @@ export class ConversationController {
|
||||||
);
|
);
|
||||||
|
|
||||||
existing.set({ e164: undefined });
|
existing.set({ e164: undefined });
|
||||||
updateConversation(existing.attributes);
|
drop(updateConversation(existing.attributes));
|
||||||
|
|
||||||
byE164[e164] = conversation;
|
byE164[e164] = conversation;
|
||||||
|
|
||||||
|
@ -1144,7 +1148,7 @@ export class ConversationController {
|
||||||
group.set({
|
group.set({
|
||||||
members: currentAdded,
|
members: currentAdded,
|
||||||
});
|
});
|
||||||
updateConversation(group.attributes);
|
drop(updateConversation(group.attributes));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1337,7 +1341,7 @@ export class ConversationController {
|
||||||
);
|
);
|
||||||
convo.set('isPinned', true);
|
convo.set('isPinned', true);
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(convo.attributes);
|
drop(updateConversation(convo.attributes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,7 +1357,7 @@ export class ConversationController {
|
||||||
`updating ${sharedWith.length} conversations`
|
`updating ${sharedWith.length} conversations`
|
||||||
);
|
);
|
||||||
|
|
||||||
await window.Signal.Data.updateConversations(
|
await updateConversations(
|
||||||
sharedWith.map(c => {
|
sharedWith.map(c => {
|
||||||
c.unset('shareMyPhoneNumber');
|
c.unset('shareMyPhoneNumber');
|
||||||
return c.attributes;
|
return c.attributes;
|
||||||
|
@ -1440,7 +1444,7 @@ export class ConversationController {
|
||||||
|
|
||||||
const isChanged = maybeDeriveGroupV2Id(conversation);
|
const isChanged = maybeDeriveGroupV2Id(conversation);
|
||||||
if (isChanged) {
|
if (isChanged) {
|
||||||
updateConversation(conversation.attributes);
|
await updateConversation(conversation.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case a too-large draft was saved to the database
|
// In case a too-large draft was saved to the database
|
||||||
|
@ -1449,7 +1453,7 @@ export class ConversationController {
|
||||||
conversation.set({
|
conversation.set({
|
||||||
draft: draft.slice(0, MAX_MESSAGE_BODY_LENGTH),
|
draft: draft.slice(0, MAX_MESSAGE_BODY_LENGTH),
|
||||||
});
|
});
|
||||||
updateConversation(conversation.attributes);
|
await updateConversation(conversation.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up the conversations that have service id as their e164.
|
// Clean up the conversations that have service id as their e164.
|
||||||
|
@ -1457,7 +1461,7 @@ export class ConversationController {
|
||||||
const serviceId = conversation.getServiceId();
|
const serviceId = conversation.getServiceId();
|
||||||
if (e164 && isServiceIdString(e164) && serviceId) {
|
if (e164 && isServiceIdString(e164) && serviceId) {
|
||||||
conversation.set({ e164: undefined });
|
conversation.set({ e164: undefined });
|
||||||
updateConversation(conversation.attributes);
|
await updateConversation(conversation.attributes);
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
`Cleaning up conversation(${serviceId}) with invalid e164`
|
`Cleaning up conversation(${serviceId}) with invalid e164`
|
||||||
|
|
|
@ -18,10 +18,13 @@ import {
|
||||||
SignedPreKeyRecord,
|
SignedPreKeyRecord,
|
||||||
} from '@signalapp/libsignal-client';
|
} from '@signalapp/libsignal-client';
|
||||||
|
|
||||||
|
import { DataReader, DataWriter } from './sql/Client';
|
||||||
|
import type { ItemType } from './sql/Interface';
|
||||||
import * as Bytes from './Bytes';
|
import * as Bytes from './Bytes';
|
||||||
import { constantTimeEqual, sha256 } from './Crypto';
|
import { constantTimeEqual, sha256 } from './Crypto';
|
||||||
import { assertDev, strictAssert } from './util/assert';
|
import { assertDev, strictAssert } from './util/assert';
|
||||||
import { isNotNil } from './util/isNotNil';
|
import { isNotNil } from './util/isNotNil';
|
||||||
|
import { drop } from './util/drop';
|
||||||
import { Zone } from './util/Zone';
|
import { Zone } from './util/Zone';
|
||||||
import { isMoreRecentThan } from './util/timestamp';
|
import { isMoreRecentThan } from './util/timestamp';
|
||||||
import {
|
import {
|
||||||
|
@ -294,7 +297,9 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
(async () => {
|
(async () => {
|
||||||
this.ourIdentityKeys.clear();
|
this.ourIdentityKeys.clear();
|
||||||
const map = await window.Signal.Data.getItemById('identityKeyMap');
|
const map = (await DataReader.getItemById(
|
||||||
|
'identityKeyMap'
|
||||||
|
)) as unknown as ItemType<'identityKeyMap'>;
|
||||||
if (!map) {
|
if (!map) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -313,7 +318,9 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
})(),
|
})(),
|
||||||
(async () => {
|
(async () => {
|
||||||
this.ourRegistrationIds.clear();
|
this.ourRegistrationIds.clear();
|
||||||
const map = await window.Signal.Data.getItemById('registrationIdMap');
|
const map = (await DataReader.getItemById(
|
||||||
|
'registrationIdMap'
|
||||||
|
)) as unknown as ItemType<'registrationIdMap'>;
|
||||||
if (!map) {
|
if (!map) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -329,32 +336,32 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
_fillCaches<string, IdentityKeyType, PublicKey>(
|
_fillCaches<string, IdentityKeyType, PublicKey>(
|
||||||
this,
|
this,
|
||||||
'identityKeys',
|
'identityKeys',
|
||||||
window.Signal.Data.getAllIdentityKeys()
|
DataReader.getAllIdentityKeys()
|
||||||
),
|
),
|
||||||
_fillCaches<string, KyberPreKeyType, KyberPreKeyRecord>(
|
_fillCaches<string, KyberPreKeyType, KyberPreKeyRecord>(
|
||||||
this,
|
this,
|
||||||
'kyberPreKeys',
|
'kyberPreKeys',
|
||||||
window.Signal.Data.getAllKyberPreKeys()
|
DataReader.getAllKyberPreKeys()
|
||||||
),
|
),
|
||||||
_fillCaches<string, SessionType, SessionRecord>(
|
_fillCaches<string, SessionType, SessionRecord>(
|
||||||
this,
|
this,
|
||||||
'sessions',
|
'sessions',
|
||||||
window.Signal.Data.getAllSessions()
|
DataReader.getAllSessions()
|
||||||
),
|
),
|
||||||
_fillCaches<string, PreKeyType, PreKeyRecord>(
|
_fillCaches<string, PreKeyType, PreKeyRecord>(
|
||||||
this,
|
this,
|
||||||
'preKeys',
|
'preKeys',
|
||||||
window.Signal.Data.getAllPreKeys()
|
DataReader.getAllPreKeys()
|
||||||
),
|
),
|
||||||
_fillCaches<string, SenderKeyType, SenderKeyRecord>(
|
_fillCaches<string, SenderKeyType, SenderKeyRecord>(
|
||||||
this,
|
this,
|
||||||
'senderKeys',
|
'senderKeys',
|
||||||
window.Signal.Data.getAllSenderKeys()
|
DataReader.getAllSenderKeys()
|
||||||
),
|
),
|
||||||
_fillCaches<string, SignedPreKeyType, SignedPreKeyRecord>(
|
_fillCaches<string, SignedPreKeyType, SignedPreKeyRecord>(
|
||||||
this,
|
this,
|
||||||
'signedPreKeys',
|
'signedPreKeys',
|
||||||
window.Signal.Data.getAllSignedPreKeys()
|
DataReader.getAllSignedPreKeys()
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -470,7 +477,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await window.Signal.Data.createOrUpdateKyberPreKey(confirmedItem.fromDB);
|
await DataWriter.createOrUpdateKyberPreKey(confirmedItem.fromDB);
|
||||||
kyberPreKeyCache.set(id, confirmedItem);
|
kyberPreKeyCache.set(id, confirmedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +512,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
toSave.push(kyberPreKey);
|
toSave.push(kyberPreKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
await window.Signal.Data.bulkAddKyberPreKeys(toSave);
|
await DataWriter.bulkAddKyberPreKeys(toSave);
|
||||||
toSave.forEach(kyberPreKey => {
|
toSave.forEach(kyberPreKey => {
|
||||||
kyberPreKeyCache.set(kyberPreKey.id, {
|
kyberPreKeyCache.set(kyberPreKey.id, {
|
||||||
hydrated: false,
|
hydrated: false,
|
||||||
|
@ -546,7 +553,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
const ids = keyIds.map(keyId => this._getKeyId(ourServiceId, keyId));
|
const ids = keyIds.map(keyId => this._getKeyId(ourServiceId, keyId));
|
||||||
|
|
||||||
log.info('removeKyberPreKeys: Removing kyber prekeys:', formatKeys(keyIds));
|
log.info('removeKyberPreKeys: Removing kyber prekeys:', formatKeys(keyIds));
|
||||||
const changes = await window.Signal.Data.removeKyberPreKeyById(ids);
|
const changes = await DataWriter.removeKyberPreKeyById(ids);
|
||||||
log.info(`removeKyberPreKeys: Removed ${changes} kyber prekeys`);
|
log.info(`removeKyberPreKeys: Removed ${changes} kyber prekeys`);
|
||||||
ids.forEach(id => {
|
ids.forEach(id => {
|
||||||
kyberPreKeyCache.delete(id);
|
kyberPreKeyCache.delete(id);
|
||||||
|
@ -564,7 +571,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
if (this.kyberPreKeys) {
|
if (this.kyberPreKeys) {
|
||||||
this.kyberPreKeys.clear();
|
this.kyberPreKeys.clear();
|
||||||
}
|
}
|
||||||
const changes = await window.Signal.Data.removeAllKyberPreKeys();
|
const changes = await DataWriter.removeAllKyberPreKeys();
|
||||||
log.info(`clearKyberPreKeyStore: Removed ${changes} kyber prekeys`);
|
log.info(`clearKyberPreKeyStore: Removed ${changes} kyber prekeys`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +653,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
});
|
});
|
||||||
|
|
||||||
log.info(`storePreKeys: Saving ${toSave.length} prekeys`);
|
log.info(`storePreKeys: Saving ${toSave.length} prekeys`);
|
||||||
await window.Signal.Data.bulkAddPreKeys(toSave);
|
await DataWriter.bulkAddPreKeys(toSave);
|
||||||
toSave.forEach(preKey => {
|
toSave.forEach(preKey => {
|
||||||
preKeyCache.set(preKey.id, {
|
preKeyCache.set(preKey.id, {
|
||||||
hydrated: false,
|
hydrated: false,
|
||||||
|
@ -668,7 +675,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
log.info('removePreKeys: Removing prekeys:', formatKeys(keyIds));
|
log.info('removePreKeys: Removing prekeys:', formatKeys(keyIds));
|
||||||
|
|
||||||
const changes = await window.Signal.Data.removePreKeyById(ids);
|
const changes = await DataWriter.removePreKeyById(ids);
|
||||||
log.info(`removePreKeys: Removed ${changes} prekeys`);
|
log.info(`removePreKeys: Removed ${changes} prekeys`);
|
||||||
ids.forEach(id => {
|
ids.forEach(id => {
|
||||||
preKeyCache.delete(id);
|
preKeyCache.delete(id);
|
||||||
|
@ -683,7 +690,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
if (this.preKeys) {
|
if (this.preKeys) {
|
||||||
this.preKeys.clear();
|
this.preKeys.clear();
|
||||||
}
|
}
|
||||||
const changes = await window.Signal.Data.removeAllPreKeys();
|
const changes = await DataWriter.removeAllPreKeys();
|
||||||
log.info(`clearPreKeyStore: Removed ${changes} prekeys`);
|
log.info(`clearPreKeyStore: Removed ${changes} prekeys`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,7 +776,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await window.Signal.Data.createOrUpdateSignedPreKey(confirmedItem.fromDB);
|
await DataWriter.createOrUpdateSignedPreKey(confirmedItem.fromDB);
|
||||||
signedPreKeyCache.set(id, confirmedItem);
|
signedPreKeyCache.set(id, confirmedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,7 +803,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
confirmed: Boolean(confirmed),
|
confirmed: Boolean(confirmed),
|
||||||
};
|
};
|
||||||
|
|
||||||
await window.Signal.Data.createOrUpdateSignedPreKey(fromDB);
|
await DataWriter.createOrUpdateSignedPreKey(fromDB);
|
||||||
this.signedPreKeys.set(id, {
|
this.signedPreKeys.set(id, {
|
||||||
hydrated: false,
|
hydrated: false,
|
||||||
fromDB,
|
fromDB,
|
||||||
|
@ -818,7 +825,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
'removeSignedPreKeys: Removing signed prekeys:',
|
'removeSignedPreKeys: Removing signed prekeys:',
|
||||||
formatKeys(keyIds)
|
formatKeys(keyIds)
|
||||||
);
|
);
|
||||||
await window.Signal.Data.removeSignedPreKeyById(ids);
|
await DataWriter.removeSignedPreKeyById(ids);
|
||||||
ids.forEach(id => {
|
ids.forEach(id => {
|
||||||
signedPreKeyCache.delete(id);
|
signedPreKeyCache.delete(id);
|
||||||
});
|
});
|
||||||
|
@ -828,7 +835,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
if (this.signedPreKeys) {
|
if (this.signedPreKeys) {
|
||||||
this.signedPreKeys.clear();
|
this.signedPreKeys.clear();
|
||||||
}
|
}
|
||||||
const changes = await window.Signal.Data.removeAllSignedPreKeys();
|
const changes = await DataWriter.removeAllSignedPreKeys();
|
||||||
log.info(`clearSignedPreKeysStore: Removed ${changes} signed prekeys`);
|
log.info(`clearSignedPreKeysStore: Removed ${changes} signed prekeys`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,7 +999,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
try {
|
try {
|
||||||
const id = this.getSenderKeyId(qualifiedAddress, distributionId);
|
const id = this.getSenderKeyId(qualifiedAddress, distributionId);
|
||||||
|
|
||||||
await window.Signal.Data.removeSenderKeyById(id);
|
await DataWriter.removeSenderKeyById(id);
|
||||||
|
|
||||||
this.senderKeys.delete(id);
|
this.senderKeys.delete(id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -1011,7 +1018,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
if (this.pendingSenderKeys) {
|
if (this.pendingSenderKeys) {
|
||||||
this.pendingSenderKeys.clear();
|
this.pendingSenderKeys.clear();
|
||||||
}
|
}
|
||||||
await window.Signal.Data.removeAllSenderKeys();
|
await DataWriter.removeAllSenderKeys();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1191,7 +1198,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
// Commit both sender keys, sessions and unprocessed in the same database transaction
|
// Commit both sender keys, sessions and unprocessed in the same database transaction
|
||||||
// to unroll both on error.
|
// to unroll both on error.
|
||||||
await window.Signal.Data.commitDecryptResult({
|
await DataWriter.commitDecryptResult({
|
||||||
senderKeys: Array.from(pendingSenderKeys.values()).map(
|
senderKeys: Array.from(pendingSenderKeys.values()).map(
|
||||||
({ fromDB }) => fromDB
|
({ fromDB }) => fromDB
|
||||||
),
|
),
|
||||||
|
@ -1593,7 +1600,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
const id = qualifiedAddress.toString();
|
const id = qualifiedAddress.toString();
|
||||||
log.info('removeSession: deleting session for', id);
|
log.info('removeSession: deleting session for', id);
|
||||||
try {
|
try {
|
||||||
await window.Signal.Data.removeSessionById(id);
|
await DataWriter.removeSessionById(id);
|
||||||
this.sessions.delete(id);
|
this.sessions.delete(id);
|
||||||
this.pendingSessions.delete(id);
|
this.pendingSessions.delete(id);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1640,7 +1647,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await window.Signal.Data.removeSessionsByConversation(id);
|
await DataWriter.removeSessionsByConversation(id);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1665,7 +1672,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await window.Signal.Data.removeSessionsByServiceId(serviceId);
|
await DataWriter.removeSessionsByServiceId(serviceId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1772,7 +1779,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
this.sessions.clear();
|
this.sessions.clear();
|
||||||
}
|
}
|
||||||
this.pendingSessions.clear();
|
this.pendingSessions.clear();
|
||||||
const changes = await window.Signal.Data.removeAllSessions();
|
const changes = await DataWriter.removeAllSessions();
|
||||||
log.info(`clearSessionStore: Removed ${changes} sessions`);
|
log.info(`clearSessionStore: Removed ${changes} sessions`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1893,9 +1900,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
await this._saveIdentityKey(newRecord);
|
await this._saveIdentityKey(newRecord);
|
||||||
|
|
||||||
this.identityKeys.delete(record.fromDB.id);
|
this.identityKeys.delete(record.fromDB.id);
|
||||||
const changes = await window.Signal.Data.removeIdentityKeyById(
|
const changes = await DataWriter.removeIdentityKeyById(record.fromDB.id);
|
||||||
record.fromDB.id
|
|
||||||
);
|
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
`getOrMigrateIdentityRecord: Removed ${changes} old identity keys for ${record.fromDB.id}`
|
`getOrMigrateIdentityRecord: Removed ${changes} old identity keys for ${record.fromDB.id}`
|
||||||
|
@ -2042,7 +2047,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
const { id } = data;
|
const { id } = data;
|
||||||
|
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey(data);
|
await DataWriter.createOrUpdateIdentityKey(data);
|
||||||
this.identityKeys.set(id, {
|
this.identityKeys.set(id, {
|
||||||
hydrated: false,
|
hydrated: false,
|
||||||
fromDB: data,
|
fromDB: data,
|
||||||
|
@ -2345,7 +2350,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
// We only want to clear previousIdentityKey on a match, or on successfully emit.
|
// We only want to clear previousIdentityKey on a match, or on successfully emit.
|
||||||
conversation.set({ previousIdentityKey: undefined });
|
conversation.set({ previousIdentityKey: undefined });
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
drop(DataWriter.updateConversation(conversation.attributes));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(
|
log.error(
|
||||||
'saveIdentity: error triggering keychange:',
|
'saveIdentity: error triggering keychange:',
|
||||||
|
@ -2462,20 +2467,20 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
const id = serviceId;
|
const id = serviceId;
|
||||||
this.identityKeys.delete(id);
|
this.identityKeys.delete(id);
|
||||||
await window.Signal.Data.removeIdentityKeyById(serviceId);
|
await DataWriter.removeIdentityKeyById(serviceId);
|
||||||
await this.removeSessionsByServiceId(serviceId);
|
await this.removeSessionsByServiceId(serviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not yet processed messages - for resiliency
|
// Not yet processed messages - for resiliency
|
||||||
getUnprocessedCount(): Promise<number> {
|
getUnprocessedCount(): Promise<number> {
|
||||||
return this.withZone(GLOBAL_ZONE, 'getUnprocessedCount', async () => {
|
return this.withZone(GLOBAL_ZONE, 'getUnprocessedCount', async () => {
|
||||||
return window.Signal.Data.getUnprocessedCount();
|
return DataReader.getUnprocessedCount();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getAllUnprocessedIds(): Promise<Array<string>> {
|
getAllUnprocessedIds(): Promise<Array<string>> {
|
||||||
return this.withZone(GLOBAL_ZONE, 'getAllUnprocessedIds', () => {
|
return this.withZone(GLOBAL_ZONE, 'getAllUnprocessedIds', () => {
|
||||||
return window.Signal.Data.getAllUnprocessedIds();
|
return DataWriter.getAllUnprocessedIds();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2486,14 +2491,14 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
GLOBAL_ZONE,
|
GLOBAL_ZONE,
|
||||||
'getAllUnprocessedByIdsAndIncrementAttempts',
|
'getAllUnprocessedByIdsAndIncrementAttempts',
|
||||||
async () => {
|
async () => {
|
||||||
return window.Signal.Data.getUnprocessedByIdsAndIncrementAttempts(ids);
|
return DataWriter.getUnprocessedByIdsAndIncrementAttempts(ids);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getUnprocessedById(id: string): Promise<UnprocessedType | undefined> {
|
getUnprocessedById(id: string): Promise<UnprocessedType | undefined> {
|
||||||
return this.withZone(GLOBAL_ZONE, 'getUnprocessedById', async () => {
|
return this.withZone(GLOBAL_ZONE, 'getUnprocessedById', async () => {
|
||||||
return window.Signal.Data.getUnprocessedById(id);
|
return DataReader.getUnprocessedById(id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2531,7 +2536,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
data: UnprocessedUpdateType
|
data: UnprocessedUpdateType
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return this.withZone(GLOBAL_ZONE, 'updateUnprocessedWithData', async () => {
|
return this.withZone(GLOBAL_ZONE, 'updateUnprocessedWithData', async () => {
|
||||||
await window.Signal.Data.updateUnprocessedWithData(id, data);
|
await DataWriter.updateUnprocessedWithData(id, data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2542,14 +2547,14 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
GLOBAL_ZONE,
|
GLOBAL_ZONE,
|
||||||
'updateUnprocessedsWithData',
|
'updateUnprocessedsWithData',
|
||||||
async () => {
|
async () => {
|
||||||
await window.Signal.Data.updateUnprocessedsWithData(items);
|
await DataWriter.updateUnprocessedsWithData(items);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeUnprocessed(idOrArray: string | Array<string>): Promise<void> {
|
removeUnprocessed(idOrArray: string | Array<string>): Promise<void> {
|
||||||
return this.withZone(GLOBAL_ZONE, 'removeUnprocessed', async () => {
|
return this.withZone(GLOBAL_ZONE, 'removeUnprocessed', async () => {
|
||||||
await window.Signal.Data.removeUnprocessed(idOrArray);
|
await DataWriter.removeUnprocessed(idOrArray);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2557,7 +2562,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
removeAllUnprocessed(): Promise<void> {
|
removeAllUnprocessed(): Promise<void> {
|
||||||
log.info('removeAllUnprocessed');
|
log.info('removeAllUnprocessed');
|
||||||
return this.withZone(GLOBAL_ZONE, 'removeAllUnprocessed', async () => {
|
return this.withZone(GLOBAL_ZONE, 'removeAllUnprocessed', async () => {
|
||||||
await window.Signal.Data.removeAllUnprocessed();
|
await DataWriter.removeAllUnprocessed();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2603,9 +2608,9 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
'registrationIdMap',
|
'registrationIdMap',
|
||||||
omit(storage.get('registrationIdMap') || {}, oldPni)
|
omit(storage.get('registrationIdMap') || {}, oldPni)
|
||||||
),
|
),
|
||||||
window.Signal.Data.removePreKeysByServiceId(oldPni),
|
DataWriter.removePreKeysByServiceId(oldPni),
|
||||||
window.Signal.Data.removeSignedPreKeysByServiceId(oldPni),
|
DataWriter.removeSignedPreKeysByServiceId(oldPni),
|
||||||
window.Signal.Data.removeKyberPreKeysByServiceId(oldPni),
|
DataWriter.removeKyberPreKeysByServiceId(oldPni),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2695,7 +2700,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeAllData(): Promise<void> {
|
async removeAllData(): Promise<void> {
|
||||||
await window.Signal.Data.removeAll();
|
await DataWriter.removeAll();
|
||||||
await this.hydrateCaches();
|
await this.hydrateCaches();
|
||||||
|
|
||||||
window.storage.reset();
|
window.storage.reset();
|
||||||
|
@ -2716,7 +2721,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
conversation.unset('senderKeyInfo');
|
conversation.unset('senderKeyInfo');
|
||||||
});
|
});
|
||||||
|
|
||||||
await window.Signal.Data.removeAllConfiguration();
|
await DataWriter.removeAllConfiguration();
|
||||||
|
|
||||||
await this.hydrateCaches();
|
await this.hydrateCaches();
|
||||||
|
|
||||||
|
|
|
@ -209,6 +209,7 @@ import { isEnabled } from './RemoteConfig';
|
||||||
import { AttachmentBackupManager } from './jobs/AttachmentBackupManager';
|
import { AttachmentBackupManager } from './jobs/AttachmentBackupManager';
|
||||||
import { getConversationIdForLogging } from './util/idForLogging';
|
import { getConversationIdForLogging } from './util/idForLogging';
|
||||||
import { encryptConversationAttachments } from './util/encryptConversationAttachments';
|
import { encryptConversationAttachments } from './util/encryptConversationAttachments';
|
||||||
|
import { DataReader, DataWriter } from './sql/Client';
|
||||||
|
|
||||||
export function isOverHourIntoPast(timestamp: number): boolean {
|
export function isOverHourIntoPast(timestamp: number): boolean {
|
||||||
return isNumber(timestamp) && isOlderThan(timestamp, HOUR);
|
return isNumber(timestamp) && isOlderThan(timestamp, HOUR);
|
||||||
|
@ -256,7 +257,7 @@ export async function startApp(): Promise<void> {
|
||||||
let initialBadgesState: BadgesStateType = { byId: {} };
|
let initialBadgesState: BadgesStateType = { byId: {} };
|
||||||
async function loadInitialBadgesState(): Promise<void> {
|
async function loadInitialBadgesState(): Promise<void> {
|
||||||
initialBadgesState = {
|
initialBadgesState = {
|
||||||
byId: makeLookup(await window.Signal.Data.getAllBadges(), 'id'),
|
byId: makeLookup(await DataReader.getAllBadges(), 'id'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +437,7 @@ export async function startApp(): Promise<void> {
|
||||||
window.i18n
|
window.i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
const version = await window.Signal.Data.getItemById('version');
|
const version = await DataReader.getItemById('version');
|
||||||
if (!version) {
|
if (!version) {
|
||||||
const isIndexedDBPresent = await indexedDb.doesDatabaseExist();
|
const isIndexedDBPresent = await indexedDb.doesDatabaseExist();
|
||||||
if (isIndexedDBPresent) {
|
if (isIndexedDBPresent) {
|
||||||
|
@ -472,8 +473,8 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
indexedDb.removeDatabase(),
|
indexedDb.removeDatabase(),
|
||||||
window.Signal.Data.removeAll(),
|
DataWriter.removeAll(),
|
||||||
window.Signal.Data.removeIndexedDBFiles(),
|
DataWriter.removeIndexedDBFiles(),
|
||||||
]);
|
]);
|
||||||
log.info('Done with SQL deletion and IndexedDB file deletion.');
|
log.info('Done with SQL deletion and IndexedDB file deletion.');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -485,7 +486,7 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
// Set a flag to delete IndexedDB on next startup if it wasn't deleted just now.
|
// Set a flag to delete IndexedDB on next startup if it wasn't deleted just now.
|
||||||
// We need to use direct data calls, since window.storage isn't ready yet.
|
// We need to use direct data calls, since window.storage isn't ready yet.
|
||||||
await window.Signal.Data.createOrUpdateItem({
|
await DataWriter.createOrUpdateItem({
|
||||||
id: 'indexeddb-delete-needed',
|
id: 'indexeddb-delete-needed',
|
||||||
value: true,
|
value: true,
|
||||||
});
|
});
|
||||||
|
@ -826,7 +827,7 @@ export async function startApp(): Promise<void> {
|
||||||
log.info('background/shutdown: closing the database');
|
log.info('background/shutdown: closing the database');
|
||||||
|
|
||||||
// Shut down the data interface cleanly
|
// Shut down the data interface cleanly
|
||||||
await window.Signal.Data.shutdown();
|
await DataWriter.shutdown();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -926,12 +927,12 @@ export async function startApp(): Promise<void> {
|
||||||
key: legacyChallengeKey,
|
key: legacyChallengeKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
await window.Signal.Data.clearAllErrorStickerPackAttempts();
|
await DataWriter.clearAllErrorStickerPackAttempts();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.isBeforeVersion(lastVersion, 'v5.51.0-beta.2')) {
|
if (window.isBeforeVersion(lastVersion, 'v5.51.0-beta.2')) {
|
||||||
await window.storage.put('groupCredentials', []);
|
await window.storage.put('groupCredentials', []);
|
||||||
await window.Signal.Data.removeAllProfileKeyCredentials();
|
await DataWriter.removeAllProfileKeyCredentials();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.isBeforeVersion(lastVersion, 'v6.38.0-beta.1')) {
|
if (window.isBeforeVersion(lastVersion, 'v6.38.0-beta.1')) {
|
||||||
|
@ -963,9 +964,9 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
if (newVersion || window.storage.get('needOrphanedAttachmentCheck')) {
|
if (newVersion || window.storage.get('needOrphanedAttachmentCheck')) {
|
||||||
await window.storage.remove('needOrphanedAttachmentCheck');
|
await window.storage.remove('needOrphanedAttachmentCheck');
|
||||||
await window.Signal.Data.cleanupOrphanedAttachments();
|
await DataWriter.cleanupOrphanedAttachments();
|
||||||
|
|
||||||
drop(window.Signal.Data.ensureFilePermissions());
|
drop(DataWriter.ensureFilePermissions());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -1004,9 +1005,8 @@ export async function startApp(): Promise<void> {
|
||||||
const batchWithIndex = await migrateMessageData({
|
const batchWithIndex = await migrateMessageData({
|
||||||
numMessagesPerBatch: NUM_MESSAGES_PER_BATCH,
|
numMessagesPerBatch: NUM_MESSAGES_PER_BATCH,
|
||||||
upgradeMessageSchema,
|
upgradeMessageSchema,
|
||||||
getMessagesNeedingUpgrade:
|
getMessagesNeedingUpgrade: DataReader.getMessagesNeedingUpgrade,
|
||||||
window.Signal.Data.getMessagesNeedingUpgrade,
|
saveMessages: DataWriter.saveMessages,
|
||||||
saveMessages: window.Signal.Data.saveMessages,
|
|
||||||
});
|
});
|
||||||
log.info('idleDetector/idle: Upgraded messages:', batchWithIndex);
|
log.info('idleDetector/idle: Upgraded messages:', batchWithIndex);
|
||||||
isMigrationWithIndexComplete = batchWithIndex.done;
|
isMigrationWithIndexComplete = batchWithIndex.done;
|
||||||
|
@ -1056,9 +1056,7 @@ export async function startApp(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await window.Signal.Data.deleteSentProtosOlderThan(
|
await DataWriter.deleteSentProtosOlderThan(now - sentProtoMaxAge);
|
||||||
now - sentProtoMaxAge
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(
|
log.error(
|
||||||
'background/onready/setInterval: Error deleting sent protos: ',
|
'background/onready/setInterval: Error deleting sent protos: ',
|
||||||
|
@ -1412,7 +1410,7 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
log.info('Expiration start timestamp cleanup: starting...');
|
log.info('Expiration start timestamp cleanup: starting...');
|
||||||
const messagesUnexpectedlyMissingExpirationStartTimestamp =
|
const messagesUnexpectedlyMissingExpirationStartTimestamp =
|
||||||
await window.Signal.Data.getMessagesUnexpectedlyMissingExpirationStartTimestamp();
|
await DataReader.getMessagesUnexpectedlyMissingExpirationStartTimestamp();
|
||||||
log.info(
|
log.info(
|
||||||
`Expiration start timestamp cleanup: Found ${messagesUnexpectedlyMissingExpirationStartTimestamp.length} messages for cleanup`
|
`Expiration start timestamp cleanup: Found ${messagesUnexpectedlyMissingExpirationStartTimestamp.length} messages for cleanup`
|
||||||
);
|
);
|
||||||
|
@ -1446,7 +1444,7 @@ export async function startApp(): Promise<void> {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
await window.Signal.Data.saveMessages(newMessageAttributes, {
|
await DataWriter.saveMessages(newMessageAttributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1454,10 +1452,10 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
{
|
{
|
||||||
log.info('Startup/syncTasks: Fetching tasks');
|
log.info('Startup/syncTasks: Fetching tasks');
|
||||||
const syncTasks = await window.Signal.Data.getAllSyncTasks();
|
const syncTasks = await DataWriter.getAllSyncTasks();
|
||||||
|
|
||||||
log.info(`Startup/syncTasks: Queueing ${syncTasks.length} sync tasks`);
|
log.info(`Startup/syncTasks: Queueing ${syncTasks.length} sync tasks`);
|
||||||
await queueSyncTasks(syncTasks, window.Signal.Data.removeSyncTaskById);
|
await queueSyncTasks(syncTasks, DataWriter.removeSyncTaskById);
|
||||||
|
|
||||||
log.info('`Startup/syncTasks: Done');
|
log.info('`Startup/syncTasks: Done');
|
||||||
}
|
}
|
||||||
|
@ -2402,7 +2400,7 @@ export async function startApp(): Promise<void> {
|
||||||
`for ${sender.idForLogging()}`
|
`for ${sender.idForLogging()}`
|
||||||
);
|
);
|
||||||
sender.set({ shareMyPhoneNumber: true });
|
sender.set({ shareMyPhoneNumber: true });
|
||||||
window.Signal.Data.updateConversation(sender.attributes);
|
drop(DataWriter.updateConversation(sender.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message.get('unidentifiedDeliveryReceived')) {
|
if (!message.get('unidentifiedDeliveryReceived')) {
|
||||||
|
@ -2585,7 +2583,7 @@ export async function startApp(): Promise<void> {
|
||||||
const conversation = window.ConversationController.get(id)!;
|
const conversation = window.ConversationController.get(id)!;
|
||||||
|
|
||||||
conversation.enableProfileSharing();
|
conversation.enableProfileSharing();
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
|
|
||||||
// Then we update our own profileKey if it's different from what we have
|
// Then we update our own profileKey if it's different from what we have
|
||||||
const ourId = window.ConversationController.getOurConversationId();
|
const ourId = window.ConversationController.getOurConversationId();
|
||||||
|
@ -3037,14 +3035,14 @@ export async function startApp(): Promise<void> {
|
||||||
window.ConversationController.getOurConversation();
|
window.ConversationController.getOurConversation();
|
||||||
if (ourConversation) {
|
if (ourConversation) {
|
||||||
ourConversation.unset('username');
|
ourConversation.unset('username');
|
||||||
window.Signal.Data.updateConversation(ourConversation.attributes);
|
await DataWriter.updateConversation(ourConversation.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then make sure outstanding conversation saves are flushed
|
// Then make sure outstanding conversation saves are flushed
|
||||||
await window.Signal.Data.flushUpdateConversationBatcher();
|
await DataWriter.flushUpdateConversationBatcher();
|
||||||
|
|
||||||
// Then make sure that all previously-outstanding database saves are flushed
|
// Then make sure that all previously-outstanding database saves are flushed
|
||||||
await window.Signal.Data.getItemById('manifestVersion');
|
await DataReader.getItemById('manifestVersion');
|
||||||
|
|
||||||
// Finally, conversations in the database, and delete all config tables
|
// Finally, conversations in the database, and delete all config tables
|
||||||
await window.textsecure.storage.protocol.removeAllConfiguration();
|
await window.textsecure.storage.protocol.removeAllConfiguration();
|
||||||
|
@ -3319,13 +3317,13 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
log.info(`${logId}: Saving ${syncTasks.length} sync tasks`);
|
log.info(`${logId}: Saving ${syncTasks.length} sync tasks`);
|
||||||
|
|
||||||
await window.Signal.Data.saveSyncTasks(syncTasks);
|
await DataWriter.saveSyncTasks(syncTasks);
|
||||||
|
|
||||||
confirm();
|
confirm();
|
||||||
|
|
||||||
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
||||||
|
|
||||||
await queueSyncTasks(syncTasks, window.Signal.Data.removeSyncTaskById);
|
await queueSyncTasks(syncTasks, DataWriter.removeSyncTaskById);
|
||||||
|
|
||||||
log.info(`${logId}: Done`);
|
log.info(`${logId}: Done`);
|
||||||
}
|
}
|
||||||
|
@ -3391,13 +3389,13 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
log.info(`${logId}: Saving ${syncTasks.length} sync tasks`);
|
log.info(`${logId}: Saving ${syncTasks.length} sync tasks`);
|
||||||
|
|
||||||
await window.Signal.Data.saveSyncTasks(syncTasks);
|
await DataWriter.saveSyncTasks(syncTasks);
|
||||||
|
|
||||||
confirm();
|
confirm();
|
||||||
|
|
||||||
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
||||||
|
|
||||||
await queueSyncTasks(syncTasks, window.Signal.Data.removeSyncTaskById);
|
await queueSyncTasks(syncTasks, DataWriter.removeSyncTaskById);
|
||||||
|
|
||||||
log.info(`${logId}: Done`);
|
log.info(`${logId}: Done`);
|
||||||
}
|
}
|
||||||
|
@ -3463,13 +3461,13 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
log.info(`${logId}: Saving ${syncTasks.length} sync tasks`);
|
log.info(`${logId}: Saving ${syncTasks.length} sync tasks`);
|
||||||
|
|
||||||
await window.Signal.Data.saveSyncTasks(syncTasks);
|
await DataWriter.saveSyncTasks(syncTasks);
|
||||||
|
|
||||||
confirm();
|
confirm();
|
||||||
|
|
||||||
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
||||||
|
|
||||||
await queueSyncTasks(syncTasks, window.Signal.Data.removeSyncTaskById);
|
await queueSyncTasks(syncTasks, DataWriter.removeSyncTaskById);
|
||||||
|
|
||||||
log.info(`${logId}: Done`);
|
log.info(`${logId}: Done`);
|
||||||
}
|
}
|
||||||
|
@ -3544,13 +3542,13 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
log.info(`${logId}: Saving ${syncTasks.length} sync tasks`);
|
log.info(`${logId}: Saving ${syncTasks.length} sync tasks`);
|
||||||
|
|
||||||
await window.Signal.Data.saveSyncTasks(syncTasks);
|
await DataWriter.saveSyncTasks(syncTasks);
|
||||||
|
|
||||||
confirm();
|
confirm();
|
||||||
|
|
||||||
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
||||||
|
|
||||||
await queueSyncTasks(syncTasks, window.Signal.Data.removeSyncTaskById);
|
await queueSyncTasks(syncTasks, DataWriter.removeSyncTaskById);
|
||||||
|
|
||||||
log.info(`${logId}: Done`);
|
log.info(`${logId}: Done`);
|
||||||
}
|
}
|
||||||
|
@ -3579,13 +3577,13 @@ export async function startApp(): Promise<void> {
|
||||||
sentAt: timestamp,
|
sentAt: timestamp,
|
||||||
type: item.type,
|
type: item.type,
|
||||||
}));
|
}));
|
||||||
await window.Signal.Data.saveSyncTasks(syncTasks);
|
await DataWriter.saveSyncTasks(syncTasks);
|
||||||
|
|
||||||
confirm();
|
confirm();
|
||||||
|
|
||||||
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
log.info(`${logId}: Queuing ${syncTasks.length} sync tasks`);
|
||||||
|
|
||||||
await queueSyncTasks(syncTasks, window.Signal.Data.removeSyncTaskById);
|
await queueSyncTasks(syncTasks, DataWriter.removeSyncTaskById);
|
||||||
|
|
||||||
log.info(`${logId}: Done`);
|
log.info(`${logId}: Done`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
|
import { DataWriter } from '../sql/Client';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { MINUTE } from '../util/durations';
|
import { MINUTE } from '../util/durations';
|
||||||
import { missingCaseError } from '../util/missingCaseError';
|
import { missingCaseError } from '../util/missingCaseError';
|
||||||
|
@ -100,7 +101,7 @@ async function downloadBadgeImageFile(url: string): Promise<string> {
|
||||||
imageFileData
|
imageFileData
|
||||||
);
|
);
|
||||||
|
|
||||||
await window.Signal.Data.badgeImageFileDownloaded(url, localPath);
|
await DataWriter.badgeImageFileDownloaded(url, localPath);
|
||||||
|
|
||||||
window.reduxActions.badges.badgeImageFileDownloaded(url, localPath);
|
window.reduxActions.badges.badgeImageFileDownloaded(url, localPath);
|
||||||
|
|
||||||
|
|
36
ts/groups.ts
36
ts/groups.ts
|
@ -19,7 +19,7 @@ import {
|
||||||
maybeFetchNewCredentials,
|
maybeFetchNewCredentials,
|
||||||
} from './services/groupCredentialFetcher';
|
} from './services/groupCredentialFetcher';
|
||||||
import { storageServiceUploadJob } from './services/storage';
|
import { storageServiceUploadJob } from './services/storage';
|
||||||
import dataInterface from './sql/Client';
|
import { DataReader, DataWriter } from './sql/Client';
|
||||||
import { toWebSafeBase64, fromWebSafeBase64 } from './util/webSafeBase64';
|
import { toWebSafeBase64, fromWebSafeBase64 } from './util/webSafeBase64';
|
||||||
import { assertDev, strictAssert } from './util/assert';
|
import { assertDev, strictAssert } from './util/assert';
|
||||||
import { isMoreRecentThan } from './util/timestamp';
|
import { isMoreRecentThan } from './util/timestamp';
|
||||||
|
@ -263,7 +263,7 @@ const groupFieldsCache = new LRU<string, GroupFields>({
|
||||||
max: MAX_CACHED_GROUP_FIELDS,
|
max: MAX_CACHED_GROUP_FIELDS,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { updateConversation } = dataInterface;
|
const { updateConversation } = DataWriter;
|
||||||
|
|
||||||
if (!isNumber(MAX_MESSAGE_SCHEMA)) {
|
if (!isNumber(MAX_MESSAGE_SCHEMA)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -1602,9 +1602,7 @@ export async function modifyGroupV2({
|
||||||
groupMembersV2: membersV2,
|
groupMembersV2: membersV2,
|
||||||
});
|
});
|
||||||
|
|
||||||
await dataInterface.replaceAllEndorsementsForGroup(
|
await DataWriter.replaceAllEndorsementsForGroup(groupEndorsementData);
|
||||||
groupEndorsementData
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1921,7 +1919,7 @@ export async function createGroupV2(
|
||||||
groupMembersV2: membersV2,
|
groupMembersV2: membersV2,
|
||||||
});
|
});
|
||||||
|
|
||||||
await dataInterface.replaceAllEndorsementsForGroup(groupEndorsementData);
|
await DataWriter.replaceAllEndorsementsForGroup(groupEndorsementData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!(error instanceof HTTPError)) {
|
if (!(error instanceof HTTPError)) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -2023,7 +2021,7 @@ export async function createGroupV2(
|
||||||
details: [{ type: 'create' }],
|
details: [{ type: 'create' }],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
await dataInterface.saveMessages([createdTheGroupMessage], {
|
await DataWriter.saveMessages([createdTheGroupMessage], {
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
ourAci,
|
ourAci,
|
||||||
});
|
});
|
||||||
|
@ -2482,7 +2480,7 @@ export async function initiateMigrationToGroupV2(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save these most recent updates to conversation
|
// Save these most recent updates to conversation
|
||||||
updateConversation(conversation.attributes);
|
await updateConversation(conversation.attributes);
|
||||||
|
|
||||||
strictAssert(
|
strictAssert(
|
||||||
Bytes.isNotEmpty(groupSendEndorsementResponse),
|
Bytes.isNotEmpty(groupSendEndorsementResponse),
|
||||||
|
@ -2496,7 +2494,7 @@ export async function initiateMigrationToGroupV2(
|
||||||
groupMembersV2: membersV2,
|
groupMembersV2: membersV2,
|
||||||
});
|
});
|
||||||
|
|
||||||
await dataInterface.replaceAllEndorsementsForGroup(groupEndorsementData);
|
await DataWriter.replaceAllEndorsementsForGroup(groupEndorsementData);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const logId = conversation.idForLogging();
|
const logId = conversation.idForLogging();
|
||||||
|
@ -2960,7 +2958,7 @@ export async function respondToGroupV2Migration({
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save these most recent updates to conversation
|
// Save these most recent updates to conversation
|
||||||
updateConversation(conversation.attributes);
|
await updateConversation(conversation.attributes);
|
||||||
|
|
||||||
// Finally, check for any changes to the group since its initial creation using normal
|
// Finally, check for any changes to the group since its initial creation using normal
|
||||||
// group update codepaths.
|
// group update codepaths.
|
||||||
|
@ -2983,7 +2981,7 @@ export async function respondToGroupV2Migration({
|
||||||
groupMembersV2: membersV2,
|
groupMembersV2: membersV2,
|
||||||
});
|
});
|
||||||
|
|
||||||
await dataInterface.replaceAllEndorsementsForGroup(groupEndorsementData);
|
await DataWriter.replaceAllEndorsementsForGroup(groupEndorsementData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3364,7 +3362,7 @@ async function appendChangeMessages(
|
||||||
|
|
||||||
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
||||||
|
|
||||||
let lastMessage = await dataInterface.getLastConversationMessage({
|
let lastMessage = await DataReader.getLastConversationMessage({
|
||||||
conversationId: conversation.id,
|
conversationId: conversation.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3400,7 +3398,7 @@ async function appendChangeMessages(
|
||||||
strictAssert(first !== undefined, 'First message must be there');
|
strictAssert(first !== undefined, 'First message must be there');
|
||||||
|
|
||||||
log.info(`appendChangeMessages/${logId}: updating ${first.id}`);
|
log.info(`appendChangeMessages/${logId}: updating ${first.id}`);
|
||||||
await dataInterface.saveMessage(first, {
|
await DataWriter.saveMessage(first, {
|
||||||
ourAci,
|
ourAci,
|
||||||
|
|
||||||
// We don't use forceSave here because this is an update of existing
|
// We don't use forceSave here because this is an update of existing
|
||||||
|
@ -3410,7 +3408,7 @@ async function appendChangeMessages(
|
||||||
log.info(
|
log.info(
|
||||||
`appendChangeMessages/${logId}: saving ${rest.length} new messages`
|
`appendChangeMessages/${logId}: saving ${rest.length} new messages`
|
||||||
);
|
);
|
||||||
await dataInterface.saveMessages(rest, {
|
await DataWriter.saveMessages(rest, {
|
||||||
ourAci,
|
ourAci,
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -3418,7 +3416,7 @@ async function appendChangeMessages(
|
||||||
log.info(
|
log.info(
|
||||||
`appendChangeMessages/${logId}: saving ${mergedMessages.length} new messages`
|
`appendChangeMessages/${logId}: saving ${mergedMessages.length} new messages`
|
||||||
);
|
);
|
||||||
await dataInterface.saveMessages(mergedMessages, {
|
await DataWriter.saveMessages(mergedMessages, {
|
||||||
ourAci,
|
ourAci,
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -3766,7 +3764,7 @@ async function updateGroupViaState({
|
||||||
groupMembersV2: membersV2,
|
groupMembersV2: membersV2,
|
||||||
});
|
});
|
||||||
|
|
||||||
await dataInterface.replaceAllEndorsementsForGroup(groupEndorsementData);
|
await DataWriter.replaceAllEndorsementsForGroup(groupEndorsementData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -3890,7 +3888,7 @@ async function updateGroupViaLogs({
|
||||||
strictAssert(groupId != null, 'Group must have groupId');
|
strictAssert(groupId != null, 'Group must have groupId');
|
||||||
|
|
||||||
let cachedEndorsementsExpiration =
|
let cachedEndorsementsExpiration =
|
||||||
await dataInterface.getGroupSendCombinedEndorsementExpiration(groupId);
|
await DataReader.getGroupSendCombinedEndorsementExpiration(groupId);
|
||||||
|
|
||||||
let response: GroupLogResponseType;
|
let response: GroupLogResponseType;
|
||||||
let groupSendEndorsementResponse: Uint8Array | null = null;
|
let groupSendEndorsementResponse: Uint8Array | null = null;
|
||||||
|
@ -3925,7 +3923,7 @@ async function updateGroupViaLogs({
|
||||||
'updateGroupViaLogs: Received paginated response, deleting group endorsements'
|
'updateGroupViaLogs: Received paginated response, deleting group endorsements'
|
||||||
);
|
);
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await dataInterface.deleteAllEndorsementsForGroup(groupId);
|
await DataWriter.deleteAllEndorsementsForGroup(groupId);
|
||||||
cachedEndorsementsExpiration = null; // gets sent as 0 in header
|
cachedEndorsementsExpiration = null; // gets sent as 0 in header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3971,7 +3969,7 @@ async function updateGroupViaLogs({
|
||||||
groupSecretParamsBase64: secretParams,
|
groupSecretParamsBase64: secretParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
await dataInterface.replaceAllEndorsementsForGroup(groupEndorsementData);
|
await DataWriter.replaceAllEndorsementsForGroup(groupEndorsementData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return updates;
|
return updates;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import type { ConversationAttributesType } from '../model-types.d';
|
||||||
import type { ConversationModel } from '../models/conversations';
|
import type { ConversationModel } from '../models/conversations';
|
||||||
import type { PreJoinConversationType } from '../state/ducks/conversations';
|
import type { PreJoinConversationType } from '../state/ducks/conversations';
|
||||||
|
|
||||||
|
import { DataWriter } from '../sql/Client';
|
||||||
import * as Bytes from '../Bytes';
|
import * as Bytes from '../Bytes';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
@ -160,7 +161,7 @@ export async function joinViaLink(value: string): Promise<void> {
|
||||||
const active_at = existingConversation.get('active_at') || Date.now();
|
const active_at = existingConversation.get('active_at') || Date.now();
|
||||||
// eslint-disable-next-line camelcase
|
// eslint-disable-next-line camelcase
|
||||||
existingConversation.set({ active_at, timestamp });
|
existingConversation.set({ active_at, timestamp });
|
||||||
window.Signal.Data.updateConversation(existingConversation.attributes);
|
await DataWriter.updateConversation(existingConversation.attributes);
|
||||||
|
|
||||||
// We're waiting for the left pane to re-sort before we navigate to that conversation
|
// We're waiting for the left pane to re-sort before we navigate to that conversation
|
||||||
await sleep(200);
|
await sleep(200);
|
||||||
|
@ -320,7 +321,7 @@ export async function joinViaLink(value: string): Promise<void> {
|
||||||
temporaryMemberCount: memberCount,
|
temporaryMemberCount: memberCount,
|
||||||
timestamp,
|
timestamp,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(
|
await DataWriter.updateConversation(
|
||||||
targetConversation.attributes
|
targetConversation.attributes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -343,9 +344,7 @@ export async function joinViaLink(value: string): Promise<void> {
|
||||||
// We want to keep this conversation around, since the join succeeded
|
// We want to keep this conversation around, since the join succeeded
|
||||||
isTemporary: undefined,
|
isTemporary: undefined,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(
|
await DataWriter.updateConversation(tempConversation.attributes);
|
||||||
tempConversation.attributes
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.reduxActions.conversations.showConversation({
|
window.reduxActions.conversations.showConversation({
|
||||||
|
@ -357,7 +356,7 @@ export async function joinViaLink(value: string): Promise<void> {
|
||||||
window.ConversationController.dangerouslyRemoveById(
|
window.ConversationController.dangerouslyRemoveById(
|
||||||
tempConversation.id
|
tempConversation.id
|
||||||
);
|
);
|
||||||
await window.Signal.Data.removeConversation(tempConversation.id);
|
await DataWriter.removeConversation(tempConversation.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { PassThrough } from 'node:stream';
|
||||||
|
|
||||||
import * as durations from '../util/durations';
|
import * as durations from '../util/durations';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import dataInterface from '../sql/Client';
|
import { DataWriter } from '../sql/Client';
|
||||||
|
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import { redactGenericText } from '../util/privacy';
|
import { redactGenericText } from '../util/privacy';
|
||||||
|
@ -81,10 +81,10 @@ const THUMBNAIL_RETRY_CONFIG = {
|
||||||
export class AttachmentBackupManager extends JobManager<CoreAttachmentBackupJobType> {
|
export class AttachmentBackupManager extends JobManager<CoreAttachmentBackupJobType> {
|
||||||
private static _instance: AttachmentBackupManager | undefined;
|
private static _instance: AttachmentBackupManager | undefined;
|
||||||
static defaultParams: JobManagerParamsType<CoreAttachmentBackupJobType> = {
|
static defaultParams: JobManagerParamsType<CoreAttachmentBackupJobType> = {
|
||||||
markAllJobsInactive: dataInterface.markAllAttachmentBackupJobsInactive,
|
markAllJobsInactive: DataWriter.markAllAttachmentBackupJobsInactive,
|
||||||
saveJob: dataInterface.saveAttachmentBackupJob,
|
saveJob: DataWriter.saveAttachmentBackupJob,
|
||||||
removeJob: dataInterface.removeAttachmentBackupJob,
|
removeJob: DataWriter.removeAttachmentBackupJob,
|
||||||
getNextJobs: dataInterface.getNextAttachmentBackupJobs,
|
getNextJobs: DataWriter.getNextAttachmentBackupJobs,
|
||||||
runJob: runAttachmentBackupJob,
|
runJob: runAttachmentBackupJob,
|
||||||
shouldHoldOffOnStartingQueuedJobs: () => {
|
shouldHoldOffOnStartingQueuedJobs: () => {
|
||||||
const reduxState = window.reduxStore?.getState();
|
const reduxState = window.reduxStore?.getState();
|
||||||
|
@ -604,7 +604,7 @@ async function copyToBackupTier({
|
||||||
|
|
||||||
// Update our local understanding of what's in the backup cdn
|
// Update our local understanding of what's in the backup cdn
|
||||||
const sizeOnBackupCdn = getAesCbcCiphertextLength(ciphertextLength);
|
const sizeOnBackupCdn = getAesCbcCiphertextLength(ciphertextLength);
|
||||||
await window.Signal.Data.saveBackupCdnObjectMetadata([
|
await DataWriter.saveBackupCdnObjectMetadata([
|
||||||
{ mediaId, cdnNumber: response.cdn, sizeOnBackupCdn },
|
{ mediaId, cdnNumber: response.cdn, sizeOnBackupCdn },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
AttachmentPermanentlyUndownloadableError,
|
AttachmentPermanentlyUndownloadableError,
|
||||||
downloadAttachment as downloadAttachmentUtil,
|
downloadAttachment as downloadAttachmentUtil,
|
||||||
} from '../util/downloadAttachment';
|
} from '../util/downloadAttachment';
|
||||||
import dataInterface from '../sql/Client';
|
import { DataWriter } from '../sql/Client';
|
||||||
import { getValue } from '../RemoteConfig';
|
import { getValue } from '../RemoteConfig';
|
||||||
|
|
||||||
import { isInCall as isInCallSelector } from '../state/selectors/calling';
|
import { isInCall as isInCallSelector } from '../state/selectors/calling';
|
||||||
|
@ -103,10 +103,10 @@ export class AttachmentDownloadManager extends JobManager<CoreAttachmentDownload
|
||||||
override logPrefix = 'AttachmentDownloadManager';
|
override logPrefix = 'AttachmentDownloadManager';
|
||||||
|
|
||||||
static defaultParams: AttachmentDownloadManagerParamsType = {
|
static defaultParams: AttachmentDownloadManagerParamsType = {
|
||||||
markAllJobsInactive: dataInterface.resetAttachmentDownloadActive,
|
markAllJobsInactive: DataWriter.resetAttachmentDownloadActive,
|
||||||
saveJob: dataInterface.saveAttachmentDownloadJob,
|
saveJob: DataWriter.saveAttachmentDownloadJob,
|
||||||
removeJob: dataInterface.removeAttachmentDownloadJob,
|
removeJob: DataWriter.removeAttachmentDownloadJob,
|
||||||
getNextJobs: dataInterface.getNextAttachmentDownloadJobs,
|
getNextJobs: DataWriter.getNextAttachmentDownloadJobs,
|
||||||
runDownloadAttachmentJob,
|
runDownloadAttachmentJob,
|
||||||
shouldHoldOffOnStartingQueuedJobs: () => {
|
shouldHoldOffOnStartingQueuedJobs: () => {
|
||||||
const reduxState = window.reduxStore?.getState();
|
const reduxState = window.reduxStore?.getState();
|
||||||
|
@ -321,7 +321,7 @@ async function runDownloadAttachmentJob({
|
||||||
} finally {
|
} finally {
|
||||||
// This will fail if the message has been deleted before the download finished, which
|
// This will fail if the message has been deleted before the download finished, which
|
||||||
// is good
|
// is good
|
||||||
await dataInterface.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { AsyncQueue } from '../util/AsyncQueue';
|
||||||
import { concat, wrapPromise } from '../util/asyncIterables';
|
import { concat, wrapPromise } from '../util/asyncIterables';
|
||||||
import type { JobQueueStore, StoredJob } from './types';
|
import type { JobQueueStore, StoredJob } from './types';
|
||||||
import { formatJobForInsert } from './formatJobForInsert';
|
import { formatJobForInsert } from './formatJobForInsert';
|
||||||
import databaseInterface from '../sql/Client';
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
|
||||||
type Database = {
|
type Database = {
|
||||||
|
@ -107,6 +107,8 @@ export class JobQueueDatabaseStore implements JobQueueStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const jobQueueDatabaseStore = new JobQueueDatabaseStore(
|
export const jobQueueDatabaseStore = new JobQueueDatabaseStore({
|
||||||
databaseInterface
|
getJobsInQueue: DataReader.getJobsInQueue,
|
||||||
);
|
insertJob: DataWriter.insertJob,
|
||||||
|
deleteJob: DataWriter.deleteJob,
|
||||||
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as z from 'zod';
|
||||||
import type { LoggerType } from '../types/Logging';
|
import type { LoggerType } from '../types/Logging';
|
||||||
import { applyNewAvatar } from '../groups';
|
import { applyNewAvatar } from '../groups';
|
||||||
import { isGroupV2 } from '../util/whatTypeOfConversation';
|
import { isGroupV2 } from '../util/whatTypeOfConversation';
|
||||||
import Data from '../sql/Client';
|
import { DataWriter } from '../sql/Client';
|
||||||
|
|
||||||
import type { JOB_STATUS } from './JobQueue';
|
import type { JOB_STATUS } from './JobQueue';
|
||||||
import { JobQueue } from './JobQueue';
|
import { JobQueue } from './JobQueue';
|
||||||
|
@ -46,7 +46,7 @@ export class GroupAvatarJobQueue extends JobQueue<GroupAvatarJobData> {
|
||||||
const patch = await applyNewAvatar(newAvatarUrl, attributes, logId);
|
const patch = await applyNewAvatar(newAvatarUrl, attributes, logId);
|
||||||
|
|
||||||
convo.set(patch);
|
convo.set(patch);
|
||||||
await Data.updateConversation(convo.attributes);
|
await DataWriter.updateConversation(convo.attributes);
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
} from './handleMultipleSendErrors';
|
} from './handleMultipleSendErrors';
|
||||||
import { ourProfileKeyService } from '../../services/ourProfileKey';
|
import { ourProfileKeyService } from '../../services/ourProfileKey';
|
||||||
import { wrapWithSyncMessageSend } from '../../util/wrapWithSyncMessageSend';
|
import { wrapWithSyncMessageSend } from '../../util/wrapWithSyncMessageSend';
|
||||||
|
import { DataWriter } from '../../sql/Client';
|
||||||
|
|
||||||
import type { ConversationModel } from '../../models/conversations';
|
import type { ConversationModel } from '../../models/conversations';
|
||||||
import type {
|
import type {
|
||||||
|
@ -302,7 +303,7 @@ async function updateMessageWithSuccessfulSends(
|
||||||
deletedForEveryoneSendStatus: {},
|
deletedForEveryoneSendStatus: {},
|
||||||
deletedForEveryoneFailed: undefined,
|
deletedForEveryoneFailed: undefined,
|
||||||
});
|
});
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -325,7 +326,7 @@ async function updateMessageWithSuccessfulSends(
|
||||||
deletedForEveryoneSendStatus,
|
deletedForEveryoneSendStatus,
|
||||||
deletedForEveryoneFailed: undefined,
|
deletedForEveryoneFailed: undefined,
|
||||||
});
|
});
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -341,7 +342,7 @@ async function updateMessageWithFailure(
|
||||||
);
|
);
|
||||||
|
|
||||||
message.set({ deletedForEveryoneFailed: true });
|
message.set({ deletedForEveryoneFailed: true });
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
maybeExpandErrors,
|
maybeExpandErrors,
|
||||||
} from './handleMultipleSendErrors';
|
} from './handleMultipleSendErrors';
|
||||||
import { ourProfileKeyService } from '../../services/ourProfileKey';
|
import { ourProfileKeyService } from '../../services/ourProfileKey';
|
||||||
|
import { DataWriter } from '../../sql/Client';
|
||||||
|
|
||||||
import type { ConversationModel } from '../../models/conversations';
|
import type { ConversationModel } from '../../models/conversations';
|
||||||
import type {
|
import type {
|
||||||
|
@ -277,7 +278,7 @@ async function updateMessageWithSuccessfulSends(
|
||||||
deletedForEveryoneSendStatus: {},
|
deletedForEveryoneSendStatus: {},
|
||||||
deletedForEveryoneFailed: undefined,
|
deletedForEveryoneFailed: undefined,
|
||||||
});
|
});
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -300,7 +301,7 @@ async function updateMessageWithSuccessfulSends(
|
||||||
deletedForEveryoneSendStatus,
|
deletedForEveryoneSendStatus,
|
||||||
deletedForEveryoneFailed: undefined,
|
deletedForEveryoneFailed: undefined,
|
||||||
});
|
});
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -316,7 +317,7 @@ async function updateMessageWithFailure(
|
||||||
);
|
);
|
||||||
|
|
||||||
message.set({ deletedForEveryoneFailed: true });
|
message.set({ deletedForEveryoneFailed: true });
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { isNumber } from 'lodash';
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
import { v4 as generateUuid } from 'uuid';
|
import { v4 as generateUuid } from 'uuid';
|
||||||
|
|
||||||
|
import { DataWriter } from '../../sql/Client';
|
||||||
import * as Errors from '../../types/errors';
|
import * as Errors from '../../types/errors';
|
||||||
import { strictAssert } from '../../util/assert';
|
import { strictAssert } from '../../util/assert';
|
||||||
import type { MessageModel } from '../../models/messages';
|
import type { MessageModel } from '../../models/messages';
|
||||||
|
@ -650,7 +651,7 @@ async function getMessageSendData({
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Save message after uploading attachments
|
// Save message after uploading attachments
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1106,7 +1107,7 @@ async function markMessageFailed({
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
message.markFailed(targetTimestamp);
|
message.markFailed(targetTimestamp);
|
||||||
void message.saveErrors(errors, { skipSave: true });
|
void message.saveErrors(errors, { skipSave: true });
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import type { CallbackResultType } from '../../textsecure/Types.d';
|
||||||
import type { MessageModel } from '../../models/messages';
|
import type { MessageModel } from '../../models/messages';
|
||||||
import type { MessageReactionType } from '../../model-types.d';
|
import type { MessageReactionType } from '../../model-types.d';
|
||||||
import type { ConversationModel } from '../../models/conversations';
|
import type { ConversationModel } from '../../models/conversations';
|
||||||
|
import { DataWriter } from '../../sql/Client';
|
||||||
|
|
||||||
import * as reactionUtil from '../../reactions/util';
|
import * as reactionUtil from '../../reactions/util';
|
||||||
import { isSent, SendStatus } from '../../messages/MessageSendState';
|
import { isSent, SendStatus } from '../../messages/MessageSendState';
|
||||||
|
@ -86,7 +87,7 @@ export async function sendReaction(
|
||||||
if (!canReact(message.attributes, ourConversationId, findAndFormatContact)) {
|
if (!canReact(message.attributes, ourConversationId, findAndFormatContact)) {
|
||||||
log.info(`could not react to ${messageId}. Removing this pending reaction`);
|
log.info(`could not react to ${messageId}. Removing this pending reaction`);
|
||||||
markReactionFailed(message, pendingReaction);
|
markReactionFailed(message, pendingReaction);
|
||||||
await window.Signal.Data.saveMessage(message.attributes, { ourAci });
|
await DataWriter.saveMessage(message.attributes, { ourAci });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ export async function sendReaction(
|
||||||
`reacting to message ${messageId} ran out of time. Giving up on sending it`
|
`reacting to message ${messageId} ran out of time. Giving up on sending it`
|
||||||
);
|
);
|
||||||
markReactionFailed(message, pendingReaction);
|
markReactionFailed(message, pendingReaction);
|
||||||
await window.Signal.Data.saveMessage(message.attributes, { ourAci });
|
await DataWriter.saveMessage(message.attributes, { ourAci });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +336,7 @@ export async function sendReaction(
|
||||||
await reactionMessage.hydrateStoryContext(message.attributes, {
|
await reactionMessage.hydrateStoryContext(message.attributes, {
|
||||||
shouldSave: false,
|
shouldSave: false,
|
||||||
});
|
});
|
||||||
await window.Signal.Data.saveMessage(reactionMessage.attributes, {
|
await DataWriter.saveMessage(reactionMessage.attributes, {
|
||||||
ourAci,
|
ourAci,
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -374,7 +375,7 @@ export async function sendReaction(
|
||||||
toThrow: originalError || thrownError,
|
toThrow: originalError || thrownError,
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
await window.Signal.Data.saveMessage(message.attributes, { ourAci });
|
await DataWriter.saveMessage(message.attributes, { ourAci });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import type { ServiceIdString } from '../../types/ServiceId';
|
||||||
import type { StoryDistributionIdString } from '../../types/StoryDistributionId';
|
import type { StoryDistributionIdString } from '../../types/StoryDistributionId';
|
||||||
import * as Errors from '../../types/errors';
|
import * as Errors from '../../types/errors';
|
||||||
import type { StoryMessageRecipientsType } from '../../types/Stories';
|
import type { StoryMessageRecipientsType } from '../../types/Stories';
|
||||||
import dataInterface from '../../sql/Client';
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import { SignalService as Proto } from '../../protobuf';
|
import { SignalService as Proto } from '../../protobuf';
|
||||||
import { getMessagesById } from '../../messages/getMessagesById';
|
import { getMessagesById } from '../../messages/getMessagesById';
|
||||||
import {
|
import {
|
||||||
|
@ -252,7 +252,7 @@ export async function sendStory(
|
||||||
|
|
||||||
const distributionList = isGroupV2(conversation.attributes)
|
const distributionList = isGroupV2(conversation.attributes)
|
||||||
? undefined
|
? undefined
|
||||||
: await dataInterface.getStoryDistributionWithMembers(receiverId);
|
: await DataReader.getStoryDistributionWithMembers(receiverId);
|
||||||
|
|
||||||
let messageSendErrors: Array<Error> = [];
|
let messageSendErrors: Array<Error> = [];
|
||||||
|
|
||||||
|
@ -541,7 +541,7 @@ export async function sendStory(
|
||||||
}
|
}
|
||||||
|
|
||||||
message.set('sendStateByConversationId', newSendStateByConversationId);
|
message.set('sendStateByConversationId', newSendStateByConversationId);
|
||||||
return window.Signal.Data.saveMessage(message.attributes, {
|
return DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -688,7 +688,7 @@ async function markMessageFailed(
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
message.markFailed();
|
message.markFailed();
|
||||||
void message.saveErrors(errors, { skipSave: true });
|
void message.saveErrors(errors, { skipSave: true });
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { MessageAttributesType } from '../model-types.d';
|
import type { MessageAttributesType } from '../model-types.d';
|
||||||
import { getAuthorId } from '../messages/helpers';
|
import { getAuthorId } from '../messages/helpers';
|
||||||
|
import { DataReader } from '../sql/Client';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import { deleteForEveryone } from '../util/deleteForEveryone';
|
import { deleteForEveryone } from '../util/deleteForEveryone';
|
||||||
|
@ -72,7 +73,7 @@ export async function onDelete(del: DeleteAttributesType): Promise<void> {
|
||||||
targetConversation.queueJob('Deletes.onDelete', async () => {
|
targetConversation.queueJob('Deletes.onDelete', async () => {
|
||||||
log.info(`${logId}: Handling DOE`);
|
log.info(`${logId}: Handling DOE`);
|
||||||
|
|
||||||
const messages = await window.Signal.Data.getMessagesBySentAt(
|
const messages = await DataReader.getMessagesBySentAt(
|
||||||
del.targetSentTimestamp
|
del.targetSentTimestamp
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ import {
|
||||||
getConversationFromTarget,
|
getConversationFromTarget,
|
||||||
getMessageQueryFromTarget,
|
getMessageQueryFromTarget,
|
||||||
} from '../util/deleteForMe';
|
} from '../util/deleteForMe';
|
||||||
import dataInterface from '../sql/Client';
|
import { DataWriter } from '../sql/Client';
|
||||||
|
|
||||||
const { removeSyncTaskById } = dataInterface;
|
const { removeSyncTaskById } = DataWriter;
|
||||||
|
|
||||||
export type DeleteForMeAttributesType = {
|
export type DeleteForMeAttributesType = {
|
||||||
conversation: ConversationToDelete;
|
conversation: ConversationToDelete;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import type { MessageAttributesType } from '../model-types.d';
|
import type { MessageAttributesType } from '../model-types.d';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
import { DataReader } from '../sql/Client';
|
||||||
import { drop } from '../util/drop';
|
import { drop } from '../util/drop';
|
||||||
import { getAuthorId } from '../messages/helpers';
|
import { getAuthorId } from '../messages/helpers';
|
||||||
import { handleEditMessage } from '../util/handleEditMessage';
|
import { handleEditMessage } from '../util/handleEditMessage';
|
||||||
|
@ -117,7 +118,7 @@ export async function onEdit(edit: EditAttributesType): Promise<void> {
|
||||||
targetConversation.queueJob('Edits.onEdit', async () => {
|
targetConversation.queueJob('Edits.onEdit', async () => {
|
||||||
log.info(`${logId}: Handling edit`);
|
log.info(`${logId}: Handling edit`);
|
||||||
|
|
||||||
const messages = await window.Signal.Data.getMessagesBySentAt(
|
const messages = await DataReader.getMessagesBySentAt(
|
||||||
edit.targetSentTimestamp
|
edit.targetSentTimestamp
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ import {
|
||||||
UNDELIVERED_SEND_STATUSES,
|
UNDELIVERED_SEND_STATUSES,
|
||||||
sendStateReducer,
|
sendStateReducer,
|
||||||
} from '../messages/MessageSendState';
|
} from '../messages/MessageSendState';
|
||||||
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import type { DeleteSentProtoRecipientOptionsType } from '../sql/Interface';
|
import type { DeleteSentProtoRecipientOptionsType } from '../sql/Interface';
|
||||||
import dataInterface from '../sql/Client';
|
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { getSourceServiceId } from '../messages/helpers';
|
import { getSourceServiceId } from '../messages/helpers';
|
||||||
import { getMessageSentTimestamp } from '../util/getMessageSentTimestamp';
|
import { getMessageSentTimestamp } from '../util/getMessageSentTimestamp';
|
||||||
|
@ -31,7 +31,7 @@ import {
|
||||||
} from '../types/Receipt';
|
} from '../types/Receipt';
|
||||||
import { drop } from '../util/drop';
|
import { drop } from '../util/drop';
|
||||||
|
|
||||||
const { deleteSentProtoRecipient, removeSyncTaskById } = dataInterface;
|
const { deleteSentProtoRecipient, removeSyncTaskById } = DataWriter;
|
||||||
|
|
||||||
export const messageReceiptTypeSchema = z.enum(['Delivery', 'Read', 'View']);
|
export const messageReceiptTypeSchema = z.enum(['Delivery', 'Read', 'View']);
|
||||||
|
|
||||||
|
@ -99,11 +99,11 @@ const processReceiptBatcher = createWaitBatcher({
|
||||||
|
|
||||||
const messagesMatchingTimestamp =
|
const messagesMatchingTimestamp =
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await window.Signal.Data.getMessagesBySentAt(sentAt);
|
await DataReader.getMessagesBySentAt(sentAt);
|
||||||
|
|
||||||
if (messagesMatchingTimestamp.length === 0) {
|
if (messagesMatchingTimestamp.length === 0) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
const reaction = await window.Signal.Data.getReactionByTimestamp(
|
const reaction = await DataReader.getReactionByTimestamp(
|
||||||
window.ConversationController.getOurConversationIdOrThrow(),
|
window.ConversationController.getOurConversationIdOrThrow(),
|
||||||
sentAt
|
sentAt
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import type { AciString } from '../types/ServiceId';
|
||||||
import type { MessageAttributesType } from '../model-types.d';
|
import type { MessageAttributesType } from '../model-types.d';
|
||||||
import type { MessageModel } from '../models/messages';
|
import type { MessageModel } from '../models/messages';
|
||||||
import type { ReactionSource } from '../reactions/ReactionSource';
|
import type { ReactionSource } from '../reactions/ReactionSource';
|
||||||
|
import { DataReader } from '../sql/Client';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { getAuthor } from '../messages/helpers';
|
import { getAuthor } from '../messages/helpers';
|
||||||
|
@ -66,9 +67,7 @@ async function findMessageForReaction({
|
||||||
reactionSenderConversationId: string;
|
reactionSenderConversationId: string;
|
||||||
logId: string;
|
logId: string;
|
||||||
}): Promise<MessageAttributesType | undefined> {
|
}): Promise<MessageAttributesType | undefined> {
|
||||||
const messages = await window.Signal.Data.getMessagesBySentAt(
|
const messages = await DataReader.getMessagesBySentAt(targetTimestamp);
|
||||||
targetTimestamp
|
|
||||||
);
|
|
||||||
|
|
||||||
const matchingMessages = messages.filter(message =>
|
const matchingMessages = messages.filter(message =>
|
||||||
isMessageAMatchForReaction({
|
isMessageAMatchForReaction({
|
||||||
|
|
|
@ -16,9 +16,9 @@ import { notificationService } from '../services/notifications';
|
||||||
import { queueUpdateMessage } from '../util/messageBatcher';
|
import { queueUpdateMessage } from '../util/messageBatcher';
|
||||||
import { strictAssert } from '../util/assert';
|
import { strictAssert } from '../util/assert';
|
||||||
import { isAciString } from '../util/isAciString';
|
import { isAciString } from '../util/isAciString';
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
|
|
||||||
const { removeSyncTaskById } = dataInterface;
|
const { removeSyncTaskById } = DataWriter;
|
||||||
|
|
||||||
export const readSyncTaskSchema = z.object({
|
export const readSyncTaskSchema = z.object({
|
||||||
type: z.literal('ReadSync').readonly(),
|
type: z.literal('ReadSync').readonly(),
|
||||||
|
@ -51,7 +51,7 @@ async function maybeItIsAReactionReadSync(
|
||||||
const { readSync } = sync;
|
const { readSync } = sync;
|
||||||
const logId = `ReadSyncs.onSync(timestamp=${readSync.timestamp})`;
|
const logId = `ReadSyncs.onSync(timestamp=${readSync.timestamp})`;
|
||||||
|
|
||||||
const readReaction = await window.Signal.Data.markReactionAsRead(
|
const readReaction = await DataWriter.markReactionAsRead(
|
||||||
readSync.senderAci,
|
readSync.senderAci,
|
||||||
Number(readSync.timestamp)
|
Number(readSync.timestamp)
|
||||||
);
|
);
|
||||||
|
@ -129,9 +129,7 @@ export async function onSync(sync: ReadSyncAttributesType): Promise<void> {
|
||||||
const logId = `ReadSyncs.onSync(timestamp=${readSync.timestamp})`;
|
const logId = `ReadSyncs.onSync(timestamp=${readSync.timestamp})`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const messages = await window.Signal.Data.getMessagesBySentAt(
|
const messages = await DataReader.getMessagesBySentAt(readSync.timestamp);
|
||||||
readSync.timestamp
|
|
||||||
);
|
|
||||||
|
|
||||||
const found = messages.find(item => {
|
const found = messages.find(item => {
|
||||||
const sender = window.ConversationController.lookupOrCreate({
|
const sender = window.ConversationController.lookupOrCreate({
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { AciString } from '../types/ServiceId';
|
import type { AciString } from '../types/ServiceId';
|
||||||
import type { MessageModel } from '../models/messages';
|
import type { MessageModel } from '../models/messages';
|
||||||
|
import { DataReader } from '../sql/Client';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { getMessageIdForLogging } from '../util/idForLogging';
|
import { getMessageIdForLogging } from '../util/idForLogging';
|
||||||
|
@ -66,9 +67,7 @@ export async function onSync(
|
||||||
const logId = `ViewOnceOpenSyncs.onSync(timestamp=${sync.timestamp})`;
|
const logId = `ViewOnceOpenSyncs.onSync(timestamp=${sync.timestamp})`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const messages = await window.Signal.Data.getMessagesBySentAt(
|
const messages = await DataReader.getMessagesBySentAt(sync.timestamp);
|
||||||
sync.timestamp
|
|
||||||
);
|
|
||||||
|
|
||||||
const found = messages.find(item => {
|
const found = messages.find(item => {
|
||||||
const itemSourceAci = item.sourceServiceId;
|
const itemSourceAci = item.sourceServiceId;
|
||||||
|
|
|
@ -18,9 +18,7 @@ import { queueAttachmentDownloads } from '../util/queueAttachmentDownloads';
|
||||||
import { queueUpdateMessage } from '../util/messageBatcher';
|
import { queueUpdateMessage } from '../util/messageBatcher';
|
||||||
import { AttachmentDownloadUrgency } from '../jobs/AttachmentDownloadManager';
|
import { AttachmentDownloadUrgency } from '../jobs/AttachmentDownloadManager';
|
||||||
import { isAciString } from '../util/isAciString';
|
import { isAciString } from '../util/isAciString';
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
|
|
||||||
const { removeSyncTaskById } = dataInterface;
|
|
||||||
|
|
||||||
export const viewSyncTaskSchema = z.object({
|
export const viewSyncTaskSchema = z.object({
|
||||||
type: z.literal('ViewSync').readonly(),
|
type: z.literal('ViewSync').readonly(),
|
||||||
|
@ -42,7 +40,7 @@ export type ViewSyncAttributesType = {
|
||||||
const viewSyncs = new Map<string, ViewSyncAttributesType>();
|
const viewSyncs = new Map<string, ViewSyncAttributesType>();
|
||||||
|
|
||||||
async function remove(sync: ViewSyncAttributesType): Promise<void> {
|
async function remove(sync: ViewSyncAttributesType): Promise<void> {
|
||||||
await removeSyncTaskById(sync.syncTaskId);
|
await DataWriter.removeSyncTaskById(sync.syncTaskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function forMessage(
|
export async function forMessage(
|
||||||
|
@ -92,9 +90,7 @@ export async function onSync(sync: ViewSyncAttributesType): Promise<void> {
|
||||||
const logId = `ViewSyncs.onSync(timestamp=${viewSync.timestamp})`;
|
const logId = `ViewSyncs.onSync(timestamp=${viewSync.timestamp})`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const messages = await window.Signal.Data.getMessagesBySentAt(
|
const messages = await DataReader.getMessagesBySentAt(viewSync.timestamp);
|
||||||
viewSync.timestamp
|
|
||||||
);
|
|
||||||
|
|
||||||
const found = messages.find(item => {
|
const found = messages.find(item => {
|
||||||
const sender = window.ConversationController.lookupOrCreate({
|
const sender = window.ConversationController.lookupOrCreate({
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import type { QuotedMessageType } from '../model-types';
|
import type { QuotedMessageType } from '../model-types';
|
||||||
import type { MessageModel } from '../models/messages';
|
import type { MessageModel } from '../models/messages';
|
||||||
import { SignalService } from '../protobuf';
|
import { SignalService } from '../protobuf';
|
||||||
|
@ -50,7 +51,7 @@ export const copyFromQuotedMessage = async (
|
||||||
queryMessage = matchingMessage;
|
queryMessage = matchingMessage;
|
||||||
} else {
|
} else {
|
||||||
log.info('copyFromQuotedMessage: db lookup needed', id);
|
log.info('copyFromQuotedMessage: db lookup needed', id);
|
||||||
const messages = await window.Signal.Data.getMessagesBySentAt(id);
|
const messages = await DataReader.getMessagesBySentAt(id);
|
||||||
const found = messages.find(item =>
|
const found = messages.find(item =>
|
||||||
isQuoteAMatch(item, conversationId, result)
|
isQuoteAMatch(item, conversationId, result)
|
||||||
);
|
);
|
||||||
|
@ -142,7 +143,7 @@ export const copyQuoteContentFromOriginal = async (
|
||||||
originalMessage.attributes
|
originalMessage.attributes
|
||||||
);
|
);
|
||||||
originalMessage.set(upgradedMessage);
|
originalMessage.set(upgradedMessage);
|
||||||
await window.Signal.Data.saveMessage(upgradedMessage, {
|
await DataWriter.saveMessage(upgradedMessage, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
import { DataReader } from '../sql/Client';
|
||||||
import type { MessageAttributesType } from '../model-types.d';
|
import type { MessageAttributesType } from '../model-types.d';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import type { MessageModel } from '../models/messages';
|
import type { MessageModel } from '../models/messages';
|
||||||
|
@ -16,7 +17,7 @@ export async function __DEPRECATED$getMessageById(
|
||||||
|
|
||||||
let found: MessageAttributesType | undefined;
|
let found: MessageAttributesType | undefined;
|
||||||
try {
|
try {
|
||||||
found = await window.Signal.Data.getMessageById(messageId);
|
found = await DataReader.getMessageById(messageId);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
log.error(
|
log.error(
|
||||||
`failed to load message with id ${messageId} ` +
|
`failed to load message with id ${messageId} ` +
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
import { DataReader } from '../sql/Client';
|
||||||
import type { MessageModel } from '../models/messages';
|
import type { MessageModel } from '../models/messages';
|
||||||
import type { MessageAttributesType } from '../model-types.d';
|
import type { MessageAttributesType } from '../model-types.d';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
|
@ -23,7 +24,7 @@ export async function getMessagesById(
|
||||||
|
|
||||||
let rawMessagesFromDatabase: Array<MessageAttributesType>;
|
let rawMessagesFromDatabase: Array<MessageAttributesType>;
|
||||||
try {
|
try {
|
||||||
rawMessagesFromDatabase = await window.Signal.Data.getMessagesById(
|
rawMessagesFromDatabase = await DataReader.getMessagesById(
|
||||||
messageIdsToLookUpInDatabase
|
messageIdsToLookUpInDatabase
|
||||||
);
|
);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import type {
|
||||||
QuotedMessageType,
|
QuotedMessageType,
|
||||||
SenderKeyInfoType,
|
SenderKeyInfoType,
|
||||||
} from '../model-types.d';
|
} from '../model-types.d';
|
||||||
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import { getConversation } from '../util/getConversation';
|
import { getConversation } from '../util/getConversation';
|
||||||
import { drop } from '../util/drop';
|
import { drop } from '../util/drop';
|
||||||
import { isShallowEqual } from '../util/isShallowEqual';
|
import { isShallowEqual } from '../util/isShallowEqual';
|
||||||
|
@ -195,7 +196,6 @@ const {
|
||||||
writeNewAttachmentData,
|
writeNewAttachmentData,
|
||||||
} = window.Signal.Migrations;
|
} = window.Signal.Migrations;
|
||||||
const {
|
const {
|
||||||
addStickerPackReference,
|
|
||||||
getConversationRangeCenteredOnMessage,
|
getConversationRangeCenteredOnMessage,
|
||||||
getOlderMessagesByConversation,
|
getOlderMessagesByConversation,
|
||||||
getMessageMetricsForConversation,
|
getMessageMetricsForConversation,
|
||||||
|
@ -203,7 +203,8 @@ const {
|
||||||
getMostRecentAddressableMessages,
|
getMostRecentAddressableMessages,
|
||||||
getMostRecentAddressableNondisappearingMessages,
|
getMostRecentAddressableNondisappearingMessages,
|
||||||
getNewerMessagesByConversation,
|
getNewerMessagesByConversation,
|
||||||
} = window.Signal.Data;
|
} = DataReader;
|
||||||
|
const { addStickerPackReference } = DataWriter;
|
||||||
|
|
||||||
const FIVE_MINUTES = MINUTE * 5;
|
const FIVE_MINUTES = MINUTE * 5;
|
||||||
const FETCH_TIMEOUT = SECOND * 30;
|
const FETCH_TIMEOUT = SECOND * 30;
|
||||||
|
@ -471,7 +472,7 @@ export class ConversationModel extends window.Backbone
|
||||||
getSenderKeyInfo: () => this.get('senderKeyInfo'),
|
getSenderKeyInfo: () => this.get('senderKeyInfo'),
|
||||||
saveSenderKeyInfo: async (senderKeyInfo: SenderKeyInfoType) => {
|
saveSenderKeyInfo: async (senderKeyInfo: SenderKeyInfoType) => {
|
||||||
this.set({ senderKeyInfo });
|
this.set({ senderKeyInfo });
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -828,7 +829,7 @@ export class ConversationModel extends window.Backbone
|
||||||
});
|
});
|
||||||
|
|
||||||
if (shouldSave) {
|
if (shouldSave) {
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
const e164 = this.get('e164');
|
const e164 = this.get('e164');
|
||||||
|
@ -882,7 +883,7 @@ export class ConversationModel extends window.Backbone
|
||||||
});
|
});
|
||||||
|
|
||||||
if (shouldSave) {
|
if (shouldSave) {
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -1015,7 +1016,7 @@ export class ConversationModel extends window.Backbone
|
||||||
drop(this.queueJob('removeContact', () => this.maybeSetContactRemoved()));
|
drop(this.queueJob('removeContact', () => this.maybeSetContactRemoved()));
|
||||||
|
|
||||||
if (shouldSave) {
|
if (shouldSave) {
|
||||||
await window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,7 +1049,7 @@ export class ConversationModel extends window.Backbone
|
||||||
await this.maybeClearContactRemoved();
|
await this.maybeClearContactRemoved();
|
||||||
|
|
||||||
if (shouldSave) {
|
if (shouldSave) {
|
||||||
await window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1239,7 +1240,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
this.set({ masterKey, secretParams, publicParams, groupVersion: 2 });
|
this.set({ masterKey, secretParams, publicParams, groupVersion: 2 });
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
getGroupV2Info(
|
getGroupV2Info(
|
||||||
|
@ -1429,7 +1430,7 @@ export class ConversationModel extends window.Backbone
|
||||||
removalStage: 'messageRequest',
|
removalStage: 'messageRequest',
|
||||||
});
|
});
|
||||||
await this.maybeClearContactRemoved();
|
await this.maybeClearContactRemoved();
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void this.addSingleMessage(message);
|
void this.addSingleMessage(message);
|
||||||
|
@ -1831,7 +1832,7 @@ export class ConversationModel extends window.Backbone
|
||||||
const upgradedMessage = await upgradeMessageSchema(attributes);
|
const upgradedMessage = await upgradeMessageSchema(attributes);
|
||||||
message.set(upgradedMessage);
|
message.set(upgradedMessage);
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await window.Signal.Data.saveMessage(upgradedMessage, { ourAci });
|
await DataWriter.saveMessage(upgradedMessage, { ourAci });
|
||||||
upgraded += 1;
|
upgraded += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1900,7 +1901,7 @@ export class ConversationModel extends window.Backbone
|
||||||
void this.addChangeNumberNotification(oldValue, e164);
|
void this.addChangeNumberNotification(oldValue, e164);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
this.trigger('idUpdated', this, 'e164', oldValue);
|
this.trigger('idUpdated', this, 'e164', oldValue);
|
||||||
this.captureChange('updateE164');
|
this.captureChange('updateE164');
|
||||||
}
|
}
|
||||||
|
@ -1917,7 +1918,7 @@ export class ConversationModel extends window.Backbone
|
||||||
? normalizeServiceId(serviceId, 'Conversation.updateServiceId')
|
? normalizeServiceId(serviceId, 'Conversation.updateServiceId')
|
||||||
: undefined
|
: undefined
|
||||||
);
|
);
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
this.trigger('idUpdated', this, 'serviceId', oldValue);
|
this.trigger('idUpdated', this, 'serviceId', oldValue);
|
||||||
|
|
||||||
// We should delete the old sessions and identity information in all situations except
|
// We should delete the old sessions and identity information in all situations except
|
||||||
|
@ -1950,7 +1951,7 @@ export class ConversationModel extends window.Backbone
|
||||||
this.set({
|
this.set({
|
||||||
previousIdentityKey: identityKey,
|
previousIdentityKey: identityKey,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePni(pni: PniString | undefined, pniSignatureVerified: boolean): void {
|
updatePni(pni: PniString | undefined, pniSignatureVerified: boolean): void {
|
||||||
|
@ -2025,7 +2026,7 @@ export class ConversationModel extends window.Backbone
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
this.trigger('idUpdated', this, 'pni', oldValue);
|
this.trigger('idUpdated', this, 'pni', oldValue);
|
||||||
this.captureChange('updatePni');
|
this.captureChange('updatePni');
|
||||||
}
|
}
|
||||||
|
@ -2034,7 +2035,7 @@ export class ConversationModel extends window.Backbone
|
||||||
const oldValue = this.get('groupId');
|
const oldValue = this.get('groupId');
|
||||||
if (groupId && groupId !== oldValue) {
|
if (groupId && groupId !== oldValue) {
|
||||||
this.set('groupId', groupId);
|
this.set('groupId', groupId);
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
this.trigger('idUpdated', this, 'groupId', oldValue);
|
this.trigger('idUpdated', this, 'groupId', oldValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2048,14 +2049,14 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set('reportingToken', newValue);
|
this.set('reportingToken', newValue);
|
||||||
await window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
incrementMessageCount(): void {
|
incrementMessageCount(): void {
|
||||||
this.set({
|
this.set({
|
||||||
messageCount: (this.get('messageCount') || 0) + 1,
|
messageCount: (this.get('messageCount') || 0) + 1,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
incrementSentMessageCount({ dry = false }: { dry?: boolean } = {}):
|
incrementSentMessageCount({ dry = false }: { dry?: boolean } = {}):
|
||||||
|
@ -2073,7 +2074,7 @@ export class ConversationModel extends window.Backbone
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
this.set(update);
|
this.set(update);
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -2093,7 +2094,7 @@ export class ConversationModel extends window.Backbone
|
||||||
const first = messages ? messages[0] : undefined;
|
const first = messages ? messages[0] : undefined;
|
||||||
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
messages = await window.Signal.Data.getOlderMessagesByConversation({
|
messages = await DataReader.getOlderMessagesByConversation({
|
||||||
conversationId: this.get('id'),
|
conversationId: this.get('id'),
|
||||||
includeStoryReplies: !isGroup(this.attributes),
|
includeStoryReplies: !isGroup(this.attributes),
|
||||||
limit: 100,
|
limit: 100,
|
||||||
|
@ -2143,7 +2144,7 @@ export class ConversationModel extends window.Backbone
|
||||||
);
|
);
|
||||||
const shouldSave = await registered.queueAttachmentDownloads();
|
const shouldSave = await registered.queueAttachmentDownloads();
|
||||||
if (shouldSave) {
|
if (shouldSave) {
|
||||||
await window.Signal.Data.saveMessage(registered.attributes, {
|
await DataWriter.saveMessage(registered.attributes, {
|
||||||
ourAci,
|
ourAci,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2178,7 +2179,7 @@ export class ConversationModel extends window.Backbone
|
||||||
messageRequestResponseEvent: event,
|
messageRequestResponseEvent: event,
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = await window.Signal.Data.saveMessage(message, {
|
const id = await DataWriter.saveMessage(message, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -2358,7 +2359,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (shouldSave) {
|
if (shouldSave) {
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2439,7 +2440,7 @@ export class ConversationModel extends window.Backbone
|
||||||
messageRequestResponseType: messageRequestEnum.ACCEPT,
|
messageRequestResponseType: messageRequestEnum.ACCEPT,
|
||||||
active_at: this.get('active_at') || Date.now(),
|
active_at: this.get('active_at') || Date.now(),
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
async cancelJoinRequest(): Promise<void> {
|
async cancelJoinRequest(): Promise<void> {
|
||||||
|
@ -2631,7 +2632,7 @@ export class ConversationModel extends window.Backbone
|
||||||
if (oldVerified !== verified) {
|
if (oldVerified !== verified) {
|
||||||
this.set({ verified });
|
this.set({ verified });
|
||||||
this.captureChange(`updateVerified from=${oldVerified} to=${verified}`);
|
this.captureChange(`updateVerified from=${oldVerified} to=${verified}`);
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -2694,7 +2695,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
this.set({ verified });
|
this.set({ verified });
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
|
|
||||||
if (beginningVerified !== verified) {
|
if (beginningVerified !== verified) {
|
||||||
this.captureChange(
|
this.captureChange(
|
||||||
|
@ -2938,7 +2939,7 @@ export class ConversationModel extends window.Backbone
|
||||||
// this type does not fully implement the interface it is expected to
|
// this type does not fully implement the interface it is expected to
|
||||||
} as unknown as MessageAttributesType;
|
} as unknown as MessageAttributesType;
|
||||||
|
|
||||||
const id = await window.Signal.Data.saveMessage(message, {
|
const id = await DataWriter.saveMessage(message, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
const model = window.MessageCache.__DEPRECATED$register(
|
const model = window.MessageCache.__DEPRECATED$register(
|
||||||
|
@ -2990,7 +2991,7 @@ export class ConversationModel extends window.Backbone
|
||||||
// this type does not fully implement the interface it is expected to
|
// this type does not fully implement the interface it is expected to
|
||||||
} as unknown as MessageAttributesType;
|
} as unknown as MessageAttributesType;
|
||||||
|
|
||||||
const id = await window.Signal.Data.saveMessage(message, {
|
const id = await DataWriter.saveMessage(message, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
const model = window.MessageCache.__DEPRECATED$register(
|
const model = window.MessageCache.__DEPRECATED$register(
|
||||||
|
@ -3044,7 +3045,7 @@ export class ConversationModel extends window.Backbone
|
||||||
schemaVersion: Message.VERSION_NEEDED_FOR_DISPLAY,
|
schemaVersion: Message.VERSION_NEEDED_FOR_DISPLAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
await window.Signal.Data.saveMessage(message, {
|
await DataWriter.saveMessage(message, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -3108,7 +3109,7 @@ export class ConversationModel extends window.Backbone
|
||||||
schemaVersion: Message.VERSION_NEEDED_FOR_DISPLAY,
|
schemaVersion: Message.VERSION_NEEDED_FOR_DISPLAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = await window.Signal.Data.saveMessage(message, {
|
const id = await DataWriter.saveMessage(message, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -3161,7 +3162,7 @@ export class ConversationModel extends window.Backbone
|
||||||
schemaVersion: Message.VERSION_NEEDED_FOR_DISPLAY,
|
schemaVersion: Message.VERSION_NEEDED_FOR_DISPLAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = await window.Signal.Data.saveMessage(message, {
|
const id = await DataWriter.saveMessage(message, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -3212,7 +3213,7 @@ export class ConversationModel extends window.Backbone
|
||||||
verifiedChanged: verifiedChangeId,
|
verifiedChanged: verifiedChangeId,
|
||||||
};
|
};
|
||||||
|
|
||||||
await window.Signal.Data.saveMessage(message, {
|
await DataWriter.saveMessage(message, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -3255,7 +3256,7 @@ export class ConversationModel extends window.Backbone
|
||||||
// TODO: DESKTOP-722
|
// TODO: DESKTOP-722
|
||||||
} as unknown as MessageAttributesType;
|
} as unknown as MessageAttributesType;
|
||||||
|
|
||||||
const id = await window.Signal.Data.saveMessage(message, {
|
const id = await DataWriter.saveMessage(message, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
const model = window.MessageCache.__DEPRECATED$register(
|
const model = window.MessageCache.__DEPRECATED$register(
|
||||||
|
@ -3300,7 +3301,7 @@ export class ConversationModel extends window.Backbone
|
||||||
...extra,
|
...extra,
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = await window.Signal.Data.saveMessage(
|
const id = await DataWriter.saveMessage(
|
||||||
// TODO: DESKTOP-722
|
// TODO: DESKTOP-722
|
||||||
message as MessageAttributesType,
|
message as MessageAttributesType,
|
||||||
{
|
{
|
||||||
|
@ -3395,7 +3396,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
const message = window.MessageCache.__DEPRECATED$getById(notificationId);
|
const message = window.MessageCache.__DEPRECATED$getById(notificationId);
|
||||||
if (message) {
|
if (message) {
|
||||||
await window.Signal.Data.removeMessage(message.id, {
|
await DataWriter.removeMessage(message.id, {
|
||||||
singleProtoJobQueue,
|
singleProtoJobQueue,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3422,7 +3423,7 @@ export class ConversationModel extends window.Backbone
|
||||||
'contact-removed-notification'
|
'contact-removed-notification'
|
||||||
);
|
);
|
||||||
this.set('pendingRemovedContactNotification', notificationId);
|
this.set('pendingRemovedContactNotification', notificationId);
|
||||||
await window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
async maybeClearContactRemoved(): Promise<boolean> {
|
async maybeClearContactRemoved(): Promise<boolean> {
|
||||||
|
@ -3438,7 +3439,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
const message = window.MessageCache.__DEPRECATED$getById(notificationId);
|
const message = window.MessageCache.__DEPRECATED$getById(notificationId);
|
||||||
if (message) {
|
if (message) {
|
||||||
await window.Signal.Data.removeMessage(message.id, {
|
await DataWriter.removeMessage(message.id, {
|
||||||
singleProtoJobQueue,
|
singleProtoJobQueue,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4015,7 +4016,7 @@ export class ConversationModel extends window.Backbone
|
||||||
log.info(
|
log.info(
|
||||||
`enqueueMessageForSend: saving message ${message.id} and job ${jobToInsert.id}`
|
`enqueueMessageForSend: saving message ${message.id} and job ${jobToInsert.id}`
|
||||||
);
|
);
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
jobToInsert,
|
jobToInsert,
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
|
@ -4063,7 +4064,7 @@ export class ConversationModel extends window.Backbone
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
|
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
@ -4127,7 +4128,7 @@ export class ConversationModel extends window.Backbone
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
this.captureChange('clearUsername');
|
this.captureChange('clearUsername');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4152,7 +4153,7 @@ export class ConversationModel extends window.Backbone
|
||||||
this.captureChange('updateUsername');
|
this.captureChange('updateUsername');
|
||||||
|
|
||||||
if (shouldSave) {
|
if (shouldSave) {
|
||||||
await window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4169,7 +4170,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
const conversationId = this.id;
|
const conversationId = this.id;
|
||||||
|
|
||||||
const stats = await window.Signal.Data.getConversationMessageStats({
|
const stats = await DataReader.getConversationMessageStats({
|
||||||
conversationId,
|
conversationId,
|
||||||
includeStoryReplies: !isGroup(this.attributes),
|
includeStoryReplies: !isGroup(this.attributes),
|
||||||
});
|
});
|
||||||
|
@ -4256,14 +4257,14 @@ export class ConversationModel extends window.Backbone
|
||||||
: false,
|
: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
setArchived(isArchived: boolean): void {
|
setArchived(isArchived: boolean): void {
|
||||||
const before = this.get('isArchived');
|
const before = this.get('isArchived');
|
||||||
|
|
||||||
this.set({ isArchived });
|
this.set({ isArchived });
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
|
|
||||||
const after = this.get('isArchived');
|
const after = this.get('isArchived');
|
||||||
|
|
||||||
|
@ -4279,7 +4280,7 @@ export class ConversationModel extends window.Backbone
|
||||||
const previousMarkedUnread = this.get('markedUnread');
|
const previousMarkedUnread = this.get('markedUnread');
|
||||||
|
|
||||||
this.set({ markedUnread });
|
this.set({ markedUnread });
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
|
|
||||||
if (Boolean(previousMarkedUnread) !== Boolean(markedUnread)) {
|
if (Boolean(previousMarkedUnread) !== Boolean(markedUnread)) {
|
||||||
this.captureChange('markedUnread');
|
this.captureChange('markedUnread');
|
||||||
|
@ -4562,7 +4563,7 @@ export class ConversationModel extends window.Backbone
|
||||||
// the pending flags.
|
// the pending flags.
|
||||||
await this.maybeRemoveUniversalTimer();
|
await this.maybeRemoveUniversalTimer();
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
|
|
||||||
// When we add a disappearing messages notification to the conversation, we want it
|
// When we add a disappearing messages notification to the conversation, we want it
|
||||||
// to be above the message that initiated that change, hence the subtraction.
|
// to be above the message that initiated that change, hence the subtraction.
|
||||||
|
@ -4596,7 +4597,7 @@ export class ConversationModel extends window.Backbone
|
||||||
type: 'timer-notification' as const,
|
type: 'timer-notification' as const,
|
||||||
};
|
};
|
||||||
|
|
||||||
await window.Signal.Data.saveMessage(attributes, {
|
await DataWriter.saveMessage(attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -4655,11 +4656,8 @@ export class ConversationModel extends window.Backbone
|
||||||
includeStoryReplies: !isGroup(this.attributes),
|
includeStoryReplies: !isGroup(this.attributes),
|
||||||
};
|
};
|
||||||
const [unreadCount, unreadMentionsCount] = await Promise.all([
|
const [unreadCount, unreadMentionsCount] = await Promise.all([
|
||||||
window.Signal.Data.getTotalUnreadForConversation(this.id, options),
|
DataReader.getTotalUnreadForConversation(this.id, options),
|
||||||
window.Signal.Data.getTotalUnreadMentionsOfMeForConversation(
|
DataReader.getTotalUnreadMentionsOfMeForConversation(this.id, options),
|
||||||
this.id,
|
|
||||||
options
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const prevUnreadCount = this.get('unreadCount');
|
const prevUnreadCount = this.get('unreadCount');
|
||||||
|
@ -4672,7 +4670,7 @@ export class ConversationModel extends window.Backbone
|
||||||
unreadCount,
|
unreadCount,
|
||||||
unreadMentionsCount,
|
unreadMentionsCount,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4870,7 +4868,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
// We will update the conversation during storage service sync
|
// We will update the conversation during storage service sync
|
||||||
if (!viaStorageServiceSync) {
|
if (!viaStorageServiceSync) {
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -4971,7 +4969,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
this.set({ lastProfile: { profileKey, profileKeyVersion } });
|
this.set({ lastProfile: { profileKey, profileKeyVersion } });
|
||||||
|
|
||||||
await window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeLastProfile(
|
async removeLastProfile(
|
||||||
|
@ -4997,7 +4995,7 @@ export class ConversationModel extends window.Backbone
|
||||||
profileAvatar: undefined,
|
profileAvatar: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
await window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasMember(serviceId: ServiceIdString): boolean {
|
hasMember(serviceId: ServiceIdString): boolean {
|
||||||
|
@ -5044,7 +5042,7 @@ export class ConversationModel extends window.Backbone
|
||||||
active_at: null,
|
active_at: null,
|
||||||
pendingUniversalTimer: undefined,
|
pendingUniversalTimer: undefined,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
await DataWriter.updateConversation(this.attributes);
|
||||||
|
|
||||||
const ourConversation =
|
const ourConversation =
|
||||||
window.ConversationController.getOurConversationOrThrow();
|
window.ConversationController.getOurConversationOrThrow();
|
||||||
|
@ -5114,7 +5112,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info(`${logId}: Starting delete`);
|
log.info(`${logId}: Starting delete`);
|
||||||
await window.Signal.Data.removeMessagesInConversation(this.id, {
|
await DataWriter.removeMessagesInConversation(this.id, {
|
||||||
fromSync: source !== 'local-delete-sync',
|
fromSync: source !== 'local-delete-sync',
|
||||||
logId: this.idForLogging(),
|
logId: this.idForLogging(),
|
||||||
singleProtoJobQueue,
|
singleProtoJobQueue,
|
||||||
|
@ -5227,7 +5225,7 @@ export class ConversationModel extends window.Backbone
|
||||||
);
|
);
|
||||||
this.set({ hideStory });
|
this.set({ hideStory });
|
||||||
this.captureChange('hideStory');
|
this.captureChange('hideStory');
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
setMuteExpiration(
|
setMuteExpiration(
|
||||||
|
@ -5247,7 +5245,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
if (!viaStorageServiceSync) {
|
if (!viaStorageServiceSync) {
|
||||||
this.captureChange('mutedUntilTimestamp');
|
this.captureChange('mutedUntilTimestamp');
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5572,7 +5570,7 @@ export class ConversationModel extends window.Backbone
|
||||||
if (this.get('isArchived')) {
|
if (this.get('isArchived')) {
|
||||||
this.set({ isArchived: false });
|
this.set({ isArchived: false });
|
||||||
}
|
}
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
unpin(): void {
|
unpin(): void {
|
||||||
|
@ -5591,7 +5589,7 @@ export class ConversationModel extends window.Backbone
|
||||||
this.writePinnedConversations([...pinnedConversationIds]);
|
this.writePinnedConversations([...pinnedConversationIds]);
|
||||||
|
|
||||||
this.set('isPinned', false);
|
this.set('isPinned', false);
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
writePinnedConversations(pinnedConversationIds: Array<string>): void {
|
writePinnedConversations(pinnedConversationIds: Array<string>): void {
|
||||||
|
@ -5612,7 +5610,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set({ dontNotifyForMentionsIfMuted: newValue });
|
this.set({ dontNotifyForMentionsIfMuted: newValue });
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
this.captureChange('dontNotifyForMentionsIfMuted');
|
this.captureChange('dontNotifyForMentionsIfMuted');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5620,7 +5618,7 @@ export class ConversationModel extends window.Backbone
|
||||||
groupNameCollisions: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
groupNameCollisions: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
||||||
): void {
|
): void {
|
||||||
this.set('acknowledgedGroupNameCollisions', groupNameCollisions);
|
this.set('acknowledgedGroupNameCollisions', groupNameCollisions);
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
drop(DataWriter.updateConversation(this.attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenStart(): void {
|
onOpenStart(): void {
|
||||||
|
|
|
@ -134,7 +134,7 @@ import {
|
||||||
addToAttachmentDownloadQueue,
|
addToAttachmentDownloadQueue,
|
||||||
shouldUseAttachmentDownloadQueue,
|
shouldUseAttachmentDownloadQueue,
|
||||||
} from '../util/attachmentDownloadQueue';
|
} from '../util/attachmentDownloadQueue';
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import { shouldReplyNotifyUser } from '../util/shouldReplyNotifyUser';
|
import { shouldReplyNotifyUser } from '../util/shouldReplyNotifyUser';
|
||||||
import type { RawBodyRange } from '../types/BodyRange';
|
import type { RawBodyRange } from '../types/BodyRange';
|
||||||
import { BodyRange } from '../types/BodyRange';
|
import { BodyRange } from '../types/BodyRange';
|
||||||
|
@ -163,7 +163,7 @@ window.Whisper = window.Whisper || {};
|
||||||
|
|
||||||
const { Message: TypedMessage } = window.Signal.Types;
|
const { Message: TypedMessage } = window.Signal.Types;
|
||||||
const { upgradeMessageSchema } = window.Signal.Migrations;
|
const { upgradeMessageSchema } = window.Signal.Migrations;
|
||||||
const { getMessageBySender } = window.Signal.Data;
|
const { getMessageBySender } = DataReader;
|
||||||
|
|
||||||
export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
CURRENT_PROTOCOL_VERSION?: number;
|
CURRENT_PROTOCOL_VERSION?: number;
|
||||||
|
@ -459,9 +459,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
isQuoteAMatch(message.attributes, this.get('conversationId'), quote)
|
isQuoteAMatch(message.attributes, this.get('conversationId'), quote)
|
||||||
);
|
);
|
||||||
if (!matchingMessage) {
|
if (!matchingMessage) {
|
||||||
const messages = await window.Signal.Data.getMessagesBySentAt(
|
const messages = await DataReader.getMessagesBySentAt(Number(sentAt));
|
||||||
Number(sentAt)
|
|
||||||
);
|
|
||||||
const found = messages.find(item =>
|
const found = messages.find(item =>
|
||||||
isQuoteAMatch(item, this.get('conversationId'), quote)
|
isQuoteAMatch(item, this.get('conversationId'), quote)
|
||||||
);
|
);
|
||||||
|
@ -540,12 +538,12 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
this.getConversation()?.debouncedUpdateLastMessage();
|
this.getConversation()?.debouncedUpdateLastMessage();
|
||||||
|
|
||||||
if (shouldPersist) {
|
if (shouldPersist) {
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await window.Signal.Data.deleteSentProtoByMessageId(this.id);
|
await DataWriter.deleteSentProtoByMessageId(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
override isEmpty(): boolean {
|
override isEmpty(): boolean {
|
||||||
|
@ -675,7 +673,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
this.set({ errors });
|
this.set({ errors });
|
||||||
|
|
||||||
if (!skipSave && !this.doNotSave) {
|
if (!skipSave && !this.doNotSave) {
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -695,7 +693,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
|
|
||||||
if (storyDistributionListId) {
|
if (storyDistributionListId) {
|
||||||
const storyDistribution =
|
const storyDistribution =
|
||||||
await dataInterface.getStoryDistributionWithMembers(
|
await DataReader.getStoryDistributionWithMembers(
|
||||||
storyDistributionListId
|
storyDistributionListId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -755,7 +753,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
timestamp: this.attributes.timestamp,
|
timestamp: this.attributes.timestamp,
|
||||||
},
|
},
|
||||||
async jobToInsert => {
|
async jobToInsert => {
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
jobToInsert,
|
jobToInsert,
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
|
@ -770,7 +768,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
revision: conversation.get('revision'),
|
revision: conversation.get('revision'),
|
||||||
},
|
},
|
||||||
async jobToInsert => {
|
async jobToInsert => {
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
jobToInsert,
|
jobToInsert,
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
|
@ -918,7 +916,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.doNotSave) {
|
if (!this.doNotSave) {
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1092,7 +1090,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.doNotSave) {
|
if (!this.doNotSave) {
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1151,7 +1149,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1305,7 +1303,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
@ -1521,7 +1519,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
sendStateByConversationId,
|
sendStateByConversationId,
|
||||||
unidentifiedDeliveries: [...unidentifiedDeliveriesSet],
|
unidentifiedDeliveries: [...unidentifiedDeliveriesSet],
|
||||||
});
|
});
|
||||||
await window.Signal.Data.saveMessage(toUpdate.attributes, {
|
await DataWriter.saveMessage(toUpdate.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1780,7 +1778,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
|
|
||||||
if (storyDistributionListId) {
|
if (storyDistributionListId) {
|
||||||
const storyDistribution =
|
const storyDistribution =
|
||||||
await dataInterface.getStoryDistributionWithMembers(
|
await DataReader.getStoryDistributionWithMembers(
|
||||||
storyDistributionListId
|
storyDistributionListId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2056,7 +2054,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
conversation.setArchived(false);
|
conversation.setArchived(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
|
|
||||||
const giftBadge = message.get('giftBadge');
|
const giftBadge = message.get('giftBadge');
|
||||||
if (giftBadge) {
|
if (giftBadge) {
|
||||||
|
@ -2295,7 +2293,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
shouldSave: false,
|
shouldSave: false,
|
||||||
});
|
});
|
||||||
// Note: generatedMessage comes with an id, so we have to force this save
|
// Note: generatedMessage comes with an id, so we have to force this save
|
||||||
await window.Signal.Data.saveMessage(generatedMessage.attributes, {
|
await DataWriter.saveMessage(generatedMessage.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -2320,9 +2318,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
targetConversation.set({
|
targetConversation.set({
|
||||||
active_at: messageToAdd.get('timestamp'),
|
active_at: messageToAdd.get('timestamp'),
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(
|
await DataWriter.updateConversation(targetConversation.attributes);
|
||||||
targetConversation.attributes
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2414,14 +2410,14 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reaction.remove) {
|
if (reaction.remove) {
|
||||||
await window.Signal.Data.removeReactionFromConversation({
|
await DataWriter.removeReactionFromConversation({
|
||||||
emoji: reaction.emoji,
|
emoji: reaction.emoji,
|
||||||
fromId: reaction.fromId,
|
fromId: reaction.fromId,
|
||||||
targetAuthorServiceId: reaction.targetAuthorAci,
|
targetAuthorServiceId: reaction.targetAuthorAci,
|
||||||
targetTimestamp: reaction.targetTimestamp,
|
targetTimestamp: reaction.targetTimestamp,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await window.Signal.Data.addReaction(
|
await DataWriter.addReaction(
|
||||||
{
|
{
|
||||||
conversationId: this.get('conversationId'),
|
conversationId: this.get('conversationId'),
|
||||||
emoji: reaction.emoji,
|
emoji: reaction.emoji,
|
||||||
|
@ -2465,7 +2461,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
await generatedMessage.hydrateStoryContext(this.attributes, {
|
await generatedMessage.hydrateStoryContext(this.attributes, {
|
||||||
shouldSave: false,
|
shouldSave: false,
|
||||||
});
|
});
|
||||||
await window.Signal.Data.saveMessage(generatedMessage.attributes, {
|
await DataWriter.saveMessage(generatedMessage.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
});
|
});
|
||||||
|
@ -2499,7 +2495,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
jobToInsert.id
|
jobToInsert.id
|
||||||
}`
|
}`
|
||||||
);
|
);
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
jobToInsert,
|
jobToInsert,
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
|
@ -2508,7 +2504,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
await conversationJobQueue.add(jobData);
|
await conversationJobQueue.add(jobData);
|
||||||
}
|
}
|
||||||
} else if (shouldPersist && !isStory(this.attributes)) {
|
} else if (shouldPersist && !isStory(this.attributes)) {
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await DataWriter.saveMessage(this.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import noop from 'lodash/noop';
|
import noop from 'lodash/noop';
|
||||||
import { v4 as generateUuid } from 'uuid';
|
import { v4 as generateUuid } from 'uuid';
|
||||||
|
|
||||||
|
import { DataWriter } from '../sql/Client';
|
||||||
import type { ReactionAttributesType } from '../messageModifiers/Reactions';
|
import type { ReactionAttributesType } from '../messageModifiers/Reactions';
|
||||||
import { ReactionSource } from './ReactionSource';
|
import { ReactionSource } from './ReactionSource';
|
||||||
import { __DEPRECATED$getMessageById } from '../messages/getMessageById';
|
import { __DEPRECATED$getMessageById } from '../messages/getMessageById';
|
||||||
|
@ -63,9 +64,7 @@ export async function enqueueReactionForSend({
|
||||||
log.info('Enabling profile sharing for reaction send');
|
log.info('Enabling profile sharing for reaction send');
|
||||||
if (!messageConversation.get('profileSharing')) {
|
if (!messageConversation.get('profileSharing')) {
|
||||||
messageConversation.set('profileSharing', true);
|
messageConversation.set('profileSharing', true);
|
||||||
await window.Signal.Data.updateConversation(
|
await DataWriter.updateConversation(messageConversation.attributes);
|
||||||
messageConversation.attributes
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
await messageConversation.restoreContact();
|
await messageConversation.restoreContact();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { throttle } from 'lodash';
|
||||||
import LRU from 'lru-cache';
|
import LRU from 'lru-cache';
|
||||||
import type { MessageAttributesType } from '../model-types.d';
|
import type { MessageAttributesType } from '../model-types.d';
|
||||||
import type { MessageModel } from '../models/messages';
|
import type { MessageModel } from '../models/messages';
|
||||||
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { getEnvironment, Environment } from '../environment';
|
import { getEnvironment, Environment } from '../environment';
|
||||||
|
@ -152,7 +153,7 @@ export class MessageCache {
|
||||||
|
|
||||||
let messageAttributesFromDatabase: MessageAttributesType | undefined;
|
let messageAttributesFromDatabase: MessageAttributesType | undefined;
|
||||||
try {
|
try {
|
||||||
messageAttributesFromDatabase = await window.Signal.Data.getMessageById(
|
messageAttributesFromDatabase = await DataReader.getMessageById(
|
||||||
messageId
|
messageId
|
||||||
);
|
);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
|
@ -260,7 +261,7 @@ export class MessageCache {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return window.Signal.Data.saveMessage(nextMessageAttributes, {
|
return DataWriter.saveMessage(nextMessageAttributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,12 @@ import pTimeout from 'p-timeout';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
|
|
||||||
import { Backups, SignalService } from '../../protobuf';
|
import { Backups, SignalService } from '../../protobuf';
|
||||||
import Data from '../../sql/Client';
|
import {
|
||||||
|
DataReader,
|
||||||
|
DataWriter,
|
||||||
|
pauseWriteAccess,
|
||||||
|
resumeWriteAccess,
|
||||||
|
} from '../../sql/Client';
|
||||||
import type { PageMessagesCursorType } from '../../sql/Interface';
|
import type { PageMessagesCursorType } from '../../sql/Interface';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import { GiftBadgeStates } from '../../components/conversation/Message';
|
import { GiftBadgeStates } from '../../components/conversation/Message';
|
||||||
|
@ -183,15 +188,16 @@ export class BackupExportStream extends Readable {
|
||||||
(async () => {
|
(async () => {
|
||||||
log.info('BackupExportStream: starting...');
|
log.info('BackupExportStream: starting...');
|
||||||
drop(AttachmentBackupManager.stop());
|
drop(AttachmentBackupManager.stop());
|
||||||
await Data.pauseWriteAccess();
|
await pauseWriteAccess();
|
||||||
try {
|
try {
|
||||||
await this.unsafeRun(backupLevel);
|
await this.unsafeRun(backupLevel);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.emit('error', error);
|
this.emit('error', error);
|
||||||
} finally {
|
} finally {
|
||||||
await Data.resumeWriteAccess();
|
await resumeWriteAccess();
|
||||||
|
|
||||||
// TODO (DESKTOP-7344): Clear & add backup jobs in a single transaction
|
// TODO (DESKTOP-7344): Clear & add backup jobs in a single transaction
|
||||||
await Data.clearAllAttachmentBackupJobs();
|
await DataWriter.clearAllAttachmentBackupJobs();
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
this.attachmentBackupJobs.map(job =>
|
this.attachmentBackupJobs.map(job =>
|
||||||
AttachmentBackupManager.addJobAndMaybeThumbnailJob(job)
|
AttachmentBackupManager.addJobAndMaybeThumbnailJob(job)
|
||||||
|
@ -248,7 +254,8 @@ export class BackupExportStream extends Readable {
|
||||||
stats.conversations += 1;
|
stats.conversations += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const distributionLists = await Data.getAllStoryDistributionsWithMembers();
|
const distributionLists =
|
||||||
|
await DataReader.getAllStoryDistributionsWithMembers();
|
||||||
|
|
||||||
for (const list of distributionLists) {
|
for (const list of distributionLists) {
|
||||||
const { PrivacyMode } = Backups.DistributionList;
|
const { PrivacyMode } = Backups.DistributionList;
|
||||||
|
@ -296,7 +303,7 @@ export class BackupExportStream extends Readable {
|
||||||
stats.distributionLists += 1;
|
stats.distributionLists += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const stickerPacks = await Data.getInstalledStickerPacks();
|
const stickerPacks = await DataReader.getInstalledStickerPacks();
|
||||||
|
|
||||||
for (const { id, key } of stickerPacks) {
|
for (const { id, key } of stickerPacks) {
|
||||||
this.pushFrame({
|
this.pushFrame({
|
||||||
|
@ -379,7 +386,9 @@ export class BackupExportStream extends Readable {
|
||||||
try {
|
try {
|
||||||
while (!cursor?.done) {
|
while (!cursor?.done) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
const { messages, cursor: newCursor } = await Data.pageMessages(cursor);
|
const { messages, cursor: newCursor } = await DataReader.pageMessages(
|
||||||
|
cursor
|
||||||
|
);
|
||||||
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
const items = await pMap(
|
const items = await pMap(
|
||||||
|
@ -413,7 +422,7 @@ export class BackupExportStream extends Readable {
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (cursor !== undefined) {
|
if (cursor !== undefined) {
|
||||||
await Data.finishPageMessages(cursor);
|
await DataReader.finishPageMessages(cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { Writable } from 'stream';
|
||||||
import { isNumber } from 'lodash';
|
import { isNumber } from 'lodash';
|
||||||
|
|
||||||
import { Backups, SignalService } from '../../protobuf';
|
import { Backups, SignalService } from '../../protobuf';
|
||||||
import Data from '../../sql/Client';
|
import { DataWriter } from '../../sql/Client';
|
||||||
import type { StoryDistributionWithMembersType } from '../../sql/Interface';
|
import type { StoryDistributionWithMembersType } from '../../sql/Interface';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import { GiftBadgeStates } from '../../components/conversation/Message';
|
import { GiftBadgeStates } from '../../components/conversation/Message';
|
||||||
|
@ -112,14 +112,14 @@ async function processConversationOpBatch(
|
||||||
`updates=${updates.length}`
|
`updates=${updates.length}`
|
||||||
);
|
);
|
||||||
|
|
||||||
await Data.saveConversations(saves);
|
await DataWriter.saveConversations(saves);
|
||||||
await Data.updateConversations(updates);
|
await DataWriter.updateConversations(updates);
|
||||||
}
|
}
|
||||||
async function processMessagesBatch(
|
async function processMessagesBatch(
|
||||||
ourAci: AciString,
|
ourAci: AciString,
|
||||||
batch: ReadonlyArray<MessageAttributesType>
|
batch: ReadonlyArray<MessageAttributesType>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const ids = await Data.saveMessages(batch, {
|
const ids = await DataWriter.saveMessages(batch, {
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
ourAci,
|
ourAci,
|
||||||
});
|
});
|
||||||
|
@ -138,7 +138,7 @@ async function processMessagesBatch(
|
||||||
|
|
||||||
if (editHistory?.length) {
|
if (editHistory?.length) {
|
||||||
drop(
|
drop(
|
||||||
Data.saveEditedMessages(
|
DataWriter.saveEditedMessages(
|
||||||
attributes,
|
attributes,
|
||||||
ourAci,
|
ourAci,
|
||||||
editHistory.slice(0, -1).map(({ timestamp }) => ({
|
editHistory.slice(0, -1).map(({ timestamp }) => ({
|
||||||
|
@ -966,7 +966,7 @@ export class BackupImportStream extends Writable {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
await Data.createNewStoryDistribution(result);
|
await DataWriter.createNewStoryDistribution(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async fromChat(chat: Backups.IChat): Promise<void> {
|
private async fromChat(chat: Backups.IChat): Promise<void> {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { createCipheriv, createHmac, randomBytes } from 'crypto';
|
||||||
import { noop } from 'lodash';
|
import { noop } from 'lodash';
|
||||||
import { BackupLevel } from '@signalapp/libsignal-client/zkgroup';
|
import { BackupLevel } from '@signalapp/libsignal-client/zkgroup';
|
||||||
|
|
||||||
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import * as Bytes from '../../Bytes';
|
import * as Bytes from '../../Bytes';
|
||||||
import { strictAssert } from '../../util/assert';
|
import { strictAssert } from '../../util/assert';
|
||||||
|
@ -187,7 +188,7 @@ export class BackupsService {
|
||||||
|
|
||||||
public async fetchAndSaveBackupCdnObjectMetadata(): Promise<void> {
|
public async fetchAndSaveBackupCdnObjectMetadata(): Promise<void> {
|
||||||
log.info('fetchAndSaveBackupCdnObjectMetadata: clearing existing metadata');
|
log.info('fetchAndSaveBackupCdnObjectMetadata: clearing existing metadata');
|
||||||
await window.Signal.Data.clearAllBackupCdnObjectMetadata();
|
await DataWriter.clearAllBackupCdnObjectMetadata();
|
||||||
|
|
||||||
let cursor: string | undefined;
|
let cursor: string | undefined;
|
||||||
const PAGE_SIZE = 1000;
|
const PAGE_SIZE = 1000;
|
||||||
|
@ -198,7 +199,7 @@ export class BackupsService {
|
||||||
const listResult = await this.api.listMedia({ cursor, limit: PAGE_SIZE });
|
const listResult = await this.api.listMedia({ cursor, limit: PAGE_SIZE });
|
||||||
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await window.Signal.Data.saveBackupCdnObjectMetadata(
|
await DataWriter.saveBackupCdnObjectMetadata(
|
||||||
listResult.storedMediaObjects.map(object => ({
|
listResult.storedMediaObjects.map(object => ({
|
||||||
mediaId: object.mediaId,
|
mediaId: object.mediaId,
|
||||||
cdnNumber: object.cdn,
|
cdnNumber: object.cdn,
|
||||||
|
@ -220,9 +221,7 @@ export class BackupsService {
|
||||||
): Promise<
|
): Promise<
|
||||||
{ isInBackupTier: true; cdnNumber: number } | { isInBackupTier: false }
|
{ isInBackupTier: true; cdnNumber: number } | { isInBackupTier: false }
|
||||||
> {
|
> {
|
||||||
const storedInfo = await window.Signal.Data.getBackupCdnObjectMetadata(
|
const storedInfo = await DataReader.getBackupCdnObjectMetadata(mediaId);
|
||||||
mediaId
|
|
||||||
);
|
|
||||||
if (!storedInfo) {
|
if (!storedInfo) {
|
||||||
return { isInBackupTier: false };
|
return { isInBackupTier: false };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2024 Signal Messenger, LLC
|
// Copyright 2024 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import { DataReader } from '../../../sql/Client';
|
||||||
import * as Bytes from '../../../Bytes';
|
import * as Bytes from '../../../Bytes';
|
||||||
import { getBackupKey } from '../crypto';
|
import { getBackupKey } from '../crypto';
|
||||||
import type { AttachmentType } from '../../../types/Attachment';
|
import type { AttachmentType } from '../../../types/Attachment';
|
||||||
|
@ -63,9 +64,7 @@ export type GetBackupCdnInfoType = (
|
||||||
export const getBackupCdnInfo: GetBackupCdnInfoType = async (
|
export const getBackupCdnInfo: GetBackupCdnInfoType = async (
|
||||||
mediaId: string
|
mediaId: string
|
||||||
) => {
|
) => {
|
||||||
const savedInfo = await window.Signal.Data.getBackupCdnObjectMetadata(
|
const savedInfo = await DataReader.getBackupCdnObjectMetadata(mediaId);
|
||||||
mediaId
|
|
||||||
);
|
|
||||||
if (!savedInfo) {
|
if (!savedInfo) {
|
||||||
return { isInBackupTier: false };
|
return { isInBackupTier: false };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2023 Signal Messenger, LLC
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import type { CallHistoryDetails } from '../types/CallDisposition';
|
import type { CallHistoryDetails } from '../types/CallDisposition';
|
||||||
import { strictAssert } from '../util/assert';
|
import { strictAssert } from '../util/assert';
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ let callsHistoryData: ReadonlyArray<CallHistoryDetails>;
|
||||||
let callsHistoryUnreadCount: number;
|
let callsHistoryUnreadCount: number;
|
||||||
|
|
||||||
export async function loadCallsHistory(): Promise<void> {
|
export async function loadCallsHistory(): Promise<void> {
|
||||||
await dataInterface.cleanupCallHistoryMessages();
|
await DataWriter.cleanupCallHistoryMessages();
|
||||||
callsHistoryData = await dataInterface.getAllCallHistory();
|
callsHistoryData = await DataReader.getAllCallHistory();
|
||||||
callsHistoryUnreadCount = await dataInterface.getCallHistoryUnreadCount();
|
callsHistoryUnreadCount = await DataReader.getCallHistoryUnreadCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCallsHistoryForRedux(): ReadonlyArray<CallHistoryDetails> {
|
export function getCallsHistoryForRedux(): ReadonlyArray<CallHistoryDetails> {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
// Copyright 2023 Signal Messenger, LLC
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader } from '../sql/Client';
|
||||||
import type { CallLinkType } from '../types/CallLink';
|
import type { CallLinkType } from '../types/CallLink';
|
||||||
import { strictAssert } from '../util/assert';
|
import { strictAssert } from '../util/assert';
|
||||||
|
|
||||||
let callLinksData: ReadonlyArray<CallLinkType>;
|
let callLinksData: ReadonlyArray<CallLinkType>;
|
||||||
|
|
||||||
export async function loadCallLinks(): Promise<void> {
|
export async function loadCallLinks(): Promise<void> {
|
||||||
callLinksData = await dataInterface.getAllCallLinks();
|
callLinksData = await DataReader.getAllCallLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCallLinksForRedux(): ReadonlyArray<CallLinkType> {
|
export function getCallLinksForRedux(): ReadonlyArray<CallLinkType> {
|
||||||
|
|
|
@ -105,7 +105,7 @@ import { callingMessageToProto } from '../util/callingMessageToProto';
|
||||||
import { requestMicrophonePermissions } from '../util/requestMicrophonePermissions';
|
import { requestMicrophonePermissions } from '../util/requestMicrophonePermissions';
|
||||||
import OS from '../util/os/osMain';
|
import OS from '../util/os/osMain';
|
||||||
import { SignalService as Proto } from '../protobuf';
|
import { SignalService as Proto } from '../protobuf';
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import {
|
import {
|
||||||
notificationService,
|
notificationService,
|
||||||
NotificationSetting,
|
NotificationSetting,
|
||||||
|
@ -159,11 +159,11 @@ import type {
|
||||||
import { CallLinkRestrictions } from '../types/CallLink';
|
import { CallLinkRestrictions } from '../types/CallLink';
|
||||||
import { getConversationIdForLogging } from '../util/idForLogging';
|
import { getConversationIdForLogging } from '../util/idForLogging';
|
||||||
|
|
||||||
|
const { wasGroupCallRingPreviouslyCanceled } = DataReader;
|
||||||
const {
|
const {
|
||||||
processGroupCallRingCancellation,
|
processGroupCallRingCancellation,
|
||||||
cleanExpiredGroupCallRingCancellations,
|
cleanExpiredGroupCallRingCancellations,
|
||||||
wasGroupCallRingPreviouslyCanceled,
|
} = DataWriter;
|
||||||
} = dataInterface;
|
|
||||||
|
|
||||||
const RINGRTC_HTTP_METHOD_TO_OUR_HTTP_METHOD: Map<
|
const RINGRTC_HTTP_METHOD_TO_OUR_HTTP_METHOD: Map<
|
||||||
HttpMethod,
|
HttpMethod,
|
||||||
|
@ -933,7 +933,7 @@ export class CallingClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async cleanupStaleRingingCalls(): Promise<void> {
|
public async cleanupStaleRingingCalls(): Promise<void> {
|
||||||
const calls = await dataInterface.getRecentStaleRingsAndMarkOlderMissed();
|
const calls = await DataWriter.getRecentStaleRingsAndMarkOlderMissed();
|
||||||
|
|
||||||
const results = await Promise.all(
|
const results = await Promise.all(
|
||||||
calls.map(async call => {
|
calls.map(async call => {
|
||||||
|
@ -950,7 +950,7 @@ export class CallingClass {
|
||||||
return result.callId;
|
return result.callId;
|
||||||
});
|
});
|
||||||
|
|
||||||
await dataInterface.markCallHistoryMissed(staleCallIds);
|
await DataWriter.markCallHistoryMissed(staleCallIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async peekGroupCall(conversationId: string): Promise<PeekInfo> {
|
public async peekGroupCall(conversationId: string): Promise<PeekInfo> {
|
||||||
|
@ -3281,8 +3281,7 @@ export class CallingClass {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prevMessageId =
|
const prevMessageId = await DataReader.getCallHistoryMessageByCallId({
|
||||||
await window.Signal.Data.getCallHistoryMessageByCallId({
|
|
||||||
conversationId: conversation.id,
|
conversationId: conversation.id,
|
||||||
callId: groupCallMeta.callId,
|
callId: groupCallMeta.callId,
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
|
|
||||||
|
import { DataWriter } from '../sql/Client';
|
||||||
import type { ContactSyncEvent } from '../textsecure/messageReceiverEvents';
|
import type { ContactSyncEvent } from '../textsecure/messageReceiverEvents';
|
||||||
import type { ContactDetailsWithAvatar } from '../textsecure/ContactsParser';
|
import type { ContactDetailsWithAvatar } from '../textsecure/ContactsParser';
|
||||||
import { normalizeAci } from '../util/normalizeAci';
|
import { normalizeAci } from '../util/normalizeAci';
|
||||||
|
@ -167,7 +168,7 @@ async function doContactSync({
|
||||||
|
|
||||||
// Save new conversation attributes
|
// Save new conversation attributes
|
||||||
promises.push(
|
promises.push(
|
||||||
window.Signal.Data.updateConversations(
|
DataWriter.updateConversations(
|
||||||
[...updatedConversations, ...notUpdated].map(convo => convo.attributes)
|
[...updatedConversations, ...notUpdated].map(convo => convo.attributes)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2022 Signal Messenger, LLC
|
// Copyright 2022 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader } from '../sql/Client';
|
||||||
import type { StoryDistributionWithMembersType } from '../sql/Interface';
|
import type { StoryDistributionWithMembersType } from '../sql/Interface';
|
||||||
import type { StoryDistributionListDataType } from '../state/ducks/storyDistributionLists';
|
import type { StoryDistributionListDataType } from '../state/ducks/storyDistributionLists';
|
||||||
import { strictAssert } from '../util/assert';
|
import { strictAssert } from '../util/assert';
|
||||||
|
@ -9,7 +9,7 @@ import { strictAssert } from '../util/assert';
|
||||||
let distributionLists: Array<StoryDistributionWithMembersType> | undefined;
|
let distributionLists: Array<StoryDistributionWithMembersType> | undefined;
|
||||||
|
|
||||||
export async function loadDistributionLists(): Promise<void> {
|
export async function loadDistributionLists(): Promise<void> {
|
||||||
distributionLists = await dataInterface.getAllStoryDistributionsWithMembers();
|
distributionLists = await DataReader.getAllStoryDistributionsWithMembers();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDistributionListsForRedux(): Array<StoryDistributionListDataType> {
|
export function getDistributionListsForRedux(): Array<StoryDistributionListDataType> {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import { batch } from 'react-redux';
|
import { batch } from 'react-redux';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary';
|
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary';
|
||||||
import { sleep } from '../util/sleep';
|
import { sleep } from '../util/sleep';
|
||||||
import { SECOND } from '../util/durations';
|
import { SECOND } from '../util/durations';
|
||||||
|
@ -27,7 +28,7 @@ class ExpiringMessagesDeletionService {
|
||||||
window.SignalContext.log.info(
|
window.SignalContext.log.info(
|
||||||
'destroyExpiredMessages: Loading messages...'
|
'destroyExpiredMessages: Loading messages...'
|
||||||
);
|
);
|
||||||
const messages = await window.Signal.Data.getExpiredMessages();
|
const messages = await DataReader.getExpiredMessages();
|
||||||
window.SignalContext.log.info(
|
window.SignalContext.log.info(
|
||||||
`destroyExpiredMessages: found ${messages.length} messages to expire`
|
`destroyExpiredMessages: found ${messages.length} messages to expire`
|
||||||
);
|
);
|
||||||
|
@ -45,7 +46,7 @@ class ExpiringMessagesDeletionService {
|
||||||
inMemoryMessages.push(message);
|
inMemoryMessages.push(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
await window.Signal.Data.removeMessages(messageIds, {
|
await DataWriter.removeMessages(messageIds, {
|
||||||
singleProtoJobQueue: this.singleProtoJobQueue,
|
singleProtoJobQueue: this.singleProtoJobQueue,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ class ExpiringMessagesDeletionService {
|
||||||
'checkExpiringMessages: checking for expiring messages'
|
'checkExpiringMessages: checking for expiring messages'
|
||||||
);
|
);
|
||||||
|
|
||||||
const soonestExpiry = await window.Signal.Data.getSoonestMessageExpiry();
|
const soonestExpiry = await DataReader.getSoonestMessageExpiry();
|
||||||
if (!soonestExpiry) {
|
if (!soonestExpiry) {
|
||||||
window.SignalContext.log.info(
|
window.SignalContext.log.info(
|
||||||
'checkExpiringMessages: found no messages to expire'
|
'checkExpiringMessages: found no messages to expire'
|
||||||
|
|
|
@ -11,6 +11,7 @@ import type {
|
||||||
GetProfileUnauthOptionsType,
|
GetProfileUnauthOptionsType,
|
||||||
} from '../textsecure/WebAPI';
|
} from '../textsecure/WebAPI';
|
||||||
import type { ServiceIdString } from '../types/ServiceId';
|
import type { ServiceIdString } from '../types/ServiceId';
|
||||||
|
import { DataWriter } from '../sql/Client';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import * as Bytes from '../Bytes';
|
import * as Bytes from '../Bytes';
|
||||||
|
@ -594,7 +595,7 @@ async function doGetProfile(c: ConversationModel): Promise<void> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(c.attributes);
|
await DataWriter.updateConversation(c.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UpdateIdentityKeyOptionsType = Readonly<{
|
export type UpdateIdentityKeyOptionsType = Readonly<{
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { debounce, isNumber, chunk } from 'lodash';
|
||||||
import pMap from 'p-map';
|
import pMap from 'p-map';
|
||||||
import Long from 'long';
|
import Long from 'long';
|
||||||
|
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import * as Bytes from '../Bytes';
|
import * as Bytes from '../Bytes';
|
||||||
import {
|
import {
|
||||||
getRandomBytes,
|
getRandomBytes,
|
||||||
|
@ -71,13 +71,14 @@ import { redactExtendedStorageID, redactStorageID } from '../util/privacy';
|
||||||
|
|
||||||
type IManifestRecordIdentifier = Proto.ManifestRecord.IIdentifier;
|
type IManifestRecordIdentifier = Proto.ManifestRecord.IIdentifier;
|
||||||
|
|
||||||
|
const { getItemById } = DataReader;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
eraseStorageServiceState,
|
eraseStorageServiceState,
|
||||||
flushUpdateConversationBatcher,
|
flushUpdateConversationBatcher,
|
||||||
getItemById,
|
|
||||||
updateConversation,
|
updateConversation,
|
||||||
updateConversations,
|
updateConversations,
|
||||||
} = dataInterface;
|
} = DataWriter;
|
||||||
|
|
||||||
const uploadBucket: Array<number> = [];
|
const uploadBucket: Array<number> = [];
|
||||||
|
|
||||||
|
@ -319,7 +320,7 @@ async function generateManifest(
|
||||||
storageVersion: version,
|
storageVersion: version,
|
||||||
storageID,
|
storageID,
|
||||||
});
|
});
|
||||||
updateConversation(conversation.attributes);
|
drop(updateConversation(conversation.attributes));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,7 +361,7 @@ async function generateManifest(
|
||||||
);
|
);
|
||||||
deleteKeys.add(droppedID);
|
deleteKeys.add(droppedID);
|
||||||
|
|
||||||
drop(dataInterface.deleteStoryDistribution(storyDistributionList.id));
|
drop(DataWriter.deleteStoryDistribution(storyDistributionList.id));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,7 +375,7 @@ async function generateManifest(
|
||||||
|
|
||||||
if (isNewItem) {
|
if (isNewItem) {
|
||||||
postUploadUpdateFunctions.push(() => {
|
postUploadUpdateFunctions.push(() => {
|
||||||
void dataInterface.modifyStoryDistribution({
|
void DataWriter.modifyStoryDistribution({
|
||||||
...storyDistributionList,
|
...storyDistributionList,
|
||||||
storageID,
|
storageID,
|
||||||
storageVersion: version,
|
storageVersion: version,
|
||||||
|
@ -407,7 +408,7 @@ async function generateManifest(
|
||||||
|
|
||||||
if (isNewItem) {
|
if (isNewItem) {
|
||||||
postUploadUpdateFunctions.push(() => {
|
postUploadUpdateFunctions.push(() => {
|
||||||
void dataInterface.addUninstalledStickerPack({
|
void DataWriter.addUninstalledStickerPack({
|
||||||
...stickerPack,
|
...stickerPack,
|
||||||
storageID,
|
storageID,
|
||||||
storageVersion: version,
|
storageVersion: version,
|
||||||
|
@ -449,7 +450,7 @@ async function generateManifest(
|
||||||
|
|
||||||
if (isNewItem) {
|
if (isNewItem) {
|
||||||
postUploadUpdateFunctions.push(() => {
|
postUploadUpdateFunctions.push(() => {
|
||||||
void dataInterface.createOrUpdateStickerPack({
|
void DataWriter.createOrUpdateStickerPack({
|
||||||
...stickerPack,
|
...stickerPack,
|
||||||
storageID,
|
storageID,
|
||||||
storageVersion: version,
|
storageVersion: version,
|
||||||
|
@ -1088,9 +1089,9 @@ async function getNonConversationRecords(): Promise<NonConversationRecordsResult
|
||||||
uninstalledStickerPacks,
|
uninstalledStickerPacks,
|
||||||
installedStickerPacks,
|
installedStickerPacks,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
dataInterface.getAllStoryDistributionsWithMembers(),
|
DataReader.getAllStoryDistributionsWithMembers(),
|
||||||
dataInterface.getUninstalledStickerPacks(),
|
DataReader.getUninstalledStickerPacks(),
|
||||||
dataInterface.getInstalledStickerPacks(),
|
DataReader.getInstalledStickerPacks(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1256,7 +1257,7 @@ async function processManifest(
|
||||||
}
|
}
|
||||||
conversation.unset('storageID');
|
conversation.unset('storageID');
|
||||||
conversation.unset('storageVersion');
|
conversation.unset('storageVersion');
|
||||||
updateConversation(conversation.attributes);
|
drop(updateConversation(conversation.attributes));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1279,7 +1280,7 @@ async function processManifest(
|
||||||
`storageService.process(${version}): localKey=${missingKey} was not ` +
|
`storageService.process(${version}): localKey=${missingKey} was not ` +
|
||||||
'in remote manifest'
|
'in remote manifest'
|
||||||
);
|
);
|
||||||
void dataInterface.addUninstalledStickerPack({
|
void DataWriter.addUninstalledStickerPack({
|
||||||
...stickerPack,
|
...stickerPack,
|
||||||
storageID: undefined,
|
storageID: undefined,
|
||||||
storageVersion: undefined,
|
storageVersion: undefined,
|
||||||
|
@ -1297,7 +1298,7 @@ async function processManifest(
|
||||||
`storageService.process(${version}): localKey=${missingKey} was not ` +
|
`storageService.process(${version}): localKey=${missingKey} was not ` +
|
||||||
'in remote manifest'
|
'in remote manifest'
|
||||||
);
|
);
|
||||||
void dataInterface.createOrUpdateStickerPack({
|
void DataWriter.createOrUpdateStickerPack({
|
||||||
...stickerPack,
|
...stickerPack,
|
||||||
storageID: undefined,
|
storageID: undefined,
|
||||||
storageVersion: undefined,
|
storageVersion: undefined,
|
||||||
|
@ -1315,7 +1316,7 @@ async function processManifest(
|
||||||
`storageService.process(${version}): localKey=${missingKey} was not ` +
|
`storageService.process(${version}): localKey=${missingKey} was not ` +
|
||||||
'in remote manifest'
|
'in remote manifest'
|
||||||
);
|
);
|
||||||
void dataInterface.modifyStoryDistribution({
|
void DataWriter.modifyStoryDistribution({
|
||||||
...storyDistributionList,
|
...storyDistributionList,
|
||||||
storageID: undefined,
|
storageID: undefined,
|
||||||
storageVersion: undefined,
|
storageVersion: undefined,
|
||||||
|
@ -1339,7 +1340,7 @@ async function processManifest(
|
||||||
storageNeedsSync: true,
|
storageNeedsSync: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
await dataInterface.createNewStoryDistribution(storyDistribution);
|
await DataWriter.createNewStoryDistribution(storyDistribution);
|
||||||
|
|
||||||
const shouldSave = false;
|
const shouldSave = false;
|
||||||
window.reduxActions.storyDistributionLists.createDistributionList(
|
window.reduxActions.storyDistributionLists.createDistributionList(
|
||||||
|
|
|
@ -59,7 +59,7 @@ import type {
|
||||||
StoryDistributionWithMembersType,
|
StoryDistributionWithMembersType,
|
||||||
StickerPackInfoType,
|
StickerPackInfoType,
|
||||||
} from '../sql/Interface';
|
} from '../sql/Interface';
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import { MY_STORY_ID, StorySendMode } from '../types/Stories';
|
import { MY_STORY_ID, StorySendMode } from '../types/Stories';
|
||||||
import { findAndDeleteOnboardingStoryIfExists } from '../util/findAndDeleteOnboardingStoryIfExists';
|
import { findAndDeleteOnboardingStoryIfExists } from '../util/findAndDeleteOnboardingStoryIfExists';
|
||||||
import { downloadOnboardingStory } from '../util/downloadOnboardingStory';
|
import { downloadOnboardingStory } from '../util/downloadOnboardingStory';
|
||||||
|
@ -1682,7 +1682,7 @@ export async function mergeStoryDistributionListRecord(
|
||||||
}
|
}
|
||||||
|
|
||||||
const localStoryDistributionList =
|
const localStoryDistributionList =
|
||||||
await dataInterface.getStoryDistributionWithMembers(listId);
|
await DataReader.getStoryDistributionWithMembers(listId);
|
||||||
|
|
||||||
const remoteListMembers: Array<ServiceIdString> = (
|
const remoteListMembers: Array<ServiceIdString> = (
|
||||||
storyDistributionListRecord.recipientServiceIds || []
|
storyDistributionListRecord.recipientServiceIds || []
|
||||||
|
@ -1714,7 +1714,7 @@ export async function mergeStoryDistributionListRecord(
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!localStoryDistributionList) {
|
if (!localStoryDistributionList) {
|
||||||
await dataInterface.createNewStoryDistribution(storyDistribution);
|
await DataWriter.createNewStoryDistribution(storyDistribution);
|
||||||
|
|
||||||
const shouldSave = false;
|
const shouldSave = false;
|
||||||
window.reduxActions.storyDistributionLists.createDistributionList(
|
window.reduxActions.storyDistributionLists.createDistributionList(
|
||||||
|
@ -1766,7 +1766,7 @@ export async function mergeStoryDistributionListRecord(
|
||||||
);
|
);
|
||||||
|
|
||||||
details.push('updated');
|
details.push('updated');
|
||||||
await dataInterface.modifyStoryDistributionWithMembers(storyDistribution, {
|
await DataWriter.modifyStoryDistributionWithMembers(storyDistribution, {
|
||||||
toAdd,
|
toAdd,
|
||||||
toRemove,
|
toRemove,
|
||||||
});
|
});
|
||||||
|
@ -1804,7 +1804,7 @@ export async function mergeStickerPackRecord(
|
||||||
const details: Array<string> = [];
|
const details: Array<string> = [];
|
||||||
const id = Bytes.toHex(stickerPackRecord.packId);
|
const id = Bytes.toHex(stickerPackRecord.packId);
|
||||||
|
|
||||||
const localStickerPack = await dataInterface.getStickerPackInfo(id);
|
const localStickerPack = await DataReader.getStickerPackInfo(id);
|
||||||
|
|
||||||
if (stickerPackRecord.$unknownFields) {
|
if (stickerPackRecord.$unknownFields) {
|
||||||
details.push('adding unknown fields');
|
details.push('adding unknown fields');
|
||||||
|
@ -1897,7 +1897,7 @@ export async function mergeStickerPackRecord(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await dataInterface.updateStickerPackInfo(stickerPack);
|
await DataWriter.updateStickerPackInfo(stickerPack);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
details: [...details, ...conflictDetails],
|
details: [...details, ...conflictDetails],
|
||||||
|
|
|
@ -6,7 +6,7 @@ import type { MessageAttributesType } from '../model-types.d';
|
||||||
import type { StoryDataType } from '../state/ducks/stories';
|
import type { StoryDataType } from '../state/ducks/stories';
|
||||||
import * as durations from '../util/durations';
|
import * as durations from '../util/durations';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import dataInterface from '../sql/Client';
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import type { GetAllStoriesResultType } from '../sql/Interface';
|
import type { GetAllStoriesResultType } from '../sql/Interface';
|
||||||
import {
|
import {
|
||||||
getAttachmentsForMessage,
|
getAttachmentsForMessage,
|
||||||
|
@ -22,7 +22,7 @@ import { SIGNAL_ACI } from '../types/SignalConversation';
|
||||||
let storyData: GetAllStoriesResultType | undefined;
|
let storyData: GetAllStoriesResultType | undefined;
|
||||||
|
|
||||||
export async function loadStories(): Promise<void> {
|
export async function loadStories(): Promise<void> {
|
||||||
storyData = await dataInterface.getAllStories({});
|
storyData = await DataReader.getAllStories({});
|
||||||
|
|
||||||
await repairUnexpiredStories();
|
await repairUnexpiredStories();
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ async function repairUnexpiredStories(): Promise<void> {
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
storiesWithExpiry.map(messageAttributes => {
|
storiesWithExpiry.map(messageAttributes => {
|
||||||
return window.Signal.Data.saveMessage(messageAttributes, {
|
return DataWriter.saveMessage(messageAttributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { DataReader } from '../sql/Client';
|
||||||
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary';
|
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary';
|
||||||
import { DAY } from '../util/durations';
|
import { DAY } from '../util/durations';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
|
@ -11,8 +12,7 @@ async function eraseTapToViewMessages() {
|
||||||
window.SignalContext.log.info(
|
window.SignalContext.log.info(
|
||||||
'eraseTapToViewMessages: Loading messages...'
|
'eraseTapToViewMessages: Loading messages...'
|
||||||
);
|
);
|
||||||
const messages =
|
const messages = await DataReader.getTapToViewMessagesNeedingErase();
|
||||||
await window.Signal.Data.getTapToViewMessagesNeedingErase();
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
messages.map(async fromDB => {
|
messages.map(async fromDB => {
|
||||||
const message = window.MessageCache.__DEPRECATED$register(
|
const message = window.MessageCache.__DEPRECATED$register(
|
||||||
|
@ -54,7 +54,7 @@ class TapToViewMessagesDeletionService {
|
||||||
|
|
||||||
private async checkTapToViewMessages() {
|
private async checkTapToViewMessages() {
|
||||||
const receivedAt =
|
const receivedAt =
|
||||||
await window.Signal.Data.getNextTapToViewMessageTimestampToAgeOut();
|
await DataReader.getNextTapToViewMessageTimestampToAgeOut();
|
||||||
if (!receivedAt) {
|
if (!receivedAt) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import dataInterface from '../sql/Client';
|
import { DataWriter } from '../sql/Client';
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
@ -134,7 +134,7 @@ export async function writeProfile(
|
||||||
...maybeProfileAvatarUpdate,
|
...maybeProfileAvatarUpdate,
|
||||||
});
|
});
|
||||||
|
|
||||||
dataInterface.updateConversation(model.attributes);
|
await DataWriter.updateConversation(model.attributes);
|
||||||
model.captureChange('writeProfile');
|
model.captureChange('writeProfile');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
import { DataWriter } from '../sql/Client';
|
||||||
import { deleteAllLogs } from '../util/deleteAllLogs';
|
import { deleteAllLogs } from '../util/deleteAllLogs';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
|
|
||||||
|
@ -11,19 +12,19 @@ export async function deleteAllData(): Promise<void> {
|
||||||
|
|
||||||
log.info('deleteAllData: deleted all logs');
|
log.info('deleteAllData: deleted all logs');
|
||||||
|
|
||||||
await window.Signal.Data.removeAll();
|
await DataWriter.removeAll();
|
||||||
|
|
||||||
log.info('deleteAllData: emptied database');
|
log.info('deleteAllData: emptied database');
|
||||||
|
|
||||||
await window.Signal.Data.close();
|
await DataWriter.close();
|
||||||
|
|
||||||
log.info('deleteAllData: closed database');
|
log.info('deleteAllData: closed database');
|
||||||
|
|
||||||
await window.Signal.Data.removeDB();
|
await DataWriter.removeDB();
|
||||||
|
|
||||||
log.info('deleteAllData: removed database');
|
log.info('deleteAllData: removed database');
|
||||||
|
|
||||||
await window.Signal.Data.removeOtherData();
|
await DataWriter.removeOtherData();
|
||||||
|
|
||||||
log.info('deleteAllData: removed all other data');
|
log.info('deleteAllData: removed all other data');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
import * as Crypto from './Crypto';
|
import * as Crypto from './Crypto';
|
||||||
import * as Curve from './Curve';
|
import * as Curve from './Curve';
|
||||||
import { start as conversationControllerStart } from './ConversationController';
|
import { start as conversationControllerStart } from './ConversationController';
|
||||||
import Data from './sql/Client';
|
|
||||||
import * as Groups from './groups';
|
import * as Groups from './groups';
|
||||||
import OS from './util/os/osMain';
|
import OS from './util/os/osMain';
|
||||||
import * as RemoteConfig from './RemoteConfig';
|
import * as RemoteConfig from './RemoteConfig';
|
||||||
|
@ -455,7 +454,6 @@ export const setup = (options: {
|
||||||
Curve,
|
Curve,
|
||||||
// Note: used in test/index.html, and not type-checked!
|
// Note: used in test/index.html, and not type-checked!
|
||||||
conversationControllerStart,
|
conversationControllerStart,
|
||||||
Data,
|
|
||||||
Groups,
|
Groups,
|
||||||
Migrations,
|
Migrations,
|
||||||
OS,
|
OS,
|
||||||
|
|
224
ts/sql/Client.ts
224
ts/sql/Client.ts
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import { ipcRenderer as ipc } from 'electron';
|
import { ipcRenderer as ipc } from 'electron';
|
||||||
|
|
||||||
import { has, get, groupBy, isTypedArray, last, map, omit } from 'lodash';
|
import { groupBy, isTypedArray, last, map, omit } from 'lodash';
|
||||||
|
|
||||||
import { deleteExternalFiles } from '../types/Conversation';
|
import { deleteExternalFiles } from '../types/Conversation';
|
||||||
import { update as updateExpiringMessagesService } from '../services/expiringMessagesDeletion';
|
import { update as updateExpiringMessagesService } from '../services/expiringMessagesDeletion';
|
||||||
|
@ -23,13 +23,16 @@ import * as Errors from '../types/errors';
|
||||||
import type { StoredJob } from '../jobs/types';
|
import type { StoredJob } from '../jobs/types';
|
||||||
import { formatJobForInsert } from '../jobs/formatJobForInsert';
|
import { formatJobForInsert } from '../jobs/formatJobForInsert';
|
||||||
import { cleanupMessages } from '../util/cleanup';
|
import { cleanupMessages } from '../util/cleanup';
|
||||||
import { ipcInvoke, doShutdown } from './channels';
|
import { AccessType, ipcInvoke, doShutdown } from './channels';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
ClientInterfaceWrap,
|
||||||
AdjacentMessagesByConversationOptionsType,
|
AdjacentMessagesByConversationOptionsType,
|
||||||
AllItemsType,
|
AllItemsType,
|
||||||
ClientInterface,
|
ServerReadableDirectInterface,
|
||||||
ClientExclusiveInterface,
|
ServerWritableDirectInterface,
|
||||||
|
ClientReadableInterface,
|
||||||
|
ClientWritableInterface,
|
||||||
ClientSearchResultMessageType,
|
ClientSearchResultMessageType,
|
||||||
ConversationType,
|
ConversationType,
|
||||||
GetConversationRangeCenteredOnMessageResultType,
|
GetConversationRangeCenteredOnMessageResultType,
|
||||||
|
@ -45,13 +48,14 @@ import type {
|
||||||
PreKeyIdType,
|
PreKeyIdType,
|
||||||
PreKeyType,
|
PreKeyType,
|
||||||
StoredPreKeyType,
|
StoredPreKeyType,
|
||||||
ServerInterface,
|
|
||||||
ServerSearchResultMessageType,
|
ServerSearchResultMessageType,
|
||||||
SignedPreKeyIdType,
|
SignedPreKeyIdType,
|
||||||
SignedPreKeyType,
|
SignedPreKeyType,
|
||||||
StoredSignedPreKeyType,
|
StoredSignedPreKeyType,
|
||||||
KyberPreKeyType,
|
KyberPreKeyType,
|
||||||
StoredKyberPreKeyType,
|
StoredKyberPreKeyType,
|
||||||
|
ClientOnlyReadableInterface,
|
||||||
|
ClientOnlyWritableInterface,
|
||||||
} from './Interface';
|
} from './Interface';
|
||||||
import { getMessageIdForLogging } from '../util/idForLogging';
|
import { getMessageIdForLogging } from '../util/idForLogging';
|
||||||
import type { MessageAttributesType } from '../model-types';
|
import type { MessageAttributesType } from '../model-types';
|
||||||
|
@ -67,44 +71,54 @@ const ERASE_TEMP_KEY = 'erase-temp';
|
||||||
const ERASE_DRAFTS_KEY = 'erase-drafts';
|
const ERASE_DRAFTS_KEY = 'erase-drafts';
|
||||||
const CLEANUP_ORPHANED_ATTACHMENTS_KEY = 'cleanup-orphaned-attachments';
|
const CLEANUP_ORPHANED_ATTACHMENTS_KEY = 'cleanup-orphaned-attachments';
|
||||||
const ENSURE_FILE_PERMISSIONS = 'ensure-file-permissions';
|
const ENSURE_FILE_PERMISSIONS = 'ensure-file-permissions';
|
||||||
|
const PAUSE_WRITE_ACCESS = 'pause-sql-writes';
|
||||||
|
const RESUME_WRITE_ACCESS = 'resume-sql-writes';
|
||||||
|
|
||||||
const exclusiveInterface: ClientExclusiveInterface = {
|
const clientOnlyReadable: ClientOnlyReadableInterface = {
|
||||||
createOrUpdateIdentityKey,
|
|
||||||
getIdentityKeyById,
|
getIdentityKeyById,
|
||||||
bulkAddIdentityKeys,
|
|
||||||
getAllIdentityKeys,
|
getAllIdentityKeys,
|
||||||
|
|
||||||
createOrUpdateKyberPreKey,
|
|
||||||
getKyberPreKeyById,
|
getKyberPreKeyById,
|
||||||
bulkAddKyberPreKeys,
|
|
||||||
getAllKyberPreKeys,
|
getAllKyberPreKeys,
|
||||||
|
|
||||||
createOrUpdatePreKey,
|
|
||||||
getPreKeyById,
|
getPreKeyById,
|
||||||
bulkAddPreKeys,
|
|
||||||
getAllPreKeys,
|
getAllPreKeys,
|
||||||
|
|
||||||
createOrUpdateSignedPreKey,
|
|
||||||
getSignedPreKeyById,
|
getSignedPreKeyById,
|
||||||
bulkAddSignedPreKeys,
|
|
||||||
getAllSignedPreKeys,
|
getAllSignedPreKeys,
|
||||||
|
|
||||||
createOrUpdateItem,
|
|
||||||
getItemById,
|
getItemById,
|
||||||
getAllItems,
|
getAllItems,
|
||||||
|
|
||||||
|
searchMessages,
|
||||||
|
|
||||||
|
getRecentStoryReplies,
|
||||||
|
getOlderMessagesByConversation,
|
||||||
|
getNewerMessagesByConversation,
|
||||||
|
getConversationRangeCenteredOnMessage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const clientOnlyWritable: ClientOnlyWritableInterface = {
|
||||||
|
createOrUpdateIdentityKey,
|
||||||
|
bulkAddIdentityKeys,
|
||||||
|
|
||||||
|
createOrUpdateKyberPreKey,
|
||||||
|
bulkAddKyberPreKeys,
|
||||||
|
|
||||||
|
createOrUpdatePreKey,
|
||||||
|
bulkAddPreKeys,
|
||||||
|
|
||||||
|
createOrUpdateSignedPreKey,
|
||||||
|
bulkAddSignedPreKeys,
|
||||||
|
|
||||||
|
createOrUpdateItem,
|
||||||
|
|
||||||
updateConversation,
|
updateConversation,
|
||||||
removeConversation,
|
removeConversation,
|
||||||
|
|
||||||
searchMessages,
|
|
||||||
removeMessage,
|
removeMessage,
|
||||||
removeMessages,
|
removeMessages,
|
||||||
|
|
||||||
getRecentStoryReplies,
|
|
||||||
getOlderMessagesByConversation,
|
|
||||||
getConversationRangeCenteredOnMessage,
|
|
||||||
getNewerMessagesByConversation,
|
|
||||||
|
|
||||||
// Client-side only
|
// Client-side only
|
||||||
|
|
||||||
flushUpdateConversationBatcher,
|
flushUpdateConversationBatcher,
|
||||||
|
@ -117,48 +131,82 @@ const exclusiveInterface: ClientExclusiveInterface = {
|
||||||
ensureFilePermissions,
|
ensureFilePermissions,
|
||||||
};
|
};
|
||||||
|
|
||||||
type ClientOverridesType = ClientExclusiveInterface &
|
type ClientOverridesType = ClientOnlyWritableInterface &
|
||||||
Pick<
|
Pick<
|
||||||
ServerInterface,
|
ClientInterfaceWrap<ServerWritableDirectInterface>,
|
||||||
| 'saveAttachmentDownloadJob'
|
| 'saveAttachmentDownloadJob'
|
||||||
| 'saveMessage'
|
| 'saveMessage'
|
||||||
| 'saveMessages'
|
| 'saveMessages'
|
||||||
| 'updateConversations'
|
| 'updateConversations'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
const channels: ServerInterface = new Proxy({} as ServerInterface, {
|
const clientOnlyWritableOverrides: ClientOverridesType = {
|
||||||
get(_target, name) {
|
...clientOnlyWritable,
|
||||||
return async (...args: ReadonlyArray<unknown>) =>
|
|
||||||
ipcInvoke(String(name), args);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const clientExclusiveOverrides: ClientOverridesType = {
|
|
||||||
...exclusiveInterface,
|
|
||||||
saveAttachmentDownloadJob,
|
saveAttachmentDownloadJob,
|
||||||
saveMessage,
|
saveMessage,
|
||||||
saveMessages,
|
saveMessages,
|
||||||
updateConversations,
|
updateConversations,
|
||||||
};
|
};
|
||||||
|
|
||||||
const dataInterface: ClientInterface = new Proxy(
|
type ReadableChannelInterface =
|
||||||
|
ClientInterfaceWrap<ServerReadableDirectInterface>;
|
||||||
|
|
||||||
|
const readableChannel: ReadableChannelInterface = new Proxy(
|
||||||
|
{} as ReadableChannelInterface,
|
||||||
{
|
{
|
||||||
...clientExclusiveOverrides,
|
get(_target, name) {
|
||||||
} as ClientInterface,
|
return async (...args: ReadonlyArray<unknown>) =>
|
||||||
|
ipcInvoke(AccessType.Read, String(name), args);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
type WritableChannelInterface =
|
||||||
|
ClientInterfaceWrap<ServerWritableDirectInterface>;
|
||||||
|
|
||||||
|
const writableChannel: WritableChannelInterface = new Proxy(
|
||||||
|
{} as WritableChannelInterface,
|
||||||
|
{
|
||||||
|
get(_target, name) {
|
||||||
|
return async (...args: ReadonlyArray<unknown>) =>
|
||||||
|
ipcInvoke(AccessType.Write, String(name), args);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const DataReader: ClientReadableInterface = new Proxy(
|
||||||
|
{
|
||||||
|
...clientOnlyReadable,
|
||||||
|
} as ClientReadableInterface,
|
||||||
{
|
{
|
||||||
get(target, name) {
|
get(target, name) {
|
||||||
return async (...args: ReadonlyArray<unknown>) => {
|
return async (...args: ReadonlyArray<unknown>) => {
|
||||||
if (has(target, name)) {
|
if (Reflect.has(target, name)) {
|
||||||
return get(target, name)(...args);
|
return Reflect.get(target, name)(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return get(channels, name)(...args);
|
return Reflect.get(readableChannel, name)(...args);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export default dataInterface;
|
export const DataWriter: ClientWritableInterface = new Proxy(
|
||||||
|
{
|
||||||
|
...clientOnlyWritableOverrides,
|
||||||
|
} as ClientWritableInterface,
|
||||||
|
{
|
||||||
|
get(target, name) {
|
||||||
|
return async (...args: ReadonlyArray<unknown>) => {
|
||||||
|
if (Reflect.has(target, name)) {
|
||||||
|
return Reflect.get(target, name)(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Reflect.get(writableChannel, name)(...args);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function _cleanData(
|
function _cleanData(
|
||||||
data: unknown
|
data: unknown
|
||||||
|
@ -246,9 +294,6 @@ async function shutdown(): Promise<void> {
|
||||||
|
|
||||||
// Stop accepting new SQL jobs, flush outstanding queue
|
// Stop accepting new SQL jobs, flush outstanding queue
|
||||||
await doShutdown();
|
await doShutdown();
|
||||||
|
|
||||||
// Close database
|
|
||||||
await channels.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identity Keys
|
// Identity Keys
|
||||||
|
@ -256,12 +301,12 @@ async function shutdown(): Promise<void> {
|
||||||
const IDENTITY_KEY_SPEC = ['publicKey'];
|
const IDENTITY_KEY_SPEC = ['publicKey'];
|
||||||
async function createOrUpdateIdentityKey(data: IdentityKeyType): Promise<void> {
|
async function createOrUpdateIdentityKey(data: IdentityKeyType): Promise<void> {
|
||||||
const updated: StoredIdentityKeyType = specFromBytes(IDENTITY_KEY_SPEC, data);
|
const updated: StoredIdentityKeyType = specFromBytes(IDENTITY_KEY_SPEC, data);
|
||||||
await channels.createOrUpdateIdentityKey(updated);
|
await writableChannel.createOrUpdateIdentityKey(updated);
|
||||||
}
|
}
|
||||||
async function getIdentityKeyById(
|
async function getIdentityKeyById(
|
||||||
id: IdentityKeyIdType
|
id: IdentityKeyIdType
|
||||||
): Promise<IdentityKeyType | undefined> {
|
): Promise<IdentityKeyType | undefined> {
|
||||||
const data = await channels.getIdentityKeyById(id);
|
const data = await readableChannel.getIdentityKeyById(id);
|
||||||
|
|
||||||
return specToBytes(IDENTITY_KEY_SPEC, data);
|
return specToBytes(IDENTITY_KEY_SPEC, data);
|
||||||
}
|
}
|
||||||
|
@ -271,10 +316,10 @@ async function bulkAddIdentityKeys(
|
||||||
const updated: Array<StoredIdentityKeyType> = map(array, data =>
|
const updated: Array<StoredIdentityKeyType> = map(array, data =>
|
||||||
specFromBytes(IDENTITY_KEY_SPEC, data)
|
specFromBytes(IDENTITY_KEY_SPEC, data)
|
||||||
);
|
);
|
||||||
await channels.bulkAddIdentityKeys(updated);
|
await writableChannel.bulkAddIdentityKeys(updated);
|
||||||
}
|
}
|
||||||
async function getAllIdentityKeys(): Promise<Array<IdentityKeyType>> {
|
async function getAllIdentityKeys(): Promise<Array<IdentityKeyType>> {
|
||||||
const keys = await channels.getAllIdentityKeys();
|
const keys = await readableChannel.getAllIdentityKeys();
|
||||||
|
|
||||||
return keys.map(key => specToBytes(IDENTITY_KEY_SPEC, key));
|
return keys.map(key => specToBytes(IDENTITY_KEY_SPEC, key));
|
||||||
}
|
}
|
||||||
|
@ -287,12 +332,12 @@ async function createOrUpdateKyberPreKey(data: KyberPreKeyType): Promise<void> {
|
||||||
KYBER_PRE_KEY_SPEC,
|
KYBER_PRE_KEY_SPEC,
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
await channels.createOrUpdateKyberPreKey(updated);
|
await writableChannel.createOrUpdateKyberPreKey(updated);
|
||||||
}
|
}
|
||||||
async function getKyberPreKeyById(
|
async function getKyberPreKeyById(
|
||||||
id: PreKeyIdType
|
id: PreKeyIdType
|
||||||
): Promise<KyberPreKeyType | undefined> {
|
): Promise<KyberPreKeyType | undefined> {
|
||||||
const data = await channels.getPreKeyById(id);
|
const data = await readableChannel.getPreKeyById(id);
|
||||||
|
|
||||||
return specToBytes(KYBER_PRE_KEY_SPEC, data);
|
return specToBytes(KYBER_PRE_KEY_SPEC, data);
|
||||||
}
|
}
|
||||||
|
@ -302,10 +347,10 @@ async function bulkAddKyberPreKeys(
|
||||||
const updated: Array<StoredKyberPreKeyType> = map(array, data =>
|
const updated: Array<StoredKyberPreKeyType> = map(array, data =>
|
||||||
specFromBytes(KYBER_PRE_KEY_SPEC, data)
|
specFromBytes(KYBER_PRE_KEY_SPEC, data)
|
||||||
);
|
);
|
||||||
await channels.bulkAddKyberPreKeys(updated);
|
await writableChannel.bulkAddKyberPreKeys(updated);
|
||||||
}
|
}
|
||||||
async function getAllKyberPreKeys(): Promise<Array<KyberPreKeyType>> {
|
async function getAllKyberPreKeys(): Promise<Array<KyberPreKeyType>> {
|
||||||
const keys = await channels.getAllKyberPreKeys();
|
const keys = await readableChannel.getAllKyberPreKeys();
|
||||||
|
|
||||||
return keys.map(key => specToBytes(KYBER_PRE_KEY_SPEC, key));
|
return keys.map(key => specToBytes(KYBER_PRE_KEY_SPEC, key));
|
||||||
}
|
}
|
||||||
|
@ -314,12 +359,12 @@ async function getAllKyberPreKeys(): Promise<Array<KyberPreKeyType>> {
|
||||||
|
|
||||||
async function createOrUpdatePreKey(data: PreKeyType): Promise<void> {
|
async function createOrUpdatePreKey(data: PreKeyType): Promise<void> {
|
||||||
const updated: StoredPreKeyType = specFromBytes(PRE_KEY_SPEC, data);
|
const updated: StoredPreKeyType = specFromBytes(PRE_KEY_SPEC, data);
|
||||||
await channels.createOrUpdatePreKey(updated);
|
await writableChannel.createOrUpdatePreKey(updated);
|
||||||
}
|
}
|
||||||
async function getPreKeyById(
|
async function getPreKeyById(
|
||||||
id: PreKeyIdType
|
id: PreKeyIdType
|
||||||
): Promise<PreKeyType | undefined> {
|
): Promise<PreKeyType | undefined> {
|
||||||
const data = await channels.getPreKeyById(id);
|
const data = await readableChannel.getPreKeyById(id);
|
||||||
|
|
||||||
return specToBytes(PRE_KEY_SPEC, data);
|
return specToBytes(PRE_KEY_SPEC, data);
|
||||||
}
|
}
|
||||||
|
@ -327,10 +372,10 @@ async function bulkAddPreKeys(array: Array<PreKeyType>): Promise<void> {
|
||||||
const updated: Array<StoredPreKeyType> = map(array, data =>
|
const updated: Array<StoredPreKeyType> = map(array, data =>
|
||||||
specFromBytes(PRE_KEY_SPEC, data)
|
specFromBytes(PRE_KEY_SPEC, data)
|
||||||
);
|
);
|
||||||
await channels.bulkAddPreKeys(updated);
|
await writableChannel.bulkAddPreKeys(updated);
|
||||||
}
|
}
|
||||||
async function getAllPreKeys(): Promise<Array<PreKeyType>> {
|
async function getAllPreKeys(): Promise<Array<PreKeyType>> {
|
||||||
const keys = await channels.getAllPreKeys();
|
const keys = await readableChannel.getAllPreKeys();
|
||||||
|
|
||||||
return keys.map(key => specToBytes(PRE_KEY_SPEC, key));
|
return keys.map(key => specToBytes(PRE_KEY_SPEC, key));
|
||||||
}
|
}
|
||||||
|
@ -342,17 +387,17 @@ async function createOrUpdateSignedPreKey(
|
||||||
data: SignedPreKeyType
|
data: SignedPreKeyType
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const updated: StoredSignedPreKeyType = specFromBytes(PRE_KEY_SPEC, data);
|
const updated: StoredSignedPreKeyType = specFromBytes(PRE_KEY_SPEC, data);
|
||||||
await channels.createOrUpdateSignedPreKey(updated);
|
await writableChannel.createOrUpdateSignedPreKey(updated);
|
||||||
}
|
}
|
||||||
async function getSignedPreKeyById(
|
async function getSignedPreKeyById(
|
||||||
id: SignedPreKeyIdType
|
id: SignedPreKeyIdType
|
||||||
): Promise<SignedPreKeyType | undefined> {
|
): Promise<SignedPreKeyType | undefined> {
|
||||||
const data = await channels.getSignedPreKeyById(id);
|
const data = await readableChannel.getSignedPreKeyById(id);
|
||||||
|
|
||||||
return specToBytes(PRE_KEY_SPEC, data);
|
return specToBytes(PRE_KEY_SPEC, data);
|
||||||
}
|
}
|
||||||
async function getAllSignedPreKeys(): Promise<Array<SignedPreKeyType>> {
|
async function getAllSignedPreKeys(): Promise<Array<SignedPreKeyType>> {
|
||||||
const keys = await channels.getAllSignedPreKeys();
|
const keys = await readableChannel.getAllSignedPreKeys();
|
||||||
|
|
||||||
return keys.map(key => specToBytes(PRE_KEY_SPEC, key));
|
return keys.map(key => specToBytes(PRE_KEY_SPEC, key));
|
||||||
}
|
}
|
||||||
|
@ -362,7 +407,7 @@ async function bulkAddSignedPreKeys(
|
||||||
const updated: Array<StoredSignedPreKeyType> = map(array, data =>
|
const updated: Array<StoredSignedPreKeyType> = map(array, data =>
|
||||||
specFromBytes(PRE_KEY_SPEC, data)
|
specFromBytes(PRE_KEY_SPEC, data)
|
||||||
);
|
);
|
||||||
await channels.bulkAddSignedPreKeys(updated);
|
await writableChannel.bulkAddSignedPreKeys(updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Items
|
// Items
|
||||||
|
@ -398,13 +443,13 @@ async function createOrUpdateItem<K extends ItemKeyType>(
|
||||||
? specFromBytes(spec, data)
|
? specFromBytes(spec, data)
|
||||||
: (data as unknown as StoredItemType<K>);
|
: (data as unknown as StoredItemType<K>);
|
||||||
|
|
||||||
await channels.createOrUpdateItem(updated);
|
await writableChannel.createOrUpdateItem(updated);
|
||||||
}
|
}
|
||||||
async function getItemById<K extends ItemKeyType>(
|
async function getItemById<K extends ItemKeyType>(
|
||||||
id: K
|
id: K
|
||||||
): Promise<ItemType<K> | undefined> {
|
): Promise<ItemType<K> | undefined> {
|
||||||
const spec = ITEM_SPECS[id];
|
const spec = ITEM_SPECS[id];
|
||||||
const data = await channels.getItemById(id);
|
const data = await readableChannel.getItemById(id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return spec ? specToBytes(spec, data) : (data as unknown as ItemType<K>);
|
return spec ? specToBytes(spec, data) : (data as unknown as ItemType<K>);
|
||||||
|
@ -414,7 +459,7 @@ async function getItemById<K extends ItemKeyType>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function getAllItems(): Promise<AllItemsType> {
|
async function getAllItems(): Promise<AllItemsType> {
|
||||||
const items = await channels.getAllItems();
|
const items = await readableChannel.getAllItems();
|
||||||
|
|
||||||
const result = Object.create(null);
|
const result = Object.create(null);
|
||||||
|
|
||||||
|
@ -458,7 +503,7 @@ const updateConversationBatcher = createBatcher<ConversationType>({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateConversation(data: ConversationType): void {
|
async function updateConversation(data: ConversationType): Promise<void> {
|
||||||
updateConversationBatcher.add(data);
|
updateConversationBatcher.add(data);
|
||||||
}
|
}
|
||||||
async function flushUpdateConversationBatcher(): Promise<void> {
|
async function flushUpdateConversationBatcher(): Promise<void> {
|
||||||
|
@ -473,16 +518,16 @@ async function updateConversations(
|
||||||
!pathsChanged.length,
|
!pathsChanged.length,
|
||||||
`Paths were cleaned: ${JSON.stringify(pathsChanged)}`
|
`Paths were cleaned: ${JSON.stringify(pathsChanged)}`
|
||||||
);
|
);
|
||||||
await channels.updateConversations(cleaned);
|
await writableChannel.updateConversations(cleaned);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function removeConversation(id: string): Promise<void> {
|
async function removeConversation(id: string): Promise<void> {
|
||||||
const existing = await channels.getConversationById(id);
|
const existing = await readableChannel.getConversationById(id);
|
||||||
|
|
||||||
// Note: It's important to have a fully database-hydrated model to delete here because
|
// 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.
|
// it needs to delete all associated on-disk files along with the database delete.
|
||||||
if (existing) {
|
if (existing) {
|
||||||
await channels.removeConversation(id);
|
await writableChannel.removeConversation(id);
|
||||||
await deleteExternalFiles(existing, {
|
await deleteExternalFiles(existing, {
|
||||||
deleteAttachmentData: window.Signal.Migrations.deleteAttachmentData,
|
deleteAttachmentData: window.Signal.Migrations.deleteAttachmentData,
|
||||||
});
|
});
|
||||||
|
@ -528,7 +573,7 @@ async function searchMessages({
|
||||||
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
}): Promise<Array<ClientSearchResultMessageType>> {
|
}): Promise<Array<ClientSearchResultMessageType>> {
|
||||||
const messages = await channels.searchMessages({
|
const messages = await readableChannel.searchMessages({
|
||||||
query,
|
query,
|
||||||
conversationId,
|
conversationId,
|
||||||
options,
|
options,
|
||||||
|
@ -548,7 +593,7 @@ async function saveMessage(
|
||||||
ourAci: AciString;
|
ourAci: AciString;
|
||||||
}
|
}
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const id = await channels.saveMessage(_cleanMessageData(data), {
|
const id = await writableChannel.saveMessage(_cleanMessageData(data), {
|
||||||
...options,
|
...options,
|
||||||
jobToInsert: options.jobToInsert && formatJobForInsert(options.jobToInsert),
|
jobToInsert: options.jobToInsert && formatJobForInsert(options.jobToInsert),
|
||||||
});
|
});
|
||||||
|
@ -565,7 +610,7 @@ async function saveMessages(
|
||||||
arrayOfMessages: ReadonlyArray<MessageType>,
|
arrayOfMessages: ReadonlyArray<MessageType>,
|
||||||
options: { forceSave?: boolean; ourAci: AciString }
|
options: { forceSave?: boolean; ourAci: AciString }
|
||||||
): Promise<Array<string>> {
|
): Promise<Array<string>> {
|
||||||
const result = await channels.saveMessages(
|
const result = await writableChannel.saveMessages(
|
||||||
arrayOfMessages.map(message => _cleanMessageData(message)),
|
arrayOfMessages.map(message => _cleanMessageData(message)),
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
|
@ -583,15 +628,15 @@ async function removeMessage(
|
||||||
fromSync?: boolean;
|
fromSync?: boolean;
|
||||||
}
|
}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const message = await channels.getMessageById(id);
|
const message = await readableChannel.getMessageById(id);
|
||||||
|
|
||||||
// Note: It's important to have a fully database-hydrated model to delete here because
|
// 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.
|
// it needs to delete all associated on-disk files along with the database delete.
|
||||||
if (message) {
|
if (message) {
|
||||||
await channels.removeMessage(id);
|
await writableChannel.removeMessage(id);
|
||||||
await cleanupMessages([message], {
|
await cleanupMessages([message], {
|
||||||
...options,
|
...options,
|
||||||
markCallHistoryDeleted: dataInterface.markCallHistoryDeleted,
|
markCallHistoryDeleted: DataWriter.markCallHistoryDeleted,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -607,12 +652,12 @@ export async function deleteAndCleanup(
|
||||||
const ids = messages.map(message => message.id);
|
const ids = messages.map(message => message.id);
|
||||||
|
|
||||||
log.info(`deleteAndCleanup/${logId}: Deleting ${ids.length} messages...`);
|
log.info(`deleteAndCleanup/${logId}: Deleting ${ids.length} messages...`);
|
||||||
await channels.removeMessages(ids);
|
await writableChannel.removeMessages(ids);
|
||||||
|
|
||||||
log.info(`deleteAndCleanup/${logId}: Cleanup for ${ids.length} messages...`);
|
log.info(`deleteAndCleanup/${logId}: Cleanup for ${ids.length} messages...`);
|
||||||
await cleanupMessages(messages, {
|
await cleanupMessages(messages, {
|
||||||
...options,
|
...options,
|
||||||
markCallHistoryDeleted: dataInterface.markCallHistoryDeleted,
|
markCallHistoryDeleted: DataWriter.markCallHistoryDeleted,
|
||||||
});
|
});
|
||||||
|
|
||||||
log.info(`deleteAndCleanup/${logId}: Complete`);
|
log.info(`deleteAndCleanup/${logId}: Complete`);
|
||||||
|
@ -625,12 +670,12 @@ async function removeMessages(
|
||||||
singleProtoJobQueue: SingleProtoJobQueue;
|
singleProtoJobQueue: SingleProtoJobQueue;
|
||||||
}
|
}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const messages = await channels.getMessagesById(messageIds);
|
const messages = await readableChannel.getMessagesById(messageIds);
|
||||||
await cleanupMessages(messages, {
|
await cleanupMessages(messages, {
|
||||||
...options,
|
...options,
|
||||||
markCallHistoryDeleted: dataInterface.markCallHistoryDeleted,
|
markCallHistoryDeleted: DataWriter.markCallHistoryDeleted,
|
||||||
});
|
});
|
||||||
await channels.removeMessages(messageIds);
|
await writableChannel.removeMessages(messageIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMessageJSON(
|
function handleMessageJSON(
|
||||||
|
@ -642,7 +687,9 @@ function handleMessageJSON(
|
||||||
async function getNewerMessagesByConversation(
|
async function getNewerMessagesByConversation(
|
||||||
options: AdjacentMessagesByConversationOptionsType
|
options: AdjacentMessagesByConversationOptionsType
|
||||||
): Promise<Array<MessageType>> {
|
): Promise<Array<MessageType>> {
|
||||||
const messages = await channels.getNewerMessagesByConversation(options);
|
const messages = await readableChannel.getNewerMessagesByConversation(
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
return handleMessageJSON(messages);
|
return handleMessageJSON(messages);
|
||||||
}
|
}
|
||||||
|
@ -651,7 +698,10 @@ async function getRecentStoryReplies(
|
||||||
storyId: string,
|
storyId: string,
|
||||||
options?: GetRecentStoryRepliesOptionsType
|
options?: GetRecentStoryRepliesOptionsType
|
||||||
): Promise<Array<MessageType>> {
|
): Promise<Array<MessageType>> {
|
||||||
const messages = await channels.getRecentStoryReplies(storyId, options);
|
const messages = await readableChannel.getRecentStoryReplies(
|
||||||
|
storyId,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
return handleMessageJSON(messages);
|
return handleMessageJSON(messages);
|
||||||
}
|
}
|
||||||
|
@ -659,7 +709,9 @@ async function getRecentStoryReplies(
|
||||||
async function getOlderMessagesByConversation(
|
async function getOlderMessagesByConversation(
|
||||||
options: AdjacentMessagesByConversationOptionsType
|
options: AdjacentMessagesByConversationOptionsType
|
||||||
): Promise<Array<MessageType>> {
|
): Promise<Array<MessageType>> {
|
||||||
const messages = await channels.getOlderMessagesByConversation(options);
|
const messages = await readableChannel.getOlderMessagesByConversation(
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
return handleMessageJSON(messages);
|
return handleMessageJSON(messages);
|
||||||
}
|
}
|
||||||
|
@ -667,7 +719,9 @@ async function getOlderMessagesByConversation(
|
||||||
async function getConversationRangeCenteredOnMessage(
|
async function getConversationRangeCenteredOnMessage(
|
||||||
options: AdjacentMessagesByConversationOptionsType
|
options: AdjacentMessagesByConversationOptionsType
|
||||||
): Promise<GetConversationRangeCenteredOnMessageResultType<MessageType>> {
|
): Promise<GetConversationRangeCenteredOnMessageResultType<MessageType>> {
|
||||||
const result = await channels.getConversationRangeCenteredOnMessage(options);
|
const result = await readableChannel.getConversationRangeCenteredOnMessage(
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
|
@ -721,7 +775,7 @@ async function removeMessagesInConversation(
|
||||||
async function saveAttachmentDownloadJob(
|
async function saveAttachmentDownloadJob(
|
||||||
job: AttachmentDownloadJobType
|
job: AttachmentDownloadJobType
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await channels.saveAttachmentDownloadJob(_cleanData(job));
|
await writableChannel.saveAttachmentDownloadJob(_cleanData(job));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
@ -758,3 +812,11 @@ async function invokeWithTimeout(name: string): Promise<void> {
|
||||||
`callChannel call to ${name}`
|
`callChannel call to ${name}`
|
||||||
)();
|
)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function pauseWriteAccess(): Promise<void> {
|
||||||
|
return invokeWithTimeout(PAUSE_WRITE_ACCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resumeWriteAccess(): Promise<void> {
|
||||||
|
return invokeWithTimeout(RESUME_WRITE_ACCESS);
|
||||||
|
}
|
||||||
|
|
1283
ts/sql/Interface.ts
1283
ts/sql/Interface.ts
File diff suppressed because it is too large
Load diff
2236
ts/sql/Server.ts
2236
ts/sql/Server.ts
File diff suppressed because it is too large
Load diff
|
@ -5,13 +5,21 @@ import { ipcRenderer } from 'electron';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import createTaskWithTimeout from '../textsecure/TaskWithTimeout';
|
import createTaskWithTimeout from '../textsecure/TaskWithTimeout';
|
||||||
import { explodePromise } from '../util/explodePromise';
|
import { explodePromise } from '../util/explodePromise';
|
||||||
|
import { missingCaseError } from '../util/missingCaseError';
|
||||||
|
|
||||||
const SQL_CHANNEL_KEY = 'sql-channel';
|
const SQL_READ_KEY = 'sql-channel:read';
|
||||||
|
const SQL_WRITE_KEY = 'sql-channel:write';
|
||||||
let activeJobCount = 0;
|
let activeJobCount = 0;
|
||||||
let resolveShutdown: (() => void) | undefined;
|
let resolveShutdown: (() => void) | undefined;
|
||||||
let shutdownPromise: Promise<void> | null = null;
|
let shutdownPromise: Promise<void> | null = null;
|
||||||
|
|
||||||
|
export enum AccessType {
|
||||||
|
Read = 'Read',
|
||||||
|
Write = 'Write',
|
||||||
|
}
|
||||||
|
|
||||||
export async function ipcInvoke<T>(
|
export async function ipcInvoke<T>(
|
||||||
|
access: AccessType,
|
||||||
name: string,
|
name: string,
|
||||||
args: ReadonlyArray<unknown>
|
args: ReadonlyArray<unknown>
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
|
@ -19,21 +27,31 @@ export async function ipcInvoke<T>(
|
||||||
|
|
||||||
if (shutdownPromise && name !== 'close') {
|
if (shutdownPromise && name !== 'close') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Rejecting SQL channel job (${fnName}); application is shutting down`
|
`Rejecting SQL channel job (${access}, ${fnName}); ` +
|
||||||
|
'application is shutting down'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let channel: string;
|
||||||
|
if (access === AccessType.Read) {
|
||||||
|
channel = SQL_READ_KEY;
|
||||||
|
} else if (access === AccessType.Write) {
|
||||||
|
channel = SQL_WRITE_KEY;
|
||||||
|
} else {
|
||||||
|
throw missingCaseError(access);
|
||||||
|
}
|
||||||
|
|
||||||
activeJobCount += 1;
|
activeJobCount += 1;
|
||||||
return createTaskWithTimeout(async () => {
|
return createTaskWithTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
return await ipcRenderer.invoke(SQL_CHANNEL_KEY, name, ...args);
|
return await ipcRenderer.invoke(channel, name, ...args);
|
||||||
} finally {
|
} finally {
|
||||||
activeJobCount -= 1;
|
activeJobCount -= 1;
|
||||||
if (activeJobCount === 0) {
|
if (activeJobCount === 0) {
|
||||||
resolveShutdown?.();
|
resolveShutdown?.();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, `SQL channel call (${fnName})`)();
|
}, `SQL channel call (${access}, ${fnName})`)();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function doShutdown(): Promise<void> {
|
export async function doShutdown(): Promise<void> {
|
||||||
|
|
406
ts/sql/main.ts
406
ts/sql/main.ts
|
@ -10,10 +10,15 @@ import { strictAssert } from '../util/assert';
|
||||||
import { explodePromise } from '../util/explodePromise';
|
import { explodePromise } from '../util/explodePromise';
|
||||||
import type { LoggerType } from '../types/Logging';
|
import type { LoggerType } from '../types/Logging';
|
||||||
import { SqliteErrorKind } from './errors';
|
import { SqliteErrorKind } from './errors';
|
||||||
import type DB from './Server';
|
import type {
|
||||||
|
ServerReadableDirectInterface,
|
||||||
|
ServerWritableDirectInterface,
|
||||||
|
} from './Interface';
|
||||||
|
|
||||||
const MIN_TRACE_DURATION = 40;
|
const MIN_TRACE_DURATION = 40;
|
||||||
|
|
||||||
|
const WORKER_COUNT = 4;
|
||||||
|
|
||||||
export type InitializeOptions = Readonly<{
|
export type InitializeOptions = Readonly<{
|
||||||
appVersion: string;
|
appVersion: string;
|
||||||
configDir: string;
|
configDir: string;
|
||||||
|
@ -25,16 +30,19 @@ export type WorkerRequest = Readonly<
|
||||||
| {
|
| {
|
||||||
type: 'init';
|
type: 'init';
|
||||||
options: Omit<InitializeOptions, 'logger'>;
|
options: Omit<InitializeOptions, 'logger'>;
|
||||||
|
isPrimary: boolean;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'close';
|
type: 'close' | 'removeDB';
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'removeDB';
|
type: 'sqlCall:read';
|
||||||
|
method: keyof ServerReadableDirectInterface;
|
||||||
|
args: ReadonlyArray<unknown>;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'sqlCall';
|
type: 'sqlCall:write';
|
||||||
method: keyof typeof DB;
|
method: keyof ServerWritableDirectInterface;
|
||||||
args: ReadonlyArray<unknown>;
|
args: ReadonlyArray<unknown>;
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
@ -71,14 +79,26 @@ type KnownErrorResolverType = Readonly<{
|
||||||
resolve: (err: Error) => void;
|
resolve: (err: Error) => void;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
type CreateWorkerResultType = Readonly<{
|
||||||
|
worker: Worker;
|
||||||
|
onExit: Promise<void>;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
type PoolEntry = {
|
||||||
|
readonly worker: Worker;
|
||||||
|
load: number;
|
||||||
|
};
|
||||||
|
|
||||||
export class MainSQL {
|
export class MainSQL {
|
||||||
private readonly worker: Worker;
|
private readonly pool = new Array<PoolEntry>();
|
||||||
|
|
||||||
|
private pauseWaiters: Array<() => void> | undefined;
|
||||||
|
|
||||||
private isReady = false;
|
private isReady = false;
|
||||||
|
|
||||||
private onReady: Promise<void> | undefined;
|
private onReady: Promise<void> | undefined;
|
||||||
|
|
||||||
private readonly onExit: Promise<void>;
|
private readonly onExit: Promise<unknown>;
|
||||||
|
|
||||||
// Promise resolve callbacks for corruption and readonly errors.
|
// Promise resolve callbacks for corruption and readonly errors.
|
||||||
private errorResolvers = new Array<KnownErrorResolverType>();
|
private errorResolvers = new Array<KnownErrorResolverType>();
|
||||||
|
@ -93,10 +113,246 @@ export class MainSQL {
|
||||||
private shouldTimeQueries = false;
|
private shouldTimeQueries = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const scriptDir = join(app.getAppPath(), 'ts', 'sql', 'mainWorker.js');
|
const exitPromises = new Array<Promise<void>>();
|
||||||
this.worker = new Worker(scriptDir);
|
for (let i = 0; i < WORKER_COUNT; i += 1) {
|
||||||
|
const { worker, onExit } = this.createWorker();
|
||||||
|
this.pool.push({ worker, load: 0 });
|
||||||
|
|
||||||
this.worker.on('message', (wrappedResponse: WrappedWorkerResponse) => {
|
exitPromises.push(onExit);
|
||||||
|
}
|
||||||
|
this.onExit = Promise.all(exitPromises);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async initialize({
|
||||||
|
appVersion,
|
||||||
|
configDir,
|
||||||
|
key,
|
||||||
|
logger,
|
||||||
|
}: InitializeOptions): Promise<void> {
|
||||||
|
if (this.isReady || this.onReady) {
|
||||||
|
throw new Error('Already initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.shouldTimeQueries = Boolean(process.env.TIME_QUERIES);
|
||||||
|
|
||||||
|
this.logger = logger;
|
||||||
|
|
||||||
|
this.onReady = (async () => {
|
||||||
|
const primary = this.pool[0];
|
||||||
|
const rest = this.pool.slice(1);
|
||||||
|
|
||||||
|
await this.send(primary, {
|
||||||
|
type: 'init',
|
||||||
|
options: { appVersion, configDir, key },
|
||||||
|
isPrimary: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
rest.map(worker =>
|
||||||
|
this.send(worker, {
|
||||||
|
type: 'init',
|
||||||
|
options: { appVersion, configDir, key },
|
||||||
|
isPrimary: false,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})();
|
||||||
|
|
||||||
|
await this.onReady;
|
||||||
|
|
||||||
|
this.onReady = undefined;
|
||||||
|
this.isReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public pauseWriteAccess(): void {
|
||||||
|
strictAssert(this.pauseWaiters == null, 'Already paused');
|
||||||
|
|
||||||
|
this.pauseWaiters = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public resumeWriteAccess(): void {
|
||||||
|
const { pauseWaiters } = this;
|
||||||
|
strictAssert(pauseWaiters != null, 'Not paused');
|
||||||
|
this.pauseWaiters = undefined;
|
||||||
|
|
||||||
|
for (const waiter of pauseWaiters) {
|
||||||
|
waiter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public whenCorrupted(): Promise<Error> {
|
||||||
|
const { promise, resolve } = explodePromise<Error>();
|
||||||
|
this.errorResolvers.push({ kind: SqliteErrorKind.Corrupted, resolve });
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
public whenReadonly(): Promise<Error> {
|
||||||
|
const { promise, resolve } = explodePromise<Error>();
|
||||||
|
this.errorResolvers.push({ kind: SqliteErrorKind.Readonly, resolve });
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async close(): Promise<void> {
|
||||||
|
if (!this.isReady) {
|
||||||
|
throw new Error('Not initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.terminate({ type: 'close' });
|
||||||
|
await this.onExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async removeDB(): Promise<void> {
|
||||||
|
await this.terminate({ type: 'removeDB' });
|
||||||
|
}
|
||||||
|
|
||||||
|
public async sqlRead<Method extends keyof ServerReadableDirectInterface>(
|
||||||
|
method: Method,
|
||||||
|
...args: Parameters<ServerReadableDirectInterface[Method]>
|
||||||
|
): Promise<ReturnType<ServerReadableDirectInterface[Method]>> {
|
||||||
|
type SqlCallResult = Readonly<{
|
||||||
|
result: ReturnType<ServerReadableDirectInterface[Method]>;
|
||||||
|
duration: number;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
// pageMessages runs over several queries and needs to have access to
|
||||||
|
// the same temporary table.
|
||||||
|
const isPaging = method === 'pageMessages';
|
||||||
|
|
||||||
|
const entry = isPaging ? this.pool.at(-1) : this.getWorker();
|
||||||
|
strictAssert(entry != null, 'Must have a pool entry');
|
||||||
|
|
||||||
|
const { result, duration } = await this.send<SqlCallResult>(entry, {
|
||||||
|
type: 'sqlCall:read',
|
||||||
|
method,
|
||||||
|
args,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.traceDuration(method, duration);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async sqlWrite<Method extends keyof ServerWritableDirectInterface>(
|
||||||
|
method: Method,
|
||||||
|
...args: Parameters<ServerWritableDirectInterface[Method]>
|
||||||
|
): Promise<ReturnType<ServerWritableDirectInterface[Method]>> {
|
||||||
|
type Result = ReturnType<ServerWritableDirectInterface[Method]>;
|
||||||
|
type SqlCallResult = Readonly<{
|
||||||
|
result: Result;
|
||||||
|
duration: number;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
while (this.pauseWaiters != null) {
|
||||||
|
const { promise, resolve } = explodePromise<void>();
|
||||||
|
this.pauseWaiters.push(resolve);
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case since we need to broadcast this to every pool entry.
|
||||||
|
if (method === 'removeDB') {
|
||||||
|
return (await this.removeDB()) as Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const primary = this.pool[0];
|
||||||
|
|
||||||
|
const { result, duration } = await this.send<SqlCallResult>(primary, {
|
||||||
|
type: 'sqlCall:write',
|
||||||
|
method,
|
||||||
|
args,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.traceDuration(method, duration);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async send<Response>(
|
||||||
|
entry: PoolEntry,
|
||||||
|
request: WorkerRequest
|
||||||
|
): Promise<Response> {
|
||||||
|
if (request.type === 'sqlCall:read' || request.type === 'sqlCall:write') {
|
||||||
|
if (this.onReady) {
|
||||||
|
await this.onReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isReady) {
|
||||||
|
throw new Error('Not initialized');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { seq } = this;
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
this.seq = (this.seq + 1) >>> 0;
|
||||||
|
|
||||||
|
const { promise: result, resolve, reject } = explodePromise<Response>();
|
||||||
|
this.onResponse.set(seq, { resolve, reject });
|
||||||
|
|
||||||
|
const wrappedRequest: WrappedWorkerRequest = {
|
||||||
|
seq,
|
||||||
|
request,
|
||||||
|
};
|
||||||
|
entry.worker.postMessage(wrappedRequest);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
entry.load += 1;
|
||||||
|
return await result;
|
||||||
|
} finally {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
entry.load -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async terminate(request: WorkerRequest): Promise<void> {
|
||||||
|
const primary = this.pool[0];
|
||||||
|
const rest = this.pool.slice(1);
|
||||||
|
|
||||||
|
// Terminate non-primary workers first
|
||||||
|
await Promise.all(rest.map(worker => this.send(worker, request)));
|
||||||
|
|
||||||
|
// Primary last
|
||||||
|
await this.send(primary, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private onError(errorKind: SqliteErrorKind, error: Error): void {
|
||||||
|
if (errorKind === SqliteErrorKind.Unknown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvers = new Array<(error: Error) => void>();
|
||||||
|
this.errorResolvers = this.errorResolvers.filter(entry => {
|
||||||
|
if (entry.kind === errorKind) {
|
||||||
|
resolvers.push(entry.resolve);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const resolve of resolvers) {
|
||||||
|
resolve(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private traceDuration(method: string, duration: number): void {
|
||||||
|
if (this.shouldTimeQueries && !app.isPackaged) {
|
||||||
|
const twoDecimals = Math.round(100 * duration) / 100;
|
||||||
|
this.logger?.info(`MainSQL query: ${method}, duration=${twoDecimals}ms`);
|
||||||
|
}
|
||||||
|
if (duration > MIN_TRACE_DURATION) {
|
||||||
|
strictAssert(this.logger !== undefined, 'Logger not initialized');
|
||||||
|
this.logger.info(
|
||||||
|
`MainSQL: slow query ${method} duration=${Math.round(duration)}ms`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private createWorker(): CreateWorkerResultType {
|
||||||
|
const scriptPath = join(app.getAppPath(), 'ts', 'sql', 'mainWorker.js');
|
||||||
|
|
||||||
|
const worker = new Worker(scriptPath);
|
||||||
|
|
||||||
|
worker.on('message', (wrappedResponse: WrappedWorkerResponse) => {
|
||||||
if (wrappedResponse.type === 'log') {
|
if (wrappedResponse.type === 'log') {
|
||||||
const { level, args } = wrappedResponse;
|
const { level, args } = wrappedResponse;
|
||||||
strictAssert(this.logger !== undefined, 'Logger not initialized');
|
strictAssert(this.logger !== undefined, 'Logger not initialized');
|
||||||
|
@ -123,129 +379,21 @@ export class MainSQL {
|
||||||
});
|
});
|
||||||
|
|
||||||
const { promise: onExit, resolve: resolveOnExit } = explodePromise<void>();
|
const { promise: onExit, resolve: resolveOnExit } = explodePromise<void>();
|
||||||
this.onExit = onExit;
|
worker.once('exit', resolveOnExit);
|
||||||
this.worker.once('exit', resolveOnExit);
|
|
||||||
|
return { worker, onExit };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initialize({
|
// Find first pool entry with minimal load
|
||||||
appVersion,
|
private getWorker(): PoolEntry {
|
||||||
configDir,
|
let min = this.pool[0];
|
||||||
key,
|
for (const entry of this.pool) {
|
||||||
logger,
|
if (min && min.load < entry.load) {
|
||||||
}: InitializeOptions): Promise<void> {
|
continue;
|
||||||
if (this.isReady || this.onReady) {
|
|
||||||
throw new Error('Already initialized');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shouldTimeQueries = Boolean(process.env.TIME_QUERIES);
|
min = entry;
|
||||||
|
|
||||||
this.logger = logger;
|
|
||||||
|
|
||||||
this.onReady = this.send({
|
|
||||||
type: 'init',
|
|
||||||
options: { appVersion, configDir, key },
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.onReady;
|
|
||||||
|
|
||||||
this.onReady = undefined;
|
|
||||||
this.isReady = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public whenCorrupted(): Promise<Error> {
|
|
||||||
const { promise, resolve } = explodePromise<Error>();
|
|
||||||
this.errorResolvers.push({ kind: SqliteErrorKind.Corrupted, resolve });
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
public whenReadonly(): Promise<Error> {
|
|
||||||
const { promise, resolve } = explodePromise<Error>();
|
|
||||||
this.errorResolvers.push({ kind: SqliteErrorKind.Readonly, resolve });
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async close(): Promise<void> {
|
|
||||||
if (!this.isReady) {
|
|
||||||
throw new Error('Not initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.send({ type: 'close' });
|
|
||||||
await this.onExit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async removeDB(): Promise<void> {
|
|
||||||
await this.send({ type: 'removeDB' });
|
|
||||||
}
|
|
||||||
|
|
||||||
public async sqlCall<Method extends keyof typeof DB>(
|
|
||||||
method: Method,
|
|
||||||
...args: Parameters<typeof DB[Method]>
|
|
||||||
): Promise<ReturnType<typeof DB[Method]>> {
|
|
||||||
if (this.onReady) {
|
|
||||||
await this.onReady;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.isReady) {
|
|
||||||
throw new Error('Not initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
type SqlCallResult = Readonly<{
|
|
||||||
result: ReturnType<typeof DB[Method]>;
|
|
||||||
duration: number;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
const { result, duration } = await this.send<SqlCallResult>({
|
|
||||||
type: 'sqlCall',
|
|
||||||
method,
|
|
||||||
args,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.shouldTimeQueries && !app.isPackaged) {
|
|
||||||
const twoDecimals = Math.round(100 * duration) / 100;
|
|
||||||
this.logger?.info(`MainSQL query: ${method}, duration=${twoDecimals}ms`);
|
|
||||||
}
|
|
||||||
if (duration > MIN_TRACE_DURATION) {
|
|
||||||
strictAssert(this.logger !== undefined, 'Logger not initialized');
|
|
||||||
this.logger.info(
|
|
||||||
`MainSQL: slow query ${method} duration=${Math.round(duration)}ms`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async send<Response>(request: WorkerRequest): Promise<Response> {
|
|
||||||
const { seq } = this;
|
|
||||||
this.seq += 1;
|
|
||||||
|
|
||||||
const { promise: result, resolve, reject } = explodePromise<Response>();
|
|
||||||
this.onResponse.set(seq, { resolve, reject });
|
|
||||||
|
|
||||||
const wrappedRequest: WrappedWorkerRequest = {
|
|
||||||
seq,
|
|
||||||
request,
|
|
||||||
};
|
|
||||||
this.worker.postMessage(wrappedRequest);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private onError(errorKind: SqliteErrorKind, error: Error): void {
|
|
||||||
if (errorKind === SqliteErrorKind.Unknown) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const resolvers = new Array<(error: Error) => void>();
|
|
||||||
this.errorResolvers = this.errorResolvers.filter(entry => {
|
|
||||||
if (entry.kind === errorKind) {
|
|
||||||
resolvers.push(entry.resolve);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const resolve of resolvers) {
|
|
||||||
resolve(error);
|
|
||||||
}
|
}
|
||||||
|
return min;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ import type {
|
||||||
WrappedWorkerResponse,
|
WrappedWorkerResponse,
|
||||||
WrappedWorkerLogEntry,
|
WrappedWorkerLogEntry,
|
||||||
} from './main';
|
} from './main';
|
||||||
import db from './Server';
|
import type { WritableDB } from './Interface';
|
||||||
|
import { initialize, DataReader, DataWriter } from './Server';
|
||||||
import { SqliteErrorKind, parseSqliteError } from './errors';
|
import { SqliteErrorKind, parseSqliteError } from './errors';
|
||||||
|
|
||||||
if (!parentPort) {
|
if (!parentPort) {
|
||||||
|
@ -27,8 +28,8 @@ function respond(seq: number, error: Error | undefined, response?: any) {
|
||||||
errorKind = parseSqliteError(error);
|
errorKind = parseSqliteError(error);
|
||||||
errorString = Errors.toLogFormat(error);
|
errorString = Errors.toLogFormat(error);
|
||||||
|
|
||||||
if (errorKind === SqliteErrorKind.Corrupted) {
|
if (errorKind === SqliteErrorKind.Corrupted && db != null) {
|
||||||
db.runCorruptionChecks();
|
DataWriter.runCorruptionChecks(db);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,11 +76,18 @@ const logger: LoggerType = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
port.on('message', async ({ seq, request }: WrappedWorkerRequest) => {
|
let db: WritableDB | undefined;
|
||||||
|
let isPrimary = false;
|
||||||
|
let isRemoved = false;
|
||||||
|
|
||||||
|
port.on('message', ({ seq, request }: WrappedWorkerRequest) => {
|
||||||
try {
|
try {
|
||||||
if (request.type === 'init') {
|
if (request.type === 'init') {
|
||||||
await db.initialize({
|
isPrimary = request.isPrimary;
|
||||||
|
isRemoved = false;
|
||||||
|
db = initialize({
|
||||||
...request.options,
|
...request.options,
|
||||||
|
isPrimary,
|
||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -87,8 +95,24 @@ port.on('message', async ({ seq, request }: WrappedWorkerRequest) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 'close' is sent on shutdown, but we already removed the database.
|
||||||
|
if (isRemoved && request.type === 'close') {
|
||||||
|
respond(seq, undefined, undefined);
|
||||||
|
process.exit(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!db) {
|
||||||
|
throw new Error('Not initialized');
|
||||||
|
}
|
||||||
|
|
||||||
if (request.type === 'close') {
|
if (request.type === 'close') {
|
||||||
await db.close();
|
if (isPrimary) {
|
||||||
|
DataWriter.close(db);
|
||||||
|
} else {
|
||||||
|
DataReader.close(db);
|
||||||
|
}
|
||||||
|
db = undefined;
|
||||||
|
|
||||||
respond(seq, undefined, undefined);
|
respond(seq, undefined, undefined);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
@ -96,21 +120,30 @@ port.on('message', async ({ seq, request }: WrappedWorkerRequest) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.type === 'removeDB') {
|
if (request.type === 'removeDB') {
|
||||||
await db.removeDB();
|
if (isPrimary) {
|
||||||
|
DataWriter.removeDB(db);
|
||||||
|
} else {
|
||||||
|
DataReader.close(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
isRemoved = true;
|
||||||
|
db = undefined;
|
||||||
|
|
||||||
respond(seq, undefined, undefined);
|
respond(seq, undefined, undefined);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.type === 'sqlCall') {
|
if (request.type === 'sqlCall:read' || request.type === 'sqlCall:write') {
|
||||||
|
const DataInterface =
|
||||||
|
request.type === 'sqlCall:read' ? DataReader : DataWriter;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const method = (db as any)[request.method];
|
const method = (DataInterface as any)[request.method];
|
||||||
if (typeof method !== 'function') {
|
if (typeof method !== 'function') {
|
||||||
throw new Error(`Invalid sql method: ${method}`);
|
throw new Error(`Invalid sql method: ${method}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const start = performance.now();
|
const start = performance.now();
|
||||||
const result = await method.apply(db, request.args);
|
const result = method(db, ...request.args);
|
||||||
const end = performance.now();
|
const end = performance.now();
|
||||||
|
|
||||||
respond(seq, undefined, { result, duration: end - start });
|
respond(seq, undefined, { result, duration: end - start });
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
// Copyright 2024 Signal Messenger, LLC
|
// Copyright 2024 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
|
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
import { sql } from '../util';
|
import { sql } from '../util';
|
||||||
|
import type { WritableDB } from '../Interface';
|
||||||
import { getOurUuid } from './41-uuid-keys';
|
import { getOurUuid } from './41-uuid-keys';
|
||||||
|
|
||||||
export const version = 1020;
|
export const version = 1020;
|
||||||
|
|
||||||
export function updateToSchemaVersion1020(
|
export function updateToSchemaVersion1020(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
): void {
|
): void {
|
||||||
if (currentVersion >= 1020) {
|
if (currentVersion >= 1020) {
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
|
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
import { isValidUuid } from '../../util/isValidUuid';
|
import { isValidUuid } from '../../util/isValidUuid';
|
||||||
import { assertSync } from '../../util/assert';
|
|
||||||
import Helpers from '../../textsecure/Helpers';
|
import Helpers from '../../textsecure/Helpers';
|
||||||
import { createOrUpdate, getById, removeById } from '../util';
|
import { createOrUpdate, getById, removeById } from '../util';
|
||||||
import type { EmptyQuery, Query } from '../util';
|
import type { EmptyQuery, Query } from '../util';
|
||||||
import type { ItemKeyType } from '../Interface';
|
import type { ItemKeyType, ReadableDB, WritableDB } from '../Interface';
|
||||||
|
|
||||||
export function getOurUuid(db: Database): string | undefined {
|
export function getOurUuid(db: ReadableDB): string | undefined {
|
||||||
const UUID_ID: ItemKeyType = 'uuid_id';
|
const UUID_ID: ItemKeyType = 'uuid_id';
|
||||||
|
|
||||||
const row: { json: string } | undefined = db
|
const row: { json: string } | undefined = db
|
||||||
|
@ -30,7 +27,7 @@ export function getOurUuid(db: Database): string | undefined {
|
||||||
|
|
||||||
export default function updateToSchemaVersion41(
|
export default function updateToSchemaVersion41(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
): void {
|
): void {
|
||||||
if (currentVersion >= 41) {
|
if (currentVersion >= 41) {
|
||||||
|
@ -92,8 +89,8 @@ export default function updateToSchemaVersion41(
|
||||||
db.prepare('DELETE FROM preKeys').run().changes,
|
db.prepare('DELETE FROM preKeys').run().changes,
|
||||||
].reduce((a: number, b: number): number => a + b);
|
].reduce((a: number, b: number): number => a + b);
|
||||||
|
|
||||||
assertSync(removeById<string>(db, 'items', 'identityKey'));
|
removeById<string>(db, 'items', 'identityKey');
|
||||||
assertSync(removeById<string>(db, 'items', 'registrationId'));
|
removeById<string>(db, 'items', 'registrationId');
|
||||||
|
|
||||||
return keyCount;
|
return keyCount;
|
||||||
};
|
};
|
||||||
|
@ -104,36 +101,34 @@ export default function updateToSchemaVersion41(
|
||||||
publicKey: string;
|
publicKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const identityKey = assertSync(
|
const identityKey = getById<string, { value: IdentityKeyType }>(
|
||||||
getById<string, { value: IdentityKeyType }>(db, 'items', 'identityKey')
|
db,
|
||||||
|
'items',
|
||||||
|
'identityKey'
|
||||||
);
|
);
|
||||||
|
|
||||||
type RegistrationId = number;
|
type RegistrationId = number;
|
||||||
|
|
||||||
const registrationId = assertSync(
|
const registrationId = getById<string, { value: RegistrationId }>(
|
||||||
getById<string, { value: RegistrationId }>(db, 'items', 'registrationId')
|
db,
|
||||||
|
'items',
|
||||||
|
'registrationId'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (identityKey) {
|
if (identityKey) {
|
||||||
assertSync(
|
|
||||||
createOrUpdate<ItemKeyType>(db, 'items', {
|
createOrUpdate<ItemKeyType>(db, 'items', {
|
||||||
id: 'identityKeyMap',
|
id: 'identityKeyMap',
|
||||||
value: {
|
value: {
|
||||||
[ourUuid]: identityKey.value,
|
[ourUuid]: identityKey.value,
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registrationId) {
|
if (registrationId) {
|
||||||
assertSync(
|
|
||||||
createOrUpdate<ItemKeyType>(db, 'items', {
|
createOrUpdate<ItemKeyType>(db, 'items', {
|
||||||
id: 'registrationIdMap',
|
id: 'registrationIdMap',
|
||||||
value: {
|
value: {
|
||||||
[ourUuid]: registrationId.value,
|
[ourUuid]: registrationId.value,
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db.exec(
|
db.exec(
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
|
|
||||||
import { batchMultiVarQuery } from '../util';
|
import { batchMultiVarQuery } from '../util';
|
||||||
import type { ArrayQuery } from '../util';
|
import type { ArrayQuery } from '../util';
|
||||||
|
import type { WritableDB } from '../Interface';
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
|
|
||||||
export default function updateToSchemaVersion42(
|
export default function updateToSchemaVersion42(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
): void {
|
): void {
|
||||||
if (currentVersion >= 42) {
|
if (currentVersion >= 42) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
|
@ -16,6 +15,7 @@ import {
|
||||||
objectToJSON,
|
objectToJSON,
|
||||||
} from '../util';
|
} from '../util';
|
||||||
import type { EmptyQuery, Query } from '../util';
|
import type { EmptyQuery, Query } from '../util';
|
||||||
|
import type { WritableDB } from '../Interface';
|
||||||
|
|
||||||
type MessageType = Readonly<{
|
type MessageType = Readonly<{
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -35,7 +35,7 @@ type ConversationType = Readonly<{
|
||||||
|
|
||||||
export default function updateToSchemaVersion43(
|
export default function updateToSchemaVersion43(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
): void {
|
): void {
|
||||||
if (currentVersion >= 43) {
|
if (currentVersion >= 43) {
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
|
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
import { getOurUuid } from './41-uuid-keys';
|
import { getOurUuid } from './41-uuid-keys';
|
||||||
|
import type { WritableDB } from '../Interface';
|
||||||
import type { Query } from '../util';
|
import type { Query } from '../util';
|
||||||
|
|
||||||
export default function updateToSchemaVersion47(
|
export default function updateToSchemaVersion47(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
): void {
|
): void {
|
||||||
if (currentVersion >= 47) {
|
if (currentVersion >= 47) {
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
// Copyright 2022 Signal Messenger, LLC
|
// Copyright 2022 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
|
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
import { isRecord } from '../../util/isRecord';
|
import { isRecord } from '../../util/isRecord';
|
||||||
import {
|
import type { WritableDB } from '../Interface';
|
||||||
getJobsInQueueSync,
|
import { getJobsInQueue, getMessageById, insertJob } from '../Server';
|
||||||
getMessageByIdSync,
|
|
||||||
insertJobSync,
|
|
||||||
} from '../Server';
|
|
||||||
|
|
||||||
export default function updateToSchemaVersion51(
|
export default function updateToSchemaVersion51(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
): void {
|
): void {
|
||||||
if (currentVersion >= 51) {
|
if (currentVersion >= 51) {
|
||||||
|
@ -26,7 +21,7 @@ export default function updateToSchemaVersion51(
|
||||||
);
|
);
|
||||||
|
|
||||||
// First, make sure that reactions job data has a type and conversationId
|
// First, make sure that reactions job data has a type and conversationId
|
||||||
const reactionsJobs = getJobsInQueueSync(db, 'reactions');
|
const reactionsJobs = getJobsInQueue(db, 'reactions');
|
||||||
deleteJobsInQueue.run({ queueType: 'reactions' });
|
deleteJobsInQueue.run({ queueType: 'reactions' });
|
||||||
|
|
||||||
reactionsJobs.forEach(job => {
|
reactionsJobs.forEach(job => {
|
||||||
|
@ -47,7 +42,7 @@ export default function updateToSchemaVersion51(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = getMessageByIdSync(db, messageId);
|
const message = getMessageById(db, messageId);
|
||||||
if (!message) {
|
if (!message) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`updateToSchemaVersion51: Unable to find message for reaction job ${id}`
|
`updateToSchemaVersion51: Unable to find message for reaction job ${id}`
|
||||||
|
@ -73,11 +68,11 @@ export default function updateToSchemaVersion51(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
insertJobSync(db, newJob);
|
insertJob(db, newJob);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Then make sure all normal send job data has a type
|
// Then make sure all normal send job data has a type
|
||||||
const normalSendJobs = getJobsInQueueSync(db, 'normal send');
|
const normalSendJobs = getJobsInQueue(db, 'normal send');
|
||||||
deleteJobsInQueue.run({ queueType: 'normal send' });
|
deleteJobsInQueue.run({ queueType: 'normal send' });
|
||||||
|
|
||||||
normalSendJobs.forEach(job => {
|
normalSendJobs.forEach(job => {
|
||||||
|
@ -99,7 +94,7 @@ export default function updateToSchemaVersion51(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
insertJobSync(db, newJob);
|
insertJob(db, newJob);
|
||||||
});
|
});
|
||||||
|
|
||||||
db.pragma('user_version = 51');
|
db.pragma('user_version = 51');
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
// Copyright 2022 Signal Messenger, LLC
|
// Copyright 2022 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
import { getJobsInQueueSync, insertJobSync } from '../Server';
|
import { getJobsInQueue, insertJob } from '../Server';
|
||||||
|
import type { WritableDB } from '../Interface';
|
||||||
import { isRecord } from '../../util/isRecord';
|
import { isRecord } from '../../util/isRecord';
|
||||||
import { isIterable } from '../../util/iterables';
|
import { isIterable } from '../../util/iterables';
|
||||||
|
|
||||||
export default function updateToSchemaVersion55(
|
export default function updateToSchemaVersion55(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
): void {
|
): void {
|
||||||
if (currentVersion >= 55) {
|
if (currentVersion >= 55) {
|
||||||
|
@ -22,7 +22,7 @@ export default function updateToSchemaVersion55(
|
||||||
);
|
);
|
||||||
|
|
||||||
// First, make sure that report spam job data has e164 and serverGuids
|
// First, make sure that report spam job data has e164 and serverGuids
|
||||||
const reportSpamJobs = getJobsInQueueSync(db, 'report spam');
|
const reportSpamJobs = getJobsInQueue(db, 'report spam');
|
||||||
deleteJobsInQueue.run({ queueType: 'report spam' });
|
deleteJobsInQueue.run({ queueType: 'report spam' });
|
||||||
|
|
||||||
reportSpamJobs.forEach(job => {
|
reportSpamJobs.forEach(job => {
|
||||||
|
@ -59,7 +59,7 @@ export default function updateToSchemaVersion55(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
insertJobSync(db, newJob);
|
insertJob(db, newJob);
|
||||||
});
|
});
|
||||||
|
|
||||||
db.pragma('user_version = 55');
|
db.pragma('user_version = 55');
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
// Copyright 2023 Signal Messenger, LLC
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
|
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
import { isRecord } from '../../util/isRecord';
|
import { isRecord } from '../../util/isRecord';
|
||||||
import {
|
import type { WritableDB } from '../Interface';
|
||||||
getJobsInQueueSync,
|
import { getJobsInQueue, getMessageById, insertJob } from '../Server';
|
||||||
getMessageByIdSync,
|
|
||||||
insertJobSync,
|
|
||||||
} from '../Server';
|
|
||||||
|
|
||||||
export default function updateToSchemaVersion78(
|
export default function updateToSchemaVersion78(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
): void {
|
): void {
|
||||||
if (currentVersion >= 78) {
|
if (currentVersion >= 78) {
|
||||||
|
@ -47,7 +42,7 @@ export default function updateToSchemaVersion78(
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const queue of queues) {
|
for (const queue of queues) {
|
||||||
const prevJobs = getJobsInQueueSync(db, queue.queueType);
|
const prevJobs = getJobsInQueue(db, queue.queueType);
|
||||||
deleteJobsInQueue.run({ queueType: queue.queueType });
|
deleteJobsInQueue.run({ queueType: queue.queueType });
|
||||||
|
|
||||||
prevJobs.forEach(job => {
|
prevJobs.forEach(job => {
|
||||||
|
@ -67,7 +62,7 @@ export default function updateToSchemaVersion78(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = getMessageByIdSync(db, messageId);
|
const message = getMessageById(db, messageId);
|
||||||
if (!message) {
|
if (!message) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`updateToSchemaVersion78: Unable to find message for ${queue.queueType} job ${id}`
|
`updateToSchemaVersion78: Unable to find message for ${queue.queueType} job ${id}`
|
||||||
|
@ -121,7 +116,7 @@ export default function updateToSchemaVersion78(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
insertJobSync(db, newJob);
|
insertJob(db, newJob);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2023 Signal Messenger, LLC
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
import { callIdFromEra } from '@signalapp/ringrtc';
|
import { callIdFromEra } from '@signalapp/ringrtc';
|
||||||
import Long from 'long';
|
import Long from 'long';
|
||||||
import { v4 as generateUuid } from 'uuid';
|
import { v4 as generateUuid } from 'uuid';
|
||||||
|
@ -20,7 +19,7 @@ import {
|
||||||
callHistoryDetailsSchema,
|
callHistoryDetailsSchema,
|
||||||
} from '../../types/CallDisposition';
|
} from '../../types/CallDisposition';
|
||||||
import { CallMode } from '../../types/Calling';
|
import { CallMode } from '../../types/Calling';
|
||||||
import type { MessageType, ConversationType } from '../Interface';
|
import type { WritableDB, MessageType, ConversationType } from '../Interface';
|
||||||
import { strictAssert } from '../../util/assert';
|
import { strictAssert } from '../../util/assert';
|
||||||
import { missingCaseError } from '../../util/missingCaseError';
|
import { missingCaseError } from '../../util/missingCaseError';
|
||||||
import { isAciString } from '../../util/isAciString';
|
import { isAciString } from '../../util/isAciString';
|
||||||
|
@ -188,7 +187,7 @@ function convertLegacyCallDetails(
|
||||||
|
|
||||||
export default function updateToSchemaVersion89(
|
export default function updateToSchemaVersion89(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
): void {
|
): void {
|
||||||
if (currentVersion >= 89) {
|
if (currentVersion >= 89) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
jsonToObject,
|
jsonToObject,
|
||||||
} from '../util';
|
} from '../util';
|
||||||
import type { Query, EmptyQuery } from '../util';
|
import type { Query, EmptyQuery } from '../util';
|
||||||
|
import type { WritableDB } from '../Interface';
|
||||||
|
|
||||||
import updateToSchemaVersion41 from './41-uuid-keys';
|
import updateToSchemaVersion41 from './41-uuid-keys';
|
||||||
import updateToSchemaVersion42 from './42-stale-reactions';
|
import updateToSchemaVersion42 from './42-stale-reactions';
|
||||||
|
@ -2075,7 +2076,7 @@ export function enableFTS5SecureDelete(db: Database, logger: LoggerType): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateSchema(db: Database, logger: LoggerType): void {
|
export function updateSchema(db: WritableDB, logger: LoggerType): void {
|
||||||
const sqliteVersion = getSQLiteVersion(db);
|
const sqliteVersion = getSQLiteVersion(db);
|
||||||
const sqlcipherVersion = getSQLCipherVersion(db);
|
const sqlcipherVersion = getSQLCipherVersion(db);
|
||||||
const startingVersion = getUserVersion(db);
|
const startingVersion = getUserVersion(db);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2024 Signal Messenger, LLC
|
// Copyright 2024 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
import { CallLinkRootKey } from '@signalapp/ringrtc';
|
import { CallLinkRootKey } from '@signalapp/ringrtc';
|
||||||
import type { CallLinkStateType, CallLinkType } from '../../types/CallLink';
|
import type { CallLinkStateType, CallLinkType } from '../../types/CallLink';
|
||||||
import {
|
import {
|
||||||
|
@ -13,12 +12,12 @@ import {
|
||||||
callLinkFromRecord,
|
callLinkFromRecord,
|
||||||
toAdminKeyBytes,
|
toAdminKeyBytes,
|
||||||
} from '../../util/callLinks';
|
} from '../../util/callLinks';
|
||||||
import { getReadonlyInstance, getWritableInstance, prepare } from '../Server';
|
import type { ReadableDB, WritableDB } from '../Interface';
|
||||||
|
import { prepare } from '../Server';
|
||||||
import { sql } from '../util';
|
import { sql } from '../util';
|
||||||
import { strictAssert } from '../../util/assert';
|
import { strictAssert } from '../../util/assert';
|
||||||
|
|
||||||
export async function callLinkExists(roomId: string): Promise<boolean> {
|
export function callLinkExists(db: ReadableDB, roomId: string): boolean {
|
||||||
const db = getReadonlyInstance();
|
|
||||||
const [query, params] = sql`
|
const [query, params] = sql`
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM callLinks
|
FROM callLinks
|
||||||
|
@ -27,10 +26,10 @@ export async function callLinkExists(roomId: string): Promise<boolean> {
|
||||||
return db.prepare(query).pluck(true).get(params) === 1;
|
return db.prepare(query).pluck(true).get(params) === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCallLinkByRoomId(
|
export function getCallLinkByRoomId(
|
||||||
|
db: ReadableDB,
|
||||||
roomId: string
|
roomId: string
|
||||||
): Promise<CallLinkType | undefined> {
|
): CallLinkType | undefined {
|
||||||
const db = getReadonlyInstance();
|
|
||||||
const row = prepare(db, 'SELECT * FROM callLinks WHERE roomId = $roomId').get(
|
const row = prepare(db, 'SELECT * FROM callLinks WHERE roomId = $roomId').get(
|
||||||
{
|
{
|
||||||
roomId,
|
roomId,
|
||||||
|
@ -44,8 +43,7 @@ export async function getCallLinkByRoomId(
|
||||||
return callLinkFromRecord(callLinkRecordSchema.parse(row));
|
return callLinkFromRecord(callLinkRecordSchema.parse(row));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAllCallLinks(): Promise<ReadonlyArray<CallLinkType>> {
|
export function getAllCallLinks(db: ReadableDB): ReadonlyArray<CallLinkType> {
|
||||||
const db = getReadonlyInstance();
|
|
||||||
const [query] = sql`
|
const [query] = sql`
|
||||||
SELECT * FROM callLinks;
|
SELECT * FROM callLinks;
|
||||||
`;
|
`;
|
||||||
|
@ -55,7 +53,7 @@ export async function getAllCallLinks(): Promise<ReadonlyArray<CallLinkType>> {
|
||||||
.map(item => callLinkFromRecord(callLinkRecordSchema.parse(item)));
|
.map(item => callLinkFromRecord(callLinkRecordSchema.parse(item)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function _insertCallLink(db: Database, callLink: CallLinkType): void {
|
function _insertCallLink(db: WritableDB, callLink: CallLinkType): void {
|
||||||
const { roomId, rootKey } = callLink;
|
const { roomId, rootKey } = callLink;
|
||||||
assertRoomIdMatchesRootKey(roomId, rootKey);
|
assertRoomIdMatchesRootKey(roomId, rootKey);
|
||||||
|
|
||||||
|
@ -84,17 +82,16 @@ function _insertCallLink(db: Database, callLink: CallLinkType): void {
|
||||||
).run(data);
|
).run(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function insertCallLink(callLink: CallLinkType): Promise<void> {
|
export function insertCallLink(db: WritableDB, callLink: CallLinkType): void {
|
||||||
const db = await getWritableInstance();
|
|
||||||
_insertCallLink(db, callLink);
|
_insertCallLink(db, callLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateCallLinkState(
|
export function updateCallLinkState(
|
||||||
|
db: WritableDB,
|
||||||
roomId: string,
|
roomId: string,
|
||||||
callLinkState: CallLinkStateType
|
callLinkState: CallLinkStateType
|
||||||
): Promise<CallLinkType> {
|
): CallLinkType {
|
||||||
const { name, restrictions, expiration, revoked } = callLinkState;
|
const { name, restrictions, expiration, revoked } = callLinkState;
|
||||||
const db = await getWritableInstance();
|
|
||||||
const restrictionsValue = callLinkRestrictionsSchema.parse(restrictions);
|
const restrictionsValue = callLinkRestrictionsSchema.parse(restrictions);
|
||||||
const [query, params] = sql`
|
const [query, params] = sql`
|
||||||
UPDATE callLinks
|
UPDATE callLinks
|
||||||
|
@ -111,11 +108,11 @@ export async function updateCallLinkState(
|
||||||
return callLinkFromRecord(callLinkRecordSchema.parse(row));
|
return callLinkFromRecord(callLinkRecordSchema.parse(row));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateCallLinkAdminKeyByRoomId(
|
export function updateCallLinkAdminKeyByRoomId(
|
||||||
|
db: WritableDB,
|
||||||
roomId: string,
|
roomId: string,
|
||||||
adminKey: string
|
adminKey: string
|
||||||
): Promise<void> {
|
): void {
|
||||||
const db = await getWritableInstance();
|
|
||||||
const adminKeyBytes = toAdminKeyBytes(adminKey);
|
const adminKeyBytes = toAdminKeyBytes(adminKey);
|
||||||
prepare(
|
prepare(
|
||||||
db,
|
db,
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
// Copyright 2024 Signal Messenger, LLC
|
// Copyright 2024 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
import type {
|
import type {
|
||||||
GroupSendCombinedEndorsementRecord,
|
GroupSendCombinedEndorsementRecord,
|
||||||
GroupSendEndorsementsData,
|
GroupSendEndorsementsData,
|
||||||
GroupSendMemberEndorsementRecord,
|
GroupSendMemberEndorsementRecord,
|
||||||
} from '../../types/GroupSendEndorsements';
|
} from '../../types/GroupSendEndorsements';
|
||||||
import { groupSendEndorsementExpirationSchema } from '../../types/GroupSendEndorsements';
|
import { groupSendEndorsementExpirationSchema } from '../../types/GroupSendEndorsements';
|
||||||
import { getReadonlyInstance, getWritableInstance, prepare } from '../Server';
|
import { prepare } from '../Server';
|
||||||
|
import type { ReadableDB, WritableDB } from '../Interface';
|
||||||
import { sql } from '../util';
|
import { sql } from '../util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We don't need to store more than one endorsement per group or per member.
|
* We don't need to store more than one endorsement per group or per member.
|
||||||
*/
|
*/
|
||||||
export async function replaceAllEndorsementsForGroup(
|
export function replaceAllEndorsementsForGroup(
|
||||||
|
db: WritableDB,
|
||||||
data: GroupSendEndorsementsData
|
data: GroupSendEndorsementsData
|
||||||
): Promise<void> {
|
): void {
|
||||||
const db = await getWritableInstance();
|
|
||||||
db.transaction(() => {
|
db.transaction(() => {
|
||||||
const { combinedEndorsement, memberEndorsements } = data;
|
const { combinedEndorsement, memberEndorsements } = data;
|
||||||
_replaceCombinedEndorsement(db, combinedEndorsement);
|
_replaceCombinedEndorsement(db, combinedEndorsement);
|
||||||
|
@ -26,7 +26,7 @@ export async function replaceAllEndorsementsForGroup(
|
||||||
}
|
}
|
||||||
|
|
||||||
function _replaceCombinedEndorsement(
|
function _replaceCombinedEndorsement(
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
combinedEndorsement: GroupSendCombinedEndorsementRecord
|
combinedEndorsement: GroupSendCombinedEndorsementRecord
|
||||||
): void {
|
): void {
|
||||||
const { groupId, expiration, endorsement } = combinedEndorsement;
|
const { groupId, expiration, endorsement } = combinedEndorsement;
|
||||||
|
@ -39,7 +39,7 @@ function _replaceCombinedEndorsement(
|
||||||
}
|
}
|
||||||
|
|
||||||
function _replaceMemberEndorsements(
|
function _replaceMemberEndorsements(
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
memberEndorsements: ReadonlyArray<GroupSendMemberEndorsementRecord>
|
memberEndorsements: ReadonlyArray<GroupSendMemberEndorsementRecord>
|
||||||
) {
|
) {
|
||||||
for (const memberEndorsement of memberEndorsements) {
|
for (const memberEndorsement of memberEndorsements) {
|
||||||
|
@ -53,10 +53,10 @@ function _replaceMemberEndorsements(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteAllEndorsementsForGroup(
|
export function deleteAllEndorsementsForGroup(
|
||||||
|
db: WritableDB,
|
||||||
groupId: string
|
groupId: string
|
||||||
): Promise<void> {
|
): void {
|
||||||
const db = await getWritableInstance();
|
|
||||||
db.transaction(() => {
|
db.transaction(() => {
|
||||||
const [deleteCombined, deleteCombinedParams] = sql`
|
const [deleteCombined, deleteCombinedParams] = sql`
|
||||||
DELETE FROM groupSendCombinedEndorsement
|
DELETE FROM groupSendCombinedEndorsement
|
||||||
|
@ -71,10 +71,10 @@ export async function deleteAllEndorsementsForGroup(
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getGroupSendCombinedEndorsementExpiration(
|
export function getGroupSendCombinedEndorsementExpiration(
|
||||||
|
db: ReadableDB,
|
||||||
groupId: string
|
groupId: string
|
||||||
): Promise<number | null> {
|
): number | null {
|
||||||
const db = getReadonlyInstance();
|
|
||||||
const [selectGroup, selectGroupParams] = sql`
|
const [selectGroup, selectGroupParams] = sql`
|
||||||
SELECT expiration FROM groupSendCombinedEndorsement
|
SELECT expiration FROM groupSendCombinedEndorsement
|
||||||
WHERE groupId = ${groupId};
|
WHERE groupId = ${groupId};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
|
||||||
import { isNumber, last } from 'lodash';
|
import { isNumber, last } from 'lodash';
|
||||||
|
import type { ReadableDB, WritableDB } from './Interface';
|
||||||
|
|
||||||
export type EmptyQuery = [];
|
export type EmptyQuery = [];
|
||||||
export type ArrayQuery = Array<ReadonlyArray<null | number | bigint | string>>;
|
export type ArrayQuery = Array<ReadonlyArray<null | number | bigint | string>>;
|
||||||
|
@ -185,7 +185,7 @@ type QueryPlan = Readonly<{
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function explainQueryPlan(
|
export function explainQueryPlan(
|
||||||
db: Database,
|
db: ReadableDB,
|
||||||
template: QueryTemplate
|
template: QueryTemplate
|
||||||
): QueryPlan {
|
): QueryPlan {
|
||||||
const [query, params] = template;
|
const [query, params] = template;
|
||||||
|
@ -197,7 +197,7 @@ export function explainQueryPlan(
|
||||||
// Database helpers
|
// Database helpers
|
||||||
//
|
//
|
||||||
|
|
||||||
export function getSQLiteVersion(db: Database): string {
|
export function getSQLiteVersion(db: ReadableDB): string {
|
||||||
const { sqlite_version: version } = db
|
const { sqlite_version: version } = db
|
||||||
.prepare<EmptyQuery>('select sqlite_version() AS sqlite_version')
|
.prepare<EmptyQuery>('select sqlite_version() AS sqlite_version')
|
||||||
.get();
|
.get();
|
||||||
|
@ -205,22 +205,22 @@ export function getSQLiteVersion(db: Database): string {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSchemaVersion(db: Database): number {
|
export function getSchemaVersion(db: ReadableDB): number {
|
||||||
return db.pragma('schema_version', { simple: true });
|
return db.pragma('schema_version', { simple: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setUserVersion(db: Database, version: number): void {
|
export function setUserVersion(db: WritableDB, version: number): void {
|
||||||
if (!isNumber(version)) {
|
if (!isNumber(version)) {
|
||||||
throw new Error(`setUserVersion: version ${version} is not a number`);
|
throw new Error(`setUserVersion: version ${version} is not a number`);
|
||||||
}
|
}
|
||||||
db.pragma(`user_version = ${version}`);
|
db.pragma(`user_version = ${version}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUserVersion(db: Database): number {
|
export function getUserVersion(db: ReadableDB): number {
|
||||||
return db.pragma('user_version', { simple: true });
|
return db.pragma('user_version', { simple: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSQLCipherVersion(db: Database): string | undefined {
|
export function getSQLCipherVersion(db: ReadableDB): string | undefined {
|
||||||
return db.pragma('cipher_version', { simple: true });
|
return db.pragma('cipher_version', { simple: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,18 +229,18 @@ export function getSQLCipherVersion(db: Database): string | undefined {
|
||||||
//
|
//
|
||||||
|
|
||||||
export function batchMultiVarQuery<ValueT>(
|
export function batchMultiVarQuery<ValueT>(
|
||||||
db: Database,
|
db: ReadableDB,
|
||||||
values: ReadonlyArray<ValueT>,
|
values: ReadonlyArray<ValueT>,
|
||||||
query: (batch: ReadonlyArray<ValueT>) => void
|
query: (batch: ReadonlyArray<ValueT>) => void
|
||||||
): [];
|
): [];
|
||||||
export function batchMultiVarQuery<ValueT, ResultT>(
|
export function batchMultiVarQuery<ValueT, ResultT>(
|
||||||
db: Database,
|
db: ReadableDB,
|
||||||
values: ReadonlyArray<ValueT>,
|
values: ReadonlyArray<ValueT>,
|
||||||
query: (batch: ReadonlyArray<ValueT>) => Array<ResultT>
|
query: (batch: ReadonlyArray<ValueT>) => Array<ResultT>
|
||||||
): Array<ResultT>;
|
): Array<ResultT>;
|
||||||
|
|
||||||
export function batchMultiVarQuery<ValueT, ResultT>(
|
export function batchMultiVarQuery<ValueT, ResultT>(
|
||||||
db: Database,
|
db: ReadableDB,
|
||||||
values: ReadonlyArray<ValueT>,
|
values: ReadonlyArray<ValueT>,
|
||||||
query:
|
query:
|
||||||
| ((batch: ReadonlyArray<ValueT>) => void)
|
| ((batch: ReadonlyArray<ValueT>) => void)
|
||||||
|
@ -265,7 +265,7 @@ export function batchMultiVarQuery<ValueT, ResultT>(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createOrUpdate<Key extends string | number>(
|
export function createOrUpdate<Key extends string | number>(
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
table: TableType,
|
table: TableType,
|
||||||
data: Record<string, unknown> & { id: Key }
|
data: Record<string, unknown> & { id: Key }
|
||||||
): void {
|
): void {
|
||||||
|
@ -291,7 +291,7 @@ export function createOrUpdate<Key extends string | number>(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function bulkAdd(
|
export function bulkAdd(
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
table: TableType,
|
table: TableType,
|
||||||
array: Array<Record<string, unknown> & { id: string | number }>
|
array: Array<Record<string, unknown> & { id: string | number }>
|
||||||
): void {
|
): void {
|
||||||
|
@ -303,7 +303,7 @@ export function bulkAdd(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getById<Key extends string | number, Result = unknown>(
|
export function getById<Key extends string | number, Result = unknown>(
|
||||||
db: Database,
|
db: ReadableDB,
|
||||||
table: TableType,
|
table: TableType,
|
||||||
id: Key
|
id: Key
|
||||||
): Result | undefined {
|
): Result | undefined {
|
||||||
|
@ -327,7 +327,7 @@ export function getById<Key extends string | number, Result = unknown>(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeById<Key extends string | number>(
|
export function removeById<Key extends string | number>(
|
||||||
db: Database,
|
db: WritableDB,
|
||||||
tableName: TableType,
|
tableName: TableType,
|
||||||
id: Key | Array<Key>
|
id: Key | Array<Key>
|
||||||
): number {
|
): number {
|
||||||
|
@ -359,11 +359,11 @@ export function removeById<Key extends string | number>(
|
||||||
return totalChanges;
|
return totalChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeAllFromTable(db: Database, table: TableType): number {
|
export function removeAllFromTable(db: WritableDB, table: TableType): number {
|
||||||
return db.prepare<EmptyQuery>(`DELETE FROM ${table};`).run().changes;
|
return db.prepare<EmptyQuery>(`DELETE FROM ${table};`).run().changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAllFromTable<T>(db: Database, table: TableType): Array<T> {
|
export function getAllFromTable<T>(db: ReadableDB, table: TableType): Array<T> {
|
||||||
const rows: JSONRows = db
|
const rows: JSONRows = db
|
||||||
.prepare<EmptyQuery>(`SELECT json FROM ${table};`)
|
.prepare<EmptyQuery>(`SELECT json FROM ${table};`)
|
||||||
.all();
|
.all();
|
||||||
|
@ -371,7 +371,7 @@ export function getAllFromTable<T>(db: Database, table: TableType): Array<T> {
|
||||||
return rows.map(row => jsonToObject(row.json));
|
return rows.map(row => jsonToObject(row.json));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCountFromTable(db: Database, table: TableType): number {
|
export function getCountFromTable(db: ReadableDB, table: TableType): number {
|
||||||
const result: null | number = db
|
const result: null | number = db
|
||||||
.prepare<EmptyQuery>(`SELECT count(*) from ${table};`)
|
.prepare<EmptyQuery>(`SELECT count(*) from ${table};`)
|
||||||
.pluck(true)
|
.pluck(true)
|
||||||
|
@ -384,7 +384,7 @@ export function getCountFromTable(db: Database, table: TableType): number {
|
||||||
|
|
||||||
export class TableIterator<ObjectType extends { id: string }> {
|
export class TableIterator<ObjectType extends { id: string }> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly db: Database,
|
private readonly db: ReadableDB,
|
||||||
private readonly table: TableType,
|
private readonly table: TableType,
|
||||||
private readonly pageSize = 500
|
private readonly pageSize = 500
|
||||||
) {}
|
) {}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
import { isEqual, mapValues } from 'lodash';
|
import { isEqual, mapValues } from 'lodash';
|
||||||
import type { ReadonlyDeep } from 'type-fest';
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
|
import { DataWriter } from '../../sql/Client';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import type { BadgeType, BadgeImageType } from '../../badges/types';
|
import type { BadgeType, BadgeImageType } from '../../badges/types';
|
||||||
import { getOwn } from '../../util/getOwn';
|
import { getOwn } from '../../util/getOwn';
|
||||||
|
@ -70,7 +71,7 @@ function updateOrCreate(
|
||||||
// check (e.g., due to a crash), we won't download its image files. In the unlikely
|
// check (e.g., due to a crash), we won't download its image files. In the unlikely
|
||||||
// event that this happens, we'll repair it the next time we check for undownloaded
|
// event that this happens, we'll repair it the next time we check for undownloaded
|
||||||
// image files.
|
// image files.
|
||||||
await window.Signal.Data.updateOrCreateBadges(badges);
|
await DataWriter.updateOrCreateBadges(badges);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: UPDATE_OR_CREATE,
|
type: UPDATE_OR_CREATE,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
import { useBoundActions } from '../../hooks/useBoundActions';
|
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
import type { ToastActionType } from './toast';
|
import type { ToastActionType } from './toast';
|
||||||
import { showToast } from './toast';
|
import { showToast } from './toast';
|
||||||
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import { ToastType } from '../../types/Toast';
|
import { ToastType } from '../../types/Toast';
|
||||||
import type { CallHistoryDetails } from '../../types/CallDisposition';
|
import type { CallHistoryDetails } from '../../types/CallDisposition';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
|
@ -77,7 +78,7 @@ function updateCallHistoryUnreadCount(): ThunkAction<
|
||||||
> {
|
> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
try {
|
try {
|
||||||
const unreadCount = await window.Signal.Data.getCallHistoryUnreadCount();
|
const unreadCount = await DataReader.getCallHistoryUnreadCount();
|
||||||
dispatch({ type: CALL_HISTORY_UPDATE_UNREAD, payload: unreadCount });
|
dispatch({ type: CALL_HISTORY_UPDATE_UNREAD, payload: unreadCount });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(
|
log.error(
|
||||||
|
@ -94,7 +95,7 @@ function markCallHistoryRead(
|
||||||
): ThunkAction<void, RootStateType, unknown, CallHistoryUpdateUnread> {
|
): ThunkAction<void, RootStateType, unknown, CallHistoryUpdateUnread> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
try {
|
try {
|
||||||
await window.Signal.Data.markCallHistoryRead(callId);
|
await DataWriter.markCallHistoryRead(callId);
|
||||||
drop(window.ConversationController.get(conversationId)?.updateUnread());
|
drop(window.ConversationController.get(conversationId)?.updateUnread());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(
|
log.error(
|
||||||
|
|
|
@ -86,7 +86,7 @@ import type { ShowErrorModalActionType } from './globalModals';
|
||||||
import { SHOW_ERROR_MODAL } from './globalModals';
|
import { SHOW_ERROR_MODAL } from './globalModals';
|
||||||
import { ButtonVariant } from '../../components/Button';
|
import { ButtonVariant } from '../../components/Button';
|
||||||
import { getConversationIdForLogging } from '../../util/idForLogging';
|
import { getConversationIdForLogging } from '../../util/idForLogging';
|
||||||
import dataInterface from '../../sql/Client';
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import { isAciString } from '../../util/isAciString';
|
import { isAciString } from '../../util/isAciString';
|
||||||
import type { CallHistoryDetails } from '../../types/CallDisposition';
|
import type { CallHistoryDetails } from '../../types/CallDisposition';
|
||||||
import {
|
import {
|
||||||
|
@ -1415,7 +1415,7 @@ function handleCallLinkUpdate(
|
||||||
}
|
}
|
||||||
|
|
||||||
const { callLinkState: freshCallLinkState } = readResult;
|
const { callLinkState: freshCallLinkState } = readResult;
|
||||||
const existingCallLink = await dataInterface.getCallLinkByRoomId(roomId);
|
const existingCallLink = await DataReader.getCallLinkByRoomId(roomId);
|
||||||
const existingCallLinkState = pick(existingCallLink, [
|
const existingCallLinkState = pick(existingCallLink, [
|
||||||
'name',
|
'name',
|
||||||
'restrictions',
|
'restrictions',
|
||||||
|
@ -1434,16 +1434,16 @@ function handleCallLinkUpdate(
|
||||||
|
|
||||||
if (existingCallLink) {
|
if (existingCallLink) {
|
||||||
if (adminKey && adminKey !== existingCallLink.adminKey) {
|
if (adminKey && adminKey !== existingCallLink.adminKey) {
|
||||||
await dataInterface.updateCallLinkAdminKeyByRoomId(roomId, adminKey);
|
await DataWriter.updateCallLinkAdminKeyByRoomId(roomId, adminKey);
|
||||||
log.info(`${logId}: Updated existing call link with new adminKey`);
|
log.info(`${logId}: Updated existing call link with new adminKey`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freshCallLinkState) {
|
if (freshCallLinkState) {
|
||||||
await dataInterface.updateCallLinkState(roomId, freshCallLinkState);
|
await DataWriter.updateCallLinkState(roomId, freshCallLinkState);
|
||||||
log.info(`${logId}: Updated existing call link state`);
|
log.info(`${logId}: Updated existing call link state`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await dataInterface.insertCallLink(callLink);
|
await DataWriter.insertCallLink(callLink);
|
||||||
log.info(`${logId}: Saved new call link`);
|
log.info(`${logId}: Saved new call link`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1985,8 +1985,8 @@ function createCallLink(
|
||||||
status: AdhocCallStatus.Pending,
|
status: AdhocCallStatus.Pending,
|
||||||
};
|
};
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
dataInterface.insertCallLink(callLink),
|
DataWriter.insertCallLink(callLink),
|
||||||
dataInterface.saveCallHistory(callHistory),
|
DataWriter.saveCallHistory(callHistory),
|
||||||
]);
|
]);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: HANDLE_CALL_LINK_UPDATE,
|
type: HANDLE_CALL_LINK_UPDATE,
|
||||||
|
@ -2003,13 +2003,13 @@ function updateCallLinkName(
|
||||||
name: string
|
name: string
|
||||||
): ThunkAction<void, RootStateType, unknown, HandleCallLinkUpdateActionType> {
|
): ThunkAction<void, RootStateType, unknown, HandleCallLinkUpdateActionType> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const prevCallLink = await dataInterface.getCallLinkByRoomId(roomId);
|
const prevCallLink = await DataReader.getCallLinkByRoomId(roomId);
|
||||||
strictAssert(
|
strictAssert(
|
||||||
prevCallLink,
|
prevCallLink,
|
||||||
`updateCallLinkName(${roomId}): call link not found`
|
`updateCallLinkName(${roomId}): call link not found`
|
||||||
);
|
);
|
||||||
const callLinkState = await calling.updateCallLinkName(prevCallLink, name);
|
const callLinkState = await calling.updateCallLinkName(prevCallLink, name);
|
||||||
const callLink = await dataInterface.updateCallLinkState(
|
const callLink = await DataWriter.updateCallLinkState(
|
||||||
roomId,
|
roomId,
|
||||||
callLinkState
|
callLinkState
|
||||||
);
|
);
|
||||||
|
@ -2025,7 +2025,7 @@ function updateCallLinkRestrictions(
|
||||||
restrictions: CallLinkRestrictions
|
restrictions: CallLinkRestrictions
|
||||||
): ThunkAction<void, RootStateType, unknown, HandleCallLinkUpdateActionType> {
|
): ThunkAction<void, RootStateType, unknown, HandleCallLinkUpdateActionType> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const prevCallLink = await dataInterface.getCallLinkByRoomId(roomId);
|
const prevCallLink = await DataReader.getCallLinkByRoomId(roomId);
|
||||||
strictAssert(
|
strictAssert(
|
||||||
prevCallLink,
|
prevCallLink,
|
||||||
`updateCallLinkRestrictions(${roomId}): call link not found`
|
`updateCallLinkRestrictions(${roomId}): call link not found`
|
||||||
|
@ -2034,7 +2034,7 @@ function updateCallLinkRestrictions(
|
||||||
prevCallLink,
|
prevCallLink,
|
||||||
restrictions
|
restrictions
|
||||||
);
|
);
|
||||||
const callLink = await dataInterface.updateCallLinkState(
|
const callLink = await DataWriter.updateCallLinkState(
|
||||||
roomId,
|
roomId,
|
||||||
callLinkState
|
callLinkState
|
||||||
);
|
);
|
||||||
|
@ -2126,13 +2126,13 @@ const _startCallLinkLobby = async ({
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const callLinkExists = await dataInterface.callLinkExists(roomId);
|
const callLinkExists = await DataReader.callLinkExists(roomId);
|
||||||
if (callLinkExists) {
|
if (callLinkExists) {
|
||||||
await dataInterface.updateCallLinkState(roomId, callLinkState);
|
await DataWriter.updateCallLinkState(roomId, callLinkState);
|
||||||
log.info('startCallLinkLobby: Updated existing call link', roomId);
|
log.info('startCallLinkLobby: Updated existing call link', roomId);
|
||||||
} else {
|
} else {
|
||||||
const { name, restrictions, expiration, revoked } = callLinkState;
|
const { name, restrictions, expiration, revoked } = callLinkState;
|
||||||
await dataInterface.insertCallLink({
|
await DataWriter.insertCallLink({
|
||||||
roomId,
|
roomId,
|
||||||
rootKey,
|
rootKey,
|
||||||
adminKey: null,
|
adminKey: null,
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
isVideoAttachment,
|
isVideoAttachment,
|
||||||
isImageAttachment,
|
isImageAttachment,
|
||||||
} from '../../types/Attachment';
|
} from '../../types/Attachment';
|
||||||
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
import type { DraftBodyRanges } from '../../types/BodyRange';
|
import type { DraftBodyRanges } from '../../types/BodyRange';
|
||||||
import type { LinkPreviewType } from '../../types/message/LinkPreviews';
|
import type { LinkPreviewType } from '../../types/message/LinkPreviews';
|
||||||
|
@ -336,7 +337,7 @@ function scrollToQuotedMessage({
|
||||||
ShowToastActionType | ScrollToMessageActionType
|
ShowToastActionType | ScrollToMessageActionType
|
||||||
> {
|
> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const messages = await window.Signal.Data.getMessagesBySentAt(sentAt);
|
const messages = await DataReader.getMessagesBySentAt(sentAt);
|
||||||
const message = messages.find(item =>
|
const message = messages.find(item =>
|
||||||
Boolean(
|
Boolean(
|
||||||
item.conversationId === conversationId &&
|
item.conversationId === conversationId &&
|
||||||
|
@ -765,7 +766,7 @@ export function setQuoteByMessageId(
|
||||||
timestamp,
|
timestamp,
|
||||||
});
|
});
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message) {
|
if (message) {
|
||||||
|
@ -866,7 +867,7 @@ function addAttachment(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -904,7 +905,7 @@ function addPendingAttachment(
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
conversation.attributes.draftAttachments = nextAttachments;
|
conversation.attributes.draftAttachments = nextAttachments;
|
||||||
conversation.attributes.draftChanged = true;
|
conversation.attributes.draftChanged = true;
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
drop(DataWriter.updateConversation(conversation.attributes));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1201,7 +1202,7 @@ function removeAttachment(
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
conversation.attributes.draftAttachments = nextAttachments;
|
conversation.attributes.draftAttachments = nextAttachments;
|
||||||
conversation.attributes.draftChanged = true;
|
conversation.attributes.draftChanged = true;
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
replaceAttachments(conversationId, nextAttachments)(
|
replaceAttachments(conversationId, nextAttachments)(
|
||||||
|
@ -1312,7 +1313,7 @@ function saveDraft(
|
||||||
draftChanged: true,
|
draftChanged: true,
|
||||||
draftBodyRanges: [],
|
draftBodyRanges: [],
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
drop(DataWriter.updateConversation(conversation.attributes));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1336,7 +1337,7 @@ function saveDraft(
|
||||||
draftChanged: true,
|
draftChanged: true,
|
||||||
timestamp,
|
timestamp,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
drop(DataWriter.updateConversation(conversation.attributes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import type { PhoneNumber } from 'google-libphonenumber';
|
||||||
|
|
||||||
import { clipboard } from 'electron';
|
import { clipboard } from 'electron';
|
||||||
import type { ReadonlyDeep } from 'type-fest';
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import type { AttachmentType } from '../../types/Attachment';
|
import type { AttachmentType } from '../../types/Attachment';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import * as groups from '../../groups';
|
import * as groups from '../../groups';
|
||||||
|
@ -1480,7 +1481,7 @@ async function getAvatarsAndUpdateConversation(
|
||||||
conversation.attributes.avatars = nextAvatars.map(avatarData =>
|
conversation.attributes.avatars = nextAvatars.map(avatarData =>
|
||||||
omit(avatarData, ['buffer'])
|
omit(avatarData, ['buffer'])
|
||||||
);
|
);
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
|
|
||||||
return nextAvatars;
|
return nextAvatars;
|
||||||
}
|
}
|
||||||
|
@ -1750,8 +1751,7 @@ function deleteMessages({
|
||||||
let nearbyMessageId: string | null = null;
|
let nearbyMessageId: string | null = null;
|
||||||
|
|
||||||
if (nearbyMessageId == null && lastSelectedMessage != null) {
|
if (nearbyMessageId == null && lastSelectedMessage != null) {
|
||||||
const foundMessageId =
|
const foundMessageId = await DataReader.getNearbyMessageFromDeletedSet({
|
||||||
await window.Signal.Data.getNearbyMessageFromDeletedSet({
|
|
||||||
conversationId,
|
conversationId,
|
||||||
lastSelectedMessage,
|
lastSelectedMessage,
|
||||||
deletedMessageIds: messageIds,
|
deletedMessageIds: messageIds,
|
||||||
|
@ -1764,7 +1764,7 @@ function deleteMessages({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await window.Signal.Data.removeMessages(messageIds, {
|
await DataWriter.removeMessages(messageIds, {
|
||||||
singleProtoJobQueue,
|
singleProtoJobQueue,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2189,7 +2189,7 @@ function removeCustomColorOnConversations(
|
||||||
});
|
});
|
||||||
|
|
||||||
if (conversationsToUpdate.length) {
|
if (conversationsToUpdate.length) {
|
||||||
await window.Signal.Data.updateConversations(conversationsToUpdate);
|
await DataWriter.updateConversations(conversationsToUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -2209,7 +2209,7 @@ function resetAllChatColors(): ThunkAction<
|
||||||
> {
|
> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
// Calling this with no args unsets all the colors in the db
|
// Calling this with no args unsets all the colors in the db
|
||||||
await window.Signal.Data.updateAllConversationColors();
|
await DataWriter.updateAllConversationColors();
|
||||||
|
|
||||||
window.getConversations().forEach(conversation => {
|
window.getConversations().forEach(conversation => {
|
||||||
conversation.set({
|
conversation.set({
|
||||||
|
@ -2245,7 +2245,7 @@ function kickOffAttachmentDownload(
|
||||||
|
|
||||||
if (didUpdateValues) {
|
if (didUpdateValues) {
|
||||||
drop(
|
drop(
|
||||||
window.Signal.Data.saveMessage(message.attributes, {
|
DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -2402,7 +2402,7 @@ export function setVoiceNotePlaybackRate({
|
||||||
conversationModel.set({
|
conversationModel.set({
|
||||||
voiceNotePlaybackRate: rate === 1 ? undefined : rate,
|
voiceNotePlaybackRate: rate === 1 ? undefined : rate,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(conversationModel.attributes);
|
await DataWriter.updateConversation(conversationModel.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversation = conversationModel?.format();
|
const conversation = conversationModel?.format();
|
||||||
|
@ -2456,7 +2456,7 @@ function colorSelected({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -2779,9 +2779,7 @@ function toggleSelectMessage(
|
||||||
message => message
|
message => message
|
||||||
);
|
);
|
||||||
|
|
||||||
const betweenIds = await window.Signal.Data.getMessagesBetween(
|
const betweenIds = await DataReader.getMessagesBetween(conversationId, {
|
||||||
conversationId,
|
|
||||||
{
|
|
||||||
after: {
|
after: {
|
||||||
sent_at: after.sent_at,
|
sent_at: after.sent_at,
|
||||||
received_at: after.received_at,
|
received_at: after.received_at,
|
||||||
|
@ -2791,8 +2789,7 @@ function toggleSelectMessage(
|
||||||
received_at: before.received_at,
|
received_at: before.received_at,
|
||||||
},
|
},
|
||||||
includeStoryReplies: !isGroup(conversation.attributes),
|
includeStoryReplies: !isGroup(conversation.attributes),
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
toggledMessageIds = [messageId, ...betweenIds];
|
toggledMessageIds = [messageId, ...betweenIds];
|
||||||
} else {
|
} else {
|
||||||
|
@ -3434,7 +3431,7 @@ function reportSpam(
|
||||||
addReportSpamJob({
|
addReportSpamJob({
|
||||||
conversation,
|
conversation,
|
||||||
getMessageServerGuidsForSpam:
|
getMessageServerGuidsForSpam:
|
||||||
window.Signal.Data.getMessageServerGuidsForSpam,
|
DataReader.getMessageServerGuidsForSpam,
|
||||||
jobQueue: reportSpamJobQueue,
|
jobQueue: reportSpamJobQueue,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
@ -3484,7 +3481,7 @@ function blockAndReportSpam(
|
||||||
addReportSpamJob({
|
addReportSpamJob({
|
||||||
conversation: conversationForSpam,
|
conversation: conversationForSpam,
|
||||||
getMessageServerGuidsForSpam:
|
getMessageServerGuidsForSpam:
|
||||||
window.Signal.Data.getMessageServerGuidsForSpam,
|
DataReader.getMessageServerGuidsForSpam,
|
||||||
jobQueue: reportSpamJobQueue,
|
jobQueue: reportSpamJobQueue,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
@ -3654,12 +3651,9 @@ function loadRecentMediaItems(
|
||||||
): ThunkAction<void, RootStateType, unknown, SetRecentMediaItemsActionType> {
|
): ThunkAction<void, RootStateType, unknown, SetRecentMediaItemsActionType> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const messages: Array<MessageAttributesType> =
|
const messages: Array<MessageAttributesType> =
|
||||||
await window.Signal.Data.getMessagesWithVisualMediaAttachments(
|
await DataReader.getMessagesWithVisualMediaAttachments(conversationId, {
|
||||||
conversationId,
|
|
||||||
{
|
|
||||||
limit,
|
limit,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
// Cache these messages in memory to ensure Lightbox can find them
|
// Cache these messages in memory to ensure Lightbox can find them
|
||||||
messages.forEach(message => {
|
messages.forEach(message => {
|
||||||
|
@ -3839,7 +3833,7 @@ export function scrollToOldestUnreadMention(
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldestUnreadMention =
|
const oldestUnreadMention =
|
||||||
await window.Signal.Data.getOldestUnreadMentionOfMeForConversation(
|
await DataReader.getOldestUnreadMentionOfMeForConversation(
|
||||||
conversationId,
|
conversationId,
|
||||||
{
|
{
|
||||||
includeStoryReplies: !isGroup(conversation),
|
includeStoryReplies: !isGroup(conversation),
|
||||||
|
@ -4151,7 +4145,7 @@ function toggleGroupsForStorySend(
|
||||||
conversation.set({
|
conversation.set({
|
||||||
storySendMode: newStorySendMode,
|
storySendMode: newStorySendMode,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
conversation.captureChange('storySendMode');
|
conversation.captureChange('storySendMode');
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -4413,7 +4407,7 @@ function onConversationClosed(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
|
|
||||||
drop(conversation.updateLastMessage());
|
drop(conversation.updateLastMessage());
|
||||||
}
|
}
|
||||||
|
@ -4784,7 +4778,7 @@ function updateNicknameAndNote(
|
||||||
nicknameFamilyName: nickname?.familyName,
|
nicknameFamilyName: nickname?.familyName,
|
||||||
note,
|
note,
|
||||||
});
|
});
|
||||||
window.Signal.Data.updateConversation(conversationModel.attributes);
|
await DataWriter.updateConversation(conversationModel.attributes);
|
||||||
const conversation = conversationModel.format();
|
const conversation = conversationModel.format();
|
||||||
dispatch(conversationChanged(conversationId, conversation));
|
dispatch(conversationChanged(conversationId, conversation));
|
||||||
conversationModel.captureChange('nicknameAndNote');
|
conversationModel.captureChange('nicknameAndNote');
|
||||||
|
|
|
@ -5,11 +5,11 @@ import { take, uniq } from 'lodash';
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
import type { ReadonlyDeep } from 'type-fest';
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { EmojiPickDataType } from '../../components/emoji/EmojiPicker';
|
import type { EmojiPickDataType } from '../../components/emoji/EmojiPicker';
|
||||||
import dataInterface from '../../sql/Client';
|
import { DataWriter } from '../../sql/Client';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
import { useBoundActions } from '../../hooks/useBoundActions';
|
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
|
|
||||||
const { updateEmojiUsage } = dataInterface;
|
const { updateEmojiUsage } = DataWriter;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ import {
|
||||||
} from './conversations';
|
} from './conversations';
|
||||||
import { showStickerPackPreview } from './globalModals';
|
import { showStickerPackPreview } from './globalModals';
|
||||||
import { useBoundActions } from '../../hooks/useBoundActions';
|
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
import dataInterface from '../../sql/Client';
|
import { DataReader } from '../../sql/Client';
|
||||||
|
|
||||||
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type LightboxStateType =
|
export type LightboxStateType =
|
||||||
|
@ -349,7 +349,7 @@ function showLightbox(opts: {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { older, newer } =
|
const { older, newer } =
|
||||||
await dataInterface.getConversationRangeCenteredOnMessage({
|
await DataReader.getConversationRangeCenteredOnMessage({
|
||||||
conversationId: message.get('conversationId'),
|
conversationId: message.get('conversationId'),
|
||||||
messageId,
|
messageId,
|
||||||
receivedAt,
|
receivedAt,
|
||||||
|
@ -436,8 +436,8 @@ function showLightboxForAdjacentMessage(
|
||||||
|
|
||||||
const [adjacent] =
|
const [adjacent] =
|
||||||
direction === AdjacentMessageDirection.Previous
|
direction === AdjacentMessageDirection.Previous
|
||||||
? await dataInterface.getOlderMessagesByConversation(options)
|
? await DataReader.getOlderMessagesByConversation(options)
|
||||||
: await dataInterface.getNewerMessagesByConversation(options);
|
: await DataReader.getNewerMessagesByConversation(options);
|
||||||
|
|
||||||
if (!adjacent) {
|
if (!adjacent) {
|
||||||
log.warn(
|
log.warn(
|
||||||
|
|
|
@ -15,7 +15,7 @@ import type { MIMEType } from '../../types/MIME';
|
||||||
import type { MediaItemType } from '../../types/MediaItem';
|
import type { MediaItemType } from '../../types/MediaItem';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
|
|
||||||
import dataInterface from '../../sql/Client';
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import {
|
import {
|
||||||
CONVERSATION_UNLOADED,
|
CONVERSATION_UNLOADED,
|
||||||
MESSAGE_CHANGED,
|
MESSAGE_CHANGED,
|
||||||
|
@ -84,13 +84,13 @@ function loadMediaItems(
|
||||||
|
|
||||||
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
||||||
|
|
||||||
const rawMedia = await dataInterface.getMessagesWithVisualMediaAttachments(
|
const rawMedia = await DataReader.getMessagesWithVisualMediaAttachments(
|
||||||
conversationId,
|
conversationId,
|
||||||
{
|
{
|
||||||
limit: DEFAULT_MEDIA_FETCH_COUNT,
|
limit: DEFAULT_MEDIA_FETCH_COUNT,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const rawDocuments = await dataInterface.getMessagesWithFileAttachments(
|
const rawDocuments = await DataReader.getMessagesWithFileAttachments(
|
||||||
conversationId,
|
conversationId,
|
||||||
{
|
{
|
||||||
limit: DEFAULT_DOCUMENTS_FETCH_COUNT,
|
limit: DEFAULT_DOCUMENTS_FETCH_COUNT,
|
||||||
|
@ -111,7 +111,7 @@ function loadMediaItems(
|
||||||
const upgradedMsgAttributes = await upgradeMessageSchema(message);
|
const upgradedMsgAttributes = await upgradeMessageSchema(message);
|
||||||
model.set(upgradedMsgAttributes);
|
model.set(upgradedMsgAttributes);
|
||||||
|
|
||||||
await dataInterface.saveMessage(upgradedMsgAttributes, { ourAci });
|
await DataWriter.saveMessage(upgradedMsgAttributes, { ourAci });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,11 +7,8 @@ import { debounce, omit, reject } from 'lodash';
|
||||||
import type { ReadonlyDeep } from 'type-fest';
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import { filterAndSortConversations } from '../../util/filterAndSortConversations';
|
import { filterAndSortConversations } from '../../util/filterAndSortConversations';
|
||||||
import type {
|
import type { ClientSearchResultMessageType } from '../../sql/Interface';
|
||||||
ClientSearchResultMessageType,
|
import { DataReader } from '../../sql/Client';
|
||||||
ClientInterface,
|
|
||||||
} from '../../sql/Interface';
|
|
||||||
import dataInterface from '../../sql/Client';
|
|
||||||
import { makeLookup } from '../../util/makeLookup';
|
import { makeLookup } from '../../util/makeLookup';
|
||||||
import { isNotNil } from '../../util/isNotNil';
|
import { isNotNil } from '../../util/isNotNil';
|
||||||
import type { ServiceIdString } from '../../types/ServiceId';
|
import type { ServiceIdString } from '../../types/ServiceId';
|
||||||
|
@ -44,7 +41,7 @@ import * as log from '../../logging/log';
|
||||||
import { searchConversationTitles } from '../../util/searchConversationTitles';
|
import { searchConversationTitles } from '../../util/searchConversationTitles';
|
||||||
import { isDirectConversation } from '../../util/whatTypeOfConversation';
|
import { isDirectConversation } from '../../util/whatTypeOfConversation';
|
||||||
|
|
||||||
const { searchMessages: dataSearchMessages }: ClientInterface = dataInterface;
|
const { searchMessages: dataSearchMessages } = DataReader;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import type {
|
||||||
StickerType as StickerDBType,
|
StickerType as StickerDBType,
|
||||||
StickerPackType as StickerPackDBType,
|
StickerPackType as StickerPackDBType,
|
||||||
} from '../../sql/Interface';
|
} from '../../sql/Interface';
|
||||||
import dataInterface from '../../sql/Client';
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import type { RecentStickerType } from '../../types/Stickers';
|
import type { RecentStickerType } from '../../types/Stickers';
|
||||||
import {
|
import {
|
||||||
downloadStickerPack as externalDownloadStickerPack,
|
downloadStickerPack as externalDownloadStickerPack,
|
||||||
|
@ -25,7 +25,8 @@ import type { NoopActionType } from './noop';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
import { useBoundActions } from '../../hooks/useBoundActions';
|
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
|
|
||||||
const { getRecentStickers, updateStickerLastUsed } = dataInterface;
|
const { getRecentStickers } = DataReader;
|
||||||
|
const { updateStickerLastUsed } = DataWriter;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
|
@ -241,7 +242,7 @@ async function doInstallStickerPack(
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
await dataInterface.installStickerPack(packId, timestamp);
|
await DataWriter.installStickerPack(packId, timestamp);
|
||||||
|
|
||||||
if (!fromSync && !fromStorageService && !fromBackup) {
|
if (!fromSync && !fromStorageService && !fromBackup) {
|
||||||
// Kick this off, but don't wait for it
|
// Kick this off, but don't wait for it
|
||||||
|
@ -283,7 +284,7 @@ async function doUninstallStickerPack(
|
||||||
const { fromSync = false, fromStorageService = false } = options;
|
const { fromSync = false, fromStorageService = false } = options;
|
||||||
|
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
await dataInterface.uninstallStickerPack(packId, timestamp);
|
await DataWriter.uninstallStickerPack(packId, timestamp);
|
||||||
|
|
||||||
// If there are no more references, it should be removed
|
// If there are no more references, it should be removed
|
||||||
await maybeDeletePack(packId);
|
await maybeDeletePack(packId);
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { isAciString } from '../../util/isAciString';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import { TARGETED_CONVERSATION_CHANGED } from './conversations';
|
import { TARGETED_CONVERSATION_CHANGED } from './conversations';
|
||||||
import { SIGNAL_ACI } from '../../types/SignalConversation';
|
import { SIGNAL_ACI } from '../../types/SignalConversation';
|
||||||
import dataInterface from '../../sql/Client';
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import { ReadStatus } from '../../messages/MessageReadStatus';
|
import { ReadStatus } from '../../messages/MessageReadStatus';
|
||||||
import { SendStatus } from '../../messages/MessageSendState';
|
import { SendStatus } from '../../messages/MessageSendState';
|
||||||
import { SafetyNumberChangeSource } from '../../components/SafetyNumberChangeDialog';
|
import { SafetyNumberChangeSource } from '../../components/SafetyNumberChangeDialog';
|
||||||
|
@ -285,7 +285,7 @@ function deleteGroupStoryReply(
|
||||||
messageId: string
|
messageId: string
|
||||||
): ThunkAction<void, RootStateType, unknown, StoryReplyDeletedActionType> {
|
): ThunkAction<void, RootStateType, unknown, StoryReplyDeletedActionType> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
await window.Signal.Data.removeMessage(messageId, { singleProtoJobQueue });
|
await DataWriter.removeMessage(messageId, { singleProtoJobQueue });
|
||||||
dispatch({
|
dispatch({
|
||||||
type: STORY_REPLY_DELETED,
|
type: STORY_REPLY_DELETED,
|
||||||
payload: messageId,
|
payload: messageId,
|
||||||
|
@ -337,7 +337,7 @@ function loadStoryReplies(
|
||||||
): ThunkAction<void, RootStateType, unknown, LoadStoryRepliesActionType> {
|
): ThunkAction<void, RootStateType, unknown, LoadStoryRepliesActionType> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const conversation = getConversationSelector(getState())(conversationId);
|
const conversation = getConversationSelector(getState())(conversationId);
|
||||||
const replies = await dataInterface.getOlderMessagesByConversation({
|
const replies = await DataReader.getOlderMessagesByConversation({
|
||||||
conversationId,
|
conversationId,
|
||||||
limit: 9000,
|
limit: 9000,
|
||||||
storyId: messageId,
|
storyId: messageId,
|
||||||
|
@ -421,7 +421,7 @@ function markStoryRead(
|
||||||
|
|
||||||
message.set(markViewed(message.attributes, storyReadDate));
|
message.set(markViewed(message.attributes, storyReadDate));
|
||||||
drop(
|
drop(
|
||||||
dataInterface.saveMessage(message.attributes, {
|
DataWriter.saveMessage(message.attributes, {
|
||||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -459,7 +459,7 @@ function markStoryRead(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await dataInterface.addNewStoryRead({
|
await DataWriter.addNewStoryRead({
|
||||||
authorId,
|
authorId,
|
||||||
conversationId: message.attributes.conversationId,
|
conversationId: message.attributes.conversationId,
|
||||||
storyId: messageId,
|
storyId: messageId,
|
||||||
|
@ -1409,7 +1409,7 @@ function removeAllContactStories(
|
||||||
|
|
||||||
log.info(`${logId}: removing ${messages.length} stories`);
|
log.info(`${logId}: removing ${messages.length} stories`);
|
||||||
|
|
||||||
await dataInterface.removeMessages(messageIds, { singleProtoJobQueue });
|
await DataWriter.removeMessages(messageIds, { singleProtoJobQueue });
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'NOOP',
|
type: 'NOOP',
|
||||||
|
|
|
@ -10,7 +10,7 @@ import type { StoryDistributionWithMembersType } from '../../sql/Interface';
|
||||||
import type { StoryDistributionIdString } from '../../types/StoryDistributionId';
|
import type { StoryDistributionIdString } from '../../types/StoryDistributionId';
|
||||||
import type { ServiceIdString } from '../../types/ServiceId';
|
import type { ServiceIdString } from '../../types/ServiceId';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import dataInterface from '../../sql/Client';
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import { MY_STORY_ID } from '../../types/Stories';
|
import { MY_STORY_ID } from '../../types/Stories';
|
||||||
import { generateStoryDistributionId } from '../../types/StoryDistributionId';
|
import { generateStoryDistributionId } from '../../types/StoryDistributionId';
|
||||||
import { deleteStoryForEveryone } from '../../util/deleteStoryForEveryone';
|
import { deleteStoryForEveryone } from '../../util/deleteStoryForEveryone';
|
||||||
|
@ -112,8 +112,9 @@ function allowsRepliesChanged(
|
||||||
allowsReplies: boolean
|
allowsReplies: boolean
|
||||||
): ThunkAction<void, RootStateType, null, AllowRepliesChangedActionType> {
|
): ThunkAction<void, RootStateType, null, AllowRepliesChangedActionType> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const storyDistribution =
|
const storyDistribution = await DataReader.getStoryDistributionWithMembers(
|
||||||
await dataInterface.getStoryDistributionWithMembers(listId);
|
listId
|
||||||
|
);
|
||||||
|
|
||||||
if (!storyDistribution) {
|
if (!storyDistribution) {
|
||||||
log.warn(
|
log.warn(
|
||||||
|
@ -131,7 +132,7 @@ function allowsRepliesChanged(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await dataInterface.modifyStoryDistribution({
|
await DataWriter.modifyStoryDistribution({
|
||||||
...storyDistribution,
|
...storyDistribution,
|
||||||
allowsReplies,
|
allowsReplies,
|
||||||
storageNeedsSync: true,
|
storageNeedsSync: true,
|
||||||
|
@ -178,7 +179,7 @@ function createDistributionList(
|
||||||
};
|
};
|
||||||
|
|
||||||
if (shouldSave) {
|
if (shouldSave) {
|
||||||
await dataInterface.createNewStoryDistribution(storyDistribution);
|
await DataWriter.createNewStoryDistribution(storyDistribution);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storyDistribution.storageNeedsSync) {
|
if (storyDistribution.storageNeedsSync) {
|
||||||
|
@ -207,15 +208,16 @@ function deleteDistributionList(
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const deletedAtTimestamp = Date.now();
|
const deletedAtTimestamp = Date.now();
|
||||||
|
|
||||||
const storyDistribution =
|
const storyDistribution = await DataReader.getStoryDistributionWithMembers(
|
||||||
await dataInterface.getStoryDistributionWithMembers(listId);
|
listId
|
||||||
|
);
|
||||||
|
|
||||||
if (!storyDistribution) {
|
if (!storyDistribution) {
|
||||||
log.warn('No story distribution found for id', listId);
|
log.warn('No story distribution found for id', listId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await dataInterface.modifyStoryDistributionWithMembers(
|
await DataWriter.modifyStoryDistributionWithMembers(
|
||||||
{
|
{
|
||||||
...storyDistribution,
|
...storyDistribution,
|
||||||
deletedAtTimestamp,
|
deletedAtTimestamp,
|
||||||
|
@ -266,7 +268,7 @@ function hideMyStoriesFrom(
|
||||||
memberServiceIds: Array<ServiceIdString>
|
memberServiceIds: Array<ServiceIdString>
|
||||||
): ThunkAction<void, RootStateType, null, HideMyStoriesFromActionType> {
|
): ThunkAction<void, RootStateType, null, HideMyStoriesFromActionType> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const myStories = await dataInterface.getStoryDistributionWithMembers(
|
const myStories = await DataReader.getStoryDistributionWithMembers(
|
||||||
MY_STORY_ID
|
MY_STORY_ID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -279,7 +281,7 @@ function hideMyStoriesFrom(
|
||||||
|
|
||||||
const toAdd = new Set<ServiceIdString>(memberServiceIds);
|
const toAdd = new Set<ServiceIdString>(memberServiceIds);
|
||||||
|
|
||||||
await dataInterface.modifyStoryDistributionWithMembers(
|
await DataWriter.modifyStoryDistributionWithMembers(
|
||||||
{
|
{
|
||||||
...myStories,
|
...myStories,
|
||||||
isBlockList: true,
|
isBlockList: true,
|
||||||
|
@ -315,8 +317,9 @@ function removeMembersFromDistributionList(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const storyDistribution =
|
const storyDistribution = await DataReader.getStoryDistributionWithMembers(
|
||||||
await dataInterface.getStoryDistributionWithMembers(listId);
|
listId
|
||||||
|
);
|
||||||
|
|
||||||
if (!storyDistribution) {
|
if (!storyDistribution) {
|
||||||
log.warn(
|
log.warn(
|
||||||
|
@ -343,7 +346,7 @@ function removeMembersFromDistributionList(
|
||||||
await window.storage.put('hasSetMyStoriesPrivacy', true);
|
await window.storage.put('hasSetMyStoriesPrivacy', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await dataInterface.modifyStoryDistributionWithMembers(
|
await DataWriter.modifyStoryDistributionWithMembers(
|
||||||
{
|
{
|
||||||
...storyDistribution,
|
...storyDistribution,
|
||||||
isBlockList,
|
isBlockList,
|
||||||
|
@ -385,7 +388,7 @@ function setMyStoriesToAllSignalConnections(): ThunkAction<
|
||||||
ResetMyStoriesActionType
|
ResetMyStoriesActionType
|
||||||
> {
|
> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const myStories = await dataInterface.getStoryDistributionWithMembers(
|
const myStories = await DataReader.getStoryDistributionWithMembers(
|
||||||
MY_STORY_ID
|
MY_STORY_ID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -397,7 +400,7 @@ function setMyStoriesToAllSignalConnections(): ThunkAction<
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myStories.isBlockList || myStories.members.length > 0) {
|
if (myStories.isBlockList || myStories.members.length > 0) {
|
||||||
await dataInterface.modifyStoryDistributionWithMembers(
|
await DataWriter.modifyStoryDistributionWithMembers(
|
||||||
{
|
{
|
||||||
...myStories,
|
...myStories,
|
||||||
isBlockList: true,
|
isBlockList: true,
|
||||||
|
@ -425,8 +428,9 @@ function updateStoryViewers(
|
||||||
memberServiceIds: Array<ServiceIdString>
|
memberServiceIds: Array<ServiceIdString>
|
||||||
): ThunkAction<void, RootStateType, null, ViewersChangedActionType> {
|
): ThunkAction<void, RootStateType, null, ViewersChangedActionType> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const storyDistribution =
|
const storyDistribution = await DataReader.getStoryDistributionWithMembers(
|
||||||
await dataInterface.getStoryDistributionWithMembers(listId);
|
listId
|
||||||
|
);
|
||||||
|
|
||||||
if (!storyDistribution) {
|
if (!storyDistribution) {
|
||||||
log.warn(
|
log.warn(
|
||||||
|
@ -456,7 +460,7 @@ function updateStoryViewers(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await dataInterface.modifyStoryDistributionWithMembers(
|
await DataWriter.modifyStoryDistributionWithMembers(
|
||||||
{
|
{
|
||||||
...storyDistribution,
|
...storyDistribution,
|
||||||
isBlockList: false,
|
isBlockList: false,
|
||||||
|
@ -489,7 +493,7 @@ function removeMemberFromAllDistributionLists(
|
||||||
): ThunkAction<void, RootStateType, null, ModifyListActionType> {
|
): ThunkAction<void, RootStateType, null, ModifyListActionType> {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const logId = `removeMemberFromAllDistributionLists(${member})`;
|
const logId = `removeMemberFromAllDistributionLists(${member})`;
|
||||||
const lists = await dataInterface.getAllStoryDistributionsWithMembers();
|
const lists = await DataReader.getAllStoryDistributionsWithMembers();
|
||||||
|
|
||||||
const listsWithMember = lists.filter(({ members }) =>
|
const listsWithMember = lists.filter(({ members }) =>
|
||||||
members.includes(member)
|
members.includes(member)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import type { VerificationTransport } from '../../types/VerificationTransport';
|
import type { VerificationTransport } from '../../types/VerificationTransport';
|
||||||
|
import { DataWriter } from '../../sql/Client';
|
||||||
import { App } from '../../components/App';
|
import { App } from '../../components/App';
|
||||||
import OS from '../../util/os/osMain';
|
import OS from '../../util/os/osMain';
|
||||||
import { getConversation } from '../../util/getConversation';
|
import { getConversation } from '../../util/getConversation';
|
||||||
|
@ -101,7 +102,7 @@ async function uploadProfile({
|
||||||
us.set('profileName', firstName);
|
us.set('profileName', firstName);
|
||||||
us.set('profileFamilyName', lastName);
|
us.set('profileFamilyName', lastName);
|
||||||
us.captureChange('standaloneProfile');
|
us.captureChange('standaloneProfile');
|
||||||
await window.Signal.Data.updateConversation(us.attributes);
|
await DataWriter.updateConversation(us.attributes);
|
||||||
|
|
||||||
await writeProfile(getConversation(us), {
|
await writeProfile(getConversation(us), {
|
||||||
keepAvatar: true,
|
keepAvatar: true,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
import React, { memo, useCallback, useEffect, useMemo } from 'react';
|
import React, { memo, useCallback, useEffect, useMemo } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
import { DataReader } from '../../sql/Client';
|
||||||
import { useItemsActions } from '../ducks/items';
|
import { useItemsActions } from '../ducks/items';
|
||||||
import {
|
import {
|
||||||
getNavTabsCollapsed,
|
getNavTabsCollapsed,
|
||||||
|
@ -184,7 +185,7 @@ export const SmartCallsTab = memo(function SmartCallsTab() {
|
||||||
if (callHistoryFilter == null) {
|
if (callHistoryFilter == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const count = await window.Signal.Data.getCallHistoryGroupsCount(
|
const count = await DataReader.getCallHistoryGroupsCount(
|
||||||
callHistoryFilter
|
callHistoryFilter
|
||||||
);
|
);
|
||||||
return count;
|
return count;
|
||||||
|
@ -206,7 +207,7 @@ export const SmartCallsTab = memo(function SmartCallsTab() {
|
||||||
if (callHistoryFilter == null) {
|
if (callHistoryFilter == null) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const results = await window.Signal.Data.getCallHistoryGroups(
|
const results = await DataReader.getCallHistoryGroups(
|
||||||
callHistoryFilter,
|
callHistoryFilter,
|
||||||
pagination
|
pagination
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import { assert } from 'chai';
|
import { assert } from 'chai';
|
||||||
|
|
||||||
import { strictAssert } from '../util/assert';
|
import { strictAssert } from '../util/assert';
|
||||||
|
import { DataWriter } from '../sql/Client';
|
||||||
|
|
||||||
import type { ConversationModel } from '../models/conversations';
|
import type { ConversationModel } from '../models/conversations';
|
||||||
import type { AciString, PniString, ServiceIdString } from '../types/ServiceId';
|
import type { AciString, PniString, ServiceIdString } from '../types/ServiceId';
|
||||||
|
@ -32,7 +33,7 @@ describe('ConversationController', () => {
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await window.Signal.Data._removeAllConversations();
|
await DataWriter._removeAllConversations();
|
||||||
|
|
||||||
window.ConversationController.reset();
|
window.ConversationController.reset();
|
||||||
await window.ConversationController.load();
|
await window.ConversationController.load();
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { assert } from 'chai';
|
||||||
|
|
||||||
import { type AciString, generateAci } from '../types/ServiceId';
|
import { type AciString, generateAci } from '../types/ServiceId';
|
||||||
import type { MessageAttributesType } from '../model-types';
|
import type { MessageAttributesType } from '../model-types';
|
||||||
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import { SendStatus } from '../messages/MessageSendState';
|
import { SendStatus } from '../messages/MessageSendState';
|
||||||
import type {
|
import type {
|
||||||
MessageReceiptAttributesType,
|
MessageReceiptAttributesType,
|
||||||
|
@ -77,7 +78,7 @@ describe('MessageReceipts', () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await window.Signal.Data.saveMessage(messageAttributes, {
|
await DataWriter.saveMessage(messageAttributes, {
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
ourAci,
|
ourAci,
|
||||||
});
|
});
|
||||||
|
@ -97,7 +98,7 @@ describe('MessageReceipts', () => {
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const messageFromDatabase = await window.Signal.Data.getMessageById(id);
|
const messageFromDatabase = await DataReader.getMessageById(id);
|
||||||
const savedSendState = messageFromDatabase?.sendStateByConversationId;
|
const savedSendState = messageFromDatabase?.sendStateByConversationId;
|
||||||
|
|
||||||
assert.equal(savedSendState?.aaaa.status, SendStatus.Read, 'aaaa');
|
assert.equal(savedSendState?.aaaa.status, SendStatus.Read, 'aaaa');
|
||||||
|
@ -154,11 +155,11 @@ describe('MessageReceipts', () => {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
await window.Signal.Data.saveMessage(messageAttributes, {
|
await DataWriter.saveMessage(messageAttributes, {
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
ourAci,
|
ourAci,
|
||||||
});
|
});
|
||||||
await window.Signal.Data.saveEditedMessage(messageAttributes, ourAci, {
|
await DataWriter.saveEditedMessage(messageAttributes, ourAci, {
|
||||||
conversationId: messageAttributes.conversationId,
|
conversationId: messageAttributes.conversationId,
|
||||||
messageId: messageAttributes.id,
|
messageId: messageAttributes.id,
|
||||||
readStatus: ReadStatus.Read,
|
readStatus: ReadStatus.Read,
|
||||||
|
@ -211,7 +212,7 @@ describe('MessageReceipts', () => {
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const messageFromDatabase = await window.Signal.Data.getMessageById(id);
|
const messageFromDatabase = await DataReader.getMessageById(id);
|
||||||
const rootSendState = messageFromDatabase?.sendStateByConversationId;
|
const rootSendState = messageFromDatabase?.sendStateByConversationId;
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
} from '@signalapp/libsignal-client';
|
} from '@signalapp/libsignal-client';
|
||||||
import { v4 as generateUuid } from 'uuid';
|
import { v4 as generateUuid } from 'uuid';
|
||||||
|
|
||||||
|
import { DataReader, DataWriter } from '../sql/Client';
|
||||||
import { signal } from '../protobuf/compiled';
|
import { signal } from '../protobuf/compiled';
|
||||||
import { sessionStructureToBytes } from '../util/sessionTranslation';
|
import { sessionStructureToBytes } from '../util/sessionTranslation';
|
||||||
import * as durations from '../util/durations';
|
import * as durations from '../util/durations';
|
||||||
|
@ -295,21 +296,21 @@ describe('SignalProtocolStore', () => {
|
||||||
await store.saveIdentity(identifier, testKey.pubKey);
|
await store.saveIdentity(identifier, testKey.pubKey);
|
||||||
});
|
});
|
||||||
it('marks the key firstUse', async () => {
|
it('marks the key firstUse', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
assert(identity.firstUse);
|
assert(identity.firstUse);
|
||||||
});
|
});
|
||||||
it('sets the timestamp', async () => {
|
it('sets the timestamp', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
assert(identity.timestamp);
|
assert(identity.timestamp);
|
||||||
});
|
});
|
||||||
it('sets the verified status to DEFAULT', async () => {
|
it('sets the verified status to DEFAULT', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -321,7 +322,7 @@ describe('SignalProtocolStore', () => {
|
||||||
const oldTimestamp = Date.now();
|
const oldTimestamp = Date.now();
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
firstUse: true,
|
firstUse: true,
|
||||||
|
@ -334,14 +335,14 @@ describe('SignalProtocolStore', () => {
|
||||||
await store.saveIdentity(identifier, newIdentity);
|
await store.saveIdentity(identifier, newIdentity);
|
||||||
});
|
});
|
||||||
it('marks the key not firstUse', async () => {
|
it('marks the key not firstUse', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
assert(!identity.firstUse);
|
assert(!identity.firstUse);
|
||||||
});
|
});
|
||||||
it('updates the timestamp', async () => {
|
it('updates the timestamp', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -350,7 +351,7 @@ describe('SignalProtocolStore', () => {
|
||||||
|
|
||||||
describe('The previous verified status was DEFAULT', () => {
|
describe('The previous verified status was DEFAULT', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
firstUse: true,
|
firstUse: true,
|
||||||
|
@ -363,9 +364,7 @@ describe('SignalProtocolStore', () => {
|
||||||
await store.saveIdentity(identifier, newIdentity);
|
await store.saveIdentity(identifier, newIdentity);
|
||||||
});
|
});
|
||||||
it('sets the new key to default', async () => {
|
it('sets the new key to default', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
theirAci
|
|
||||||
);
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -374,7 +373,7 @@ describe('SignalProtocolStore', () => {
|
||||||
});
|
});
|
||||||
describe('The previous verified status was VERIFIED', () => {
|
describe('The previous verified status was VERIFIED', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
firstUse: true,
|
firstUse: true,
|
||||||
|
@ -387,9 +386,7 @@ describe('SignalProtocolStore', () => {
|
||||||
await store.saveIdentity(identifier, newIdentity);
|
await store.saveIdentity(identifier, newIdentity);
|
||||||
});
|
});
|
||||||
it('sets the new key to unverified', async () => {
|
it('sets the new key to unverified', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
theirAci
|
|
||||||
);
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -401,7 +398,7 @@ describe('SignalProtocolStore', () => {
|
||||||
});
|
});
|
||||||
describe('The previous verified status was UNVERIFIED', () => {
|
describe('The previous verified status was UNVERIFIED', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
firstUse: true,
|
firstUse: true,
|
||||||
|
@ -414,9 +411,7 @@ describe('SignalProtocolStore', () => {
|
||||||
await store.saveIdentity(identifier, newIdentity);
|
await store.saveIdentity(identifier, newIdentity);
|
||||||
});
|
});
|
||||||
it('sets the new key to unverified', async () => {
|
it('sets the new key to unverified', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
theirAci
|
|
||||||
);
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -430,7 +425,7 @@ describe('SignalProtocolStore', () => {
|
||||||
describe('When the key has not changed', () => {
|
describe('When the key has not changed', () => {
|
||||||
const oldTimestamp = Date.now();
|
const oldTimestamp = Date.now();
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
timestamp: oldTimestamp,
|
timestamp: oldTimestamp,
|
||||||
|
@ -442,22 +437,18 @@ describe('SignalProtocolStore', () => {
|
||||||
});
|
});
|
||||||
describe('If it is marked firstUse', () => {
|
describe('If it is marked firstUse', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
theirAci
|
|
||||||
);
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
identity.firstUse = true;
|
identity.firstUse = true;
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey(identity);
|
await DataWriter.createOrUpdateIdentityKey(identity);
|
||||||
await store.hydrateCaches();
|
await store.hydrateCaches();
|
||||||
});
|
});
|
||||||
it('nothing changes', async () => {
|
it('nothing changes', async () => {
|
||||||
await store.saveIdentity(identifier, testKey.pubKey, true);
|
await store.saveIdentity(identifier, testKey.pubKey, true);
|
||||||
|
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
theirAci
|
|
||||||
);
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -467,36 +458,30 @@ describe('SignalProtocolStore', () => {
|
||||||
});
|
});
|
||||||
describe('If it is not marked firstUse', () => {
|
describe('If it is not marked firstUse', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
theirAci
|
|
||||||
);
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
identity.firstUse = false;
|
identity.firstUse = false;
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey(identity);
|
await DataWriter.createOrUpdateIdentityKey(identity);
|
||||||
await store.hydrateCaches();
|
await store.hydrateCaches();
|
||||||
});
|
});
|
||||||
describe('If nonblocking approval is required', () => {
|
describe('If nonblocking approval is required', () => {
|
||||||
let now: number;
|
let now: number;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
now = Date.now();
|
now = Date.now();
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
theirAci
|
|
||||||
);
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
identity.timestamp = now;
|
identity.timestamp = now;
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey(identity);
|
await DataWriter.createOrUpdateIdentityKey(identity);
|
||||||
await store.hydrateCaches();
|
await store.hydrateCaches();
|
||||||
});
|
});
|
||||||
it('sets non-blocking approval', async () => {
|
it('sets non-blocking approval', async () => {
|
||||||
await store.saveIdentity(identifier, testKey.pubKey, true);
|
await store.saveIdentity(identifier, testKey.pubKey, true);
|
||||||
|
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
theirAci
|
|
||||||
);
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -532,35 +517,35 @@ describe('SignalProtocolStore', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('publicKey is saved', async () => {
|
it('publicKey is saved', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
assert.isTrue(constantTimeEqual(identity.publicKey, testKey.pubKey));
|
assert.isTrue(constantTimeEqual(identity.publicKey, testKey.pubKey));
|
||||||
});
|
});
|
||||||
it('firstUse is saved', async () => {
|
it('firstUse is saved', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
assert.strictEqual(identity.firstUse, true);
|
assert.strictEqual(identity.firstUse, true);
|
||||||
});
|
});
|
||||||
it('timestamp is saved', async () => {
|
it('timestamp is saved', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
assert.strictEqual(identity.timestamp, now);
|
assert.strictEqual(identity.timestamp, now);
|
||||||
});
|
});
|
||||||
it('verified is saved', async () => {
|
it('verified is saved', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
assert.strictEqual(identity.verified, store.VerifiedStatus.VERIFIED);
|
assert.strictEqual(identity.verified, store.VerifiedStatus.VERIFIED);
|
||||||
});
|
});
|
||||||
it('nonblockingApproval is saved', async () => {
|
it('nonblockingApproval is saved', async () => {
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -607,7 +592,7 @@ describe('SignalProtocolStore', () => {
|
||||||
describe('setApproval', () => {
|
describe('setApproval', () => {
|
||||||
it('sets nonblockingApproval', async () => {
|
it('sets nonblockingApproval', async () => {
|
||||||
await store.setApproval(theirAci, true);
|
await store.setApproval(theirAci, true);
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -617,7 +602,7 @@ describe('SignalProtocolStore', () => {
|
||||||
});
|
});
|
||||||
describe('setVerified', () => {
|
describe('setVerified', () => {
|
||||||
async function saveRecordDefault() {
|
async function saveRecordDefault() {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
firstUse: true,
|
firstUse: true,
|
||||||
|
@ -632,7 +617,7 @@ describe('SignalProtocolStore', () => {
|
||||||
it('updates the verified status', async () => {
|
it('updates the verified status', async () => {
|
||||||
await store.setVerified(theirAci, store.VerifiedStatus.VERIFIED);
|
await store.setVerified(theirAci, store.VerifiedStatus.VERIFIED);
|
||||||
|
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -646,7 +631,7 @@ describe('SignalProtocolStore', () => {
|
||||||
it('updates the verified status', async () => {
|
it('updates the verified status', async () => {
|
||||||
await store.setVerified(theirAci, store.VerifiedStatus.VERIFIED);
|
await store.setVerified(theirAci, store.VerifiedStatus.VERIFIED);
|
||||||
|
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -667,7 +652,7 @@ describe('SignalProtocolStore', () => {
|
||||||
keychangeTriggered += 1;
|
keychangeTriggered += 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
timestamp: Date.now() - 10 * 1000 * 60,
|
timestamp: Date.now() - 10 * 1000 * 60,
|
||||||
|
@ -693,7 +678,7 @@ describe('SignalProtocolStore', () => {
|
||||||
assert.isFalse(needsNotification);
|
assert.isFalse(needsNotification);
|
||||||
assert.strictEqual(keychangeTriggered, 0);
|
assert.strictEqual(keychangeTriggered, 0);
|
||||||
|
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(newAci);
|
const identity = await DataReader.getIdentityKeyById(newAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -712,7 +697,7 @@ describe('SignalProtocolStore', () => {
|
||||||
assert.isTrue(needsNotification);
|
assert.isTrue(needsNotification);
|
||||||
assert.strictEqual(keychangeTriggered, 0);
|
assert.strictEqual(keychangeTriggered, 0);
|
||||||
|
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(newAci);
|
const identity = await DataReader.getIdentityKeyById(newAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -729,7 +714,7 @@ describe('SignalProtocolStore', () => {
|
||||||
assert.isFalse(needsNotification);
|
assert.isFalse(needsNotification);
|
||||||
assert.strictEqual(keychangeTriggered, 1);
|
assert.strictEqual(keychangeTriggered, 1);
|
||||||
|
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -746,7 +731,7 @@ describe('SignalProtocolStore', () => {
|
||||||
assert.isTrue(needsNotification);
|
assert.isTrue(needsNotification);
|
||||||
assert.strictEqual(keychangeTriggered, 0);
|
assert.strictEqual(keychangeTriggered, 0);
|
||||||
|
|
||||||
const identity = await window.Signal.Data.getIdentityKeyById(theirAci);
|
const identity = await DataReader.getIdentityKeyById(theirAci);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
throw new Error('Missing identity!');
|
throw new Error('Missing identity!');
|
||||||
}
|
}
|
||||||
|
@ -757,7 +742,7 @@ describe('SignalProtocolStore', () => {
|
||||||
|
|
||||||
describe('isUntrusted', () => {
|
describe('isUntrusted', () => {
|
||||||
it('returns false if identity key old enough', async () => {
|
it('returns false if identity key old enough', async () => {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
timestamp: Date.now() - 10 * 1000 * 60,
|
timestamp: Date.now() - 10 * 1000 * 60,
|
||||||
|
@ -772,7 +757,7 @@ describe('SignalProtocolStore', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if new but nonblockingApproval is true', async () => {
|
it('returns false if new but nonblockingApproval is true', async () => {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
|
@ -787,7 +772,7 @@ describe('SignalProtocolStore', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if new but firstUse is true', async () => {
|
it('returns false if new but firstUse is true', async () => {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
|
@ -802,7 +787,7 @@ describe('SignalProtocolStore', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if new, and no flags are set', async () => {
|
it('returns true if new, and no flags are set', async () => {
|
||||||
await window.Signal.Data.createOrUpdateIdentityKey({
|
await DataWriter.createOrUpdateIdentityKey({
|
||||||
id: theirAci,
|
id: theirAci,
|
||||||
publicKey: testKey.pubKey,
|
publicKey: testKey.pubKey,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { assert } from 'chai';
|
||||||
|
|
||||||
import type { ConversationModel } from '../../models/conversations';
|
import type { ConversationModel } from '../../models/conversations';
|
||||||
import * as Bytes from '../../Bytes';
|
import * as Bytes from '../../Bytes';
|
||||||
import Data from '../../sql/Client';
|
import { DataWriter } from '../../sql/Client';
|
||||||
import { type AciString, generateAci } from '../../types/ServiceId';
|
import { type AciString, generateAci } from '../../types/ServiceId';
|
||||||
import { ReadStatus } from '../../messages/MessageReadStatus';
|
import { ReadStatus } from '../../messages/MessageReadStatus';
|
||||||
import { SeenStatus } from '../../MessageSeenStatus';
|
import { SeenStatus } from '../../MessageSeenStatus';
|
||||||
|
@ -39,8 +39,8 @@ describe('backup/attachments', () => {
|
||||||
let contactA: ConversationModel;
|
let contactA: ConversationModel;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await Data._removeAllMessages();
|
await DataWriter._removeAllMessages();
|
||||||
await Data._removeAllConversations();
|
await DataWriter._removeAllConversations();
|
||||||
window.storage.reset();
|
window.storage.reset();
|
||||||
|
|
||||||
await setupBasics();
|
await setupBasics();
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import { v4 as generateGuid } from 'uuid';
|
import { v4 as generateGuid } from 'uuid';
|
||||||
|
|
||||||
import Data from '../../sql/Client';
|
import { DataWriter } from '../../sql/Client';
|
||||||
import { SignalService as Proto } from '../../protobuf';
|
import { SignalService as Proto } from '../../protobuf';
|
||||||
|
|
||||||
import { generateAci, generatePni } from '../../types/ServiceId';
|
import { generateAci, generatePni } from '../../types/ServiceId';
|
||||||
|
@ -73,8 +73,8 @@ function createMessage(
|
||||||
|
|
||||||
describe('backup/groupv2/notifications', () => {
|
describe('backup/groupv2/notifications', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await Data._removeAllMessages();
|
await DataWriter._removeAllMessages();
|
||||||
await Data._removeAllConversations();
|
await DataWriter._removeAllConversations();
|
||||||
window.storage.reset();
|
window.storage.reset();
|
||||||
|
|
||||||
await setupBasics();
|
await setupBasics();
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { SendStatus } from '../../messages/MessageSendState';
|
||||||
import type { ConversationModel } from '../../models/conversations';
|
import type { ConversationModel } from '../../models/conversations';
|
||||||
import { GiftBadgeStates } from '../../components/conversation/Message';
|
import { GiftBadgeStates } from '../../components/conversation/Message';
|
||||||
|
|
||||||
import Data from '../../sql/Client';
|
import { DataWriter } from '../../sql/Client';
|
||||||
import { getRandomBytes } from '../../Crypto';
|
import { getRandomBytes } from '../../Crypto';
|
||||||
import * as Bytes from '../../Bytes';
|
import * as Bytes from '../../Bytes';
|
||||||
import { generateAci } from '../../types/ServiceId';
|
import { generateAci } from '../../types/ServiceId';
|
||||||
|
@ -39,8 +39,8 @@ describe('backup/bubble messages', () => {
|
||||||
let gv1: ConversationModel;
|
let gv1: ConversationModel;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await Data._removeAllMessages();
|
await DataWriter._removeAllMessages();
|
||||||
await Data._removeAllConversations();
|
await DataWriter._removeAllConversations();
|
||||||
window.storage.reset();
|
window.storage.reset();
|
||||||
|
|
||||||
await setupBasics();
|
await setupBasics();
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Long from 'long';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
import { BackupLevel } from '@signalapp/libsignal-client/zkgroup';
|
import { BackupLevel } from '@signalapp/libsignal-client/zkgroup';
|
||||||
|
import { DataWriter } from '../../sql/Client';
|
||||||
import { Backups } from '../../protobuf';
|
import { Backups } from '../../protobuf';
|
||||||
import {
|
import {
|
||||||
getFilePointerForAttachment,
|
getFilePointerForAttachment,
|
||||||
|
@ -552,7 +553,7 @@ describe('getBackupJobForAttachmentAndFilePointer', async () => {
|
||||||
await window.storage.put('masterKey', Bytes.toBase64(getRandomBytes(32)));
|
await window.storage.put('masterKey', Bytes.toBase64(getRandomBytes(32)));
|
||||||
});
|
});
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await window.Signal.Data.removeAll();
|
await DataWriter.removeAll();
|
||||||
});
|
});
|
||||||
const attachment = composeAttachment();
|
const attachment = composeAttachment();
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import type {
|
||||||
import { backupsService } from '../../services/backups';
|
import { backupsService } from '../../services/backups';
|
||||||
import { isUnsupportedMessage } from '../../state/selectors/message';
|
import { isUnsupportedMessage } from '../../state/selectors/message';
|
||||||
import { generateAci, generatePni } from '../../types/ServiceId';
|
import { generateAci, generatePni } from '../../types/ServiceId';
|
||||||
import Data from '../../sql/Client';
|
import { DataReader, DataWriter } from '../../sql/Client';
|
||||||
import { getRandomBytes } from '../../Crypto';
|
import { getRandomBytes } from '../../Crypto';
|
||||||
import * as Bytes from '../../Bytes';
|
import * as Bytes from '../../Bytes';
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ export async function symmetricRoundtripHarness(
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateConvoIdToTitle() {
|
async function updateConvoIdToTitle() {
|
||||||
const all = await Data.getAllConversations();
|
const all = await DataReader.getAllConversations();
|
||||||
for (const convo of all) {
|
for (const convo of all) {
|
||||||
CONVO_ID_TO_STABLE_ID.set(
|
CONVO_ID_TO_STABLE_ID.set(
|
||||||
convo.id,
|
convo.id,
|
||||||
|
@ -167,7 +167,7 @@ export async function asymmetricRoundtripHarness(
|
||||||
try {
|
try {
|
||||||
const targetOutputFile = path.join(outDir, 'backup.bin');
|
const targetOutputFile = path.join(outDir, 'backup.bin');
|
||||||
|
|
||||||
await Data.saveMessages(before, { forceSave: true, ourAci: OUR_ACI });
|
await DataWriter.saveMessages(before, { forceSave: true, ourAci: OUR_ACI });
|
||||||
|
|
||||||
await backupsService.exportToDisk(targetOutputFile, options.backupLevel);
|
await backupsService.exportToDisk(targetOutputFile, options.backupLevel);
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ export async function asymmetricRoundtripHarness(
|
||||||
|
|
||||||
await backupsService.importBackup(() => createReadStream(targetOutputFile));
|
await backupsService.importBackup(() => createReadStream(targetOutputFile));
|
||||||
|
|
||||||
const messagesFromDatabase = await Data._getAllMessages();
|
const messagesFromDatabase = await DataReader._getAllMessages();
|
||||||
|
|
||||||
await updateConvoIdToTitle();
|
await updateConvoIdToTitle();
|
||||||
|
|
||||||
|
@ -199,9 +199,9 @@ export async function asymmetricRoundtripHarness(
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clearData() {
|
async function clearData() {
|
||||||
await Data._removeAllMessages();
|
await DataWriter._removeAllMessages();
|
||||||
await Data._removeAllConversations();
|
await DataWriter._removeAllConversations();
|
||||||
await Data.removeAllItems();
|
await DataWriter.removeAllItems();
|
||||||
window.storage.reset();
|
window.storage.reset();
|
||||||
window.ConversationController.reset();
|
window.ConversationController.reset();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import type { ConversationModel } from '../../models/conversations';
|
||||||
import { getRandomBytes } from '../../Crypto';
|
import { getRandomBytes } from '../../Crypto';
|
||||||
import * as Bytes from '../../Bytes';
|
import * as Bytes from '../../Bytes';
|
||||||
import { SignalService as Proto, Backups } from '../../protobuf';
|
import { SignalService as Proto, Backups } from '../../protobuf';
|
||||||
import Data from '../../sql/Client';
|
import { DataWriter } from '../../sql/Client';
|
||||||
import { generateAci } from '../../types/ServiceId';
|
import { generateAci } from '../../types/ServiceId';
|
||||||
import { PaymentEventKind } from '../../types/Payment';
|
import { PaymentEventKind } from '../../types/Payment';
|
||||||
import { ContactFormType } from '../../types/EmbeddedContact';
|
import { ContactFormType } from '../../types/EmbeddedContact';
|
||||||
|
@ -32,8 +32,8 @@ describe('backup/non-bubble messages', () => {
|
||||||
let group: ConversationModel;
|
let group: ConversationModel;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await Data._removeAllMessages();
|
await DataWriter._removeAllMessages();
|
||||||
await Data._removeAllConversations();
|
await DataWriter._removeAllConversations();
|
||||||
window.storage.reset();
|
window.storage.reset();
|
||||||
|
|
||||||
await setupBasics();
|
await setupBasics();
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import { assert } from 'chai';
|
import { assert } from 'chai';
|
||||||
import { v4 as generateUuid } from 'uuid';
|
import { v4 as generateUuid } from 'uuid';
|
||||||
|
|
||||||
|
import { DataWriter } from '../../sql/Client';
|
||||||
import { SendStatus } from '../../messages/MessageSendState';
|
import { SendStatus } from '../../messages/MessageSendState';
|
||||||
import { IMAGE_PNG } from '../../types/MIME';
|
import { IMAGE_PNG } from '../../types/MIME';
|
||||||
import { generateAci, generatePni } from '../../types/ServiceId';
|
import { generateAci, generatePni } from '../../types/ServiceId';
|
||||||
|
@ -79,7 +80,7 @@ describe('Conversations', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Saving to db and updating the convo's last message
|
// Saving to db and updating the convo's last message
|
||||||
await window.Signal.Data.saveMessage(message.attributes, {
|
await DataWriter.saveMessage(message.attributes, {
|
||||||
forceSave: true,
|
forceSave: true,
|
||||||
ourAci,
|
ourAci,
|
||||||
});
|
});
|
||||||
|
@ -88,7 +89,7 @@ describe('Conversations', () => {
|
||||||
message,
|
message,
|
||||||
'test'
|
'test'
|
||||||
);
|
);
|
||||||
await window.Signal.Data.updateConversation(conversation.attributes);
|
await DataWriter.updateConversation(conversation.attributes);
|
||||||
await conversation.updateLastMessage();
|
await conversation.updateLastMessage();
|
||||||
|
|
||||||
// Should be set to bananas because that's the last message sent.
|
// Should be set to bananas because that's the last message sent.
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue