@ollaid/native-sso 2.7.1 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -9617,6 +9617,8 @@ function LoginModal({
9617
9617
  const [loginSuccess, setLoginSuccess] = react.useState(false);
9618
9618
  const [loginData, setLoginData] = react.useState(null);
9619
9619
  const [showPasswordRecovery, setShowPasswordRecovery] = react.useState(false);
9620
+ const [passwordSubmitting, setPasswordSubmitting] = react.useState(false);
9621
+ const successCallbackTimerRef = react.useRef(null);
9620
9622
  const CCPHONE = "+221";
9621
9623
  const isSubmitting = authLoading || loading;
9622
9624
  const error = localError || authError;
@@ -9634,15 +9636,11 @@ function LoginModal({
9634
9636
  setResendCooldown(60);
9635
9637
  }
9636
9638
  }, [status, step]);
9637
- react.useEffect(() => {
9638
- if (loginSuccess && loginData) {
9639
- const timer = setTimeout(() => {
9640
- onLoginSuccess == null ? void 0 : onLoginSuccess(loginData.token, loginData.user);
9641
- }, 1e3);
9642
- return () => clearTimeout(timer);
9643
- }
9644
- }, [loginSuccess, loginData, onLoginSuccess]);
9645
9639
  const resetState = react.useCallback(() => {
9640
+ if (successCallbackTimerRef.current) {
9641
+ clearTimeout(successCallbackTimerRef.current);
9642
+ successCallbackTimerRef.current = null;
9643
+ }
9646
9644
  setStep("choice");
9647
9645
  setEmail("");
9648
9646
  setPassword("");
@@ -9656,6 +9654,7 @@ function LoginModal({
9656
9654
  setLoginSuccess(false);
9657
9655
  setLoginData(null);
9658
9656
  setResendCooldown(0);
9657
+ setPasswordSubmitting(false);
9659
9658
  resetAuth();
9660
9659
  }, [resetAuth]);
9661
9660
  react.useEffect(() => {
@@ -9668,12 +9667,34 @@ function LoginModal({
9668
9667
  }
9669
9668
  }, [open, initialPhone]);
9670
9669
  const finalizeLogin = (result) => {
9671
- if (result.success && result.user) {
9670
+ if (result.success) {
9672
9671
  const token = getAuthToken() || "";
9673
- setLoginData({ token, user: result.user });
9674
- setLoginSuccess(true);
9672
+ const resolvedUser = result.user || user;
9673
+ if (resolvedUser) {
9674
+ setLoginData({ token, user: resolvedUser });
9675
+ setLoginSuccess(true);
9676
+ }
9675
9677
  }
9676
9678
  };
9679
+ react.useEffect(() => {
9680
+ if (!loginSuccess || !loginData || !onLoginSuccess) return;
9681
+ if (successCallbackTimerRef.current) {
9682
+ clearTimeout(successCallbackTimerRef.current);
9683
+ }
9684
+ successCallbackTimerRef.current = setTimeout(() => {
9685
+ try {
9686
+ onLoginSuccess(loginData.token, loginData.user);
9687
+ } catch (callbackError) {
9688
+ console.error("Erreur dans onLoginSuccess", callbackError);
9689
+ }
9690
+ }, 900);
9691
+ return () => {
9692
+ if (successCallbackTimerRef.current) {
9693
+ clearTimeout(successCallbackTimerRef.current);
9694
+ successCallbackTimerRef.current = null;
9695
+ }
9696
+ };
9697
+ }, [loginSuccess, loginData, onLoginSuccess]);
9677
9698
  const handleEmailCheck = async () => {
9678
9699
  setLocalError(null);
9679
9700
  clearError();
@@ -9690,18 +9711,24 @@ function LoginModal({
9690
9711
  };
9691
9712
  const handleEmailPasswordSubmit = async (e) => {
9692
9713
  e.preventDefault();
9714
+ if (passwordSubmitting || isSubmitting) return;
9715
+ setPasswordSubmitting(true);
9693
9716
  setLocalError(null);
9694
9717
  clearError();
9695
- if (!password) {
9696
- setLocalError("Le mot de passe est requis");
9697
- return;
9698
- }
9699
- if (password.length < 8) {
9700
- setLocalError("Le mot de passe doit contenir au moins 8 caractères");
9701
- return;
9718
+ try {
9719
+ if (!password) {
9720
+ setLocalError("Le mot de passe est requis");
9721
+ return;
9722
+ }
9723
+ if (password.length < 8) {
9724
+ setLocalError("Le mot de passe doit contenir au moins 8 caractères");
9725
+ return;
9726
+ }
9727
+ const result = await submitPassword(password);
9728
+ finalizeLogin(result);
9729
+ } finally {
9730
+ setPasswordSubmitting(false);
9702
9731
  }
9703
- const result = await submitPassword(password);
9704
- finalizeLogin(result);
9705
9732
  };
9706
9733
  const handleEmailOtpVerify = async () => {
9707
9734
  setLocalError(null);
@@ -9965,7 +9992,7 @@ function LoginModal({
9965
9992
  placeholder: "••••••••",
9966
9993
  value: password,
9967
9994
  onChange: (e) => setPassword(e.target.value),
9968
- disabled: isSubmitting,
9995
+ disabled: isSubmitting || passwordSubmitting,
9969
9996
  style: { paddingRight: "2.5rem" }
9970
9997
  }
9971
9998
  ),
@@ -9981,7 +10008,7 @@ function LoginModal({
9981
10008
  ] })
9982
10009
  ] })
9983
10010
  ] }) }),
