GitLab MR Viewed File Counter

Displays viewed/total file count on GitLab merge request pages

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         GitLab MR Viewed File Counter
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  Displays viewed/total file count on GitLab merge request pages
// @match        https://gitlab.com/*/-/merge_requests/*
// @grant        none
// @run-at       document-idle
// @author       bzly
// @license      GPL-3.0-or-later
// ==/UserScript==

(function () {
  'use strict';

  const badge = document.querySelector('.js-changes-tab-count');
  let total = badge.textContent.trim();
  const mrPath = window.location.pathname.match(/.*\/merge_requests\/\d+/)?.[0];
  const mrKey = `code-review-${mrPath}`;
  const pill = document.querySelector('.diffs-tab .gl-badge');

  function getViewedCount() {
    try {
      const viewed = JSON.parse(localStorage.getItem(mrKey));
      return Array.isArray(viewed) ? viewed.length : 0;
    } catch {
      return 0;
    }
  }

  function updateBadge() {
    const viewed = getViewedCount();
    const pct = total > 0 ? Math.round((viewed / total) * 100) : 0;
    badge.textContent = `${viewed}/${total}`;
    if (viewed > 0) {
        // when any files are marked as viewed, gradually turn from the GitLab 'closed' colour to the 'merged' colour.
        pill.style.backgroundColor = `color-mix(in srgb, var(--gl-badge-success-background-color-default) ${pct}%, var(--gl-badge-danger-background-color-default))`;
    } else {
       pill.style.backgroundColor = 'var(--gl-badge-neutral-background-color-default)';
    }
  }

  // update count when GitLab changes the element back at random times
  new MutationObserver(() => {
    if (!badge.textContent.includes('/')) {
      total = badge.textContent.trim();
      updateBadge();
    }
  }).observe(badge, { childList: true, characterData: true, subtree: true });

  // update count on same-tab changes
  const _setItem = localStorage.setItem.bind(localStorage);
  localStorage.setItem = function (key, value) {
    _setItem(key, value);
    if (key === mrKey) updateBadge();
  };

  // update count when going back to 0 viewed
  const _removeItem = localStorage.removeItem.bind(localStorage);
  localStorage.removeItem = function (key) {
    _removeItem(key);
    if (key === mrKey) updateBadge();
  };

  // update count on different-tab change (i.e. you are working across multiple tabs)
  window.addEventListener('storage', (e) => {
    if (e.key === mrKey) updateBadge();
  });
  
  updateBadge();
})();