diff --git a/apps/mobile/app/hooks/use-app-events.tsx b/apps/mobile/app/hooks/use-app-events.tsx
index 1ee50a689..c92bff51b 100644
--- a/apps/mobile/app/hooks/use-app-events.tsx
+++ b/apps/mobile/app/hooks/use-app-events.tsx
@@ -341,24 +341,32 @@ const onSubscriptionError = async (error: RNIap.PurchaseError) => {
const SodiumEventEmitter = new NativeEventEmitter(NativeModules.Sodium);
+const setAppMessage = async () => {
+ await useMessageStore.getState().setAnnouncement();
+ if (await checkAppUpdateAvailable()) return;
+ const user = await db.user.getUser();
+ if (!user) {
+ setLoginMessage();
+ return;
+ }
+ if (!user?.isEmailConfirmed) setEmailVerifyMessage();
+ if (await checkForRateAppRequest()) return;
+ if (
+ user?.isEmailConfirmed &&
+ !SettingsService.get().recoveryKeySaved &&
+ !useMessageStore.getState().message?.visible
+ ) {
+ setRecoveryKeyMessage();
+ }
+};
+
const doAppLoadActions = async () => {
if (SettingsService.get().sessionExpired) {
eSendEvent(eLoginSessionExpired);
return;
}
-
- await useMessageStore.getState().setAnnouncement();
-
notifee.setBadgeCount(0);
-
- if (!(await db.user.getUser())) {
- setLoginMessage();
- return;
- }
-
if (NewFeature.present()) return;
- if (await checkAppUpdateAvailable()) return;
- if (await checkForRateAppRequest()) return;
if (SettingsService.get().introCompleted) {
useMessageStore.subscribe((state) => {
const dialogs = state.dialogs;
@@ -401,7 +409,7 @@ const checkForRateAppRequest = async () => {
!useMessageStore.getState().message?.visible
) {
setRateAppMessage();
- return false;
+ return true;
}
return false;
};
@@ -440,6 +448,7 @@ const initializeDatabase = async (password?: string) => {
if (IsDatabaseMigrationRequired()) return;
if (db.isInitialized) {
+ await setAppMessage();
useSettingStore.getState().setAppLoading(false);
Notifications.setupReminders(true);
if (SettingsService.get().notifNotes) {
@@ -584,8 +593,6 @@ export const useAppEvents = () => {
syncedOnLaunch.current = true;
return;
}
-
- clearMessage();
subscribeToPurchaseListeners();
if (!isLogin) {
user = await db.user.fetchUser();
@@ -596,6 +603,11 @@ export const useAppEvents = () => {
});
}
+ if (useMessageStore.getState().message.id === "log-in") {
+ clearMessage();
+ setAppMessage();
+ }
+
await PremiumService.setPremiumStatus();
if (user?.isEmailConfirmed && !isUserEmailConfirmed) {
setTimeout(() => {
@@ -609,16 +621,6 @@ export const useAppEvents = () => {
ToastManager.error(e as Error, "Error updating user", "global");
}
- user = await db.user.getUser();
- if (
- user?.isEmailConfirmed &&
- !SettingsService.get().recoveryKeySaved &&
- !useMessageStore.getState().message?.visible
- ) {
- setRecoveryKeyMessage();
- }
- if (!user?.isEmailConfirmed) setEmailVerifyMessage();
-
syncedOnLaunch.current = true;
if (!isLogin) {
checkAutoBackup();
diff --git a/apps/mobile/app/services/message.js b/apps/mobile/app/services/message.js
deleted file mode 100644
index 0a47e71fb..000000000
--- a/apps/mobile/app/services/message.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
-This file is part of the Notesnook project (https://notesnook.com/)
-
-Copyright (C) 2023 Streetwriters (Private) Limited
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-import { strings } from "@notesnook/intl";
-import React from "react";
-import { Platform } from "react-native";
-import { AuthMode } from "../components/auth/common";
-import { Update } from "../components/sheets/update";
-import { verifyUser } from "../screens/settings/functions";
-import { useMessageStore } from "../stores/use-message-store";
-import { eOpenRateDialog, eOpenRecoveryKeyDialog } from "../utils/events";
-import { eSendEvent, presentSheet } from "./event-manager";
-import Navigation from "./navigation";
-import PremiumService from "./premium";
-import SettingsService from "./settings";
-
-const rateAppMessage = {
- visible: true,
- message: strings.rateAppMessage(),
- actionText: strings.rateAppActionText(Platform.OS),
- onPress: () => {
- eSendEvent(eOpenRateDialog);
- },
- data: {},
- icon: "star",
- type: "normal"
-};
-
-export function setRateAppMessage() {
- useMessageStore.getState().setMessage(rateAppMessage);
-}
-
-const recoveryKeyMessage = {
- visible: true,
- message: strings.recoveryKeyMessage(),
- actionText: strings.recoveryKeyMessageActionText(),
- onPress: () => {
- verifyUser(
- null,
- () => {
- eSendEvent(eOpenRecoveryKeyDialog);
- },
- false,
- async () => {
- SettingsService.set({
- recoveryKeySaved: true
- });
- clearMessage();
- },
- "Cancel"
- );
- },
- data: {},
- icon: "key",
- type: "normal"
-};
-
-export function setRecoveryKeyMessage() {
- useMessageStore.getState().setMessage(recoveryKeyMessage);
-}
-
-const loginMessage = {
- visible: true,
- message: strings.loginMessage(),
- actionText: strings.loginMessageActionText(),
- onPress: () => {
- Navigation.navigate("Auth", {
- mode: AuthMode.login
- });
- },
- data: {},
- icon: "account-outline",
- type: "normal"
-};
-
-export function setLoginMessage() {
- useMessageStore.getState().setMessage(loginMessage);
-}
-
-const emailMessage = {
- visible: true,
- message: strings.syncDisabled(),
- actionText: strings.syncDisabledActionText(),
- onPress: () => {
- PremiumService.showVerifyEmailDialog();
- },
- data: {},
- icon: "email",
- type: "error"
-};
-
-export function setEmailVerifyMessage() {
- useMessageStore.getState().setMessage(emailMessage);
-}
-
-const noMessage = {
- visible: false,
- message: "",
- actionText: "",
- onPress: null,
- data: {},
- icon: "account-outline"
-};
-
-export function clearMessage() {
- useMessageStore.getState().setMessage(noMessage);
-}
-
-const autoBackupsOff = {
- visible: true,
- message: strings.autoBackupsOffMessage(),
- actionText: strings.autoBackupsOffActionText(),
- onPress: () => {
- clearMessage();
- },
- data: {},
- icon: "backup-restore",
- type: "error"
-};
-
-export function setAutobackOffMessage() {
- useMessageStore.getState().setMessage(autoBackupsOff);
-}
-
-const updateAvailableMessage = (version) => ({
- visible: true,
- message: strings.newUpdateMessage(),
- actionText: strings.newUpdateActionText(),
- onPress: () => {
- presentSheet({
- component: (ref) =>
- });
- },
- data: {},
- icon: "update",
- type: "normal"
-});
-
-export function setUpdateAvailableMessage(version) {
- useMessageStore.getState().setMessage(updateAvailableMessage(version));
-}
diff --git a/apps/mobile/app/services/message.tsx b/apps/mobile/app/services/message.tsx
new file mode 100644
index 000000000..966d67025
--- /dev/null
+++ b/apps/mobile/app/services/message.tsx
@@ -0,0 +1,155 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { strings } from "@notesnook/intl";
+import { Platform } from "react-native";
+import { AuthMode } from "../components/auth/common";
+import { verifyUser } from "../screens/settings/functions";
+import {
+ Message,
+ MessageId,
+ useMessageStore
+} from "../stores/use-message-store";
+import { eOpenRateDialog, eOpenRecoveryKeyDialog } from "../utils/events";
+import { eSendEvent, presentSheet } from "./event-manager";
+import Navigation from "./navigation";
+import PremiumService from "./premium";
+import SettingsService from "./settings";
+import { Update } from "../components/sheets/update";
+import { GithubVersionInfo } from "../utils/github-version";
+import { CheckVersionResponse } from "react-native-check-version";
+
+const APP_MESSAGES: Message[] = [
+ {
+ visible: true,
+ message: strings.rateAppMessage(),
+ actionText: strings.rateAppActionText(Platform.OS),
+ onPress: () => {
+ eSendEvent(eOpenRateDialog);
+ },
+ data: {},
+ icon: "star",
+ type: "normal",
+ id: "rate-app"
+ },
+ {
+ visible: true,
+ message: strings.recoveryKeyMessage(),
+ actionText: strings.recoveryKeyMessageActionText(),
+ onPress: () => {
+ verifyUser(
+ null,
+ () => {
+ eSendEvent(eOpenRecoveryKeyDialog);
+ },
+ false,
+ async () => {
+ SettingsService.set({
+ recoveryKeySaved: true
+ });
+ clearMessage();
+ },
+ "Cancel"
+ );
+ },
+ data: {},
+ icon: "key",
+ type: "normal",
+ id: "recovery-key"
+ },
+ {
+ visible: true,
+ message: strings.loginMessage(),
+ actionText: strings.loginMessageActionText(),
+ onPress: () => {
+ Navigation.navigate("Auth", {
+ mode: AuthMode.login
+ });
+ },
+ data: {},
+ icon: "account-outline",
+ type: "normal",
+ id: "log-in"
+ },
+ {
+ visible: true,
+ message: strings.syncDisabled(),
+ actionText: strings.syncDisabledActionText(),
+ onPress: () => {
+ PremiumService.showVerifyEmailDialog();
+ },
+ data: {},
+ icon: "email",
+ type: "error",
+ id: "confirm-email"
+ }
+];
+
+function showMessageById(id: MessageId) {
+ useMessageStore
+ .getState()
+ .setMessage(APP_MESSAGES.find((m) => m.id === id) as Message);
+}
+
+export function setRateAppMessage() {
+ showMessageById("rate-app");
+}
+
+export function setRecoveryKeyMessage() {
+ showMessageById("recovery-key");
+}
+
+export function setLoginMessage() {
+ showMessageById("log-in");
+}
+
+export function setEmailVerifyMessage() {
+ showMessageById("confirm-email");
+}
+
+export function clearMessage() {
+ useMessageStore.getState().setMessage({
+ ...useMessageStore.getState().message,
+ visible: false
+ });
+}
+
+const updateAvailableMessage = (
+ version: GithubVersionInfo | CheckVersionResponse
+) =>
+ ({
+ visible: true,
+ message: strings.newUpdateMessage(),
+ actionText: strings.newUpdateActionText(),
+ onPress: () => {
+ presentSheet({
+ component: (ref) =>
+ });
+ },
+ data: {},
+ icon: "update",
+ type: "normal",
+ id: "app-update"
+ }) as Message;
+
+export function setUpdateAvailableMessage(
+ version: GithubVersionInfo | CheckVersionResponse
+) {
+ useMessageStore.getState().setMessage(updateAvailableMessage(version));
+}
diff --git a/apps/mobile/app/stores/use-message-store.ts b/apps/mobile/app/stores/use-message-store.ts
index 47a31588c..6ffd9c5b6 100644
--- a/apps/mobile/app/stores/use-message-store.ts
+++ b/apps/mobile/app/stores/use-message-store.ts
@@ -33,6 +33,14 @@ export interface MessageStore {
remove: (id: string) => void;
}
+export type MessageId =
+ | "rate-app"
+ | "log-in"
+ | "recovery-key"
+ | "confirm-email"
+ | "app-update"
+ | "none";
+
export type Message = {
visible: boolean;
message: string | null;
@@ -40,7 +48,8 @@ export type Message = {
onPress: () => void;
data: object;
icon: string;
- type?: string;
+ type: "error" | "normal";
+ id: MessageId;
};
export type Action = {
@@ -97,7 +106,8 @@ export const useMessageStore = create((set, get) => ({
onPress: () => null,
data: {},
icon: "account-outline",
- type: ""
+ type: "normal",
+ id: "none"
},
setMessage: (message) => {
set({ message: { ...message } });
diff --git a/apps/mobile/app/utils/github-version.ts b/apps/mobile/app/utils/github-version.ts
index 37478b4eb..33cd6024c 100644
--- a/apps/mobile/app/utils/github-version.ts
+++ b/apps/mobile/app/utils/github-version.ts
@@ -42,8 +42,17 @@ export interface GithubRelease {
reactions: unknown;
discussion_url: string;
}
-
-export const getGithubVersion = async () => {
+export type GithubVersionInfo = {
+ version: string | null;
+ releasedAt: string;
+ notes: string;
+ body: string;
+ url: string;
+ lastChecked: string;
+ needsUpdate: boolean;
+ current: string;
+};
+export const getGithubVersion = async (): Promise => {
const url = `https://api.github.com/repos/streetwriters/notesnook/releases`;
let res;
try {