From e50f4eb92efd65b0b8fa3a5001b8dfb611f60180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Thu, 22 Sep 2022 20:18:19 +0200 Subject: [PATCH] Revert "Revert "feat(web): move emails notifications to one pane and enable opening settings via url (#1614)" (#1617)" (#1619) This reverts commit 6824dd2d5fe4a6d427ff5465540f3b7865933e98. --- .../lib/Services/Settings/SettingsList.ts | 2 + .../Preferences/Panes/General/Email.tsx | 134 ++++++++++++++++++ .../Preferences/Panes/General/General.tsx | 2 + .../Preferences/Panes/Security/Privacy.tsx | 41 +----- .../Controllers/PreferencesController.ts | 9 ++ .../Controllers/ViewControllerManager.ts | 24 +++- 6 files changed, 171 insertions(+), 41 deletions(-) create mode 100644 packages/web/src/javascripts/Components/Preferences/Panes/General/Email.tsx diff --git a/packages/snjs/lib/Services/Settings/SettingsList.ts b/packages/snjs/lib/Services/Settings/SettingsList.ts index 3636a8b60..0b6bd32ec 100644 --- a/packages/snjs/lib/Services/Settings/SettingsList.ts +++ b/packages/snjs/lib/Services/Settings/SettingsList.ts @@ -11,6 +11,7 @@ import { ListedAuthorSecretsData, LogSessionUserAgentOption, SettingName, + MuteMarketingEmailsOption, } from '@standardnotes/settings' type SettingType = @@ -23,6 +24,7 @@ type SettingType = | MuteFailedBackupsEmailsOption | MuteFailedCloudBackupsEmailsOption | MuteSignInEmailsOption + | MuteMarketingEmailsOption | OneDriveBackupFrequency export class SettingsList { diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/General/Email.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/General/Email.tsx new file mode 100644 index 000000000..e5d3f9115 --- /dev/null +++ b/packages/web/src/javascripts/Components/Preferences/Panes/General/Email.tsx @@ -0,0 +1,134 @@ +import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator' +import Switch from '@/Components/Switch/Switch' +import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content' +import { WebApplication } from '@/Application/Application' +import { MuteMarketingEmailsOption, MuteSignInEmailsOption, SettingName } from '@standardnotes/snjs' +import { observer } from 'mobx-react-lite' +import { FunctionComponent, useCallback, useEffect, useState } from 'react' +import { STRING_FAILED_TO_UPDATE_USER_SETTING } from '@/Constants/Strings' +import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup' +import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment' +import Spinner from '@/Components/Spinner/Spinner' + +type Props = { + application: WebApplication +} + +const Email: FunctionComponent = ({ application }: Props) => { + const [signInEmailsMutedValue, setSignInEmailsMutedValue] = useState(MuteSignInEmailsOption.NotMuted) + const [marketingEmailsMutedValue, setMarketingEmailsMutedValue] = useState(MuteMarketingEmailsOption.NotMuted) + const [isLoading, setIsLoading] = useState(true) + + const updateSetting = async (settingName: SettingName, payload: string): Promise => { + try { + await application.settings.updateSetting(settingName, payload, false) + return true + } catch (e) { + application.alertService.alert(STRING_FAILED_TO_UPDATE_USER_SETTING).catch(console.error) + return false + } + } + + const loadSettings = useCallback(async () => { + if (!application.getUser()) { + return + } + setIsLoading(true) + + try { + const userSettings = await application.settings.listSettings() + setSignInEmailsMutedValue( + userSettings.getSettingValue( + SettingName.MuteSignInEmails, + MuteSignInEmailsOption.NotMuted, + ), + ), + setMarketingEmailsMutedValue( + userSettings.getSettingValue( + SettingName.MuteMarketingEmails, + MuteMarketingEmailsOption.NotMuted, + ), + ) + } catch (error) { + console.error(error) + } finally { + setIsLoading(false) + } + }, [application]) + + useEffect(() => { + loadSettings().catch(console.error) + }, [loadSettings]) + + const toggleMuteSignInEmails = async () => { + const previousValue = signInEmailsMutedValue + const newValue = + previousValue === MuteSignInEmailsOption.Muted ? MuteSignInEmailsOption.NotMuted : MuteSignInEmailsOption.Muted + setSignInEmailsMutedValue(newValue) + + const updateResult = await updateSetting(SettingName.MuteSignInEmails, newValue) + + if (!updateResult) { + setSignInEmailsMutedValue(previousValue) + } + } + + const toggleMuteMarketingEmails = async () => { + const previousValue = marketingEmailsMutedValue + const newValue = + previousValue === MuteMarketingEmailsOption.Muted + ? MuteMarketingEmailsOption.NotMuted + : MuteMarketingEmailsOption.Muted + setMarketingEmailsMutedValue(newValue) + + const updateResult = await updateSetting(SettingName.MuteMarketingEmails, newValue) + + if (!updateResult) { + setMarketingEmailsMutedValue(previousValue) + } + } + + return ( + + + Email +
+
+
+ Disable sign-in notification emails + + Disables email notifications when a new sign-in occurs on your account. (Email notifications are + available to paid subscribers). + +
+ {isLoading ? ( + + ) : ( + + )} +
+ +
+
+ Disable marketing notification emails + Disables email notifications with special deals and promotions. +
+ {isLoading ? ( + + ) : ( + + )} +
+
+
+
+ ) +} + +export default observer(Email) diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/General/General.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/General/General.tsx index db3e8a94a..178cf42e8 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/General/General.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/General/General.tsx @@ -8,6 +8,7 @@ import Defaults from './Defaults' import LabsPane from './Labs/Labs' import Advanced from '@/Components/Preferences/Panes/General/Advanced/AdvancedSection' import PreferencesPane from '../../PreferencesComponents/PreferencesPane' +import Email from './Email' type Props = { viewControllerManager: ViewControllerManager @@ -19,6 +20,7 @@ const General: FunctionComponent = ({ viewControllerManager, application, + = ({ application }: Props) => { - const [signInEmailsMutedValue, setSignInEmailsMutedValue] = useState( - MuteSignInEmailsOption.NotMuted, - ) const [sessionUaLoggingValue, setSessionUaLoggingValue] = useState( LogSessionUserAgentOption.Enabled, ) @@ -41,12 +38,6 @@ const Privacy: FunctionComponent = ({ application }: Props) => { try { const userSettings = await application.settings.listSettings() - setSignInEmailsMutedValue( - userSettings.getSettingValue( - SettingName.MuteSignInEmails, - MuteSignInEmailsOption.NotMuted, - ), - ) setSessionUaLoggingValue( userSettings.getSettingValue( SettingName.LogSessionUserAgent, @@ -64,19 +55,6 @@ const Privacy: FunctionComponent = ({ application }: Props) => { loadSettings().catch(console.error) }, [loadSettings]) - const toggleMuteSignInEmails = async () => { - const previousValue = signInEmailsMutedValue - const newValue = - previousValue === MuteSignInEmailsOption.Muted ? MuteSignInEmailsOption.NotMuted : MuteSignInEmailsOption.Muted - setSignInEmailsMutedValue(newValue) - - const updateResult = await updateSetting(SettingName.MuteSignInEmails, newValue) - - if (!updateResult) { - setSignInEmailsMutedValue(previousValue) - } - } - const toggleSessionLogging = async () => { const previousValue = sessionUaLoggingValue const newValue = @@ -97,23 +75,6 @@ const Privacy: FunctionComponent = ({ application }: Props) => { Privacy
-
-
- Disable sign-in notification emails - - Disables email notifications when a new sign-in occurs on your account. (Email notifications are - available to paid subscribers). - -
- {isLoading ? ( - - ) : ( - - )} -
diff --git a/packages/web/src/javascripts/Controllers/PreferencesController.ts b/packages/web/src/javascripts/Controllers/PreferencesController.ts index ff3fa4e20..846e516d6 100644 --- a/packages/web/src/javascripts/Controllers/PreferencesController.ts +++ b/packages/web/src/javascripts/Controllers/PreferencesController.ts @@ -29,9 +29,18 @@ export class PreferencesController { closePreferences = (): void => { this._open = false this.currentPane = DEFAULT_PANE + this.removePreferencesToggleFromURLQueryParameters() } get isOpen(): boolean { return this._open } + + private removePreferencesToggleFromURLQueryParameters() { + const urlSearchParams = new URLSearchParams(window.location.search) + urlSearchParams.delete('settings') + + const newUrl = `${window.location.origin}${window.location.pathname}${urlSearchParams.toString()}` + window.history.replaceState(null, document.title, newUrl) + } } diff --git a/packages/web/src/javascripts/Controllers/ViewControllerManager.ts b/packages/web/src/javascripts/Controllers/ViewControllerManager.ts index d2cec0695..1be78ff49 100644 --- a/packages/web/src/javascripts/Controllers/ViewControllerManager.ts +++ b/packages/web/src/javascripts/Controllers/ViewControllerManager.ts @@ -29,6 +29,8 @@ import { NavigationController } from './Navigation/NavigationController' import { FilePreviewModalController } from './FilePreviewModalController' import { SelectedItemsController } from './SelectedItemsController' import { HistoryModalController } from './NoteHistory/HistoryModalController' +import { PreferenceId } from '@/Components/Preferences/PreferencesMenu' +import { AccountMenuPane } from '@/Components/AccountMenu/AccountMenuPane' export class ViewControllerManager { readonly enableUnfinishedFeatures: boolean = window?.enabledUnfinishedFeatures @@ -209,11 +211,31 @@ export class ViewControllerManager { addAppEventObserver() { this.unsubAppEventObserver = this.application.addEventObserver(async (eventName) => { + const urlSearchParams = new URLSearchParams(window.location.search) + switch (eventName) { case ApplicationEvent.Launched: - if (window.location.search.includes('purchase=true')) { + if (urlSearchParams.get('purchase')) { this.purchaseFlowController.openPurchaseFlow() } + if (urlSearchParams.get('settings')) { + const user = this.application.getUser() + if (user === undefined) { + this.accountMenuController.setShow(true) + this.accountMenuController.setCurrentPane(AccountMenuPane.SignIn) + + break + } + + this.preferencesController.openPreferences() + this.preferencesController.setCurrentPane(urlSearchParams.get('settings') as PreferenceId) + } + break + case ApplicationEvent.SignedIn: + if (urlSearchParams.get('settings')) { + this.preferencesController.openPreferences() + this.preferencesController.setCurrentPane(urlSearchParams.get('settings') as PreferenceId) + } break case ApplicationEvent.SyncStatusChanged: this.syncStatusController.update(this.application.sync.getSyncStatus())