Add Authentik sign-in, fix tab scroll insets, and polish multi-account auth.
Mobile app detects SSO per server, supports OAuth sign-in, and preserves saved sessions when adding accounts. Tab screens get proper chrome layout and tab-bar clearance with scrollable page headers. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+32
-18
@@ -50,6 +50,7 @@ export function AppLockProvider({ children }: { children: ReactNode }) {
|
||||
const [biometricAvailable, setBiometricAvailable] = useState(false);
|
||||
const [biometricLabel, setBiometricLabel] = useState("Biometrics");
|
||||
const wasBackgrounded = useRef(false);
|
||||
const biometricUnlockInProgress = useRef(false);
|
||||
const hydrated = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -105,11 +106,17 @@ export function AppLockProvider({ children }: { children: ReactNode }) {
|
||||
const subscription = AppState.addEventListener("change", (nextState: AppStateStatus) => {
|
||||
if (!hydrated.current || !enabled || !activeAccountId) return;
|
||||
|
||||
if (nextState === "background" || nextState === "inactive") {
|
||||
// Only true backgrounding should re-lock — `inactive` fires during Face ID,
|
||||
// Control Center, and other system sheets and must not trigger another lock.
|
||||
if (nextState === "background") {
|
||||
wasBackgrounded.current = true;
|
||||
}
|
||||
|
||||
if (nextState === "active" && wasBackgrounded.current) {
|
||||
if (
|
||||
nextState === "active" &&
|
||||
wasBackgrounded.current &&
|
||||
!biometricUnlockInProgress.current
|
||||
) {
|
||||
wasBackgrounded.current = false;
|
||||
setIsLocked(true);
|
||||
}
|
||||
@@ -125,6 +132,7 @@ export function AppLockProvider({ children }: { children: ReactNode }) {
|
||||
if (!stored || stored !== pin) {
|
||||
return false;
|
||||
}
|
||||
wasBackgrounded.current = false;
|
||||
setIsLocked(false);
|
||||
return true;
|
||||
},
|
||||
@@ -136,24 +144,30 @@ export function AppLockProvider({ children }: { children: ReactNode }) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = await LocalAuthentication.authenticateAsync({
|
||||
promptMessage: "Unlock beenvoice",
|
||||
cancelLabel: "Use PIN",
|
||||
disableDeviceFallback: false,
|
||||
biometricsSecurityLevel: "weak",
|
||||
});
|
||||
biometricUnlockInProgress.current = true;
|
||||
try {
|
||||
const result = await LocalAuthentication.authenticateAsync({
|
||||
promptMessage: "Unlock beenvoice",
|
||||
cancelLabel: "Use PIN",
|
||||
disableDeviceFallback: false,
|
||||
biometricsSecurityLevel: "weak",
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
return false;
|
||||
if (!result.success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!biometricEnabled) {
|
||||
await setBiometricEnabled(activeAccountId, true);
|
||||
setBiometricEnabledState(true);
|
||||
}
|
||||
|
||||
wasBackgrounded.current = false;
|
||||
setIsLocked(false);
|
||||
return true;
|
||||
} finally {
|
||||
biometricUnlockInProgress.current = false;
|
||||
}
|
||||
|
||||
if (!biometricEnabled) {
|
||||
await setBiometricEnabled(activeAccountId, true);
|
||||
setBiometricEnabledState(true);
|
||||
}
|
||||
|
||||
setIsLocked(false);
|
||||
return true;
|
||||
}, [biometricAvailable, biometricEnabled, activeAccountId]);
|
||||
|
||||
const enableLock = useCallback(
|
||||
|
||||
Reference in New Issue
Block a user