|  |  |  | /* global moment: false */ | 
					
						
							|  |  |  | /* global Whisper: false */ | 
					
						
							|  |  |  | /* global extension: false */ | 
					
						
							|  |  |  | /* global i18n: false */ | 
					
						
							|  |  |  | /* global _: false */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // eslint-disable-next-line func-names
 | 
					
						
							|  |  |  | (function() { | 
					
						
							|  |  |  |   'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   window.Whisper = window.Whisper || {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   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'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Whisper.TimestampView = Whisper.View.extend({ | 
					
						
							|  |  |  |     initialize() { | 
					
						
							|  |  |  |       extension.windows.onClosed(this.clearTimeout.bind(this)); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     update() { | 
					
						
							|  |  |  |       this.clearTimeout(); | 
					
						
							|  |  |  |       const millisNow = Date.now(); | 
					
						
							|  |  |  |       let millis = this.$el.data('timestamp'); | 
					
						
							|  |  |  |       if (millis === '') { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (millis >= millisNow) { | 
					
						
							|  |  |  |         millis = millisNow; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       const result = this.getRelativeTimeSpanString(millis); | 
					
						
							|  |  |  |       this.delay = this.getDelay(millis); | 
					
						
							|  |  |  |       this.$el.text(result); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const timestamp = moment(millis); | 
					
						
							|  |  |  |       this.$el.attr('title', timestamp.format('llll')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (this.delay) { | 
					
						
							|  |  |  |         if (this.delay < 0) { | 
					
						
							|  |  |  |           this.delay = 1000; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         this.timeout = setTimeout(this.update.bind(this), this.delay); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     clearTimeout() { | 
					
						
							|  |  |  |       clearTimeout(this.timeout); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     getRelativeTimeSpanString(timestamp) { | 
					
						
							|  |  |  |       return getRelativeTimeSpanString(timestamp); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     getDelay(rawTimestamp) { | 
					
						
							|  |  |  |       // 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 null; | 
					
						
							|  |  |  |       } else if (timediff.months() > 0 || timediff.days() > 6) { | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |       } else if (timediff.days() > 0) { | 
					
						
							|  |  |  |         return moment(timestamp) | 
					
						
							|  |  |  |           .add(timediff.days() + 1, 'd') | 
					
						
							|  |  |  |           .diff(now); | 
					
						
							|  |  |  |       } else if (timediff.hours() >= 1) { | 
					
						
							|  |  |  |         return moment(timestamp) | 
					
						
							|  |  |  |           .add(timediff.hours() + 1, 'h') | 
					
						
							|  |  |  |           .diff(now); | 
					
						
							|  |  |  |       } else if (timediff.minutes() >= 1) { | 
					
						
							|  |  |  |         return moment(timestamp) | 
					
						
							|  |  |  |           .add(timediff.minutes() + 1, 'm') | 
					
						
							|  |  |  |           .diff(now); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return moment(timestamp) | 
					
						
							|  |  |  |         .add(1, 'm') | 
					
						
							|  |  |  |         .diff(now); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   Whisper.ExtendedTimestampView = Whisper.TimestampView.extend({ | 
					
						
							|  |  |  |     getRelativeTimeSpanString(timestamp) { | 
					
						
							|  |  |  |       return getRelativeTimeSpanString(timestamp, { extended: true }); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | })(); |