Migrate messages, conversations, conversation_view, background to TS
Co-authored-by: Sidney Keese <sidney@carbonfive.com>
This commit is contained in:
parent
6e7930f7a9
commit
b5df9b4067
42 changed files with 11676 additions and 10516 deletions
|
@ -326,6 +326,7 @@
|
|||
</script>
|
||||
|
||||
<script type='text/javascript' src='js/components.js'></script>
|
||||
<script type='text/javascript' src='ts/backboneJquery.js'></script>
|
||||
<script type='text/javascript' src='js/reliable_trigger.js'></script>
|
||||
<script type='text/javascript' src='js/database.js'></script>
|
||||
<script type='text/javascript' src='js/storage.js'></script>
|
||||
|
@ -341,8 +342,6 @@
|
|||
<script type='text/javascript' src='js/reactions.js'></script>
|
||||
<script type='text/javascript' src='js/deletes.js'></script>
|
||||
<script type='text/javascript' src='js/libphonenumber-util.js'></script>
|
||||
<script type='text/javascript' src='js/models/messages.js'></script>
|
||||
<script type='text/javascript' src='js/models/conversations.js'></script>
|
||||
<script type='text/javascript' src='js/models/blockedNumbers.js'></script>
|
||||
<script type='text/javascript' src='js/expiring_messages.js'></script>
|
||||
<script type='text/javascript' src='js/expiring_tap_to_view_messages.js'></script>
|
||||
|
@ -358,7 +357,7 @@
|
|||
<script type='text/javascript' src='js/views/key_verification_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/group_member_list_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/recorder_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/conversation_view.js'></script>
|
||||
<script type='text/javascript' src='ts/views/conversation_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/inbox_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/confirmation_dialog_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/identicon_svg_view.js'></script>
|
||||
|
@ -387,6 +386,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script type='text/javascript' src='js/background.js'></script>
|
||||
<script type='text/javascript' src='ts/background.js'></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
"license": "GPLV3",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"indexeddb-backbonejs-adapter": "*",
|
||||
"mp3lameencoder": "https://github.com/higuma/mp3-lame-encoder-js.git",
|
||||
"protobuf": "~3.8.0",
|
||||
"qrcode": "https://github.com/davidshimjs/qrcodejs.git#1c78ccd71",
|
||||
|
@ -18,9 +17,6 @@
|
|||
"bytebuffer": [
|
||||
"dist/ByteBufferAB.js"
|
||||
],
|
||||
"indexeddb-backbonejs-adapter": [
|
||||
"backbone-indexeddb.js"
|
||||
],
|
||||
"long": [
|
||||
"dist/Long.js"
|
||||
],
|
||||
|
@ -49,8 +45,6 @@
|
|||
"components/protobuf/**/*.js",
|
||||
"node_modules/mustache/mustache.js",
|
||||
"node_modules/underscore/underscore.js",
|
||||
"node_modules/backbone/backbone.js",
|
||||
"components/indexeddb-backbonejs-adapter/**/*.js",
|
||||
"components/qrcode/**/*.js",
|
||||
"node_modules/intl-tel-input/build/js/intlTelInput.js",
|
||||
"components/autosize/**/*.js",
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
{{ toastMessage }}
|
||||
</script>
|
||||
<script type='text/javascript' src='js/components.js'></script>
|
||||
<script type='text/javascript' src='ts/backboneJquery.js'></script>
|
||||
<script type='text/javascript' src='js/views/whisper_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/toast_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/debug_log_view.js'></script>
|
||||
|
|
|
@ -23,3 +23,4 @@ window.getEnvironment = () => config.environment;
|
|||
require('./js/logging');
|
||||
|
||||
window.closeDebugLog = () => ipcRenderer.send('close-debug-log');
|
||||
window.Backbone = require('backbone');
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -19,6 +19,7 @@
|
|||
<div class="message"></div>
|
||||
</div>
|
||||
<script type="text/javascript" src="js/components.js"></script>
|
||||
<script type='text/javascript' src='ts/backboneJquery.js'></script>
|
||||
<script type="text/javascript" src="js/loading_start.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -10,3 +10,4 @@ const { locale } = config;
|
|||
const localeMessages = ipcRenderer.sendSync('locale-data');
|
||||
|
||||
window.i18n = i18n.setup(locale, localeMessages);
|
||||
window.Backbone = require('backbone');
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
</div>
|
||||
</script>
|
||||
<script type='text/javascript' src='js/components.js'></script>
|
||||
<script type='text/javascript' src='ts/backboneJquery.js'></script>
|
||||
<script type='text/javascript' src='js/views/whisper_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/confirmation_dialog_view.js'></script>
|
||||
<script type='text/javascript' src='js/permissions_popup_start.js'></script>
|
||||
|
|
|
@ -40,3 +40,4 @@ window.setMediaPermissions = makeSetter('media-permissions');
|
|||
window.setMediaCameraPermissions = makeSetter('media-camera-permissions');
|
||||
window.getThemeSetting = makeGetter('theme-setting');
|
||||
window.setThemeSetting = makeSetter('theme-setting');
|
||||
window.Backbone = require('backbone');
|
||||
|
|
|
@ -424,6 +424,7 @@ try {
|
|||
window.ReactDOM = require('react-dom');
|
||||
window.moment = require('moment');
|
||||
window.PQueue = require('p-queue').default;
|
||||
window.Backbone = require('backbone');
|
||||
|
||||
const Signal = require('./js/modules/signal');
|
||||
const i18n = require('./js/modules/i18n');
|
||||
|
@ -452,6 +453,10 @@ try {
|
|||
logger: window.log,
|
||||
});
|
||||
|
||||
// these need access to window.Signal:
|
||||
require('./ts/models/messages');
|
||||
require('./ts/models/conversations');
|
||||
|
||||
function wrapWithPromise(fn) {
|
||||
return (...args) => Promise.resolve(fn(...args));
|
||||
}
|
||||
|
|
|
@ -164,6 +164,7 @@
|
|||
</div>
|
||||
</script>
|
||||
<script type='text/javascript' src='js/components.js'></script>
|
||||
<script type='text/javascript' src='ts/backboneJquery.js'></script>
|
||||
<script type='text/javascript' src='js/views/whisper_view.js'></script>
|
||||
<script type='text/javascript' src='js/views/settings_view.js'></script>
|
||||
<script type='text/javascript' src='js/settings_start.js'></script>
|
||||
|
|
|
@ -118,3 +118,5 @@ function makeSetter(name) {
|
|||
}
|
||||
|
||||
require('./js/logging');
|
||||
|
||||
window.Backbone = require('backbone');
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<div id="root"></div>
|
||||
<script type="text/javascript" src="../../js/components.js"></script>
|
||||
<script type="text/javascript" src="../../js/signal_protocol_store.js"></script>
|
||||
<script type="text/javascript" src="../../ts/backbonejQuery.js"></script>
|
||||
<script type="text/javascript" src="../../js/storage.js"></script>
|
||||
<script type="text/javascript" src="../../js/libtextsecure.js"></script>
|
||||
</body>
|
||||
|
|
|
@ -18,6 +18,7 @@ window.getEnvironment = () => config.environment;
|
|||
window.getVersion = () => config.version;
|
||||
window.getGuid = require('uuid/v4');
|
||||
window.PQueue = require('p-queue').default;
|
||||
window.Backbone = require('backbone');
|
||||
|
||||
window.localeMessages = ipc.sendSync('locale-data');
|
||||
|
||||
|
|
|
@ -332,6 +332,7 @@
|
|||
<script type="text/javascript" src="../libtextsecure/test/fake_web_api.js"></script>
|
||||
|
||||
<script type="text/javascript" src="../js/components.js"></script>
|
||||
<script type='text/javascript' src='../ts/backboneJquery.js'></script>
|
||||
<script type="text/javascript" src="../js/reliable_trigger.js" data-cover></script>
|
||||
<script type="text/javascript" src="test.js"></script>
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@ import { debounce, reduce, uniq, without } from 'lodash';
|
|||
import dataInterface from './sql/Client';
|
||||
import {
|
||||
ConversationModelCollectionType,
|
||||
ConversationModelType,
|
||||
ConversationTypeType,
|
||||
WhatIsThis,
|
||||
ConversationAttributesTypeType,
|
||||
} from './model-types.d';
|
||||
import { SendOptionsType } from './textsecure/SendMessage';
|
||||
import { SendOptionsType, CallbackResultType } from './textsecure/SendMessage';
|
||||
import { ConversationModel } from './models/conversations';
|
||||
|
||||
const MAX_MESSAGE_BODY_LENGTH = 64 * 1024;
|
||||
|
||||
|
@ -40,7 +41,7 @@ export function start(): void {
|
|||
this.on('add remove change:unreadCount', debouncedUpdateUnreadCount);
|
||||
window.Whisper.events.on('updateUnreadCount', debouncedUpdateUnreadCount);
|
||||
},
|
||||
addActive(model: ConversationModelType) {
|
||||
addActive(model: ConversationModel) {
|
||||
if (model.get('active_at')) {
|
||||
this.add(model);
|
||||
} else {
|
||||
|
@ -52,7 +53,7 @@ export function start(): void {
|
|||
'badge-count-muted-conversations'
|
||||
);
|
||||
const newUnreadCount = reduce(
|
||||
this.map((m: ConversationModelType) =>
|
||||
this.map((m: ConversationModel) =>
|
||||
!canCountMutedConversations && m.isMuted() ? 0 : m.get('unreadCount')
|
||||
),
|
||||
(item: number, memo: number) => (item || 0) + memo,
|
||||
|
@ -91,7 +92,7 @@ export class ConversationController {
|
|||
this._conversations = conversations;
|
||||
}
|
||||
|
||||
get(id?: string | null): ConversationModelType | undefined {
|
||||
get(id?: string | null): ConversationModel | undefined {
|
||||
if (!this._initialFetchComplete) {
|
||||
throw new Error(
|
||||
'ConversationController.get() needs complete initial fetch'
|
||||
|
@ -103,16 +104,16 @@ export class ConversationController {
|
|||
}
|
||||
|
||||
dangerouslyCreateAndAdd(
|
||||
attributes: Partial<ConversationModelType>
|
||||
): ConversationModelType {
|
||||
attributes: Partial<ConversationModel>
|
||||
): ConversationModel {
|
||||
return this._conversations.add(attributes);
|
||||
}
|
||||
|
||||
getOrCreate(
|
||||
identifier: string,
|
||||
type: ConversationTypeType,
|
||||
identifier: string | null,
|
||||
type: ConversationAttributesTypeType,
|
||||
additionalInitialProps = {}
|
||||
): ConversationModelType {
|
||||
): ConversationModel {
|
||||
if (typeof identifier !== 'string') {
|
||||
throw new TypeError("'id' must be a string");
|
||||
}
|
||||
|
@ -202,10 +203,10 @@ export class ConversationController {
|
|||
}
|
||||
|
||||
async getOrCreateAndWait(
|
||||
id: string,
|
||||
type: ConversationTypeType,
|
||||
id: string | null,
|
||||
type: ConversationAttributesTypeType,
|
||||
additionalInitialProps = {}
|
||||
): Promise<ConversationModelType> {
|
||||
): Promise<ConversationModel> {
|
||||
await this._initialPromise;
|
||||
const conversation = this.getOrCreate(id, type, additionalInitialProps);
|
||||
|
||||
|
@ -217,7 +218,7 @@ export class ConversationController {
|
|||
throw new Error('getOrCreateAndWait: did not get conversation');
|
||||
}
|
||||
|
||||
getConversationId(address: string): string | null {
|
||||
getConversationId(address: string | null): string | null {
|
||||
if (!address) {
|
||||
return null;
|
||||
}
|
||||
|
@ -251,8 +252,8 @@ export class ConversationController {
|
|||
uuid,
|
||||
highTrust,
|
||||
}: {
|
||||
e164?: string;
|
||||
uuid?: string;
|
||||
e164?: string | null;
|
||||
uuid?: string | null;
|
||||
highTrust?: boolean;
|
||||
}): string | undefined {
|
||||
// Check for at least one parameter being provided. This is necessary
|
||||
|
@ -488,8 +489,8 @@ export class ConversationController {
|
|||
}
|
||||
|
||||
async combineContacts(
|
||||
current: ConversationModelType,
|
||||
obsolete: ConversationModelType
|
||||
current: ConversationModel,
|
||||
obsolete: ConversationModel
|
||||
): Promise<void> {
|
||||
const obsoleteId = obsolete.get('id');
|
||||
const currentId = current.get('id');
|
||||
|
@ -503,7 +504,11 @@ export class ConversationController {
|
|||
'combineContacts: Copying profile key from old to new contact'
|
||||
);
|
||||
|
||||
await current.setProfileKey(obsolete.get('profileKey'));
|
||||
const profileKey = obsolete.get('profileKey');
|
||||
|
||||
if (profileKey) {
|
||||
await current.setProfileKey(profileKey);
|
||||
}
|
||||
}
|
||||
|
||||
window.log.warn(
|
||||
|
@ -583,7 +588,7 @@ export class ConversationController {
|
|||
async getConversationForTargetMessage(
|
||||
targetFromId: string,
|
||||
targetTimestamp: number
|
||||
): Promise<boolean | ConversationModelType | null | undefined> {
|
||||
): Promise<boolean | ConversationModel | null | undefined> {
|
||||
const messages = await getMessagesBySentAt(targetTimestamp, {
|
||||
MessageCollection: window.Whisper.MessageCollection,
|
||||
});
|
||||
|
@ -605,11 +610,13 @@ export class ConversationController {
|
|||
return null;
|
||||
}
|
||||
|
||||
prepareForSend<T>(
|
||||
id: string,
|
||||
options?: unknown
|
||||
prepareForSend(
|
||||
id: string | undefined,
|
||||
options?: WhatIsThis
|
||||
): {
|
||||
wrap: (promise: Promise<T>) => Promise<T>;
|
||||
wrap: (
|
||||
promise: Promise<CallbackResultType | void | null>
|
||||
) => Promise<CallbackResultType | void | null>;
|
||||
sendOptions: SendOptionsType | undefined;
|
||||
} {
|
||||
// id is any valid conversation identifier
|
||||
|
@ -619,14 +626,14 @@ export class ConversationController {
|
|||
: undefined;
|
||||
const wrap = conversation
|
||||
? conversation.wrapSend.bind(conversation)
|
||||
: async (promise: Promise<T>) => promise;
|
||||
: async (promise: Promise<CallbackResultType | void | null>) => promise;
|
||||
|
||||
return { wrap, sendOptions };
|
||||
}
|
||||
|
||||
async getAllGroupsInvolvingId(
|
||||
conversationId: string
|
||||
): Promise<Array<ConversationModelType>> {
|
||||
): Promise<Array<ConversationModel>> {
|
||||
const groups = await getAllGroupsInvolvingId(conversationId, {
|
||||
ConversationCollection: window.Whisper.ConversationCollection,
|
||||
});
|
||||
|
|
3
ts/backboneJquery.ts
Normal file
3
ts/backboneJquery.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
// we are requiring backbone in preload.js, and we need to tell backbone where
|
||||
// jquery is after it's loaded.
|
||||
window.Backbone.$ = window.Backbone.$ || window.$;
|
File diff suppressed because it is too large
Load diff
|
@ -15,8 +15,10 @@ interface Contact {
|
|||
isMe?: boolean;
|
||||
}
|
||||
|
||||
export type ChangeType = 'add' | 'remove' | 'name' | 'avatar' | 'general';
|
||||
|
||||
interface Change {
|
||||
type: 'add' | 'remove' | 'name' | 'avatar' | 'general';
|
||||
type: ChangeType;
|
||||
newName?: string;
|
||||
contacts?: Array<Contact>;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,14 @@ import { ContactName } from './ContactName';
|
|||
import { Intl } from '../Intl';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
export type TimerNotificationType =
|
||||
| 'fromOther'
|
||||
| 'fromMe'
|
||||
| 'fromSync'
|
||||
| 'fromMember';
|
||||
|
||||
export type PropsData = {
|
||||
type: 'fromOther' | 'fromMe' | 'fromSync' | 'fromMember';
|
||||
type: TimerNotificationType;
|
||||
phoneNumber?: string;
|
||||
profileName?: string;
|
||||
title: string;
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
} from './services/groupCredentialFetcher';
|
||||
import {
|
||||
ConversationAttributesType,
|
||||
ConversationModelType,
|
||||
GroupV2MemberType,
|
||||
GroupV2PendingMemberType,
|
||||
MessageAttributesType,
|
||||
|
@ -50,6 +49,7 @@ import {
|
|||
} from './textsecure.d';
|
||||
import { GroupCredentialsType } from './textsecure/WebAPI';
|
||||
import { CURRENT_SCHEMA_VERSION as MAX_MESSAGE_SCHEMA } from '../js/modules/types/message';
|
||||
import { ConversationModel } from './models/conversations';
|
||||
|
||||
export type GroupV2AccessAttributesChangeType = {
|
||||
type: 'access-attributes';
|
||||
|
@ -265,7 +265,7 @@ export function deriveGroupFields(
|
|||
// Fetching and applying group changes
|
||||
|
||||
type MaybeUpdatePropsType = {
|
||||
conversation: ConversationModelType;
|
||||
conversation: ConversationModel;
|
||||
groupChangeBase64?: string;
|
||||
newRevision?: number;
|
||||
receivedAt?: number;
|
||||
|
@ -548,7 +548,8 @@ function generateBasicMessage() {
|
|||
return {
|
||||
id: getGuid(),
|
||||
schemaVersion: MAX_MESSAGE_SCHEMA,
|
||||
};
|
||||
// this is missing most properties to fulfill this type
|
||||
} as MessageAttributesType;
|
||||
}
|
||||
|
||||
function generateLeftGroupChanges(
|
||||
|
|
218
ts/model-types.d.ts
vendored
218
ts/model-types.d.ts
vendored
|
@ -1,17 +1,27 @@
|
|||
import * as Backbone from 'backbone';
|
||||
|
||||
import { GroupV2ChangeType } from './groups';
|
||||
import { LocalizerType } from './types/Util';
|
||||
import { LocalizerType, BodyRangesType } from './types/Util';
|
||||
import { CallHistoryDetailsType } from './types/Calling';
|
||||
import { ColorType } from './types/Colors';
|
||||
import { ConversationType } from './state/ducks/conversations';
|
||||
import {
|
||||
ConversationType,
|
||||
MessageType,
|
||||
LastMessageStatus,
|
||||
} from './state/ducks/conversations';
|
||||
import { SendOptionsType } from './textsecure/SendMessage';
|
||||
import { SyncMessageClass } from './textsecure.d';
|
||||
import { UserMessage } from './types/Message';
|
||||
import { MessageModel } from './models/messages';
|
||||
import { ConversationModel } from './models/conversations';
|
||||
import { ProfileNameChangeType } from './util/getStringForProfileChange';
|
||||
|
||||
interface ModelAttributesInterface {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export type WhatIsThis = any;
|
||||
|
||||
type DeletesAttributesType = {
|
||||
fromId: string;
|
||||
serverTimestamp: number;
|
||||
|
@ -21,18 +31,89 @@ type DeletesAttributesType = {
|
|||
export declare class DeletesModelType extends Backbone.Model<
|
||||
DeletesAttributesType
|
||||
> {
|
||||
forMessage(message: MessageModelType): Array<DeletesModelType>;
|
||||
forMessage(message: MessageModel): Array<DeletesModelType>;
|
||||
onDelete(doe: DeletesAttributesType): Promise<void>;
|
||||
}
|
||||
|
||||
type TaskResultType = any;
|
||||
|
||||
export interface CustomError extends Error {
|
||||
identifier?: string;
|
||||
number?: string;
|
||||
}
|
||||
|
||||
export type MessageAttributesType = {
|
||||
bodyPending: boolean;
|
||||
bodyRanges: BodyRangesType;
|
||||
callHistoryDetails: CallHistoryDetailsType;
|
||||
changedId: string;
|
||||
dataMessage: ArrayBuffer | null;
|
||||
decrypted_at: number;
|
||||
deletedForEveryone: boolean;
|
||||
delivered: number;
|
||||
delivered_to: Array<string | null>;
|
||||
errors: Array<CustomError> | null;
|
||||
expirationStartTimestamp: number | null;
|
||||
expireTimer: number;
|
||||
expires_at: number;
|
||||
group_update: {
|
||||
avatarUpdated: boolean;
|
||||
joined: Array<string>;
|
||||
left: string | 'You';
|
||||
name: string;
|
||||
};
|
||||
hasAttachments: boolean;
|
||||
hasFileAttachments: boolean;
|
||||
hasVisualMediaAttachments: boolean;
|
||||
isErased: boolean;
|
||||
isTapToViewInvalid: boolean;
|
||||
isViewOnce: boolean;
|
||||
key_changed: string;
|
||||
local: boolean;
|
||||
logger: unknown;
|
||||
message: unknown;
|
||||
messageTimer: unknown;
|
||||
profileChange: ProfileNameChangeType;
|
||||
quote: {
|
||||
attachments: Array<typeof window.WhatIsThis>;
|
||||
author: string;
|
||||
authorUuid: string;
|
||||
bodyRanges: BodyRangesType;
|
||||
id: string;
|
||||
referencedMessageNotFound: boolean;
|
||||
text: string;
|
||||
} | null;
|
||||
reactions: Array<{ fromId: string; emoji: unknown; timestamp: unknown }>;
|
||||
read_by: Array<string | null>;
|
||||
requiredProtocolVersion: number;
|
||||
sent: boolean;
|
||||
sourceDevice: string | number;
|
||||
snippet: unknown;
|
||||
supportedVersionAtReceive: unknown;
|
||||
synced: boolean;
|
||||
unidentifiedDeliveryReceived: boolean;
|
||||
verified: boolean;
|
||||
verifiedChanged: string;
|
||||
|
||||
id: string;
|
||||
type?: string;
|
||||
body: string;
|
||||
attachments: Array<WhatIsThis>;
|
||||
preview: Array<WhatIsThis>;
|
||||
sticker: WhatIsThis;
|
||||
sent_at: WhatIsThis;
|
||||
sent_to: Array<string>;
|
||||
unidentifiedDeliveries: Array<string>;
|
||||
contact: Array<WhatIsThis>;
|
||||
conversationId: string;
|
||||
recipients: Array<WhatIsThis>;
|
||||
reaction: WhatIsThis;
|
||||
destination?: WhatIsThis;
|
||||
destinationUuid?: string;
|
||||
|
||||
expirationTimerUpdate?: {
|
||||
expireTimer: number;
|
||||
fromSync?: unknown;
|
||||
source?: string;
|
||||
sourceUuid?: string;
|
||||
};
|
||||
|
@ -46,39 +127,47 @@ export type MessageAttributesType = {
|
|||
// We set this so that the idle message upgrade process doesn't pick this message up
|
||||
schemaVersion: number;
|
||||
serverTimestamp?: number;
|
||||
source?: string;
|
||||
sourceUuid?: string;
|
||||
|
||||
unread: number;
|
||||
timestamp: number;
|
||||
};
|
||||
|
||||
export declare class MessageModelType extends Backbone.Model<
|
||||
MessageAttributesType
|
||||
> {
|
||||
id: string;
|
||||
|
||||
static updateTimers(): void;
|
||||
|
||||
getContact(): ConversationModelType | undefined | null;
|
||||
getConversation(): ConversationModelType | undefined | null;
|
||||
getPropsForSearchResult(): any;
|
||||
getPropsForBubble(): any;
|
||||
cleanup(): Promise<void>;
|
||||
handleDeleteForEveryone(
|
||||
doe: DeletesModelType,
|
||||
shouldPersist: boolean
|
||||
): Promise<void>;
|
||||
}
|
||||
|
||||
export type ConversationTypeType = 'private' | 'group';
|
||||
export type ConversationAttributesTypeType = 'private' | 'group';
|
||||
|
||||
export type ConversationAttributesType = {
|
||||
accessKey: string | null;
|
||||
addedBy: string;
|
||||
capabilities: { uuid: string };
|
||||
color?: ColorType;
|
||||
discoveredUnregisteredAt: number;
|
||||
draftAttachments: Array<unknown>;
|
||||
draftTimestamp: number | null;
|
||||
inbox_position: number;
|
||||
lastMessageDeletedForEveryone: unknown;
|
||||
lastMessageStatus: LastMessageStatus | null;
|
||||
messageCount: number;
|
||||
messageCountBeforeMessageRequests: number;
|
||||
messageRequestResponseType: number;
|
||||
muteExpiresAt: number;
|
||||
profileAvatar: WhatIsThis;
|
||||
profileKeyCredential: unknown | null;
|
||||
profileKeyVersion: string;
|
||||
quotedMessageId: string;
|
||||
sealedSender: unknown;
|
||||
sentMessageCount: number;
|
||||
sharedGroupNames: Array<string>;
|
||||
|
||||
id: string;
|
||||
type: ConversationTypeType;
|
||||
timestamp: number;
|
||||
type: ConversationAttributesTypeType;
|
||||
timestamp: number | null;
|
||||
|
||||
// Shared fields
|
||||
active_at?: number | null;
|
||||
draft?: string;
|
||||
draft?: string | null;
|
||||
isArchived?: boolean;
|
||||
lastMessage?: string;
|
||||
lastMessage?: string | null;
|
||||
name?: string;
|
||||
needsStorageServiceSync?: boolean;
|
||||
needsVerification?: boolean;
|
||||
|
@ -93,9 +182,9 @@ export type ConversationAttributesType = {
|
|||
e164?: string;
|
||||
|
||||
// Private other fields
|
||||
profileFamilyName?: string | null;
|
||||
profileKey?: string | null;
|
||||
profileName?: string | null;
|
||||
profileFamilyName?: string;
|
||||
profileKey?: string;
|
||||
profileName?: string;
|
||||
verified?: number;
|
||||
|
||||
// Group-only
|
||||
|
@ -121,7 +210,7 @@ export type ConversationAttributesType = {
|
|||
url: string;
|
||||
path: string;
|
||||
hash: string;
|
||||
};
|
||||
} | null;
|
||||
expireTimer?: number;
|
||||
membersV2?: Array<GroupV2MemberType>;
|
||||
pendingMembersV2?: Array<GroupV2PendingMemberType>;
|
||||
|
@ -138,80 +227,19 @@ export type GroupV2PendingMemberType = {
|
|||
timestamp: number;
|
||||
};
|
||||
|
||||
type VerificationOptions = {
|
||||
export type VerificationOptions = {
|
||||
key?: null | ArrayBuffer;
|
||||
viaContactSync?: boolean;
|
||||
viaStorageServiceSync?: boolean;
|
||||
viaSyncMessage?: boolean;
|
||||
};
|
||||
|
||||
export declare class ConversationModelType extends Backbone.Model<
|
||||
ConversationAttributesType
|
||||
> {
|
||||
id: string;
|
||||
cachedProps: ConversationType;
|
||||
initialPromise: Promise<any>;
|
||||
messageRequestEnum: typeof SyncMessageClass.MessageRequestResponse.Type;
|
||||
|
||||
addCallHistory(details: CallHistoryDetailsType): void;
|
||||
applyMessageRequestResponse(
|
||||
response: number,
|
||||
options?: { fromSync: boolean; viaStorageServiceSync?: boolean }
|
||||
): void;
|
||||
cleanup(): Promise<void>;
|
||||
disableProfileSharing(options?: { viaStorageServiceSync?: boolean }): void;
|
||||
dropProfileKey(): Promise<void>;
|
||||
enableProfileSharing(options?: { viaStorageServiceSync?: boolean }): void;
|
||||
generateProps(): void;
|
||||
getAccepted(): boolean;
|
||||
getAvatarPath(): string | undefined;
|
||||
getColor(): ColorType | undefined;
|
||||
getName(): string | undefined;
|
||||
getNumber(): string;
|
||||
getProfileName(): string | undefined;
|
||||
getProfiles(): Promise<Array<Promise<void>>>;
|
||||
getRecipients: () => Array<string>;
|
||||
getSendOptions(options?: any): SendOptionsType | undefined;
|
||||
getTitle(): string;
|
||||
idForLogging(): string;
|
||||
debugID(): string;
|
||||
isFromOrAddedByTrustedContact(): boolean;
|
||||
isBlocked(): boolean;
|
||||
isMe(): boolean;
|
||||
isMuted(): boolean;
|
||||
isPrivate(): boolean;
|
||||
isVerified(): boolean;
|
||||
maybeRepairGroupV2(data: {
|
||||
masterKey: string;
|
||||
secretParams: string;
|
||||
publicParams: string;
|
||||
}): void;
|
||||
queueJob(job: () => Promise<void>): Promise<void>;
|
||||
safeGetVerified(): Promise<number>;
|
||||
setArchived(isArchived: boolean): void;
|
||||
setProfileKey(
|
||||
profileKey?: string | null,
|
||||
options?: { viaStorageServiceSync?: boolean }
|
||||
): Promise<void>;
|
||||
setProfileAvatar(avatarPath: string): Promise<void>;
|
||||
setUnverified(options: VerificationOptions): Promise<TaskResultType>;
|
||||
setVerified(options: VerificationOptions): Promise<TaskResultType>;
|
||||
setVerifiedDefault(options: VerificationOptions): Promise<TaskResultType>;
|
||||
toggleVerified(): Promise<TaskResultType>;
|
||||
block(options?: { viaStorageServiceSync?: boolean }): void;
|
||||
unblock(options?: { viaStorageServiceSync?: boolean }): boolean;
|
||||
updateE164: (e164?: string) => void;
|
||||
updateLastMessage: () => Promise<void>;
|
||||
updateUuid: (uuid?: string) => void;
|
||||
wrapSend: (sendPromise: Promise<any>) => Promise<any>;
|
||||
}
|
||||
|
||||
export declare class ConversationModelCollectionType extends Backbone.Collection<
|
||||
ConversationModelType
|
||||
ConversationModel
|
||||
> {
|
||||
resetLookups(): void;
|
||||
}
|
||||
|
||||
declare class MessageModelCollectionType extends Backbone.Collection<
|
||||
MessageModelType
|
||||
export declare class MessageModelCollectionType extends Backbone.Collection<
|
||||
MessageModel
|
||||
> {}
|
||||
|
|
3673
ts/models/conversations.ts
Normal file
3673
ts/models/conversations.ts
Normal file
File diff suppressed because it is too large
Load diff
3420
ts/models/messages.ts
Normal file
3420
ts/models/messages.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -22,12 +22,12 @@ import {
|
|||
CallDetailsType,
|
||||
} from '../state/ducks/calling';
|
||||
import { CallingMessageClass, EnvelopeClass } from '../textsecure.d';
|
||||
import { ConversationModelType } from '../model-types.d';
|
||||
import {
|
||||
AudioDevice,
|
||||
CallHistoryDetailsType,
|
||||
MediaDeviceSettings,
|
||||
} from '../types/Calling';
|
||||
import { ConversationModel } from '../models/conversations';
|
||||
|
||||
export {
|
||||
CallState,
|
||||
|
@ -87,7 +87,7 @@ export class CallingClass {
|
|||
}
|
||||
|
||||
async startOutgoingCall(
|
||||
conversation: ConversationModelType,
|
||||
conversation: ConversationModel,
|
||||
isVideoCall: boolean
|
||||
): Promise<void> {
|
||||
window.log.info('CallingClass.startOutgoingCall()');
|
||||
|
@ -626,7 +626,7 @@ export class CallingClass {
|
|||
this.addCallHistoryForAutoEndedIncomingCall(conversation, reason);
|
||||
}
|
||||
|
||||
private attachToCall(conversation: ConversationModelType, call: Call): void {
|
||||
private attachToCall(conversation: ConversationModel, call: Call): void {
|
||||
const { uxActions } = this;
|
||||
if (!uxActions) {
|
||||
return;
|
||||
|
@ -679,8 +679,8 @@ export class CallingClass {
|
|||
}
|
||||
|
||||
private getRemoteUserIdFromConversation(
|
||||
conversation: ConversationModelType
|
||||
): UserId | undefined {
|
||||
conversation: ConversationModel
|
||||
): UserId | undefined | null {
|
||||
const recipients = conversation.getRecipients();
|
||||
if (recipients.length !== 1) {
|
||||
return undefined;
|
||||
|
@ -705,7 +705,7 @@ export class CallingClass {
|
|||
}
|
||||
|
||||
private async getCallSettings(
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): Promise<CallSettings> {
|
||||
if (!window.textsecure.messaging) {
|
||||
throw new Error('getCallSettings: offline!');
|
||||
|
@ -725,9 +725,12 @@ export class CallingClass {
|
|||
}
|
||||
|
||||
private getUxCallDetails(
|
||||
conversation: ConversationModelType,
|
||||
conversation: ConversationModel,
|
||||
call: Call
|
||||
): CallDetailsType {
|
||||
// Does not meet CallDetailsType interface requirements
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
return {
|
||||
...conversation.cachedProps,
|
||||
|
||||
|
@ -738,7 +741,7 @@ export class CallingClass {
|
|||
}
|
||||
|
||||
private addCallHistoryForEndedCall(
|
||||
conversation: ConversationModelType,
|
||||
conversation: ConversationModel,
|
||||
call: Call,
|
||||
acceptedTimeParam: number | undefined
|
||||
) {
|
||||
|
@ -770,7 +773,7 @@ export class CallingClass {
|
|||
}
|
||||
|
||||
private addCallHistoryForFailedIncomingCall(
|
||||
conversation: ConversationModelType,
|
||||
conversation: ConversationModel,
|
||||
call: Call
|
||||
) {
|
||||
const callHistoryDetails: CallHistoryDetailsType = {
|
||||
|
@ -785,7 +788,7 @@ export class CallingClass {
|
|||
}
|
||||
|
||||
private addCallHistoryForAutoEndedIncomingCall(
|
||||
conversation: ConversationModelType,
|
||||
conversation: ConversationModel,
|
||||
_reason: CallEndedReason
|
||||
) {
|
||||
const callHistoryDetails: CallHistoryDetailsType = {
|
||||
|
|
|
@ -17,7 +17,6 @@ import {
|
|||
StorageManifestClass,
|
||||
StorageRecordClass,
|
||||
} from '../textsecure.d';
|
||||
import { ConversationModelType } from '../model-types.d';
|
||||
import { isEnabled } from '../RemoteConfig';
|
||||
import {
|
||||
mergeAccountRecord,
|
||||
|
@ -29,6 +28,7 @@ import {
|
|||
toGroupV1Record,
|
||||
toGroupV2Record,
|
||||
} from './storageRecordOps';
|
||||
import { ConversationModel } from '../models/conversations';
|
||||
|
||||
const {
|
||||
eraseStorageServiceStateFromConversations,
|
||||
|
@ -98,7 +98,7 @@ function generateStorageID(): ArrayBuffer {
|
|||
return Crypto.getRandomBytes(16);
|
||||
}
|
||||
|
||||
function isGroupV1(conversation: ConversationModelType): boolean {
|
||||
function isGroupV1(conversation: ConversationModel): boolean {
|
||||
const groupID = conversation.get('groupId');
|
||||
if (!groupID) {
|
||||
return false;
|
||||
|
@ -109,7 +109,7 @@ function isGroupV1(conversation: ConversationModelType): boolean {
|
|||
|
||||
type GeneratedManifestType = {
|
||||
conversationsToUpdate: Array<{
|
||||
conversation: ConversationModelType;
|
||||
conversation: ConversationModel;
|
||||
storageID: string | undefined;
|
||||
}>;
|
||||
deleteKeys: Array<ArrayBuffer>;
|
||||
|
@ -602,7 +602,7 @@ async function processManifest(
|
|||
|
||||
const localKeys = window
|
||||
.getConversations()
|
||||
.map((conversation: ConversationModelType) => conversation.get('storageID'))
|
||||
.map((conversation: ConversationModel) => conversation.get('storageID'))
|
||||
.filter(Boolean);
|
||||
|
||||
const unknownRecordsArray =
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
GroupV2RecordClass,
|
||||
} from '../textsecure.d';
|
||||
import { deriveGroupFields, waitThenMaybeUpdateGroup } from '../groups';
|
||||
import { ConversationModelType } from '../model-types.d';
|
||||
import { ConversationModel } from '../models/conversations';
|
||||
|
||||
const { updateConversation } = dataInterface;
|
||||
|
||||
|
@ -40,7 +40,7 @@ function toRecordVerified(verified: number): number {
|
|||
|
||||
function addUnknownFields(
|
||||
record: RecordClass,
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): void {
|
||||
if (record.__unknownFields) {
|
||||
window.log.info(
|
||||
|
@ -56,7 +56,7 @@ function addUnknownFields(
|
|||
|
||||
function applyUnknownFields(
|
||||
record: RecordClass,
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): void {
|
||||
if (conversation.get('storageUnknownFields')) {
|
||||
window.log.info(
|
||||
|
@ -72,7 +72,7 @@ function applyUnknownFields(
|
|||
}
|
||||
|
||||
export async function toContactRecord(
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): Promise<ContactRecordClass> {
|
||||
const contactRecord = new window.textsecure.protobuf.ContactRecord();
|
||||
if (conversation.get('uuid')) {
|
||||
|
@ -113,7 +113,7 @@ export async function toContactRecord(
|
|||
}
|
||||
|
||||
export async function toAccountRecord(
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): Promise<AccountRecordClass> {
|
||||
const accountRecord = new window.textsecure.protobuf.AccountRecord();
|
||||
|
||||
|
@ -147,7 +147,7 @@ export async function toAccountRecord(
|
|||
}
|
||||
|
||||
export async function toGroupV1Record(
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): Promise<GroupV1RecordClass> {
|
||||
const groupV1Record = new window.textsecure.protobuf.GroupV1Record();
|
||||
|
||||
|
@ -164,7 +164,7 @@ export async function toGroupV1Record(
|
|||
}
|
||||
|
||||
export async function toGroupV2Record(
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): Promise<GroupV2RecordClass> {
|
||||
const groupV2Record = new window.textsecure.protobuf.GroupV2Record();
|
||||
|
||||
|
@ -185,7 +185,7 @@ type MessageRequestCapableRecord = ContactRecordClass | GroupV1RecordClass;
|
|||
|
||||
function applyMessageRequestState(
|
||||
record: MessageRequestCapableRecord,
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): void {
|
||||
if (record.blocked) {
|
||||
conversation.applyMessageRequestResponse(
|
||||
|
@ -218,7 +218,7 @@ type RecordClassObject = {
|
|||
function doRecordsConflict(
|
||||
localRecord: RecordClassObject,
|
||||
remoteRecord: RecordClassObject,
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): boolean {
|
||||
const debugID = conversation.debugID();
|
||||
|
||||
|
@ -277,7 +277,7 @@ function doRecordsConflict(
|
|||
function doesRecordHavePendingChanges(
|
||||
mergedRecord: RecordClass,
|
||||
serviceRecord: RecordClass,
|
||||
conversation: ConversationModelType
|
||||
conversation: ConversationModel
|
||||
): boolean {
|
||||
const shouldSync = Boolean(conversation.get('needsStorageServiceSync'));
|
||||
|
||||
|
|
|
@ -21,9 +21,7 @@ import { createBatcher } from '../util/batcher';
|
|||
|
||||
import {
|
||||
ConversationModelCollectionType,
|
||||
ConversationModelType,
|
||||
MessageModelCollectionType,
|
||||
MessageModelType,
|
||||
} from '../model-types.d';
|
||||
|
||||
import {
|
||||
|
@ -45,6 +43,8 @@ import {
|
|||
StickerType,
|
||||
UnprocessedType,
|
||||
} from './Interface';
|
||||
import { MessageModel } from '../models/messages';
|
||||
import { ConversationModel } from '../models/conversations';
|
||||
|
||||
// We listen to a lot of events on ipcRenderer, often on the same channel. This prevents
|
||||
// any warnings that might be sent to the console in that case.
|
||||
|
@ -726,7 +726,7 @@ async function saveConversations(array: Array<ConversationType>) {
|
|||
|
||||
async function getConversationById(
|
||||
id: string,
|
||||
{ Conversation }: { Conversation: typeof ConversationModelType }
|
||||
{ Conversation }: { Conversation: typeof ConversationModel }
|
||||
) {
|
||||
const data = await channels.getConversationById(id);
|
||||
|
||||
|
@ -756,7 +756,7 @@ async function updateConversations(array: Array<ConversationType>) {
|
|||
|
||||
async function removeConversation(
|
||||
id: string,
|
||||
{ Conversation }: { Conversation: typeof ConversationModelType }
|
||||
{ Conversation }: { Conversation: typeof ConversationModel }
|
||||
) {
|
||||
const existing = await getConversationById(id, { Conversation });
|
||||
|
||||
|
@ -869,10 +869,7 @@ async function getMessageCount(conversationId?: string) {
|
|||
|
||||
async function saveMessage(
|
||||
data: MessageType,
|
||||
{
|
||||
forceSave,
|
||||
Message,
|
||||
}: { forceSave?: boolean; Message: typeof MessageModelType }
|
||||
{ forceSave, Message }: { forceSave?: boolean; Message: typeof MessageModel }
|
||||
) {
|
||||
const id = await channels.saveMessage(_cleanData(data), { forceSave });
|
||||
Message.updateTimers();
|
||||
|
@ -889,7 +886,7 @@ async function saveMessages(
|
|||
|
||||
async function removeMessage(
|
||||
id: string,
|
||||
{ Message }: { Message: typeof MessageModelType }
|
||||
{ Message }: { Message: typeof MessageModel }
|
||||
) {
|
||||
const message = await getMessageById(id, { Message });
|
||||
|
||||
|
@ -908,7 +905,7 @@ async function _removeMessages(ids: Array<string>) {
|
|||
|
||||
async function getMessageById(
|
||||
id: string,
|
||||
{ Message }: { Message: typeof MessageModelType }
|
||||
{ Message }: { Message: typeof MessageModel }
|
||||
) {
|
||||
const message = await channels.getMessageById(id);
|
||||
if (!message) {
|
||||
|
@ -947,7 +944,7 @@ async function getMessageBySender(
|
|||
sourceDevice: string;
|
||||
sent_at: number;
|
||||
},
|
||||
{ Message }: { Message: typeof MessageModelType }
|
||||
{ Message }: { Message: typeof MessageModel }
|
||||
) {
|
||||
const messages = await channels.getMessageBySender({
|
||||
source,
|
||||
|
@ -1027,9 +1024,9 @@ async function getNewerMessagesByConversation(
|
|||
async function getLastConversationActivity(
|
||||
conversationId: string,
|
||||
options: {
|
||||
Message: typeof MessageModelType;
|
||||
Message: typeof MessageModel;
|
||||
}
|
||||
): Promise<MessageModelType | undefined> {
|
||||
): Promise<MessageModel | undefined> {
|
||||
const { Message } = options;
|
||||
const result = await channels.getLastConversationActivity(conversationId);
|
||||
if (result) {
|
||||
|
@ -1040,9 +1037,9 @@ async function getLastConversationActivity(
|
|||
async function getLastConversationPreview(
|
||||
conversationId: string,
|
||||
options: {
|
||||
Message: typeof MessageModelType;
|
||||
Message: typeof MessageModel;
|
||||
}
|
||||
): Promise<MessageModelType | undefined> {
|
||||
): Promise<MessageModel | undefined> {
|
||||
const { Message } = options;
|
||||
const result = await channels.getLastConversationPreview(conversationId);
|
||||
if (result) {
|
||||
|
@ -1083,12 +1080,12 @@ async function removeAllMessagesInConversation(
|
|||
return;
|
||||
}
|
||||
|
||||
const ids = messages.map((message: MessageModelType) => message.id);
|
||||
const ids = messages.map((message: MessageModel) => message.id);
|
||||
|
||||
// Note: It's very important that these models are fully hydrated because
|
||||
// we need to delete all associated on-disk files along with the database delete.
|
||||
await Promise.all(
|
||||
messages.map(async (message: MessageModelType) => message.cleanup())
|
||||
messages.map(async (message: MessageModel) => message.cleanup())
|
||||
);
|
||||
|
||||
await channels.removeMessage(ids);
|
||||
|
@ -1129,7 +1126,7 @@ async function getOutgoingWithoutExpiresAt({
|
|||
async function getNextExpiringMessage({
|
||||
Message,
|
||||
}: {
|
||||
Message: typeof MessageModelType;
|
||||
Message: typeof MessageModel;
|
||||
}) {
|
||||
const message = await channels.getNextExpiringMessage();
|
||||
|
||||
|
@ -1143,7 +1140,7 @@ async function getNextExpiringMessage({
|
|||
async function getNextTapToViewMessageToAgeOut({
|
||||
Message,
|
||||
}: {
|
||||
Message: typeof MessageModelType;
|
||||
Message: typeof MessageModel;
|
||||
}) {
|
||||
const message = await channels.getNextTapToViewMessageToAgeOut();
|
||||
if (!message) {
|
||||
|
|
|
@ -19,10 +19,10 @@ export type UnprocessedType = any;
|
|||
|
||||
import {
|
||||
ConversationModelCollectionType,
|
||||
ConversationModelType,
|
||||
MessageModelCollectionType,
|
||||
MessageModelType,
|
||||
} from '../model-types.d';
|
||||
import { MessageModel } from '../models/messages';
|
||||
import { ConversationModel } from '../models/conversations';
|
||||
|
||||
export interface DataInterface {
|
||||
close: () => Promise<void>;
|
||||
|
@ -204,7 +204,11 @@ export type ServerInterface = DataInterface & {
|
|||
getMessagesBySentAt: (sentAt: number) => Promise<Array<MessageType>>;
|
||||
getOlderMessagesByConversation: (
|
||||
conversationId: string,
|
||||
options?: { limit?: number; receivedAt?: number; messageId?: string }
|
||||
options?: {
|
||||
limit?: number;
|
||||
receivedAt?: number;
|
||||
messageId?: string;
|
||||
}
|
||||
) => Promise<Array<MessageTypeUnhydrated>>;
|
||||
getNewerMessagesByConversation: (
|
||||
conversationId: string,
|
||||
|
@ -228,7 +232,7 @@ export type ServerInterface = DataInterface & {
|
|||
saveMessage: (
|
||||
data: MessageType,
|
||||
options: { forceSave?: boolean }
|
||||
) => Promise<number>;
|
||||
) => Promise<string>;
|
||||
updateConversation: (data: ConversationType) => Promise<void>;
|
||||
|
||||
// For testing only
|
||||
|
@ -272,8 +276,8 @@ export type ClientInterface = DataInterface & {
|
|||
}) => Promise<ConversationModelCollectionType>;
|
||||
getConversationById: (
|
||||
id: string,
|
||||
{ Conversation }: { Conversation: typeof ConversationModelType }
|
||||
) => Promise<ConversationModelType>;
|
||||
{ Conversation }: { Conversation: typeof ConversationModel }
|
||||
) => Promise<ConversationModel>;
|
||||
getExpiredMessages: ({
|
||||
MessageCollection,
|
||||
}: {
|
||||
|
@ -281,7 +285,7 @@ export type ClientInterface = DataInterface & {
|
|||
}) => Promise<MessageModelCollectionType>;
|
||||
getMessageById: (
|
||||
id: string,
|
||||
{ Message }: { Message: typeof MessageModelType }
|
||||
{ Message }: { Message: typeof MessageModel }
|
||||
) => Promise<MessageType | undefined>;
|
||||
getMessageBySender: (
|
||||
options: {
|
||||
|
@ -290,8 +294,8 @@ export type ClientInterface = DataInterface & {
|
|||
sourceDevice: string;
|
||||
sent_at: number;
|
||||
},
|
||||
{ Message }: { Message: typeof MessageModelType }
|
||||
) => Promise<MessageModelType | null>;
|
||||
{ Message }: { Message: typeof MessageModel }
|
||||
) => Promise<MessageModel | null>;
|
||||
getMessagesBySentAt: (
|
||||
sentAt: number,
|
||||
{
|
||||
|
@ -302,6 +306,7 @@ export type ClientInterface = DataInterface & {
|
|||
conversationId: string,
|
||||
options: {
|
||||
limit?: number;
|
||||
messageId?: string;
|
||||
receivedAt?: number;
|
||||
MessageCollection: typeof MessageModelCollectionType;
|
||||
}
|
||||
|
@ -317,25 +322,25 @@ export type ClientInterface = DataInterface & {
|
|||
getLastConversationActivity: (
|
||||
conversationId: string,
|
||||
options: {
|
||||
Message: typeof MessageModelType;
|
||||
Message: typeof MessageModel;
|
||||
}
|
||||
) => Promise<MessageModelType | undefined>;
|
||||
) => Promise<MessageModel | undefined>;
|
||||
getLastConversationPreview: (
|
||||
conversationId: string,
|
||||
options: {
|
||||
Message: typeof MessageModelType;
|
||||
Message: typeof MessageModel;
|
||||
}
|
||||
) => Promise<MessageModelType | undefined>;
|
||||
) => Promise<MessageModel | undefined>;
|
||||
getNextExpiringMessage: ({
|
||||
Message,
|
||||
}: {
|
||||
Message: typeof MessageModelType;
|
||||
}) => Promise<MessageModelType | null>;
|
||||
Message: typeof MessageModel;
|
||||
}) => Promise<MessageModel | null>;
|
||||
getNextTapToViewMessageToAgeOut: ({
|
||||
Message,
|
||||
}: {
|
||||
Message: typeof MessageModelType;
|
||||
}) => Promise<MessageModelType | null>;
|
||||
Message: typeof MessageModel;
|
||||
}) => Promise<MessageModel | null>;
|
||||
getOutgoingWithoutExpiresAt: ({
|
||||
MessageCollection,
|
||||
}: {
|
||||
|
@ -354,17 +359,17 @@ export type ClientInterface = DataInterface & {
|
|||
) => Promise<MessageModelCollectionType>;
|
||||
removeConversation: (
|
||||
id: string,
|
||||
{ Conversation }: { Conversation: typeof ConversationModelType }
|
||||
{ Conversation }: { Conversation: typeof ConversationModel }
|
||||
) => Promise<void>;
|
||||
removeMessage: (
|
||||
id: string,
|
||||
{ Message }: { Message: typeof MessageModelType }
|
||||
{ Message }: { Message: typeof MessageModel }
|
||||
) => Promise<void>;
|
||||
saveMessage: (
|
||||
data: MessageType,
|
||||
options: { forceSave?: boolean; Message: typeof MessageModelType }
|
||||
) => Promise<number>;
|
||||
updateConversation: (data: ConversationType) => void;
|
||||
options: { forceSave?: boolean; Message: typeof MessageModel }
|
||||
) => Promise<string>;
|
||||
updateConversation: (data: ConversationType, extra?: unknown) => void;
|
||||
|
||||
// Test-only
|
||||
|
||||
|
|
|
@ -2674,7 +2674,11 @@ async function getOlderMessagesByConversation(
|
|||
limit = 100,
|
||||
receivedAt = Number.MAX_VALUE,
|
||||
messageId,
|
||||
}: { limit?: number; receivedAt?: number; messageId?: string } = {}
|
||||
}: {
|
||||
limit?: number;
|
||||
receivedAt?: number;
|
||||
messageId?: string;
|
||||
} = {}
|
||||
) {
|
||||
const db = getInstance();
|
||||
let rows;
|
||||
|
|
|
@ -23,6 +23,17 @@ export type DBConversationType = {
|
|||
lastMessage: string;
|
||||
type: string;
|
||||
};
|
||||
|
||||
export type LastMessageStatus =
|
||||
| 'error'
|
||||
| 'partial-sent'
|
||||
| 'sending'
|
||||
| 'sent'
|
||||
| 'delivered'
|
||||
| 'read';
|
||||
|
||||
export type ConversationTypeType = 'direct' | 'group';
|
||||
|
||||
export type ConversationType = {
|
||||
id: string;
|
||||
uuid?: string;
|
||||
|
@ -39,19 +50,13 @@ export type ConversationType = {
|
|||
timestamp?: number;
|
||||
inboxPosition?: number;
|
||||
lastMessage?: {
|
||||
status:
|
||||
| 'error'
|
||||
| 'partial-sent'
|
||||
| 'sending'
|
||||
| 'sent'
|
||||
| 'delivered'
|
||||
| 'read';
|
||||
status: LastMessageStatus;
|
||||
text: string;
|
||||
};
|
||||
phoneNumber?: string;
|
||||
membersCount?: number;
|
||||
muteExpiresAt?: number;
|
||||
type: 'direct' | 'group';
|
||||
type: ConversationTypeType;
|
||||
isMe?: boolean;
|
||||
lastUpdated: number;
|
||||
title: string;
|
||||
|
@ -59,14 +64,14 @@ export type ConversationType = {
|
|||
isSelected?: boolean;
|
||||
typingContact?: {
|
||||
avatarPath?: string;
|
||||
color: string;
|
||||
color?: ColorType;
|
||||
name?: string;
|
||||
phoneNumber: string;
|
||||
phoneNumber?: string;
|
||||
profileName?: string;
|
||||
};
|
||||
} | null;
|
||||
|
||||
shouldShowDraft?: boolean;
|
||||
draftText?: string;
|
||||
draftText?: string | null;
|
||||
draftPreview?: string;
|
||||
|
||||
messageRequestsEnabled?: boolean;
|
||||
|
|
19
ts/textsecure.d.ts
vendored
19
ts/textsecure.d.ts
vendored
|
@ -39,7 +39,7 @@ export type StorageServiceCredentials = {
|
|||
|
||||
export type TextSecureType = {
|
||||
createTaskWithTimeout: (
|
||||
task: () => Promise<any>,
|
||||
task: () => Promise<any> | any,
|
||||
id?: string,
|
||||
options?: { timeout?: number }
|
||||
) => () => Promise<any>;
|
||||
|
@ -77,12 +77,16 @@ export type TextSecureType = {
|
|||
protocol: StorageProtocolType;
|
||||
};
|
||||
messageReceiver: MessageReceiver;
|
||||
messaging?: SendMessage;
|
||||
messageSender: MessageSender;
|
||||
messaging: SendMessage;
|
||||
protobuf: ProtobufCollectionType;
|
||||
utils: typeof utils;
|
||||
|
||||
EventTarget: typeof EventTarget;
|
||||
MessageReceiver: typeof MessageReceiver;
|
||||
AccountManager: WhatIsThis;
|
||||
MessageSender: WhatIsThis;
|
||||
SyncRequest: WhatIsThis;
|
||||
};
|
||||
|
||||
type StoredSignedPreKeyType = SignedPreKeyType & {
|
||||
|
@ -108,11 +112,13 @@ export type StorageProtocolType = StorageType & {
|
|||
removeSession: (identifier: string) => Promise<void>;
|
||||
getDeviceIds: (identifier: string) => Promise<Array<number>>;
|
||||
getIdentityRecord: (identifier: string) => IdentityKeyRecord | undefined;
|
||||
getVerified: (id: string) => Promise<number>;
|
||||
hydrateCaches: () => Promise<void>;
|
||||
clearPreKeyStore: () => Promise<void>;
|
||||
clearSignedPreKeysStore: () => Promise<void>;
|
||||
clearSessionStore: () => Promise<void>;
|
||||
isTrustedIdentity: () => void;
|
||||
isUntrusted: (id: string) => Promise<boolean>;
|
||||
storePreKey: (keyId: number, keyPair: KeyPairType) => Promise<void>;
|
||||
storeSignedPreKey: (
|
||||
keyId: number,
|
||||
|
@ -131,6 +137,7 @@ export type StorageProtocolType = StorageType & {
|
|||
number: string,
|
||||
options: IdentityKeyRecord
|
||||
) => Promise<void>;
|
||||
setApproval: (id: string, something: boolean) => void;
|
||||
setVerified: (
|
||||
encodedAddress: string,
|
||||
verifiedStatus: number,
|
||||
|
@ -138,6 +145,8 @@ export type StorageProtocolType = StorageType & {
|
|||
) => Promise<void>;
|
||||
removeSignedPreKey: (keyId: number) => Promise<void>;
|
||||
removeAllData: () => Promise<void>;
|
||||
on: (key: string, callback: () => void) => WhatIsThis;
|
||||
removeAllConfiguration: () => Promise<void>;
|
||||
};
|
||||
|
||||
// Protobufs
|
||||
|
@ -279,6 +288,7 @@ export declare class AccessControlClass {
|
|||
// Note: we need to use namespaces to express nested classes in Typescript
|
||||
export declare namespace AccessControlClass {
|
||||
class AccessRequired {
|
||||
static ANY: number;
|
||||
static UNKNOWN: number;
|
||||
static MEMBER: number;
|
||||
static ADMINISTRATOR: number;
|
||||
|
@ -445,6 +455,10 @@ export declare class AttachmentPointerClass {
|
|||
encoding?: string
|
||||
) => AttachmentPointerClass;
|
||||
|
||||
static Flags: {
|
||||
VOICE_MESSAGE: number;
|
||||
};
|
||||
|
||||
cdnId?: ProtoBigNumberType;
|
||||
cdnKey?: string;
|
||||
contentType?: string;
|
||||
|
@ -1144,6 +1158,7 @@ export declare class VerifiedClass {
|
|||
data: ArrayBuffer | ByteBufferClass,
|
||||
encoding?: string
|
||||
) => VerifiedClass;
|
||||
static State: WhatIsThis;
|
||||
|
||||
destination?: string;
|
||||
destinationUuid?: string;
|
||||
|
|
|
@ -586,7 +586,7 @@ export default class MessageSender {
|
|||
messageProto: DataMessageClass,
|
||||
silent?: boolean,
|
||||
options?: SendOptionsType
|
||||
) {
|
||||
): Promise<CallbackResultType> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const callback = (result: CallbackResultType) => {
|
||||
if (result && result.errors && result.errors.length > 0) {
|
||||
|
@ -615,7 +615,7 @@ export default class MessageSender {
|
|||
timestamp: number,
|
||||
silent?: boolean,
|
||||
options?: SendOptionsType
|
||||
) {
|
||||
): Promise<CallbackResultType> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const callback = (res: CallbackResultType) => {
|
||||
if (res && res.errors && res.errors.length > 0) {
|
||||
|
@ -651,8 +651,8 @@ export default class MessageSender {
|
|||
async sendSyncMessage(
|
||||
encodedDataMessage: ArrayBuffer,
|
||||
timestamp: number,
|
||||
destination: string,
|
||||
destinationUuid: string | null,
|
||||
destination: string | undefined,
|
||||
destinationUuid: string | null | undefined,
|
||||
expirationStartTimestamp: number | null,
|
||||
sentTo: Array<string> = [],
|
||||
unidentifiedDeliveries: Array<string> = [],
|
||||
|
@ -927,11 +927,11 @@ export default class MessageSender {
|
|||
|
||||
async sendTypingMessage(
|
||||
options: {
|
||||
recipientId: string;
|
||||
groupId: string;
|
||||
recipientId?: string;
|
||||
groupId?: string;
|
||||
groupMembers: Array<string>;
|
||||
isTyping: boolean;
|
||||
timestamp: number;
|
||||
timestamp?: number;
|
||||
},
|
||||
sendOptions: SendOptionsType = {}
|
||||
) {
|
||||
|
@ -950,9 +950,9 @@ export default class MessageSender {
|
|||
throw new Error('Need to provide either recipientId or groupId!');
|
||||
}
|
||||
|
||||
const recipients = groupId
|
||||
? (without(groupMembers, myNumber, myUuid) as Array<string>)
|
||||
: [recipientId];
|
||||
const recipients = (groupId
|
||||
? without(groupMembers, myNumber, myUuid)
|
||||
: [recipientId]) as Array<string>;
|
||||
const groupIdBuffer = groupId
|
||||
? fromEncodedBinaryToArrayBuffer(groupId)
|
||||
: null;
|
||||
|
@ -1035,7 +1035,7 @@ export default class MessageSender {
|
|||
recipientUuid: string,
|
||||
timestamps: Array<number>,
|
||||
options?: SendOptionsType
|
||||
) {
|
||||
): Promise<CallbackResultType | void> {
|
||||
const myNumber = window.textsecure.storage.user.getNumber();
|
||||
const myUuid = window.textsecure.storage.user.getUuid();
|
||||
const myDevice = window.textsecure.storage.user.getDeviceId();
|
||||
|
@ -1129,7 +1129,7 @@ export default class MessageSender {
|
|||
senderUuid: string,
|
||||
timestamp: number,
|
||||
options?: SendOptionsType
|
||||
) {
|
||||
): Promise<CallbackResultType | null> {
|
||||
const myNumber = window.textsecure.storage.user.getNumber();
|
||||
const myUuid = window.textsecure.storage.user.getUuid();
|
||||
const myDevice = window.textsecure.storage.user.getDeviceId();
|
||||
|
@ -1207,7 +1207,7 @@ export default class MessageSender {
|
|||
installed: boolean;
|
||||
}>,
|
||||
options?: SendOptionsType
|
||||
) {
|
||||
): Promise<CallbackResultType | null> {
|
||||
const myDevice = window.textsecure.storage.user.getDeviceId();
|
||||
if (myDevice === 1 || myDevice === '1') {
|
||||
return null;
|
||||
|
@ -1359,10 +1359,10 @@ export default class MessageSender {
|
|||
|
||||
async getMessageProto(
|
||||
destination: string,
|
||||
body: string,
|
||||
attachments: Array<AttachmentType> | null,
|
||||
body: string | undefined,
|
||||
attachments: Array<AttachmentType>,
|
||||
quote: any,
|
||||
preview: Array<PreviewType> | null,
|
||||
preview: Array<PreviewType>,
|
||||
sticker: any,
|
||||
reaction: any,
|
||||
timestamp: number,
|
||||
|
@ -1402,10 +1402,10 @@ export default class MessageSender {
|
|||
|
||||
async sendMessageToIdentifier(
|
||||
identifier: string,
|
||||
messageText: string,
|
||||
attachments: Array<AttachmentType> | null,
|
||||
messageText: string | undefined,
|
||||
attachments: Array<AttachmentType> | undefined,
|
||||
quote: any,
|
||||
preview: Array<PreviewType> | null,
|
||||
preview: Array<PreviewType> | undefined,
|
||||
sticker: any,
|
||||
reaction: any,
|
||||
timestamp: number,
|
||||
|
|
|
@ -419,7 +419,7 @@ async function _promiseAjax(
|
|||
// Build expired!
|
||||
if (response.status === 499) {
|
||||
window.log.error('Error: build expired');
|
||||
window.storage.put('remoteBuildExpiration', Date.now());
|
||||
await window.storage.put('remoteBuildExpiration', Date.now());
|
||||
window.reduxActions.expiration.hydrateExpirationStatus(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ export type RenderTextCallbackType = (options: {
|
|||
}) => JSX.Element | string;
|
||||
|
||||
export type ReplacementValuesType = {
|
||||
[key: string]: string;
|
||||
[key: string]: string | undefined;
|
||||
};
|
||||
|
||||
export type LocalizerType = (
|
||||
key: string,
|
||||
values?: Array<string> | ReplacementValuesType
|
||||
values?: Array<string | null> | ReplacementValuesType
|
||||
) => string;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { DeletesModelType, MessageModelType } from '../model-types.d';
|
||||
import { DeletesModelType } from '../model-types.d';
|
||||
import { MessageModel } from '../models/messages';
|
||||
|
||||
const ONE_DAY = 24 * 60 * 60 * 1000;
|
||||
|
||||
export async function deleteForEveryone(
|
||||
message: MessageModelType,
|
||||
message: MessageModel,
|
||||
doe: DeletesModelType,
|
||||
shouldPersist = true
|
||||
): Promise<void> {
|
||||
|
|
|
@ -46,10 +46,14 @@ const excludedFilesRegexps = [
|
|||
'\\.d\\.ts$',
|
||||
|
||||
// High-traffic files in our project
|
||||
'^js/models/messages.js',
|
||||
'^js/models/conversations.js',
|
||||
'^js/views/conversation_view.js',
|
||||
'^js/background.js',
|
||||
'^ts/models/messages.js',
|
||||
'^ts/models/messages.ts',
|
||||
'^ts/models/conversations.js',
|
||||
'^ts/models/conversations.ts',
|
||||
'^ts/views/conversation_view.js',
|
||||
'^ts/views/conversation_view.ts',
|
||||
'^ts/background.js',
|
||||
'^ts/background.ts',
|
||||
'^ts/Crypto.js',
|
||||
'^ts/Crypto.ts',
|
||||
'^ts/textsecure/MessageReceiver.js',
|
||||
|
|
3297
ts/views/conversation_view.ts
Normal file
3297
ts/views/conversation_view.ts
Normal file
File diff suppressed because it is too large
Load diff
500
ts/window.d.ts
vendored
500
ts/window.d.ts
vendored
|
@ -5,9 +5,8 @@ import * as Underscore from 'underscore';
|
|||
import { Ref } from 'react';
|
||||
import {
|
||||
ConversationModelCollectionType,
|
||||
ConversationModelType,
|
||||
MessageModelCollectionType,
|
||||
MessageModelType,
|
||||
MessageAttributesType,
|
||||
} from './model-types.d';
|
||||
import {
|
||||
LibSignalType,
|
||||
|
@ -19,7 +18,7 @@ import { WebAPIConnectType } from './textsecure/WebAPI';
|
|||
import { CallingClass } from './services/calling';
|
||||
import * as Crypto from './Crypto';
|
||||
import * as RemoteConfig from './RemoteConfig';
|
||||
import { LocalizerType } from './types/Util';
|
||||
import { LocalizerType, BodyRangesType } from './types/Util';
|
||||
import { CallHistoryDetailsType } from './types/Calling';
|
||||
import { ColorType } from './types/Colors';
|
||||
import { ConversationController } from './ConversationController';
|
||||
|
@ -27,16 +26,47 @@ import { ReduxActions } from './state/types';
|
|||
import { SendOptionsType } from './textsecure/SendMessage';
|
||||
import AccountManager from './textsecure/AccountManager';
|
||||
import Data from './sql/Client';
|
||||
import { UserMessage } from './types/Message';
|
||||
import PQueue from 'p-queue/dist';
|
||||
import { PhoneNumberFormat } from 'google-libphonenumber';
|
||||
import { MessageModel } from './models/messages';
|
||||
import { ConversationModel } from './models/conversations';
|
||||
import { combineNames } from './util';
|
||||
import { BatcherType } from './util/batcher';
|
||||
|
||||
export { Long } from 'long';
|
||||
|
||||
type TaskResultType = any;
|
||||
|
||||
type WhatIsThis = any;
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
_: typeof Underscore;
|
||||
$: typeof jQuery;
|
||||
|
||||
extension: any;
|
||||
moment: any;
|
||||
imageToBlurHash: any;
|
||||
autoOrientImage: any;
|
||||
dataURLToBlobSync: any;
|
||||
loadImage: any;
|
||||
isBehindProxy: any;
|
||||
|
||||
PQueue: typeof PQueue;
|
||||
PQueueType: PQueue;
|
||||
|
||||
WhatIsThis: WhatIsThis;
|
||||
|
||||
baseAttachmentsPath: string;
|
||||
baseStickersPath: string;
|
||||
baseTempPath: string;
|
||||
dcodeIO: DCodeIOType;
|
||||
enterKeyboardMode: () => void;
|
||||
enterMouseMode: () => void;
|
||||
getAccountManager: () => AccountManager | undefined;
|
||||
getAlwaysRelayCalls: () => Promise<boolean>;
|
||||
getBuiltInImages: () => Promise<Array<WhatIsThis>>;
|
||||
getCallRingtoneNotification: () => Promise<boolean>;
|
||||
getCallSystemNotification: () => Promise<boolean>;
|
||||
getConversations: () => ConversationModelCollectionType;
|
||||
|
@ -46,20 +76,33 @@ declare global {
|
|||
getGuid: () => string;
|
||||
getInboxCollection: () => ConversationModelCollectionType;
|
||||
getIncomingCallNotification: () => Promise<boolean>;
|
||||
getInteractionMode: () => string;
|
||||
getMediaCameraPermissions: () => Promise<boolean>;
|
||||
getMediaPermissions: () => Promise<boolean>;
|
||||
getServerPublicParams: () => string;
|
||||
getSocketStatus: () => number;
|
||||
getSyncRequest: () => WhatIsThis;
|
||||
getTitle: () => string;
|
||||
waitForEmptyEventQueue: () => Promise<void>;
|
||||
getVersion: () => string;
|
||||
showCallingPermissionsPopup: (forCamera: boolean) => Promise<void>;
|
||||
i18n: LocalizerType;
|
||||
isValidGuid: (maybeGuid: string) => boolean;
|
||||
isActive: () => boolean;
|
||||
isAfterVersion: (version: WhatIsThis, anotherVersion: string) => boolean;
|
||||
isBeforeVersion: (version: WhatIsThis, anotherVersion: string) => boolean;
|
||||
isValidGuid: (maybeGuid: string | null) => boolean;
|
||||
isValidE164: (maybeE164: unknown) => boolean;
|
||||
libphonenumber: {
|
||||
util: {
|
||||
getRegionCodeForNumber: (number: string) => string;
|
||||
parseNumber: (
|
||||
e164: string,
|
||||
regionCode: string
|
||||
) => typeof window.Signal.Types.PhoneNumber;
|
||||
};
|
||||
parse: (number: string) => string;
|
||||
getRegionCodeForNumber: (number: string) => string;
|
||||
format: (number: string, format: PhoneNumberFormat) => string;
|
||||
};
|
||||
libsignal: LibSignalType;
|
||||
log: {
|
||||
|
@ -67,28 +110,69 @@ declare global {
|
|||
warn: LoggerType;
|
||||
error: LoggerType;
|
||||
};
|
||||
nodeSetImmediate: typeof setImmediate;
|
||||
normalizeUuids: (obj: any, paths: Array<string>, context: string) => any;
|
||||
owsDesktopApp: WhatIsThis;
|
||||
platform: string;
|
||||
preloadedImages: Array<WhatIsThis>;
|
||||
reduxActions: ReduxActions;
|
||||
reduxStore: WhatIsThis;
|
||||
registerForActive: (handler: WhatIsThis) => void;
|
||||
resetActiveTimer: () => void;
|
||||
restart: () => void;
|
||||
setImmediate: typeof setImmediate;
|
||||
showWindow: () => void;
|
||||
showSettings: () => void;
|
||||
shutdown: () => void;
|
||||
setAutoHideMenuBar: (value: WhatIsThis) => void;
|
||||
setBadgeCount: (count: number) => void;
|
||||
setMenuBarVisibility: (value: WhatIsThis) => void;
|
||||
showKeyboardShortcuts: () => void;
|
||||
storage: {
|
||||
put: (key: string, value: any) => void;
|
||||
remove: (key: string) => Promise<void>;
|
||||
get: <T = any>(key: string) => T | undefined;
|
||||
addBlockedGroup: (group: string) => void;
|
||||
addBlockedNumber: (number: string) => void;
|
||||
addBlockedUuid: (uuid: string) => void;
|
||||
fetch: () => void;
|
||||
get: <T = any>(key: string, defaultValue?: T) => T | undefined;
|
||||
getItemsState: () => WhatIsThis;
|
||||
isBlocked: (number: string) => boolean;
|
||||
isGroupBlocked: (group: unknown) => boolean;
|
||||
isUuidBlocked: (uuid: string) => boolean;
|
||||
onready: WhatIsThis;
|
||||
put: (key: string, value: any) => Promise<void>;
|
||||
remove: (key: string) => Promise<void>;
|
||||
removeBlockedGroup: (group: string) => void;
|
||||
removeBlockedNumber: (number: string) => void;
|
||||
removeBlockedUuid: (uuid: string) => void;
|
||||
};
|
||||
systemTheme: WhatIsThis;
|
||||
textsecure: TextSecureType;
|
||||
unregisterForActive: (handler: WhatIsThis) => void;
|
||||
updateTrayIcon: (count: number) => void;
|
||||
|
||||
Backbone: typeof Backbone;
|
||||
Signal: {
|
||||
Backbone: any;
|
||||
AttachmentDownloads: {
|
||||
addJob: <T = unknown>(
|
||||
attachment: unknown,
|
||||
options: unknown
|
||||
) => Promise<T>;
|
||||
start: (options: WhatIsThis) => void;
|
||||
stop: () => void;
|
||||
};
|
||||
Crypto: typeof Crypto;
|
||||
Data: typeof Data;
|
||||
Groups: {
|
||||
maybeUpdateGroup: (options: unknown) => Promise<void>;
|
||||
waitThenMaybeUpdateGroup: (options: unknown) => Promise<void>;
|
||||
uploadGroupChange: (
|
||||
options: unknown
|
||||
) => Promise<{ toArrayBuffer: () => ArrayBuffer }>;
|
||||
buildDisappearingMessagesTimerChange: (
|
||||
options: unknown
|
||||
) => { version: number };
|
||||
};
|
||||
Metadata: {
|
||||
SecretSessionCipher: typeof SecretSessionCipherClass;
|
||||
createCertificateValidator: (
|
||||
|
@ -98,22 +182,301 @@ declare global {
|
|||
RemoteConfig: typeof RemoteConfig;
|
||||
Services: {
|
||||
calling: CallingClass;
|
||||
eraseAllStorageServiceState: () => Promise<void>;
|
||||
handleUnknownRecords: (param: WhatIsThis) => void;
|
||||
initializeGroupCredentialFetcher: () => void;
|
||||
initializeNetworkObserver: (network: WhatIsThis) => void;
|
||||
initializeUpdateListener: (
|
||||
updates: WhatIsThis,
|
||||
events: WhatIsThis
|
||||
) => void;
|
||||
runStorageServiceSyncJob: () => Promise<void>;
|
||||
storageServiceUploadJob: () => void;
|
||||
};
|
||||
Migrations: {
|
||||
readTempData: any;
|
||||
deleteAttachmentData: (path: string) => Promise<void>;
|
||||
doesAttachmentExist: () => unknown;
|
||||
writeNewAttachmentData: (data: ArrayBuffer) => Promise<string>;
|
||||
deleteExternalMessageFiles: (attributes: unknown) => Promise<void>;
|
||||
getAbsoluteAttachmentPath: (path: string) => string;
|
||||
loadAttachmentData: (attachment: WhatIsThis) => WhatIsThis;
|
||||
loadQuoteData: (quote: unknown) => WhatIsThis;
|
||||
loadPreviewData: (preview: unknown) => WhatIsThis;
|
||||
loadStickerData: (sticker: unknown) => WhatIsThis;
|
||||
readStickerData: (path: string) => Promise<ArrayBuffer>;
|
||||
upgradeMessageSchema: (attributes: unknown) => WhatIsThis;
|
||||
|
||||
copyIntoTempDirectory: any;
|
||||
deleteDraftFile: any;
|
||||
deleteTempFile: any;
|
||||
getAbsoluteDraftPath: any;
|
||||
getAbsoluteTempPath: any;
|
||||
openFileInFolder: any;
|
||||
readAttachmentData: any;
|
||||
readDraftData: any;
|
||||
saveAttachmentToDisk: any;
|
||||
writeNewDraftData: any;
|
||||
};
|
||||
Stickers: {
|
||||
getDataFromLink: any;
|
||||
copyStickerToAttachments: (
|
||||
packId: string,
|
||||
stickerId: number
|
||||
) => Promise<typeof window.Signal.Types.Sticker>;
|
||||
deletePackReference: (id: string, packId: string) => Promise<void>;
|
||||
downloadEphemeralPack: (
|
||||
packId: string,
|
||||
key: WhatIsThis
|
||||
) => Promise<void>;
|
||||
downloadQueuedPacks: () => void;
|
||||
downloadStickerPack: (
|
||||
id: string,
|
||||
key: string,
|
||||
options: WhatIsThis
|
||||
) => void;
|
||||
getInitialState: () => WhatIsThis;
|
||||
load: () => void;
|
||||
removeEphemeralPack: (packId: string) => Promise<void>;
|
||||
savePackMetadata: (
|
||||
packId: string,
|
||||
packKey: string,
|
||||
metadata: unknown
|
||||
) => void;
|
||||
getStickerPackStatus: (packId: string) => 'downloaded' | 'installed';
|
||||
getSticker: (
|
||||
packId: string,
|
||||
stickerId: number
|
||||
) => typeof window.Signal.Types.Sticker;
|
||||
getStickerPack: (packId: string) => WhatIsThis;
|
||||
getInstalledStickerPacks: () => WhatIsThis;
|
||||
};
|
||||
Types: {
|
||||
Attachment: {
|
||||
save: any;
|
||||
path: string;
|
||||
pending: boolean;
|
||||
flags: number;
|
||||
size: number;
|
||||
screenshot: {
|
||||
path: string;
|
||||
};
|
||||
thumbnail: {
|
||||
path: string;
|
||||
objectUrl: string;
|
||||
};
|
||||
contentType: string;
|
||||
error: unknown;
|
||||
|
||||
migrateDataToFileSystem: (
|
||||
attachment: WhatIsThis,
|
||||
options: unknown
|
||||
) => WhatIsThis;
|
||||
|
||||
isVoiceMessage: (attachments: unknown) => boolean;
|
||||
isImage: (attachments: unknown) => boolean;
|
||||
isVideo: (attachments: unknown) => boolean;
|
||||
isAudio: (attachments: unknown) => boolean;
|
||||
};
|
||||
MIME: {
|
||||
IMAGE_GIF: unknown;
|
||||
isImage: any;
|
||||
isJPEG: any;
|
||||
};
|
||||
Contact: {
|
||||
avatar?: { avatar?: unknown };
|
||||
number: Array<{ value: string }>;
|
||||
signalAccount: unknown;
|
||||
|
||||
contactSelector: (
|
||||
contact: typeof window.Signal.Types.Contact,
|
||||
options: unknown
|
||||
) => typeof window.Signal.Types.Contact;
|
||||
getName: (contact: typeof window.Signal.Types.Contact) => string;
|
||||
};
|
||||
Conversation: {
|
||||
computeHash: (data: string) => Promise<string>;
|
||||
deleteExternalFiles: (
|
||||
attributes: unknown,
|
||||
options: unknown
|
||||
) => Promise<void>;
|
||||
maybeUpdateProfileAvatar: (
|
||||
attributes: unknown,
|
||||
decrypted: unknown,
|
||||
options: unknown
|
||||
) => Promise<Record<string, unknown>>;
|
||||
maybeUpdateAvatar: (
|
||||
attributes: unknown,
|
||||
data: unknown,
|
||||
options: unknown
|
||||
) => Promise<WhatIsThis>;
|
||||
};
|
||||
PhoneNumber: {
|
||||
format: (
|
||||
identifier: string,
|
||||
options: Record<string, unknown>
|
||||
) => string;
|
||||
isValidNumber(
|
||||
phoneNumber: string,
|
||||
options?: {
|
||||
regionCode?: string;
|
||||
}
|
||||
): boolean;
|
||||
e164: string;
|
||||
error: string;
|
||||
};
|
||||
Errors: {
|
||||
toLogFormat(error: Error): void;
|
||||
};
|
||||
Message: {
|
||||
CURRENT_SCHEMA_VERSION: number;
|
||||
VERSION_NEEDED_FOR_DISPLAY: number;
|
||||
GROUP: 'group';
|
||||
PRIVATE: 'private';
|
||||
|
||||
initializeSchemaVersion: (version: {
|
||||
message: unknown;
|
||||
logger: unknown;
|
||||
}) => unknown & {
|
||||
schemaVersion: number;
|
||||
};
|
||||
hasExpiration: (json: string) => boolean;
|
||||
};
|
||||
Sticker: {
|
||||
emoji: string;
|
||||
packId: string;
|
||||
packKey: string;
|
||||
stickerId: number;
|
||||
data: {
|
||||
pending: boolean;
|
||||
path: string;
|
||||
};
|
||||
width: number;
|
||||
height: number;
|
||||
path: string;
|
||||
};
|
||||
VisualAttachment: any;
|
||||
};
|
||||
Util: {
|
||||
isFileDangerous: any;
|
||||
GoogleChrome: {
|
||||
isImageTypeSupported: (contentType: string) => unknown;
|
||||
isVideoTypeSupported: (contentType: string) => unknown;
|
||||
};
|
||||
downloadAttachment: (attachment: WhatIsThis) => WhatIsThis;
|
||||
getStringForProfileChange: (
|
||||
change: unknown,
|
||||
changedContact: unknown,
|
||||
i18n: unknown
|
||||
) => string;
|
||||
getTextWithMentions: (
|
||||
bodyRanges: BodyRangesType,
|
||||
text: string
|
||||
) => string;
|
||||
deleteForEveryone: (
|
||||
message: unknown,
|
||||
del: unknown,
|
||||
bool: boolean
|
||||
) => void;
|
||||
zkgroup: {
|
||||
generateProfileKeyCredentialRequest: (
|
||||
clientZkProfileCipher: unknown,
|
||||
uuid: string,
|
||||
profileKey: unknown
|
||||
) => { requestHex: string; context: unknown };
|
||||
getClientZkProfileOperations: (params: unknown) => unknown;
|
||||
handleProfileKeyCredential: (
|
||||
clientZkProfileCipher: unknown,
|
||||
profileCredentialRequestContext: unknown,
|
||||
credential: unknown
|
||||
) => unknown;
|
||||
deriveProfileKeyVersion: (
|
||||
profileKey: unknown,
|
||||
uuid: string
|
||||
) => string;
|
||||
};
|
||||
combineNames: typeof combineNames;
|
||||
migrateColor: (color: string) => ColorType;
|
||||
createBatcher: (options: WhatIsThis) => WhatIsThis;
|
||||
Registration: {
|
||||
everDone: () => boolean;
|
||||
markDone: () => void;
|
||||
markEverDone: () => void;
|
||||
remove: () => void;
|
||||
};
|
||||
hasExpired: () => boolean;
|
||||
makeLookup: (conversations: WhatIsThis, key: string) => void;
|
||||
parseRemoteClientExpiration: (value: WhatIsThis) => WhatIsThis;
|
||||
};
|
||||
LinkPreviews: {
|
||||
isMediaLinkInWhitelist: any;
|
||||
getTitleMetaTag: any;
|
||||
getImageMetaTag: any;
|
||||
assembleChunks: any;
|
||||
getChunkPattern: any;
|
||||
isLinkInWhitelist: any;
|
||||
isStickerPack: (url: string) => boolean;
|
||||
isLinkSafeToPreview: (url: string) => boolean;
|
||||
findLinks: (body: string, unknown?: any) => Array<string>;
|
||||
getDomain: (url: string) => string;
|
||||
};
|
||||
GroupChange: {
|
||||
renderChange: (change: unknown, things: unknown) => Array<string>;
|
||||
};
|
||||
Components: {
|
||||
StagedLinkPreview: any;
|
||||
Quote: any;
|
||||
ContactDetail: any;
|
||||
MessageDetail: any;
|
||||
Lightbox: any;
|
||||
MediaGallery: any;
|
||||
CaptionEditor: any;
|
||||
ConversationHeader: any;
|
||||
AttachmentList: any;
|
||||
getCallingNotificationText: (
|
||||
callHistoryDetails: unknown,
|
||||
i18n: unknown
|
||||
) => string;
|
||||
LightboxGallery: any;
|
||||
};
|
||||
OS: {
|
||||
isLinux: () => boolean;
|
||||
};
|
||||
Workflow: {
|
||||
IdleDetector: WhatIsThis;
|
||||
MessageDataMigrator: WhatIsThis;
|
||||
};
|
||||
IndexedDB: {
|
||||
removeDatabase: WhatIsThis;
|
||||
doesDatabaseExist: WhatIsThis;
|
||||
};
|
||||
Views: WhatIsThis;
|
||||
State: WhatIsThis;
|
||||
Logs: WhatIsThis;
|
||||
conversationControllerStart: WhatIsThis;
|
||||
Emojis: {
|
||||
getInitialState: () => WhatIsThis;
|
||||
load: () => void;
|
||||
};
|
||||
RefreshSenderCertificate: WhatIsThis;
|
||||
};
|
||||
|
||||
ConversationController: ConversationController;
|
||||
Events: WhatIsThis;
|
||||
MessageController: MessageControllerType;
|
||||
WebAPI: WebAPIConnectType;
|
||||
Whisper: WhisperType;
|
||||
|
||||
AccountCache: Record<string, boolean>;
|
||||
AccountJobs: Record<string, Promise<void>>;
|
||||
|
||||
doesAccountCheckJobExist: (number: string) => boolean;
|
||||
checkForSignalAccount: (number: string) => Promise<void>;
|
||||
isSignalAccountCheckComplete: (number: string) => boolean;
|
||||
hasSignalAccount: (number: string) => boolean;
|
||||
getServerTrustRoot: () => WhatIsThis;
|
||||
readyForUpdates: () => void;
|
||||
|
||||
// Flags
|
||||
CALLING: boolean;
|
||||
GV2: boolean;
|
||||
|
@ -132,12 +495,13 @@ export type DCodeIOType = {
|
|||
};
|
||||
Long: Long & {
|
||||
fromBits: (low: number, high: number, unsigned: boolean) => number;
|
||||
fromString: (str: string) => Long;
|
||||
fromString: (str: string | null) => Long;
|
||||
};
|
||||
};
|
||||
|
||||
type MessageControllerType = {
|
||||
register: (id: string, model: MessageModelType) => MessageModelType;
|
||||
register: (id: string, model: MessageModel) => MessageModel;
|
||||
unregister: (id: string) => void;
|
||||
};
|
||||
|
||||
export class CertificateValidatorType {
|
||||
|
@ -211,7 +575,7 @@ export type LoggerType = (...args: Array<any>) => void;
|
|||
export type WhisperType = {
|
||||
events: {
|
||||
on: (name: string, callback: (param1: any, param2?: any) => void) => void;
|
||||
trigger: (name: string, param1: any, param2?: any) => void;
|
||||
trigger: (name: string, param1?: any, param2?: any) => void;
|
||||
};
|
||||
Database: {
|
||||
open: () => Promise<IDBDatabase>;
|
||||
|
@ -221,8 +585,120 @@ export type WhisperType = {
|
|||
reject: Function
|
||||
) => void;
|
||||
};
|
||||
GroupConversationCollection: typeof ConversationModelCollectionType;
|
||||
ConversationCollection: typeof ConversationModelCollectionType;
|
||||
Conversation: typeof ConversationModelType;
|
||||
ConversationCollectionType: ConversationModelCollectionType;
|
||||
Conversation: typeof ConversationModel;
|
||||
ConversationType: ConversationModel;
|
||||
MessageCollection: typeof MessageModelCollectionType;
|
||||
Message: typeof MessageModelType;
|
||||
MessageCollectionType: MessageModelCollectionType;
|
||||
MessageAttributesType: MessageAttributesType;
|
||||
Message: typeof MessageModel;
|
||||
MessageType: MessageModel;
|
||||
GroupMemberConversation: WhatIsThis;
|
||||
KeyChangeListener: WhatIsThis;
|
||||
ConfirmationDialogView: WhatIsThis;
|
||||
ClearDataView: WhatIsThis;
|
||||
ReactWrapperView: WhatIsThis;
|
||||
activeConfirmationView: WhatIsThis;
|
||||
ToastView: WhatIsThis;
|
||||
ConversationArchivedToast: WhatIsThis;
|
||||
ConversationUnarchivedToast: WhatIsThis;
|
||||
AppView: WhatIsThis;
|
||||
WallClockListener: WhatIsThis;
|
||||
MessageRequests: WhatIsThis;
|
||||
BannerView: any;
|
||||
RecorderView: any;
|
||||
GroupMemberList: any;
|
||||
KeyVerificationPanelView: any;
|
||||
SafetyNumberChangeDialogView: any;
|
||||
|
||||
ExpirationTimerOptions: {
|
||||
map: any;
|
||||
getName: (number: number) => string;
|
||||
getAbbreviated: (number: number) => string;
|
||||
};
|
||||
|
||||
Notifications: {
|
||||
removeBy: (filter: Partial<unknown>) => void;
|
||||
add: (notification: unknown) => void;
|
||||
clear: () => void;
|
||||
disable: () => void;
|
||||
enable: () => void;
|
||||
fastClear: () => void;
|
||||
on: (
|
||||
event: string,
|
||||
callback: (id: string, messageId: string) => void
|
||||
) => void;
|
||||
};
|
||||
|
||||
DeliveryReceipts: {
|
||||
add: (reciept: WhatIsThis) => void;
|
||||
forMessage: (conversation: unknown, message: unknown) => Array<WhatIsThis>;
|
||||
onReceipt: (receipt: WhatIsThis) => void;
|
||||
};
|
||||
|
||||
ReadReceipts: {
|
||||
add: (receipt: WhatIsThis) => WhatIsThis;
|
||||
forMessage: (conversation: unknown, message: unknown) => Array<WhatIsThis>;
|
||||
onReceipt: (receipt: WhatIsThis) => void;
|
||||
};
|
||||
|
||||
ReadSyncs: {
|
||||
add: (sync: WhatIsThis) => WhatIsThis;
|
||||
forMessage: (message: unknown) => WhatIsThis;
|
||||
onReceipt: (receipt: WhatIsThis) => WhatIsThis;
|
||||
};
|
||||
|
||||
ViewSyncs: {
|
||||
add: (sync: WhatIsThis) => WhatIsThis;
|
||||
forMessage: (message: unknown) => Array<WhatIsThis>;
|
||||
onSync: (sync: WhatIsThis) => WhatIsThis;
|
||||
};
|
||||
|
||||
Reactions: {
|
||||
forMessage: (message: unknown) => Array<WhatIsThis>;
|
||||
add: (reaction: unknown) => WhatIsThis;
|
||||
onReaction: (reactionModel: unknown) => unknown;
|
||||
};
|
||||
|
||||
Deletes: {
|
||||
add: (model: WhatIsThis) => WhatIsThis;
|
||||
forMessage: (message: unknown) => Array<WhatIsThis>;
|
||||
onDelete: (model: WhatIsThis) => void;
|
||||
};
|
||||
|
||||
IdenticonSVGView: WhatIsThis;
|
||||
|
||||
ExpiringMessagesListener: WhatIsThis;
|
||||
TapToViewMessagesListener: WhatIsThis;
|
||||
|
||||
deliveryReceiptQueue: PQueue<WhatIsThis>;
|
||||
deliveryReceiptBatcher: BatcherType<WhatIsThis>;
|
||||
RotateSignedPreKeyListener: WhatIsThis;
|
||||
|
||||
ExpiredToast: any;
|
||||
BlockedToast: any;
|
||||
BlockedGroupToast: any;
|
||||
LeftGroupToast: any;
|
||||
OriginalNotFoundToast: any;
|
||||
OriginalNoLongerAvailableToast: any;
|
||||
FoundButNotLoadedToast: any;
|
||||
VoiceNoteLimit: any;
|
||||
VoiceNoteMustBeOnlyAttachmentToast: any;
|
||||
TapToViewExpiredIncomingToast: any;
|
||||
TapToViewExpiredOutgoingToast: any;
|
||||
FileSavedToast: any;
|
||||
ReactionFailedToast: any;
|
||||
MessageBodyTooLongToast: any;
|
||||
FileSizeToast: any;
|
||||
UnableToLoadToast: any;
|
||||
DangerousFileTypeToast: any;
|
||||
OneNonImageAtATimeToast: any;
|
||||
CannotMixImageAndNonImageAttachmentsToast: any;
|
||||
MaxAttachmentsToast: any;
|
||||
TimerConflictToast: any;
|
||||
ConversationLoadingScreen: any;
|
||||
ConversationView: any;
|
||||
View: any;
|
||||
};
|
||||
|
|
|
@ -186,6 +186,7 @@
|
|||
"ts/components/conversation/**",
|
||||
"ts/components/emoji/**",
|
||||
"ts/components/stickers/**",
|
||||
"ts/models/**",
|
||||
"ts/notifications/**",
|
||||
"ts/protobuf/**",
|
||||
"ts/scripts/**",
|
||||
|
@ -196,7 +197,8 @@
|
|||
"ts/test/**",
|
||||
"ts/types/**",
|
||||
"ts/updater/**",
|
||||
"ts/util/**"
|
||||
"ts/util/**",
|
||||
"ts/views/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue