From 6214368295b21cdce0dc27f040543aa97146d569 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sat, 9 May 2026 02:13:11 +0500 Subject: [PATCH 01/12] `on-altered-click` - Prevent default behaviour only on middle click --- source/helpers/on-altered-click.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/helpers/on-altered-click.ts b/source/helpers/on-altered-click.ts index d7317c3ab549..8f74de173f02 100644 --- a/source/helpers/on-altered-click.ts +++ b/source/helpers/on-altered-click.ts @@ -2,6 +2,10 @@ import type {ParseSelector} from 'typed-query-selector/parser.d.js'; import delegate, {type DelegateEventHandler, type DelegateOptions} from 'delegate-it'; import {isAlteredClick} from 'filter-altered-clicks'; +function isMiddleClick(event: MouseEvent): boolean { + return event.button === 1; +} + export default function onAlteredClick( selector: Selector | readonly Selector[], callback: DelegateEventHandler>, @@ -14,14 +18,15 @@ export default function onAlteredClick( }; const auxClickListener: typeof callback = event => { - // Is middle click - if (event.button === 1) { + if (isMiddleClick(event)) { callback(event); } }; const preventAutoScrolling = (event: MouseEvent): void => { - event.preventDefault(); + if (isMiddleClick(event)) { + event.preventDefault(); + } }; delegate(selector, 'click', clickListener, {capture: true, ...options}); From 1b0221d973f9159449cbe573d1330387f0a93b48 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sat, 9 May 2026 15:21:16 +0500 Subject: [PATCH 02/12] `closing-remarks` - Fix on unreleased commits --- source/features/closing-remarks.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/features/closing-remarks.tsx b/source/features/closing-remarks.tsx index 6cbfa9602b1f..a693502dc3e0 100644 --- a/source/features/closing-remarks.tsx +++ b/source/features/closing-remarks.tsx @@ -1,5 +1,5 @@ import React from 'dom-chef'; -import {$, $$} from 'select-dom'; +import {$, $$, $$optional} from 'select-dom'; import {CachedFunction} from 'webext-storage-cache'; import * as pageDetect from 'github-url-detection'; @@ -30,7 +30,7 @@ function ExplanationLink(): JSX.Element { const firstTag = new CachedFunction('first-tag', { async updater(commit: string): Promise { const tagsAndBranches = await fetchDom(buildRepoUrl('branch_commits', commit)); - const tags = $$('ul.branches-tag-list a', tagsAndBranches); + const tags = $$optional('ul.branches-tag-list a', tagsAndBranches); // eslint-disable-next-line unicorn/no-array-callback-reference -- Just this once, I swear return tags.findLast(excludeNightliesAndJunk)?.textContent ?? false; }, From 868265933b88d81f9648e4b433d2d364c7cbff85 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sat, 9 May 2026 15:22:15 +0500 Subject: [PATCH 03/12] `hide-inactive-deployments` - Fix on PRs without deployments --- source/features/hide-inactive-deployments.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/features/hide-inactive-deployments.tsx b/source/features/hide-inactive-deployments.tsx index 30fef6973999..694d91e5bb0d 100644 --- a/source/features/hide-inactive-deployments.tsx +++ b/source/features/hide-inactive-deployments.tsx @@ -1,12 +1,12 @@ import * as pageDetect from 'github-url-detection'; -import {elementExists, $$} from 'select-dom'; +import {elementExists, $$optional} from 'select-dom'; import features from '../feature-manager.js'; // This feature doesn't need an active observer function init(): void { // Selects all the deployments first so that we can leave the last one on the page - const deployments = $$('.js-socket-channel[data-gid^="PR"]:has(.octicon-rocket)'); + const deployments = $$optional('.js-socket-channel[data-gid^="PR"]:has(.octicon-rocket)'); deployments.pop(); // Don't hide the last deployment, even if it is inactive for (const deployment of deployments) { From 3166f024565481c40171c58ae88e5f5784786ad4 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sat, 9 May 2026 15:22:38 +0500 Subject: [PATCH 04/12] `linkify-line-numbers` - Exclude empty cells --- source/features/linkify-line-numbers.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/features/linkify-line-numbers.tsx b/source/features/linkify-line-numbers.tsx index a8c62efccdb5..15db69f86e9e 100644 --- a/source/features/linkify-line-numbers.tsx +++ b/source/features/linkify-line-numbers.tsx @@ -24,7 +24,7 @@ function linkify(lineNumberCell: HTMLTableCellElement): void { } function init(signal: AbortSignal): void { - observe('.blob-num:empty:not(.blob-num-hunk)', linkify, {signal}); + observe('.blob-num:not(:is(.blob-num-hunk, .empty-cell))', linkify, {signal}); } void features.add(import.meta.url, { From 4f40e5aaad7d5304917c5bf7ca5169e60776dc5a Mon Sep 17 00:00:00 2001 From: Grigory Date: Sat, 9 May 2026 15:31:59 +0500 Subject: [PATCH 05/12] simplify `directoryListingFileIcon` selector --- source/github-helpers/selectors.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/source/github-helpers/selectors.ts b/source/github-helpers/selectors.ts index 130393ce331b..f7f3c5a196d8 100644 --- a/source/github-helpers/selectors.ts +++ b/source/github-helpers/selectors.ts @@ -46,11 +46,7 @@ export const branchSelector_ = [ export const branchSelectorParent = 'details#branch-select-menu'; export const branchSelectorParent_ = branchSelector_; -export const directoryListingFileIcon = [ - // .color-fg-muted selects only files; some icon extensions use `img` tags - '.react-directory-filename-column > :is(svg, img).color-fg-muted', - '.js-navigation-container .octicon-file', -]; +export const directoryListingFileIcon = '.react-directory-filename-column > .octicon-file'; export const directoryListingFileIcon_ = [ [18, 'https://github.com/refined-github/refined-github'], [3, 'https://github.com/refined-github/refined-github/tree/main/.github'], From 7f5b0c667d895de2b4861757897d233b703b45ea Mon Sep 17 00:00:00 2001 From: Grigory Date: Sat, 9 May 2026 23:53:34 +0500 Subject: [PATCH 06/12] `hideEventsAndCollapsedComments` -> `hideEventsBotsCollapsedComments` --- source/features/conversation-activity-filter.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/features/conversation-activity-filter.tsx b/source/features/conversation-activity-filter.tsx index 4cb4f2b3d0e3..426c02b86bab 100644 --- a/source/features/conversation-activity-filter.tsx +++ b/source/features/conversation-activity-filter.tsx @@ -36,7 +36,7 @@ const minorFixesIssuePages = [ const states = { showAll: 'Show all activities', hideEvents: 'Hide events', - hideEventsAndCollapsedComments: 'Hide events, bots, collapsed comments', + hideEventsBotsCollapsedComments: 'Hide events, bots, collapsed comments', } as const; type State = keyof typeof states; @@ -290,7 +290,7 @@ function switchToNextFilter(): void { async function init(signal: AbortSignal): Promise { currentState = SessionPageSetting.get() ?? (minorFixesIssuePages.some(url => location.href.startsWith(url)) - ? 'hideEventsAndCollapsedComments' // Automatically hide resolved comments on "Minor codebase updates and fixes" issue pages + ? 'hideEventsBotsCollapsedComments' // Automatically hide resolved comments on "Minor codebase updates and fixes" issue pages : 'showAll'); const initialSetupOnce = onetime(() => { From 035947eb24a3ec75477646f3ec98d13a2e410f5a Mon Sep 17 00:00:00 2001 From: Grigory Date: Sun, 10 May 2026 15:40:30 +0500 Subject: [PATCH 07/12] remove unused import --- source/features/closing-remarks.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/features/closing-remarks.tsx b/source/features/closing-remarks.tsx index a693502dc3e0..c99a57c2300b 100644 --- a/source/features/closing-remarks.tsx +++ b/source/features/closing-remarks.tsx @@ -1,5 +1,5 @@ import React from 'dom-chef'; -import {$, $$, $$optional} from 'select-dom'; +import {$, $$optional} from 'select-dom'; import {CachedFunction} from 'webext-storage-cache'; import * as pageDetect from 'github-url-detection'; From 779511d0e6f723df28140490a158cb95a47d25a3 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sun, 10 May 2026 16:01:19 +0500 Subject: [PATCH 08/12] remove redundant :is Co-authored-by: fregante --- source/features/linkify-line-numbers.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/features/linkify-line-numbers.tsx b/source/features/linkify-line-numbers.tsx index 15db69f86e9e..2a2b3e282e54 100644 --- a/source/features/linkify-line-numbers.tsx +++ b/source/features/linkify-line-numbers.tsx @@ -24,7 +24,7 @@ function linkify(lineNumberCell: HTMLTableCellElement): void { } function init(signal: AbortSignal): void { - observe('.blob-num:not(:is(.blob-num-hunk, .empty-cell))', linkify, {signal}); + observe('.blob-num:not(.blob-num-hunk, .empty-cell)', linkify, {signal}); } void features.add(import.meta.url, { From 462be4d06e558ca90615b49cf99afcc43e1e14de Mon Sep 17 00:00:00 2001 From: Federico Date: Sun, 10 May 2026 18:05:29 +0700 Subject: [PATCH 09/12] Fix lint rule --- eslint.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index 2878134cf546..aefc8f6517b1 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -91,7 +91,7 @@ export default defineConfig([ 'error', { selector: - ':matches([callee.name=delegate], [callee.name=$], [callee.name=$$], [callee.name=$optional], [callee.name=$closest], [callee.name=$closestOptional], [callee.name=observe], [callee.property.name=querySelector], [callee.property.name=querySelectorAll])[arguments.0.value=/,/][arguments.0.value.length>=20]:not([arguments.0.value=/:has|:is/])', + ':matches([callee.name=delegate], [callee.name=$], [callee.name=$$], [callee.name=$optional], [callee.name=$closest], [callee.name=$closestOptional], [callee.name=observe], [callee.property.name=querySelector], [callee.property.name=querySelectorAll])[arguments.0.value=/,/][arguments.0.value.length>=20]:not([arguments.0.value=/:has|:is|:not/])', message: 'Instead of a single string, pass an array of selectors and add comments to each selector', }, { From f748ed5066438bbc2e96452304f5411835d09617 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sun, 10 May 2026 18:26:50 +0500 Subject: [PATCH 10/12] `reactions-avatars` - Fix on comments with no reactions --- source/features/reactions-avatars.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/source/features/reactions-avatars.tsx b/source/features/reactions-avatars.tsx index 9213214ff997..888f10bca946 100644 --- a/source/features/reactions-avatars.tsx +++ b/source/features/reactions-avatars.tsx @@ -3,7 +3,7 @@ import './reactions-avatars.css'; import React from 'dom-chef'; import {flatZip} from 'flat-zip'; import * as pageDetect from 'github-url-detection'; -import {$$} from 'select-dom'; +import {$$, $$optional} from 'select-dom'; import {onAbort} from 'abort-utils'; @@ -73,12 +73,16 @@ const viewportObserver = new IntersectionObserver(changes => { rootMargin: '500px', }); -function showAvatarsOn(commentReactions: Element): void { - const reactions = $$([ - 'button[aria-pressed]', // Discussions, releases, PRs, old issues +function showAvatarsOn(reactionsContainer: Element): void { + const reactions = $$optional([ + 'button[aria-pressed]', // Discussions, releases, PRs 'button[aria-checked]', // React issues - ], commentReactions) - .map(button => getParticipants(button)); // Get all participants for each reaction + ], reactionsContainer) + .map(button => getParticipants(button)); // Get all participants for each reaction type + if (reactions.length === 0) { + return; + } + const avatarLimit = arbitraryAvatarLimit - (reactions.length * approximateHeaderLength); const flatParticipants = flatZip(reactions, avatarLimit); @@ -107,7 +111,7 @@ function init(signal: AbortSignal): void { [ // `batch-deferred-content` means the participant list hasn't loaded yet '.has-reactions .js-comment-reactions-options:not(batch-deferred-content .js-comment-reactions-options)', - '[aria-label="Reactions"]', + 'div[aria-label="Reactions"]', ], observeCommentReactions, {signal}, From d4d945c177915be42b3a488d80bb45ff5ce498b2 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sun, 10 May 2026 18:28:49 +0500 Subject: [PATCH 11/12] lint --- source/features/reactions-avatars.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/features/reactions-avatars.tsx b/source/features/reactions-avatars.tsx index 888f10bca946..9281a141dfec 100644 --- a/source/features/reactions-avatars.tsx +++ b/source/features/reactions-avatars.tsx @@ -3,7 +3,7 @@ import './reactions-avatars.css'; import React from 'dom-chef'; import {flatZip} from 'flat-zip'; import * as pageDetect from 'github-url-detection'; -import {$$, $$optional} from 'select-dom'; +import {$$optional} from 'select-dom'; import {onAbort} from 'abort-utils'; @@ -76,7 +76,7 @@ const viewportObserver = new IntersectionObserver(changes => { function showAvatarsOn(reactionsContainer: Element): void { const reactions = $$optional([ 'button[aria-pressed]', // Discussions, releases, PRs - 'button[aria-checked]', // React issues + 'button[aria-checked]', // Issues ], reactionsContainer) .map(button => getParticipants(button)); // Get all participants for each reaction type if (reactions.length === 0) { From d2f9d4fb529b3ba50fbb9b50ee07c7f795ea8093 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sun, 10 May 2026 18:29:43 +0500 Subject: [PATCH 12/12] revert comment change --- source/features/reactions-avatars.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/features/reactions-avatars.tsx b/source/features/reactions-avatars.tsx index 9281a141dfec..614a36d24f19 100644 --- a/source/features/reactions-avatars.tsx +++ b/source/features/reactions-avatars.tsx @@ -78,7 +78,7 @@ function showAvatarsOn(reactionsContainer: Element): void { 'button[aria-pressed]', // Discussions, releases, PRs 'button[aria-checked]', // Issues ], reactionsContainer) - .map(button => getParticipants(button)); // Get all participants for each reaction type + .map(button => getParticipants(button)); // Get all participants for each reaction if (reactions.length === 0) { return; }