feat: 设定静音状态下群组小红点为灰色

pull/70/head
moonrailgun 2 years ago
parent 3635653798
commit 0c5e5c3cf4

@ -0,0 +1,53 @@
import { GroupPanelType } from '../../model/group';
import { useGroupInfo } from '../../redux/hooks/useGroup';
import { useUserNotifyMute } from './useUserSettings';
import _zip from 'lodash/zip';
import { useUnread } from '../../redux/hooks/useUnread';
/**
*
* @param groupId id
*/
export function useGroupUnreadState(
groupId: string
): 'none' | 'muted' | 'unread' {
const group = useGroupInfo(groupId);
const groupTextPanelIds = (group?.panels ?? [])
.filter((panel) => panel.type === GroupPanelType.TEXT)
.map((p) => p.id);
const { mutedList } = useUserNotifyMute();
const unreadList = useUnread(groupTextPanelIds);
const unreadEntires = _zip(groupTextPanelIds, unreadList);
let hasUnread = false;
let hasUnmutedUnread = false;
const isGroupMuted = mutedList.includes(groupId); // 群组自身是否被禁用
for (const [panelId, isUnread] of unreadEntires) {
if (isUnread === true) {
hasUnread = true;
if (isGroupMuted) {
// 如果群组已经被静音,则无需做后续判断,跳出循环
break;
}
if (panelId && !mutedList.includes(panelId)) {
// 如果面板没有并禁言,且有未读消息
hasUnmutedUnread = true;
break;
}
}
}
if (hasUnread) {
if (hasUnmutedUnread) {
return 'unread'; // 有未读消息,显示红点
} else {
return 'muted'; // 有未读消息,但是未读消息均被静音,显示灰点
}
} else {
return 'none'; // 没有未读消息,不显示任何状态
}
}

@ -54,6 +54,7 @@ export { useLanguage } from './i18n/language';
// hooks
export { createUseStorageState } from './hooks/factory/createUseStorageState';
export { useAvailableServices } from './hooks/model/useAvailableServices';
export { useGroupUnreadState } from './hooks/model/useGroupUnreadState';
export { useMessageNotifyEventFilter } from './hooks/model/useMessageNotifyEventFilter';
export { useUserInfoList } from './hooks/model/useUserInfoList';
export { useUsernames } from './hooks/model/useUsernames';
@ -189,7 +190,6 @@ export {
useGroupPanels,
useGroupPanelInfo,
useIsGroupOwner,
useGroupUnread,
useGroupTextPanelUnread,
} from './redux/hooks/useGroup';
export { useGroupAck } from './redux/hooks/useGroupAck';

@ -1,6 +1,6 @@
import { useMemo } from 'react';
import { useUserInfoList } from '../..';
import { GroupInfo, GroupPanel, GroupPanelType } from '../../model/group';
import type { GroupInfo, GroupPanel } from '../../model/group';
import type { UserBaseInfo } from '../../model/user';
import { isValidStr } from '../../utils/string-helper';
import { useAppSelector } from './useAppSelector';
@ -75,21 +75,6 @@ export function useIsGroupOwner(groupId: string, userId?: string): boolean {
}
}
/**
*
* @param groupId id
*/
export function useGroupUnread(groupId: string): boolean {
const group = useGroupInfo(groupId);
const groupTextPanelIds = (group?.panels ?? [])
.filter((panel) => panel.type === GroupPanelType.TEXT)
.map((p) => p.id);
const unread = useUnread(groupTextPanelIds);
return unread.some((u) => u === true);
}
/**
*
* @param textPanelId id

@ -8,7 +8,7 @@ import {
t,
useAppSelector,
useGroupAck,
useGroupUnread,
useGroupUnreadState,
} from 'tailchat-shared';
import { NavbarNavItem } from './NavItem';
import { Dropdown } from 'antd';
@ -18,7 +18,7 @@ import { Dropdown } from 'antd';
*/
const GroupNavItem: React.FC<{ group: GroupInfo }> = React.memo(({ group }) => {
const groupId = group._id;
const hasUnread = useGroupUnread(groupId);
const unreadState = useGroupUnreadState(groupId);
const { markGroupAllAck } = useGroupAck(groupId);
const menu = {
@ -42,7 +42,10 @@ const GroupNavItem: React.FC<{ group: GroupInfo }> = React.memo(({ group }) => {
name={group.name}
to={`/main/group/${group._id}`}
showPill={true}
badge={hasUnread}
badge={['muted', 'unread'].includes(unreadState)}
badgeProps={{
status: unreadState === 'unread' ? 'error' : 'default',
}}
>
<Avatar
shape="square"

@ -8,6 +8,7 @@ import { NavbarNavItem } from './NavItem';
*/
export const InboxNav: React.FC = React.memo(() => {
const inbox = useInboxList();
const unreadList = inbox.filter((i) => !i.readed);
return (
<NavbarNavItem
@ -15,7 +16,10 @@ export const InboxNav: React.FC = React.memo(() => {
name={t('收件箱')}
to={'/main/inbox'}
showPill={true}
badge={inbox.filter((i) => !i.readed).length}
badge={unreadList.length > 0}
badgeProps={{
count: unreadList.length,
}}
data-testid="inbox"
>
<Icon className="text-3xl text-white" icon="mdi:inbox-arrow-down" />

@ -1,4 +1,4 @@
import { Tooltip, Badge } from 'antd';
import { Tooltip, Badge, BadgeProps } from 'antd';
import type { ClassValue } from 'clsx';
import clsx from 'clsx';
import React, { PropsWithChildren } from 'react';
@ -11,7 +11,8 @@ export const NavbarNavItem: React.FC<
className?: ClassValue;
to?: string;
showPill?: boolean;
badge?: boolean | number;
badge?: boolean;
badgeProps?: BadgeProps;
onClick?: () => void;
['data-testid']?: string;
}>
@ -67,11 +68,7 @@ export const NavbarNavItem: React.FC<
{inner}
<div className="absolute right-0 bottom-0">
{badge === true ? (
<Badge status="error" />
) : (
<Badge size="small" count={Number(badge) || 0} />
)}
{badge === true && <Badge status="error" {...props.badgeProps} />}
</div>
</div>
);

Loading…
Cancel
Save