mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-12-23 23:50:36 +00:00
Reworked account management / selection UI
This commit is contained in:
parent
6c6d25fc63
commit
40ca3940f6
5 changed files with 89 additions and 29 deletions
|
@ -21,6 +21,7 @@ struct SettingsTabs: View {
|
|||
@StateObject private var routerPath = RouterPath()
|
||||
|
||||
@State private var addAccountSheetPresented = false
|
||||
@State private var isEditingAccount = false
|
||||
|
||||
@Binding var popToRootTab: Tab
|
||||
|
||||
|
@ -69,27 +70,47 @@ struct SettingsTabs: View {
|
|||
private var accountsSection: some View {
|
||||
Section("settings.section.accounts") {
|
||||
ForEach(appAccountsManager.availableAccounts) { account in
|
||||
AppAccountView(viewModel: .init(appAccount: account))
|
||||
HStack {
|
||||
if isEditingAccount {
|
||||
Button {
|
||||
Task {
|
||||
await logoutAccount(account: account)
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "trash")
|
||||
.renderingMode(.template)
|
||||
.tint(.red)
|
||||
}
|
||||
}
|
||||
AppAccountView(viewModel: .init(appAccount: account))
|
||||
}
|
||||
}
|
||||
.onDelete { indexSet in
|
||||
if let index = indexSet.first {
|
||||
let account = appAccountsManager.availableAccounts[index]
|
||||
if let token = account.oauthToken,
|
||||
let sub = pushNotifications.subscriptions.first(where: { $0.account.token == token })
|
||||
{
|
||||
Task {
|
||||
let client = Client(server: account.server, oauthToken: token)
|
||||
await TimelineCache.shared.clearCache(for: client)
|
||||
await sub.deleteSubscription()
|
||||
appAccountsManager.delete(account: account)
|
||||
}
|
||||
Task {
|
||||
await logoutAccount(account: account)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !appAccountsManager.availableAccounts.isEmpty {
|
||||
editAccountButton
|
||||
}
|
||||
addAccountButton
|
||||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
|
||||
private func logoutAccount(account: AppAccount) async {
|
||||
if let token = account.oauthToken,
|
||||
let sub = pushNotifications.subscriptions.first(where: { $0.account.token == token })
|
||||
{
|
||||
let client = Client(server: account.server, oauthToken: token)
|
||||
await TimelineCache.shared.clearCache(for: client)
|
||||
await sub.deleteSubscription()
|
||||
appAccountsManager.delete(account: account)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var generalSection: some View {
|
||||
|
@ -214,6 +235,20 @@ struct SettingsTabs: View {
|
|||
AddAccountView()
|
||||
}
|
||||
}
|
||||
|
||||
private var editAccountButton: some View {
|
||||
Button(role: isEditingAccount ? .none : .destructive) {
|
||||
withAnimation {
|
||||
isEditingAccount.toggle()
|
||||
}
|
||||
} label: {
|
||||
if isEditingAccount {
|
||||
Text("action.done")
|
||||
} else {
|
||||
Text("account.action.logout")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var remoteLocalTimelinesView: some View {
|
||||
Form {
|
||||
|
|
|
@ -6,12 +6,22 @@ import SwiftUI
|
|||
@MainActor
|
||||
public class AppAccountViewModel: ObservableObject {
|
||||
private static var avatarsCache: [String: UIImage] = [:]
|
||||
private static var accountsCache: [String: Account] = [:]
|
||||
|
||||
var appAccount: AppAccount
|
||||
let client: Client
|
||||
let isCompact: Bool
|
||||
|
||||
@Published var account: Account?
|
||||
@Published var account: Account? {
|
||||
didSet {
|
||||
if let account {
|
||||
refreshAcct(account: account)
|
||||
Task {
|
||||
await refreshAvatar(account: account)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Published var roundedAvatar: UIImage?
|
||||
|
||||
var acct: String {
|
||||
|
@ -30,23 +40,31 @@ public class AppAccountViewModel: ObservableObject {
|
|||
|
||||
func fetchAccount() async {
|
||||
do {
|
||||
account = Self.accountsCache[appAccount.id]
|
||||
roundedAvatar = Self.avatarsCache[appAccount.id]
|
||||
|
||||
account = try await client.get(endpoint: Accounts.verifyCredentials)
|
||||
if appAccount.accountName == nil, let account {
|
||||
|
||||
Self.accountsCache[appAccount.id] = account
|
||||
|
||||
} catch {}
|
||||
}
|
||||
|
||||
private func refreshAcct(account: Account) {
|
||||
do {
|
||||
if appAccount.accountName == nil {
|
||||
appAccount.accountName = "\(account.acct)@\(appAccount.server)"
|
||||
try appAccount.save()
|
||||
}
|
||||
|
||||
if let account {
|
||||
if let image = Self.avatarsCache[account.id] {
|
||||
roundedAvatar = image
|
||||
} else if let (data, _) = try? await URLSession.shared.data(from: account.avatar),
|
||||
let image = UIImage(data: data)?.roundedImage
|
||||
{
|
||||
roundedAvatar = image
|
||||
Self.avatarsCache[account.id] = image
|
||||
}
|
||||
}
|
||||
|
||||
} catch {}
|
||||
} catch { }
|
||||
}
|
||||
|
||||
private func refreshAvatar(account: Account) async {
|
||||
if roundedAvatar == nil,
|
||||
let (data, _) = try? await URLSession.shared.data(from: account.avatar),
|
||||
let image = UIImage(data: data)?.roundedImage {
|
||||
roundedAvatar = image
|
||||
Self.avatarsCache[account.id] = image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ public struct AppAccountsSelectorView: View {
|
|||
if let avatar = currentAccount.account?.avatar, !currentAccount.isLoadingAccount {
|
||||
AvatarView(url: avatar, size: avatarSize)
|
||||
} else {
|
||||
ProgressView()
|
||||
AvatarView(url: nil, size: avatarSize)
|
||||
.redacted(reason: .placeholder)
|
||||
}
|
||||
}.overlay(alignment: .topTrailing) {
|
||||
if !currentAccount.followRequests.isEmpty {
|
||||
|
|
|
@ -39,10 +39,10 @@ public struct AvatarView: View {
|
|||
}
|
||||
}
|
||||
|
||||
public let url: URL
|
||||
public let url: URL?
|
||||
public let size: Size
|
||||
|
||||
public init(url: URL, size: Size = .status) {
|
||||
public init(url: URL?, size: Size = .status) {
|
||||
self.url = url
|
||||
self.size = size
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import Network
|
|||
|
||||
@MainActor
|
||||
public class CurrentAccount: ObservableObject {
|
||||
static private var accountsCache: [String: Account] = [:]
|
||||
|
||||
@Published public private(set) var account: Account?
|
||||
@Published public private(set) var lists: [List] = []
|
||||
@Published public private(set) var tags: [Tag] = []
|
||||
|
@ -57,9 +59,13 @@ public class CurrentAccount: ObservableObject {
|
|||
account = nil
|
||||
return
|
||||
}
|
||||
isLoadingAccount = true
|
||||
account = Self.accountsCache[client.id]
|
||||
if account == nil {
|
||||
isLoadingAccount = true
|
||||
}
|
||||
account = try? await client.get(endpoint: Accounts.verifyCredentials)
|
||||
isLoadingAccount = false
|
||||
Self.accountsCache[client.id] = account
|
||||
}
|
||||
|
||||
public func fetchLists() async {
|
||||
|
|
Loading…
Reference in a new issue