Fix crash issue after first sign in.
This commit is contained in:
parent
68e40d2fd1
commit
2320a83ff5
|
@ -35,9 +35,9 @@ class ApplicationSettingsHandler {
|
|||
}
|
||||
}
|
||||
|
||||
func set(accountData: AccountData?) {
|
||||
func set(accountId: String?) {
|
||||
let defaultSettings = self.get()
|
||||
defaultSettings.currentAccount = accountData?.id
|
||||
defaultSettings.currentAccount = accountId
|
||||
CoreDataHandler.shared.save()
|
||||
}
|
||||
|
||||
|
|
|
@ -1308,7 +1308,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 89;
|
||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = VernissageWidget/Info.plist;
|
||||
|
@ -1336,7 +1336,7 @@
|
|||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 89;
|
||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = VernissageWidget/Info.plist;
|
||||
|
@ -1484,7 +1484,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 89;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
|
@ -1524,7 +1524,7 @@
|
|||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 88;
|
||||
CURRENT_PROJECT_VERSION = 89;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
|
|
|
@ -15,28 +15,28 @@ public class AuthorizationService {
|
|||
private init() { }
|
||||
|
||||
/// Access token verification.
|
||||
public func verifyAccount(session: AuthorizationSession, currentAccount: AccountData?, _ result: @escaping (AccountData?) -> Void) async {
|
||||
public func verifyAccount(session: AuthorizationSession, accountModel: AccountModel, _ result: @escaping (AccountModel?) -> Void) async {
|
||||
// When we dont have even one account stored in database then we have to ask user to enter server and sign in.
|
||||
guard let currentAccount, let accessToken = currentAccount.accessToken else {
|
||||
guard let accessToken = accountModel.accessToken else {
|
||||
result(nil)
|
||||
return
|
||||
}
|
||||
|
||||
// When we have at least one account then we have to verify access token.
|
||||
let client = PixelfedClient(baseURL: currentAccount.serverUrl).getAuthenticated(token: accessToken)
|
||||
let client = PixelfedClient(baseURL: accountModel.serverUrl).getAuthenticated(token: accessToken)
|
||||
|
||||
do {
|
||||
let account = try await client.verifyCredentials()
|
||||
await self.update(accountId: currentAccount.id,
|
||||
let signedInAccountModel = await self.update(accountId: accountModel.id,
|
||||
basedOn: account,
|
||||
accessToken: accessToken,
|
||||
refreshToken: currentAccount.refreshToken)
|
||||
refreshToken: accountModel.refreshToken)
|
||||
|
||||
result(currentAccount)
|
||||
result(signedInAccountModel)
|
||||
} catch {
|
||||
do {
|
||||
try await self.refreshCredentials(for: currentAccount, presentationContextProvider: session)
|
||||
result(currentAccount)
|
||||
let signedInAccountModel = try await self.refreshCredentials(for: accountModel, presentationContextProvider: session)
|
||||
result(signedInAccountModel)
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Issues during refreshing credentials.", showToastr: true)
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ public class AuthorizationService {
|
|||
}
|
||||
|
||||
/// Sign in to the Pixelfed server.
|
||||
public func sign(in serverAddress: String, session: AuthorizationSession, _ result: @escaping (AccountData) -> Void) async throws {
|
||||
public func sign(in serverAddress: String, session: AuthorizationSession, _ result: @escaping (AccountModel) -> Void) async throws {
|
||||
|
||||
guard let baseUrl = URL(string: serverAddress) else {
|
||||
throw AuthorisationError.badServerUrl
|
||||
|
@ -124,7 +124,8 @@ public class AuthorizationService {
|
|||
CoreDataHandler.shared.save(viewContext: backgroundContext)
|
||||
|
||||
// Return account data.
|
||||
result(accountData)
|
||||
let accountModel = AccountModel(accountData: accountData)
|
||||
result(accountModel)
|
||||
}
|
||||
|
||||
public func refreshAccessTokens() async {
|
||||
|
@ -134,7 +135,7 @@ public class AuthorizationService {
|
|||
for account in accounts {
|
||||
group.addTask {
|
||||
do {
|
||||
try await self.refreshAccessToken(accountData: account)
|
||||
_ = try await self.refreshAccessToken(accountData: account)
|
||||
|
||||
#if DEBUG
|
||||
ToastrService.shared.showSuccess("New access tokens has been retrieved.", imageSystemName: "key.fill")
|
||||
|
@ -151,11 +152,11 @@ public class AuthorizationService {
|
|||
}
|
||||
}
|
||||
|
||||
private func refreshAccessToken(accountData: AccountData) async throws {
|
||||
private func refreshAccessToken(accountData: AccountData) async throws -> AccountModel? {
|
||||
let client = PixelfedClient(baseURL: accountData.serverUrl)
|
||||
|
||||
guard let refreshToken = accountData.refreshToken else {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
let oAuthSwiftCredential = try await client.refreshToken(clientId: accountData.clientId,
|
||||
|
@ -167,21 +168,22 @@ public class AuthorizationService {
|
|||
|
||||
// Get account information from server.
|
||||
let account = try await authenticatedClient.verifyCredentials()
|
||||
await self.update(accountId: accountData.id,
|
||||
|
||||
return await self.update(accountId: accountData.id,
|
||||
basedOn: account,
|
||||
accessToken: oAuthSwiftCredential.oauthToken,
|
||||
refreshToken: oAuthSwiftCredential.oauthRefreshToken)
|
||||
}
|
||||
|
||||
private func refreshCredentials(for accountData: AccountData,
|
||||
private func refreshCredentials(for accountModel: AccountModel,
|
||||
presentationContextProvider: ASWebAuthenticationPresentationContextProviding
|
||||
) async throws {
|
||||
) async throws -> AccountModel? {
|
||||
|
||||
let client = PixelfedClient(baseURL: accountData.serverUrl)
|
||||
let client = PixelfedClient(baseURL: accountModel.serverUrl)
|
||||
|
||||
// Create application (we will get clientId and clientSecret).
|
||||
let oAuthApp = Application(clientId: accountData.clientId,
|
||||
clientSecret: accountData.clientSecret,
|
||||
let oAuthApp = Application(clientId: accountModel.clientId,
|
||||
clientSecret: accountModel.clientSecret,
|
||||
redirectUri: AppConstants.oauthRedirectUri)
|
||||
|
||||
// Authorize a user (browser, we will get clientCode).
|
||||
|
@ -195,7 +197,8 @@ public class AuthorizationService {
|
|||
|
||||
// Get account information from server.
|
||||
let account = try await authenticatedClient.verifyCredentials()
|
||||
await self.update(accountId: accountData.id,
|
||||
|
||||
return await self.update(accountId: accountModel.id,
|
||||
basedOn: account,
|
||||
accessToken: oAuthSwiftCredential.oauthToken,
|
||||
refreshToken: oAuthSwiftCredential.oauthRefreshToken)
|
||||
|
@ -205,10 +208,10 @@ public class AuthorizationService {
|
|||
basedOn account: Account,
|
||||
accessToken: String,
|
||||
refreshToken: String?
|
||||
) async {
|
||||
) async -> AccountModel? {
|
||||
let backgroundContext = CoreDataHandler.shared.newBackgroundContext()
|
||||
guard let dbAccount = AccountDataHandler.shared.getAccountData(accountId: accountId, viewContext: backgroundContext) else {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
dbAccount.username = account.username
|
||||
|
@ -241,6 +244,8 @@ public class AuthorizationService {
|
|||
|
||||
// Save account data in database and in application state.
|
||||
CoreDataHandler.shared.save(viewContext: backgroundContext)
|
||||
|
||||
return AccountModel(accountData: dbAccount)
|
||||
}
|
||||
|
||||
private func getAccountData(account: Account, backgroundContext: NSManagedObjectContext) -> AccountData {
|
||||
|
|
|
@ -34,8 +34,8 @@ struct VernissageApp: App {
|
|||
.withAppRouteur()
|
||||
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
||||
case .signIn:
|
||||
SignInView { accountData in
|
||||
self.setApplicationState(accountData: accountData)
|
||||
SignInView { accountModel in
|
||||
self.setApplicationState(accountModel: accountModel)
|
||||
}
|
||||
.withAppRouteur()
|
||||
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
||||
|
@ -91,6 +91,7 @@ struct VernissageApp: App {
|
|||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func onApplicationStart() async {
|
||||
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.white.withAlphaComponent(0.7)
|
||||
UIPageControl.appearance().pageIndicatorTintColor = UIColor.white.withAlphaComponent(0.4)
|
||||
|
@ -104,22 +105,29 @@ struct VernissageApp: App {
|
|||
// Refresh other access tokens.
|
||||
await self.refreshAccessTokens()
|
||||
|
||||
// Verify access token correctness.
|
||||
let authorizationSession = AuthorizationSession()
|
||||
let currentAccount = AccountDataHandler.shared.getCurrentAccountData()
|
||||
await AuthorizationService.shared.verifyAccount(session: authorizationSession, currentAccount: currentAccount) { accountData in
|
||||
guard let accountData = accountData else {
|
||||
// When user doesn't exists then we have to open sign in view.
|
||||
guard let currentAccount = AccountDataHandler.shared.getCurrentAccountData() else {
|
||||
self.applicationViewMode = .signIn
|
||||
return
|
||||
}
|
||||
|
||||
self.setApplicationState(accountData: accountData, checkNewPhotos: true)
|
||||
// Create model based on core data entity.
|
||||
let accountModel = AccountModel(accountData: currentAccount)
|
||||
|
||||
// Verify access token correctness.
|
||||
let authorizationSession = AuthorizationSession()
|
||||
await AuthorizationService.shared.verifyAccount(session: authorizationSession, accountModel: accountModel) { signedInAccountModel in
|
||||
guard let signedInAccountModel else {
|
||||
self.applicationViewMode = .signIn
|
||||
return
|
||||
}
|
||||
|
||||
self.setApplicationState(accountModel: signedInAccountModel, checkNewPhotos: true)
|
||||
}
|
||||
}
|
||||
|
||||
private func setApplicationState(accountData: AccountData, checkNewPhotos: Bool = false) {
|
||||
private func setApplicationState(accountModel: AccountModel, checkNewPhotos: Bool = false) {
|
||||
Task { @MainActor in
|
||||
let accountModel = AccountModel(accountData: accountData)
|
||||
let instance = try? await self.client.instances.instance(url: accountModel.serverUrl)
|
||||
|
||||
// Refresh client state.
|
||||
|
@ -128,7 +136,7 @@ struct VernissageApp: App {
|
|||
// Refresh application state.
|
||||
self.applicationState.changeApplicationState(accountModel: accountModel,
|
||||
instance: instance,
|
||||
lastSeenStatusId: accountData.lastSeenStatusId)
|
||||
lastSeenStatusId: accountModel.lastSeenStatusId)
|
||||
|
||||
// Change view displayed by application.
|
||||
self.applicationViewMode = .mainView
|
||||
|
|
|
@ -323,26 +323,27 @@ struct MainView: View {
|
|||
Task {
|
||||
// Verify access token correctness.
|
||||
let authorizationSession = AuthorizationSession()
|
||||
await AuthorizationService.shared.verifyAccount(session: authorizationSession, currentAccount: account) { accountData in
|
||||
guard let accountData = accountData else {
|
||||
let accountModel = AccountModel(accountData: account)
|
||||
|
||||
await AuthorizationService.shared.verifyAccount(session: authorizationSession, accountModel: accountModel) { signedInAccountModel in
|
||||
guard let signedInAccountModel else {
|
||||
ToastrService.shared.showError(subtitle: "mainview.error.switchAccounts")
|
||||
return
|
||||
}
|
||||
|
||||
Task { @MainActor in
|
||||
let accountModel = AccountModel(accountData: accountData)
|
||||
let instance = try? await self.client.instances.instance(url: accountModel.serverUrl)
|
||||
let instance = try? await self.client.instances.instance(url: signedInAccountModel.serverUrl)
|
||||
|
||||
// Refresh client state.
|
||||
self.client.setAccount(account: accountModel)
|
||||
self.client.setAccount(account: signedInAccountModel)
|
||||
|
||||
// Refresh application state.
|
||||
self.applicationState.changeApplicationState(accountModel: accountModel,
|
||||
self.applicationState.changeApplicationState(accountModel: signedInAccountModel,
|
||||
instance: instance,
|
||||
lastSeenStatusId: accountData.lastSeenStatusId)
|
||||
lastSeenStatusId: signedInAccountModel.lastSeenStatusId)
|
||||
|
||||
// Set account as default (application will open this account after restart).
|
||||
ApplicationSettingsHandler.shared.set(accountData: accountData)
|
||||
ApplicationSettingsHandler.shared.set(accountId: signedInAccountModel.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ struct AccountsSectionView: View {
|
|||
if shouldClearApplicationState {
|
||||
// We have to do this after animation of deleting row is ended.
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
ApplicationSettingsHandler.shared.set(accountData: nil)
|
||||
ApplicationSettingsHandler.shared.set(accountId: nil)
|
||||
self.applicationState.clearApplicationState()
|
||||
self.client.clearAccount()
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ struct SignInView: View {
|
|||
@State private var instructionsUrlString:String?
|
||||
@State private var instances: [Instance] = []
|
||||
|
||||
var onSignedIn: ((_ accountData: AccountData) -> Void)?
|
||||
var onSignedIn: ((_ accountModel: AccountModel) -> Void)?
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
|
@ -91,8 +91,8 @@ struct SignInView: View {
|
|||
Task {
|
||||
do {
|
||||
let authorizationSession = AuthorizationSession()
|
||||
try await AuthorizationService.shared.sign(in: baseAddress, session: authorizationSession) { accountData in
|
||||
onSignedIn?(accountData)
|
||||
try await AuthorizationService.shared.sign(in: baseAddress, session: authorizationSession) { accountModel in
|
||||
onSignedIn?(accountModel)
|
||||
|
||||
DispatchQueue.main.sync {
|
||||
dismiss()
|
||||
|
|
Loading…
Reference in New Issue