Files
Haven/plugins/MessageTimestamps.plugin.js

62 lines
1.9 KiB
JavaScript

/**
* @name Message Timestamps
* @description Adds relative timestamps (e.g. "2m ago") next to every message
* @author Haven
* @version 1.0.0
*/
class MessageTimestamps {
start() {
this._interval = setInterval(() => this._updateTimestamps(), 30000);
this._updateTimestamps();
HavenApi.DOM.addStyle('MessageTimestamps', `
.msg-relative-time {
font-size: 10px;
color: var(--text-muted);
margin-left: 6px;
opacity: 0.7;
}
`);
console.log('[MessageTimestamps] Started');
}
stop() {
clearInterval(this._interval);
document.querySelectorAll('.msg-relative-time').forEach(el => el.remove());
HavenApi.DOM.removeStyle('MessageTimestamps');
console.log('[MessageTimestamps] Stopped');
}
_updateTimestamps() {
document.querySelectorAll('.message').forEach(msg => {
const timeEl = msg.querySelector('.msg-time');
if (!timeEl) return;
// Don't duplicate
let badge = msg.querySelector('.msg-relative-time');
if (!badge) {
badge = document.createElement('span');
badge.className = 'msg-relative-time';
timeEl.parentNode.insertBefore(badge, timeEl.nextSibling);
}
// Parse the timestamp text (format varies, try ISO or displayed text)
const raw = timeEl.getAttribute('title') || timeEl.textContent;
const date = new Date(raw);
if (isNaN(date)) return;
badge.textContent = this._relative(date);
});
}
_relative(date) {
const secs = Math.floor((Date.now() - date.getTime()) / 1000);
if (secs < 60) return 'just now';
const mins = Math.floor(secs / 60);
if (mins < 60) return `${mins}m ago`;
const hrs = Math.floor(mins / 60);
if (hrs < 24) return `${hrs}h ago`;
const days = Math.floor(hrs / 24);
return `${days}d ago`;
}
}
// Register with the plugin loader's _win scope
if (typeof _win !== 'undefined') _win.MessageTimestamps = MessageTimestamps;