From ea21de8311a2b7252b8ebed18e0eb57dd4dce958 Mon Sep 17 00:00:00 2001 From: Cats Juice Date: Thu, 17 Jul 2025 15:03:32 +0800 Subject: [PATCH] feat(core): add flag for two-step journal conformation (#13246) ## Summary by CodeRabbit * **New Features** * Introduced a feature flag to control a two-step journal confirmation process. * Users may now experience either an immediate journal opening or a confirmation step before journal creation, depending on the feature flag status. * **Chores** * Added a new feature flag for two-step journal confirmation, configurable in canary builds. --- .../journal/date-picker.tsx | 21 +++++++--- .../detail-page/tabs/journal/index.tsx | 21 +++++++--- .../pages/workspace/journals/index.tsx | 40 ++++++++++++++++++- .../core/src/modules/feature-flag/constant.ts | 8 ++++ 4 files changed, 78 insertions(+), 12 deletions(-) diff --git a/packages/frontend/core/src/blocksuite/block-suite-header/journal/date-picker.tsx b/packages/frontend/core/src/blocksuite/block-suite-header/journal/date-picker.tsx index 99d5b91ae..50908f2af 100644 --- a/packages/frontend/core/src/blocksuite/block-suite-header/journal/date-picker.tsx +++ b/packages/frontend/core/src/blocksuite/block-suite-header/journal/date-picker.tsx @@ -1,5 +1,6 @@ import type { WeekDatePickerHandle } from '@affine/component'; import { WeekDatePicker } from '@affine/component'; +import { FeatureFlagService } from '@affine/core/modules/feature-flag'; import { JOURNAL_DATE_FORMAT, JournalService, @@ -25,6 +26,11 @@ export const JournalWeekDatePicker = ({ page }: JournalWeekDatePickerProps) => { ); const workbench = useService(WorkbenchService).workbench; + const featureFlagService = useService(FeatureFlagService); + const isTwoStepJournalConfirmationEnabled = useLiveData( + featureFlagService.flags.enable_two_step_journal_confirmation.$ + ); + useEffect(() => { if (!journalDate) return; setDate(journalDate.format(JOURNAL_DATE_FORMAT)); @@ -33,14 +39,19 @@ export const JournalWeekDatePicker = ({ page }: JournalWeekDatePickerProps) => { const openJournal = useCallback( (date: string) => { - const docs = journalService.journalsByDate$(date).value; - if (docs.length > 0) { - workbench.openDoc(docs[0].id, { at: 'active' }); + if (isTwoStepJournalConfirmationEnabled) { + const docs = journalService.journalsByDate$(date).value; + if (docs.length > 0) { + workbench.openDoc(docs[0].id, { at: 'active' }); + } else { + workbench.open(`/journals?date=${date}`, { at: 'active' }); + } } else { - workbench.open(`/journals?date=${date}`, { at: 'active' }); + const doc = journalService.ensureJournalByDate(date); + workbench.openDoc(doc.id, { at: 'active' }); } }, - [journalService, workbench] + [isTwoStepJournalConfirmationEnabled, journalService, workbench] ); return ( diff --git a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/journal/index.tsx b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/journal/index.tsx index 4bfbc949a..8134b0043 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/journal/index.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/journal/index.tsx @@ -16,6 +16,7 @@ import { DocsService, } from '@affine/core/modules/doc'; import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta'; +import { FeatureFlagService } from '@affine/core/modules/feature-flag'; import { JournalService } from '@affine/core/modules/journal'; import { WorkbenchLink, @@ -113,16 +114,26 @@ export const EditorJournalPanel = () => { const journalDate = journalDateStr ? dayjs(journalDateStr) : null; const isJournal = !!journalDate; + const featureFlagService = useService(FeatureFlagService); + const isTwoStepJournalConfirmationEnabled = useLiveData( + featureFlagService.flags.enable_two_step_journal_confirmation.$ + ); + const openJournal = useCallback( (date: string) => { - const docs = journalService.journalsByDate$(date).value; - if (docs.length > 0) { - workbench.openDoc(docs[0].id, { at: 'active' }); + if (isTwoStepJournalConfirmationEnabled) { + const docs = journalService.journalsByDate$(date).value; + if (docs.length > 0) { + workbench.openDoc(docs[0].id, { at: 'active' }); + } else { + workbench.open(`/journals?date=${date}`, { at: 'active' }); + } } else { - workbench.open(`/journals?date=${date}`, { at: 'active' }); + const doc = journalService.ensureJournalByDate(date); + workbench.openDoc(doc.id, { at: 'active' }); } }, - [journalService, workbench] + [isTwoStepJournalConfirmationEnabled, journalService, workbench] ); const onDateSelect = useCallback( diff --git a/packages/frontend/core/src/desktop/pages/workspace/journals/index.tsx b/packages/frontend/core/src/desktop/pages/workspace/journals/index.tsx index ffbbac030..46ca14bcb 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/journals/index.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/journals/index.tsx @@ -4,6 +4,7 @@ import { type WeekDatePickerHandle, } from '@affine/component'; import { BlocksuiteEditorJournalDocTitleUI } from '@affine/core/blocksuite/block-suite-editor/journal-doc-title'; +import { FeatureFlagService } from '@affine/core/modules/feature-flag'; import { JOURNAL_DATE_FORMAT, JournalService, @@ -21,7 +22,13 @@ import { TodayIcon } from '@blocksuite/icons/rc'; import { useLiveData, useService } from '@toeverything/infra'; import dayjs from 'dayjs'; import type { Location } from 'history'; -import { useCallback, useLayoutEffect, useRef, useState } from 'react'; +import { + useCallback, + useEffect, + useLayoutEffect, + useRef, + useState, +} from 'react'; import { AllDocSidebarTabs } from '../layouts/all-doc-sidebar-tabs'; import * as styles from './index.css'; @@ -36,7 +43,7 @@ function getDateFromUrl(location: Location) { const weekStyle = { maxWidth: 800, width: '100%' }; // this route page acts as a redirector to today's journal -export const Component = () => { +export const JournalsPageWithConfirmation = () => { const handleRef = useRef(null); const t = useI18n(); @@ -139,3 +146,32 @@ export const Component = () => { ); }; + +export const JournalsPageWithoutConfirmation = () => { + const journalService = useService(JournalService); + const workbench = useService(WorkbenchService).workbench; + + useEffect(() => { + const today = dayjs().format(JOURNAL_DATE_FORMAT); + const doc = journalService.ensureJournalByDate(today); + workbench.openDoc(doc.id, { + replaceHistory: true, + at: 'active', + }); + }, [journalService, workbench]); + + return null; +}; + +export const Component = () => { + const featureFlagService = useService(FeatureFlagService); + const isTwoStepJournalConfirmationEnabled = useLiveData( + featureFlagService.flags.enable_two_step_journal_confirmation.$ + ); + + if (isTwoStepJournalConfirmationEnabled) { + return ; + } + + return ; +}; diff --git a/packages/frontend/core/src/modules/feature-flag/constant.ts b/packages/frontend/core/src/modules/feature-flag/constant.ts index 0efa9c873..7b3e18fdc 100644 --- a/packages/frontend/core/src/modules/feature-flag/constant.ts +++ b/packages/frontend/core/src/modules/feature-flag/constant.ts @@ -264,6 +264,14 @@ export const AFFINE_FLAGS = { configurable: isCanaryBuild, defaultState: false, }, + enable_two_step_journal_confirmation: { + category: 'affine', + displayName: 'Enable Two Step Journal Confirmation', + description: + 'When enabled, you must confirm the journal before you can create a new journal.', + configurable: isCanaryBuild, + defaultState: isCanaryBuild, + }, } satisfies { [key in string]: FlagInfo }; // oxlint-disable-next-line no-redeclare