From 614d8bc36e50fdac63f2d86cdea2ee8d846f577b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20=C5=A0olc=20AI?= Date: Thu, 5 Nov 2026 21:27:45 +0100 Subject: [PATCH] fix(gitlab-mark-viewed): advance after marking rapid diffs viewed --- README.md | 2 +- gitlab-mark-viewed.user.js | 83 +++++++++++++++++++++++++------------- 2 files changed, 57 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index fa5b0ae..8ff9d88 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ the `==UserScript==` header and prompts to install. | Script | Install | Description | | ---------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `gitlab-mark-viewed.user.js` | [install](https://raw.githubusercontent.com/solcik/userscripts/main/gitlab-mark-viewed.user.js) | Press `v` on a GitLab MR page to toggle the focused file's "Viewed" checkbox. Marking one viewed advances to the next file (GitLab's own `j`) and pins it under the sticky header, so a long commit message no longer sits above the diff; un-viewing stays put so you can read it. Matches `gitlab.com` and `git.vs-point.cz`. | +| `gitlab-mark-viewed.user.js` | [install](https://raw.githubusercontent.com/solcik/userscripts/main/gitlab-mark-viewed.user.js) | Press `v` on a GitLab MR page to toggle the focused file's "Viewed" checkbox. The script advances after you mark a file viewed. It supports rapid diffs and the legacy viewer. Unmarking a viewed file keeps that file selected. Matches `gitlab.com` and `git.vs-point.cz`. | | `gitlab-commit-nav.user.js` | [install](https://raw.githubusercontent.com/solcik/userscripts/main/gitlab-commit-nav.user.js) | Press `x` / `c` on a GitLab MR single-commit diff to go to the previous / next commit. Restores the built-in shortcut broken on GitLab < 17.10 ([#499143](https://gitlab.com/gitlab-org/gitlab/-/issues/499143)). | | `github-mark-viewed.user.js` | [install](https://raw.githubusercontent.com/solcik/userscripts/main/github-mark-viewed.user.js) | Keyboard review flow for a GitHub PR diff. `v` marks the focused file viewed and pins the next file under the header; un-viewing stays put so you can read it. The first `v` on a PR only unticks "Viewed files" in the file filter, so only unviewed files remain. `j` / `k` go to the next / previous file; an outline marks the current file, so this also works at the end of the page where the diff cannot scroll further. `u` un-marks the last file `v` marked and jumps to it (undo stack per PR in `sessionStorage`). `Shift+V` shows or hides viewed files without changing review state. | diff --git a/gitlab-mark-viewed.user.js b/gitlab-mark-viewed.user.js index 9adb54e..1e14327 100644 --- a/gitlab-mark-viewed.user.js +++ b/gitlab-mark-viewed.user.js @@ -1,8 +1,8 @@ // ==UserScript== // @name GitLab — mark file as Viewed with "v" // @namespace https://github.com/solcik/userscripts -// @version 0.5.2 -// @description In a GitLab merge request diff, press "v" (GitLab toggles the focused file's "Viewed" checkbox) and advance to the next file — pinned under the sticky header — only when marking one viewed. +// @version 0.5.3 +// @description Press "v" to toggle the current GitLab diff file as viewed. Marking a file viewed advances to the next file. // @author David Solc // @match https://gitlab.com/*/-/merge_requests/* // @match https://git.vs-point.cz/*/-/merge_requests/* @@ -11,7 +11,6 @@ // @supportURL https://github.com/solcik/userscripts/issues // @updateURL https://raw.githubusercontent.com/solcik/userscripts/main/gitlab-mark-viewed.user.js // @downloadURL https://raw.githubusercontent.com/solcik/userscripts/main/gitlab-mark-viewed.user.js -// @require https://cdn.jsdelivr.net/npm/mousetrap@1.6.5/mousetrap.min.js // @grant none // @license MIT // ==/UserScript== @@ -63,12 +62,23 @@ return files.find((file) => file.getBoundingClientRect().bottom > edge) || files.at(-1); } - // GitLab's own "next file" shortcut already knows about lazily rendered files, - // the sticky header offset and the file tree selection, so trigger it instead - // of scrolling ourselves. Its Mousetrap handler reads the legacy `which`, and - // its stopCallback expects an element target — dispatching on `document` is - // silently dropped. - function goToNextFile() { + // Use the viewer's navigation button in single-file mode. + // Select the next rapid diff directly in multi-file mode. + // The legacy viewer still handles the "j" shortcut. + function goToNextFile(file) { + const navigation = document.querySelector('[data-testid="file-by-file-navigation"]'); + if (navigation) { + const next = navigation.querySelector('[data-testid="nextButton"]'); + if (next && !next.disabled && next.getAttribute('aria-disabled') !== 'true') next.click(); + return; + } + + if (file.matches('diff-file')) { + const files = [...document.querySelectorAll('diff-file')]; + files[files.indexOf(file) + 1]?.selectFile(); + return; + } + const event = new KeyboardEvent('keypress', { key: NEXT_FILE_KEY, bubbles: true, @@ -108,22 +118,41 @@ })(); } - // GitLab now binds "v" ("Viewed by me") itself. Clicking the checkbox here - // too would toggle it twice, so let GitLab toggle and only watch the result. - Mousetrap.bind('v', function () { - const file = focusedFile(); - const checkbox = file && file.querySelector(REVIEW_CHECKBOX); - if (!checkbox) return; - - const was = checkbox.checked; - const key = fileKey(file); - - setTimeout(function () { - // Un-reviewing expands the file again, which is the whole point of - // pressing "v" on an already-viewed file — stay put so it can be read. - if (was || !checkbox.checked) return; - goToNextFile(); - pinNextFile(key); - }, 50); - }); + // Capture "v" before GitLab handles it. One owner prevents duplicate toggles. + document.addEventListener( + 'keydown', + function (event) { + if ( + event.key !== 'v' || + event.ctrlKey || + event.altKey || + event.metaKey || + event.shiftKey || + event.isComposing || + event.target.closest( + 'input, textarea, select, [contenteditable]:not([contenteditable="false"]), [role="textbox"]', + ) + ) + return; + + const file = focusedFile(); + const checkbox = file && file.querySelector(REVIEW_CHECKBOX); + if (!checkbox || checkbox.disabled) return; + + event.preventDefault(); + event.stopImmediatePropagation(); + if (event.repeat) return; + + const marking = !checkbox.checked; + const key = fileKey(file); + checkbox.click(); + if (!marking || !checkbox.checked) return; + + requestAnimationFrame(function () { + goToNextFile(file); + pinNextFile(key); + }); + }, + true, + ); })();