🐛 fix: gate inbox unread count by login state (#15724)

This commit is contained in:
YuTengjing
2026-06-12 23:32:14 +08:00
committed by GitHub
parent 29974d3ab9
commit ce81ea44bf
3 changed files with 103 additions and 12 deletions
@@ -7,23 +7,14 @@ import { memo, useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { DESKTOP_HEADER_ICON_SMALL_SIZE } from '@/const/layoutTokens';
import { useClientDataSWR } from '@/libs/swr';
import { notificationService } from '@/services/notification';
import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
import InboxDrawer from './InboxDrawer';
import { UNREAD_COUNT_KEY } from './InboxDrawer/constants';
import { useInboxUnreadCount } from './useInboxUnreadCount';
const InboxButton = memo(() => {
const { t } = useTranslation('notification');
const [open, setOpen] = useState(false);
const enableBusinessFeatures = useServerConfigStore(serverConfigSelectors.enableBusinessFeatures);
const { data: unreadCount = 0 } = useClientDataSWR<number>(
enableBusinessFeatures ? UNREAD_COUNT_KEY : null,
() => notificationService.getUnreadCount(),
{ refreshInterval: 10_000 },
);
const { enabled, unreadCount } = useInboxUnreadCount();
const handleToggle = useCallback(() => {
setOpen((prev) => !prev);
@@ -33,7 +24,7 @@ const InboxButton = memo(() => {
setOpen(false);
}, []);
if (!enableBusinessFeatures) return null;
if (!enabled) return null;
return (
<>
@@ -0,0 +1,77 @@
import { renderHook } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { UNREAD_COUNT_KEY } from './InboxDrawer/constants';
import { INBOX_UNREAD_COUNT_REFRESH_INTERVAL, useInboxUnreadCount } from './useInboxUnreadCount';
const mocks = vi.hoisted(() => ({
state: {
enableBusinessFeatures: true,
isSignedIn: false,
},
useClientDataSWR: vi.fn(() => ({ data: undefined })),
}));
vi.mock('@/libs/swr', () => ({
useClientDataSWR: mocks.useClientDataSWR,
}));
vi.mock('@/services/notification', () => ({
notificationService: {
getUnreadCount: vi.fn(),
},
}));
vi.mock('@/store/serverConfig', () => ({
serverConfigSelectors: {
enableBusinessFeatures: (state: { serverConfig: { enableBusinessFeatures: boolean } }) =>
state.serverConfig.enableBusinessFeatures,
},
useServerConfigStore: (
selector: (state: { serverConfig: { enableBusinessFeatures: boolean } }) => boolean,
) => selector({ serverConfig: { enableBusinessFeatures: mocks.state.enableBusinessFeatures } }),
}));
vi.mock('@/store/user', () => ({
useUserStore: (selector: (state: { isSignedIn: boolean }) => boolean) =>
selector({ isSignedIn: mocks.state.isSignedIn }),
}));
vi.mock('@/store/user/selectors', () => ({
authSelectors: {
isLogin: (state: { isSignedIn: boolean }) => state.isSignedIn,
},
}));
beforeEach(() => {
mocks.state.enableBusinessFeatures = true;
mocks.state.isSignedIn = false;
mocks.useClientDataSWR.mockClear();
mocks.useClientDataSWR.mockReturnValue({ data: undefined });
});
describe('useInboxUnreadCount', () => {
it('does not request unread count before login', () => {
const { result } = renderHook(() => useInboxUnreadCount());
expect(result.current.enabled).toBe(false);
expect(mocks.useClientDataSWR).toHaveBeenCalledWith(null, expect.any(Function), {
refreshInterval: INBOX_UNREAD_COUNT_REFRESH_INTERVAL,
});
});
it('requests unread count when business features are enabled and user is logged in', () => {
mocks.state.isSignedIn = true;
const { result } = renderHook(() => useInboxUnreadCount());
expect(result.current.enabled).toBe(true);
expect(mocks.useClientDataSWR).toHaveBeenCalledWith(UNREAD_COUNT_KEY, expect.any(Function), {
refreshInterval: INBOX_UNREAD_COUNT_REFRESH_INTERVAL,
});
});
it('keeps unread count polling on the same 10 second cadence', () => {
expect(INBOX_UNREAD_COUNT_REFRESH_INTERVAL).toBe(10_000);
});
});
@@ -0,0 +1,23 @@
import { useClientDataSWR } from '@/libs/swr';
import { notificationService } from '@/services/notification';
import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
import { useUserStore } from '@/store/user';
import { authSelectors } from '@/store/user/selectors';
import { UNREAD_COUNT_KEY } from './InboxDrawer/constants';
export const INBOX_UNREAD_COUNT_REFRESH_INTERVAL = 10_000;
export const useInboxUnreadCount = () => {
const enableBusinessFeatures = useServerConfigStore(serverConfigSelectors.enableBusinessFeatures);
const isLogin = useUserStore(authSelectors.isLogin);
const enabled = enableBusinessFeatures && isLogin === true;
const { data: unreadCount = 0 } = useClientDataSWR<number>(
enabled ? UNREAD_COUNT_KEY : null,
() => notificationService.getUnreadCount(),
{ refreshInterval: INBOX_UNREAD_COUNT_REFRESH_INTERVAL },
);
return { enabled, unreadCount };
};