From f559442a6726444f338a43e51d7a872f19bce701 Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Sat, 17 Dec 2022 00:35:25 +0530 Subject: [PATCH] feat: Added "Whats New" indicator to Preferences button (#2107) --- .../src/Changelog/ChangelogService.ts | 17 +++++++++-- .../Changelog/ChangelogServiceInterface.ts | 3 ++ .../javascripts/Components/Footer/Footer.tsx | 5 +++- .../Components/Footer/PreferencesButton.tsx | 28 ++++++++++++++++--- 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/packages/ui-services/src/Changelog/ChangelogService.ts b/packages/ui-services/src/Changelog/ChangelogService.ts index bf1790bb5..40a7eee66 100644 --- a/packages/ui-services/src/Changelog/ChangelogService.ts +++ b/packages/ui-services/src/Changelog/ChangelogService.ts @@ -1,7 +1,7 @@ import { Environment } from '@standardnotes/models' import { StorageServiceInterface, StorageKey } from '@standardnotes/services' import { Changelog, ChangelogVersion } from './Changelog' -import { ChangelogServiceInterface } from './ChangelogServiceInterface' +import { ChangelogLastReadVersionListener, ChangelogServiceInterface } from './ChangelogServiceInterface' import { LegacyWebToDesktopVersionMapping } from './LegacyDesktopMapping' import { LegacyWebToMobileVersionMapping } from './LegacyMobileMapping' @@ -10,9 +10,18 @@ const DesktopDownloadsUrlBase = 'https://github.com/standardnotes/app/releases/t export class ChangelogService implements ChangelogServiceInterface { private changeLog?: Changelog + private lastReadChangeListeners: ChangelogLastReadVersionListener[] = [] constructor(private environment: Environment, private diskService: StorageServiceInterface) {} + public addLastReadChangeListener(listener: ChangelogLastReadVersionListener) { + this.lastReadChangeListeners.push(listener) + + return () => { + this.lastReadChangeListeners = this.lastReadChangeListeners.filter((l) => l !== listener) + } + } + private async performDownloadChangelog(): Promise { const response = await fetch(WebChangelogUrl) const changelog = await response.text() @@ -47,7 +56,11 @@ export class ChangelogService implements ChangelogServiceInterface { return } - this.diskService.setValue(StorageKey.LastReadChangelogVersion, this.changeLog.versions[0].version) + const version = this.changeLog.versions[0].version + this.diskService.setValue(StorageKey.LastReadChangelogVersion, version) + if (version) { + this.lastReadChangeListeners.forEach((listener) => listener(version)) + } } public getLastReadVersion(): string | undefined { diff --git a/packages/ui-services/src/Changelog/ChangelogServiceInterface.ts b/packages/ui-services/src/Changelog/ChangelogServiceInterface.ts index d0313d5a2..c05a45f66 100644 --- a/packages/ui-services/src/Changelog/ChangelogServiceInterface.ts +++ b/packages/ui-services/src/Changelog/ChangelogServiceInterface.ts @@ -1,6 +1,9 @@ import { Changelog, ChangelogVersion } from './Changelog' +export type ChangelogLastReadVersionListener = (version: string) => void + export interface ChangelogServiceInterface { + addLastReadChangeListener(listener: ChangelogLastReadVersionListener): () => void getChangelog(): Promise getVersions(): Promise getDesktopDownloadsUrl(version: string): string diff --git a/packages/web/src/javascripts/Components/Footer/Footer.tsx b/packages/web/src/javascripts/Components/Footer/Footer.tsx index 62ce99c1a..4a5fc41b9 100644 --- a/packages/web/src/javascripts/Components/Footer/Footer.tsx +++ b/packages/web/src/javascripts/Components/Footer/Footer.tsx @@ -339,8 +339,11 @@ class Footer extends AbstractComponent { this.viewControllerManager.quickSettingsMenuController.closeQuickSettingsMenu() } - openPreferences = () => { + openPreferences = (openWhatsNew: boolean) => { this.clickOutsideQuickSettingsMenu() + if (openWhatsNew) { + this.viewControllerManager.preferencesController.setCurrentPane('whats-new') + } this.viewControllerManager.preferencesController.openPreferences() } diff --git a/packages/web/src/javascripts/Components/Footer/PreferencesButton.tsx b/packages/web/src/javascripts/Components/Footer/PreferencesButton.tsx index 71e12cc27..88116b69d 100644 --- a/packages/web/src/javascripts/Components/Footer/PreferencesButton.tsx +++ b/packages/web/src/javascripts/Components/Footer/PreferencesButton.tsx @@ -1,27 +1,47 @@ +import { compareSemVersions } from '@standardnotes/snjs' import { keyboardStringForShortcut, OPEN_PREFERENCES_COMMAND } from '@standardnotes/ui-services' -import { useMemo } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' +import { useApplication } from '../ApplicationProvider' import { useCommandService } from '../CommandProvider' import Icon from '../Icon/Icon' import StyledTooltip from '../StyledTooltip/StyledTooltip' type Props = { - openPreferences: () => void + openPreferences: (openWhatsNew: boolean) => void } const PreferencesButton = ({ openPreferences }: Props) => { - const commandService = useCommandService() + const application = useApplication() + const commandService = useCommandService() const shortcut = useMemo( () => keyboardStringForShortcut(commandService.keyboardShortcutForCommand(OPEN_PREFERENCES_COMMAND)), [commandService], ) + const [changelogLastReadVersion, setChangelogLastReadVersion] = useState(() => + application.changelogService.getLastReadVersion(), + ) + const isChangelogUnread = useMemo( + () => (changelogLastReadVersion ? compareSemVersions(application.version, changelogLastReadVersion) > 0 : false), + [application.version, changelogLastReadVersion], + ) + useEffect( + () => application.changelogService.addLastReadChangeListener(setChangelogLastReadVersion), + [application.changelogService], + ) + + const onClick = useCallback(() => { + openPreferences(isChangelogUnread) + }, [isChangelogUnread, openPreferences]) + return ( - )