Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// MediaWiki:Common.js

mw.loader.using('mediawiki.api').then(() => {
  const api = new mw.Api();
  const RC_CONTAINER = document.getElementById('RCMain');

  // Simple "time ago" formatter
  const timeAgo = timestamp => {
    const seconds = Math.floor((Date.now() - new Date(timestamp)) / 1000);
    const intervals = [
      { label: 'day',    secs: 86400 },
      { label: 'hour',   secs: 3600  },
      { label: 'minute', secs: 60    },
      { label: 'second', secs: 1     }
    ];
    for (const { label, secs } of intervals) {
      const count = Math.floor(seconds / secs);
      if (count > 0) {
        return `${count} ${label}${count > 1 ? 's' : ''}`;
      }
    }
    return 'just now';
  };

  // Build one entry, prepend it, then activate
  const prependChange = c => {
    const entry = document.createElement('div');
    entry.className = 'rc-entry';
    entry.innerHTML = `
      <div class="rc-line1">
        <strong>${mw.html.escape(c.user)}</strong>
        ${c.type}
        <a href="${mw.config.get('wgServer') + mw.config.get('wgScriptPath')}/index.php?title=${encodeURIComponent(c.title)}">
          ${mw.html.escape(c.title)}
        </a>
      </div>
      <div class="rc-line2">
        ${timeAgo(c.timestamp)} ago
      </div>
    `;
    RC_CONTAINER.insertBefore(entry, RC_CONTAINER.firstChild);
    // give the browser a tick before adding the active class
    setTimeout(() => {
      entry.classList.add('rc-active');
    }, 1);
  };

  // Fetch recent changes
  api.get({
    action:  'query',
    list:    'recentchanges',
    rcprop:  'title|ids|sizes|comment|user|timestamp|flags',
    rclimit: 50,
    rcshow:  '!bot',
    format:  'json'
  }).then(data => {
    const changes = data.query.recentchanges;
    // 1. clear placeholder
    RC_CONTAINER.replaceChildren();

    // 2. prepend first 3 immediately
    changes.slice(0, 3).forEach(prependChange);

    // 3–5. every 3s prepend the next one with activation
    let idx = 3;
    const timer = setInterval(() => {
      if (idx >= changes.length) {
        clearInterval(timer);
      } else {
        prependChange(changes[idx++]);
      }
    }, 3000);
  }).catch(err => {
    console.error('Failed to load recent changes:', err);
    RC_CONTAINER.textContent = 'Error loading recent changes.';
  });
});