diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/constants.ts b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/constants.ts index cefc5df7af..c4822ea340 100644 --- a/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/constants.ts +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/constants.ts @@ -6,6 +6,7 @@ export const MONTH_VIEW_HEIGHT = TOTAL_WEEKS * CELL_HEIGHT + (TOTAL_WEEKS - 1) * ROWS_GAP; export const WEEK_VIEW_HEIGHT = CELL_HEIGHT; -export const HORIZONTAL_SWIPE_THRESHOLD = 4 * CELL_HEIGHT; +export const HORIZONTAL_SWIPE_THRESHOLD = 2 * CELL_HEIGHT; +export const SCROLL_DOWN_TO_FOLD_THRESHOLD = 30; export const DATE_FORMAT = 'YYYY-MM-DD'; diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/index.tsx b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/index.tsx index 131339abc0..b8fe2a613a 100644 --- a/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/index.tsx +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/index.tsx @@ -1,9 +1,10 @@ -import { useCallback, useEffect, useState } from 'react'; +import { type HTMLAttributes, useCallback, useEffect, useState } from 'react'; import { JournalDatePickerContext } from './context'; import { ResizeViewport } from './viewport'; -export interface JournalDatePickerProps { +export interface JournalDatePickerProps + extends Omit, 'onChange'> { date: string; onChange: (date: string) => void; withDotDates: Set; @@ -12,6 +13,7 @@ export const JournalDatePicker = ({ date: selected, onChange, withDotDates, + ...attrs }: JournalDatePickerProps) => { const [cursor, setCursor] = useState(selected); @@ -39,7 +41,7 @@ export const JournalDatePicker = ({ withDotDates, }} > - + ); }; diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/viewport.tsx b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/viewport.tsx index 7a0fb7f4ca..061292e198 100644 --- a/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/viewport.tsx +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/journal-date-picker/viewport.tsx @@ -1,11 +1,21 @@ +import { useGlobalEvent } from '@affine/core/mobile/hooks/use-global-events'; import anime from 'animejs'; +import clsx from 'clsx'; import dayjs from 'dayjs'; -import { useCallback, useContext, useEffect, useRef, useState } from 'react'; +import { + type HTMLAttributes, + useCallback, + useContext, + useEffect, + useRef, + useState, +} from 'react'; import { CELL_HEIGHT, DATE_FORMAT, MONTH_VIEW_HEIGHT, + SCROLL_DOWN_TO_FOLD_THRESHOLD, WEEK_VIEW_HEIGHT, } from './constants'; import { JournalDatePickerContext } from './context'; @@ -14,7 +24,10 @@ import { SwipeHelper } from './swipe-helper'; import * as styles from './viewport.css'; import { WeekHeader, WeekRowSwipe } from './week'; -export const ResizeViewport = () => { +export const ResizeViewport = ({ + className, + ...attrs +}: HTMLAttributes) => { const { selected } = useContext(JournalDatePickerContext); const draggableRef = useRef(null); const viewportRef = useRef(null); @@ -97,8 +110,29 @@ export const ResizeViewport = () => { }); }, [handleToggleModeWithAnimation, mode]); + // auto fold when scroll down + const prevScrollYRef = useRef(window.scrollY); + useGlobalEvent( + 'scroll', + useCallback(() => { + if (mode === 'week') return; + if (isAnimating) return; + const offset = window.scrollY - prevScrollYRef.current; + if (offset >= SCROLL_DOWN_TO_FOLD_THRESHOLD) { + prevScrollYRef.current = window.scrollY; + handleToggleModeWithAnimation('week', 0); + } + }, [handleToggleModeWithAnimation, isAnimating, mode]) + ); + useGlobalEvent( + 'scrollend', + useCallback(() => { + prevScrollYRef.current = window.scrollY; + }, []) + ); + return ( -
+
{mode === 'month' || isDragging || isAnimating ? ( diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.css.ts b/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.css.ts index 9cf9b651ac..5a5f60330a 100644 --- a/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.css.ts +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.css.ts @@ -93,3 +93,15 @@ export const journalIconButton = style({ right: 12, display: 'flex', }); + +export const journalDatePickerSticky = style({ + background: cssVarV2('layer/background/primary'), + position: 'sticky', + zIndex: 1, + top: 56, + selectors: { + '&[data-standalone]': { + top: 'calc(44px + env(safe-area-inset-top, 12px))', + }, + }, +}); 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 01ce08d1a6..a315218eab 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 @@ -262,6 +262,12 @@ const MobileDetailPage = ({ date={date} onChange={handleDateChange} withDotDates={allJournalDates} + className={styles.journalDatePickerSticky} + data-standalone={ + environment.isPwa || BUILD_CONFIG.isAndroid || BUILD_CONFIG.isIOS + ? '' + : undefined + } /> ) : null}