diff --git a/apps/web/src/app.js b/apps/web/src/app.js index 11b8aa01f..df35be77a 100644 --- a/apps/web/src/app.js +++ b/apps/web/src/app.js @@ -19,6 +19,7 @@ import { EV } from "notes-core/common"; import useTablet from "./utils/use-tablet"; import { showBuyDialog } from "./components/dialogs/buy-dialog"; import Banner from "./components/banner"; +import { showAccountDeletedNotice } from "./components/dialogs/confirm"; function App() { const [show, setShow] = useState(true); @@ -58,6 +59,9 @@ function App() { return { type, result: false }; } }); + EV.subscribe("user:deleted", async () => { + await showAccountDeletedNotice(); + }); }, []); useEffect(() => { diff --git a/apps/web/src/components/dialogs/confirm.js b/apps/web/src/components/dialogs/confirm.js index ec511743f..fb4df025a 100644 --- a/apps/web/src/components/dialogs/confirm.js +++ b/apps/web/src/components/dialogs/confirm.js @@ -1,9 +1,12 @@ -import React from "react"; +import React, { useState } from "react"; import { Box, Text } from "rebass"; import Dialog, { showDialog } from "./dialog"; import * as Icon from "../icons"; +import Field from "../field"; function Confirm(props) { + const [isButtonEnabled, setIsButtonEnabled] = useState(!props.confirmWith); + return ( @@ -21,12 +25,36 @@ function Confirm(props) { {props.message} + {props.confirmWith && ( + + Please type + + {`${props.confirmWith}`} + + to confirm + + } + id="confirm" + name="confirm" + onChange={(e) => { + if (e.target.value === props.confirmWith) + setIsButtonEnabled(true); + }} + /> + )} ); } -export function confirm(icon, { title, subtitle, message, yesText, noText }) { +export function confirm( + icon, + { title, subtitle, message, yesText, noText, confirmWith } +) { return showDialog((perform) => ( perform(false)} onYes={() => perform(true)} @@ -96,3 +125,28 @@ export function showLogoutConfirmation() { noText: "No", }); } + +export function showAccountDeleteConfirmation(username) { + return confirm(Icon.Logout, { + title: `Delete Account?`, + message: ( + <> + This action is IRREVERSIBLE. All your data (notes, notebooks, + tags, pins, favorites) will be permanently deleted with no way of + recovery. + + ), + confirmWith: username, + yesText: `I understand, delete my account`, + noText: "Cancel", + }); +} + +export function showAccountDeletedNotice() { + return confirm(Icon.Logout, { + title: `Your account was deleted.`, + message: + "You deleted your account from another device. You have been logged out.", + yesText: `Okay`, + }); +} diff --git a/apps/web/src/stores/app-store.js b/apps/web/src/stores/app-store.js index 95a84ae2c..898cca114 100644 --- a/apps/web/src/stores/app-store.js +++ b/apps/web/src/stores/app-store.js @@ -22,6 +22,7 @@ class AppStore extends BaseStore { menuPins = []; refresh = async () => { + await resetReminders(); noteStore.refresh(); notebookStore.refresh(); trashStore.refresh(); @@ -29,7 +30,6 @@ class AppStore extends BaseStore { editorStore.openLastSession(); this.refreshColors(); this.refreshMenuPins(); - await resetReminders(); }; refreshColors = () => { diff --git a/apps/web/src/stores/user-store.js b/apps/web/src/stores/user-store.js index 43d89b4d4..f30c5fe69 100644 --- a/apps/web/src/stores/user-store.js +++ b/apps/web/src/stores/user-store.js @@ -33,6 +33,13 @@ class UserStore extends BaseStore { }); EV.subscribe("db:sync", () => this.sync(false)); EV.subscribe("user:loggedOut", async () => { + this.set((state) => { + state.user = {}; + state.isLoggedIn = false; + }); + config.clear(); + await appStore.refresh(); + if (window.PasswordCredential) { await navigator.credentials.preventSilentAccess(); if (navigator.credentials.requireUserMediation) @@ -95,17 +102,6 @@ class UserStore extends BaseStore { this.set((state) => (state.isSyncing = false)); }); }; - - logout = () => { - return db.user.logout().then(async () => { - this.set((state) => { - state.user = {}; - state.isLoggedIn = false; - }); - config.clear(); - await appStore.refresh(); - }); - }; } /** diff --git a/apps/web/src/views/settings.js b/apps/web/src/views/settings.js index 58e72abde..f101cd1ad 100644 --- a/apps/web/src/views/settings.js +++ b/apps/web/src/views/settings.js @@ -7,7 +7,10 @@ import { useStore as useSettingStore } from "../stores/setting-store"; import AccentItem from "../components/accent-item"; import accents from "../theme/accents"; import { showLogInDialog } from "../components/dialogs/logindialog"; -import { showLogoutConfirmation } from "../components/dialogs/confirm"; +import { + showAccountDeleteConfirmation, + showLogoutConfirmation, +} from "../components/dialogs/confirm"; import useSystemTheme from "../utils/use-system-theme"; import { createBackup, @@ -67,7 +70,6 @@ function Settings(props) { ); const user = useUserStore((store) => store.user); const isLoggedIn = useUserStore((store) => store.isLoggedIn); - const logout = useUserStore((store) => store.logout); const [backupReminderOffset, setBackupReminderOffset] = usePersistentState( "backupReminderOffset", 0 @@ -191,7 +193,7 @@ function Settings(props) { variant="list" onClick={async () => { if (await showLogoutConfirmation()) { - await logout(); + await db.user.logout(); } }} > @@ -200,6 +202,21 @@ function Settings(props) { tip="Log out of your account and clear all data." /> + )} + {text} - + {tip} diff --git a/apps/web/yarn.lock b/apps/web/yarn.lock index 32492c881..2e56d465b 100644 --- a/apps/web/yarn.lock +++ b/apps/web/yarn.lock @@ -8959,7 +8959,7 @@ normalize-url@^3.0.0, normalize-url@^3.0.1: "notes-core@git+ssh://git@github.com:streetwriters/notesnook-core.git": version "4.3.1" - resolved "git+ssh://git@github.com:streetwriters/notesnook-core.git#81188213c112d4ba421854bb4879f0527b4a814d" + resolved "git+ssh://git@github.com:streetwriters/notesnook-core.git#1d1e86e59a3f149c97cf4dafb39ffe555981d528" dependencies: fast-sort "^2.0.1" fuzzysearch "^1.0.3"