diff --git a/packages/frontend/core/src/desktop/pages/workspace/journals/index.css.ts b/packages/frontend/core/src/desktop/pages/workspace/journals/index.css.ts
index 615c981ad5..91cd112c39 100644
--- a/packages/frontend/core/src/desktop/pages/workspace/journals/index.css.ts
+++ b/packages/frontend/core/src/desktop/pages/workspace/journals/index.css.ts
@@ -20,12 +20,22 @@ export const body = style({
width: '100%',
height: '100%',
borderTop: `0.5px solid ${cssVarV2.layer.insideBorder.border}`,
+ selectors: {
+ '&[data-mobile]': {
+ borderTop: 'none',
+ },
+ },
});
export const content = style({
maxWidth: 944,
padding: '0px 50px',
margin: '0 auto',
+ selectors: {
+ '[data-mobile] &': {
+ padding: '0 24px',
+ },
+ },
});
export const docTitleContainer = style({
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 46ca14bcb2..c57ba39d5e 100644
--- a/packages/frontend/core/src/desktop/pages/workspace/journals/index.tsx
+++ b/packages/frontend/core/src/desktop/pages/workspace/journals/index.tsx
@@ -33,7 +33,7 @@ import {
import { AllDocSidebarTabs } from '../layouts/all-doc-sidebar-tabs';
import * as styles from './index.css';
-function getDateFromUrl(location: Location) {
+export function getDateFromUrl(location: Location) {
const searchParams = new URLSearchParams(location.search);
const date = searchParams.get('date')
? dayjs(searchParams.get('date'))
@@ -41,6 +41,49 @@ function getDateFromUrl(location: Location) {
return date.format(JOURNAL_DATE_FORMAT);
}
+export const JournalPlaceholder = ({ dateString }: { dateString: string }) => {
+ const t = useI18n();
+ const [redirecting, setRedirecting] = useState(false);
+ const workbench = useService(WorkbenchService).workbench;
+ const journalService = useService(JournalService);
+
+ const createJournal = useCallback(() => {
+ if (redirecting) return;
+ setRedirecting(true);
+ const doc = journalService.ensureJournalByDate(dateString);
+ workbench.openDoc(doc.id, {
+ replaceHistory: true,
+ at: 'active',
+ });
+ }, [dateString, journalService, redirecting, workbench]);
+
+ return (
+
+
+
+
+
+
+
+
+ {t['com.affine.journal.placeholder.title']()}
+
+
+
+
+
+ );
+};
+
const weekStyle = { maxWidth: 800, width: '100%' };
// this route page acts as a redirector to today's journal
export const JournalsPageWithConfirmation = () => {
@@ -55,19 +98,8 @@ export const JournalsPageWithConfirmation = () => {
const todayString = dayjs().format(JOURNAL_DATE_FORMAT);
const isToday = dateString === todayString;
- const [redirecting, setRedirecting] = useState(false);
const [ready, setReady] = useState(false);
- const createJournal = useCallback(() => {
- if (redirecting) return;
- setRedirecting(true);
- const doc = journalService.ensureJournalByDate(dateString);
- workbench.openDoc(doc.id, {
- replaceHistory: true,
- at: 'active',
- });
- }, [dateString, journalService, redirecting, workbench]);
-
const openJournal = useCallback(
(date: string) => {
workbench.open(`/journals?date=${date}`, { at: 'active' });
@@ -118,29 +150,7 @@ export const JournalsPageWithConfirmation = () => {
-
-
-
-
-
-
-
-
- {t['com.affine.journal.placeholder.title']()}
-
-
-
-
-
+
>
diff --git a/packages/frontend/core/src/mobile/components/app-tabs/journal.tsx b/packages/frontend/core/src/mobile/components/app-tabs/journal.tsx
index 5e65fe4f32..5abeb3a044 100644
--- a/packages/frontend/core/src/mobile/components/app-tabs/journal.tsx
+++ b/packages/frontend/core/src/mobile/components/app-tabs/journal.tsx
@@ -1,4 +1,5 @@
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 { WorkbenchService } from '@affine/core/modules/workbench';
import { TodayIcon } from '@blocksuite/icons/rc';
@@ -13,15 +14,23 @@ export const AppTabJournal = ({ tab }: AppTabCustomFCProps) => {
const location = useLiveData(workbench.location$);
const journalService = useService(JournalService);
const docDisplayMetaService = useService(DocDisplayMetaService);
+ const featureFlagService = useService(FeatureFlagService);
+ const isTwoStepJournalConfirmationEnabled = useLiveData(
+ featureFlagService.flags.enable_two_step_journal_confirmation.$
+ );
const maybeDocId = location.pathname.split('/')[1];
const journalDate = useLiveData(journalService.journalDate$(maybeDocId));
const JournalIcon = useLiveData(docDisplayMetaService.icon$(maybeDocId));
const handleOpenToday = useCallback(() => {
- const docId = journalService.ensureJournalByDate(new Date()).id;
- workbench.openDoc({ docId, fromTab: 'true' }, { at: 'active' });
- }, [journalService, workbench]);
+ if (isTwoStepJournalConfirmationEnabled) {
+ workbench.open('/journals', { at: 'active' });
+ } else {
+ const docId = journalService.ensureJournalByDate(new Date()).id;
+ workbench.openDoc({ docId, fromTab: 'true' }, { at: 'active' });
+ }
+ }, [workbench, journalService, isTwoStepJournalConfirmationEnabled]);
const Icon = journalDate ? JournalIcon : TodayIcon;
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 46f1449d85..8990f06570 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
@@ -242,6 +242,10 @@ const MobileDetailPage = ({
const workbench = useService(WorkbenchService).workbench;
const [showTitle, setShowTitle] = useState(checkShowTitle);
const title = useLiveData(docDisplayMetaService.title$(pageId));
+ const featureFlagService = useService(FeatureFlagService);
+ const isTwoStepJournalConfirmationEnabled = useLiveData(
+ featureFlagService.flags.enable_two_step_journal_confirmation.$
+ );
const canAccess = useGuard('Doc_Read', pageId);
@@ -252,13 +256,25 @@ const MobileDetailPage = ({
const handleDateChange = useCallback(
(date: string) => {
- const docId = journalService.ensureJournalByDate(date).id;
- workbench.openDoc(
- { docId, fromTab: fromTab ? 'true' : undefined },
- { replaceHistory: true }
- );
+ if (isTwoStepJournalConfirmationEnabled) {
+ const docs = journalService.journalsByDate$(date).value;
+ if (docs.length > 0) {
+ workbench.openDoc(
+ { docId: docs[0].id, fromTab: fromTab ? 'true' : undefined },
+ { replaceHistory: true }
+ );
+ } else {
+ workbench.open(`/journals?date=${date}`);
+ }
+ } else {
+ const docId = journalService.ensureJournalByDate(date).id;
+ workbench.openDoc(
+ { docId, fromTab: fromTab ? 'true' : undefined },
+ { replaceHistory: true }
+ );
+ }
},
- [fromTab, journalService, workbench]
+ [fromTab, isTwoStepJournalConfirmationEnabled, journalService, workbench]
);
useGlobalEvent(
diff --git a/packages/frontend/core/src/mobile/pages/workspace/journals.css.ts b/packages/frontend/core/src/mobile/pages/workspace/journals.css.ts
new file mode 100644
index 0000000000..8655989402
--- /dev/null
+++ b/packages/frontend/core/src/mobile/pages/workspace/journals.css.ts
@@ -0,0 +1,26 @@
+import { cssVarV2 } from '@toeverything/theme/v2';
+import { style } from '@vanilla-extract/css';
+
+export const container = style({
+ display: 'flex',
+ flexDirection: 'column',
+ height: '100dvh',
+ overflow: 'hidden',
+ backgroundColor: cssVarV2('layer/background/primary'),
+});
+
+export const header = style({
+ backgroundColor: cssVarV2('layer/background/primary'),
+});
+
+export const headerTitle = style({
+ color: cssVarV2('text/primary'),
+ fontSize: 17,
+ lineHeight: '22px',
+ fontWeight: 600,
+ letterSpacing: -0.43,
+});
+
+export const journalDatePicker = style({
+ backgroundColor: cssVarV2('layer/background/primary'),
+});
diff --git a/packages/frontend/core/src/mobile/pages/workspace/journals.tsx b/packages/frontend/core/src/mobile/pages/workspace/journals.tsx
new file mode 100644
index 0000000000..840134bd76
--- /dev/null
+++ b/packages/frontend/core/src/mobile/pages/workspace/journals.tsx
@@ -0,0 +1,107 @@
+import {
+ getDateFromUrl,
+ JournalPlaceholder,
+} from '@affine/core/desktop/pages/workspace/journals';
+import { FeatureFlagService } from '@affine/core/modules/feature-flag';
+import {
+ JOURNAL_DATE_FORMAT,
+ JournalService,
+} from '@affine/core/modules/journal';
+import { ViewService, WorkbenchService } from '@affine/core/modules/workbench';
+import { i18nTime } from '@affine/i18n';
+import { useLiveData, useService } from '@toeverything/infra';
+import { cssVarV2 } from '@toeverything/theme/v2';
+import dayjs from 'dayjs';
+import { useCallback, useEffect, useLayoutEffect, useState } from 'react';
+
+import { AppTabs, PageHeader } from '../../components';
+import { JournalDatePicker } from './detail/journal-date-picker';
+import * as styles from './journals.css';
+
+export const JournalsPageWithConfirmation = () => {
+ const journalService = useService(JournalService);
+ const workbench = useService(WorkbenchService).workbench;
+ const view = useService(ViewService).view;
+ const location = useLiveData(view.location$);
+ const dateString = getDateFromUrl(location);
+ const [ready, setReady] = useState(false);
+ const allJournalDates = useLiveData(journalService.allJournalDates$);
+
+ const handleDateChange = useCallback(
+ (date: string) => {
+ workbench.open(`/journals?date=${date}`, { at: 'active' });
+ },
+ [workbench]
+ );
+
+ useLayoutEffect(() => {
+ // only handle current route
+ if (!location.pathname.startsWith('/journals')) return;
+
+ // check if the journal is created
+ const docs = journalService.journalsByDate$(dateString).value;
+ if (docs.length === 0) {
+ setReady(true);
+ return;
+ }
+
+ // if created, redirect to the journal
+ const journal = docs[0];
+ workbench.openDoc(journal.id, { replaceHistory: true, at: 'active' });
+ }, [dateString, journalService, location.pathname, view, workbench]);
+
+ if (!ready) return null;
+
+ return (
+ <>
+
+
+ }
+ contentClassName={styles.headerTitle}
+ bottomSpacer={94}
+ >
+ {i18nTime(dayjs(dateString), { absolute: { accuracy: 'month' } })}
+
+
+
+
+ >
+ );
+};
+
+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/mobile/workbench-router.ts b/packages/frontend/core/src/mobile/workbench-router.ts
index 03de0f009c..accee5c1ce 100644
--- a/packages/frontend/core/src/mobile/workbench-router.ts
+++ b/packages/frontend/core/src/mobile/workbench-router.ts
@@ -4,6 +4,7 @@ import { Component as All } from './pages/workspace/all';
import { Component as Collection } from './pages/workspace/collection';
import { Component as CollectionDetail } from './pages/workspace/collection/detail';
import { Component as Home } from './pages/workspace/home';
+import { Component as Journals } from './pages/workspace/journals';
import { Component as Search } from './pages/workspace/search';
import { Component as Tag } from './pages/workspace/tag';
import { Component as TagDetail } from './pages/workspace/tag/detail';
@@ -41,6 +42,11 @@ export const workbenchRoutes = [
// lazy: () => import('./pages/workspace/tag/detail'),
Component: TagDetail,
},
+ {
+ path: '/journals',
+ // lazy: () => import('./pages/workspace/journals'),
+ Component: Journals,
+ },
{
path: '/trash',
lazy: () => import('./pages/workspace/trash'),