diff --git a/apps/meteor/client/hooks/useHideRoomAction.tsx b/apps/meteor/client/hooks/useHideRoomAction.tsx
new file mode 100644
index 00000000000..51b07cdd046
--- /dev/null
+++ b/apps/meteor/client/hooks/useHideRoomAction.tsx
@@ -0,0 +1,95 @@
+import type { RoomType } from '@rocket.chat/core-typings';
+import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
+import type { TranslationKey } from '@rocket.chat/ui-contexts';
+import { useEndpoint, useSetModal, useToastMessageDispatch, useRouter, useUserId } from '@rocket.chat/ui-contexts';
+import { useMutation } from '@tanstack/react-query';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { useDontAskAgain } from './useDontAskAgain';
+import { UiTextContext } from '../../definition/IRoomTypeConfig';
+import { GenericModalDoNotAskAgain } from '../components/GenericModal';
+import { updateSubscription } from '../lib/mutationEffects/updateSubscription';
+import { roomCoordinator } from '../lib/rooms/roomCoordinator';
+
+type HideRoomProps = {
+ rid: string;
+ type: RoomType;
+ name: string;
+};
+
+type HideRoomOptions = {
+ redirect?: boolean;
+};
+
+const CLOSE_ENDPOINTS_BY_ROOM_TYPE = {
+ p: '/v1/groups.close', // private
+ c: '/v1/channels.close', // channel
+ d: '/v1/im.close', // direct message
+ v: '/v1/channels.close', // omnichannel voip
+ l: '/v1/channels.close', // livechat
+} as const;
+
+export const useHideRoomAction = ({ rid: roomId, type, name }: HideRoomProps, { redirect = true }: HideRoomOptions = {}) => {
+ const { t } = useTranslation();
+ const setModal = useSetModal();
+ const closeModal = useEffectEvent(() => setModal());
+ const dispatchToastMessage = useToastMessageDispatch();
+ const dontAskHideRoom = useDontAskAgain('hideRoom');
+ const router = useRouter();
+ const userId = useUserId();
+
+ const hideRoomEndpoint = useEndpoint('POST', CLOSE_ENDPOINTS_BY_ROOM_TYPE[type]);
+
+ const hideRoom = useMutation({
+ mutationFn: () => hideRoomEndpoint({ roomId }),
+ onMutate: async () => {
+ closeModal();
+
+ if (userId) {
+ return updateSubscription(roomId, userId, { alert: false, open: false });
+ }
+ },
+ onSuccess: () => {
+ if (redirect) {
+ router.navigate('/home');
+ }
+ },
+ onError: async (error, _, rollbackDocument) => {
+ dispatchToastMessage({ type: 'error', message: error });
+
+ if (userId && rollbackDocument) {
+ const { alert, open } = rollbackDocument;
+ updateSubscription(roomId, userId, { alert, open });
+ }
+ },
+ });
+
+ const handleHide = useEffectEvent(async () => {
+ const warnText = roomCoordinator.getRoomDirectives(type).getUiText(UiTextContext.HIDE_WARNING);
+
+ if (dontAskHideRoom) {
+ hideRoom.mutate();
+ return;
+ }
+
+ setModal(
+ hideRoom.mutate()}
+ dontAskAgain={{
+ action: 'hideRoom',
+ label: t('Hide_room'),
+ }}
+ >
+ {t(warnText as TranslationKey, { postProcess: 'sprintf', sprintf: [name] })}
+ ,
+ );
+ });
+
+ return handleHide;
+};
diff --git a/apps/meteor/client/lib/mutationEffects/updateSubscription.ts b/apps/meteor/client/lib/mutationEffects/updateSubscription.ts
new file mode 100644
index 00000000000..4decdbb4ccb
--- /dev/null
+++ b/apps/meteor/client/lib/mutationEffects/updateSubscription.ts
@@ -0,0 +1,11 @@
+import type { ISubscription } from '@rocket.chat/core-typings';
+
+import { Subscriptions } from '../../../app/models/client';
+
+export const updateSubscription = (roomId: string, userId: string, data: Partial) => {
+ const oldDocument = Subscriptions.findOne({ 'rid': roomId, 'u._id': userId });
+
+ Subscriptions.update({ 'rid': roomId, 'u._id': userId }, { $set: data });
+
+ return oldDocument;
+};
diff --git a/apps/meteor/client/methods/hideRoom.ts b/apps/meteor/client/methods/hideRoom.ts
deleted file mode 100644
index 0f45717fd49..00000000000
--- a/apps/meteor/client/methods/hideRoom.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import type { ServerMethods } from '@rocket.chat/ddp-client';
-import { Meteor } from 'meteor/meteor';
-
-import { Subscriptions } from '../../app/models/client';
-
-Meteor.methods({
- async hideRoom(rid) {
- if (!Meteor.userId()) {
- return 0;
- }
-
- return Subscriptions.update(
- {
- rid,
- 'u._id': Meteor.userId(),
- },
- {
- $set: {
- alert: false,
- open: false,
- },
- },
- );
- },
-});
diff --git a/apps/meteor/client/methods/index.ts b/apps/meteor/client/methods/index.ts
index 7be75a2707f..0cdd4e54be5 100644
--- a/apps/meteor/client/methods/index.ts
+++ b/apps/meteor/client/methods/index.ts
@@ -1,4 +1,3 @@
-import './hideRoom';
import './openRoom';
import './pinMessage';
import './unpinMessage';
diff --git a/apps/meteor/client/sidebar/RoomMenu.tsx b/apps/meteor/client/sidebar/RoomMenu.tsx
index 4baeb3fb824..4e20baf8929 100644
--- a/apps/meteor/client/sidebar/RoomMenu.tsx
+++ b/apps/meteor/client/sidebar/RoomMenu.tsx
@@ -19,9 +19,8 @@ import React, { memo, useMemo } from 'react';
import { LegacyRoomManager } from '../../app/ui-utils/client';
import { UiTextContext } from '../../definition/IRoomTypeConfig';
-import { GenericModalDoNotAskAgain } from '../components/GenericModal';
import WarningModal from '../components/WarningModal';
-import { useDontAskAgain } from '../hooks/useDontAskAgain';
+import { useHideRoomAction } from '../hooks/useHideRoomAction';
import { roomCoordinator } from '../lib/rooms/roomCoordinator';
import { useOmnichannelPrioritiesMenu } from '../omnichannel/hooks/useOmnichannelPrioritiesMenu';
@@ -43,15 +42,6 @@ type RoomMenuProps = {
hideDefaultOptions: boolean;
};
-const closeEndpoints = {
- p: '/v1/groups.close',
- c: '/v1/channels.close',
- d: '/v1/im.close',
-
- v: '/v1/channels.close',
- l: '/v1/groups.close',
-} as const;
-
const leaveEndpoints = {
p: '/v1/groups.leave',
c: '/v1/channels.leave',
@@ -84,9 +74,6 @@ const RoomMenu = ({
const canFavorite = useSetting('Favorite_Rooms');
const isFavorite = Boolean(subscription?.f);
- const dontAskHideRoom = useDontAskAgain('hideRoom');
-
- const hideRoom = useEndpoint('POST', closeEndpoints[type]);
const readMessages = useEndpoint('POST', '/v1/subscriptions.read');
const toggleFavorite = useEndpoint('POST', '/v1/rooms.favorite');
const leaveRoom = useEndpoint('POST', leaveEndpoints[type]);
@@ -103,6 +90,8 @@ const RoomMenu = ({
const queryClient = useQueryClient();
+ const handleHide = useHideRoomAction({ rid, type, name }, { redirect: false });
+
const canLeave = ((): boolean => {
if (type === 'c' && !canLeaveChannel) {
return false;
@@ -140,40 +129,6 @@ const RoomMenu = ({
);
});
- const handleHide = useMutableCallback(async () => {
- const hide = async (): Promise => {
- try {
- await hideRoom({ roomId: rid });
- } catch (error) {
- dispatchToastMessage({ type: 'error', message: error });
- }
- closeModal();
- };
-
- const warnText = roomCoordinator.getRoomDirectives(type).getUiText(UiTextContext.HIDE_WARNING);
-
- if (dontAskHideRoom) {
- return hide();
- }
-
- setModal(
-
- {t(warnText as TranslationKey, name)}
- ,
- );
- });
-
const handleToggleRead = useMutableCallback(async () => {
try {
queryClient.invalidateQueries(['sidebar/search/spotlight']);
diff --git a/apps/meteor/client/sidebarv2/RoomMenu.tsx b/apps/meteor/client/sidebarv2/RoomMenu.tsx
index 8b031e8cfce..0c593afd683 100644
--- a/apps/meteor/client/sidebarv2/RoomMenu.tsx
+++ b/apps/meteor/client/sidebarv2/RoomMenu.tsx
@@ -19,9 +19,8 @@ import React, { memo, useMemo } from 'react';
import { LegacyRoomManager } from '../../app/ui-utils/client';
import { UiTextContext } from '../../definition/IRoomTypeConfig';
-import { GenericModalDoNotAskAgain } from '../components/GenericModal';
import WarningModal from '../components/WarningModal';
-import { useDontAskAgain } from '../hooks/useDontAskAgain';
+import { useHideRoomAction } from '../hooks/useHideRoomAction';
import { roomCoordinator } from '../lib/rooms/roomCoordinator';
import { useOmnichannelPrioritiesMenu } from '../omnichannel/hooks/useOmnichannelPrioritiesMenu';
@@ -43,15 +42,6 @@ type RoomMenuProps = {
hideDefaultOptions: boolean;
};
-const closeEndpoints = {
- p: '/v1/groups.close',
- c: '/v1/channels.close',
- d: '/v1/im.close',
-
- v: '/v1/channels.close',
- l: '/v1/groups.close',
-} as const;
-
const leaveEndpoints = {
p: '/v1/groups.leave',
c: '/v1/channels.leave',
@@ -84,9 +74,6 @@ const RoomMenu = ({
const canFavorite = useSetting('Favorite_Rooms');
const isFavorite = Boolean(subscription?.f);
- const dontAskHideRoom = useDontAskAgain('hideRoom');
-
- const hideRoom = useEndpoint('POST', closeEndpoints[type]);
const readMessages = useEndpoint('POST', '/v1/subscriptions.read');
const toggleFavorite = useEndpoint('POST', '/v1/rooms.favorite');
const leaveRoom = useEndpoint('POST', leaveEndpoints[type]);
@@ -103,6 +90,8 @@ const RoomMenu = ({
const queryClient = useQueryClient();
+ const handleHide = useHideRoomAction({ rid, type, name }, { redirect: false });
+
const canLeave = ((): boolean => {
if (type === 'c' && !canLeaveChannel) {
return false;
@@ -140,40 +129,6 @@ const RoomMenu = ({
);
});
- const handleHide = useEffectEvent(async () => {
- const hide = async (): Promise => {
- try {
- await hideRoom({ roomId: rid });
- } catch (error) {
- dispatchToastMessage({ type: 'error', message: error });
- }
- closeModal();
- };
-
- const warnText = roomCoordinator.getRoomDirectives(type).getUiText(UiTextContext.HIDE_WARNING);
-
- if (dontAskHideRoom) {
- return hide();
- }
-
- setModal(
-
- {t(warnText as TranslationKey, name)}
- ,
- );
- });
-
const handleToggleRead = useEffectEvent(async () => {
try {
queryClient.invalidateQueries(['sidebar/search/spotlight']);
diff --git a/apps/meteor/client/views/room/contextualBar/Info/hooks/actions/useRoomHide.tsx b/apps/meteor/client/views/room/contextualBar/Info/hooks/actions/useRoomHide.tsx
deleted file mode 100644
index c381359d52c..00000000000
--- a/apps/meteor/client/views/room/contextualBar/Info/hooks/actions/useRoomHide.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import type { IRoom } from '@rocket.chat/core-typings';
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import type { TranslationKey } from '@rocket.chat/ui-contexts';
-import { useSetModal, useToastMessageDispatch, useMethod, useTranslation, useRouter } from '@rocket.chat/ui-contexts';
-import React from 'react';
-
-import { UiTextContext } from '../../../../../../../definition/IRoomTypeConfig';
-import WarningModal from '../../../../../../components/WarningModal';
-import { roomCoordinator } from '../../../../../../lib/rooms/roomCoordinator';
-
-export const useRoomHide = (room: IRoom) => {
- const t = useTranslation();
- const setModal = useSetModal();
- const dispatchToastMessage = useToastMessageDispatch();
- const hideRoom = useMethod('hideRoom');
- const router = useRouter();
-
- const handleHide = useMutableCallback(async () => {
- const hide = async () => {
- try {
- await hideRoom(room._id);
- router.navigate('/home');
- } catch (error) {
- dispatchToastMessage({ type: 'error', message: error });
- }
- setModal(null);
- };
-
- const warnText = roomCoordinator.getRoomDirectives(room.t).getUiText(UiTextContext.HIDE_WARNING);
-
- setModal(
- setModal(null)}
- cancelText={t('Cancel')}
- confirm={hide}
- />,
- );
- });
-
- return handleHide;
-};
diff --git a/apps/meteor/client/views/room/contextualBar/Info/hooks/useRoomActions.ts b/apps/meteor/client/views/room/contextualBar/Info/hooks/useRoomActions.ts
index 592093fa1ae..201e0131646 100644
--- a/apps/meteor/client/views/room/contextualBar/Info/hooks/useRoomActions.ts
+++ b/apps/meteor/client/views/room/contextualBar/Info/hooks/useRoomActions.ts
@@ -3,9 +3,9 @@ import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useRoomConvertToTeam } from './actions/useRoomConvertToTeam';
-import { useRoomHide } from './actions/useRoomHide';
import { useRoomLeave } from './actions/useRoomLeave';
import { useRoomMoveToTeam } from './actions/useRoomMoveToTeam';
+import { useHideRoomAction } from '../../../../../hooks/useHideRoomAction';
import { useDeleteRoom } from '../../../../hooks/roomActions/useDeleteRoom';
type UseRoomActionsOptions = {
@@ -18,11 +18,12 @@ export const useRoomActions = (room: IRoom, options: UseRoomActionsOptions) => {
const { onClickEnterRoom, onClickEdit, resetState } = options;
const { t } = useTranslation();
- const handleHide = useRoomHide(room);
+
const handleLeave = useRoomLeave(room);
const { handleDelete, canDeleteRoom } = useDeleteRoom(room, { reload: resetState });
const handleMoveToTeam = useRoomMoveToTeam(room);
const handleConvertToTeam = useRoomConvertToTeam(room);
+ const handleHide = useHideRoomAction({ rid: room._id, type: room.t, name: room.name ?? '' });
return useMemo(() => {
const memoizedActions = {
diff --git a/apps/meteor/client/views/teams/contextualBar/info/TeamsInfoWithData.tsx b/apps/meteor/client/views/teams/contextualBar/info/TeamsInfoWithData.tsx
index a90e5b98a3a..4136ebcea61 100644
--- a/apps/meteor/client/views/teams/contextualBar/info/TeamsInfoWithData.tsx
+++ b/apps/meteor/client/views/teams/contextualBar/info/TeamsInfoWithData.tsx
@@ -1,17 +1,13 @@
import type { IRoom, Serialized } from '@rocket.chat/core-typings';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import type { TranslationKey } from '@rocket.chat/ui-contexts';
-import { useSetModal, useToastMessageDispatch, useUserId, usePermission, useMethod, useRouter } from '@rocket.chat/ui-contexts';
+import { useSetModal, useToastMessageDispatch, useUserId, usePermission, useRouter } from '@rocket.chat/ui-contexts';
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import LeaveTeam from './LeaveTeam';
import TeamsInfo from './TeamsInfo';
-import { UiTextContext } from '../../../../../definition/IRoomTypeConfig';
-import { GenericModalDoNotAskAgain } from '../../../../components/GenericModal';
-import { useDontAskAgain } from '../../../../hooks/useDontAskAgain';
import { useEndpointAction } from '../../../../hooks/useEndpointAction';
-import { roomCoordinator } from '../../../../lib/rooms/roomCoordinator';
+import { useHideRoomAction } from '../../../../hooks/useHideRoomAction';
import { useDeleteRoom } from '../../../hooks/roomActions/useDeleteRoom';
import { useRoom } from '../../../room/contexts/RoomContext';
import { useRoomToolbox } from '../../../room/contexts/RoomToolboxContext';
@@ -27,8 +23,6 @@ const TeamsInfoWithLogic = ({ openEditing }: TeamsInfoWithLogicProps) => {
const { t } = useTranslation();
const userId = useUserId();
- const dontAskHideRoom = useDontAskAgain('hideRoom');
-
const dispatchToastMessage = useToastMessageDispatch();
const setModal = useSetModal();
const closeModal = useMutableCallback(() => setModal());
@@ -36,7 +30,7 @@ const TeamsInfoWithLogic = ({ openEditing }: TeamsInfoWithLogicProps) => {
const leaveTeam = useEndpointAction('POST', '/v1/teams.leave');
const convertTeamToChannel = useEndpointAction('POST', '/v1/teams.convertToChannel');
- const hideTeam = useMethod('hideRoom');
+ const hideTeam = useHideRoomAction({ rid: room._id, type: room.t, name: room.name ?? '' });
const router = useRouter();
@@ -68,42 +62,6 @@ const TeamsInfoWithLogic = ({ openEditing }: TeamsInfoWithLogicProps) => {
setModal();
});
- const handleHide = useMutableCallback(async () => {
- const hide = async () => {
- try {
- await hideTeam(room._id);
- router.navigate('/home');
- } catch (error) {
- dispatchToastMessage({ type: 'error', message: error });
- } finally {
- closeModal();
- }
- };
-
- const warnText = roomCoordinator.getRoomDirectives(room.t).getUiText(UiTextContext.HIDE_WARNING) as TranslationKey;
-
- if (dontAskHideRoom) {
- return hide();
- }
-
- setModal(
-
- {t(warnText, { postProcess: 'sprintf', sprintf: [room.fname] })}
- ,
- );
- });
-
const onClickViewChannels = useCallback(() => openTab('team-channels'), [openTab]);
const onClickConvertToChannel = useMutableCallback(() => {
@@ -134,7 +92,7 @@ const TeamsInfoWithLogic = ({ openEditing }: TeamsInfoWithLogicProps) => {
onClickClose={closeTab}
onClickDelete={canDeleteRoom ? handleDelete : undefined}
onClickLeave={onClickLeave}
- onClickHide={handleHide}
+ onClickHide={hideTeam}
onClickViewChannels={onClickViewChannels}
onClickConvertToChannel={canEdit ? onClickConvertToChannel : undefined}
/>