summaryrefslogtreecommitdiff
path: root/source/features/faster-pr-diff-options.tsx
blob: 6ac6f9409e2c251fbcac429481f3f779650e7d8f (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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import React from 'dom-chef';
import select from 'select-dom';
import * as pageDetect from 'github-url-detection';
import {BookIcon, CheckIcon, DiffIcon, DiffModifiedIcon} from '@primer/octicons-react';

import features from '.';

function makeLink(type: string, icon: Element, selected: boolean): JSX.Element {
	const url = new URL(location.href);
	url.searchParams.set('diff', type);
	const classes = pageDetect.isPR()
		? 'tooltipped tooltipped-s d-none d-lg-block ml-2 color-icon-secondary'
		: 'tooltipped tooltipped-s btn btn-sm BtnGroup-item ' + (selected ? 'selected' : '');

	return (
		<a
			className={classes}
			aria-label={`Switch to the ${type} diff view`}
			href={url.href}
		>
			{icon}
		</a>
	);
}

function createDiffStyleToggle(): DocumentFragment {
	const isUnified = select.exists([
		'[value="unified"][checked]', // Form in PR
		'.table-of-contents .selected[href*="diff=unified"]', // Link in single commit
	]);

	if (pageDetect.isPR()) {
		return isUnified
			? makeLink('split', <BookIcon/>, false)
			: makeLink('unified', <DiffIcon/>, false);
	}

	return (
		<>
			{makeLink('unified', <DiffIcon/>, isUnified)}
			{makeLink('split', <BookIcon/>, !isUnified)}
		</>
	);
}

function createWhitespaceButton(): HTMLElement {
	const url = new URL(location.href);
	const isHidingWhitespace = url.searchParams.get('w') === '1';

	if (isHidingWhitespace) {
		url.searchParams.delete('w');
	} else {
		url.searchParams.set('w', '1');
	}

	const classes = pageDetect.isPR()
		? 'tooltipped tooltipped-s d-none d-lg-block color-icon-secondary ' + (isHidingWhitespace ? '' : 'color-icon-info')
		: 'tooltipped tooltipped-s btn btn-sm btn-outline tooltipped ' + (isHidingWhitespace ? 'bg-gray-light text-gray-light color-text-tertiary' : '');

	return (
		<a
			href={url.href}
			data-hotkey="d w"
			className={classes}
			aria-label={`${isHidingWhitespace ? 'Show' : 'Hide'} whitespace changes`}
		>
			{pageDetect.isPR() ? <DiffModifiedIcon/> : <>{isHidingWhitespace && <CheckIcon/>} No Whitespace</>}
		</a>
	);
}

function initPR(): false | void {
	select('.js-file-filter')!.closest('.flex-auto')!.append(
		<div className="diffbar-item d-flex">{createDiffStyleToggle()}</div>,
		<div className="diffbar-item d-flex">{createWhitespaceButton()}</div>,
	);

	// Trim title
	const prTitle = select('.pr-toolbar .js-issue-title');
	if (prTitle && select.exists('.pr-toolbar progress-bar')) { // Only review view has progress-bar
		prTitle.style.maxWidth = '24em';
		prTitle.title = prTitle.textContent!;
	}

	// Only show the native dropdown on medium and small screens #2597
	select('.js-diff-settings')!.closest('details')!.classList.add('d-lg-none');

	// Make space for the new button by removing "Changes from" #655
	select('[data-hotkey="c"] strong')!.previousSibling!.remove();

	// Remove extraneous padding around "Clear filters" button
	select('.subset-files-tab')?.classList.replace('px-sm-3', 'ml-sm-2');
}

function initCommitAndCompare(): false | void {
	select('#toc')!.prepend(
		<div className="float-right d-flex">
			<div className="d-flex ml-3 BtnGroup">{createDiffStyleToggle()}</div>
			<div className="d-flex ml-3 BtnGroup">{createWhitespaceButton()}</div>
		</div>,
	);

	// Remove previous options UI
	select('[data-ga-load^="Diff, view"]')!.remove();
}

void features.add(__filebasename, {
	include: [
		pageDetect.isPRFiles,
		pageDetect.isPRCommit,
	],
	exclude: [
		pageDetect.isPRFile404,
	],
	shortcuts: {
		'd w': 'Show/hide whitespaces in diffs',
	},
	init: initPR,
}, {
	include: [
		pageDetect.isSingleCommit,
		pageDetect.isCompare,
	],
	shortcuts: {
		'd w': 'Show/hide whitespaces in diffs',
	},
	init: initCommitAndCompare,
});