Move StatProvider above UI, increment chats unread counter from streaming events
This commit is contained in:
parent
d811500812
commit
fbd2471dc6
|
@ -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' : ''}`);
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 };
|
|
@ -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>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 };
|
Loading…
Reference in New Issue