Merge pull request #1423 from Bilb/fix-conversation-message-list
Fix conversation message listpull/1435/head
commit
62e637857b
@ -1,336 +1,339 @@
|
|||||||
import {
|
import {
|
||||||
ConversationAttributes,
|
ConversationAttributes,
|
||||||
ConversationModel,
|
ConversationModel,
|
||||||
} from '../../../js/models/conversations';
|
} from '../../../js/models/conversations';
|
||||||
import { BlockedNumberController } from '../../util';
|
import { BlockedNumberController } from '../../util';
|
||||||
|
|
||||||
// It's not only data from the db which is stored on the MessageController entries, we could fetch this again. What we cannot fetch from the db and which is stored here is all listeners a particular messages is linked to for instance. We will be able to get rid of this once we don't use backbone models at all
|
// It's not only data from the db which is stored on the MessageController entries, we could fetch this again. What we cannot fetch from the db and which is stored here is all listeners a particular messages is linked to for instance. We will be able to get rid of this once we don't use backbone models at all
|
||||||
export class ConversationController {
|
export class ConversationController {
|
||||||
private static instance: ConversationController | null;
|
private static instance: ConversationController | null;
|
||||||
private readonly conversations: any;
|
private readonly conversations: any;
|
||||||
private _initialFetchComplete: boolean = false;
|
private _initialFetchComplete: boolean = false;
|
||||||
private _initialPromise?: Promise<any>;
|
private _initialPromise?: Promise<any>;
|
||||||
|
|
||||||
private constructor() {
|
private constructor() {
|
||||||
this.conversations = new window.Whisper.ConversationCollection();
|
this.conversations = new window.Whisper.ConversationCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance() {
|
||||||
|
if (ConversationController.instance) {
|
||||||
|
return ConversationController.instance;
|
||||||
}
|
}
|
||||||
|
ConversationController.instance = new ConversationController();
|
||||||
public static getInstance() {
|
return ConversationController.instance;
|
||||||
if (ConversationController.instance) {
|
}
|
||||||
return ConversationController.instance;
|
|
||||||
}
|
public get(id: string): ConversationModel {
|
||||||
ConversationController.instance = new ConversationController();
|
if (!this._initialFetchComplete) {
|
||||||
return ConversationController.instance;
|
throw new Error(
|
||||||
|
'ConversationController.get() needs complete initial fetch'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get(id: string): ConversationModel {
|
return this.conversations.get(id);
|
||||||
if (!this._initialFetchComplete) {
|
}
|
||||||
throw new Error(
|
|
||||||
'ConversationController.get() needs complete initial fetch'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.conversations.get(id);
|
public getOrThrow(id: string) {
|
||||||
|
if (!this._initialFetchComplete) {
|
||||||
|
throw new Error(
|
||||||
|
'ConversationController.get() needs complete initial fetch'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getOrThrow(id: string) {
|
const convo = this.conversations.get(id);
|
||||||
if (!this._initialFetchComplete) {
|
|
||||||
throw new Error(
|
|
||||||
'ConversationController.get() needs complete initial fetch'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const convo = this.conversations.get(id);
|
if (convo) {
|
||||||
|
return convo;
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
`Conversation ${id} does not exist on ConversationController.get()`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Needed for some model setup which happens during the initial fetch() call below
|
||||||
|
public getUnsafe(id: string) {
|
||||||
|
return this.conversations.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public dangerouslyCreateAndAdd(attributes: ConversationAttributes) {
|
||||||
|
return this.conversations.add(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOrCreate(id: string, type: string) {
|
||||||
|
if (typeof id !== 'string') {
|
||||||
|
throw new TypeError("'id' must be a string");
|
||||||
|
}
|
||||||
|
|
||||||
if (convo) {
|
if (type !== 'private' && type !== 'group') {
|
||||||
return convo;
|
throw new TypeError(
|
||||||
}
|
`'type' must be 'private' or 'group'; got: '${type}'`
|
||||||
throw new Error(
|
);
|
||||||
`Conversation ${id} does not exist on ConversationController.get()`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// Needed for some model setup which happens during the initial fetch() call below
|
|
||||||
public getUnsafe(id: string) {
|
if (!this._initialFetchComplete) {
|
||||||
return this.conversations.get(id);
|
throw new Error(
|
||||||
|
'ConversationController.get() needs complete initial fetch'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public dangerouslyCreateAndAdd(attributes: ConversationAttributes) {
|
let conversation = this.conversations.get(id);
|
||||||
return this.conversations.add(attributes);
|
if (conversation) {
|
||||||
|
return conversation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getOrCreate(id: string, type: string) {
|
conversation = this.conversations.add({
|
||||||
if (typeof id !== 'string') {
|
id,
|
||||||
throw new TypeError("'id' must be a string");
|
type,
|
||||||
}
|
version: 2,
|
||||||
|
} as any);
|
||||||
if (type !== 'private' && type !== 'group') {
|
|
||||||
throw new TypeError(
|
const create = async () => {
|
||||||
`'type' must be 'private' or 'group'; got: '${type}'`
|
if (!conversation.isValid()) {
|
||||||
);
|
const validationError = conversation.validationError || {};
|
||||||
}
|
window.log.error(
|
||||||
|
'Contact is not valid. Not saving, but adding to collection:',
|
||||||
if (!this._initialFetchComplete) {
|
conversation.idForLogging(),
|
||||||
throw new Error(
|
validationError.stack
|
||||||
'ConversationController.get() needs complete initial fetch'
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let conversation = this.conversations.get(id);
|
|
||||||
if (conversation) {
|
|
||||||
return conversation;
|
|
||||||
}
|
|
||||||
|
|
||||||
conversation = this.conversations.add({
|
|
||||||
id,
|
|
||||||
type,
|
|
||||||
version: 2,
|
|
||||||
} as any);
|
|
||||||
|
|
||||||
const create = async () => {
|
|
||||||
if (!conversation.isValid()) {
|
|
||||||
const validationError = conversation.validationError || {};
|
|
||||||
window.log.error(
|
|
||||||
'Contact is not valid. Not saving, but adding to collection:',
|
|
||||||
conversation.idForLogging(),
|
|
||||||
validationError.stack
|
|
||||||
);
|
|
||||||
|
|
||||||
return conversation;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await window.Signal.Data.saveConversation(conversation.attributes, {
|
|
||||||
Conversation: window.Whisper.Conversation,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
window.log.error(
|
|
||||||
'Conversation save failed! ',
|
|
||||||
id,
|
|
||||||
type,
|
|
||||||
'Error:',
|
|
||||||
error && error.stack ? error.stack : error
|
|
||||||
);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return conversation;
|
|
||||||
};
|
|
||||||
|
|
||||||
conversation.initialPromise = create();
|
|
||||||
conversation.initialPromise.then(async () => {
|
|
||||||
if (!conversation.isPublic() && !conversation.isRss()) {
|
|
||||||
await Promise.all([
|
|
||||||
conversation.updateProfileAvatar(),
|
|
||||||
// NOTE: we request snodes updating the cache, but ignore the result
|
|
||||||
window.SnodePool.getSnodesFor(id),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
if (window.inboxStore) {
|
|
||||||
conversation.on('change', this.updateReduxConvoChanged);
|
|
||||||
window.inboxStore.dispatch(
|
|
||||||
window.actionsCreators.conversationAdded(
|
|
||||||
conversation.id,
|
|
||||||
conversation.getProps()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return conversation;
|
return conversation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getContactProfileNameOrShortenedPubKey(pubKey: string): string {
|
try {
|
||||||
const conversation = ConversationController.getInstance().get(pubKey);
|
await window.Signal.Data.saveConversation(conversation.attributes, {
|
||||||
if (!conversation) {
|
Conversation: window.Whisper.Conversation,
|
||||||
return pubKey;
|
});
|
||||||
}
|
} catch (error) {
|
||||||
return conversation.getContactProfileNameOrShortenedPubKey();
|
window.log.error(
|
||||||
|
'Conversation save failed! ',
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
'Error:',
|
||||||
|
error && error.stack ? error.stack : error
|
||||||
|
);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return conversation;
|
||||||
|
};
|
||||||
|
|
||||||
|
conversation.initialPromise = create();
|
||||||
|
conversation.initialPromise.then(async () => {
|
||||||
|
if (window.inboxStore) {
|
||||||
|
conversation.on('change', this.updateReduxConvoChanged);
|
||||||
|
window.inboxStore.dispatch(
|
||||||
|
window.actionsCreators.conversationAdded(
|
||||||
|
conversation.id,
|
||||||
|
conversation.getProps()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!conversation.isPublic() && !conversation.isRss()) {
|
||||||
|
await Promise.all([
|
||||||
|
conversation.updateProfileAvatar(),
|
||||||
|
// NOTE: we request snodes updating the cache, but ignore the result
|
||||||
|
window.SnodePool.getSnodesFor(id),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return conversation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getContactProfileNameOrShortenedPubKey(pubKey: string): string {
|
||||||
|
const conversation = ConversationController.getInstance().get(pubKey);
|
||||||
|
if (!conversation) {
|
||||||
|
return pubKey;
|
||||||
}
|
}
|
||||||
|
return conversation.getContactProfileNameOrShortenedPubKey();
|
||||||
|
}
|
||||||
|
|
||||||
public getContactProfileNameOrFullPubKey(pubKey: string): string {
|
public getContactProfileNameOrFullPubKey(pubKey: string): string {
|
||||||
const conversation = this.conversations.get(pubKey);
|
const conversation = this.conversations.get(pubKey);
|
||||||
if (!conversation) {
|
if (!conversation) {
|
||||||
return pubKey;
|
return pubKey;
|
||||||
}
|
|
||||||
return conversation.getContactProfileNameOrFullPubKey();
|
|
||||||
}
|
}
|
||||||
|
return conversation.getContactProfileNameOrFullPubKey();
|
||||||
|
}
|
||||||
|
|
||||||
public isMediumGroup(hexEncodedGroupPublicKey: string): boolean {
|
public isMediumGroup(hexEncodedGroupPublicKey: string): boolean {
|
||||||
const convo = this.conversations.get(hexEncodedGroupPublicKey);
|
const convo = this.conversations.get(hexEncodedGroupPublicKey);
|
||||||
if (convo) {
|
if (convo) {
|
||||||
return convo.isMediumGroup();
|
return convo.isMediumGroup();
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
public async getOrCreateAndWait(id: any, type: string) {
|
}
|
||||||
const initialPromise = this._initialPromise !== undefined ? this._initialPromise : Promise.resolve();
|
|
||||||
return initialPromise.then(() => {
|
public async getOrCreateAndWait(id: any, type: string) {
|
||||||
if (!id) {
|
const initialPromise =
|
||||||
return Promise.reject(
|
this._initialPromise !== undefined
|
||||||
new Error('getOrCreateAndWait: invalid id passed.')
|
? this._initialPromise
|
||||||
);
|
: Promise.resolve();
|
||||||
}
|
return initialPromise.then(() => {
|
||||||
const pubkey = id && id.key ? id.key : id;
|
if (!id) {
|
||||||
const conversation = this.getOrCreate(pubkey, type);
|
return Promise.reject(
|
||||||
|
new Error('getOrCreateAndWait: invalid id passed.')
|
||||||
if (conversation) {
|
);
|
||||||
return conversation.initialPromise.then(() => conversation);
|
}
|
||||||
}
|
const pubkey = id && id.key ? id.key : id;
|
||||||
|
const conversation = this.getOrCreate(pubkey, type);
|
||||||
return Promise.reject(
|
|
||||||
new Error('getOrCreateAndWait: did not get conversation')
|
if (conversation) {
|
||||||
);
|
return conversation.initialPromise.then(() => conversation);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
return Promise.reject(
|
||||||
|
new Error('getOrCreateAndWait: did not get conversation')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getAllGroupsInvolvingId(id: String) {
|
||||||
|
const groups = await window.Signal.Data.getAllGroupsInvolvingId(id, {
|
||||||
|
ConversationCollection: window.Whisper.ConversationCollection,
|
||||||
|
});
|
||||||
|
return groups.map((group: any) => this.conversations.add(group));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deleteContact(id: string) {
|
||||||
|
if (typeof id !== 'string') {
|
||||||
|
throw new TypeError("'id' must be a string");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAllGroupsInvolvingId(id: String) {
|
if (!this._initialFetchComplete) {
|
||||||
const groups = await window.Signal.Data.getAllGroupsInvolvingId(id, {
|
throw new Error(
|
||||||
ConversationCollection: window.Whisper.ConversationCollection,
|
'ConversationController.get() needs complete initial fetch'
|
||||||
});
|
);
|
||||||
return groups.map((group: any) => this.conversations.add(group));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deleteContact(id: string) {
|
const conversation = this.conversations.get(id);
|
||||||
if (typeof id !== 'string') {
|
if (!conversation) {
|
||||||
throw new TypeError("'id' must be a string");
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._initialFetchComplete) {
|
|
||||||
throw new Error(
|
|
||||||
'ConversationController.get() needs complete initial fetch'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const conversation = this.conversations.get(id);
|
|
||||||
if (!conversation) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close group leaving
|
|
||||||
if (conversation.isClosedGroup()) {
|
|
||||||
await conversation.leaveGroup();
|
|
||||||
} else if (conversation.isPublic()) {
|
|
||||||
const channelAPI = await conversation.getPublicSendData();
|
|
||||||
if (channelAPI === null) {
|
|
||||||
window.log.warn(`Could not get API for public conversation ${id}`);
|
|
||||||
} else {
|
|
||||||
channelAPI.serverAPI.partChannel(channelAPI.channelId);
|
|
||||||
}
|
|
||||||
} else if (conversation.isPrivate()) {
|
|
||||||
const deviceIds = await window.textsecure.storage.protocol.getDeviceIds(
|
|
||||||
id
|
|
||||||
);
|
|
||||||
await Promise.all(
|
|
||||||
deviceIds.map((deviceId: string) => {
|
|
||||||
const address = new window.libsignal.SignalProtocolAddress(
|
|
||||||
id,
|
|
||||||
deviceId
|
|
||||||
);
|
|
||||||
const sessionCipher = new window.libsignal.SessionCipher(
|
|
||||||
window.textsecure.storage.protocol,
|
|
||||||
address
|
|
||||||
);
|
|
||||||
return sessionCipher.deleteAllSessionsForDevice();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await conversation.destroyMessages();
|
|
||||||
|
|
||||||
await window.Signal.Data.removeConversation(id, {
|
|
||||||
Conversation: window.Whisper.Conversation,
|
|
||||||
});
|
|
||||||
conversation.off('change', this.updateReduxConvoChanged);
|
|
||||||
this.conversations.remove(conversation);
|
|
||||||
if (window.inboxStore) {
|
|
||||||
window.inboxStore.dispatch(
|
|
||||||
window.actionsCreators.conversationRemoved(conversation.id)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getConversations(): Array<ConversationModel> {
|
// Close group leaving
|
||||||
return Array.from(this.conversations.models.values());
|
if (conversation.isClosedGroup()) {
|
||||||
|
await conversation.leaveGroup();
|
||||||
|
} else if (conversation.isPublic()) {
|
||||||
|
const channelAPI = await conversation.getPublicSendData();
|
||||||
|
if (channelAPI === null) {
|
||||||
|
window.log.warn(`Could not get API for public conversation ${id}`);
|
||||||
|
} else {
|
||||||
|
channelAPI.serverAPI.partChannel(channelAPI.channelId);
|
||||||
|
}
|
||||||
|
} else if (conversation.isPrivate()) {
|
||||||
|
const deviceIds = await window.textsecure.storage.protocol.getDeviceIds(
|
||||||
|
id
|
||||||
|
);
|
||||||
|
await Promise.all(
|
||||||
|
deviceIds.map((deviceId: string) => {
|
||||||
|
const address = new window.libsignal.SignalProtocolAddress(
|
||||||
|
id,
|
||||||
|
deviceId
|
||||||
|
);
|
||||||
|
const sessionCipher = new window.libsignal.SessionCipher(
|
||||||
|
window.textsecure.storage.protocol,
|
||||||
|
address
|
||||||
|
);
|
||||||
|
return sessionCipher.deleteAllSessionsForDevice();
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async load() {
|
await conversation.destroyMessages();
|
||||||
window.log.info('ConversationController: starting initial fetch');
|
|
||||||
|
await window.Signal.Data.removeConversation(id, {
|
||||||
if (this.conversations.length) {
|
Conversation: window.Whisper.Conversation,
|
||||||
throw new Error('ConversationController: Already loaded!');
|
});
|
||||||
}
|
conversation.off('change', this.updateReduxConvoChanged);
|
||||||
|
this.conversations.remove(conversation);
|
||||||
const load = async () => {
|
if (window.inboxStore) {
|
||||||
try {
|
window.inboxStore.dispatch(
|
||||||
const collection = await window.Signal.Data.getAllConversations({
|
window.actionsCreators.conversationRemoved(conversation.id)
|
||||||
ConversationCollection: window.Whisper.ConversationCollection,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
this.conversations.add(collection.models);
|
|
||||||
|
|
||||||
this._initialFetchComplete = true;
|
|
||||||
const promises: any = [];
|
|
||||||
this.conversations.forEach((conversation: ConversationModel) => {
|
|
||||||
if (!conversation.get('lastMessage')) {
|
|
||||||
// tslint:disable-next-line: no-void-expression
|
|
||||||
promises.push(conversation.updateLastMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
promises.concat([
|
|
||||||
conversation.updateProfileName(),
|
|
||||||
conversation.updateProfileAvatar(),
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
this.conversations.forEach((conversation: ConversationModel) => {
|
|
||||||
// register for change event on each conversation, and forward to redux
|
|
||||||
conversation.on('change', this.updateReduxConvoChanged);
|
|
||||||
});
|
|
||||||
await Promise.all(promises);
|
|
||||||
|
|
||||||
// Remove any unused images
|
|
||||||
window.profileImages.removeImagesNotInArray(
|
|
||||||
this.conversations.map((c: any) => c.id)
|
|
||||||
);
|
|
||||||
window.log.info('ConversationController: done with initial fetch');
|
|
||||||
} catch (error) {
|
|
||||||
window.log.error(
|
|
||||||
'ConversationController: initial fetch failed',
|
|
||||||
error && error.stack ? error.stack : error
|
|
||||||
);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await BlockedNumberController.load();
|
|
||||||
|
|
||||||
this._initialPromise = load();
|
|
||||||
|
|
||||||
return this._initialPromise;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public loadPromise() {
|
public getConversations(): Array<ConversationModel> {
|
||||||
return this._initialPromise;
|
return Array.from(this.conversations.models.values());
|
||||||
}
|
}
|
||||||
public reset() {
|
|
||||||
this._initialPromise = Promise.resolve();
|
public async load() {
|
||||||
this._initialFetchComplete = false;
|
window.log.info('ConversationController: starting initial fetch');
|
||||||
if (window.inboxStore) {
|
|
||||||
this.conversations.forEach((convo: ConversationModel) =>
|
if (this.conversations.length) {
|
||||||
convo.off('change', this.updateReduxConvoChanged)
|
throw new Error('ConversationController: Already loaded!');
|
||||||
);
|
|
||||||
|
|
||||||
window.inboxStore.dispatch(
|
|
||||||
window.actionsCreators.removeAllConversations()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.conversations.reset([]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateReduxConvoChanged(convo: ConversationModel) {
|
const load = async () => {
|
||||||
if (window.inboxStore) {
|
try {
|
||||||
window.inboxStore.dispatch(
|
const collection = await window.Signal.Data.getAllConversations({
|
||||||
window.actionsCreators.conversationChanged(convo.id, convo.getProps())
|
ConversationCollection: window.Whisper.ConversationCollection,
|
||||||
);
|
});
|
||||||
}
|
|
||||||
|
this.conversations.add(collection.models);
|
||||||
|
|
||||||
|
this._initialFetchComplete = true;
|
||||||
|
const promises: any = [];
|
||||||
|
this.conversations.forEach((conversation: ConversationModel) => {
|
||||||
|
if (!conversation.get('lastMessage')) {
|
||||||
|
// tslint:disable-next-line: no-void-expression
|
||||||
|
promises.push(conversation.updateLastMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
promises.concat([
|
||||||
|
conversation.updateProfileName(),
|
||||||
|
conversation.updateProfileAvatar(),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
this.conversations.forEach((conversation: ConversationModel) => {
|
||||||
|
// register for change event on each conversation, and forward to redux
|
||||||
|
conversation.on('change', this.updateReduxConvoChanged);
|
||||||
|
});
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
// Remove any unused images
|
||||||
|
window.profileImages.removeImagesNotInArray(
|
||||||
|
this.conversations.map((c: any) => c.id)
|
||||||
|
);
|
||||||
|
window.log.info('ConversationController: done with initial fetch');
|
||||||
|
} catch (error) {
|
||||||
|
window.log.error(
|
||||||
|
'ConversationController: initial fetch failed',
|
||||||
|
error && error.stack ? error.stack : error
|
||||||
|
);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await BlockedNumberController.load();
|
||||||
|
|
||||||
|
this._initialPromise = load();
|
||||||
|
|
||||||
|
return this._initialPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
public loadPromise() {
|
||||||
|
return this._initialPromise;
|
||||||
|
}
|
||||||
|
public reset() {
|
||||||
|
this._initialPromise = Promise.resolve();
|
||||||
|
this._initialFetchComplete = false;
|
||||||
|
if (window.inboxStore) {
|
||||||
|
this.conversations.forEach((convo: ConversationModel) =>
|
||||||
|
convo.off('change', this.updateReduxConvoChanged)
|
||||||
|
);
|
||||||
|
|
||||||
|
window.inboxStore.dispatch(
|
||||||
|
window.actionsCreators.removeAllConversations()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.conversations.reset([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateReduxConvoChanged(convo: ConversationModel) {
|
||||||
|
if (window.inboxStore) {
|
||||||
|
window.inboxStore.dispatch(
|
||||||
|
window.actionsCreators.conversationChanged(convo.id, convo.getProps())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue