Move StatProvider above UI, increment chats unread counter from streaming events

This commit is contained in:
Alex Gleason 2022-12-07 00:45:10 -06:00
parent d811500812
commit fbd2471dc6
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
5 changed files with 74 additions and 53 deletions

View File

@ -2,7 +2,7 @@ import { getSettings } from 'soapbox/actions/settings';
import messages from 'soapbox/locales/messages'; import messages from 'soapbox/locales/messages';
import { ChatKeys, IChat, isLastMessage } from 'soapbox/queries/chats'; import { ChatKeys, IChat, isLastMessage } from 'soapbox/queries/chats';
import { queryClient } from 'soapbox/queries/client'; import { queryClient } from 'soapbox/queries/client';
import { updateChatListItem } from 'soapbox/utils/chats'; import { getUnreadChatsCount, updateChatListItem } from 'soapbox/utils/chats';
import { removePageItem } from 'soapbox/utils/queries'; import { removePageItem } from 'soapbox/utils/queries';
import { play, soundCache } from 'soapbox/utils/sounds'; import { play, soundCache } from 'soapbox/utils/sounds';
@ -27,6 +27,7 @@ import {
processTimelineUpdate, processTimelineUpdate,
} from './timelines'; } from './timelines';
import type { IStatContext } from 'soapbox/contexts/stat-context';
import type { AppDispatch, RootState } from 'soapbox/store'; import type { AppDispatch, RootState } from 'soapbox/store';
import type { APIEntity, Chat } from 'soapbox/types/entities'; import type { APIEntity, Chat } from 'soapbox/types/entities';
@ -79,11 +80,16 @@ const updateChatQuery = (chat: IChat) => {
queryClient.setQueryData<Chat>(ChatKeys.chat(chat.id), newChat as any); queryClient.setQueryData<Chat>(ChatKeys.chat(chat.id), newChat as any);
}; };
interface StreamOpts {
statContext?: IStatContext,
}
const connectTimelineStream = ( const connectTimelineStream = (
timelineId: string, timelineId: string,
path: string, path: string,
pollingRefresh: ((dispatch: AppDispatch, done?: () => void) => void) | null = null, pollingRefresh: ((dispatch: AppDispatch, done?: () => void) => void) | null = null,
accept: ((status: APIEntity) => boolean) | null = null, accept: ((status: APIEntity) => boolean) | null = null,
opts?: StreamOpts,
) => connectStream(path, pollingRefresh, (dispatch: AppDispatch, getState: () => RootState) => { ) => connectStream(path, pollingRefresh, (dispatch: AppDispatch, getState: () => RootState) => {
const locale = getLocale(getState()); const locale = getLocale(getState());
@ -145,6 +151,9 @@ const connectTimelineStream = (
if (settings.getIn(['chats', 'sound'])) { if (settings.getIn(['chats', 'sound'])) {
play(soundCache.chat); play(soundCache.chat);
} }
// Increment unread counter
opts?.statContext?.setUnreadChatsCount(getUnreadChatsCount());
} }
}); });
break; break;
@ -186,8 +195,8 @@ const refreshHomeTimelineAndNotification = (dispatch: AppDispatch, done?: () =>
dispatch(expandNotifications({}, () => dispatch(expandNotifications({}, () =>
dispatch(fetchAnnouncements(done)))))); dispatch(fetchAnnouncements(done))))));
const connectUserStream = () => const connectUserStream = (opts?: StreamOpts) =>
connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification); connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification, null, opts);
const connectCommunityStream = ({ onlyMedia }: Record<string, any> = {}) => const connectCommunityStream = ({ onlyMedia }: Record<string, any> = {}) =>
connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`); connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`);

View File

