2018-06-27 20:53:49 +00:00
|
|
|
/* global moment: false */
|
|
|
|
/* global Whisper: false */
|
|
|
|
/* global extension: false */
|
|
|
|
/* global i18n: false */
|
|
|
|
/* global _: false */
|
|
|
|
|
|
|
|
// eslint-disable-next-line func-names
|
2018-04-27 21:25:04 +00:00
|
|
|
(function() {
|
|
|
|
'use strict';
|
2018-06-27 20:53:49 +00:00
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
window.Whisper = window.Whisper || {};
|
2015-11-06 22:58:26 +00:00
|
|
|
|
2018-06-27 20:53:49 +00:00
|
|
|
function extendedRelativeTime(number, string) {
|
|
|
|
return moment.duration(-1 * number, string).humanize(string !== 's');
|
|
|
|
}
|
|
|
|
|
|
|
|
const extendedFormats = {
|
|
|
|
y: 'lll',
|
|
|
|
M: `${i18n('timestampFormat_M') || 'MMM D'} LT`,
|
|
|
|
d: 'ddd LT',
|
|
|
|
};
|
|
|
|
|
|
|
|
function shortRelativeTime(number, string) {
|
|
|
|
return moment.duration(number, string).humanize();
|
|
|
|
}
|
|
|
|
const shortFormats = {
|
|
|
|
y: 'll',
|
|
|
|
M: i18n('timestampFormat_M') || 'MMM D',
|
|
|
|
d: 'ddd',
|
|
|
|
};
|
|
|
|
|
|
|
|
function getRelativeTimeSpanString(rawTimestamp, options = {}) {
|
|
|
|
_.defaults(options, { extended: false });
|
|
|
|
|
|
|
|
const relativeTime = options.extended
|
|
|
|
? extendedRelativeTime
|
|
|
|
: shortRelativeTime;
|
|
|
|
const formats = options.extended ? extendedFormats : shortFormats;
|
|
|
|
|
|
|
|
// Convert to moment timestamp if it isn't already
|
|
|
|
const timestamp = moment(rawTimestamp);
|
|
|
|
const now = moment();
|
|
|
|
const timediff = moment.duration(now - timestamp);
|
|
|
|
|
|
|
|
if (timediff.years() > 0) {
|
|
|
|
return timestamp.format(formats.y);
|
|
|
|
} else if (timediff.months() > 0 || timediff.days() > 6) {
|
|
|
|
return timestamp.format(formats.M);
|
|
|
|
} else if (timediff.days() > 0) {
|
|
|
|
return timestamp.format(formats.d);
|
|
|
|
} else if (timediff.hours() >= 1) {
|
|
|
|
return relativeTime(timediff.hours(), 'h');
|
|
|
|
} else if (timediff.minutes() >= 1) {
|
|
|
|
// Note that humanize seems to jump to '1 hour' as soon as we cross 45 minutes
|
|
|
|
return relativeTime(timediff.minutes(), 'm');
|
|
|
|
}
|
|
|
|
|
|
|
|
return relativeTime(timediff.seconds(), 's');
|
|
|
|
}
|
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
Whisper.TimestampView = Whisper.View.extend({
|
2018-06-27 20:53:49 +00:00
|
|
|
initialize() {
|
2018-04-27 21:25:04 +00:00
|
|
|
extension.windows.onClosed(this.clearTimeout.bind(this));
|
|
|
|
},
|
2018-06-27 20:53:49 +00:00
|
|
|
update() {
|
2018-04-27 21:25:04 +00:00
|
|
|
this.clearTimeout();
|
2018-06-27 20:53:49 +00:00
|
|
|
const millisNow = Date.now();
|
|
|
|
let millis = this.$el.data('timestamp');
|
2018-04-27 21:25:04 +00:00
|
|
|
if (millis === '') {
|
|
|
|
return;
|
|
|
|
}
|
2018-06-27 20:53:49 +00:00
|
|
|
if (millis >= millisNow) {
|
|
|
|
millis = millisNow;
|
2018-04-27 21:25:04 +00:00
|
|
|
}
|
2018-06-27 20:53:49 +00:00
|
|
|
const result = this.getRelativeTimeSpanString(millis);
|
|
|
|
this.delay = this.getDelay(millis);
|
2018-04-27 21:25:04 +00:00
|
|
|
this.$el.text(result);
|
2015-11-06 22:58:26 +00:00
|
|
|
|
2018-06-27 20:53:49 +00:00
|
|
|
const timestamp = moment(millis);
|
2018-04-27 21:25:04 +00:00
|
|
|
this.$el.attr('title', timestamp.format('llll'));
|
2016-04-19 02:48:54 +00:00
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
if (this.delay) {
|
|
|
|
if (this.delay < 0) {
|
|
|
|
this.delay = 1000;
|
2016-04-19 02:48:54 +00:00
|
|
|
}
|
2018-04-27 21:25:04 +00:00
|
|
|
this.timeout = setTimeout(this.update.bind(this), this.delay);
|
|
|
|
}
|
|
|
|
},
|
2018-06-27 20:53:49 +00:00
|
|
|
clearTimeout() {
|
2018-04-27 21:25:04 +00:00
|
|
|
clearTimeout(this.timeout);
|
|
|
|
},
|
2018-06-27 20:53:49 +00:00
|
|
|
getRelativeTimeSpanString(timestamp) {
|
|
|
|
return getRelativeTimeSpanString(timestamp);
|
|
|
|
},
|
|
|
|
getDelay(rawTimestamp) {
|
2018-04-27 21:25:04 +00:00
|
|
|
// Convert to moment timestamp if it isn't already
|
2018-06-27 20:53:49 +00:00
|
|
|
const timestamp = moment(rawTimestamp);
|
|
|
|
const now = moment();
|
|
|
|
const timediff = moment.duration(now - timestamp);
|
2018-04-27 21:25:04 +00:00
|
|
|
|
|
|
|
if (timediff.years() > 0) {
|
2018-06-27 20:53:49 +00:00
|
|
|
return null;
|
2018-04-27 21:25:04 +00:00
|
|
|
} else if (timediff.months() > 0 || timediff.days() > 6) {
|
2018-06-27 20:53:49 +00:00
|
|
|
return null;
|
2018-04-27 21:25:04 +00:00
|
|
|
} else if (timediff.days() > 0) {
|
2018-06-27 20:53:49 +00:00
|
|
|
return moment(timestamp)
|
2018-04-27 21:25:04 +00:00
|
|
|
.add(timediff.days() + 1, 'd')
|
|
|
|
.diff(now);
|
2018-06-27 20:53:49 +00:00
|
|
|
} else if (timediff.hours() >= 1) {
|
|
|
|
return moment(timestamp)
|
2018-04-27 21:25:04 +00:00
|
|
|
.add(timediff.hours() + 1, 'h')
|
|
|
|
.diff(now);
|
2018-06-27 20:53:49 +00:00
|
|
|
} else if (timediff.minutes() >= 1) {
|
|
|
|
return moment(timestamp)
|
2018-04-27 21:25:04 +00:00
|
|
|
.add(timediff.minutes() + 1, 'm')
|
|
|
|
.diff(now);
|
|
|
|
}
|
2018-06-27 20:53:49 +00:00
|
|
|
|
|
|
|
return moment(timestamp)
|
|
|
|
.add(1, 'm')
|
|
|
|
.diff(now);
|
2018-04-27 21:25:04 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
Whisper.ExtendedTimestampView = Whisper.TimestampView.extend({
|
2018-06-27 20:53:49 +00:00
|
|
|
getRelativeTimeSpanString(timestamp) {
|
|
|
|
return getRelativeTimeSpanString(timestamp, { extended: true });
|
2018-04-27 21:25:04 +00:00
|
|
|
},
|
|
|
|
});
|
2015-11-06 22:58:26 +00:00
|
|
|
})();
|