RocketChat/Rocket.Chat

View on GitHub
apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/hooks/useStatusItems.tsx

Summary

Maintainability
F
4 days
Test Coverage
import { Box } from '@rocket.chat/fuselage';
import { useEndpoint, useSetting } from '@rocket.chat/ui-contexts';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';

import { callbacks } from '../../../../../lib/callbacks';
import type { GenericMenuItemProps } from '../../../../components/GenericMenu/GenericMenuItem';
import MarkdownText from '../../../../components/MarkdownText';
import { UserStatus } from '../../../../components/UserStatus';
import { userStatuses } from '../../../../lib/userStatuses';
import type { UserStatusDescriptor } from '../../../../lib/userStatuses';
import { useStatusDisabledModal } from '../../../../views/admin/customUserStatus/hooks/useStatusDisabledModal';
import { useCustomStatusModalHandler } from './useCustomStatusModalHandler';

export const useStatusItems = (): GenericMenuItemProps[] => {
    // We should lift this up to somewhere else if we want to use it in other places

    userStatuses.invisibleAllowed = useSetting('Accounts_AllowInvisibleStatusOption', true);

    const queryClient = useQueryClient();

    useEffect(
        () =>
            userStatuses.watch(() => {
                queryClient.setQueryData(['user-statuses'], Array.from(userStatuses));
            }),
        [queryClient],
    );

    const { t } = useTranslation();

    const setStatus = useEndpoint('POST', '/v1/users.setStatus');
    const setStatusMutation = useMutation({
        mutationFn: async (status: UserStatusDescriptor) => {
            void setStatus({ status: status.statusType, message: userStatuses.isValidType(status.id) ? '' : status.name });
            void callbacks.run('userStatusManuallySet', status);
        },
    });

    const presenceDisabled = useSetting('Presence_broadcast_disabled', false);

    const { data: statuses } = useQuery({
        queryKey: ['user-statuses'],
        queryFn: async () => {
            await userStatuses.sync();
            return Array.from(userStatuses);
        },
        staleTime: Infinity,
        select: (statuses) =>
            statuses.map((status): GenericMenuItemProps => {
                const content = status.localizeName ? t(status.name) : status.name;
                return {
                    id: status.id,
                    status: <UserStatus status={status.statusType} />,
                    content: <MarkdownText content={content} parseEmoji={true} variant='inline' />,
                    disabled: presenceDisabled,
                    onClick: () => setStatusMutation.mutate(status),
                };
            }),
    });

    const handleStatusDisabledModal = useStatusDisabledModal();
    const handleCustomStatus = useCustomStatusModalHandler();

    return [
        ...(presenceDisabled
            ? [
                    {
                        id: 'presence-disabled',
                        content: (
                            <Box fontScale='p2'>
                                <Box mbe={4} wordBreak='break-word' style={{ whiteSpace: 'normal' }}>
                                    {t('User_status_disabled')}
                                </Box>
                                <Box is='a' color='info' onClick={handleStatusDisabledModal}>
                                    {t('Learn_more')}
                                </Box>
                            </Box>
                        ),
                    },
              ]
            : []),
        ...(statuses ?? []),
        { id: 'custom-status', icon: 'emoji', content: t('Custom_Status'), onClick: handleCustomStatus, disabled: presenceDisabled },
    ];
};