Share sheet: ask to unlock on every gated action, like the app

The sheet remembered one unlock for its whole lifetime, so later account picks
and hidden toggles skipped Face ID. Each switch / each turning-on of hidden
folders now prompts again; one action needing both is a single prompt.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Ayushya Amitabh
2026-10-06 20:24:20 -04:00
co-authored by Claude Sonnet 5.5
parent 02d9d799a6
commit 4ab6c5d85c
4 changed files with 104 additions and 28 deletions
+23
View File
@@ -73,6 +73,21 @@ struct SharedAccounts: Codable, Equatable {
/// Showing hidden folders needs the same unlock the app asks for when you
/// turn hidden files on.
var needsUnlockForHidden: Bool { lockHiddenFiles }
/// What choosing [account] (with [hidden] folders to show) asks the user
/// to unlock. One action, one prompt - when both the account switch and
/// the hidden folders need it, a single authentication covers both.
func unlockNeeds(choosing account: SharedAccount, showing hidden: HiddenFilter) -> SelectionUnlock {
SelectionUnlock(
switchesAccount: account.id != active?.id && needsUnlockToSwitchAccount,
showsHidden: hidden != .hide && needsUnlockForHidden)
}
/// Turning hidden folders on (from `hide`) is what the app locks; going
/// back to `hide`, or between the two revealing modes, never asks.
func needsUnlockToChangeHidden(from old: HiddenFilter, to new: HiddenFilter) -> Bool {
old == .hide && new != .hide && needsUnlockForHidden
}
}
/// Keeps the [SharedAccounts] in a Keychain access group both the app and the
@@ -136,3 +151,11 @@ enum SharedAccountStore {
SecItemDelete(legacy as CFDictionary)
}
}
/// What one selection needs unlocked - see `SharedAccounts.unlockNeeds`.
struct SelectionUnlock: Equatable {
let switchesAccount: Bool
let showsHidden: Bool
var needsPrompt: Bool { switchesAccount || showsHidden }
}