mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 02:13:00 +08:00
feat(core): notification entry for mobile (#13214)
#### PR Dependency Tree * **PR #13214** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a notification icon with a live badge displaying the notification count in the mobile home header. The badge dynamically adjusts and caps the count at "99+". * Introduced a notification menu in the mobile header, allowing users to view their notifications directly. * **Style** * Improved notification list responsiveness on mobile by making it full width. * Enhanced the appearance of the notification badge for better visibility. * Updated the app fallback UI to display skeleton placeholders for both notification and settings icons. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -7,6 +7,12 @@ export const container = style({
|
||||
width: '360px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
|
||||
selectors: {
|
||||
'&[data-mobile]': {
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const header = style({
|
||||
|
||||
@@ -90,7 +90,10 @@ export const NotificationList = () => {
|
||||
}, [notificationListService]);
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div
|
||||
className={styles.container}
|
||||
data-mobile={BUILD_CONFIG.isMobileEdition ? '' : undefined}
|
||||
>
|
||||
<div className={styles.header}>
|
||||
<span>{t['com.affine.rootAppSidebar.notifications']()}</span>
|
||||
{notifications.length > 0 && (
|
||||
|
||||
@@ -52,11 +52,23 @@ const Section = () => {
|
||||
export const AppFallback = () => {
|
||||
return (
|
||||
<SafeArea top bottom style={{ height: '100dvh', overflow: 'hidden' }}>
|
||||
{/* setting */}
|
||||
<div style={{ padding: 10, display: 'flex', justifyContent: 'end' }}>
|
||||
{/* notification and setting */}
|
||||
<div
|
||||
style={{
|
||||
padding: 10,
|
||||
paddingTop: 0,
|
||||
display: 'flex',
|
||||
justifyContent: 'end',
|
||||
gap: 10,
|
||||
}}
|
||||
>
|
||||
<Skeleton
|
||||
animation="wave"
|
||||
style={{ width: 23, height: 23, borderRadius: 4 }}
|
||||
style={{ width: 28, height: 28, borderRadius: 4 }}
|
||||
/>
|
||||
<Skeleton
|
||||
animation="wave"
|
||||
style={{ width: 28, height: 28, borderRadius: 4 }}
|
||||
/>
|
||||
</div>
|
||||
{/* workspace card */}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import {
|
||||
IconButton,
|
||||
Menu,
|
||||
SafeArea,
|
||||
startScopedViewTransition,
|
||||
} from '@affine/component';
|
||||
import { NotificationList } from '@affine/core/components/notification/list';
|
||||
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
|
||||
import { NotificationCountService } from '@affine/core/modules/notification';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { SettingsIcon } from '@blocksuite/icons/rc';
|
||||
import { useService } from '@toeverything/infra';
|
||||
import { NotificationIcon, SettingsIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import clsx from 'clsx';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
|
||||
@@ -29,6 +32,8 @@ export const HomeHeader = () => {
|
||||
const floatWorkspaceCardRef = useRef<HTMLDivElement>(null);
|
||||
const t = useI18n();
|
||||
const workbench = useService(WorkbenchService).workbench;
|
||||
const notificationCountService = useService(NotificationCountService);
|
||||
const notificationCount = useLiveData(notificationCountService.count$);
|
||||
|
||||
const navSearch = useCallback(() => {
|
||||
startScopedViewTransition(searchVTScope, () => {
|
||||
@@ -70,6 +75,21 @@ export const HomeHeader = () => {
|
||||
className={styles.floatWsSelector}
|
||||
ref={floatWorkspaceCardRef}
|
||||
/>
|
||||
<Menu items={<NotificationList />}>
|
||||
<div style={{ position: 'relative' }}>
|
||||
<NotificationIcon width={28} height={28} />
|
||||
{notificationCount > 0 && (
|
||||
<div
|
||||
className={styles.notificationBadge}
|
||||
style={{
|
||||
fontSize: notificationCount > 99 ? '8px' : '12px',
|
||||
}}
|
||||
>
|
||||
{notificationCount > 99 ? '99+' : notificationCount}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Menu>
|
||||
<IconButton
|
||||
style={{ transition: 'none' }}
|
||||
onClick={openSetting}
|
||||
|
||||
@@ -54,3 +54,17 @@ export const floatWsSelector = style({
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const notificationBadge = style({
|
||||
position: 'absolute',
|
||||
top: -2,
|
||||
right: -2,
|
||||
backgroundColor: cssVarV2('button/primary'),
|
||||
color: cssVarV2('text/pureWhite'),
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
fontSize: '12px',
|
||||
lineHeight: '16px',
|
||||
borderRadius: '50%',
|
||||
textAlign: 'center',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user