Meta: fix some `no-optional-chaining` lint issues by fregante · Pull Request #9399 · refined-github/refined-github · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 1 addition & 56 deletions eslint-suppressions.json
1 change: 1 addition & 0 deletions source/features/reactions-avatars.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ function getParticipants(button: HTMLButtonElement): Participant[] {
.replace(/,? and /, ', ')
.replace(/, \d+ more/, '')
.split(', ');
// Uses optional chaining to throw an error manually later
} else if (button.nextElementSibling?.tagName === 'TOOL-TIP') {
// The list of people who commented is in an adjacent `<tool-tip>` element #5698
users = button.nextElementSibling
Expand Down
10 changes: 8 additions & 2 deletions source/features/rgh-deduplicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ void features.add('rgh-deduplicator', {
async init() {
// `await` kicks it to the next tick, after the other features have checked for 'has-rgh', so they can run once.
await Promise.resolve();
$optional('has-rgh')?.remove(); // https://github.com/refined-github/refined-github/issues/6568

// https://github.com/refined-github/refined-github/issues/6568
$optional('has-rgh')?.remove();

// These containers only appear on some pages
$optional(_`#js-repo-pjax-container, #js-pjax-container`)?.append(<has-rgh />);
$optional(_`turbo-frame`)?.append(<has-rgh-inner />); // #4567

// https://github.com/refined-github/refined-github/issues/4567
$optional(_`turbo-frame`)?.append(<has-rgh-inner />);
},
});

Expand Down
2 changes: 1 addition & 1 deletion source/features/rgh-improve-new-issue-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async function checkToken(): Promise<void> {
try {
await baseApiFetch({apiBase: 'https://api.github.com/', path: 'user', token});
} catch (error) {
if (!navigator.onLine || (error as any)?.message === 'Failed to fetch') {
if (!navigator.onLine || (error as any)!.message === 'Failed to fetch') {
return;
}

Expand Down
3 changes: 1 addition & 2 deletions source/features/show-names.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,8 @@ async function updateLinks(found: HTMLAnchorElement[]): Promise<void> {
const userKey = api.escapeKey(username);
const {name: fullName} = names[userKey];

const fullNameWithoutEmoji = fullName?.replaceAll(/\p{RGI_Emoji}/gv, '').trim();

// Could be `null` if not set or empty string if consisting only of emojis
const fullNameWithoutEmoji = fullName?.replaceAll(/\p{RGI_Emoji}/gv, '').trim();
if (!fullNameWithoutEmoji) {
continue;
}
Expand Down
17 changes: 0 additions & 17 deletions source/features/sort-conversations-by-update-time.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import elementReady from 'element-ready';
import * as pageDetect from 'github-url-detection';
import oneEvent from 'one-event';
import {$optional} from 'select-dom';

import features from '../feature-manager.js';
import SearchQuery from '../github-helpers/search-query.js';
Expand All @@ -13,16 +11,6 @@ export function saveOriginalHref(link: HTMLAnchorElement): void {
link.dataset.originalHref ??= link.href;
}

async function selectCurrentConversationFilter(): Promise<void> {
const currentSearchUrl = location.href.replace('/pulls?', '/issues?'); // Replacement needed to make up for the redirection of "Your pull requests" link
const menu = await elementReady('#filters-select-menu');
const currentFilter = $optional(`a.SelectMenu-item[href="${currentSearchUrl}"]`, menu);
if (currentFilter) {
$optional('[aria-checked="true"]', menu)?.setAttribute('aria-checked', 'false');
currentFilter.setAttribute('aria-checked', 'true');
}
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code from #5090


async function updateLink(link: HTMLAnchorElement): Promise<void> {
if (link.host !== location.host) {
return;
Expand Down Expand Up @@ -70,11 +58,6 @@ function init(signal: AbortSignal): void {

void features.add(import.meta.url, {
init,
}, {
include: [
pageDetect.isRepoIssueOrPRList,
],
init: selectCurrentConversationFilter,
});

/*
Expand Down
1 change: 1 addition & 0 deletions source/features/status-subscription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ async function addButtonIssue(subscriptionButton: HTMLButtonElement): Promise<vo
</div>,
);

// Would be missing on the first run
previousRghButton?.remove();
subscriptionButton.hidden = true;
}
Expand Down
34 changes: 13 additions & 21 deletions source/features/sync-pr-commit-title.tsx

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$optional restored with comment

Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@ import setReactInputValue from '../helpers/set-react-input-value.js';

const commitTitleFieldSelector = '[data-testid="mergebox-partial"] input[type="text"]';

function getCurrentCommitTitleField(): HTMLInputElement | undefined {
return $optional(commitTitleFieldSelector);
}

function getCurrentCommitTitle(): string | undefined {
return getCurrentCommitTitleField()?.value.trim();
function getCurrentCommitTitle(): string {
return $(commitTitleFieldSelector).value.trim();
}

export function formatPrCommitTitle(title: string, prNumber = getConversationNumber()!): string {
Expand All @@ -39,19 +35,12 @@ function createCommitTitle(): string {
}

function needsSubmission(): boolean {
const mergeButton = $optional(confirmMergeButton);
const textContent = mergeButton?.textContent?.trim();
if (
!textContent || ![
'Confirm squash and merge',
'Confirm auto-merge (squash)',
'Confirm bypass rules and merge (squash)',
].includes(textContent)
) {
// `needsSubmission` is also called when the PR title is changed, in order to update the open merge box in real time
if (!/squash/i.test($optional(confirmMergeButton)?.textContent ?? '')) {
return false;
}

const currentCommitTitle = getCurrentCommitTitle()!;
const currentCommitTitle = getCurrentCommitTitle();
return Boolean(currentCommitTitle) && (createCommitTitle() !== currentCommitTitle);
}

Expand All @@ -68,7 +57,7 @@ function getUi(): HTMLElement {

function updateUi(): void {
if (needsSubmission()) {
getCurrentCommitTitleField()!.parentElement!.after(getUi());
$(commitTitleFieldSelector).parentElement!.after(getUi());
} else {
getUi().remove();
}
Expand All @@ -80,7 +69,7 @@ async function updatePrTitle(): Promise<void> {
}

// Remove PR number from commit title
const title = cleanPrCommitTitle(getCurrentCommitTitle()!, getConversationNumber()!);
const title = cleanPrCommitTitle(getCurrentCommitTitle(), getConversationNumber()!);

await api.v3(`pulls/${getConversationNumber()!}`, {
method: 'PATCH',
Expand All @@ -93,7 +82,7 @@ async function updateCommitTitle(): Promise<void> {
return;
}

const field = getCurrentCommitTitleField()!;
const field = $(commitTitleFieldSelector);
setReactInputValue(field, createCommitTitle());
}

Expand All @@ -104,15 +93,18 @@ function disableSubmission(): void {

function init(signal: AbortSignal): void {
// PR title -> Commit title field
observe(commitTitleFieldSelector, updateCommitTitle, {signal}); // On panel open
// On panel open
observe(commitTitleFieldSelector, updateCommitTitle, {signal});

// On PR title change
observe(
[
'h1[class^="prc-PageHeader-Title"]',
'.gh-header-title', // Old view - TODO: Remove after July 2026
],
updateCommitTitle,
{signal},
); // On PR title change
);

// Commit title field -> toggle checkbox visibility
onCommitTitleUpdate(updateUi, signal);
Expand Down
16 changes: 7 additions & 9 deletions source/features/unread-anywhere.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ function removeNotificationIndicator(element: HTMLElement): void {
}
}

async function openUnreadNotifications(event?: React.MouseEvent): Promise<void> {
if (event?.target instanceof HTMLButtonElement) {
// Hide the tooltip
event.target.blur();
event.target.disabled = true; // Prevent multiple clicks
}
async function openUnreadNotifications(event: React.MouseEvent<HTMLButtonElement>): Promise<void> {
// Hide the tooltip
event.currentTarget.blur();

// Prevent multiple clicks
event.currentTarget.disabled = true;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case we'll also get events for the hidden hotkey button, but there's no drawbacks in temporarily disabling that one too.


await showToast(async updateToast => {
const page = await fetchDomUncached('/notifications?query=is%3Aunread');
Expand Down Expand Up @@ -65,9 +65,7 @@ async function openUnreadNotifications(event?: React.MouseEvent): Promise<void>
message: 'Loading notifications…',
doneMessage: false,
}).finally(() => {
if (event?.target instanceof HTMLButtonElement) {
event.target.disabled = false;
}
event.currentTarget.disabled = false;
});
}

Expand Down
1 change: 1 addition & 0 deletions source/features/unreleased-commits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const repoPublishState = new CachedFunction('tag-ahead-by', {

const tags = new Map<string, string>();
for (const node of repository.refs.nodes as Tags[]) {
// TODO: Review or drop optional chaining, there shouldn't be any case where this happens. The types are wrong
tags.set(node.name, node.tag.commit?.oid ?? node.tag.oid);
}

Expand Down
9 changes: 2 additions & 7 deletions source/features/useful-not-found-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,14 @@ function parseCurrentUrl(): string[] {
return parts;
}

async function getLatestCommitToFile(branch: string, filePath: string): Promise<string | void> {
async function getLatestCommitToFile(branch: string, filePath: string): Promise<string> {
const {repository} = await api.v4(GetLatestCommitToFile, {
variables: {
branch,
filePath,
},
});
const commit = repository.object?.history.nodes[0];
return commit?.oid;
return repository.object.history.nodes[0].oid;
}

async function getChangesToFileInCommit(sha: string, filePath: string): Promise<FileChanges | void> {
Expand Down Expand Up @@ -140,10 +139,6 @@ async function getGitObjectHistoryLink(): Promise<HTMLElement | undefined> {
}

const commitSha = await getLatestCommitToFile(url.branch, url.filePath);
if (!commitSha) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A file exists, so its commit also exists

return;
}

const fileChanges = await getChangesToFileInCommit(commitSha, url.filePath);
if (!fileChanges) {
return;
Expand Down
1 change: 1 addition & 0 deletions source/features/visit-tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ async function addLink(branchSelector: HTMLButtonElement): Promise<void> {
return;
}

// Uses optional chaining to emit a better error manually
const tag = branchSelector.getAttribute('aria-label')?.replace(/ tag$/, '');
if (!tag) {
throw new Error('Tag not found in DOM. The feature needs to be updated');
Expand Down
2 changes: 1 addition & 1 deletion source/github-helpers/hotkey.tsx
Loading