diff --git a/apps/mobile/app/app.tsx b/apps/mobile/app/app.tsx index 9f439bcec..859889967 100644 --- a/apps/mobile/app/app.tsx +++ b/apps/mobile/app/app.tsx @@ -24,7 +24,7 @@ import { useThemeEngineStore } from "@notesnook/theme"; import React, { useEffect } from "react"; -import { Appearance, I18nManager, StatusBar } from "react-native"; +import { Appearance, I18nManager, Linking, StatusBar } from "react-native"; import "react-native-gesture-handler"; import { GestureHandlerRootView } from "react-native-gesture-handler"; import { SafeAreaProvider } from "react-native-safe-area-context"; @@ -43,7 +43,7 @@ import { changeSystemBarColors, useThemeStore } from "./stores/use-theme-store"; import { useUserStore } from "./stores/use-user-store"; import RNBootSplash from "react-native-bootsplash"; import AppLocked from "./components/app-lock"; - +import { useSettingStore } from "./stores/use-setting-store"; I18nManager.allowRTL(false); I18nManager.forceRTL(false); I18nManager.swapLeftAndRightInRTL(false); @@ -54,13 +54,18 @@ if (appLockEnabled || appLockMode !== "none") { RNBootSplash.hide({ fade: true }); +Linking.getInitialURL().then((url) => { + useSettingStore.setState({ + initialUrl: url + }); +}); const App = (props: { configureMode: "note-preview" }) => { useAppEvents(); //@ts-ignore globalThis["IS_MAIN_APP_RUNNING"] = true; useEffect(() => { - changeSystemBarColors(); SettingsService.onFirstLaunch(); + changeSystemBarColors(); setTimeout(async () => { await Notifications.get(); if (SettingsService.get().notifNotes) { diff --git a/apps/mobile/app/components/header/index.tsx b/apps/mobile/app/components/header/index.tsx index 5b64d97f3..41a9787b0 100644 --- a/apps/mobile/app/components/header/index.tsx +++ b/apps/mobile/app/components/header/index.tsx @@ -50,7 +50,7 @@ export const Header = ({ onLeftMenuButtonPress?: () => void; renderedInRoute?: RouteName; id?: string; - title: string; + title?: string; canGoBack?: boolean; onPressDefaultRightButton?: () => void; hasSearch?: boolean; @@ -114,7 +114,16 @@ export const Header = ({ onLeftButtonPress={onLeftMenuButtonPress} /> - {hasSearch ? ( + {!title ? ( + + ) : hasSearch ? ( {selectionMode ? `${selectedItemsList.length} selected` diff --git a/apps/mobile/app/hooks/use-actions.tsx b/apps/mobile/app/hooks/use-actions.tsx index ebc83e520..f52ad205e 100644 --- a/apps/mobile/app/hooks/use-actions.tsx +++ b/apps/mobile/app/hooks/use-actions.tsx @@ -709,26 +709,6 @@ export const useActions = ({ type: item.type } ); - - resetStoredState( - "app-home-navigtion-key", - isHomepage - ? undefined - : { - name: - item.type === "notebook" - ? "Notebook" - : item.type === "tag" - ? "TaggedNotes" - : item.type === "color" - ? "ColorNotes" - : undefined, - params: { - item: item, - id: item.id - } - } - ); } }); } diff --git a/apps/mobile/app/hooks/use-app-events.tsx b/apps/mobile/app/hooks/use-app-events.tsx index 62765f78b..7c572240d 100644 --- a/apps/mobile/app/hooks/use-app-events.tsx +++ b/apps/mobile/app/hooks/use-app-events.tsx @@ -85,7 +85,7 @@ import Notifications from "../services/notifications"; import PremiumService from "../services/premium"; import SettingsService from "../services/settings"; import Sync from "../services/sync"; -import { clearAllStores, initAfterSync, initialize } from "../stores"; +import { clearAllStores, initAfterSync } from "../stores"; import { refreshAllStores } from "../stores/create-db-collection-store"; import { useAttachmentStore } from "../stores/use-attachment-store"; import { useMessageStore } from "../stores/use-message-store"; @@ -159,7 +159,10 @@ const onUserSessionExpired = async () => { eSendEvent(eLoginSessionExpired); }; -const onAppOpenedFromURL = async (event: { url: string }) => { +const onAppOpenedFromURL = async (event: { + url: string; + isInitialUrl?: boolean; +}) => { const url = event.url; try { @@ -182,23 +185,34 @@ const onAppOpenedFromURL = async (event: { url: string }) => { fluidTabsRef.current?.goToPage("editor", false); } } - } else if (url.startsWith("https://app.notesnook.com/open_notebook?")) { + } else if ( + url.startsWith("https://app.notesnook.com/open_notebook?") && + !event.isInitialUrl + ) { const id = new URL(url).searchParams.get("id"); if (id) { const notebook = await db.notebooks.notebook(id); if (notebook) { Navigation.navigate("Notebook", { + id: notebook.id, + canGoBack: true, item: notebook }); } } - } else if (url.startsWith("https://app.notesnook.com/open_tag?")) { + } else if ( + url.startsWith("https://app.notesnook.com/open_tag?") && + !event.isInitialUrl + ) { const id = new URL(url).searchParams.get("id"); if (id) { const tag = await db.tags.tag(id); if (tag) { Navigation.navigate("TaggedNotes", { - item: tag + type: "tag", + id: tag.id, + item: tag, + canGoBack: true }); } } @@ -484,7 +498,10 @@ const initializeDatabase = async (password?: string) => { }; export const useAppEvents = () => { - const isAppLoading = useSettingStore((state) => state.isAppLoading); + const [isAppLoading, initialUrl] = useSettingStore((state) => [ + state.isAppLoading, + state.initialUrl + ]); const [setLastSynced, setUser, appLocked, syncing] = useUserStore((state) => [ state.setLastSynced, state.setUser, @@ -529,6 +546,15 @@ export const useAppEvents = () => { }; }, [isAppLoading, onSyncComplete]); + useEffect(() => { + if (initialUrl) { + onAppOpenedFromURL({ + url: initialUrl!, + isInitialUrl: true + }); + } + }, [initialUrl]); + const subscribeToPurchaseListeners = useCallback(async () => { if (Platform.OS === "android") { try { @@ -796,17 +822,6 @@ export const useAppEvents = () => { let sub: NativeEventSubscription; if (!isAppLoading && !appLocked) { - if (!refValues.current.initialUrl) { - Linking.getInitialURL().then((url) => { - if (url) { - refValues.current.initialUrl = url; - onAppOpenedFromURL({ - url: refValues.current.initialUrl! - }); - } - }); - } - setTimeout(() => { sub = AppState.addEventListener("change", onAppStateChanged); }, 1000); diff --git a/apps/mobile/app/navigation/navigation-stack.tsx b/apps/mobile/app/navigation/navigation-stack.tsx index 8b5d12a7c..9884182ee 100644 --- a/apps/mobile/app/navigation/navigation-stack.tsx +++ b/apps/mobile/app/navigation/navigation-stack.tsx @@ -31,8 +31,6 @@ import { useSettingStore } from "../stores/use-setting-store"; import { rootNavigatorRef } from "../utils/global-refs"; import Navigation from "../services/navigation"; import { isFeatureAvailable } from "@notesnook/common"; -import { useStoredValue } from "../hooks/use-stored-state"; -import { db } from "../common/database"; const RootStack = createNativeStackNavigator(); const AppStack = createNativeStackNavigator(); @@ -58,105 +56,102 @@ const AppNavigation = React.memo( () => { const { colors } = useThemeColors(); const homepageV2 = useSettingStore((state) => state.settings.homepageV2); - const home = useStoredValue( - "app-home-navigtion-key", - !homepageV2 || homepageV2.id === DEFAULT_HOME.name - ? DEFAULT_HOME - : undefined - ); const loading = useSettingStore((state) => state.isAppLoading); + const [home, setHome] = React.useState< + { name: string; params: any } | undefined + >(undefined); - if (!home.value && !homepageV2) { - home.value = DEFAULT_HOME; - } + React.useEffect(() => { + if (useSettingStore.getState().initialUrl) { + const url = useSettingStore.getState().initialUrl; + if (url?.startsWith("https://app.notesnook.com/open_notebook?")) { + const id = new URL(url).searchParams.get("id"); + if (id) { + setHome({ + name: "Notebook", + params: { + id: id + } + }); + return; + } + } else if (url?.startsWith("https://app.notesnook.com/open_tag?")) { + const id = new URL(url).searchParams.get("id"); + if (id) { + setHome({ + name: "TaggedNotes", + params: { + type: "tag", + id: id + } + }); + return; + } + } + } + + if (homepageV2) { + switch (homepageV2.type) { + case "notebook": { + setHome({ + name: "Notebook", + params: { + id: homepageV2.id + } + }); + return; + } + case "color": { + setHome({ + name: "ColoredNotes", + params: { + type: "color", + id: homepageV2.id + } + }); + return; + } + case "tag": { + setHome({ + name: "TaggedNotes", + params: { + type: "tag", + id: homepageV2.id + } + }); + return; + } + case "default": + setHome(DEFAULT_HOME); + return; + } + } else { + setHome(DEFAULT_HOME); + } + }, []); React.useEffect(() => { if (!homepageV2 || loading) return; (async () => { isFeatureAvailable("customHomepage").then((value) => { if (!value.isAllowed) { - home.value = DEFAULT_HOME; SettingsService.setProperty("homepageV2", undefined); } }); - - if (!home.value) { - switch (homepageV2.type) { - case "notebook": - { - const notebook = await db.notebooks.notebook(homepageV2.id); - if (notebook) { - home.value = { - name: "Notebook", - params: { - item: notebook, - id: notebook.id, - title: notebook.title - } - }; - return; - } - } - break; - case "color": { - const color = await db.colors.color(homepageV2.id); - if (color) { - home.value = { - name: "ColoredNotes", - params: { - item: color, - id: color.id, - title: color.title - } - }; - return; - } - - break; - } - case "tag": { - const tag = await db.tags.tag(homepageV2.id); - if (tag) { - home.value = { - name: "TaggedNotes", - params: { - item: tag, - id: tag.id, - title: tag.title - } - }; - return; - } - break; - } - case "default": - { - home.value = DEFAULT_HOME; - } - return; - } - - home.value = undefined; - setTimeout(() => { - home.value = DEFAULT_HOME; - }); - } })(); - }, [homepageV2, loading, home.value]); + }, [homepageV2, loading]); React.useEffect(() => { if (!home) return; + useNavigationStore.getState().update(home?.name as keyof RouteParams); useNavigationStore .getState() - .update(home.value?.name as keyof RouteParams); - useNavigationStore - .getState() - .setFocusedRouteId(home.value?.params?.id || home.value?.name); + .setFocusedRouteId(home?.params?.id || home?.name); }, [home]); - return !home.value ? null : ( + return !home ? null : ( @@ -209,7 +204,7 @@ const AppNavigation = React.memo( return ColoredNotes; }} initialParams={ - home.value?.name === "ColoredNotes" ? home.value?.params : undefined + home?.name === "ColoredNotes" ? home?.params : undefined } /> @@ -244,9 +239,7 @@ const AppNavigation = React.memo( Notebook = Notebook || require("../screens/notebook").default; return Notebook; }} - initialParams={ - home.value?.name === "Notebook" ? home.value?.params : undefined - } + initialParams={home?.name === "Notebook" ? home?.params : undefined} /> ) => { const [notes, setNotes] = useState>(); const params = useRef(route?.params); const isAppLoading = useSettingStore((state) => state.isAppLoading); + const [notebook, setNotebook] = useState( + params.current.item + ); const [loading, setLoading] = useState(true); const updateOnFocus = useRef(false); const [breadcrumbs, setBreadcrumbs] = useState< @@ -75,10 +77,10 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => { }); const syncWithNavigation = React.useCallback(() => { - useNavigationStore.getState().setFocusedRouteId(params?.current?.item?.id); + useNavigationStore.getState().setFocusedRouteId(params?.current?.id); setOnFirstSave({ type: "notebook", - id: params.current.item.id + id: params.current.id }); }, []); @@ -86,23 +88,20 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => { async (data?: NotebookScreenParams) => { if (useSettingStore.getState().isAppLoading) return; if ( - useNavigationStore.getState().focusedRouteId !== - params.current.item.id && + useNavigationStore.getState().focusedRouteId !== params.current.id && !data ) { updateOnFocus.current = true; return; } - if (data?.item?.id && params.current.item?.id !== data?.item?.id) { - const nextRootNotebookId = await findRootNotebookId(data?.item?.id); - const currentNotebookRoot = await findRootNotebookId( - params.current.item.id - ); + if (data?.id && params.current?.id !== data?.id) { + const nextRootNotebookId = await findRootNotebookId(data?.id); + const currentNotebookRoot = await findRootNotebookId(params.current.id); if ( nextRootNotebookId !== currentNotebookRoot || - nextRootNotebookId === params.current?.item?.id + nextRootNotebookId === params.current?.id ) { // Never update notebook in route if root is different or if the root is current notebook. return; @@ -112,14 +111,13 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => { if (data) params.current = data; try { - const notebook = await db.notebooks?.notebook( - params?.current?.item?.id - ); - + const notebook = await db.notebooks?.notebook(params?.current?.id); + setNotebook(notebook); + params.current.item = notebook; if (notebook) { const breadcrumbs = await db.notebooks.breadcrumbs(notebook.id); setBreadcrumbs(breadcrumbs.slice(0, breadcrumbs.length - 1)); - params.current.item = notebook; + params.current.id = notebook.id; const notes = await db.relations .from(notebook, "note") .selector.grouped(db.settings.getGroupOptions("notes")); @@ -160,29 +158,27 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => { <>
{ - Properties.present(params.current.item); + Properties.present(notebook); } }} hasSearch={true} onSearch={() => { - const selector = db.relations.from( - params.current.item, - "note" - ).selector; + if (!notebook) return; + const selector = db.relations.from(notebook, "note").selector; Navigation.push("Search", { - placeholder: strings.searchInRoute(params.current.item?.title), + placeholder: strings.searchInRoute(notebook?.title), type: "note", - title: params.current.item?.title, + title: notebook?.title, route: route.name, items: selector }); }} - id={params.current.item?.id} + id={notebook?.id} /> @@ -192,19 +188,19 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => { onRefresh={() => { onRequestUpdate(); }} - id={params.current.item?.id} + id={params.current?.id} renderedInRoute="Notebook" - headerTitle={params.current.item.title} + headerTitle={notebook?.title} loading={loading} CustomLisHeader={ } placeholder={{ - title: params.current.item?.title, + title: notebook?.title!, paragraph: strings.notesEmpty(), button: strings.addFirstNote(), action: openEditor, @@ -225,7 +221,8 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => { testID="notebookTreeSheet" size="small" onPress={() => { - Notebooks.present(params.current.item); + if (!notebook) return; + Notebooks.present(notebook); }} style={{ position: "relative", @@ -246,7 +243,7 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => { /> { const { currentRoute, focusedRouteId } = useNavigationStore.getState(); if (currentRoute === "Notebooks") { Navigation.push("Notebook", { + id: item.id, item: item, canGoBack }); @@ -276,22 +274,24 @@ NotebookScreen.navigate = async (item: Notebook, canGoBack?: boolean) => { // Update the route in place instead eSendEvent(eUpdateNotebookRoute, { - item: item, - title: item.title, - canGoBack: canGoBack + id: item.id, + canGoBack: canGoBack, + item: item }); } else { // Push a new route Navigation.push("Notebook", { - item: item, - canGoBack + id: item.id, + canGoBack, + item: item }); } } else { // Push a new route anyways Navigation.push("Notebook", { - item: item, - canGoBack + id: item.id, + canGoBack, + item: item }); } }; diff --git a/apps/mobile/app/screens/notes/colored.tsx b/apps/mobile/app/screens/notes/colored.tsx index 771289e3d..3f727b7d7 100644 --- a/apps/mobile/app/screens/notes/colored.tsx +++ b/apps/mobile/app/screens/notes/colored.tsx @@ -25,7 +25,7 @@ import Navigation, { NavigationProps } from "../../services/navigation"; import useNavigationStore, { NotesScreenParams } from "../../stores/use-navigation-store"; -import { PLACEHOLDER_DATA, openEditor, toCamelCase } from "./common"; +import { PLACEHOLDER_DATA, openEditor } from "./common"; export const ColoredNotes = ({ navigation, route @@ -45,11 +45,13 @@ export const ColoredNotes = ({ ColoredNotes.get = async (params: NotesScreenParams, grouped = true) => { if (!grouped) { - return await db.relations.from(params.item, "note").resolve(); + return await db.relations + .from({ id: params.id, type: "color" }, "note") + .resolve(); } return await db.relations - .from(params.item, "note") + .from({ id: params.id, type: "color" }, "note") .selector.grouped(db.settings.getGroupOptions("notes")); }; @@ -63,8 +65,10 @@ ColoredNotes.navigate = (item: Color, canGoBack: boolean) => { } Navigation.push<"ColoredNotes">("ColoredNotes", { - item: item, - canGoBack + type: "color", + id: item.id, + canGoBack, + item: item }); }; diff --git a/apps/mobile/app/screens/notes/index.tsx b/apps/mobile/app/screens/notes/index.tsx index bc243054a..99d75a4ee 100644 --- a/apps/mobile/app/screens/notes/index.tsx +++ b/apps/mobile/app/screens/notes/index.tsx @@ -18,7 +18,7 @@ along with this program. If not, see . */ import { resolveItems } from "@notesnook/common"; -import { VirtualizedGrouping } from "@notesnook/core"; +import { Tag, VirtualizedGrouping } from "@notesnook/core"; import { Color, Note } from "@notesnook/core"; import React, { useEffect, useRef, useState } from "react"; import { db } from "../../common/database"; @@ -76,14 +76,12 @@ const NotesPage = ({ const [notes, setNotes] = useState>(); const [loadingNotes, setLoadingNotes] = useState(true); const isMonograph = route.name === "Monographs"; - const title = - params.current?.item.type === "tag" - ? "#" + params.current?.item.title - : params.current?.item.title; + const [item, setItem] = useState( + params.current.item + ); + const title = item?.type === "tag" ? "#" + item?.title : item?.title; const accentColor = - route.name === "ColoredNotes" - ? (params.current?.item as Color)?.colorCode - : undefined; + route.name === "ColoredNotes" ? (item as Color)?.colorCode : undefined; const updateOnFocus = useRef(false); const isAppLoading = useSettingStore((state) => state.isAppLoading); const isFocused = useNavigationFocus(navigation, { @@ -107,31 +105,30 @@ const NotesPage = ({ }); const syncWithNavigation = React.useCallback(() => { - const { item } = params.current; - useNavigationStore - .getState() - .setFocusedRouteId(params?.current?.item?.id || route.name); + const { id } = params.current; + useNavigationStore.getState().setFocusedRouteId(id || route.name); !isMonograph && setOnFirstSave({ type: getItemType(route.name), - id: item.id + id: id }); }, [isMonograph, route.name]); const onRequestUpdate = React.useCallback( async (data?: NotesScreenParams) => { if (useSettingStore.getState().isAppLoading) return; + if ( - params.current.item.id && - useNavigationStore.getState().focusedRouteId !== - params.current.item.id && + params.current.id && + useNavigationStore.getState().focusedRouteId !== params.current.id && !data ) { updateOnFocus.current = false; return; } - const isNew = data && data?.item?.id !== params.current?.item?.id; + + const isNew = data && data?.id !== params.current?.id; if (data) params.current = data; try { @@ -142,9 +139,9 @@ const NotesPage = ({ )) as VirtualizedGrouping; if (route.name === "TaggedNotes" || route.name === "ColoredNotes") { - const item = await (db as any)[params.current.item.type + "s"][ - params.current.item.type - ](params.current.item.id); + const item = await (db as any)[params.current.type + "s"][ + params.current.type + ](params.current.id); if (!item) { if (rootNavigatorRef.canGoBack()) { @@ -154,7 +151,7 @@ const NotesPage = ({ } return; } - + setItem(item); params.current.item = item; } @@ -173,15 +170,7 @@ const NotesPage = ({ useEffect(() => { if (isAppLoading) return; if (loadingNotes) { - get(params.current, true) - .then(async (items) => { - setNotes(items as VirtualizedGrouping); - await (items as VirtualizedGrouping).item(0, resolveItems); - setLoadingNotes(false); - }) - .catch((e) => { - setLoadingNotes(false); - }); + onRequestUpdate(params.current); } }, [loadingNotes, get, isAppLoading]); @@ -202,19 +191,18 @@ const NotesPage = ({ } canGoBack={params?.current?.canGoBack} hasSearch={true} - id={ - route.name === "Monographs" ? "Monographs" : params?.current.item?.id - } + id={route.name === "Monographs" ? "Monographs" : params?.current?.id} onSearch={() => { + if (!item) return; const selector = route.name === "Monographs" ? db.monographs.all - : db.relations.from(params.current.item, "note").selector; + : db.relations.from(item, "note").selector; Navigation.push("Search", { placeholder: strings.searchInRoute(title || route.name), type: "note", - title: title, + title: title!, route: route.name, items: selector }); @@ -229,7 +217,7 @@ const NotesPage = ({ onRefresh={onRequestUpdate} loading={false} renderedInRoute={route.name} - id={params.current.item?.id} + id={params.current?.id} headerTitle={title || "Monographs"} customAccentColor={accentColor} placeholder={placeholder} @@ -246,7 +234,7 @@ const NotesPage = ({ ) : null} { Monographs.navigate = (canGoBack?: boolean) => { Navigation.navigate<"Monographs">("Monographs", { - item: { type: "monograph" } as any, + type: "monograph", + id: "monograph", canGoBack: canGoBack as boolean }); }; diff --git a/apps/mobile/app/screens/notes/tagged.tsx b/apps/mobile/app/screens/notes/tagged.tsx index b0d89ac44..5ad689407 100644 --- a/apps/mobile/app/screens/notes/tagged.tsx +++ b/apps/mobile/app/screens/notes/tagged.tsx @@ -46,11 +46,13 @@ export const TaggedNotes = ({ TaggedNotes.get = async (params: NotesScreenParams, grouped = true) => { if (!grouped) { - return await db.relations.from(params.item, "note").resolve(); + return await db.relations + .from({ id: params.id, type: "tag" }, "note") + .resolve(); } return await db.relations - .from(params.item, "note") + .from({ id: params.id, type: "tag" }, "note") .selector.grouped(db.settings.getGroupOptions("notes")); }; @@ -64,8 +66,10 @@ TaggedNotes.navigate = (item: Tag, canGoBack?: boolean) => { } Navigation.push<"TaggedNotes">("TaggedNotes", { - item: item, - canGoBack + id: item.id, + type: "tag", + canGoBack, + item: item }); }; diff --git a/apps/mobile/app/stores/use-navigation-store.ts b/apps/mobile/app/stores/use-navigation-store.ts index a385725b3..08984bce8 100644 --- a/apps/mobile/app/stores/use-navigation-store.ts +++ b/apps/mobile/app/stores/use-navigation-store.ts @@ -25,8 +25,7 @@ import { Note, Notebook, Reminder, - Tag, - TrashItem + Tag } from "@notesnook/core"; import { ParamListBase } from "@react-navigation/core"; import { create } from "zustand"; @@ -36,12 +35,15 @@ export type GenericRouteParam = { }; export type NotebookScreenParams = { - item: Notebook; + id: string; + item?: Notebook; canGoBack?: boolean; }; export type NotesScreenParams = { - item: Note | Notebook | Tag | Color | TrashItem | Reminder; + type: "tag" | "color" | "monograph"; + id: string; + item?: Tag | Color; canGoBack?: boolean; }; diff --git a/apps/mobile/app/stores/use-setting-store.ts b/apps/mobile/app/stores/use-setting-store.ts index bc17219a0..232ab903d 100644 --- a/apps/mobile/app/stores/use-setting-store.ts +++ b/apps/mobile/app/stores/use-setting-store.ts @@ -136,6 +136,7 @@ export interface SettingStore { dateFormat: string; dbPassword?: string; isOldAppLock: () => boolean; + initialUrl: string | null; } const { width, height } = Dimensions.get("window"); @@ -236,5 +237,6 @@ export const useSettingStore = create((set, get) => ({ }, insets: initialWindowMetrics?.insets ? initialWindowMetrics.insets - : { top: 0, right: 0, left: 0, bottom: 0 } + : { top: 0, right: 0, left: 0, bottom: 0 }, + initialUrl: null }));