9984
- /* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", disabled: isSubmitting || !password, style: { width: "100%" }, children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
10011
+ /* @__PURE__ */ jsxRuntime.jsx(DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", disabled: isSubmitting || passwordSubmitting || !password, style: { width: "100%" }, children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
9985
10012
  /* @__PURE__ */ jsxRuntime.jsx(IconLoader2, { style: { width: "1rem", height: "1rem" } }),
9986
10013
  "Connexion..."
9987
10014
  ] }) : "Se connecter" }) })
@@ -13237,6 +13264,8 @@ function NativeSSOPage({
13237
13264
  const [showOnboarding, setShowOnboarding] = react.useState(false);
13238
13265
  const [pendingSession, setPendingSession] = react.useState(null);
13239
13266
  const [debugOnboardingState, setDebugOnboardingState] = react.useState(null);
13267
+ const [redirectingTarget, setRedirectingTarget] = react.useState(null);
13268
+ const [redirectingReason, setRedirectingReason] = react.useState(null);
13240
13269
  const [session, setSession] = react.useState(() => {
13241
13270
  try {
13242
13271
  const storage2 = getNativeStorage();
@@ -13259,6 +13288,17 @@ function NativeSSOPage({
13259
13288
  react.useEffect(() => {
13260
13289
  sessionRef.current = session;
13261
13290
  }, [session]);
13291
+ react.useEffect(() => {
13292
+ if (!redirectingTarget) return;
13293
+ const timer = window.setTimeout(() => {
13294
+ const redirected = safeRedirect(redirectingTarget);
13295
+ if (!redirected) {
13296
+ setRedirectingTarget(null);
13297
+ setRedirectingReason(null);
13298
+ }
13299
+ }, 200);
13300
+ return () => window.clearTimeout(timer);
13301
+ }, [redirectingTarget]);
13262
13302
  const clearOnboardingTimers = react.useCallback(() => {
13263
13303
  if (onboardingPromptTimerRef.current) {
13264
13304
  clearTimeout(onboardingPromptTimerRef.current);
@@ -13426,6 +13466,12 @@ function NativeSSOPage({
13426
13466
  setLoginInitialPhone(phone);
13427
13467
  setTimeout(() => setModal("login"), 150);
13428
13468
  }, []);
13469
+ const beginRedirect = react.useCallback((target, reason = "login") => {
13470
+ if (!target) return false;
13471
+ setRedirectingReason(reason);
13472
+ setRedirectingTarget(target);
13473
+ return true;
13474
+ }, []);
13429
13475
  const handleLoginSuccess = react.useCallback((token, user) => {
13430
13476
  const userObj = {
13431
13477
  reference: "",
@@ -13442,10 +13488,14 @@ function NativeSSOPage({
13442
13488
  void refreshSessionProfile(true);
13443
13489
  if (!needsOnboarding(userObj)) {
13444
13490
  markProfilePromptComplete();
13445
- onLoginSuccess == null ? void 0 : onLoginSuccess(token, user);
13446
- safeRedirect(redirectAfterLogin);
13491
+ try {
13492
+ onLoginSuccess == null ? void 0 : onLoginSuccess(token, user);
13493
+ } catch (callbackError) {
13494
+ console.error("Erreur dans le callback onLoginSuccess du wrapper SSO", callbackError);
13495
+ }
13496
+ beginRedirect(redirectAfterLogin, "login");
13447
13497
  }
13448
- }, [onLoginSuccess, redirectAfterLogin, persistSessionUser, syncProfilePrompt, refreshSessionProfile, accountType]);
13498
+ }, [onLoginSuccess, redirectAfterLogin, persistSessionUser, syncProfilePrompt, refreshSessionProfile, accountType, beginRedirect]);
13449
13499
  const handleOnboardingComplete = react.useCallback((data) => {
13450
13500
  const activeSession = debugOnboardingState || pendingSession;
13451
13501
  if (!activeSession) return;
@@ -13489,11 +13539,15 @@ function NativeSSOPage({
13489
13539
  if (!debugOnboardingState) {
13490
13540
  persistSessionUser(activeSession.token, activeSession.user);
13491
13541
  snoozeProfilePrompt(PROFILE_PROMPT_SNOOZE_MS / (60 * 60 * 1e3));
13492
- onLoginSuccess == null ? void 0 : onLoginSuccess(activeSession.token, activeSession.user);
13493
- safeRedirect(redirectAfterLogin);
13542
+ try {
13543
+ onLoginSuccess == null ? void 0 : onLoginSuccess(activeSession.token, activeSession.user);
13544
+ } catch (callbackError) {
13545
+ console.error("Erreur dans le callback onLoginSuccess du wrapper SSO", callbackError);
13546
+ }
13547
+ beginRedirect(redirectAfterLogin, "login");
13494
13548
  return;
13495
13549
  }
13496
- }, [pendingSession, debugOnboardingState, onLoginSuccess, redirectAfterLogin, persistSessionUser]);
13550
+ }, [pendingSession, debugOnboardingState, onLoginSuccess, redirectAfterLogin, persistSessionUser, beginRedirect]);
13497
13551
  const handleOnboardingDismiss = react.useCallback(() => {
13498
13552
  setShowOnboarding(false);
13499
13553
  setPendingSession(null);
@@ -13506,8 +13560,8 @@ function NativeSSOPage({
13506
13560
  setDebugOnboardingState(null);
13507
13561
  clearOnboardingTimers();
13508
13562
  onLogout == null ? void 0 : onLogout();
13509
- safeRedirect(redirectAfterLogout);
13510
- }, [onLogout, redirectAfterLogout, clearOnboardingTimers]);
13563
+ beginRedirect(redirectAfterLogout, "logout");
13564
+ }, [onLogout, redirectAfterLogout, clearOnboardingTimers, beginRedirect]);
13511
13565
  const openDebugLogin = react.useCallback(() => {
13512
13566
  clearOnboardingTimers();
13513
13567
  setShowOnboarding(false);
@@ -13522,6 +13576,10 @@ function NativeSSOPage({
13522
13576
  setDebugOnboardingState(null);
13523
13577
  setModal("signup");
13524
13578
  }, [clearOnboardingTimers]);
13579
+ react.useEffect(() => {
13580
+ if (!(session == null ? void 0 : session.token) || !redirectAfterLogin || redirectingTarget) return;
13581
+ beginRedirect(redirectAfterLogin, "already-authenticated");
13582
+ }, [session == null ? void 0 : session.token, redirectAfterLogin, redirectingTarget, beginRedirect]);
13525
13583
  const openDebugOnboarding = react.useCallback((preset = "current") => {
13526
13584
  if (!session) return;
13527
13585
  clearOnboardingTimers();
@@ -13644,14 +13702,18 @@ function NativeSSOPage({
13644
13702
  overflow: "hidden"
13645
13703
  }, children: /* @__PURE__ */ jsxRuntime.jsx(AppsLogoSlider, { iamApiUrl, speed: "normal" }) }) })
13646
13704
  ] }) });
13705
+ if (redirectingTarget) {
13706
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
13707
+ /* @__PURE__ */ jsxRuntime.jsx(TopBranding, { subtitle: title }),
13708
+ /* @__PURE__ */ jsxRuntime.jsx(SliderBadge, {}),
13709
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "2rem 1.5rem 1.5rem", textAlign: "center" }, children: [
13710
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "1.25rem", fontWeight: 600, color: COLORS.cardForeground }, children: redirectingReason === "logout" ? "Déconnexion réussie" : redirectingReason === "already-authenticated" ? "Session déjà valide" : "Connexion réussie" }),
13711
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", color: COLORS.muted, marginTop: "0.5rem" }, children: "Redirection en cours..." })
13712
+ ] }) }),
13713
+ /* @__PURE__ */ jsxRuntime.jsx(Footer, { hideFooter })
13714
+ ] });
13715
+ }
13647
13716
  if (session) {
13648
- if (redirectAfterLogin) {
13649
- safeRedirect(redirectAfterLogin);
13650
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
13651
- /* @__PURE__ */ jsxRuntime.jsx(TopBranding, { subtitle: title }),
13652
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "rgba(255,255,255,0.7)", fontSize: "0.875rem" }, children: "Redirection en cours..." })
13653
- ] });
13654
- }
13655
13717
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
13656
13718
  /* @__PURE__ */ jsxRuntime.jsx(TopBranding, { subtitle: title }),
13657
13719
  /* @__PURE__ */ jsxRuntime.jsx(SliderBadge, {}),