Deleting last of the accounts

This commit is contained in:
Marcin Czachursk 2023-02-23 08:09:02 +01:00
parent 77fbe141a8
commit 482eecfd34
12 changed files with 100 additions and 19 deletions

View File

@ -8,7 +8,7 @@ import Foundation
public extension PixelfedClient {
func readInstanceInformation() async throws -> Instance {
let request = try Self.request(for: baseURL, target: Pixelfed.Instances.instance)
let request = try Self.request(for: baseURL, target: Pixelfed.Instances.instance, timeoutInterval: 5)
return try await downloadJson(Instance.self, request: request)
}
}

View File

@ -12,11 +12,11 @@ public enum PixelfedClientError: Swift.Error {
}
public protocol PixelfedClientProtocol {
static func request(for baseURL: URL, target: TargetType, withBearerToken token: String?) throws -> URLRequest
static func request(for baseURL: URL, target: TargetType, withBearerToken token: String?, timeoutInterval: Double?) throws -> URLRequest
}
public extension PixelfedClientProtocol {
static func request(for baseURL: URL, target: TargetType, withBearerToken token: String? = nil) throws -> URLRequest {
static func request(for baseURL: URL, target: TargetType, withBearerToken token: String? = nil, timeoutInterval: Double? = nil) throws -> URLRequest {
var urlComponents = URLComponents(url: baseURL.appendingPathComponent(target.path), resolvingAgainstBaseURL: false)
urlComponents?.queryItems = target.queryItems?.map { URLQueryItem(name: $0.0, value: $0.1) }
@ -25,6 +25,10 @@ public extension PixelfedClientProtocol {
var request = URLRequest(url: url)
if let timeoutInterval {
request.timeoutInterval = timeoutInterval
}
target.headers?.forEach { header in
request.setValue(header.1, forHTTPHeaderField: header.0)
}

View File

@ -1035,7 +1035,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 27;
CURRENT_PROJECT_VERSION = 28;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@ -1072,7 +1072,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 27;
CURRENT_PROJECT_VERSION = 28;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;

View File

@ -34,9 +34,9 @@ class ApplicationSettingsHandler {
}
}
func setAccountAsDefault(accountData: AccountData) {
func setAccountAsDefault(accountData: AccountData?) {
let defaultSettings = self.getDefaultSettings()
defaultSettings.currentAccount = accountData.id
defaultSettings.currentAccount = accountData?.id
CoreDataHandler.shared.save()
}

View File

@ -70,4 +70,14 @@ public class ApplicationState: ObservableObject {
self.statusCharactersReservedPerUrl = ApplicationState.defaults.statusCharactersReservedPerUrl
}
}
public func clearApplicationState() {
self.account = nil
self.lastSeenStatusId = nil
self.amountOfNewStatuses = 0
self.statusMaxCharacters = ApplicationState.defaults.statusMaxCharacters
self.statusMaxMediaAttachments = ApplicationState.defaults.statusMaxMediaAttachments
self.statusCharactersReservedPerUrl = ApplicationState.defaults.statusCharactersReservedPerUrl
}
}

View File

@ -20,6 +20,10 @@ public class Client: ObservableObject {
self.pixelfedClient = PixelfedClient(baseURL: account.serverUrl).getAuthenticated(token: accessToken)
}
func clearAccount() {
self.pixelfedClient = nil
}
}
extension Client {

View File

@ -6,7 +6,8 @@
import Foundation
public class AccountModel: ObservableObject {
public class AccountModel: ObservableObject, Identifiable {
public let id: String
public let accessToken: String?
public let refreshToken: String?
public let acct: String
@ -20,7 +21,6 @@ public class AccountModel: ObservableObject {
public let followersCount: Int32
public let followingCount: Int32
public let header: URL?
public let id: String
public let locked: Bool
public let note: String?
public let serverUrl: URL
@ -53,3 +53,9 @@ public class AccountModel: ObservableObject {
self.lastSeenStatusId = accountData.lastSeenStatusId
}
}
extension AccountModel: Equatable {
public static func == (lhs: AccountModel, rhs: AccountModel) -> Bool {
lhs.id == rhs.id
}
}

View File

@ -95,6 +95,11 @@ struct VernissageApp: App {
.onChange(of: applicationState.tintColor) { newValue in
self.tintColor = newValue.color()
}
.onChange(of: applicationState.account) { newValue in
if newValue == nil {
self.applicationViewMode = .signIn
}
}
}
}

View File

@ -150,7 +150,7 @@ struct ComposeView: View {
.padding(.horizontal, 8)
TextField("Type what's on your mind", text: $text, axis: .vertical)
TextField(self.placeholder(), text: $text, axis: .vertical)
.padding(.horizontal, 8)
.lineLimit(2...12)
.focused($focusedField, equals: .content)
@ -310,14 +310,31 @@ struct ComposeView: View {
Image(systemName: self.place == nil ? "mappin.square" : "mappin.square.fill")
}
Button {
self.text.append("#")
} label: {
Image(systemName: "number")
}
Button {
self.text.append("@")
} label: {
Image(systemName: "at")
}
Spacer()
Text("\(self.applicationState.statusMaxCharacters - text.string.utf16.count)")
.foregroundColor(.lightGrayColor)
}
.font(.callout)
}
}
private func placeholder() -> String {
self.statusViewModel == nil ? "Attach photography and type what's on your mind" : "Type what's on your mind"
}
private func isPublishButtonDisabled() -> Bool {
// Publish always disabled when there is not status text.
if self.text.isEmpty {

View File

@ -47,7 +47,7 @@ struct SettingsView: View {
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Close", role: .cancel) {
dismiss()
self.dismiss()
}
}
}
@ -69,6 +69,11 @@ struct SettingsView: View {
// Change theme of current modal screen (unformtunatelly it's not changed autmatically.
self.theme = self.applicationState.theme.colorScheme() ?? self.getSystemColorScheme()
}
.onChange(of: applicationState.account) { newValue in
if newValue == nil {
self.dismiss()
}
}
.onChange(of: tipsStore.status) { status in
if status == .successful {
withAnimation(.spring()) {

View File

@ -8,8 +8,15 @@ import SwiftUI
struct AccountsSectionView: View {
@EnvironmentObject var applicationState: ApplicationState
@EnvironmentObject var client: Client
@State private var accounts: [AccountData] = []
@State private var accounts: [AccountModel]
private var dbAccounts: [AccountData]
init() {
self.dbAccounts = AccountDataHandler.shared.getAccountsData()
self.accounts = self.dbAccounts.map({ AccountModel(accountData: $0) })
}
var body: some View {
Section("Accounts") {
@ -25,7 +32,7 @@ struct AccountsSectionView: View {
.foregroundColor(self.applicationState.tintColor.color())
}
}
.deleteDisabled(self.applicationState.account?.id == account.id)
.deleteDisabled(self.deleteDisabled(for: account))
}
.onDelete(perform: delete)
@ -37,15 +44,39 @@ struct AccountsSectionView: View {
}
}
}
.task {
self.accounts = AccountDataHandler.shared.getAccountsData()
}
}
func delete(at offsets: IndexSet) {
private func deleteDisabled(for account: AccountModel) -> Bool {
self.applicationState.account?.id == account.id && self.accounts.count > 1
}
private func delete(at offsets: IndexSet) {
let accountsToDelete = offsets.map { self.accounts[$0] }
var shouldClearApplicationState = false
// Delete from database.
for account in accountsToDelete {
AccountDataHandler.shared.remove(accountData: account)
// Check if we are deleting active user.
if account.id == self.applicationState.account?.id {
shouldClearApplicationState = true
}
if let dbAccount = self.dbAccounts.first(where: {$0.id == account.id }) {
AccountDataHandler.shared.remove(accountData: dbAccount)
}
}
// Delete from local state.
self.accounts.remove(atOffsets: offsets)
// When we are deleting active user then we have to switch to sing in view.
if shouldClearApplicationState {
// We have to do this after animation of deleting row is ended.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
ApplicationSettingsHandler.shared.setAccountAsDefault(accountData: nil)
self.applicationState.clearApplicationState()
self.client.clearAccount()
}
}
}
}

View File

@ -8,7 +8,6 @@ import SwiftUI
import StoreKit
struct SupportView: View {
@EnvironmentObject var tipsStore: TipsStore
var body: some View {