4cba16cb61
* Fetch all conversations on startup of app, not on inbox load A recent change to fetch conversations less didn't take into account all that can happen in the app without the inbox loaded. That only happens when the window is shown, and messages can come in with the app in the background. In that case, the conversation wouldn't have been loaded from the database, but would be saved to the database anyway, losing data. This change fetches all conversations as soon as the the data store is ready for a fetch. It also introduces failsafe throws to ensure that synchronous ConversationController accesses don't happen until the initial fetch is complete. A new getUnsafe() method was required to account for some of the model setup that happens during that initial conversation fetch. Fixes #1428 FREEBIE * Fix tests: ConversationController.load() required before get() FREEBIE
115 lines
3.5 KiB
JavaScript
115 lines
3.5 KiB
JavaScript
|
|
/*
|
|
* vim: ts=4:sw=4:expandtab
|
|
*/
|
|
;(function() {
|
|
'use strict';
|
|
window.Whisper = window.Whisper || {};
|
|
|
|
function destroyExpiredMessages() {
|
|
// Load messages that have expired and destroy them
|
|
var expired = new Whisper.MessageCollection();
|
|
expired.on('add', function(message) {
|
|
console.log('message', message.get('sent_at'), 'expired');
|
|
var conversation = message.getConversation();
|
|
if (conversation) {
|
|
conversation.trigger('expired', message);
|
|
}
|
|
|
|
// We delete after the trigger to allow the conversation time to process
|
|
// the expiration before the message is removed from the database.
|
|
message.destroy();
|
|
});
|
|
expired.on('reset', throttledCheckExpiringMessages);
|
|
|
|
expired.fetchExpired();
|
|
}
|
|
|
|
var timeout;
|
|
function checkExpiringMessages() {
|
|
// Look up the next expiring message and set a timer to destroy it
|
|
var expiring = new Whisper.MessageCollection();
|
|
expiring.once('add', function(next) {
|
|
var expires_at = next.get('expires_at');
|
|
console.log('next message expires', new Date(expires_at).toISOString());
|
|
|
|
var wait = expires_at - Date.now();
|
|
|
|
// In the past
|
|
if (wait < 0) { wait = 0; }
|
|
|
|
// Too far in the future, since it's limited to a 32-bit value
|
|
if (wait > 2147483647) { wait = 2147483647; }
|
|
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(destroyExpiredMessages, wait);
|
|
});
|
|
expiring.fetchNextExpiring();
|
|
}
|
|
var throttledCheckExpiringMessages = _.throttle(checkExpiringMessages, 1000);
|
|
|
|
Whisper.ExpiringMessagesListener = {
|
|
init: function(events) {
|
|
checkExpiringMessages();
|
|
events.on('timetravel', throttledCheckExpiringMessages);
|
|
},
|
|
update: throttledCheckExpiringMessages
|
|
};
|
|
|
|
var TimerOption = Backbone.Model.extend({
|
|
getName: function() {
|
|
return i18n([
|
|
'timerOption', this.get('time'), this.get('unit'),
|
|
].join('_')) || moment.duration(this.get('time'), this.get('unit')).humanize();
|
|
},
|
|
getAbbreviated: function() {
|
|
return i18n([
|
|
'timerOption', this.get('time'), this.get('unit'), 'abbreviated'
|
|
].join('_'));
|
|
}
|
|
});
|
|
Whisper.ExpirationTimerOptions = new (Backbone.Collection.extend({
|
|
model: TimerOption,
|
|
getName: function(seconds) {
|
|
if (!seconds) {
|
|
seconds = 0;
|
|
}
|
|
var o = this.findWhere({seconds: seconds});
|
|
if (o) { return o.getName(); }
|
|
else {
|
|
return [seconds, 'seconds'].join(' ');
|
|
}
|
|
},
|
|
getAbbreviated: function(seconds) {
|
|
if (!seconds) {
|
|
seconds = 0;
|
|
}
|
|
var o = this.findWhere({seconds: seconds});
|
|
if (o) { return o.getAbbreviated(); }
|
|
else {
|
|
return [seconds, 's'].join('');
|
|
}
|
|
}
|
|
}))([
|
|
[ 0, 'seconds' ],
|
|
[ 5, 'seconds' ],
|
|
[ 10, 'seconds' ],
|
|
[ 30, 'seconds' ],
|
|
[ 1, 'minute' ],
|
|
[ 5, 'minutes' ],
|
|
[ 30, 'minutes' ],
|
|
[ 1, 'hour' ],
|
|
[ 6, 'hours' ],
|
|
[ 12, 'hours' ],
|
|
[ 1, 'day' ],
|
|
[ 1, 'week' ],
|
|
].map(function(o) {
|
|
var duration = moment.duration(o[0], o[1]); // 5, 'seconds'
|
|
return {
|
|
time: o[0],
|
|
unit: o[1],
|
|
seconds: duration.asSeconds()
|
|
};
|
|
}));
|
|
|
|
})();
|