diff --git a/apps/mobile/app/app.tsx b/apps/mobile/app/app.tsx index 1fa18701b..e19c0256a 100644 --- a/apps/mobile/app/app.tsx +++ b/apps/mobile/app/app.tsx @@ -25,7 +25,6 @@ import { I18nManager, View } from "react-native"; import "react-native-gesture-handler"; import { GestureHandlerRootView } from "react-native-gesture-handler"; import { SafeAreaProvider } from "react-native-safe-area-context"; -import { initializeLogger } from "./common/database/logger"; import AppLockedOverlay from "./components/app-lock-overlay"; import { withErrorBoundry } from "./components/exception-handler"; import GlobalSafeAreaProvider from "./components/globalsafearea"; @@ -41,33 +40,24 @@ import { useUserStore } from "./stores/use-user-store"; I18nManager.allowRTL(false); I18nManager.forceRTL(false); I18nManager.swapLeftAndRightInRTL(false); +const { appLockEnabled, appLockMode } = SettingsService.get(); +if (appLockEnabled || appLockMode !== "none") { + useUserStore.getState().lockApp(true); +} const App = () => { - const init = useAppEvents(); + useAppEvents(); + //@ts-ignore + globalThis["IS_MAIN_APP_RUNNING"] = true; useEffect(() => { - initializeLogger() - .catch((e) => { - console.log(e); - }) - .finally(() => { - const { appLockEnabled, appLockMode } = SettingsService.get(); - if (appLockEnabled || appLockMode !== "none") { - useUserStore.getState().lockApp(true); - } - - //@ts-ignore - globalThis["IS_MAIN_APP_RUNNING"] = true; - init(); - setTimeout(async () => { - SettingsService.onFirstLaunch(); - await Notifications.get(); - if (SettingsService.get().notifNotes) { - Notifications.pinQuickNote(true); - } - TipManager.init(); - }, 100); - }); - // eslint-disable-next-line react-hooks/exhaustive-deps + SettingsService.onFirstLaunch(); + setTimeout(async () => { + await Notifications.get(); + if (SettingsService.get().notifNotes) { + Notifications.pinQuickNote(true); + } + TipManager.init(); + }, 100); }, []); return ( { + if (loggerLoaded) return; await initialize({ dialect: (name) => ({ createDriver: () => { @@ -37,6 +39,7 @@ const initializeLogger = async () => { journalMode: Platform.OS === "ios" ? "DELETE" : "WAL" }); setLogger(); + loggerLoaded = true; }; export { initializeLogger }; diff --git a/apps/mobile/app/components/app-lock-overlay/index.tsx b/apps/mobile/app/components/app-lock-overlay/index.tsx index 577bd7eb4..2d6aaa19a 100644 --- a/apps/mobile/app/components/app-lock-overlay/index.tsx +++ b/apps/mobile/app/components/app-lock-overlay/index.tsx @@ -203,6 +203,8 @@ const AppLockedOverlay = () => { contentContainerStyle={{ justifyContent: "center" }} + keyboardDismissMode="interactive" + keyboardShouldPersistTaps="handled" > { const { disableSync, disableAutoSync } = SettingsService.get(); @@ -280,8 +281,108 @@ const onSubscriptionError = async (error: RNIap.PurchaseError) => { const SodiumEventEmitter = new NativeEventEmitter(NativeModules.Sodium); +const doAppLoadActions = async () => { + if (SettingsService.get().sessionExpired) { + eSendEvent(eLoginSessionExpired); + return; + } + notifee.setBadgeCount(0); + + if (!(await db.user.getUser())) { + setLoginMessage(); + return; + } + + await useMessageStore.getState().setAnnouncement(); + if (NewFeature.present()) return; + if (await checkAppUpdateAvailable()) return; + if (await checkForRateAppRequest()) return; + if (await PremiumService.getRemainingTrialDaysStatus()) return; + if (SettingsService.get().introCompleted) { + useMessageStore.subscribe((state) => { + const dialogs = state.dialogs; + if (dialogs.length > 0) { + eSendEvent(eOpenAnnouncementDialog, dialogs[0]); + } + }); + } +}; + +const checkAppUpdateAvailable = async () => { + if (__DEV__ || Config.isTesting === "true" || Config.FDROID_BUILD || BETA) + return; + try { + const version = + Config.GITHUB_RELEASE === "true" + ? await getGithubVersion() + : await checkVersion(); + if (!version || !version?.needsUpdate) return false; + + setUpdateAvailableMessage(version); + return true; + } catch (e) { + return false; + } +}; + +const checkForRateAppRequest = async () => { + const rateApp = SettingsService.get().rateApp as number; + if ( + rateApp && + rateApp < Date.now() && + !useMessageStore.getState().message?.visible + ) { + setRateAppMessage(); + return false; + } + return false; +}; + +const IsDatabaseMigrationRequired = () => { + if (!db.migrations.required() || useUserStore.getState().appLocked) + return false; + + presentSheet({ + component: , + onClose: () => { + if (!db.migrations.required()) { + initializeDatabase(); + } + }, + disableClosing: true + }); + return true; +}; + +const initializeDatabase = async (password?: string) => { + if (useUserStore.getState().appLocked) return; + if (!db.isInitialized) { + RNBootSplash.hide({ fade: true }); + DatabaseLogger.info("Initializing database"); + try { + await setupDatabase(password); + await db.init(); + } catch (e) { + DatabaseLogger.error(e as Error); + ToastManager.error(e as Error, "Error initializing database", "global"); + } + } + + if (IsDatabaseMigrationRequired()) return; + + if (db.isInitialized) { + Notifications.setupReminders(true); + if (SettingsService.get().notifNotes) { + Notifications.pinQuickNote(false); + } + useSettingStore.getState().setAppLoading(false); + DatabaseLogger.info("Database initialized"); + } + Walkthrough.init(); +}; + export const useAppEvents = () => { - const loading = useSettingStore((state) => state.isAppLoading); + const isAppLoading = useSettingStore((state) => state.isAppLoading); const [setLastSynced, setUser, appLocked, syncing] = useUserStore((state) => [ state.setLastSynced, state.setUser, @@ -312,7 +413,7 @@ export const useAppEvents = () => { }, [setLastSynced]); useEffect(() => { - if (loading) return; + if (isAppLoading) return; let subscriptions: EventManagerSubscription[] = []; const eventManager = db.eventManager; @@ -327,7 +428,7 @@ export const useAppEvents = () => { return () => { subscriptions.forEach((sub) => sub?.unsubscribe?.()); }; - }, [loading, onSyncComplete]); + }, [isAppLoading, onSyncComplete]); const subscribeToPurchaseListeners = useCallback(async () => { if (Platform.OS === "android") { @@ -572,7 +673,7 @@ export const useAppEvents = () => { }); } let sub: NativeEventSubscription; - if (!loading && !appLocked) { + if (!isAppLoading && !appLocked) { setTimeout(() => { sub = AppState.addEventListener("change", onAppStateChanged); if ( @@ -594,7 +695,7 @@ export const useAppEvents = () => { sub?.remove(); unsubscribePurchaseListeners(); }; - }, [loading, appLocked, checkAutoBackup]); + }, [isAppLoading, appLocked, checkAutoBackup]); useEffect(() => { if (!appLocked && !syncing && refValues.current.backupDidWait) { @@ -643,127 +744,22 @@ export const useAppEvents = () => { } useEffect(() => { - if (!loading) { + if (!isAppLoading) { onUserUpdated(); doAppLoadActions(); } - }, [loading, onUserUpdated]); - - const initializeDatabase = useCallback(async (password?: string) => { - const IsDatabaseMigrationRequired = () => { - if (!db.migrations.required() || useUserStore.getState().appLocked) - return false; - - presentSheet({ - component: , - onClose: () => { - if (!db.migrations.required()) { - initializeDatabase(); - } - }, - disableClosing: true - }); - return true; - }; - - if (useUserStore.getState().appLocked) return; - if (!db.isInitialized) { - RNBootSplash.hide({ fade: true }); - DatabaseLogger.info("Initializing database"); - try { - await setupDatabase(password); - await db.init(); - } catch (e) { - DatabaseLogger.error(e as Error); - ToastManager.error(e as Error, "Error initializing database", "global"); - } - } - - if (IsDatabaseMigrationRequired()) return; - - if (db.isInitialized) { - Notifications.setupReminders(true); - if (SettingsService.get().notifNotes) { - Notifications.pinQuickNote(false); - } - useSettingStore.getState().setAppLoading(false); - DatabaseLogger.info("Database initialized"); - } - Walkthrough.init(); - }, []); + }, [isAppLoading, onUserUpdated]); useEffect(() => { - let sub: () => void; - if (appLocked) { - const sub = useUserStore.subscribe((state) => { - if (!state.appLocked && useSettingStore.getState().isAppLoading) { - console.log("DB initialized"); + if (!appLocked && isAppLoading) { + initializeLogger() + .catch((e) => { + console.log(e); + }) + .finally(() => { + //@ts-ignore initializeDatabase(); - sub(); - } - }); + }); } - return () => { - sub?.(); - }; - }, [appLocked, initializeDatabase]); - - return initializeDatabase; -}; - -const doAppLoadActions = async () => { - if (SettingsService.get().sessionExpired) { - eSendEvent(eLoginSessionExpired); - return; - } - notifee.setBadgeCount(0); - - if (!(await db.user.getUser())) { - setLoginMessage(); - return; - } - - await useMessageStore.getState().setAnnouncement(); - if (NewFeature.present()) return; - if (await checkAppUpdateAvailable()) return; - if (await checkForRateAppRequest()) return; - if (await PremiumService.getRemainingTrialDaysStatus()) return; - if (SettingsService.get().introCompleted) { - useMessageStore.subscribe((state) => { - const dialogs = state.dialogs; - if (dialogs.length > 0) { - eSendEvent(eOpenAnnouncementDialog, dialogs[0]); - } - }); - } -}; - -const checkAppUpdateAvailable = async () => { - if (__DEV__ || Config.isTesting === "true" || Config.FDROID_BUILD || BETA) - return; - try { - const version = - Config.GITHUB_RELEASE === "true" - ? await getGithubVersion() - : await checkVersion(); - if (!version || !version?.needsUpdate) return false; - - setUpdateAvailableMessage(version); - return true; - } catch (e) { - return false; - } -}; - -const checkForRateAppRequest = async () => { - const rateApp = SettingsService.get().rateApp as number; - if ( - rateApp && - rateApp < Date.now() && - !useMessageStore.getState().message?.visible - ) { - setRateAppMessage(); - return false; - } - return false; + }, [appLocked, isAppLoading]); }; diff --git a/apps/mobile/app/services/background-sync.ts b/apps/mobile/app/services/background-sync.ts index 32a43e67f..24b08a80b 100644 --- a/apps/mobile/app/services/background-sync.ts +++ b/apps/mobile/app/services/background-sync.ts @@ -141,7 +141,6 @@ const onBoot = async () => { } await Notifications.setupReminders(); - SettingsService.init(); if (SettingsService.get().notifNotes) { Notifications.pinQuickNote(false); } diff --git a/apps/mobile/app/stores/use-user-store.ts b/apps/mobile/app/stores/use-user-store.ts index 250fa9213..cc5c74fc0 100644 --- a/apps/mobile/app/stores/use-user-store.ts +++ b/apps/mobile/app/stores/use-user-store.ts @@ -17,8 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { Profile } from "@notesnook/core"; -import { User } from "@notesnook/core"; +import { Profile, User } from "@notesnook/core"; import create, { State } from "zustand"; export enum SyncStatus { @@ -56,7 +55,9 @@ export const useUserStore = create((set) => ({ set({ syncing: syncing, lastSyncStatus: status }); }, setLastSynced: (lastSynced) => set({ lastSynced: lastSynced }), - lockApp: (appLocked) => set({ appLocked }), + lockApp: (appLocked) => { + set({ appLocked }); + }, lastSyncStatus: SyncStatus.Never, disableAppLockRequests: false, setDisableAppLockRequests: (disableAppLockRequests) => {