GitHub Diff File Toggle

A userscript that adds global diff file toggles

As of 2022-10-24. See the latest version.

  1. // ==UserScript==
  2. // @name GitHub Diff File Toggle
  3. // @version 0.1.3
  4. // @description A userscript that adds global diff file toggles
  5. // @license MIT
  6. // @author Rob Garrison
  7. // @namespace https://github.com/Mottie
  8. // @include https://github.com/*
  9. // @run-at document-idle
  10. // @grant none
  11. // @require https://greatest.deepsurf.us/scripts/28721-mutations/code/mutations.js?version=1108163
  12. // @require https://greatest.deepsurf.us/scripts/398877-utils-js/code/utilsjs.js?version=1079637
  13. // @icon https://github.githubassets.com/pinned-octocat.svg
  14. // @supportURL https://github.com/Mottie/GitHub-userscripts/issues
  15.  
  16. // ==/UserScript==
  17. /* global $ $$ on debounce make */
  18. (() => {
  19. "use strict";
  20.  
  21. let timer;
  22. let busy = false;
  23.  
  24. const setToggleStyle = state => {
  25. const mainToggle = $(".ghdt-toggle");
  26. mainToggle.classList.toggle("ghdt-selected", state);
  27. mainToggle.style = state
  28. ? "background-color: var(--color-btn-selected-bg);"
  29. : "";
  30. };
  31.  
  32. const buildButton = () => {
  33. if (!$(".ghdt-toggle")) {
  34. const button = make({
  35. el: "button",
  36. className: "btn btn-sm ghdt-toggle tooltipped tooltipped-s float-right",
  37. text: "Toggle viewed",
  38. attrs: {
  39. "aria-label": "Toggle all viewed files"
  40. }
  41. });
  42. on(button, "click", event => {
  43. toggle(document, !event.target.classList.contains("ghdt-selected"));
  44. });
  45. $("#files.diff-view")?.prepend(button);
  46. }
  47. // Update toggle button state after initialized; timer for progressive
  48. // loading
  49. clearTimeout(timer);
  50. timer = setTimeout(() => {
  51. if ($$(".js-reviewed-checkbox").every(el => el.checked)) {
  52. setToggleStyle(true);
  53. }
  54. }, 1000);
  55. };
  56.  
  57. const toggle = (target, state) => {
  58. $$(".js-reviewed-checkbox").forEach(checkbox => {
  59. if (target !== checkbox && checkbox.checked !== state) {
  60. checkbox.click();
  61. }
  62. });
  63. setToggleStyle(state);
  64. };
  65.  
  66. const handleChange = event => {
  67. const { target, altKey, shiftKey } = event;
  68. const anyModifier = altKey || shiftKey;
  69. if (!busy && anyModifier && target.matches(".js-reviewed-checkbox")) {
  70. busy = true;
  71. toggle(target, target.checked);
  72. setTimeout(() => {
  73. busy = false;
  74. });
  75. }
  76. };
  77.  
  78. const init = () => {
  79. if ($("#files.diff-view") || $(".pr-toolbar")) {
  80. buildButton();
  81. }
  82. };
  83.  
  84. on(document, "ghmo:container ghmo:diff", init);
  85. on(document, "click", debounce(handleChange));
  86. on(document, "keydown", debounce(handleChange));
  87. init();
  88. })();