move MessageController to typescript

This commit is contained in:
Audric Ackermann 2020-12-02 11:26:31 +11:00
parent 727261b36a
commit 228e4ed662
No known key found for this signature in database
GPG key ID: 999F434D76324AD4
19 changed files with 101 additions and 98 deletions

View file

@ -156,7 +156,6 @@
<script type='text/javascript' src='js/registration.js'></script>
<script type='text/javascript' src='js/expire.js'></script>
<script type='text/javascript' src='js/conversation_controller.js'></script>
<script type='text/javascript' src='js/message_controller.js'></script>
<script type='text/javascript' src='js/views/react_wrapper_view.js'></script>
<script type='text/javascript' src='js/views/whisper_view.js'></script>

View file

@ -161,7 +161,6 @@
<script type='text/javascript' src='js/registration.js'></script>
<script type='text/javascript' src='js/expire.js'></script>
<script type='text/javascript' src='js/conversation_controller.js'></script>
<script type='text/javascript' src='js/message_controller.js'></script>
<script type='text/javascript' src='js/views/react_wrapper_view.js'></script>
<script type='text/javascript' src='js/views/whisper_view.js'></script>

View file

@ -2,7 +2,7 @@
Backbone,
Whisper,
ConversationController,
MessageController,
getMessageController,
_,
*/
@ -62,7 +62,7 @@
return null;
}
return MessageController.register(target.id, target);
return getMessageController().register(target.id, target);
},
async onReceipt(receipt) {
try {

View file

@ -2,7 +2,7 @@
_,
Backbone,
i18n,
MessageController,
getMessageController,
moment,
Whisper
*/
@ -22,7 +22,7 @@
await Promise.all(
messages.map(async fromDB => {
const message = MessageController.register(fromDB.id, fromDB);
const message = getMessageController().register(fromDB.id, fromDB);
window.log.info('Message expired', {
sentAt: message.get('sent_at'),

View file

@ -1,65 +0,0 @@
// eslint-disable-next-line func-names
(function() {
'use strict';
window.Whisper = window.Whisper || {};
const messageLookup = Object.create(null);
const SECOND = 1000;
const MINUTE = SECOND * 60;
const FIVE_MINUTES = MINUTE * 5;
const HOUR = MINUTE * 60;
function register(id, message) {
const existing = messageLookup[id];
if (existing) {
messageLookup[id] = {
message: existing.message,
timestamp: Date.now(),
};
return existing.message;
}
messageLookup[id] = {
message,
timestamp: Date.now(),
};
return message;
}
function unregister(id) {
delete messageLookup[id];
}
function cleanup() {
const messages = Object.values(messageLookup);
const now = Date.now();
for (let i = 0, max = messages.length; i < max; i += 1) {
const { message, timestamp } = messages[i];
const conversation = message.getConversation();
if (
now - timestamp > FIVE_MINUTES &&
(!conversation || !conversation.messageCollection.length)
) {
delete messageLookup[message.id];
}
}
}
function _get() {
return messageLookup;
}
setInterval(cleanup, HOUR);
window.MessageController = {
register,
unregister,
cleanup,
_get,
};
})();

View file

@ -5,7 +5,7 @@
Backbone,
libsession,
ConversationController,
MessageController,
getMessageController,
storage,
textsecure,
Whisper,
@ -461,7 +461,7 @@
this.clearContactTypingTimer(identifier);
const model = this.addSingleMessage(message);
MessageController.register(model.id, model);
getMessageController().register(model.id, model);
window.Whisper.events.trigger('messageAdded', {
conversationKey: this.id,
@ -1297,7 +1297,7 @@
};
const model = this.addSingleMessage(attributes);
const message = MessageController.register(model.id, model);
const message = getMessageController().register(model.id, model);
await message.commit(true);
@ -1780,7 +1780,7 @@
let read = await Promise.all(
_.map(oldUnread, async providedM => {
const m = MessageController.register(providedM.id, providedM);
const m = getMessageController().register(providedM.id, providedM);
if (!this.messageCollection.get(m.id)) {
window.log.warn(

View file

@ -4,7 +4,7 @@
storage,
filesize,
ConversationController,
MessageController,
getMessageController,
i18n,
Signal,
textsecure,
@ -302,7 +302,7 @@
this.cleanup();
},
async cleanup() {
MessageController.unregister(this.id);
getMessageController().unregister(this.id);
this.unload();
await deleteExternalMessageFiles(this.attributes);
},

View file

@ -1,4 +1,4 @@
/* global Whisper, Signal, setTimeout, clearTimeout, MessageController, NewReceiver */
/* global Whisper, Signal, setTimeout, clearTimeout, getMessageController, NewReceiver */
const { isNumber, omit } = require('lodash');
const getGuid = require('uuid/v4');
@ -150,7 +150,7 @@ async function _runJob(job) {
await _finishJob(null, id);
return;
}
message = MessageController.register(found.id, found);
message = getMessageController().register(found.id, found);
const pending = true;
await setAttachmentDownloadJobPending(id, pending);

View file

@ -1,5 +1,5 @@
/* global log, textsecure, libloki, Signal, Whisper, ConversationController,
clearTimeout, MessageController, libsignal, StringView, window, _,
clearTimeout, getMessageController, libsignal, StringView, window, _,
dcodeIO, Buffer, process */
const nodeFetch = require('node-fetch');
const { URL, URLSearchParams } = require('url');
@ -2134,7 +2134,7 @@ class LokiPublicChannelAPI {
});
if (found) {
const queryMessage = MessageController.register(found.id, found);
const queryMessage = getMessageController().register(found.id, found);
const replyTo = queryMessage.get('serverId');
if (replyTo) {
payload.reply_to = replyTo;

View file

@ -3,7 +3,7 @@
Backbone,
_,
ConversationController,
MessageController,
getMessageController,
window
*/
@ -60,7 +60,7 @@
return null;
}
return MessageController.register(target.id, target);
return getMessageController().register(target.id, target);
},
async onReceipt(receipt) {
try {

View file

@ -1,7 +1,7 @@
/* global
Backbone,
Whisper,
MessageController
getMessageController
*/
/* eslint-disable more/no-then */
@ -61,7 +61,7 @@
return;
}
const message = MessageController.register(found.id, found);
const message = getMessageController().register(found.id, found);
const readAt = receipt.get('read_at');
// If message is unread, we mark it read. Otherwise, we update the expiration

View file

@ -176,6 +176,9 @@ window.setPassword = (passPhrase, oldPhrase) =>
window.passwordUtil = require('./ts/util/passwordUtils');
window.libsession = require('./ts/session');
window.getMessageController =
window.libsession.Messages.MessageController.getInstance;
// We never do these in our code, so we'll prevent it everywhere
window.open = () => null;
// eslint-disable-next-line no-eval, no-multi-assign

View file

@ -192,7 +192,6 @@
<script type="text/javascript" src="../js/models/messages.js" data-cover></script>
<script type="text/javascript" src="../js/models/conversations.js" data-cover></script>
<script type="text/javascript" src="../js/conversation_controller.js" data-cover></script>
<script type="text/javascript" src="../js/message_controller.js" data-cover></script>
<script type="text/javascript" src="../js/keychange_listener.js" data-cover></script>
<script type="text/javascript" src="../js/expiring_messages.js" data-cover></script>
<script type="text/javascript" src="../js/notifications.js" data-cover></script>

View file

@ -138,7 +138,7 @@ export class SessionInboxView extends React.Component<Props, State> {
return null;
}
const msg = window.MessageController._get()[m.identifier];
const msg = window.getMessageController().get(m.identifier);
if (!msg || !msg.message) {
return null;

View file

@ -100,7 +100,7 @@ async function copyFromQuotedMessage(
quote: Quote,
attemptCount: number = 1
): Promise<void> {
const { Whisper, MessageController } = window;
const { Whisper, getMessageController } = window;
const { upgradeMessageSchema } = window.Signal.Migrations;
const { Message: TypedMessage, Errors } = window.Signal.Types;
@ -142,7 +142,7 @@ async function copyFromQuotedMessage(
window.log.info(`Found quoted message id: ${id}`);
quote.referencedMessageNotFound = false;
const queryMessage = MessageController.register(found.id, found);
const queryMessage = getMessageController().register(found.id, found);
quote.text = queryMessage.get('body');
if (attemptCount > 1) {
@ -552,11 +552,11 @@ export async function handleMessageJob(
);
}
const { Whisper, MessageController } = window;
const { Whisper, getMessageController } = window;
const id = await message.commit();
message.set({ id });
MessageController.register(message.id, message);
getMessageController().register(message.id, message);
// Note that this can save the message again, if jobs were queued. We need to
// call it after we have an id for this message, because the jobs refer back

View file

@ -117,8 +117,7 @@ export async function createMediumGroup(
};
const dbMessage = await addUpdateMessage(convo, groupDiff, 'outgoing');
window.MessageController.register(dbMessage.id, dbMessage);
window.getMessageController().register(dbMessage.id, dbMessage);
// be sure to call this before sending the message.
// the sending pipeline needs to know from GroupUtils when a message is for a medium group
@ -177,7 +176,7 @@ export async function createLegacyGroup(
};
const dbMessage = await addUpdateMessage(convo, diff, 'outgoing');
window.MessageController.register(dbMessage.id, dbMessage);
window.getMessageController().register(dbMessage.id, dbMessage);
await sendGroupUpdate(convo, diff, groupDetails, dbMessage.id);
@ -217,7 +216,7 @@ export async function leaveMediumGroup(groupId: string) {
sent_at: now,
received_at: now,
});
window.MessageController.register(dbMessage.id, dbMessage);
window.getMessageController().register(dbMessage.id, dbMessage);
const ourPrimary = await UserUtil.getPrimary();
const members = convo.get('members').filter(m => m !== ourPrimary.key);
@ -411,7 +410,7 @@ export async function initiateGroupUpdate(
}
const dbMessage = await addUpdateMessage(convo, diff, 'outgoing');
window.MessageController.register(dbMessage.id, dbMessage);
window.getMessageController().register(dbMessage.id, dbMessage);
await sendGroupUpdate(convo, diff, updateObj, dbMessage.id);
}

View file

@ -0,0 +1,67 @@
// You can see MessageController for in memory registered messages.
// Ee register messages to it everytime we send one, so that when an event happens we can find which message it was based on this id.
// 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 MessageController {
private static instance: MessageController | null;
private readonly messageLookup: Map<string, any>;
private constructor() {
this.messageLookup = new Map();
// cleanup every hour the cache
setInterval(this.cleanup, 3600 * 1000);
}
public static getInstance() {
if (MessageController.instance) {
return MessageController.instance;
}
MessageController.instance = new MessageController();
return MessageController.instance;
}
public register(id: string, message: any) {
const existing = this.messageLookup.get(id);
if (existing) {
this.messageLookup.set(id, {
message: existing.message,
timestamp: Date.now(),
});
return existing.message;
}
this.messageLookup.set(id, {
message,
timestamp: Date.now(),
});
return message;
}
public unregister(id: string) {
this.messageLookup.delete(id);
}
public cleanup() {
window.log.warn('Cleaning up getMessageController() oldest messages...');
const messages = Object.values(this.messageLookup);
const now = Date.now();
// tslint:disable-next-line: one-variable-per-declaration
for (let i = 0, max = messages.length; i < max; i += 1) {
const { message, timestamp } = messages[i];
const conversation = message.getConversation();
if (
now - timestamp > 5 * 60 * 1000 &&
(!conversation || !conversation.messageCollection.length)
) {
this.unregister(message.id);
}
}
}
// tslint:disable-next-line: function-name
public get(identifier: string) {
return this.messageLookup.get(identifier);
}
}

View file

@ -1,3 +1,4 @@
import * as Outgoing from './outgoing';
import { MessageController } from './MessageController';
export { Outgoing };
export { Outgoing, MessageController };

3
ts/window.d.ts vendored
View file

@ -17,6 +17,7 @@ import {} from 'styled-components/cssprop';
import { ConversationControllerType } from '../js/ConversationController';
import { any } from 'underscore';
import { Store } from 'redux';
import { MessageController } from './session/messages/MessageController';
/*
We declare window stuff here instead of global.d.ts because we are importing other declarations.
If you import anything in global.d.ts, the type system won't work correctly.
@ -33,7 +34,7 @@ declare global {
LokiFileServerAPI: any;
LokiPublicChatAPI: any;
LokiSnodeAPI: any;
MessageController: any;
getMessageController: () => MessageController;
Session: any;
Signal: SignalInterface;
StringView: any;