Share Extension: account picker first, hidden folders follow the app's filter + unlock

The app now publishes every uploadable account, the active one, the three
lock settings and each account's own hidden-files filter (ShareAccountSync).
The sheet lists accounts first when there are several, asks for unlock to use
a non-active account (login lock + account-switching lock), and shows hidden
folders per the account's app setting behind the hidden-files unlock.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Ayushya Amitabh
2026-10-06 19:59:29 -04:00
co-authored by Claude Sonnet 5.5
parent 0cda4a1241
commit a37524e959
14 changed files with 581 additions and 87 deletions
+7 -10
View File
@@ -8,8 +8,10 @@ import UserNotifications
/// shows a folder picker, then starts a background upload and closes:
///
/// 1. Copies whatever was shared into the App Group (`SharedInbox`).
/// 2. Reads the signed-in account the app left in the shared Keychain
/// (`SharedAccountStore`) and lists folders over WebDAV (`DavClient`).
/// 2. Reads the accounts the app left in the shared Keychain
/// (`SharedAccountStore`) - asking which one first if there are several -
/// and lists folders over WebDAV (`DavClient`), honouring the app's
/// hidden-files filter and its unlock settings (`ShareModel`).
/// 3. "Upload" queues the files on a background session that outlives this
/// process (`ShareUpload`); the app is relaunched to finish and notify.
///
@@ -22,7 +24,7 @@ final class ShareViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
model = ShareModel(account: SharedAccountStore.load())
model = ShareModel(shared: SharedAccountStore.load())
model.onUpload = { [weak self] in self?.upload() }
model.onSaveForLater = { [weak self] in self?.saveForLater() }
model.onCancel = { [weak self] in self?.cancel() }
@@ -68,12 +70,7 @@ final class ShareViewController: UIViewController {
model.stage = .failed("Noo can only receive files and photos.")
return
}
guard model.account != nil else {
model.stage = .noAccount
return
}
model.stage = .picking
await model.open("/")
await model.start()
}
/// `loadFileRepresentation`'s URL only lives for the duration of its
@@ -102,7 +99,7 @@ final class ShareViewController: UIViewController {
// MARK: - Actions
private func upload() {
guard let account = model.account else { return }
guard let account = model.selected else { return }
do {
try ShareUpload.enqueue(items: model.items, account: account, remoteFolder: model.path)
model.stage = .uploading