From dd94fb34501f5ae90f4d7bd86b8d6c301ea93f1e Mon Sep 17 00:00:00 2001 From: CatsJuice Date: Fri, 6 Dec 2024 06:57:46 +0000 Subject: [PATCH] feat(mobile): add journal conflict block to the top of detail page (#9042) --- .../detail/journal-conflict-block.css.ts | 74 +++++++++++++++++++ .../detail/journal-conflict-block.tsx | 74 +++++++++++++++++++ .../detail/menu/journal-conflicts.tsx | 8 +- .../workspace/detail/mobile-detail-page.tsx | 2 + packages/frontend/i18n/src/resources/en.json | 1 + 5 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 packages/frontend/core/src/mobile/pages/workspace/detail/journal-conflict-block.css.ts create mode 100644 packages/frontend/core/src/mobile/pages/workspace/detail/journal-conflict-block.tsx diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/journal-conflict-block.css.ts b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-conflict-block.css.ts new file mode 100644 index 0000000000..c2444f54d6 --- /dev/null +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-conflict-block.css.ts @@ -0,0 +1,74 @@ +import { + bodyRegular, + subHeadlineEmphasized, +} from '@toeverything/theme/typography'; +import { cssVarV2 } from '@toeverything/theme/v2'; +import { style } from '@vanilla-extract/css'; + +export const body = style({ + paddingTop: 8, +}); +export const header = style([ + subHeadlineEmphasized, + { + height: 42, + padding: '11px 20px', + display: 'flex', + alignItems: 'center', + color: cssVarV2.button.error, + }, +]); +export const separator = style({ + width: '100%', + height: 16, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + ':before': { + content: '', + width: '100%', + height: 0, + borderTop: '0.5px solid ' + cssVarV2.layer.insideBorder.border, + }, +}); + +export const docItem = style({ + padding: '11px 20px', + height: 44, + display: 'flex', + gap: 8, + alignItems: 'center', +}); +export const icon = style({ + fontSize: 20, + color: cssVarV2.icon.primary, +}); +export const content = style({ + width: 0, + flex: 1, + display: 'flex', + alignItems: 'center', + gap: 8, +}); +export const title = style([ + bodyRegular, + { + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + }, +]); +export const duplicatedTag = style({ + fontSize: 12, + lineHeight: '20px', + height: 20, + padding: '0 8px', + borderRadius: 4, + color: cssVarV2.toast.iconState.error, + backgroundColor: cssVarV2.layer.background.error, + border: `1px solid ${cssVarV2.database.border}`, +}); +export const edit = style({ + fontSize: 20, + color: cssVarV2.icon.primary, +}); diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/journal-conflict-block.tsx b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-conflict-block.tsx new file mode 100644 index 0000000000..927e20b2b7 --- /dev/null +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-conflict-block.tsx @@ -0,0 +1,74 @@ +import { IconButton, Menu } from '@affine/component'; +import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta'; +import { JournalService } from '@affine/core/modules/journal'; +import { useI18n } from '@affine/i18n'; +import { EditIcon, TodayIcon } from '@blocksuite/icons/rc'; +import type { DocRecord } from '@toeverything/infra'; +import { DocsService, useLiveData, useService } from '@toeverything/infra'; +import { useMemo } from 'react'; + +import * as styles from './journal-conflict-block.css'; +import { ResolveConflictOperations } from './menu/journal-conflicts'; + +export const JournalConflictBlock = ({ date }: { date?: string }) => { + return date ? : null; +}; + +const JournalConflictChecker = ({ date }: { date: string }) => { + const docRecordList = useService(DocsService).list; + const journalService = useService(JournalService); + const docs = useLiveData( + useMemo(() => journalService.journalsByDate$(date), [journalService, date]) + ); + const docRecords = useLiveData( + docRecordList.docs$.map(records => + records.filter(v => { + return docs.some(doc => doc.id === v.id); + }) + ) + ); + + if (docRecords.length <= 1) return null; + + return ; +}; + +const JournalConflictList = ({ docRecords }: { docRecords: DocRecord[] }) => { + const t = useI18n(); + return ( + <> +
+
+ {t['com.affine.editor.journal-conflict.title']()} +
+ {docRecords.map(docRecord => ( + + ))} +
+
+ + ); +}; + +const ConflictItem = ({ docRecord }: { docRecord: DocRecord }) => { + const docId = docRecord.id; + const i18n = useI18n(); + const docDisplayMetaService = useService(DocDisplayMetaService); + const titleMeta = useLiveData(docDisplayMetaService.title$(docId)); + const title = i18n.t(titleMeta); + + return ( +
+ +
+
{title}
+
+ {i18n['com.affine.page-properties.property.journal-duplicated']()} +
+
+ }> + } /> + +
+ ); +}; diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/menu/journal-conflicts.tsx b/packages/frontend/core/src/mobile/pages/workspace/detail/menu/journal-conflicts.tsx index 2096b4568b..53ee5379c1 100644 --- a/packages/frontend/core/src/mobile/pages/workspace/detail/menu/journal-conflicts.tsx +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/menu/journal-conflicts.tsx @@ -22,7 +22,11 @@ import { type MouseEvent, useCallback, useMemo } from 'react'; import * as styles from './journal-conflicts.css'; -const ResolveConflictOperations = ({ docRecord }: { docRecord: DocRecord }) => { +export const ResolveConflictOperations = ({ + docRecord, +}: { + docRecord: DocRecord; +}) => { const t = useI18n(); const journalService = useService(JournalService); const { openConfirmModal } = useConfirmModal(); @@ -106,7 +110,7 @@ const DocItem = ({ docRecord }: { docRecord: DocRecord }) => { ); }; -const ConflictList = ({ docRecords }: { docRecords: DocRecord[] }) => { +export const ConflictList = ({ docRecords }: { docRecords: DocRecord[] }) => { return docRecords.map(docRecord => ( )); diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx b/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx index 1a31acfe5f..c56b25501c 100644 --- a/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx @@ -45,6 +45,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { useParams } from 'react-router-dom'; import { AppTabs } from '../../../components'; +import { JournalConflictBlock } from './journal-conflict-block'; import { JournalDatePicker } from './journal-date-picker'; import * as styles from './mobile-detail-page.css'; import { PageHeaderMenuButton } from './page-header-more-button'; @@ -288,6 +289,7 @@ const MobileDetailPage = ({ : title} + diff --git a/packages/frontend/i18n/src/resources/en.json b/packages/frontend/i18n/src/resources/en.json index 5907838f9f..b00d4bd04e 100644 --- a/packages/frontend/i18n/src/resources/en.json +++ b/packages/frontend/i18n/src/resources/en.json @@ -1491,6 +1491,7 @@ "com.affine.attachment.preview.error.title": "Unable to preview this file", "com.affine.attachment.preview.error.subtitle": "file type not supported.", "com.affine.pdf.page.render.error": "Failed to render page.", + "com.affine.editor.journal-conflict.title": "Duplicate Entries in Today's Journal", "com.affine.editor.at-menu.link-to-doc": "Link to Doc", "com.affine.editor.at-menu.new-doc": "New Doc", "com.affine.editor.at-menu.create-doc": "Create \"{{name}}\" Doc",