From bd231a06ba509f17882fb8aaf4c25d418c28fe2c Mon Sep 17 00:00:00 2001
From: Guilherme Gazzo <guilhermegazzo@gmail.com>
Date: Tue, 11 Jul 2023 18:22:38 -0300
Subject: [PATCH] refactor: Remove Accountbox usage (#29786)

---
 apps/meteor/app/lib/README.md                 | 13 ---
 apps/meteor/app/livechat/client/ui.js         | 12 +--
 apps/meteor/app/ui-utils/client/index.ts      |  1 -
 .../app/ui-utils/client/lib/AccountBox.ts     | 32 -------
 .../actions/hooks/useAdministrationItems.tsx  | 84 +++++++++++++------
 .../actions/hooks/useAdministrationMenu.tsx   | 70 ++--------------
 .../header/actions/hooks/useAuditItems.tsx    | 19 +++--
 .../sidebar/header/hooks/useStatusItems.tsx   | 10 +--
 apps/meteor/client/startup/iframeCommands.ts  |  2 +-
 9 files changed, 86 insertions(+), 157 deletions(-)

diff --git a/apps/meteor/app/lib/README.md b/apps/meteor/app/lib/README.md
index 708a9a21790..5201c4cadf0 100644
--- a/apps/meteor/app/lib/README.md
+++ b/apps/meteor/app/lib/README.md
@@ -47,19 +47,6 @@ settingsRegistry.addGroup('Settings_Group', function() {
 * `enableQuery` - Only enable this setting if the correspondent setting has the value specified
 * `alert` - Shows an alert message with the given text
 
-### AccountBox
-
-You can add items to the left upper corner drop menu:
-```javascript
-AccountBox.addItem({
-    name: 'Livechat',
-    icon: 'icon-chat-empty',
-    class: 'livechat-manager',
-    condition: () => {
-        return RocketChat.authz.hasPermission('view-livechat-manager');
-    }
-});
-```
 
 ### Functions
 n/a
diff --git a/apps/meteor/app/livechat/client/ui.js b/apps/meteor/app/livechat/client/ui.js
index 614b410cda2..5d8cc1696d4 100644
--- a/apps/meteor/app/livechat/client/ui.js
+++ b/apps/meteor/app/livechat/client/ui.js
@@ -1,14 +1,4 @@
-import { settings } from '../../settings/client';
-import { hasAllPermission } from '../../authorization/client';
-import { AccountBox, MessageTypes } from '../../ui-utils/client';
-
-AccountBox.addItem({
-	name: 'Omnichannel',
-	icon: 'headset',
-	href: '/omnichannel/current',
-	sideNav: 'omnichannelFlex',
-	condition: () => settings.get('Livechat_enabled') && hasAllPermission('view-livechat-manager'),
-});
+import { MessageTypes } from '../../ui-utils/client';
 
 MessageTypes.registerType({
 	id: 'livechat-close',
diff --git a/apps/meteor/app/ui-utils/client/index.ts b/apps/meteor/app/ui-utils/client/index.ts
index 83a1057a728..aaa5a082570 100644
--- a/apps/meteor/app/ui-utils/client/index.ts
+++ b/apps/meteor/app/ui-utils/client/index.ts
@@ -1,6 +1,5 @@
 import './lib/messageActionDefault';
 
-export { AccountBox } from './lib/AccountBox';
 export { MessageAction } from './lib/MessageAction';
 export { messageBox } from './lib/messageBox';
 export { readMessage } from './lib/readMessages';
diff --git a/apps/meteor/app/ui-utils/client/lib/AccountBox.ts b/apps/meteor/app/ui-utils/client/lib/AccountBox.ts
index 3ed3a60b3bf..c7bda9df165 100644
--- a/apps/meteor/app/ui-utils/client/lib/AccountBox.ts
+++ b/apps/meteor/app/ui-utils/client/lib/AccountBox.ts
@@ -1,12 +1,9 @@
 import type { IUIActionButton, IUActionButtonWhen } from '@rocket.chat/apps-engine/definition/ui/IUIActionButtonDescriptor';
 import type { UserStatus } from '@rocket.chat/core-typings';
-import { ReactiveVar } from 'meteor/reactive-var';
-import { Tracker } from 'meteor/tracker';
 import type { TranslationKey, LocationPathname } from '@rocket.chat/ui-contexts';
 import type { Icon } from '@rocket.chat/fuselage';
 import type { ComponentProps } from 'react';
 
-import { applyDropdownActionButtonFilters } from '../../../ui-message/client/actionButtons/lib/applyButtonFilters';
 import { sdk } from '../../../utils/client/lib/SDKClient';
 
 export interface IAppAccountBoxItem extends IUIActionButton {
@@ -30,38 +27,9 @@ export type AccountBoxItem = {
 export const isAppAccountBoxItem = (item: IAppAccountBoxItem | AccountBoxItem): item is IAppAccountBoxItem => 'isAppButtonItem' in item;
 
 class AccountBoxBase {
-	private items = new ReactiveVar<IAppAccountBoxItem[]>([]);
-
 	public setStatus(status: UserStatus, statusText?: string): any {
 		return sdk.rest.post('/v1/users.setStatus', { status, message: statusText });
 	}
-
-	public async addItem(newItem: IAppAccountBoxItem): Promise<void> {
-		Tracker.nonreactive(() => {
-			const actual = this.items.get();
-			actual.push(newItem);
-			this.items.set(actual);
-		});
-	}
-
-	public async deleteItem(item: IAppAccountBoxItem): Promise<void> {
-		Tracker.nonreactive(() => {
-			const actual = this.items.get();
-			const itemIndex = actual.findIndex((actualItem: IAppAccountBoxItem) => actualItem.appId === item.appId);
-			actual.splice(itemIndex, 1);
-			this.items.set(actual);
-		});
-	}
-
-	public getItems(): (IAppAccountBoxItem | AccountBoxItem)[] {
-		return this.items.get().filter((item: IAppAccountBoxItem | AccountBoxItem) => {
-			if ('condition' in item) {
-				return item.condition();
-			}
-
-			return applyDropdownActionButtonFilters(item);
-		});
-	}
 }
 
 export const AccountBox = new AccountBoxBase();
diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx
index 97bcb291a37..c0dc83fb62c 100644
--- a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx
+++ b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx
@@ -1,8 +1,16 @@
-import { useTranslation, useRoute, useMethod, useSetModal, useRole, useRouter } from '@rocket.chat/ui-contexts';
+import {
+	useTranslation,
+	useRoute,
+	useMethod,
+	useSetModal,
+	useRole,
+	useRouter,
+	useAtLeastOnePermission,
+	usePermission,
+} from '@rocket.chat/ui-contexts';
 import { useQuery } from '@tanstack/react-query';
 import React from 'react';
 
-import type { AccountBoxItem } from '../../../../../app/ui-utils/client/lib/AccountBox';
 import type { UpgradeTabVariant } from '../../../../../lib/upgradeTab';
 import { getUpgradeTabLabel, isFullyFeature } from '../../../../../lib/upgradeTab';
 import Emoji from '../../../../components/Emoji';
@@ -10,17 +18,45 @@ import type { GenericMenuItemProps } from '../../../../components/GenericMenu/Ge
 import RegisterWorkspaceModal from '../../../../views/admin/cloud/modals/RegisterWorkspaceModal';
 import { useUpgradeTabParams } from '../../../../views/hooks/useUpgradeTabParams';
 
-type useAdministrationItemProps = {
-	accountBoxItems: AccountBoxItem[];
-	showWorkspace: boolean;
-};
-export const useAdministrationItems = ({ accountBoxItems, showWorkspace }: useAdministrationItemProps): GenericMenuItemProps[] => {
+const ADMIN_PERMISSIONS = [
+	'view-statistics',
+	'run-import',
+	'view-user-administration',
+	'view-room-administration',
+	'create-invite-links',
+	'manage-cloud',
+	'view-logs',
+	'manage-sounds',
+	'view-federation-data',
+	'manage-email-inbox',
+	'manage-emoji',
+	'manage-outgoing-integrations',
+	'manage-own-outgoing-integrations',
+	'manage-incoming-integrations',
+	'manage-own-incoming-integrations',
+	'manage-oauth-apps',
+	'access-mailer',
+	'manage-user-status',
+	'access-permissions',
+	'access-setting-permissions',
+	'view-privileged-setting',
+	'edit-privileged-setting',
+	'manage-selected-settings',
+	'view-engagement-dashboard',
+	'view-moderation-console',
+];
+
+export const useAdministrationItems = (): GenericMenuItemProps[] => {
 	const router = useRouter();
 	const t = useTranslation();
 
+	const shouldShowAdminMenu = useAtLeastOnePermission(ADMIN_PERMISSIONS);
+
 	const { tabType, trialEndDate, isLoading } = useUpgradeTabParams();
 	const shouldShowEmoji = isFullyFeature(tabType);
+
 	const label = getUpgradeTabLabel(tabType);
+
 	const isAdmin = useRole('admin');
 	const setModal = useSetModal();
 
@@ -36,8 +72,18 @@ export const useAdministrationItems = ({ accountBoxItems, showWorkspace }: useAd
 	const adminRoute = useRoute('admin-index');
 	const upgradeRoute = useRoute('upgrade');
 	const cloudRoute = useRoute('cloud');
+
+	const omnichannel = usePermission('view-livechat-manager');
+
 	const showUpgradeItem = !isLoading && tabType;
 
+	const omnichannelItem: GenericMenuItemProps = {
+		id: 'omnichannel',
+		content: t('Omnichannel'),
+		icon: 'headset',
+		onClick: () => router.navigate('/omnichannel/current'),
+	};
+
 	const upgradeItem: GenericMenuItemProps = {
 		id: 'showUpgradeItem',
 		content: (
@@ -71,24 +117,10 @@ export const useAdministrationItems = ({ accountBoxItems, showWorkspace }: useAd
 		},
 	};
 
-	const accountBoxItem: GenericMenuItemProps[] = accountBoxItems.map((item, key) => {
-		const action = () => {
-			if (item.href) {
-				router.navigate(item.href);
-			}
-		};
-		return {
-			id: `account-box-item-${key}`,
-			content: t(item.name),
-			icon: item.icon,
-			onClick: action,
-		};
-	});
-
 	return [
-		...(showUpgradeItem ? [upgradeItem] : []),
-		...(isAdmin ? [adminItem] : []),
-		...(showWorkspace ? [workspaceItem] : []),
-		...(accountBoxItems.length ? accountBoxItem : []),
-	];
+		showUpgradeItem && upgradeItem,
+		isAdmin && adminItem,
+		omnichannel && omnichannelItem,
+		shouldShowAdminMenu && workspaceItem,
+	].filter(Boolean) as GenericMenuItemProps[];
 };
diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationMenu.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationMenu.tsx
index 72b9b90419a..5be021cf0b7 100644
--- a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationMenu.tsx
+++ b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationMenu.tsx
@@ -1,72 +1,20 @@
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import { useAtLeastOnePermission, usePermission, useTranslation } from '@rocket.chat/ui-contexts';
+import { useTranslation } from '@rocket.chat/ui-contexts';
 
-import { AccountBox } from '../../../../../app/ui-utils/client';
-import type { IAppAccountBoxItem, AccountBoxItem } from '../../../../../app/ui-utils/client/lib/AccountBox';
-import { isAppAccountBoxItem } from '../../../../../app/ui-utils/client/lib/AccountBox';
-import { useHasLicenseModule } from '../../../../../ee/client/hooks/useHasLicenseModule';
-import { useReactiveValue } from '../../../../hooks/useReactiveValue';
+import type { GenericMenuItemProps } from '../../../../components/GenericMenu/GenericMenuItem';
 import { useAdministrationItems } from './useAdministrationItems';
 import { useAppsItems } from './useAppsItems';
 import { useAuditItems } from './useAuditItems';
 
-const ADMIN_PERMISSIONS = [
-	'view-statistics',
-	'run-import',
-	'view-user-administration',
-	'view-room-administration',
-	'create-invite-links',
-	'manage-cloud',
-	'view-logs',
-	'manage-sounds',
-	'view-federation-data',
-	'manage-email-inbox',
-	'manage-emoji',
-	'manage-outgoing-integrations',
-	'manage-own-outgoing-integrations',
-	'manage-incoming-integrations',
-	'manage-own-incoming-integrations',
-	'manage-oauth-apps',
-	'access-mailer',
-	'manage-user-status',
-	'access-permissions',
-	'access-setting-permissions',
-	'view-privileged-setting',
-	'edit-privileged-setting',
-	'manage-selected-settings',
-	'view-engagement-dashboard',
-	'view-moderation-console',
-];
-
 export const useAdministrationMenu = () => {
 	const t = useTranslation();
-	const getAccountBoxItems = useMutableCallback(() => AccountBox.getItems());
-	const accountBoxItems = useReactiveValue(getAccountBoxItems);
-
-	const hasAuditLicense = useHasLicenseModule('auditing') === true;
-	const hasManageAppsPermission = usePermission('manage-apps');
-	const hasAccessMarketplacePermission = usePermission('access-marketplace');
-	const hasAdminPermission = useAtLeastOnePermission(ADMIN_PERMISSIONS);
-	const hasAuditPermission = usePermission('can-audit') && hasAuditLicense;
-	const hasAuditLogPermission = usePermission('can-audit-log') && hasAuditLicense;
-
-	const appBoxItems = accountBoxItems.filter((item): item is IAppAccountBoxItem => isAppAccountBoxItem(item));
-	const adminBoxItems = accountBoxItems.filter((item): item is AccountBoxItem => !isAppAccountBoxItem(item));
 
-	const showAdmin = hasAdminPermission || !!adminBoxItems.length;
-	const showAudit = hasAuditPermission || hasAuditLogPermission;
-	const showWorkspace = hasAdminPermission;
-	const showApps = hasAccessMarketplacePermission || hasManageAppsPermission || !!appBoxItems.length;
-
-	const administrationItems = useAdministrationItems({ accountBoxItems: adminBoxItems, showWorkspace });
+	const administrationItems = useAdministrationItems();
 	const appItems = useAppsItems();
-	const auditItems = useAuditItems({ showAudit: hasAuditPermission, showAuditLog: hasAuditLogPermission });
-
-	const sections = [
-		{ title: t('Administration'), items: administrationItems, permission: showAdmin },
-		{ title: t('Apps'), items: appItems, permission: showApps },
-		{ title: t('Audit'), items: auditItems, permission: showAudit },
-	];
+	const auditItems = useAuditItems();
 
-	return sections.filter(({ permission }) => permission);
+	return [
+		administrationItems.length && { title: t('Administration'), items: administrationItems },
+		appItems.length && { title: t('Apps'), items: appItems },
+		auditItems.length && { title: t('Audit'), items: auditItems },
+	].filter(Boolean) as Array<{ title: string; items: GenericMenuItemProps[] }>;
 };
diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx
index 3ed3ba94dcb..07b2b9bb11c 100644
--- a/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx
+++ b/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx
@@ -1,18 +1,23 @@
-import { useTranslation, useRoute } from '@rocket.chat/ui-contexts';
+import { useTranslation, useRoute, usePermission } from '@rocket.chat/ui-contexts';
 
+import { useHasLicenseModule } from '../../../../../ee/client/hooks/useHasLicenseModule';
 import type { GenericMenuItemProps } from '../../../../components/GenericMenu/GenericMenuItem';
 
-type useAuditItemsProps = {
-	showAudit: boolean;
-	showAuditLog: boolean;
-};
+export const useAuditItems = (): GenericMenuItemProps[] => {
+	const hasAuditLicense = useHasLicenseModule('auditing') === true;
+
+	const hasAuditPermission = usePermission('can-audit') && hasAuditLicense;
+	const hasAuditLogPermission = usePermission('can-audit-log') && hasAuditLicense;
 
-export const useAuditItems = ({ showAudit, showAuditLog }: useAuditItemsProps): GenericMenuItemProps[] => {
 	const t = useTranslation();
 
 	const auditHomeRoute = useRoute('audit-home');
 	const auditSettingsRoute = useRoute('audit-log');
 
+	if (!hasAuditPermission && !hasAuditLogPermission) {
+		return [];
+	}
+
 	const auditMessageItem: GenericMenuItemProps = {
 		id: 'messages',
 		icon: 'document-eye',
@@ -26,5 +31,5 @@ export const useAuditItems = ({ showAudit, showAuditLog }: useAuditItemsProps):
 		onClick: () => auditSettingsRoute.push(),
 	};
 
-	return [...(showAudit ? [auditMessageItem] : []), ...(showAuditLog ? [auditLogItem] : [])];
+	return [hasAuditPermission && auditMessageItem, hasAuditLogPermission && auditLogItem].filter(Boolean) as GenericMenuItemProps[];
 };
diff --git a/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx b/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx
index 8621846456f..ca45e53bf5e 100644
--- a/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx
+++ b/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx
@@ -2,10 +2,9 @@ import type { IUser, ValueOf } from '@rocket.chat/core-typings';
 import { UserStatus as UserStatusEnum } from '@rocket.chat/core-typings';
 import { Box } from '@rocket.chat/fuselage';
 import type { TranslationKey } from '@rocket.chat/ui-contexts';
-import { useSetting, useTranslation } from '@rocket.chat/ui-contexts';
+import { useEndpoint, useSetting, useTranslation } from '@rocket.chat/ui-contexts';
 import React from 'react';
 
-import { AccountBox } from '../../../../app/ui-utils/client';
 import { userStatus } from '../../../../app/user-status/client';
 import { callbacks } from '../../../../lib/callbacks';
 import type { GenericMenuItemProps } from '../../../components/GenericMenu/GenericMenuItem';
@@ -27,9 +26,10 @@ const translateStatusName = (t: ReturnType<typeof useTranslation>, status: (type
 export const useStatusItems = (user: IUser): GenericMenuItemProps[] => {
 	const t = useTranslation();
 	const presenceDisabled = useSetting<boolean>('Presence_broadcast_disabled');
+	const setStatus = useEndpoint('POST', '/v1/users.setStatus');
 
-	const setStatus = (status: (typeof userStatus.list)['']): void => {
-		AccountBox.setStatus(status.statusType, !isDefaultStatus(status.id) ? status.name : '');
+	const setStatusAction = (status: (typeof userStatus.list)['']): void => {
+		setStatus({ status: status.statusType, message: !isDefaultStatus(status.id) ? status.name : '' });
 		void callbacks.run('userStatusManuallySet', status);
 	};
 
@@ -64,7 +64,7 @@ export const useStatusItems = (user: IUser): GenericMenuItemProps[] => {
 				id: status.id,
 				status: <UserStatus status={modifier} />,
 				content: <MarkdownText content={name} parseEmoji={true} variant='inline' />,
-				onClick: () => setStatus(status),
+				onClick: () => setStatusAction(status),
 				disabled: presenceDisabled,
 			};
 		});
diff --git a/apps/meteor/client/startup/iframeCommands.ts b/apps/meteor/client/startup/iframeCommands.ts
index 3ecf578587b..25836a38f5c 100644
--- a/apps/meteor/client/startup/iframeCommands.ts
+++ b/apps/meteor/client/startup/iframeCommands.ts
@@ -5,7 +5,7 @@ import { Meteor } from 'meteor/meteor';
 import { ServiceConfiguration } from 'meteor/service-configuration';
 
 import { settings } from '../../app/settings/client';
-import { AccountBox } from '../../app/ui-utils/client';
+import { AccountBox } from '../../app/ui-utils/client/lib/AccountBox';
 import { sdk } from '../../app/utils/client/lib/SDKClient';
 import { callbacks } from '../../lib/callbacks';
 import { capitalize, ltrim, rtrim } from '../../lib/utils/stringUtils';
-- 
GitLab