From d149b500ee3f13f63a1f831e6e0ba29a53e3e416 Mon Sep 17 00:00:00 2001 From: Mo Date: Thu, 8 Dec 2022 11:11:13 -0600 Subject: [PATCH] feat: Add current Writing Streak to Daily Notebooks (#2093) --- packages/utils/src/Domain/Utils/Utils.ts | 4 +++ .../ApplicationView/DotOrgNotice.tsx | 2 +- .../Calendar/InfiniteCalendar.tsx | 4 ++- .../Daily/DailyContentList.tsx | 20 +++++++++-- .../Components/ContentListView/Daily/Utils.ts | 34 +++++++++++++++++++ .../NoteView/SuperEditor/SuperEditor.tsx | 2 +- .../Preferences/Panes/WhatsNew/WhatsNew.tsx | 2 +- packages/web/tailwind.config.js | 1 + 8 files changed, 62 insertions(+), 7 deletions(-) diff --git a/packages/utils/src/Domain/Utils/Utils.ts b/packages/utils/src/Domain/Utils/Utils.ts index 5340c8398..edb3b867f 100644 --- a/packages/utils/src/Domain/Utils/Utils.ts +++ b/packages/utils/src/Domain/Utils/Utils.ts @@ -687,3 +687,7 @@ export function useBoolean(value: boolean | undefined, defaultValue: boolean): b export function spaceSeparatedStrings(...strings: string[]): string { return strings.join(' ') } + +export function pluralize(count: number, singular: string, plural: string): string { + return count === 1 ? singular : plural +} diff --git a/packages/web/src/javascripts/Components/ApplicationView/DotOrgNotice.tsx b/packages/web/src/javascripts/Components/ApplicationView/DotOrgNotice.tsx index a55250e15..cbb6044f9 100644 --- a/packages/web/src/javascripts/Components/ApplicationView/DotOrgNotice.tsx +++ b/packages/web/src/javascripts/Components/ApplicationView/DotOrgNotice.tsx @@ -2,7 +2,7 @@ import { FunctionComponent } from 'react' const DotOrgNotice: FunctionComponent = () => { return ( -
+
app.standardnotes.org is no longer maintained. Please switch to{' '} diff --git a/packages/web/src/javascripts/Components/ContentListView/Calendar/InfiniteCalendar.tsx b/packages/web/src/javascripts/Components/ContentListView/Calendar/InfiniteCalendar.tsx index 829f03f73..82f83a52a 100644 --- a/packages/web/src/javascripts/Components/ContentListView/Calendar/InfiniteCalendar.tsx +++ b/packages/web/src/javascripts/Components/ContentListView/Calendar/InfiniteCalendar.tsx @@ -18,6 +18,7 @@ type Props = { selectedDay?: Date selectedDayType?: 'item' | 'template' className?: string + children?: React.ReactNode } export type InfiniteCalendarInterface = { @@ -27,7 +28,7 @@ export type InfiniteCalendarInterface = { const PageSize = 2 const InfiniteCalendar = forwardRef( - ({ activities, onDateSelect, selectedDay, className }: Props, ref) => { + ({ activities, onDateSelect, selectedDay, className, children }: Props, ref) => { const [expanded, setExpanded] = useState(isMobileScreen() ? false : true) const [restoreScrollAfterExpand, setRestoreScrollAfterExpand] = useState(false) const scrollerRef = useRef(null) @@ -216,6 +217,7 @@ const InfiniteCalendar = forwardRef( })} )} + {expanded && children}
) }, diff --git a/packages/web/src/javascripts/Components/ContentListView/Daily/DailyContentList.tsx b/packages/web/src/javascripts/Components/ContentListView/Daily/DailyContentList.tsx index de14d6c6e..8b70e6056 100644 --- a/packages/web/src/javascripts/Components/ContentListView/Daily/DailyContentList.tsx +++ b/packages/web/src/javascripts/Components/ContentListView/Daily/DailyContentList.tsx @@ -7,9 +7,9 @@ import { AppPaneId } from '../../Panes/AppPaneMetadata' import { createDailyItemsWithToday, createItemsByDateMapping, insertBlanks } from './CreateDailySections' import { DailyItemsDay } from './DailyItemsDaySection' import { DailyItemCell } from './DailyItemCell' -import { SNTag } from '@standardnotes/snjs' +import { SNTag, pluralize } from '@standardnotes/snjs' import { CalendarActivity } from '../Calendar/CalendarActivity' -import { dateToDailyDayIdentifier } from './Utils' +import { dateToDailyDayIdentifier, getDailyWritingStreak } from './Utils' import InfiniteCalendar, { InfiniteCalendarInterface } from '../Calendar/InfiniteCalendar' import { InfiniteScrollerInterface, InfinteScroller } from '../InfiniteScroller/InfiniteScroller' import { LoggingDomain, log } from '@/Logging' @@ -50,6 +50,11 @@ const DailyContentList: FunctionComponent = ({ return createItemsByDateMapping(items) }, [items]) + const currentStreak = useMemo( + () => getDailyWritingStreak(todayItem, itemsByDateMapping), + [todayItem, itemsByDateMapping], + ) + useEffect(() => { setTodayItem(dailyItems.find((item) => item.isToday) as DailyItemsDay) }, [dailyItems]) @@ -182,7 +187,16 @@ const DailyContentList: FunctionComponent = ({ selectedDayType={!selectedDay ? undefined : hasItemsOnSelectedDay ? 'item' : 'template'} ref={calendarRef} className={'flex-column flex'} - /> + > + {currentStreak > 0 && ( +
+ Current Streak + + {currentStreak} {pluralize(currentStreak, 'Day', 'Days')} + +
+ )} + , +) { + if (!todayItem) { + return 0 + } + + const startDay = todayItem.date + let checkingDayOffsetFromToday = -1 + let keepLooping = true + let streak = 0 + + while (keepLooping) { + const checkingDay = addDaysToDate(startDay, checkingDayOffsetFromToday) + const items = itemsByDateMapping[dateToDailyDayIdentifier(checkingDay)] + if (!items || items?.length === 0) { + keepLooping = false + break + } + + streak++ + checkingDayOffsetFromToday-- + } + + const hasEntryForToday = itemsByDateMapping[dateToDailyDayIdentifier(todayItem.date)]?.length > 0 + + return streak + (hasEntryForToday ? 1 : 0) +} diff --git a/packages/web/src/javascripts/Components/NoteView/SuperEditor/SuperEditor.tsx b/packages/web/src/javascripts/Components/NoteView/SuperEditor/SuperEditor.tsx index c08306dc3..752628991 100644 --- a/packages/web/src/javascripts/Components/NoteView/SuperEditor/SuperEditor.tsx +++ b/packages/web/src/javascripts/Components/NoteView/SuperEditor/SuperEditor.tsx @@ -168,7 +168,7 @@ export const SuperEditor: FunctionComponent = ({ > { if (!changelog) { return ( -
+
Loading...
) diff --git a/packages/web/tailwind.config.js b/packages/web/tailwind.config.js index 6f0a6420d..68ef1e0e0 100644 --- a/packages/web/tailwind.config.js +++ b/packages/web/tailwind.config.js @@ -124,6 +124,7 @@ module.exports = { foreground: 'var(--sn-stylekit-foreground-color)', contrast: 'var(--sn-stylekit-contrast-background-color)', 'secondary-contrast': 'var(--sn-stylekit-secondary-contrast-border-color)', + 'secondary-background': 'var(--sn-stylekit-secondary-background-color)', text: 'var(--sn-stylekit-contrast-foreground-color)', border: 'var(--sn-stylekit-border-color)', 'secondary-border': 'var(--sn-stylekit-secondary-border-color)',