summaryrefslogtreecommitdiff
path: root/source/features/comment-fields-keyboard-shortcuts.tsx
blob: f4308ef66e9da26beefae4af9865ccdd91187616 (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
import React from 'dom-chef';
import select from 'select-dom';
import onetime from 'onetime';
import delegate from 'delegate-it';
import * as pageDetect from 'github-url-detection';

import features from '.';
import {onCommentFieldKeydown} from '../github-events/on-field-keydown';

function eventHandler(event: delegate.Event<KeyboardEvent, HTMLTextAreaElement>): void {
	const field = event.delegateTarget;

	if (event.key === 'Escape') {
		// Cancel buttons have different classes for inline comments and editable comments
		const cancelButton = select(`
			button.js-hide-inline-comment-form,
			button.js-comment-cancel-button
		`, field.form!);

		// Cancel if there is a button, else blur the field
		if (cancelButton) {
			cancelButton.click();
		} else {
			field.blur();
		}

		event.stopImmediatePropagation();
		event.preventDefault();
	} else if (event.key === 'ArrowUp' && field.value === '') {
		const currentConversationContainer = field.closest([
			'.js-inline-comments-container', // Current review thread container
			'#discussion_bucket', // Or just ALL the comments in issues
			'#all_commit_comments', // Single commit comments at the bottom
		].join(','))!;
		const lastOwnComment = select
			.all('.js-comment.current-user', currentConversationContainer)
			.reverse()
			.find(comment => {
				const collapsible = comment.closest('details');
				return !collapsible || collapsible.open;
			});

		if (lastOwnComment) {
			// Make the comment editable (the native edit button might not be available yet)
			const editButton = <button hidden type="button" className="js-comment-edit-button"/>;
			lastOwnComment.append(editButton);
			editButton.click();
			editButton.remove();
			field
				.closest('form')!
				.querySelector('button.js-hide-inline-comment-form')
				?.click();

			// Move caret to end of field
			requestAnimationFrame(() => {
				select('textarea.js-comment-field', lastOwnComment)!.selectionStart = Number.MAX_SAFE_INTEGER;
			});
		}
	}
}

function init(): void {
	onCommentFieldKeydown(eventHandler);
}

void features.add(__filebasename, {
	shortcuts: {
		'↑': 'Edit your last comment',
		esc: 'Unfocuses comment field',
	},
	include: [
		pageDetect.hasRichTextEditor,
	],
	awaitDomReady: false,
	deduplicate: 'has-rgh-inner',
	init: onetime(init),
});