diff --git a/apps/web/.env-cmdrc.js b/apps/web/.env-cmdrc.js
index ccda0d189..9cbcd3b19 100644
--- a/apps/web/.env-cmdrc.js
+++ b/apps/web/.env-cmdrc.js
@@ -7,8 +7,8 @@ const gitHash = execSync("git rev-parse --short HEAD").toString().trim();
module.exports = {
all: {
UV_THREADPOOL_SIZE: IS_CI ? NUM_CPUS : 2,
- GENERATE_SOURCEMAP: false,
- INLINE_RUNTIME_CHUNK: false,
+ // GENERATE_SOURCEMAP: false,
+ // INLINE_RUNTIME_CHUNK: false,
DISABLE_ESLINT_PLUGIN: true,
REACT_APP_GIT_HASH: gitHash,
},
diff --git a/apps/web/__e2e__/editor.test.js b/apps/web/__e2e__/editor.test.js
index 3fd04426e..df809f9d0 100644
--- a/apps/web/__e2e__/editor.test.js
+++ b/apps/web/__e2e__/editor.test.js
@@ -5,10 +5,11 @@ const { createNote, NOTE, getTestId } = require("./utils");
*/
var page = null;
global.page = null;
-test.beforeEach(async ({ page: _page }) => {
+test.beforeEach(async ({ page: _page, baseURL }) => {
global.page = _page;
page = _page;
- await page.goto("http://localhost:3000/");
+ await page.goto(baseURL);
+ await page.waitForSelector(getTestId("routeHeader"));
});
test("focus mode", async () => {
diff --git a/apps/web/__e2e__/navigation.test.js b/apps/web/__e2e__/navigation.test.js
index 1b7d2a2c5..2fb2f289b 100644
--- a/apps/web/__e2e__/navigation.test.js
+++ b/apps/web/__e2e__/navigation.test.js
@@ -5,6 +5,7 @@ const { getTestId } = require("./utils");
test.beforeEach(async ({ page, baseURL }) => {
await page.goto(baseURL);
+ await page.waitForSelector(getTestId("routeHeader"));
});
function createRoute(key, header) {
diff --git a/apps/web/__e2e__/notebooks.test.js b/apps/web/__e2e__/notebooks.test.js
index 1629d7994..67bcdd888 100644
--- a/apps/web/__e2e__/notebooks.test.js
+++ b/apps/web/__e2e__/notebooks.test.js
@@ -17,9 +17,10 @@ const { checkNotePresence, isPresent } = require("./utils/conditions");
*/
global.page = null;
-test.beforeEach(async ({ page: _page }) => {
+test.beforeEach(async ({ page: _page, baseURL }) => {
global.page = _page;
- await page.goto("http://localhost:3000/");
+ await page.goto(baseURL);
+ await page.waitForSelector(getTestId("routeHeader"));
});
async function fillNotebookDialog(notebook) {
diff --git a/apps/web/__e2e__/notes.test.js b/apps/web/__e2e__/notes.test.js
index 09a6a4612..710685603 100644
--- a/apps/web/__e2e__/notes.test.js
+++ b/apps/web/__e2e__/notes.test.js
@@ -203,9 +203,10 @@ test.describe("run tests independently", () => {
* @type {Page}
*/
global.page = null;
- test.beforeEach(async ({ page: _page }) => {
+ test.beforeEach(async ({ page: _page, baseURL }) => {
global.page = _page;
- await page.goto("http://localhost:3000/");
+ await page.goto(baseURL);
+ await page.waitForSelector(getTestId("routeHeader"));
});
test("create a note", async () => {
diff --git a/apps/web/__e2e__/user.test.js b/apps/web/__e2e__/user.test.js
index b3755e03b..3b6efbee3 100644
--- a/apps/web/__e2e__/user.test.js
+++ b/apps/web/__e2e__/user.test.js
@@ -15,6 +15,7 @@ test.beforeEach(async ({ page: _page, baseURL }) => {
global.page = _page;
page = _page;
await page.goto(baseURL);
+ await page.waitForSelector(getTestId("routeHeader"));
});
const USER = {
diff --git a/apps/web/desktop/autoupdate.js b/apps/web/desktop/autoupdate.js
index c3e4dacf3..89de0b389 100644
--- a/apps/web/desktop/autoupdate.js
+++ b/apps/web/desktop/autoupdate.js
@@ -14,7 +14,6 @@ async function configureAutoUpdater() {
sendMessageToRenderer(EVENTS.updateAvailable, info);
});
autoUpdater.addListener("download-progress", (progress) => {
- console.log("Downloading", progress);
sendMessageToRenderer(EVENTS.updateDownloadProgress, progress);
});
autoUpdater.addListener("update-downloaded", (info) => {
diff --git a/apps/web/package.json b/apps/web/package.json
index 3f0df8b0d..b590e7e8f 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -23,7 +23,7 @@
"emotion-theming": "^10.0.19",
"fast-sort": "^2.1.1",
"file-saver": "^2.0.5",
- "framer-motion": "^3.3.0",
+ "framer-motion": "^4.1.17",
"hash-wasm": "^4.9.0",
"hotkeys-js": "^3.8.3",
"immer": "^9.0.6",
@@ -77,6 +77,7 @@
"patch-package": "^6.4.7",
"source-map-explorer": "^2.5.2",
"typescript": "^4.1.5",
+ "webpack-bundle-analyzer": "^4.5.0",
"worker-loader": "^3.0.8",
"zx": "^2.0.0"
},
diff --git a/apps/web/public/fonts.css b/apps/web/public/fonts.css
deleted file mode 100644
index ed043415c..000000000
--- a/apps/web/public/fonts.css
+++ /dev/null
@@ -1,68 +0,0 @@
-/* open-sans-regular - latin */
-@font-face {
- font-family: "Open Sans";
- font-display: swap;
- font-style: normal;
- font-weight: 400;
- src: local(""),
- url("/fonts/open-sans-v20-latin-regular.woff2") format("woff2"),
- /* Chrome 26+, Opera 23+, Firefox 39+ */
- url("/fonts/open-sans-v20-latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
-}
-
-/* open-sans-italic - latin */
-@font-face {
- font-family: "Open Sans";
- font-display: swap;
- font-style: italic;
- font-weight: 400;
- src: local(""), url("/fonts/open-sans-v20-latin-italic.woff2") format("woff2"),
- /* Chrome 26+, Opera 23+, Firefox 39+ */
- url("/fonts/open-sans-v20-latin-italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
-}
-
-/* open-sans-600 - latin */
-@font-face {
- font-family: "Open Sans";
- font-display: swap;
- font-style: normal;
- font-weight: 600;
- src: local(""), url("/fonts/open-sans-v20-latin-600.woff2") format("woff2"),
- /* Chrome 26+, Opera 23+, Firefox 39+ */
- url("/fonts/open-sans-v20-latin-600.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
-}
-
-/* open-sans-600italic - latin */
-@font-face {
- font-family: "Open Sans";
- font-display: swap;
- font-style: italic;
- font-weight: 600;
- src: local(""),
- url("/fonts/open-sans-v20-latin-600italic.woff2") format("woff2"),
- /* Chrome 26+, Opera 23+, Firefox 39+ */
- url("/fonts/open-sans-v20-latin-600italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
-}
-
-/* open-sans-700 - latin */
-@font-face {
- font-family: "Open Sans";
- font-display: swap;
- font-style: normal;
- font-weight: 700;
- src: local(""), url("/fonts/open-sans-v20-latin-700.woff2") format("woff2"),
- /* Chrome 26+, Opera 23+, Firefox 39+ */
- url("/fonts/open-sans-v20-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
-}
-
-/* open-sans-700italic - latin */
-@font-face {
- font-family: "Open Sans";
- font-display: swap;
- font-style: italic;
- font-weight: 700;
- src: local(""),
- url("/fonts/open-sans-v20-latin-700italic.woff2") format("woff2"),
- /* Chrome 26+, Opera 23+, Firefox 39+ */
- url("/fonts/open-sans-v20-latin-700italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
-}
diff --git a/apps/web/public/index.html b/apps/web/public/index.html
index 8db866bbe..ec4dcf5ef 100644
--- a/apps/web/public/index.html
+++ b/apps/web/public/index.html
@@ -17,7 +17,7 @@
rel="icon"
type="image/png"
sizes="32x32"
- href="%PUBLIC_URL%/favicon-32x32.png"
+ href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAHUUExURUxpcf////////////////////////////////////////////////////////////////////////////////////39/f39/f////////////////////////////////z8/O3s7P7+/vTz8wAAAPz7++/v7/Py8u/u7vDv7+7t7dfX1/79/ezr66Kiovv6+vf29vX09OTj4w0NDfv7++Ti4vr6+vT09Ovq6vn5+f39/fb19dnX1/b29tvb29/f3xMTE/j4+Pn4+O7s7MnJyerq6uno6M/Pz8jIyN3d3dnZ2d7e3kZGRvj39/38/Pf39+zs7PDw8OPi4ubl5cvLy+rp6czMzPLy8vPz887Ozujo6MrKyuDf3+fn59PT0+bm5uXl5c3NzfX19evr6wsLC+/t7ePj4/Ty8u3r6/Lx8eXk5OPh4dDQ0Nza2tjX19vZ2fHw8Nva2tLR0djW1tbW1tra2tLS0uHh4evp6eLi4tXV1djY2L+/vysrK7q6utHR0aGhoa6urrm5uQICAigoKCEhIZCQkFxcXBgYGFRUVBISEm1tbQ4ODklJSbu7uyAgID09PZqamkVFRXh4eLGxsTg4OOTk5FFRUQEBAQoKCnx8fBcXF7/+rP8AAAAfdFJOUwBOqO2h6KT9Mtyr5+w3Str+6TTZOjXb31M24O8BOd0PapSsAAABxElEQVQ4y2NgYOBgYWWXxwLYBdmEGICAjx9Z1NJJVQfB42QE6hdG0RaoaaCqhKSCl4EF1VxNVAXyTAzcaArUUBXwMLBjKDBBViDAII+uwBZFgTy6AjU1awIKNKz1aa0g1VBfB58CDS08CuIb40AKzLAqsJKXN2tXacChwKS+rTtB3tJHRU9ewxmbFZ6tKiqTrSAKdIO1LDEUaPeoqMzsUwAp0NIt8Uj0ijJXQFVgnDJVZcK0XrACXcXY0sjoHM8AfyUkBbOn9KvMmgRSYFEW4hUVqJagHeaShqTAwX7ijJQusAkW5VXRHu6eruFqaigKkqarqAAVKFbYxWiYq1XGedijuMHBWz6xo7m2Rl7RwtvdJaw6NjzCFl2BVVNdshJQgbqBsqtdpIu7nasjXIFXS2cyRL2CW6i6JTCgFCLitUPs4QrM7cDmKZi7FRYVm6o5QeLbDGICLNEqJAVk59rk2djY5Me4FThawQOKFSzrrxmaZWpqBAamQUGmwRaakNTNzMAm7+ekrKmlqOjsrIgAGcAA1ci0NVPiYhAV8zVURgbp6nBg7isuwsDAKKfkp4AEVOHASklKApS9JZmY5bECaS5ZGQYA3vqpy6NoYh0AAABXelRYdFJhdyBwcm9maWxlIHR5cGUgaXB0YwAAeJzj8gwIcVYoKMpPy8xJ5VIAAyMLLmMLEyMTS5MUAxMgRIA0w2QDI7NUIMvY1MjEzMQcxAfLgEigSi4A6hcRdPJCNZUAAAAASUVORK5CYII="
/>
-
+
+
-
diff --git a/apps/web/src/app-effects.js b/apps/web/src/app-effects.js
index 24d051997..53d85f9d1 100644
--- a/apps/web/src/app-effects.js
+++ b/apps/web/src/app-effects.js
@@ -8,16 +8,21 @@ import { db } from "./common/db";
import { CHECK_IDS, EV, EVENTS } from "notes-core/common";
import { registerKeyMap } from "./common/key-map";
import { isUserPremium } from "./hooks/use-is-user-premium";
+import { loadTrackerScript } from "./utils/analytics";
+import Modal from "react-modal";
-function AppEffects({ isMobile, isTablet, setShow, slideToIndex }) {
+Modal.setAppElement("#root");
+if (process.env.NODE_ENV === "production") {
+ loadTrackerScript();
+ console.log = () => {};
+}
+
+export default function AppEffects({ setShow }) {
const refreshColors = useStore((store) => store.refreshColors);
const refreshMenuPins = useStore((store) => store.refreshMenuPins);
const updateLastSynced = useStore((store) => store.updateLastSynced);
const setProcessingStatus = useStore((store) => store.setProcessingStatus);
const isFocusMode = useStore((store) => store.isFocusMode);
- const isEditorOpen = useStore((store) => store.isEditorOpen);
- const toggleSideMenu = useStore((store) => store.toggleSideMenu);
- const isSideMenuOpen = useStore((store) => store.isSideMenuOpen);
const addReminder = useStore((store) => store.addReminder);
const initUser = useUserStore((store) => store.init);
const initNotes = useNotesStore((store) => store.init);
@@ -115,25 +120,8 @@ function AppEffects({ isMobile, isTablet, setShow, slideToIndex }) {
};
}, []);
- useEffect(() => {
- if (!isMobile) return;
- slideToIndex(isSideMenuOpen ? 0 : 1);
- }, [isMobile, slideToIndex, isSideMenuOpen]);
-
- useEffect(() => {
- if (!isMobile) return;
- slideToIndex(isEditorOpen ? 2 : 1);
- }, [isMobile, slideToIndex, isEditorOpen]);
-
- useEffect(() => {
- toggleSideMenu(!isMobile);
- if (!isMobile && !isTablet && !isFocusMode) setShow(true);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [isMobile, isTablet, isFocusMode, toggleSideMenu]);
-
return ;
}
-export default AppEffects;
function getProcessingStatusFromType(type) {
switch (type) {
diff --git a/apps/web/src/app-effects.mobile.js b/apps/web/src/app-effects.mobile.js
new file mode 100644
index 000000000..08b99c5d7
--- /dev/null
+++ b/apps/web/src/app-effects.mobile.js
@@ -0,0 +1,64 @@
+import { useEffect } from "react";
+import { useStore } from "./stores/app-store";
+import useSlider from "./hooks/use-slider";
+import useMobile from "./utils/use-mobile";
+import useTablet from "./utils/use-tablet";
+
+export default function MobileAppEffects({ sliderId, overlayId, setShow }) {
+ const isMobile = useMobile();
+ const isTablet = useTablet();
+ const toggleSideMenu = useStore((store) => store.toggleSideMenu);
+ const setIsEditorOpen = useStore((store) => store.setIsEditorOpen);
+ const isEditorOpen = useStore((store) => store.isEditorOpen);
+ const isSideMenuOpen = useStore((store) => store.isSideMenuOpen);
+ const isFocusMode = useStore((store) => store.isFocusMode);
+
+ const [slideToIndex] = useSlider(sliderId, {
+ onSliding: (e, { lastSlide, position, lastPosition }) => {
+ if (!isMobile) return;
+ const offset = 70;
+ const width = 180;
+
+ const percent = offset - (position / width) * offset;
+ const overlay = document.getElementById("overlay");
+ if (percent > 0) {
+ overlay.style.opacity = `${percent}%`;
+ overlay.style.pointerEvents = "all";
+ } else {
+ overlay.style.pointerEvents = "none";
+ }
+ },
+ onChange: (e, { slide, lastSlide }) => {
+ if (!lastSlide || !isMobile) return;
+ toggleSideMenu(slide?.index === 0 ? true : false);
+ setIsEditorOpen(slide?.index === 2 ? true : false);
+ },
+ });
+
+ useEffect(() => {
+ if (!isMobile) return;
+ slideToIndex(isSideMenuOpen ? 0 : 1);
+ }, [isMobile, slideToIndex, isSideMenuOpen]);
+
+ useEffect(() => {
+ if (!isMobile) return;
+ slideToIndex(isEditorOpen ? 2 : 1);
+ }, [isMobile, slideToIndex, isEditorOpen]);
+
+ useEffect(() => {
+ toggleSideMenu(!isMobile);
+ if (!isMobile && !isTablet && !isFocusMode) setShow(true);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isMobile, isTablet, isFocusMode, toggleSideMenu]);
+
+ useEffect(() => {
+ if (!overlayId) return;
+ const overlay = document.getElementById(overlayId);
+ overlay.onclick = () => toggleSideMenu(false);
+ return () => {
+ overlay.onclick = null;
+ };
+ }, [overlayId, toggleSideMenu]);
+
+ return null;
+}
diff --git a/apps/web/src/app.css b/apps/web/src/app.css
index cc8ce7f6d..268d8c101 100644
--- a/apps/web/src/app.css
+++ b/apps/web/src/app.css
@@ -1,3 +1,75 @@
+/* open-sans-regular - latin */
+@font-face {
+ font-family: "Open Sans";
+ font-display: swap;
+ font-style: normal;
+ font-weight: 400;
+ src: local(""),
+ url("./assets/fonts/open-sans-v20-latin-regular.woff2") format("woff2"),
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url("./assets/fonts/open-sans-v20-latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* open-sans-italic - latin */
+@font-face {
+ font-family: "Open Sans";
+ font-display: swap;
+ font-style: italic;
+ font-weight: 400;
+ src: local(""),
+ url("./assets/fonts/open-sans-v20-latin-italic.woff2") format("woff2"),
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url("./assets/fonts/open-sans-v20-latin-italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* open-sans-600 - latin */
+@font-face {
+ font-family: "Open Sans";
+ font-display: swap;
+ font-style: normal;
+ font-weight: 600;
+ src: local(""),
+ url("./assets/fonts/open-sans-v20-latin-600.woff2") format("woff2"),
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url("./assets/fonts/open-sans-v20-latin-600.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* open-sans-600italic - latin */
+@font-face {
+ font-family: "Open Sans";
+ font-display: swap;
+ font-style: italic;
+ font-weight: 600;
+ src: local(""),
+ url("./assets/fonts/open-sans-v20-latin-600italic.woff2") format("woff2"),
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url("./assets/fonts/open-sans-v20-latin-600italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* open-sans-700 - latin */
+@font-face {
+ font-family: "Open Sans";
+ font-display: swap;
+ font-style: normal;
+ font-weight: 700;
+ src: local(""),
+ url("./assets/fonts/open-sans-v20-latin-700.woff2") format("woff2"),
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url("./assets/fonts/open-sans-v20-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
+/* open-sans-700italic - latin */
+@font-face {
+ font-family: "Open Sans";
+ font-display: swap;
+ font-style: italic;
+ font-weight: 700;
+ src: local(""),
+ url("./assets/fonts/open-sans-v20-latin-700italic.woff2") format("woff2"),
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
+ url("./assets/fonts/open-sans-v20-latin-700italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
+}
+
.unselectable {
-webkit-touch-callout: none;
-webkit-user-select: none;
diff --git a/apps/web/src/app.js b/apps/web/src/app.js
index 779daafcd..2c62e964c 100644
--- a/apps/web/src/app.js
+++ b/apps/web/src/app.js
@@ -1,81 +1,48 @@
-import React, { useState, useEffect } from "react";
-import "./app.css";
-import { Box, Flex } from "rebass";
-import { MotionConfig, AnimationFeature, GesturesFeature } from "framer-motion";
+import React, { useState, Suspense } from "react";
+import { Box, Flex, Text } from "rebass";
import ThemeProvider from "./components/theme-provider";
-import StatusBar from "./components/statusbar";
-import Animated from "./components/animated";
-import NavigationMenu from "./components/navigationmenu";
-import GlobalMenuWrapper from "./components/globalmenuwrapper";
-import { NavigationEvents } from "./navigation";
-import rootroutes from "./navigation/rootroutes";
-import { useStore } from "./stores/app-store";
-import { Suspense } from "react";
+import { AnimatedFlex } from "./components/animated";
+import NavigationMenuPlaceholder from "./components/navigationmenu/index.lite";
+import StatusBarPlaceholder from "./components/statusbar/index.lite";
import useMobile from "./utils/use-mobile";
import useTablet from "./utils/use-tablet";
-import HashRouter from "./components/hashrouter";
-import useSlider from "./hooks/use-slider";
-import useRoutes from "./utils/use-routes";
-import { clearRouteCache } from "./components/cachedrouter";
+import { Loading } from "./components/icons";
+import { LazyMotion, domAnimation } from "framer-motion";
+import useDatabase from "./hooks/use-database";
+import Loader from "./components/loader";
+const GlobalMenuWrapper = React.lazy(() =>
+ import("./components/global-menu-wrapper")
+);
const AppEffects = React.lazy(() => import("./app-effects"));
+const MobileAppEffects = React.lazy(() => import("./app-effects.mobile"));
const CachedRouter = React.lazy(() => import("./components/cached-router"));
+const HashRouter = React.lazy(() => import("./components/hash-router"));
+const NavigationMenu = React.lazy(() => import("./components/navigation-menu"));
+const StatusBar = React.lazy(() => import("./components/status-bar"));
function App() {
const [show, setShow] = useState(true);
const isMobile = useMobile();
const isTablet = useTablet();
- const [isAppLoaded, setIsAppLoaded] = useState(false);
- const toggleSideMenu = useStore((store) => store.toggleSideMenu);
- const setIsEditorOpen = useStore((store) => store.setIsEditorOpen);
- const [sliderRef, slideToIndex] = useSlider({
- onSliding: (e, { lastSlide, position, lastPosition }) => {
- if (!isMobile) return;
- const offset = 70;
- const width = 180;
-
- const percent = offset - (position / width) * offset;
- const overlay = document.getElementById("overlay");
- if (percent > 0) {
- overlay.style.opacity = `${percent}%`;
- overlay.style.pointerEvents = "all";
- } else {
- overlay.style.pointerEvents = "none";
- }
- },
- onChange: (e, { slide, lastSlide }) => {
- if (!lastSlide || !isMobile) return;
- toggleSideMenu(slide?.index === 0 ? true : false);
- setIsEditorOpen(slide?.index === 2 ? true : false);
- },
- });
-
- useEffect(() => {
- function onNavigate() {
- NavigationEvents.unsubscribe("onNavigate", onNavigate);
- setIsAppLoaded(true);
- }
- NavigationEvents.subscribe("onNavigate", onNavigate);
- return () => {
- NavigationEvents.unsubscribe("onNavigate", onNavigate);
- };
- }, []);
+ const [isAppLoaded] = useDatabase();
return (
-
+
{isAppLoaded && (
}>
-
+
+
+ {isMobile && (
+
+ )}
)}
-
-
- {
- if (!isMobile) setShow(state || !show);
+ {
+ if (!isMobile) setShow(state || !show);
+ },
}}
+ fallback={}
/>
-
- }>
-
-
+
+ }
+ />
{isMobile && (
{
- toggleSideMenu(false);
- }}
/>
)}
-
+
-
+
+ }
+ component={HashRouter}
+ condition={isAppLoaded}
+ />
-
+ }
+ component={StatusBar}
+ condition={isAppLoaded}
+ />
-
+
);
}
-function Root() {
- const route = useRoutes(rootroutes);
- if (route) clearRouteCache();
- return route?.component || ;
-}
+export default App;
-export default Root;
+function SuspenseLoader({ condition, props, component: Component, fallback }) {
+ if (!condition) return fallback;
+
+ return (
+
+
+
+ );
+}
diff --git a/apps/web/public/fonts/open-sans-v20-latin-600.woff b/apps/web/src/assets/fonts/open-sans-v20-latin-600.woff
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-600.woff
rename to apps/web/src/assets/fonts/open-sans-v20-latin-600.woff
diff --git a/apps/web/public/fonts/open-sans-v20-latin-600.woff2 b/apps/web/src/assets/fonts/open-sans-v20-latin-600.woff2
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-600.woff2
rename to apps/web/src/assets/fonts/open-sans-v20-latin-600.woff2
diff --git a/apps/web/public/fonts/open-sans-v20-latin-600italic.woff b/apps/web/src/assets/fonts/open-sans-v20-latin-600italic.woff
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-600italic.woff
rename to apps/web/src/assets/fonts/open-sans-v20-latin-600italic.woff
diff --git a/apps/web/public/fonts/open-sans-v20-latin-600italic.woff2 b/apps/web/src/assets/fonts/open-sans-v20-latin-600italic.woff2
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-600italic.woff2
rename to apps/web/src/assets/fonts/open-sans-v20-latin-600italic.woff2
diff --git a/apps/web/public/fonts/open-sans-v20-latin-700.woff b/apps/web/src/assets/fonts/open-sans-v20-latin-700.woff
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-700.woff
rename to apps/web/src/assets/fonts/open-sans-v20-latin-700.woff
diff --git a/apps/web/public/fonts/open-sans-v20-latin-700.woff2 b/apps/web/src/assets/fonts/open-sans-v20-latin-700.woff2
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-700.woff2
rename to apps/web/src/assets/fonts/open-sans-v20-latin-700.woff2
diff --git a/apps/web/public/fonts/open-sans-v20-latin-700italic.woff b/apps/web/src/assets/fonts/open-sans-v20-latin-700italic.woff
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-700italic.woff
rename to apps/web/src/assets/fonts/open-sans-v20-latin-700italic.woff
diff --git a/apps/web/public/fonts/open-sans-v20-latin-700italic.woff2 b/apps/web/src/assets/fonts/open-sans-v20-latin-700italic.woff2
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-700italic.woff2
rename to apps/web/src/assets/fonts/open-sans-v20-latin-700italic.woff2
diff --git a/apps/web/public/fonts/open-sans-v20-latin-italic.woff b/apps/web/src/assets/fonts/open-sans-v20-latin-italic.woff
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-italic.woff
rename to apps/web/src/assets/fonts/open-sans-v20-latin-italic.woff
diff --git a/apps/web/public/fonts/open-sans-v20-latin-italic.woff2 b/apps/web/src/assets/fonts/open-sans-v20-latin-italic.woff2
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-italic.woff2
rename to apps/web/src/assets/fonts/open-sans-v20-latin-italic.woff2
diff --git a/apps/web/public/fonts/open-sans-v20-latin-regular.woff b/apps/web/src/assets/fonts/open-sans-v20-latin-regular.woff
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-regular.woff
rename to apps/web/src/assets/fonts/open-sans-v20-latin-regular.woff
diff --git a/apps/web/public/fonts/open-sans-v20-latin-regular.woff2 b/apps/web/src/assets/fonts/open-sans-v20-latin-regular.woff2
similarity index 100%
rename from apps/web/public/fonts/open-sans-v20-latin-regular.woff2
rename to apps/web/src/assets/fonts/open-sans-v20-latin-regular.woff2
diff --git a/apps/web/src/common/db.js b/apps/web/src/common/db.js
index 7eb54d5ca..c4b7758a2 100644
--- a/apps/web/src/common/db.js
+++ b/apps/web/src/common/db.js
@@ -1,11 +1,3 @@
-import StorageInterface from "../interfaces/storage";
-import FS from "../interfaces/fs";
-import Config from "../utils/config";
-import http from "notes-core/utils/http";
-import { EV, EVENTS } from "notes-core/common";
-import { getCurrentHash, hashNavigate } from "../navigation";
-import { isTesting } from "../utils/platform";
-
global.HTMLParser = new DOMParser().parseFromString(
"",
"text/html"
@@ -16,67 +8,31 @@ global.HTMLParser = new DOMParser().parseFromString(
var db;
async function initializeDatabase() {
const { default: Database } = await import("notes-core/api");
- db = new Database(StorageInterface, EventSource, FS);
+ const { default: Storage } = await import("../interfaces/storage");
+ const { default: FS } = await import("../interfaces/fs");
+ db = new Database(Storage, EventSource, FS);
- if (isTesting()) {
- db.host({
- API_HOST: "https://api.notesnook.com",
- AUTH_HOST: "https://auth.streetwriters.co",
- SSE_HOST: "https://events.streetwriters.co",
- });
- } else {
- db.host({
- API_HOST: "http://localhost:5264",
- AUTH_HOST: "http://localhost:8264",
- SSE_HOST: "http://localhost:7264",
- });
- // db.host({
- // API_HOST: "http://192.168.10.29:5264",
- // AUTH_HOST: "http://192.168.10.29:8264",
- // SSE_HOST: "http://192.168.10.29:7264",
- // });
- }
+ // if (isTesting()) {
+ // db.host({
+ // API_HOST: "https://api.notesnook.com",
+ // AUTH_HOST: "https://auth.streetwriters.co",
+ // SSE_HOST: "https://events.streetwriters.co",
+ // });
+ // } else {
+ // db.host({
+ // API_HOST: "http://localhost:5264",
+ // AUTH_HOST: "http://localhost:8264",
+ // SSE_HOST: "http://localhost:7264",
+ // });
+ // // db.host({
+ // // API_HOST: "http://192.168.10.29:5264",
+ // // AUTH_HOST: "http://192.168.10.29:8264",
+ // // SSE_HOST: "http://192.168.10.29:7264",
+ // // });
+ // }
await db.init();
-
- if (!isAppHydrated() && !isTesting()) {
- try {
- loadDefaultNotes(db);
- } catch (e) {}
- }
return db;
}
export { db, initializeDatabase };
-
-function isAppHydrated() {
- return Config.get("hydrated", false);
-}
-
-function setAppHydrated() {
- return Config.set("hydrated", true);
-}
-
-async function loadDefaultNotes(db) {
- const notes = await http.get("/notes/index_v14.json");
- if (!notes) return;
- let autoOpenId;
- const hash = getCurrentHash().replaceAll("#", "");
- for (let note of notes) {
- const content = await http.get(note.webContent);
- let id = await db.notes.add({
- title: note.title,
- headline: note.headline,
- localOnly: true,
- content: { type: "tiny", data: content },
- });
- if (note.autoOpen) autoOpenId = id;
- }
-
- if (autoOpenId) {
- hashNavigate(`/notes/${autoOpenId}/edit`);
- if (hash) setTimeout(() => hashNavigate(hash), 100);
- }
- setAppHydrated();
- EV.publish(EVENTS.appRefreshRequested);
-}
diff --git a/apps/web/src/common/height-calculator.js b/apps/web/src/common/height-calculator.js
index 6432c13e5..0d2a223e2 100644
--- a/apps/web/src/common/height-calculator.js
+++ b/apps/web/src/common/height-calculator.js
@@ -1,6 +1,6 @@
const SINGLE_LINE_HEIGHT = 1.4;
const DEFAULT_FONT_SIZE = document.getElementById("p").clientHeight - 1;
-console.log("HEIGHT", DEFAULT_FONT_SIZE);
+
const MAX_HEIGHTS = {
note: SINGLE_LINE_HEIGHT * 7 * DEFAULT_FONT_SIZE,
notebook: SINGLE_LINE_HEIGHT * 7 * DEFAULT_FONT_SIZE,
diff --git a/apps/web/src/components/animated/index.js b/apps/web/src/components/animated/index.js
index 6ffd4f160..481f8b468 100644
--- a/apps/web/src/components/animated/index.js
+++ b/apps/web/src/components/animated/index.js
@@ -1,12 +1,9 @@
-import { m as motion } from "framer-motion";
+import { m } from "framer-motion";
import { Flex, Box, Image, Text } from "rebass";
import { Input } from "@rebass/forms";
-const Animated = {
- Flex: motion.custom(Flex),
- Box: motion.custom(Box),
- Image: motion.custom(Image),
- Text: motion.custom(Text),
- Input: motion.custom(Input),
-};
-export default Animated;
+export const AnimatedFlex = m(Flex);
+export const AnimatedBox = m(Box);
+export const AnimatedImage = m(Image);
+export const AnimatedText = m(Text);
+export const AnimatedInput = m(Input);
diff --git a/apps/web/src/components/cached-router/index.js b/apps/web/src/components/cached-router/index.js
index 7f628757a..e81b43795 100644
--- a/apps/web/src/components/cached-router/index.js
+++ b/apps/web/src/components/cached-router/index.js
@@ -1,6 +1,6 @@
import React, { useEffect } from "react";
import ReactDOM from "react-dom";
-import { NavigationEvents } from "../../navigation";
+import { getHomeRoute, NavigationEvents } from "../../navigation";
import useRoutes from "../../utils/use-routes";
import RouteContainer from "../route-container";
import ThemeProvider from "../theme-provider";
@@ -8,10 +8,12 @@ import routes from "../../navigation/routes";
var cache = {};
function CachedRouter() {
- const RouteResult = useRoutes(routes, { fallbackRoute: "/" });
+ const [RouteResult, location] = useRoutes(routes, {
+ fallbackRoute: getHomeRoute(),
+ });
useEffect(() => {
if (!RouteResult) return;
- NavigationEvents.publish("onNavigate", RouteResult);
+ NavigationEvents.publish("onNavigate", RouteResult, location);
window.currentViewType = RouteResult.type;
window.currentViewKey = RouteResult.key;
@@ -45,7 +47,7 @@ function CachedRouter() {
route
);
}
- }, [RouteResult]);
+ }, [RouteResult, location]);
return (
-
) : null}
-
+
diff --git a/apps/web/src/components/editor/toolbar.js b/apps/web/src/components/editor/toolbar.js
index 764ca1b63..5af9d2c14 100644
--- a/apps/web/src/components/editor/toolbar.js
+++ b/apps/web/src/components/editor/toolbar.js
@@ -6,7 +6,7 @@ import { useStore as useAppStore } from "../../stores/app-store";
import { useStore as useThemeStore } from "../../stores/theme-store";
import { useStore, store } from "../../stores/editor-store";
import { showToast } from "../../utils/toast";
-import Animated from "../animated";
+import { AnimatedInput } from "../animated";
import { showPublishView } from "../publish-view";
import { db } from "../../common/db";
@@ -163,7 +163,7 @@ function Toolbar(props) {
clearSession();
}}
/>
- {
if (groups.length <= 0) return;
@@ -165,7 +165,7 @@ function GroupHeader(props) {
)}
)}
-
+
);
}
export default GroupHeader;
diff --git a/apps/web/src/components/icons/index.js b/apps/web/src/components/icons/index.js
index ecf5eb6de..a9fc14e95 100644
--- a/apps/web/src/components/icons/index.js
+++ b/apps/web/src/components/icons/index.js
@@ -1,8 +1,101 @@
import React, { useState } from "react";
import MDIIcon from "@mdi/react";
-import * as Icons from "@mdi/js";
+import {
+ mdiPlus,
+ mdiHomeVariantOutline,
+ mdiMinus,
+ mdiBookOutline,
+ mdiNotebookOutline,
+ mdiArrowLeft,
+ mdiArrowRight,
+ mdiArrowDown,
+ mdiBookPlusMultipleOutline,
+ mdiBookmarkOutline,
+ mdiAlert,
+ mdiShieldOutline,
+ mdiLockOpenOutline,
+ mdiLockOutline,
+ mdiStar,
+ mdiStarOutline,
+ mdiCircle,
+ mdiCircleOutline,
+ mdiUpdate,
+ mdiCheck,
+ mdiClose,
+ mdiDotsVertical,
+ mdiTrashCanOutline,
+ mdiBookRemoveOutline,
+ mdiMagnify,
+ mdiMenu,
+ mdiLoginVariant,
+ mdiEmailAlertOutline,
+ mdiAccountOutline,
+ mdiLogoutVariant,
+ mdiSunglasses,
+ mdiGlasses,
+ mdiCogOutline,
+ mdiHomeOutline,
+ mdiRecycle,
+ mdiSync,
+ mdiLoading,
+ mdiExportVariant,
+ mdiArrowExpandDown,
+ mdiArrowTopRightThick,
+ mdiChevronLeft,
+ mdiChevronRight,
+ mdiPound,
+ mdiPinOutline,
+ mdiPin,
+ mdiWeatherNight,
+ mdiWeatherSunny,
+ mdiThemeLightDark,
+ mdiCheckCircle,
+ mdiLanguageMarkdownOutline,
+ mdiFilePdfOutline,
+ mdiLanguageHtml5,
+ mdiFormatTitle,
+ mdiAlertCircle,
+ mdiInformation,
+ mdiToggleSwitchOffOutline,
+ mdiToggleSwitchOutline,
+ mdiBackupRestore,
+ mdiCurrencyUsdCircleOutline,
+ mdiPencil,
+ mdiUndoVariant,
+ mdiRedoVariant,
+ mdiTune,
+ mdiChevronDown,
+ mdiChevronUp,
+ mdiSortAscending,
+ mdiSortDescending,
+ mdiEye,
+ mdiEyeOff,
+ mdiFullscreen,
+ mdiFullscreenExit,
+ mdiBullhorn,
+ mdiCloudUploadOutline,
+ mdiCloudCheckOutline,
+ mdiContentCopy,
+ mdiCheckboxMultipleMarkedCircleOutline,
+ mdiBookEditOutline,
+ mdiDeleteForeverOutline,
+ mdiTextBoxMultipleOutline,
+ mdiRocketLaunchOutline,
+ mdiShareVariantOutline,
+ mdiFormTextboxPassword,
+ mdiBomb,
+ mdiViewHeadline,
+ mdiViewSequentialOutline,
+ mdiEmailCheckOutline,
+ mdiDiscord,
+ mdiTwitter,
+ mdiReddit,
+ mdiFileOutline,
+ mdiImage,
+ mdiNoteOutline,
+} from "@mdi/js";
import { useTheme } from "emotion-theming";
-import Animated from "../animated";
+import { AnimatedFlex } from "../animated";
function Icon({ title, name, size = 24, color = "icon", stroke, rotate }) {
const theme = useTheme();
@@ -25,7 +118,7 @@ function createIcon(name, rotate = false) {
return function (props) {
const [isHovering, setIsHovering] = useState();
return (
-
-
+
);
};
}
-export const Plus = createIcon(Icons.mdiPlus);
-export const Note = createIcon(Icons.mdiHomeVariantOutline);
-export const Minus = createIcon(Icons.mdiMinus);
-export const Notebook = createIcon(Icons.mdiBookOutline);
-export const Notebook2 = createIcon(Icons.mdiNotebookOutline);
-export const ArrowLeft = createIcon(Icons.mdiArrowLeft);
-export const ArrowRight = createIcon(Icons.mdiArrowRight);
-export const ArrowDown = createIcon(Icons.mdiArrowDown);
-export const Move = createIcon(Icons.mdiBookPlusMultipleOutline);
-export const Topic = createIcon(Icons.mdiBookmarkOutline);
-export const Alert = createIcon(Icons.mdiAlert);
-export const Vault = createIcon(Icons.mdiShieldOutline);
-export const Unlock = createIcon(Icons.mdiLockOpenOutline);
-export const Lock = createIcon(Icons.mdiLockOutline);
-export const Star = createIcon(Icons.mdiStar);
-export const StarOutline = createIcon(Icons.mdiStarOutline);
-export const Circle = createIcon(Icons.mdiCircle);
-export const CircleEmpty = createIcon(Icons.mdiCircleOutline);
-export const Update = createIcon(Icons.mdiUpdate);
-export const Check = createIcon(Icons.mdiCheck);
-export const Cross = createIcon(Icons.mdiClose);
-export const MoreVertical = createIcon(Icons.mdiDotsVertical);
-export const Trash = createIcon(Icons.mdiTrashCanOutline);
-export const TopicRemove = createIcon(Icons.mdiBookRemoveOutline);
-export const Search = createIcon(Icons.mdiMagnify);
-export const Menu = createIcon(Icons.mdiMenu);
-export const Login = createIcon(Icons.mdiLoginVariant);
-export const Email = createIcon(Icons.mdiEmailAlertOutline);
-export const Signup = createIcon(Icons.mdiAccountOutline);
-export const Logout = createIcon(Icons.mdiLogoutVariant);
-export const FocusMode = createIcon(Icons.mdiSunglasses);
-export const NormalMode = createIcon(Icons.mdiGlasses);
-export const Settings = createIcon(Icons.mdiCogOutline);
-export const Home = createIcon(Icons.mdiHomeOutline);
-export const Restore = createIcon(Icons.mdiRecycle);
-export const Sync = createIcon(Icons.mdiSync);
-export const Loading = createIcon(Icons.mdiLoading, true);
-export const Export = createIcon(Icons.mdiExportVariant);
-export const AddToNotebook = createIcon(Icons.mdiBookPlusMultipleOutline);
-export const Expand = createIcon(Icons.mdiArrowExpandDown);
-export const Shortcut = createIcon(Icons.mdiArrowTopRightThick);
-
-/** Properties Icons */
-export const ChevronLeft = createIcon(Icons.mdiChevronLeft);
-export const ChevronRight = createIcon(Icons.mdiChevronRight);
-export const Close = createIcon(Icons.mdiClose);
-export const Tag = createIcon(Icons.mdiPound);
-export const Tag2 = createIcon(Icons.mdiPound);
-export const Pin = createIcon(Icons.mdiPinOutline);
-export const PinFilled = createIcon(Icons.mdiPin);
-
-/** Settings Icons */
-export const User = createIcon(Icons.mdiAccountOutline);
-export const DarkMode = createIcon(Icons.mdiWeatherNight);
-export const LightMode = createIcon(Icons.mdiWeatherSunny);
-export const Theme = createIcon(Icons.mdiThemeLightDark);
-export const Checkmark = createIcon(Icons.mdiCheck);
-export const CheckCircle = createIcon(Icons.mdiCheckCircle);
-
-export const Properties = createIcon(Icons.mdiDotsVertical);
-
-// FORMATS
-
-export const Markdown = createIcon(Icons.mdiLanguageMarkdownOutline);
-export const PDF = createIcon(Icons.mdiFilePdfOutline);
-export const HTML = createIcon(Icons.mdiLanguageHtml5);
-export const Text = createIcon(Icons.mdiFormatTitle);
-
-// TOAST
-export const Success = createIcon(Icons.mdiCheckCircle);
-export const Error = createIcon(Icons.mdiAlertCircle);
-export const Warn = createIcon(Icons.mdiAlert);
-export const Info = createIcon(Icons.mdiInformation);
-
-export const ToggleUnchecked = createIcon(Icons.mdiToggleSwitchOffOutline);
-export const ToggleChecked = createIcon(Icons.mdiToggleSwitchOutline);
-
-export const Backup = createIcon(Icons.mdiBackupRestore);
-export const Buy = createIcon(Icons.mdiCurrencyUsdCircleOutline);
-
-export const Edit = createIcon(Icons.mdiPencil);
-
-export const Undo = createIcon(Icons.mdiUndoVariant);
-export const Redo = createIcon(Icons.mdiRedoVariant);
-
-export const Filter = createIcon(Icons.mdiTune);
-
-export const ChevronDown = createIcon(Icons.mdiChevronDown);
-export const ChevronUp = createIcon(Icons.mdiChevronUp);
-
-export const SortAsc = createIcon(Icons.mdiSortAscending);
-export const SortDesc = createIcon(Icons.mdiSortDescending);
-
-export const PasswordInvisible = createIcon(Icons.mdiEye);
-export const PasswordVisible = createIcon(Icons.mdiEyeOff);
-
-export const Fullscreen = createIcon(Icons.mdiFullscreen);
-export const ExitFullscreen = createIcon(Icons.mdiFullscreenExit);
-
-export const Announcement = createIcon(Icons.mdiBullhorn);
-export const Publish = createIcon(Icons.mdiCloudUploadOutline);
-export const Published = createIcon(Icons.mdiCloudCheckOutline);
-
-export const Copy = createIcon(Icons.mdiContentCopy);
-
-export const Select = createIcon(Icons.mdiCheckboxMultipleMarkedCircleOutline);
-export const NotebookEdit = createIcon(Icons.mdiBookEditOutline);
-export const DeleteForver = createIcon(Icons.mdiDeleteForeverOutline);
-
-export const Monographs = createIcon(Icons.mdiTextBoxMultipleOutline);
-
-export const Rocket = createIcon(Icons.mdiRocketLaunchOutline);
-export const Share = createIcon(Icons.mdiShareVariantOutline);
-export const Password = createIcon(Icons.mdiFormTextboxPassword);
-export const Destruct = createIcon(Icons.mdiBomb);
-
-export const CompactView = createIcon(Icons.mdiViewHeadline);
-export const DetailedView = createIcon(Icons.mdiViewSequentialOutline);
-
-export const MailCheck = createIcon(Icons.mdiEmailCheckOutline);
-
-export const Discord = createIcon(Icons.mdiDiscord);
-export const Twitter = createIcon(Icons.mdiTwitter);
-export const Reddit = createIcon(Icons.mdiReddit);
-
-export const Dismiss = createIcon(Icons.mdiClose);
-
-export const File = createIcon(Icons.mdiFileOutline);
-export const Download = createIcon(Icons.mdiArrowDown);
-export const ImageDownload = createIcon(Icons.mdiImage);
+export const Plus = createIcon(mdiPlus);
+export const Note = createIcon(mdiNoteOutline);
+export const Minus = createIcon(mdiMinus);
+export const Notebook = createIcon(mdiBookOutline);
+export const Notebook2 = createIcon(mdiNotebookOutline);
+export const ArrowLeft = createIcon(mdiArrowLeft);
+export const ArrowRight = createIcon(mdiArrowRight);
+export const ArrowDown = createIcon(mdiArrowDown);
+export const Move = createIcon(mdiBookPlusMultipleOutline);
+export const Topic = createIcon(mdiBookmarkOutline);
+export const Alert = createIcon(mdiAlert);
+export const Vault = createIcon(mdiShieldOutline);
+export const Unlock = createIcon(mdiLockOpenOutline);
+export const Lock = createIcon(mdiLockOutline);
+export const Star = createIcon(mdiStar);
+export const StarOutline = createIcon(mdiStarOutline);
+export const Circle = createIcon(mdiCircle);
+export const CircleEmpty = createIcon(mdiCircleOutline);
+export const Update = createIcon(mdiUpdate);
+export const Check = createIcon(mdiCheck);
+export const Cross = createIcon(mdiClose);
+export const MoreVertical = createIcon(mdiDotsVertical);
+export const Trash = createIcon(mdiTrashCanOutline);
+export const TopicRemove = createIcon(mdiBookRemoveOutline);
+export const Search = createIcon(mdiMagnify);
+export const Menu = createIcon(mdiMenu);
+export const Login = createIcon(mdiLoginVariant);
+export const Email = createIcon(mdiEmailAlertOutline);
+export const Signup = createIcon(mdiAccountOutline);
+export const Logout = createIcon(mdiLogoutVariant);
+export const FocusMode = createIcon(mdiSunglasses);
+export const NormalMode = createIcon(mdiGlasses);
+export const Settings = createIcon(mdiCogOutline);
+export const Home = createIcon(mdiHomeOutline);
+export const Restore = createIcon(mdiRecycle);
+export const Sync = createIcon(mdiSync);
+export const Loading = createIcon(mdiLoading, true);
+export const Export = createIcon(mdiExportVariant);
+export const AddToNotebook = createIcon(mdiBookPlusMultipleOutline);
+export const Expand = createIcon(mdiArrowExpandDown);
+export const Shortcut = createIcon(mdiArrowTopRightThick);
+export const ChevronLeft = createIcon(mdiChevronLeft);
+export const ChevronRight = createIcon(mdiChevronRight);
+export const Close = createIcon(mdiClose);
+export const Tag = createIcon(mdiPound);
+export const Tag2 = createIcon(mdiPound);
+export const Pin = createIcon(mdiPinOutline);
+export const PinFilled = createIcon(mdiPin);
+export const User = createIcon(mdiAccountOutline);
+export const DarkMode = createIcon(mdiWeatherNight);
+export const LightMode = createIcon(mdiWeatherSunny);
+export const Theme = createIcon(mdiThemeLightDark);
+export const Checkmark = createIcon(mdiCheck);
+export const CheckCircle = createIcon(mdiCheckCircle);
+export const Properties = createIcon(mdiDotsVertical);
+export const Markdown = createIcon(mdiLanguageMarkdownOutline);
+export const PDF = createIcon(mdiFilePdfOutline);
+export const HTML = createIcon(mdiLanguageHtml5);
+export const Text = createIcon(mdiFormatTitle);
+export const Success = createIcon(mdiCheckCircle);
+export const Error = createIcon(mdiAlertCircle);
+export const Warn = createIcon(mdiAlert);
+export const Info = createIcon(mdiInformation);
+export const ToggleUnchecked = createIcon(mdiToggleSwitchOffOutline);
+export const ToggleChecked = createIcon(mdiToggleSwitchOutline);
+export const Backup = createIcon(mdiBackupRestore);
+export const Buy = createIcon(mdiCurrencyUsdCircleOutline);
+export const Edit = createIcon(mdiPencil);
+export const Undo = createIcon(mdiUndoVariant);
+export const Redo = createIcon(mdiRedoVariant);
+export const Filter = createIcon(mdiTune);
+export const ChevronDown = createIcon(mdiChevronDown);
+export const ChevronUp = createIcon(mdiChevronUp);
+export const SortAsc = createIcon(mdiSortAscending);
+export const SortDesc = createIcon(mdiSortDescending);
+export const PasswordInvisible = createIcon(mdiEye);
+export const PasswordVisible = createIcon(mdiEyeOff);
+export const Fullscreen = createIcon(mdiFullscreen);
+export const ExitFullscreen = createIcon(mdiFullscreenExit);
+export const Announcement = createIcon(mdiBullhorn);
+export const Publish = createIcon(mdiCloudUploadOutline);
+export const Published = createIcon(mdiCloudCheckOutline);
+export const Copy = createIcon(mdiContentCopy);
+export const Select = createIcon(mdiCheckboxMultipleMarkedCircleOutline);
+export const NotebookEdit = createIcon(mdiBookEditOutline);
+export const DeleteForver = createIcon(mdiDeleteForeverOutline);
+export const Monographs = createIcon(mdiTextBoxMultipleOutline);
+export const Rocket = createIcon(mdiRocketLaunchOutline);
+export const Share = createIcon(mdiShareVariantOutline);
+export const Password = createIcon(mdiFormTextboxPassword);
+export const Destruct = createIcon(mdiBomb);
+export const CompactView = createIcon(mdiViewHeadline);
+export const DetailedView = createIcon(mdiViewSequentialOutline);
+export const MailCheck = createIcon(mdiEmailCheckOutline);
+export const Discord = createIcon(mdiDiscord);
+export const Twitter = createIcon(mdiTwitter);
+export const Reddit = createIcon(mdiReddit);
+export const Dismiss = createIcon(mdiClose);
+export const File = createIcon(mdiFileOutline);
+export const Download = createIcon(mdiArrowDown);
+export const ImageDownload = createIcon(mdiImage);
diff --git a/apps/web/src/components/loader/index.js b/apps/web/src/components/loader/index.js
new file mode 100644
index 000000000..c6c5052ae
--- /dev/null
+++ b/apps/web/src/components/loader/index.js
@@ -0,0 +1,21 @@
+import { Flex, Text } from "rebass";
+import { Loading } from "../icons";
+
+export default function Loader({ title, text }) {
+ return (
+
+
+
+ {title}
+
+
+ {text}
+
+
+ );
+}
diff --git a/apps/web/src/components/menu/index.js b/apps/web/src/components/menu/index.js
index 006f0a1db..314511155 100644
--- a/apps/web/src/components/menu/index.js
+++ b/apps/web/src/components/menu/index.js
@@ -4,7 +4,7 @@ import React, { useEffect, useMemo } from "react";
import { Flex, Box, Text, Button } from "rebass";
import { useIsUserPremium } from "../../hooks/use-is-user-premium";
import useMobile from "../../utils/use-mobile";
-import Animated from "../animated";
+import { AnimatedFlex } from "../animated";
function Menu(props) {
const { menuItems, data, closeMenu, id, style, sx, state } = props;
@@ -193,7 +193,7 @@ function MobileMenuContainer({ style, id, state, title, children }) {
overflow="hidden"
sx={{ position: "relative" }}
>
-
{children}
-
+
);
}
diff --git a/apps/web/src/components/navigation-menu/index.js b/apps/web/src/components/navigation-menu/index.js
index c75db2fa9..fa8625949 100644
--- a/apps/web/src/components/navigation-menu/index.js
+++ b/apps/web/src/components/navigation-menu/index.js
@@ -1,16 +1,32 @@
-import React, { useCallback } from "react";
+import { useCallback } from "react";
import { Box, Flex } from "rebass";
-import { useStore as useAppStore } from "../../stores/app-store";
-import * as Icon from "../icons";
-import { useStore as useUserStore } from "../../stores/user-store";
-import { useStore as useThemeStore } from "../../stores/theme-store";
-import Animated from "../animated";
+import {
+ Note,
+ Notebook,
+ StarOutline,
+ Monographs,
+ Tag,
+ Trash,
+ Settings,
+ Notebook2,
+ Tag2,
+ Topic,
+ DarkMode,
+ LightMode,
+ Sync,
+ Login,
+ Circle,
+} from "../icons";
+import { AnimatedFlex } from "../animated";
import NavigationItem from "./navigation-item";
import { navigate } from "../../navigation";
import { db } from "../../common/db";
import useMobile from "../../utils/use-mobile";
-import { useLocation } from "wouter";
import { showRenameColorDialog } from "../../common/dialog-controller";
+import { useStore as useAppStore } from "../../stores/app-store";
+import { useStore as useUserStore } from "../../stores/user-store";
+import { useStore as useThemeStore } from "../../stores/theme-store";
+import useLocation from "../../hooks/use-location";
function shouldSelectNavItem(route, pin) {
if (pin.type === "notebook") {
@@ -23,31 +39,31 @@ function shouldSelectNavItem(route, pin) {
}
const routes = [
- { title: "Notes", path: "/", icon: Icon.Note },
+ { title: "Notes", path: "/notes", icon: Note },
{
title: "Notebooks",
path: "/notebooks",
- icon: Icon.Notebook,
+ icon: Notebook,
},
{
title: "Favorites",
path: "/favorites",
- icon: Icon.StarOutline,
+ icon: StarOutline,
},
- { title: "Tags", path: "/tags", icon: Icon.Tag },
+ { title: "Tags", path: "/tags", icon: Tag },
{
title: "Monographs",
path: "/monographs",
- icon: Icon.Monographs,
+ icon: Monographs,
},
- { title: "Trash", path: "/trash", icon: Icon.Trash },
+ { title: "Trash", path: "/trash", icon: Trash },
];
const bottomRoutes = [
{
title: "Settings",
path: "/settings",
- icon: Icon.Settings,
+ icon: Settings,
},
];
@@ -77,7 +93,7 @@ function NavigationMenu(props) {
);
return (
-
+
);
}
export default NavigationMenu;
diff --git a/apps/web/src/components/navigation-menu/index.lite.js b/apps/web/src/components/navigation-menu/index.lite.js
new file mode 100644
index 000000000..291861668
--- /dev/null
+++ b/apps/web/src/components/navigation-menu/index.lite.js
@@ -0,0 +1,190 @@
+import { Flex } from "rebass";
+import { useStore as useThemeStore } from "../../stores/theme-store";
+import { Button, Text } from "rebass";
+import useTablet from "../../utils/use-tablet";
+import {
+ Note,
+ Notebook,
+ StarOutline,
+ Monographs,
+ Tag,
+ Trash,
+ Settings,
+ DarkMode,
+ LightMode,
+ Sync,
+ Login,
+} from "../icons";
+import useLocation from "../../hooks/use-location";
+
+const routes = [
+ { title: "Notes", path: "/", icon: Note },
+ {
+ title: "Notebooks",
+ path: "/notebooks",
+ icon: Notebook,
+ },
+ {
+ title: "Favorites",
+ path: "/favorites",
+ icon: StarOutline,
+ },
+ { title: "Tags", path: "/tags", icon: Tag },
+ {
+ title: "Monographs",
+ path: "/monographs",
+ icon: Monographs,
+ },
+ { title: "Trash", path: "/trash", icon: Trash },
+];
+
+const bottomRoutes = [
+ {
+ title: "Settings",
+ path: "/settings",
+ icon: Settings,
+ },
+];
+
+const NAVIGATION_MENU_WIDTH = "10em";
+const NAVIGATION_MENU_TABLET_WIDTH = "4em";
+
+function NavigationMenu() {
+ const isLoggedIn = false;
+ const theme = useThemeStore((store) => store.theme);
+ const toggleNightMode = useThemeStore((store) => store.toggleNightMode);
+ const [location] = useLocation();
+
+ return (
+
+ );
+}
+export default NavigationMenu;
+
+function NavigationItem(props) {
+ const { icon: Icon, color, title, isLoading } = props;
+ const isTablet = useTablet();
+
+ return (
+
+ );
+}
diff --git a/apps/web/src/components/placeholders/favorites-placeholder.js b/apps/web/src/components/placeholders/favorites-placeholder.js
index c805341af..7e78c9a75 100644
--- a/apps/web/src/components/placeholders/favorites-placeholder.js
+++ b/apps/web/src/components/placeholders/favorites-placeholder.js
@@ -1,5 +1,5 @@
import React from "react";
-import { ReactComponent as Fav } from "../../assets/fav.svg";
+import Fav from "../../assets/fav.svg";
import Placeholder from "./index";
function FavoritesPlaceholder() {
diff --git a/apps/web/src/components/placeholders/index.js b/apps/web/src/components/placeholders/index.js
index 6e03278c2..99fcf7f08 100644
--- a/apps/web/src/components/placeholders/index.js
+++ b/apps/web/src/components/placeholders/index.js
@@ -1,5 +1,5 @@
import React, { useEffect } from "react";
-import { Button, Flex, Text } from "rebass";
+import { Button, Flex, Image, Text } from "rebass";
import { useStore } from "../../stores/theme-store";
import { changeSvgTheme } from "../../utils/css";
@@ -8,7 +8,7 @@ function Placeholder(props) {
useEffect(() => {
changeSvgTheme(accent);
}, [accent]);
- const { image: Image, text, callToAction } = props;
+ const { image: PlaceholderImage, text, callToAction } = props;
return (
<>
@@ -17,7 +17,7 @@ function Placeholder(props) {
alignSelf="stretch"
sx={{ position: "relative" }}
>
-
+
-
-
)}
-
+
>
);
}
diff --git a/apps/web/src/components/status-bar/index.js b/apps/web/src/components/status-bar/index.js
index ae251be7f..925dedf50 100644
--- a/apps/web/src/components/status-bar/index.js
+++ b/apps/web/src/components/status-bar/index.js
@@ -1,7 +1,7 @@
import React from "react";
import { Box, Button, Flex, Text } from "rebass";
import EditorFooter from "../editor/footer";
-import * as Icon from "../icons";
+import { Circle, Sync, Loading, Update } from "../icons";
import { useStore as useUserStore } from "../../stores/user-store";
import { useStore as useAppStore } from "../../stores/app-store";
import TimeAgo from "timeago-react";
@@ -43,7 +43,7 @@ function StatusBar() {
display="flex"
sx={{ alignItems: "center", justifyContent: "center" }}
>
-
@@ -58,7 +58,7 @@ function StatusBar() {
onClick={sync}
sx={{ alignItems: "center", justifyContent: "center" }}
>
-
+
{"Synced "}
{lastSynced ? (
@@ -76,7 +76,7 @@ function StatusBar() {
onClick={() => navigate("/login")}
sx={{ alignItems: "center", justifyContent: "center" }}
>
-
+
Not logged in
@@ -84,7 +84,7 @@ function StatusBar() {
)}
{processingStatuses?.map(({ key, status, progress }) => (
-
+
{progress ? `${progress}% ${status}` : status}
@@ -106,7 +106,7 @@ function StatusBar() {
}}
sx={{ alignItems: "center", justifyContent: "center" }}
>
-
+
+
+ );
+}
+
+export default StatusBar;
diff --git a/apps/web/src/hooks/use-database.js b/apps/web/src/hooks/use-database.js
new file mode 100644
index 000000000..d983a951b
--- /dev/null
+++ b/apps/web/src/hooks/use-database.js
@@ -0,0 +1,16 @@
+import { useEffect, useState } from "react";
+import { initializeDatabase } from "../common/db";
+
+export default function useDatabase() {
+ const [isAppLoaded, setIsAppLoaded] = useState(false);
+
+ useEffect(() => {
+ (async () => {
+ await import("../app.css");
+ await initializeDatabase();
+ setIsAppLoaded(true);
+ })();
+ }, []);
+
+ return [isAppLoaded];
+}
diff --git a/apps/web/src/hooks/use-location.js b/apps/web/src/hooks/use-location.js
new file mode 100644
index 000000000..073f9fce5
--- /dev/null
+++ b/apps/web/src/hooks/use-location.js
@@ -0,0 +1,18 @@
+const { useState, useEffect } = require("react");
+const { getCurrentPath, NavigationEvents } = require("../navigation");
+
+export default function useLocation() {
+ const [location, setLocation] = useState(getCurrentPath());
+ useEffect(() => {
+ const navigateEvent = NavigationEvents.subscribe(
+ "onNavigate",
+ (_, location) => {
+ setLocation(location);
+ }
+ );
+ return () => {
+ navigateEvent.unsubscribe();
+ };
+ }, []);
+ return [location];
+}
diff --git a/apps/web/src/hooks/use-slider.js b/apps/web/src/hooks/use-slider.js
index d1eb61ddb..095a582d8 100644
--- a/apps/web/src/hooks/use-slider.js
+++ b/apps/web/src/hooks/use-slider.js
@@ -1,7 +1,10 @@
import { useCallback, useEffect, useMemo, useRef } from "react";
-export default function useSlider({ initialIndex, onSliding, onChange }) {
- const ref = useRef();
+export default function useSlider(
+ sliderId,
+ { initialIndex, onSliding, onChange }
+) {
+ const ref = useRef(document.getElementById(sliderId));
const slides = useMemo(() => [], []);
useEffect(() => {
@@ -49,5 +52,5 @@ export default function useSlider({ initialIndex, onSliding, onChange }) {
[ref, slides]
);
- return [ref, slideToIndex];
+ return [slideToIndex];
}
diff --git a/apps/web/src/index.css b/apps/web/src/index.css
deleted file mode 100644
index 77812d68e..000000000
--- a/apps/web/src/index.css
+++ /dev/null
@@ -1,65 +0,0 @@
-html,
-body {
- font-size: 16px;
-}
-
-@media only screen and (max-width: 480px) {
- html,
- body {
- font-size: 18px;
- background-color: var(--background);
- }
-}
-
-:root,
-body,
-#root {
- margin: 0 !important;
- height: 100%;
- overflow: hidden;
-}
-
-* {
- font-family: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
- Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
-}
-
-@keyframes fadeUp {
- 0% {
- transform: translateY(500px);
- opacity: 0;
- }
- 80% {
- transform: translateY(0px);
- opacity: 0.7;
- }
- 100% {
- opacity: 1;
- }
-}
-
-/* svg {
- width: 1.5rem;
-} */
-
-.ReactModal__Overlay {
- opacity: 0;
- transition: opacity 200ms ease-in-out;
-}
-
-.ReactModal__Overlay--after-open {
- opacity: 1;
-}
-
-.ReactModal__Overlay--before-close {
- opacity: 0;
-}
-
-.slide {
- background-color: transparent !important;
-}
-
-.carousel.carousel-slider {
- display: flex;
- flex-direction: row;
-}
diff --git a/apps/web/src/index.js b/apps/web/src/index.js
index ce8f235db..dfe0092b9 100644
--- a/apps/web/src/index.js
+++ b/apps/web/src/index.js
@@ -1,46 +1,46 @@
-import "./commands";
-import React from "react";
-import { initializeDatabase } from "./common/db";
-import "./index.css";
+import { render } from "react-dom";
+import { getCurrentPath } from "./navigation";
import * as serviceWorker from "./serviceWorkerRegistration";
-import { loadTrackerScript } from "./utils/analytics";
-import Config from "./utils/config";
-import { isTesting } from "./utils/platform";
+if (process.env.REACT_APP_PLATFORM === "desktop") require("./commands");
-if (process.env.NODE_ENV === "production") {
- loadTrackerScript();
- console.log = () => {};
+const ROUTES = {
+ "/account/recovery": {
+ component: () => import("./views/recovery"),
+ props: {},
+ },
+ "/account/verified": {
+ component: () => import("./views/email-confirmed"),
+ props: {},
+ },
+ "/signup": {
+ component: () => import("./views/auth"),
+ props: { type: "signup" },
+ },
+ "/login": {
+ component: () => import("./views/auth"),
+ props: { type: "login" },
+ },
+ "/recover": {
+ component: () => import("./views/auth"),
+ props: { type: "recover" },
+ },
+ default: { component: () => import("./app"), props: {} },
+};
+
+function getRoute() {
+ const path = getCurrentPath();
+ return ROUTES[path] || ROUTES.default;
}
-const HOMEPAGE_ROUTE = { 1: "/notebooks", 2: "/favorites", 3: "/tags" };
-
-async function checkRedirects(db) {
- const isLoggedIn = !!(await db.user.getUser());
- if (window.location.pathname === "/") {
- const skipInitiation = Config.get("skipInitiation", false);
- const homepage = Config.get("homepage", 0);
- if (!isTesting() && !isLoggedIn && !skipInitiation)
- window.location.replace("/signup");
- else if (homepage) {
- const route = HOMEPAGE_ROUTE[homepage];
- window.location.replace(route);
+const route = getRoute();
+route.component().then(({ default: Component }) => {
+ render(
+ ,
+ document.getElementById("root"),
+ () => {
+ document.getElementById("splash").remove();
}
- }
-}
-
-initializeDatabase().then(async (db) => {
- await checkRedirects(db);
-
- import("react-dom").then(({ render }) => {
- import("./App").then(({ default: App }) => {
- render(, document.getElementById("root"), async () => {
- document.getElementById("splash").remove();
- import("react-modal").then(({ default: Modal }) => {
- Modal.setAppElement("#root");
- });
- });
- });
- });
+ );
});
// If you want your app to work offline and load faster, you can change
diff --git a/apps/web/src/interfaces/fs.js b/apps/web/src/interfaces/fs.js
index f4dd4fba6..ad1f4990d 100644
--- a/apps/web/src/interfaces/fs.js
+++ b/apps/web/src/interfaces/fs.js
@@ -122,7 +122,6 @@ async function hashStream(reader) {
}
async function readEncrypted(filename, key, cipherData) {
- console.log("Reading encrypted file", filename);
const fileHandle = await streamablefs.readFile(filename);
if (!fileHandle) {
console.error(`File not found. Filename: ${filename}`);
@@ -159,8 +158,6 @@ async function readEncrypted(filename, key, cipherData) {
}
async function uploadFile(filename, requestOptions) {
- console.log("Request to upload file", filename, requestOptions);
-
const fileHandle = await streamablefs.readFile(filename);
if (!fileHandle)
throw new Error(`File stream not found. Filename: ${filename}`);
@@ -261,7 +258,6 @@ function reportProgress(ev, { type, hash }) {
async function downloadFile(filename, requestOptions) {
const { url, headers, cancellationToken } = requestOptions;
- console.log("Request to download file", filename, url, headers);
if (await streamablefs.exists(filename)) return true;
try {
@@ -273,7 +269,6 @@ async function downloadFile(filename, requestOptions) {
reportProgress(ev, { type: "download", hash: filename }),
});
- console.log("File downloaded", filename, url, response);
if (!isSuccessStatusCode(response.status)) return false;
const distributor = new ChunkDistributor(ENCRYPTED_CHUNK_SIZE);
distributor.fill(new Uint8Array(response.data));
@@ -352,7 +347,6 @@ function cancellable(operation) {
return {
execute: () => operation(filename, requestOptions),
cancel: (message) => {
- console.log("Canceled", message);
source.cancel(message);
},
};
diff --git a/apps/web/src/navigation/index.js b/apps/web/src/navigation/index.js
index 2b6dae211..4c3d2e9fb 100644
--- a/apps/web/src/navigation/index.js
+++ b/apps/web/src/navigation/index.js
@@ -1,6 +1,6 @@
import { useState } from "react";
import EventManager from "notes-core/utils/eventmanager";
-// import { useCallback } from "react";
+import Config from "../utils/config";
export function navigate(url, replaceOrQuery, replace) {
if (typeof url !== "string") {
@@ -81,3 +81,13 @@ export function getCurrentHash() {
}
export const NavigationEvents = new EventManager();
+
+const HOMEPAGE_ROUTE = {
+ 0: "/notes",
+ 1: "/notebooks",
+ 2: "/favorites",
+ 3: "/tags",
+};
+export function getHomeRoute() {
+ return HOMEPAGE_ROUTE[Config.get("homepage", 0)];
+}
diff --git a/apps/web/src/navigation/rootroutes.js b/apps/web/src/navigation/rootroutes.js
deleted file mode 100644
index ff1fd5e94..000000000
--- a/apps/web/src/navigation/rootroutes.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from "react";
-import AccountRecovery from "../views/recovery";
-import EmailConfirmed from "../views/emailconfirmed";
-import Auth from "../views/auth";
-
-const rootroutes = {
- "/account/recovery": () => ({ component: }),
- "/account/verified": () => ({ component: }),
- "/signup": () => ({ component: }),
- "/login": () => ({ component: }),
- "/recover": () => ({ component: }),
-};
-
-export default rootroutes;
diff --git a/apps/web/src/navigation/routes.js b/apps/web/src/navigation/routes.js
index d69a9ba40..aade74832 100644
--- a/apps/web/src/navigation/routes.js
+++ b/apps/web/src/navigation/routes.js
@@ -15,7 +15,7 @@ import Monographs from "../views/monographs";
import { showToast } from "../utils/toast";
const routes = {
- "/": () => ({
+ "/notes": () => ({
key: "home",
type: "notes",
title: "Notes",
diff --git a/apps/web/src/stores/user-store.js b/apps/web/src/stores/user-store.js
index 67c61d9e0..ef6d2ace3 100644
--- a/apps/web/src/stores/user-store.js
+++ b/apps/web/src/stores/user-store.js
@@ -67,7 +67,6 @@ class UserStore extends BaseStore {
});
EV.subscribe(EVENTS.databaseSyncRequested, async () => {
- console.log("Sync requested.");
await appStore.sync(false);
});
diff --git a/apps/web/src/utils/use-routes.js b/apps/web/src/utils/use-routes.js
index 59d5a30cf..f13cd33cb 100644
--- a/apps/web/src/utils/use-routes.js
+++ b/apps/web/src/utils/use-routes.js
@@ -1,27 +1,27 @@
import { useLocation } from "wouter";
import makeMatcher from "wouter/matcher";
-import { navigate } from "../navigation";
-import { store as selectionStore } from "../stores/selection-store";
+import { navigate, getHomeRoute } from "../navigation";
export default function useRoutes(routes, options) {
const [location] = useLocation();
const matcher = makeMatcher();
- // TODO move this to an extension function
- if (selectionStore.get().isSelectionMode)
- selectionStore.toggleSelectionMode(false);
+ if (location === "/") navigate(getHomeRoute());
+
+ options?.hooks?.beforeNavigate(location);
for (var key in routes) {
const [match, params] = matcher(key, location);
if (match) {
const result = routes[key](params);
if (!result) break;
- return result;
+ return [result, location];
}
}
- if (!options) return;
+ if (!options) return [];
const { fallbackRoute } = options;
if (fallbackRoute) {
navigate(fallbackRoute);
}
+ return [];
}
diff --git a/apps/web/src/views/auth.js b/apps/web/src/views/auth.js
index 00ad77786..410d8e17d 100644
--- a/apps/web/src/views/auth.js
+++ b/apps/web/src/views/auth.js
@@ -1,12 +1,14 @@
import { useEffect, useState } from "react";
import { Box, Button, Flex, Text } from "rebass";
import ThemeProvider from "../components/theme-provider";
-import * as Icon from "../components/icons";
+import { CheckCircle, Loading, ArrowRight, Error } from "../components/icons";
import Field from "../components/field";
import { getQueryParams, navigate, useQueryParams } from "../navigation";
import { store as userstore } from "../stores/user-store";
import { db } from "../common/db";
import Config from "../utils/config";
+import useDatabase from "../hooks/use-database";
+import Loader from "../components/loader";
const features = [
{
@@ -90,7 +92,6 @@ const authTypes = {
>
),
onSubmit: async (form, onError) => {
- console.log(form);
if (form.password !== form.confirmPassword) {
onError("Passwords do not match.");
return;
@@ -162,6 +163,7 @@ function Auth(props) {
const [error, setError] = useState();
const [success, setSuccess] = useState();
const [featureIndex, setFeatureIndex] = useState(0);
+ const [isAppLoaded] = useDatabase();
const data = authTypes[type];
const feature = features[featureIndex];
@@ -188,7 +190,7 @@ function Auth(props) {
setSuccess();
if (authTypes[type].resetOnNavigate) {
const form = document.getElementById("authForm");
- form.reset();
+ form?.reset();
}
}, [type]);
@@ -211,7 +213,7 @@ function Auth(props) {
navigate("/");
}}
>
-
+
Go to app
@@ -262,7 +264,7 @@ function Auth(props) {
mt={4}
alignItems="center"
>
-
+
{feature.linkText}
@@ -285,151 +287,171 @@ function Auth(props) {
- {
- e.preventDefault();
- setIsSubmitting(true);
- const form = new FormData(e.target);
- const obj = Object.fromEntries(form.entries());
- obj.redirect = redirect;
- await data.onSubmit(
- obj,
- (error) => {
- setIsSubmitting(false);
- setError(error);
- },
- setSuccess
- );
- setIsSubmitting(false);
- }}
- >
-
- {data.title}
-
-
- {data.subtitle.text}{" "}
- {data.subtitle.action && (
-
- {data.subtitle.action.text}
-
- )}
-
-
- {data.labels.password && (
-
- )}
-
- {data.confirmPassword && (
-
- )}
-
- {data.supportsPasswordRecovery && (
-
- )}
-
- {data.secondaryAction && (
-
- )}
- {error && (
-
-
-
- {error}
-
-
- )}
- {success && (
-
-
-
- {success}
-
-
- )}
- {data.agreementText && (
-
- {data.agreementText}
+
+ {data.title}
- )}
-
+
+ {data.subtitle.text}{" "}
+ {data.subtitle.action && (
+
+ {data.subtitle.action.text}
+
+ )}
+
+
+ {data.labels.password && (
+
+ )}
+
+ {data.confirmPassword && (
+
+ )}
+
+ {data.supportsPasswordRecovery && (
+
+ )}
+
+ {data.secondaryAction && (
+
+ )}
+ {error && (
+
+
+
+ {error}
+
+
+ )}
+ {success && (
+
+
+
+ {success}
+
+
+ )}
+ {data.agreementText && (
+
+ {data.agreementText}
+
+ )}
+
+ ) : (
+
+ )}
diff --git a/apps/web/src/views/email-confirmed.js b/apps/web/src/views/email-confirmed.js
index 1af9d0755..38e80b2ab 100644
--- a/apps/web/src/views/email-confirmed.js
+++ b/apps/web/src/views/email-confirmed.js
@@ -1,3 +1,4 @@
+import "../app.css";
import { useEffect } from "react";
import { Flex, Text } from "rebass";
import ThemeProvider from "../components/theme-provider";
diff --git a/apps/web/src/views/recovery.js b/apps/web/src/views/recovery.js
index 8e627fe05..c379b6a49 100644
--- a/apps/web/src/views/recovery.js
+++ b/apps/web/src/views/recovery.js
@@ -10,6 +10,7 @@ import { useCallback } from "react";
import { showRecoveryKeyDialog } from "../common/dialog-controller";
import { createBackup } from "../common";
import Logo from "../assets/logo.svg";
+import useDatabase from "../hooks/use-database";
function navigate(path) {
window.location.href = path;
@@ -42,7 +43,9 @@ function useRecovery() {
}
function useAuthenticateUser({ code, userId, performAction }) {
+ const [isAppLoaded] = useDatabase();
useEffect(() => {
+ if (!isAppLoaded) return;
performAction({
message: "Authenticating. Please wait...",
error: "Failed to authenticate. Please try again.",
@@ -63,7 +66,7 @@ function useAuthenticateUser({ code, userId, performAction }) {
}
await db.user.fetchUser(true);
}
- }, [code, userId, performAction]);
+ }, [code, userId, performAction, isAppLoaded]);
}
const steps = [RecoveryKeyStep, BackupDataStep, NewPasswordStep, FinalStep];