From 06076b1a85fcb7cd276c84702732b4548dc1bfd3 Mon Sep 17 00:00:00 2001 From: Gauvain Date: Fri, 17 Jul 2026 15:39:28 +0200 Subject: [PATCH] fix(auth): surface failed account save to the user A skipped or failed post-login account save only wrote a log entry, so the user believed the account was saved. Both save paths (loginMutation PIN guard and PendingAccountSaveModal catch) now show an error toast. --- components/PendingAccountSaveModal.tsx | 9 ++++++++- providers/JellyfinProvider.tsx | 4 +++- translations/en.json | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/components/PendingAccountSaveModal.tsx b/components/PendingAccountSaveModal.tsx index 9c2def07c..a43fbe004 100644 --- a/components/PendingAccountSaveModal.tsx +++ b/components/PendingAccountSaveModal.tsx @@ -1,13 +1,16 @@ import { useAtom, useAtomValue } from "jotai"; import type React from "react"; import { useEffect } from "react"; +import { useTranslation } from "react-i18next"; import { Platform } from "react-native"; +import { toast } from "sonner-native"; import { SaveAccountModal } from "@/components/SaveAccountModal"; import { pendingAccountSaveAtom, useJellyfin, userAtom, } from "@/providers/JellyfinProvider"; +import { writeErrorLog } from "@/utils/log"; /** * Post-login save-account prompt. Login flows (password or Quick Connect) @@ -19,6 +22,7 @@ export const PendingAccountSaveModal: React.FC = () => { const [pending, setPending] = useAtom(pendingAccountSaveAtom); const user = useAtomValue(userAtom); const { saveCurrentAccount } = useJellyfin(); + const { t } = useTranslation(); // A logout before answering drops the intent — it must not resurface on // the next (possibly different) login. @@ -37,7 +41,10 @@ export const PendingAccountSaveModal: React.FC = () => { const serverName = pending?.serverName; setPending(null); saveCurrentAccount({ securityType, pinCode, serverName }).catch( - (error) => console.warn("Failed to save account:", error), + (error) => { + writeErrorLog(`Failed to save account: ${error?.message ?? error}`); + toast.error(t("save_account.not_saved")); + }, ); }} /> diff --git a/providers/JellyfinProvider.tsx b/providers/JellyfinProvider.tsx index b36912471..62413483c 100644 --- a/providers/JellyfinProvider.tsx +++ b/providers/JellyfinProvider.tsx @@ -22,6 +22,7 @@ import { useTranslation } from "react-i18next"; import { AppState, Platform } from "react-native"; import { getDeviceNameSync } from "react-native-device-info"; import uuid from "react-native-uuid"; +import { toast } from "sonner-native"; import useRouter from "@/hooks/useAppRouter"; import { useInterval } from "@/hooks/useInterval"; import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr"; @@ -450,8 +451,9 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({ if (securityType === "pin" && !pinHash) { // Never persist a "pin" credential without its hash — it would be // impossible to unlock. Skip the save rather than failing a login - // that already succeeded. + // that already succeeded, and tell the user it didn't happen. writeErrorLog("Account save skipped: PIN required but missing"); + toast.error(t("save_account.not_saved")); } else { await saveAccountCredential({ serverUrl: api.basePath, diff --git a/translations/en.json b/translations/en.json index 692532eb7..8bfd9adfb 100644 --- a/translations/en.json +++ b/translations/en.json @@ -56,6 +56,7 @@ "save_account": { "title": "Save account", "save_for_later": "Save this account", + "not_saved": "Account was not saved", "security_option": "Security option", "no_protection": "No protection", "no_protection_desc": "Quick login without authentication",