@ -17,6 +17,7 @@ import * as BuildConfig from 'soapbox/build-config';
import GdprBanner from 'soapbox/components/gdpr-banner'; import GdprBanner from 'soapbox/components/gdpr-banner';
import Helmet from 'soapbox/components/helmet'; import Helmet from 'soapbox/components/helmet';
import LoadingScreen from 'soapbox/components/loading-screen'; import LoadingScreen from 'soapbox/components/loading-screen';
import { StatProvider } from 'soapbox/contexts/stat-context';
import AuthLayout from 'soapbox/features/auth-layout'; import AuthLayout from 'soapbox/features/auth-layout';
import EmbeddedStatus from 'soapbox/features/embedded-status'; import EmbeddedStatus from 'soapbox/features/embedded-status';
import PublicLayout from 'soapbox/features/public-layout'; import PublicLayout from 'soapbox/features/public-layout';
@ -296,11 +297,13 @@ const Soapbox: React.FC = () => {
return ( return (
<Provider store={store}> <Provider store={store}>
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<StatProvider>
<SoapboxHead> <SoapboxHead>
<SoapboxLoad> <SoapboxLoad>
<SoapboxMount /> <SoapboxMount />
</SoapboxLoad> </SoapboxLoad>
</SoapboxHead> </SoapboxHead>
</StatProvider>
</QueryClientProvider> </QueryClientProvider>
</Provider> </Provider>
); );

View File

@ -26,4 +26,4 @@ const StatProvider: React.FC = ({ children }) => {
const useStatContext = (): IStatContext => useContext(StatContext); const useStatContext = (): IStatContext => useContext(StatContext);
export { StatProvider, useStatContext }; export { StatProvider, useStatContext, IStatContext };

View File

@ -24,7 +24,7 @@ import Icon from 'soapbox/components/icon';
import SidebarNavigation from 'soapbox/components/sidebar-navigation'; import SidebarNavigation from 'soapbox/components/sidebar-navigation';
import ThumbNavigation from 'soapbox/components/thumb-navigation'; import ThumbNavigation from 'soapbox/components/thumb-navigation';
import { Layout } from 'soapbox/components/ui'; import { Layout } from 'soapbox/components/ui';
import { StatProvider } from 'soapbox/contexts/stat-context'; import { useStatContext } from 'soapbox/contexts/stat-context';
import { useAppDispatch, useAppSelector, useOwnAccount, useSoapboxConfig, useFeatures, useInstance } from 'soapbox/hooks'; import { useAppDispatch, useAppSelector, useOwnAccount, useSoapboxConfig, useFeatures, useInstance } from 'soapbox/hooks';
import AdminPage from 'soapbox/pages/admin-page'; import AdminPage from 'soapbox/pages/admin-page';
import ChatsPage from 'soapbox/pages/chats-page'; import ChatsPage from 'soapbox/pages/chats-page';
@ -323,6 +323,7 @@ const UI: React.FC = ({ children }) => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { data: pendingPolicy } = usePendingPolicy(); const { data: pendingPolicy } = usePendingPolicy();
const instance = useInstance(); const instance = useInstance();
const statContext = useStatContext();
const [draggingOver, setDraggingOver] = useState<boolean>(false); const [draggingOver, setDraggingOver] = useState<boolean>(false);
@ -420,7 +421,7 @@ const UI: React.FC = ({ children }) => {
const connectStreaming = () => { const connectStreaming = () => {
if (!disconnect.current && accessToken && streamingUrl) { if (!disconnect.current && accessToken && streamingUrl) {
disconnect.current = dispatch(connectUserStream()); disconnect.current = dispatch(connectUserStream({ statContext }));
} }
}; };
@ -642,7 +643,6 @@ const UI: React.FC = ({ children }) => {
}; };
return ( return (
<StatProvider>
<HotKeys keyMap={keyMap} handlers={me ? handlers : undefined} ref={setHotkeysRef} attach={window} focused> <HotKeys keyMap={keyMap} handlers={me ? handlers : undefined} ref={setHotkeysRef} attach={window} focused>
<div ref={node} style={style}> <div ref={node} style={style}>
<BackgroundShapes /> <BackgroundShapes />
@ -693,7 +693,6 @@ const UI: React.FC = ({ children }) => {
</div> </div>
</div> </div>
</HotKeys> </HotKeys>
</StatProvider>
); );
}; };

View File

@ -1,4 +1,5 @@
import { InfiniteData } from '@tanstack/react-query'; import { InfiniteData } from '@tanstack/react-query';
import sumBy from 'lodash/sumBy';
import { normalizeChatMessage } from 'soapbox/normalizers'; import { normalizeChatMessage } from 'soapbox/normalizers';
import { ChatKeys } from 'soapbox/queries/chats'; import { ChatKeys } from 'soapbox/queries/chats';
@ -71,4 +72,13 @@ const updateChatListItem = (newChat: ChatPayload) => {
} }
}; };
export { updateChatListItem }; /** Get unread chats count. */
const getUnreadChatsCount = (): number => {
const chats = flattenPages(
queryClient.getQueryData<InfiniteData<PaginatedResult<Chat>>>(ChatKeys.chatSearch()),
);
return sumBy(chats, chat => chat.unread);
};
export { updateChatListItem, getUnreadChatsCount };