From 70147d4332b68795fcede29a7fe28a34e97edbda Mon Sep 17 00:00:00 2001 From: kashaf-ansari-dev Date: Fri, 22 May 2026 18:02:04 +0500 Subject: [PATCH 1/5] mobile: show user-friendly error for invalid theme file upload Signed-off-by: kashaf-ansari-dev --- apps/mobile/app/screens/settings/theme-selector.tsx | 12 +++++++++++- packages/intl/locale/en.po | 4 ++++ packages/intl/locale/pseudo-LOCALE.po | 4 ++++ packages/intl/src/strings.ts | 4 +++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/apps/mobile/app/screens/settings/theme-selector.tsx b/apps/mobile/app/screens/settings/theme-selector.tsx index 073adbd02..8e42c6ed7 100644 --- a/apps/mobile/app/screens/settings/theme-selector.tsx +++ b/apps/mobile/app/screens/settings/theme-selector.tsx @@ -441,7 +441,17 @@ function ThemeSelector() { ReactNativeBlobUtil.fs .unlink(themeJsonCopiedPath) .catch(() => {}); - const json = JSON.parse(themeJson); + let json; + try { + json = JSON.parse(themeJson); + } catch (e) { + ToastManager.show({ + heading: strings.invalidThemeFileFormat(), + type: "error", + context: "global" + }); + return; + } const result = validateTheme(json); if (result.error) { ToastManager.error(new Error(result.error)); diff --git a/packages/intl/locale/en.po b/packages/intl/locale/en.po index 842f61e8a..bad0875a9 100644 --- a/packages/intl/locale/en.po +++ b/packages/intl/locale/en.po @@ -7273,6 +7273,10 @@ msgstr "We are creating a backup of your data. Please wait..." msgid "We are sorry, it seems that the app crashed due to an error. You can submit a bug report below so we can fix this asap." msgstr "We are sorry, it seems that the app crashed due to an error. You can submit a bug report below so we can fix this asap." +#: src/strings.ts:2700 +msgid "We couldn't load this theme. Please make sure the file is a valid theme export." +msgstr "We couldn't load this theme. Please make sure the file is a valid theme export." + #: src/strings.ts:1390 msgid "We have sent you an email confirmation link. Please check your email inbox. If you cannot find the email, check your spam folder." msgstr "We have sent you an email confirmation link. Please check your email inbox. If you cannot find the email, check your spam folder." diff --git a/packages/intl/locale/pseudo-LOCALE.po b/packages/intl/locale/pseudo-LOCALE.po index 103ffefb4..9202bdeae 100644 --- a/packages/intl/locale/pseudo-LOCALE.po +++ b/packages/intl/locale/pseudo-LOCALE.po @@ -7223,6 +7223,10 @@ msgstr "" msgid "We are sorry, it seems that the app crashed due to an error. You can submit a bug report below so we can fix this asap." msgstr "" +#: src/strings.ts:2700 +msgid "We couldn't load this theme. Please make sure the file is a valid theme export." +msgstr "" + #: src/strings.ts:1390 msgid "We have sent you an email confirmation link. Please check your email inbox. If you cannot find the email, check your spam folder." msgstr "" diff --git a/packages/intl/src/strings.ts b/packages/intl/src/strings.ts index 79024af1b..30d9bf16d 100644 --- a/packages/intl/src/strings.ts +++ b/packages/intl/src/strings.ts @@ -2695,5 +2695,7 @@ Continue without attachments?`, t`Creation date cannot be after last edited date`, noteDuplicated: () => t`Note duplicated`, maximumReminderDate: (maxDate: string) => - t`Maximum reminder date is ${maxDate}` + t`Maximum reminder date is ${maxDate}`, + invalidThemeFileFormat: () => + t`We couldn't load this theme. Please make sure the file is a valid theme export.` }; From e49291c55e2f8d6864fbcdf973ff5d873dca7344 Mon Sep 17 00:00:00 2001 From: kashaf-ansari-dev Date: Mon, 25 May 2026 11:16:49 +0500 Subject: [PATCH 2/5] mobile: add Learn more action to theme import invalid JSON file error and modified error message Signed-off-by: kashaf-ansari-dev --- apps/mobile/app/screens/settings/theme-selector.tsx | 9 ++++++++- packages/intl/locale/en.po | 4 ++-- packages/intl/locale/pseudo-LOCALE.po | 4 ++-- packages/intl/src/strings.ts | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/mobile/app/screens/settings/theme-selector.tsx b/apps/mobile/app/screens/settings/theme-selector.tsx index 8e42c6ed7..1bd150dc0 100644 --- a/apps/mobile/app/screens/settings/theme-selector.tsx +++ b/apps/mobile/app/screens/settings/theme-selector.tsx @@ -63,6 +63,7 @@ import { getElevationStyle } from "../../utils/elevation"; import { MenuItemsList } from "../../utils/menu-items"; import { AppFontSize, defaultBorderRadius } from "../../utils/size"; import { DefaultAppStyles } from "../../utils/styles"; +import { openLinkInBrowser } from "../../utils/functions"; const THEME_SERVER_URL = "https://themes-api.notesnook.com"; //@ts-ignore @@ -448,7 +449,13 @@ function ThemeSelector() { ToastManager.show({ heading: strings.invalidThemeFileFormat(), type: "error", - context: "global" + context: "global", + actionText: strings.learnMore(), + func: () => { + openLinkInBrowser( + "https://help.notesnook.com/custom-themes/introduction" + ); + } }); return; } diff --git a/packages/intl/locale/en.po b/packages/intl/locale/en.po index bad0875a9..5d891aeb7 100644 --- a/packages/intl/locale/en.po +++ b/packages/intl/locale/en.po @@ -7274,8 +7274,8 @@ msgid "We are sorry, it seems that the app crashed due to an error. You can subm msgstr "We are sorry, it seems that the app crashed due to an error. You can submit a bug report below so we can fix this asap." #: src/strings.ts:2700 -msgid "We couldn't load this theme. Please make sure the file is a valid theme export." -msgstr "We couldn't load this theme. Please make sure the file is a valid theme export." +msgid "We couldn't load this theme. Please make sure the file is a valid JSON theme file." +msgstr "We couldn't load this theme. Please make sure the file is a valid JSON theme file." #: src/strings.ts:1390 msgid "We have sent you an email confirmation link. Please check your email inbox. If you cannot find the email, check your spam folder." diff --git a/packages/intl/locale/pseudo-LOCALE.po b/packages/intl/locale/pseudo-LOCALE.po index 9202bdeae..64969b285 100644 --- a/packages/intl/locale/pseudo-LOCALE.po +++ b/packages/intl/locale/pseudo-LOCALE.po @@ -7221,10 +7221,10 @@ msgstr "" #: src/strings.ts:474 msgid "We are sorry, it seems that the app crashed due to an error. You can submit a bug report below so we can fix this asap." -msgstr "" +msgstr "<<<<<<< HEAD" #: src/strings.ts:2700 -msgid "We couldn't load this theme. Please make sure the file is a valid theme export." +msgid "We couldn't load this theme. Please make sure the file is a valid JSON theme file." msgstr "" #: src/strings.ts:1390 diff --git a/packages/intl/src/strings.ts b/packages/intl/src/strings.ts index 30d9bf16d..2f8eb2d92 100644 --- a/packages/intl/src/strings.ts +++ b/packages/intl/src/strings.ts @@ -2697,5 +2697,5 @@ Continue without attachments?`, maximumReminderDate: (maxDate: string) => t`Maximum reminder date is ${maxDate}`, invalidThemeFileFormat: () => - t`We couldn't load this theme. Please make sure the file is a valid theme export.` + t`We couldn't load this theme. Please make sure the file is a valid JSON theme file.` }; From 9eec90e3339eb94ef72265422927e31bf9fce9b4 Mon Sep 17 00:00:00 2001 From: Ammar Ahmed Date: Mon, 1 Jun 2026 09:03:00 +0500 Subject: [PATCH 3/5] mobile: fix invalid error shown on iOS if no file is picked --- apps/mobile/app/screens/settings/theme-selector.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/mobile/app/screens/settings/theme-selector.tsx b/apps/mobile/app/screens/settings/theme-selector.tsx index 1bd150dc0..72773b645 100644 --- a/apps/mobile/app/screens/settings/theme-selector.tsx +++ b/apps/mobile/app/screens/settings/theme-selector.tsx @@ -466,6 +466,9 @@ function ThemeSelector() { } select(json, true); } catch (e) { + if ((e as Error).message.includes("Code=3072")) { + return; + } ToastManager.error(e as Error); } }} From 46b6888ca393501f4d4f8a24470461ce51016768 Mon Sep 17 00:00:00 2001 From: kashaf-ansari-dev Date: Tue, 2 Jun 2026 16:21:39 +0500 Subject: [PATCH 4/5] mobile: add error message for incomplete theme files Signed-off-by: kashaf-ansari-dev --- apps/mobile/app/common/filesystem/utils.ts | 3 ++- .../app/screens/settings/theme-selector.tsx | 21 ++++++++++++++++++- packages/intl/locale/en.po | 4 ++++ packages/intl/locale/pseudo-LOCALE.po | 4 ++++ packages/intl/src/strings.ts | 4 +++- 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/mobile/app/common/filesystem/utils.ts b/apps/mobile/app/common/filesystem/utils.ts index 6998fd68f..e5f87a39e 100644 --- a/apps/mobile/app/common/filesystem/utils.ts +++ b/apps/mobile/app/common/filesystem/utils.ts @@ -192,7 +192,8 @@ export async function checkAndCreateDir(path: string) { } export const santizeUri = (uri: string) => { - return Platform.OS === "ios" ? decodeURI(uri).replace("file:///", "/") : uri; + const decoded = decodeURI(uri); + return Platform.OS === "ios" ? decoded.replace("file:///", "/") : decoded; }; export function isSuccessStatusCode(statusCode: number) { diff --git a/apps/mobile/app/screens/settings/theme-selector.tsx b/apps/mobile/app/screens/settings/theme-selector.tsx index 72773b645..c479ce9d0 100644 --- a/apps/mobile/app/screens/settings/theme-selector.tsx +++ b/apps/mobile/app/screens/settings/theme-selector.tsx @@ -460,8 +460,27 @@ function ThemeSelector() { return; } const result = validateTheme(json); + if (result.error) { - ToastManager.error(new Error(result.error)); + if ( + typeof result.error === "string" && + result.error.includes("missing from the theme") + ) { + ToastManager.show({ + heading: strings.themeMissingRequiredFields(), + type: "error", + context: "global", + actionText: strings.learnMore(), + func: () => { + openLinkInBrowser( + "https://help.notesnook.com/custom-themes/introduction" + ); + } + }); + } else { + ToastManager.error(new Error(result.error)); + } + return; } select(json, true); diff --git a/packages/intl/locale/en.po b/packages/intl/locale/en.po index 5d891aeb7..2c0ed85e4 100644 --- a/packages/intl/locale/en.po +++ b/packages/intl/locale/en.po @@ -7277,6 +7277,10 @@ msgstr "We are sorry, it seems that the app crashed due to an error. You can sub msgid "We couldn't load this theme. Please make sure the file is a valid JSON theme file." msgstr "We couldn't load this theme. Please make sure the file is a valid JSON theme file." +#: src/strings.ts:2693 +msgid "We couldn't load this theme. The file appears to be incomplete or missing required theme properties." +msgstr "We couldn't load this theme. The file appears to be incomplete or missing required theme properties." + #: src/strings.ts:1390 msgid "We have sent you an email confirmation link. Please check your email inbox. If you cannot find the email, check your spam folder." msgstr "We have sent you an email confirmation link. Please check your email inbox. If you cannot find the email, check your spam folder." diff --git a/packages/intl/locale/pseudo-LOCALE.po b/packages/intl/locale/pseudo-LOCALE.po index 64969b285..89b9590d1 100644 --- a/packages/intl/locale/pseudo-LOCALE.po +++ b/packages/intl/locale/pseudo-LOCALE.po @@ -7227,6 +7227,10 @@ msgstr "<<<<<<< HEAD" msgid "We couldn't load this theme. Please make sure the file is a valid JSON theme file." msgstr "" +#: src/strings.ts:2693 +msgid "We couldn't load this theme. The file appears to be incomplete or missing required theme properties." +msgstr "" + #: src/strings.ts:1390 msgid "We have sent you an email confirmation link. Please check your email inbox. If you cannot find the email, check your spam folder." msgstr "" diff --git a/packages/intl/src/strings.ts b/packages/intl/src/strings.ts index 2f8eb2d92..c629e2d09 100644 --- a/packages/intl/src/strings.ts +++ b/packages/intl/src/strings.ts @@ -2697,5 +2697,7 @@ Continue without attachments?`, maximumReminderDate: (maxDate: string) => t`Maximum reminder date is ${maxDate}`, invalidThemeFileFormat: () => - t`We couldn't load this theme. Please make sure the file is a valid JSON theme file.` + t`We couldn't load this theme. Please make sure the file is a valid JSON theme file.`, + themeMissingRequiredFields: () => + t`We couldn't load this theme. The file appears to be incomplete or missing required theme properties.` }; From 7adc5fbf1edcec3c1bbb3f9db8d572518367ddb5 Mon Sep 17 00:00:00 2001 From: kashaf-ansari-dev Date: Tue, 2 Jun 2026 22:35:57 +0500 Subject: [PATCH 5/5] mobile: copy actual error message for incomplete theme file uploads Signed-off-by: kashaf-ansari-dev --- apps/mobile/app/screens/settings/theme-selector.tsx | 12 ++++++++---- packages/intl/locale/en.po | 4 ++++ packages/intl/locale/pseudo-LOCALE.po | 4 ++++ packages/intl/src/strings.ts | 3 ++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/apps/mobile/app/screens/settings/theme-selector.tsx b/apps/mobile/app/screens/settings/theme-selector.tsx index c479ce9d0..8193b40c6 100644 --- a/apps/mobile/app/screens/settings/theme-selector.tsx +++ b/apps/mobile/app/screens/settings/theme-selector.tsx @@ -64,6 +64,7 @@ import { MenuItemsList } from "../../utils/menu-items"; import { AppFontSize, defaultBorderRadius } from "../../utils/size"; import { DefaultAppStyles } from "../../utils/styles"; import { openLinkInBrowser } from "../../utils/functions"; +import Clipboard from "@react-native-clipboard/clipboard"; const THEME_SERVER_URL = "https://themes-api.notesnook.com"; //@ts-ignore @@ -470,11 +471,14 @@ function ThemeSelector() { heading: strings.themeMissingRequiredFields(), type: "error", context: "global", - actionText: strings.learnMore(), + actionText: strings.copyLogs(), func: () => { - openLinkInBrowser( - "https://help.notesnook.com/custom-themes/introduction" - ); + Clipboard.setString(result.error || ""); + ToastManager.show({ + heading: strings.logsCopied(), + type: "success", + context: "global" + }); } }); } else { diff --git a/packages/intl/locale/en.po b/packages/intl/locale/en.po index 2c0ed85e4..33aac399f 100644 --- a/packages/intl/locale/en.po +++ b/packages/intl/locale/en.po @@ -1868,6 +1868,10 @@ msgstr "Copy link" msgid "Copy link text" msgstr "Copy link text" +#: src/strings.ts:2694 +msgid "Copy logs" +msgstr "Copy logs" + #: src/strings.ts:454 msgid "Copy note" msgstr "Copy note" diff --git a/packages/intl/locale/pseudo-LOCALE.po b/packages/intl/locale/pseudo-LOCALE.po index 89b9590d1..20a8dae61 100644 --- a/packages/intl/locale/pseudo-LOCALE.po +++ b/packages/intl/locale/pseudo-LOCALE.po @@ -1857,6 +1857,10 @@ msgstr "" msgid "Copy link text" msgstr "" +#: src/strings.ts:2694 +msgid "Copy logs" +msgstr "" + #: src/strings.ts:454 msgid "Copy note" msgstr "" diff --git a/packages/intl/src/strings.ts b/packages/intl/src/strings.ts index c629e2d09..aeb5e97f1 100644 --- a/packages/intl/src/strings.ts +++ b/packages/intl/src/strings.ts @@ -2699,5 +2699,6 @@ Continue without attachments?`, invalidThemeFileFormat: () => t`We couldn't load this theme. Please make sure the file is a valid JSON theme file.`, themeMissingRequiredFields: () => - t`We couldn't load this theme. The file appears to be incomplete or missing required theme properties.` + t`We couldn't load this theme. The file appears to be incomplete or missing required theme properties.`, + copyLogs: () => t`Copy logs` };