Fix unread ounter in Middle Header and icon badges

This commit is contained in:
Alexander Zinchuk 2021-08-17 02:43:20 +03:00
parent 559086c4e2
commit 876e24c20c
3 changed files with 22 additions and 50 deletions

View File

@ -1,17 +1,17 @@
import React, { import React, {
FC, useCallback, useMemo, memo, useEffect, useRef, useState, FC, useCallback, useMemo, memo, useEffect, useRef, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getGlobal, withGlobal } from '../../lib/teact/teactn';
import cycleRestrict from '../../util/cycleRestrict'; import cycleRestrict from '../../util/cycleRestrict';
import { GlobalActions, MessageListType } from '../../global/types'; import { GlobalActions, MessageListType } from '../../global/types';
import { import {
ApiMessage, ApiMessage,
ApiChat, ApiChat,
ApiUser,
ApiTypingStatus, ApiTypingStatus,
MAIN_THREAD_ID, ApiUser, MAIN_THREAD_ID,
} from '../../api/types'; } from '../../api/types';
import { NotifyException, NotifySettings } from '../../types';
import { import {
MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN, MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN,
@ -24,11 +24,9 @@ import {
import { IS_SINGLE_COLUMN_LAYOUT, IS_TABLET_COLUMN_LAYOUT } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT, IS_TABLET_COLUMN_LAYOUT } from '../../util/environment';
import { import {
isChatPrivate, isChatPrivate,
isChatArchived,
getMessageKey, getMessageKey,
getChatTitle, getChatTitle,
getSenderTitle, getSenderTitle,
selectIsChatMuted,
} from '../../modules/helpers'; } from '../../modules/helpers';
import { import {
selectChat, selectChat,
@ -44,8 +42,7 @@ import {
selectScheduledIds, selectScheduledIds,
selectIsInSelectMode, selectIsInSelectMode,
selectIsChatWithBot, selectIsChatWithBot,
selectNotifySettings, selectCountNotMutedUnread,
selectNotifyExceptions,
} from '../../modules/selectors'; } from '../../modules/selectors';
import useEnsureMessage from '../../hooks/useEnsureMessage'; import useEnsureMessage from '../../hooks/useEnsureMessage';
import useWindowSize from '../../hooks/useWindowSize'; import useWindowSize from '../../hooks/useWindowSize';
@ -91,8 +88,6 @@ type StateProps = {
isChatWithSelf?: boolean; isChatWithSelf?: boolean;
isChatWithBot?: boolean; isChatWithBot?: boolean;
lastSyncTime?: number; lastSyncTime?: number;
notifySettings: NotifySettings;
notifyExceptions?: Record<number, NotifyException>;
shouldSkipHistoryAnimations?: boolean; shouldSkipHistoryAnimations?: boolean;
currentTransitionKey: number; currentTransitionKey: number;
}; };
@ -122,8 +117,6 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
isChatWithSelf, isChatWithSelf,
isChatWithBot, isChatWithBot,
lastSyncTime, lastSyncTime,
notifySettings,
notifyExceptions,
shouldSkipHistoryAnimations, shouldSkipHistoryAnimations,
currentTransitionKey, currentTransitionKey,
openChatWithInfo, openChatWithInfo,
@ -221,32 +214,8 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
return undefined; return undefined;
} }
let isActive = false; return selectCountNotMutedUnread(getGlobal()) || undefined;
}, [isLeftColumnHideable, chatsById]);
const totalCount = Object.values(chatsById).reduce((total, currentChat) => {
if (isChatArchived(currentChat)) {
return total;
}
const count = currentChat.unreadCount || 0;
if (
count && (!selectIsChatMuted(currentChat, notifySettings, notifyExceptions) || currentChat.unreadMentionsCount)
) {
isActive = true;
}
return total + count;
}, 0);
if (!totalCount) {
return undefined;
}
return {
isActive,
totalCount,
};
}, [isLeftColumnHideable, chatsById, notifySettings, notifyExceptions]);
const canToolsCollideWithChatInfo = ( const canToolsCollideWithChatInfo = (
windowWidth >= MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN windowWidth >= MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN
@ -340,7 +309,7 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
function renderMainThreadInfo() { function renderMainThreadInfo() {
return ( return (
<> <>
{(isLeftColumnHideable || currentTransitionKey > 0) && renderBackButton(shouldShowCloseButton, unreadCount)} {(isLeftColumnHideable || currentTransitionKey > 0) && renderBackButton(shouldShowCloseButton, true)}
<div className="chat-info-wrapper" onClick={handleHeaderClick}> <div className="chat-info-wrapper" onClick={handleHeaderClick}>
{isChatPrivate(chatId) ? ( {isChatPrivate(chatId) ? (
<PrivateChatInfo <PrivateChatInfo
@ -366,7 +335,7 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
); );
} }
function renderBackButton(asClose = false, unreadCountInfo?: typeof unreadCount) { function renderBackButton(asClose = false, withUnreadCount = false) {
return ( return (
<div className="back-button"> <div className="back-button">
<Button <Button
@ -378,9 +347,9 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
> >
<div className={buildClassName('animated-close-icon', !asClose && 'state-back')} /> <div className={buildClassName('animated-close-icon', !asClose && 'state-back')} />
</Button> </Button>
{unreadCountInfo && ( {withUnreadCount && unreadCount && (
<div className={`unread-count ${unreadCountInfo.isActive ? 'active' : ''}`}> <div className="unread-count active">
{formatIntegerCompact(unreadCountInfo.totalCount)} {formatIntegerCompact(unreadCount)}
</div> </div>
)} )}
</div> </div>
@ -466,8 +435,6 @@ export default memo(withGlobal<OwnProps>(
isChatWithSelf: selectIsChatWithSelf(global, chatId), isChatWithSelf: selectIsChatWithSelf(global, chatId),
isChatWithBot: chat && selectIsChatWithBot(global, chat), isChatWithBot: chat && selectIsChatWithBot(global, chat),
lastSyncTime, lastSyncTime,
notifySettings: selectNotifySettings(global),
notifyExceptions: selectNotifyExceptions(global),
shouldSkipHistoryAnimations, shouldSkipHistoryAnimations,
currentTransitionKey: Math.max(0, global.messages.messageLists.length - 1), currentTransitionKey: Math.max(0, global.messages.messageLists.length - 1),
}; };

View File

@ -19,7 +19,8 @@ import {
selectIsChatListed, selectIsChatListed,
selectChatListType, selectChatListType,
selectCurrentMessageList, selectCurrentMessageList,
selectCountNotMutedUnread, selectNotifySettings, selectCountNotMutedUnread,
selectNotifySettings,
} from '../../selectors'; } from '../../selectors';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
@ -40,8 +41,7 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
const newGlobal = updateChat(global, update.id, update.chat, update.newProfilePhoto); const newGlobal = updateChat(global, update.id, update.chat, update.newProfilePhoto);
setGlobal(newGlobal); setGlobal(newGlobal);
const unreadCount = selectCountNotMutedUnread(newGlobal); runThrottledForUpdateAppBadge(() => updateAppBadge(selectCountNotMutedUnread(getGlobal())));
runThrottledForUpdateAppBadge(() => updateAppBadge(unreadCount));
break; break;
} }
@ -133,8 +133,7 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
})); }));
} }
const unreadCount = selectCountNotMutedUnread(getGlobal()); updateAppBadge(selectCountNotMutedUnread(getGlobal()));
updateAppBadge(unreadCount);
const { hasWebNotifications } = selectNotifySettings(global); const { hasWebNotifications } = selectNotifySettings(global);
if (hasWebNotifications) { if (hasWebNotifications) {

View File

@ -147,6 +147,7 @@ export function selectChatByUsername(global: GlobalState, username: string) {
); );
} }
// Slow, not to be used in `withGlobal`
export function selectCountNotMutedUnread(global: GlobalState) { export function selectCountNotMutedUnread(global: GlobalState) {
const activeChatIds = global.chats.listIds.active; const activeChatIds = global.chats.listIds.active;
if (!activeChatIds) { if (!activeChatIds) {
@ -154,6 +155,8 @@ export function selectCountNotMutedUnread(global: GlobalState) {
} }
const chats = global.chats.byId; const chats = global.chats.byId;
const notifySettings = selectNotifySettings(global);
const notifyExceptions = selectNotifyExceptions(global);
return activeChatIds.reduce((acc, chatId) => { return activeChatIds.reduce((acc, chatId) => {
const chat = chats[chatId]; const chat = chats[chatId];
@ -161,7 +164,10 @@ export function selectCountNotMutedUnread(global: GlobalState) {
if ( if (
chat chat
&& chat.unreadCount && chat.unreadCount
&& !selectIsChatMuted(chat, selectNotifySettings(global), selectNotifyExceptions(global)) && chat.isListed
&& !chat.isNotJoined
&& !chat.isRestricted
&& (chat.unreadMentionsCount || !selectIsChatMuted(chat, notifySettings, notifyExceptions))
) { ) {
return acc + chat.unreadCount; return acc + chat.unreadCount;
} }