From f36d4f10c725b4511e0d28d5c1fec2cf1b2a22b6 Mon Sep 17 00:00:00 2001
From: Laxman <notlmn@outlook.com>
Date: Thu, 1 Aug 2019 23:12:46 +0530
Subject: Add `minimize-user-comments` feature (#2146)

Co-Authored-By: Federico Brigante <github@bfred.it>
---
 source/features/minimize-user-comments.tsx | 104 +++++++++++++++++++++++++++++
 1 file changed, 104 insertions(+)
 create mode 100644 source/features/minimize-user-comments.tsx

(limited to 'source/features/minimize-user-comments.tsx')

diff --git a/source/features/minimize-user-comments.tsx b/source/features/minimize-user-comments.tsx
new file mode 100644
index 00000000..90c73dc9
--- /dev/null
+++ b/source/features/minimize-user-comments.tsx
@@ -0,0 +1,104 @@
+import React from 'dom-chef';
+import select from 'select-dom';
+import delegate, {DelegateEvent} from 'delegate-it';
+import features from '../libs/features';
+import {appendBefore} from '../libs/dom-utils';
+import optionsStorage from '../options-storage';
+import {getUsername} from '../libs/utils';
+import onNewComments from '../libs/on-new-comments';
+import anchorScroll from '../libs/anchor-scroll';
+
+const getLabel = (restore: boolean): string => `${restore ? 'Restore' : 'Minimize'} user’s comments`;
+
+function getUsernameFromComment(comment: Element): string {
+	return select<HTMLAnchorElement>('.author', comment)!.pathname.slice(1);
+}
+
+async function getMinimizedUsers(): Promise<string[]> {
+	return (await optionsStorage.getAll()).minimizedUsers.trim().split(/\s+/);
+}
+
+async function setMinimizedUsers(minimizedUsers: string[]): Promise<void> {
+	return optionsStorage.set({minimizedUsers: minimizedUsers.join(' ')});
+}
+
+function toggleComment(comment: HTMLElement, minimize: boolean): void {
+	if (comment.id.startsWith('issue-') || comment.id.startsWith('pullrequestreview-')) {
+		return;
+	}
+
+	select('.unminimized-comment', comment)!.classList.toggle('d-none', minimize);
+	select('.minimized-comment', comment)!.classList.toggle('d-none', !minimize);
+	select('.minimized-comment .Details-element', comment)!.toggleAttribute('open', !minimize);
+}
+
+async function onButtonClick(event: React.MouseEvent<HTMLButtonElement>): Promise<void> {
+	const comment = event.currentTarget.closest('.js-targetable-comment')!;
+	const user = getUsernameFromComment(comment);
+
+	let minimizedUsers = await getMinimizedUsers();
+	if (minimizedUsers.includes(user)) {
+		minimizedUsers = minimizedUsers.filter(mutedUser => mutedUser !== user);
+	} else {
+		minimizedUsers.push(user);
+	}
+
+	await setMinimizedUsers(minimizedUsers);
+	anchorScroll(minimizeMutedUserComments, comment);
+}
+
+async function handleMenuOpening(event: DelegateEvent): Promise<void> {
+	const dropdown = event.delegateTarget.nextElementSibling!;
+	const user = getUsernameFromComment(dropdown.closest('.js-targetable-comment')!);
+	if (user === getUsername()) {
+		return;
+	}
+
+	const minimizedUsers = await getMinimizedUsers();
+	const shouldMinimizeComment = minimizedUsers.includes(user);
+
+	const existingButton = select('.rgh-minimize-user-comments-button', dropdown);
+	if (existingButton) {
+		existingButton.textContent = getLabel(shouldMinimizeComment);
+		return;
+	}
+
+	// Add option to mute or unmute user
+	appendBefore(dropdown, 'a[data-ga-click^="Report"]',
+		<button
+			className="dropdown-item btn-link rgh-minimize-user-comments-button"
+			role="menuitem"
+			type="button"
+			onClick={onButtonClick}>
+			{getLabel(shouldMinimizeComment)}
+		</button>
+	);
+}
+
+async function minimizeMutedUserComments(): Promise<void> {
+	const minimizedUsers = await getMinimizedUsers();
+
+	for (const comment of select.all('.js-discussion .js-minimizable-comment-group')) {
+		if (minimizedUsers.includes(getUsernameFromComment(comment))) {
+			toggleComment(comment, true);
+		}
+	}
+}
+
+function init(): void {
+	minimizeMutedUserComments();
+	onNewComments(minimizeMutedUserComments);
+	delegate('.timeline-comment-action', 'click', handleMenuOpening);
+}
+
+features.add({
+	id: __featureName__,
+	description: 'Adds ability to minimize comments of certain users.',
+	screenshot: 'https://user-images.githubusercontent.com/37769974/61595681-d6d4b400-ac17-11e9-98b9-03f27b004a94.gif',
+	include: [
+		features.isIssue,
+		features.isPRConversation
+	],
+	load: features.onAjaxedPages,
+	init
+});
-- 
cgit v1.2.3

