summaryrefslogtreecommitdiff
path: root/source/features/clean-repo-filelist-actions.tsx
blob: 8c9b7bbd06659e56682758a331bad515f738faee (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import React from 'dom-chef';
import select from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {PlusIcon, SearchIcon, CodeIcon} from '@primer/octicons-react';

import observe from '../helpers/selector-observer';
import {assertNodeContent, removeTextNodeContaining, wrap} from '../helpers/dom-utils';
import features from '../feature-manager';

/** Add tooltip on a wrapper to avoid breaking dropdown functionality */
function addTooltipToSummary(childElement: Element, tooltip: string): void {
	wrap(
		childElement.closest('details')!,
		<div className="tooltipped tooltipped-ne" aria-label={tooltip}/>,
	);
}

function cleanFilelistActions(searchButton: Element): void {
	searchButton.classList.add('tooltipped', 'tooltipped-ne');
	searchButton.setAttribute('aria-label', 'Go to file');

	// Replace "Go to file" with  icon
	searchButton.firstChild!.replaceWith(<SearchIcon/>);

	// This button doesn't appear on `isSingleFile`
	const addFileDropdown = searchButton.nextElementSibling!.querySelector('.dropdown-caret');
	if (addFileDropdown) {
		addFileDropdown.parentElement!.classList.replace('d-md-flex', 'd-md-block');

		// Replace label with icon
		assertNodeContent(addFileDropdown.previousSibling, 'Add file')
			.replaceWith(<PlusIcon/>);

		addTooltipToSummary(addFileDropdown, 'Add file');
	}

	const codeDropdownButton = select('get-repo summary');
	if (codeDropdownButton) { // This dropdown doesn't appear on `isSingleFile`
		addTooltipToSummary(codeDropdownButton, 'Clone, open or download');

		// Users with Codespaces enabled already have an icon in the button https://github.com/refined-github/refined-github/pull/5074#issuecomment-983251719
		const codeIcon = select('.octicon-code', codeDropdownButton);
		if (codeIcon) {
			removeTextNodeContaining(codeIcon.nextSibling!, 'Code');
		} else {
			removeTextNodeContaining(codeDropdownButton.firstChild!, 'Code');
			codeDropdownButton.prepend(<CodeIcon/>);
		}
	}
}

function init(signal: AbortSignal): void {
	// `.btn` selects the desktop version
	observe('.btn[data-hotkey="t"]', cleanFilelistActions, {signal});
}

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