Skip to content

Commit fa8a380

Browse files
JohnMcLearclaude
andcommitted
fix: refresh "N minutes ago" strings without a page reload (#154)
moment.js computed the relative time once when each comment/reply was rendered, so "1 minute ago" never changed as the page stayed open. Hook a 60-second interval in `init()` that walks every `.comment-created-at` element in the sidebar container and recomputes the text from the ISO timestamp stored in the element's `datetime` attribute, which is the same timestamp the original render used. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 45b3995 commit fa8a380

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

static/js/index.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ EpComments.prototype.init = async function () {
113113
});
114114
$(window).resize(_.debounce(() => { this.setYofComments(); }, 100));
115115

116+
// Refresh the "N minutes ago" relative-time strings (#154). The original
117+
// date is stored in the `datetime` attribute so we can recompute
118+
// `fromNow()` without needing to track the cached string anywhere.
119+
setInterval(() => this.refreshRelativeDates(), 60 * 1000);
120+
116121
// On click comment icon toolbar
117122
$('.addComment').on('click', (e) => {
118123
e.preventDefault(); // stops focus from being lost
@@ -694,6 +699,19 @@ EpComments.prototype.allCommentsOnCorrectYPosition = function () {
694699
return allCommentsAreCorrect;
695700
};
696701

702+
// Recompute "N minutes ago" style text on every `.comment-created-at`
703+
// element, using the ISO timestamp stored in the element's `datetime`
704+
// attribute as the source of truth (#154).
705+
EpComments.prototype.refreshRelativeDates = function () {
706+
if (this.container == null) return;
707+
this.container.find('.comment-created-at[datetime]').each(function () {
708+
const iso = $(this).attr('datetime');
709+
if (!iso) return;
710+
const next = moment(iso).fromNow();
711+
if ($(this).text() !== next) $(this).text(next);
712+
});
713+
};
714+
697715
EpComments.prototype.localizeExistingComments = function () {
698716
const self = this;
699717
const padComments = this.padInner.contents().find('.comment');
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
3+
const assert = require('assert').strict;
4+
const fs = require('fs');
5+
const path = require('path');
6+
7+
const pluginRoot = path.resolve(__dirname, '..', '..', '..', '..');
8+
const indexPath = path.join(pluginRoot, 'static', 'js', 'index.js');
9+
10+
describe(__filename, function () {
11+
let src;
12+
before(function () {
13+
src = fs.readFileSync(indexPath, 'utf8');
14+
});
15+
16+
it('registers a setInterval that calls refreshRelativeDates (#154)', function () {
17+
// Any cadence works, but the interval must actually be scheduled so the
18+
// relative-time strings update without a page reload.
19+
assert(/setInterval\([^)]*refreshRelativeDates[^)]*\)/.test(src),
20+
'init should call setInterval(() => this.refreshRelativeDates(), ...)');
21+
});
22+
23+
it('refreshRelativeDates recomputes text from the datetime attribute (#154)',
24+
function () {
25+
const match = src.match(
26+
/EpComments\.prototype\.refreshRelativeDates\s*=\s*function[\s\S]*?\n\};/);
27+
assert(match, 'refreshRelativeDates should be defined on EpComments.prototype');
28+
const body = match[0];
29+
assert(/comment-created-at\[datetime\]/.test(body),
30+
'refreshRelativeDates must target elements with a datetime attribute so the ISO ' +
31+
'timestamp can be used as the source of truth');
32+
assert(/moment\([^)]+\)\.fromNow\(\)/.test(body),
33+
'refreshRelativeDates should recompute the relative time via moment(iso).fromNow()');
34+
});
35+
});

0 commit comments

Comments
 (0)