mirror of
https://github.com/yattee/yattee.git
synced 2026-10-25 22:22:52 +00:00
Give every login a screen, including the ones with nowhere to go
An account whose source is gone was listed nowhere: `orphanedAccounts` had no readers, and the credential behind it could not be reached at all — `AppEnvironment.accountCredentialsManager(for:)` resolves the store from the account's instance, and an orphan has none. The new accounts screen lists them and removes them by account ID, asking every account-keyed store because the backend is no longer knowable. The pre-revamp instance-keyed item is deliberately left behind: identifying it needs the instance too. Deleting a source has always signed out and removed the accounts on it. Both confirmations now say so, and name them. The sign-in that files a credential against an account is now one implementation instead of a private method on the source editor, so the accounts screen and the new optional sign-in step after adding a source attach a login exactly as the editor does. Extracted verbatim — the identity-scope guard, the account re-resolve, the write-then-read-back and the rollback are what keep a half-written login from looking real. Signing out from the per-instance section now asks first, and both sign-out paths run one cascade rather than two copies of it.
This commit is contained in:
@@ -68,6 +68,13 @@ struct AddRemoteServerView: View {
|
||||
@State private var showingYatteeServerWarning = false
|
||||
@State private var pendingYatteeServerInstance: Instance?
|
||||
|
||||
/// The instance whose optional sign-in step is on screen.
|
||||
///
|
||||
/// The source is already added by then, so dismissing this sheet — by
|
||||
/// signing in, by skipping, or by pulling it down — is what finishes
|
||||
/// adding. Only instances that have accounts at all get this far.
|
||||
@State private var signInInstance: Instance?
|
||||
|
||||
// Closure to dismiss the parent sheet
|
||||
var dismissSheet: DismissAction?
|
||||
|
||||
@@ -131,6 +138,9 @@ struct AddRemoteServerView: View {
|
||||
Text(String(localized: "sources.yatteeServer.warning.message"))
|
||||
}
|
||||
.presentationCompactAdaptation(.sheet)
|
||||
.fullScreenCover(item: $signInInstance, onDismiss: finishAdding) { instance in
|
||||
signInStep(for: instance)
|
||||
}
|
||||
#else
|
||||
formContent
|
||||
.navigationTitle(String(localized: "sources.addRemoteServer"))
|
||||
@@ -147,20 +157,30 @@ struct AddRemoteServerView: View {
|
||||
Text(String(localized: "sources.yatteeServer.warning.message"))
|
||||
}
|
||||
.presentationCompactAdaptation(.sheet)
|
||||
.sheet(item: $signInInstance, onDismiss: finishAdding) { instance in
|
||||
signInStep(for: instance)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// The optional login offered right after a source that supports accounts
|
||||
/// is added, so the common case does not need a second trip through
|
||||
/// settings to become useful.
|
||||
private func signInStep(for instance: Instance) -> some View {
|
||||
InstanceLoginView(instance: instance, isOptionalStep: true) { credential, username in
|
||||
guard let appEnvironment else { return false }
|
||||
return AccountSignInHandler(appEnvironment: appEnvironment, instance: instance)
|
||||
.storeLogin(credential: credential, username: username, target: .newAccount)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var yatteeServerWarningButtons: some View {
|
||||
Button(String(localized: "sources.yatteeServer.warning.disableOthers"), role: .destructive) {
|
||||
if let instance = pendingYatteeServerInstance {
|
||||
appEnvironment?.instancesManager.disableOtherYatteeServerInstances(except: instance.id)
|
||||
appEnvironment?.instancesManager.add(instance)
|
||||
if let dismissSheet {
|
||||
dismissSheet()
|
||||
} else {
|
||||
dismiss()
|
||||
}
|
||||
finishAdding()
|
||||
}
|
||||
}
|
||||
Button(String(localized: "common.cancel"), role: .cancel) {
|
||||
@@ -768,11 +788,7 @@ struct AddRemoteServerView: View {
|
||||
showingYatteeServerWarning = true
|
||||
} else {
|
||||
appEnvironment.instancesManager.add(instance)
|
||||
if let dismissSheet {
|
||||
dismissSheet()
|
||||
} else {
|
||||
dismiss()
|
||||
}
|
||||
finishAdding()
|
||||
}
|
||||
} else {
|
||||
credentialValidationError = String(localized: "sources.error.invalidCredentials")
|
||||
@@ -802,6 +818,20 @@ struct AddRemoteServerView: View {
|
||||
}
|
||||
|
||||
appEnvironment.instancesManager.add(instance)
|
||||
|
||||
// A source that can hold accounts is worth offering a login for while
|
||||
// the user is still here. Everything else is done.
|
||||
if instance.supportsAuthentication {
|
||||
signInInstance = instance
|
||||
} else {
|
||||
finishAdding()
|
||||
}
|
||||
}
|
||||
|
||||
/// Closes the add flow. Reached directly for sources with no login step,
|
||||
/// and as the sign-in sheet's dismissal for the ones that have it —
|
||||
/// signing in and skipping end the same way.
|
||||
private func finishAdding() {
|
||||
if let dismissSheet {
|
||||
dismissSheet()
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user