Bubble/Threaded/Views/Settings/SettingsView.swift

325 lines
13 KiB
Swift
Raw Normal View History

2023-12-29 11:17:37 +01:00
//Made by Lumaa
import SwiftUI
2024-02-24 13:21:31 +01:00
import SwiftData
import WatchConnectivity
2023-12-29 11:17:37 +01:00
struct SettingsView: View {
2024-02-08 08:34:36 +01:00
@Environment(UniversalNavigator.self) private var uniNav: UniversalNavigator
2024-02-24 13:21:31 +01:00
@Query private var loggedAccounts: [LoggedAccount]
2024-03-23 11:13:43 +01:00
@EnvironmentObject private var navigator: Navigator
2024-02-24 13:21:31 +01:00
@State private var switched: Bool = false
2023-12-29 11:17:37 +01:00
var body: some View {
2024-03-23 11:13:43 +01:00
List {
if loggedAccounts.count > 0 {
Section {
ForEach(loggedAccounts) { logged in
if let app = logged.app {
SwitcherRow(app: app, loggedAccount: logged)
.listRowThreaded()
2024-02-24 13:21:31 +01:00
}
}
2024-03-23 11:13:43 +01:00
if AppDelegate.premium || loggedAccounts.count < 3 {
Button {
uniNav.presentedSheet = .mastodonLogin(logged: $switched)
} label: {
Label("settings.account-switcher.add", systemImage: "person.crop.circle.badge.plus")
.foregroundStyle(Color.blue)
2024-02-24 13:21:31 +01:00
}
.listRowThreaded()
}
}
2024-03-23 11:13:43 +01:00
.onChange(of: switched) { _, new in
if new == true {
// switched correctly
HapticManager.playHaptics(haptics: Haptic.success)
uniNav.selectedTab = .timeline
navigator.path = []
2024-03-07 23:24:44 +01:00
}
2024-03-23 11:13:43 +01:00
}
} else {
Section {
//MARK: Remove in later update
HStack(alignment: .center) {
Spacer()
Text("settings.account-switcher.relog")
.foregroundStyle(Color.gray)
.multilineTextAlignment(.center)
.font(.caption)
Spacer()
2024-02-12 00:47:39 +01:00
}
.listRowThreaded()
2024-03-23 11:13:43 +01:00
}
}
Spacer()
.frame(height: 30)
.listRowThreaded()
Section {
Text("settings.restart-app")
.font(.caption)
.foregroundStyle(Color.gray)
.listRowThreaded()
2024-03-23 11:13:43 +01:00
Button {
navigator.navigate(to: .about)
} label: {
Label("about", systemImage: "info.circle")
}
.listRowThreaded()
2024-07-30 18:43:03 +02:00
Button {
navigator.navigate(to: .appicon)
} label: {
Label("setting.app-icon", systemImage: "app.dashed")
}
.listRowThreaded()
2024-03-23 11:13:43 +01:00
Button {
navigator.navigate(to: .privacy)
} label: {
Label("privacy", systemImage: "lock")
}
.listRowThreaded()
Button {
navigator.presentedCover = .shop
} label: {
Label {
Text(String("Threaded+"))
} icon: {
Image("HeroPlus")
.resizable()
.scaledToFit()
}
2024-03-23 11:13:43 +01:00
}
.listRowThreaded()
Button {
navigator.navigate(to: .support)
} label: {
Label("setting.support", systemImage: "person.crop.circle.badge.questionmark")
}
.listRowThreaded()
// Button {
// navigator.navigate(to: .appearence)
// } label: {
// Label("setting.appearence", systemImage: "rectangle.3.group")
// }
// .listRowThreaded()
2024-03-23 11:13:43 +01:00
Button {
if loggedAccounts.count <= 1 {
AppAccount.clear()
navigator.path = []
uniNav.selectedTab = .timeline
uniNav.presentedCover = .welcome
} else {
Task {
if let app = loggedAccounts[0].app {
let c: Client = Client(server: app.server, oauthToken: app.oauthToken)
let am: AccountManager = .init(client: c)
let fetched: Account? = await am.fetchAccount()
if fetched == nil {
am.clear()
} else {
AccountManager.shared.setAccount(fetched!)
AccountManager.shared.setClient(c)
2024-03-08 14:29:11 +01:00
2024-03-23 11:13:43 +01:00
navigator.path = []
uniNav.selectedTab = .timeline
2024-03-08 14:29:11 +01:00
}
}
}
}
2024-03-23 11:13:43 +01:00
} label: {
Text("logout")
.foregroundStyle(.red)
}
2024-03-23 11:13:43 +01:00
.tint(Color.red)
.listRowThreaded()
}
2023-12-29 11:17:37 +01:00
}
2024-03-23 11:13:43 +01:00
.withAppRouter(navigator)
.withCovers(sheetDestination: $navigator.presentedCover)
.listThreaded()
.navigationTitle("settings")
.navigationBarTitleDisplayMode(.inline)
2024-08-10 17:32:41 +02:00
.onAppear {
navigator.showTabbar = false
}
.onChange(of: navigator.path) { _, newValue in
guard !newValue.isEmpty else { navigator.showTabbar = true; return }
navigator.showTabbar = newValue
.filter({ $0 == RouterDestination.settings }).first == nil
}
2023-12-29 11:17:37 +01:00
}
}
2024-02-24 13:21:31 +01:00
extension SettingsView {
struct SwitcherRow: View {
@Environment(\.modelContext) private var modelContext
2024-02-24 13:21:31 +01:00
@Environment(AccountManager.self) private var accountManager: AccountManager
@Environment(UniversalNavigator.self) private var uniNav: UniversalNavigator
@EnvironmentObject private var navigator: Navigator
var logged: LoggedAccount
2024-02-24 13:21:31 +01:00
var app: AppAccount
// private let connectivity: SessionDelegator = .init()
2024-02-24 13:21:31 +01:00
@State private var account: Account? = nil
@State private var error: Bool = false
private var currentAccount: Bool {
2024-03-07 23:24:44 +01:00
let currentAccount = AccountManager.shared.forceAccount()
let currentClient = AccountManager.shared.forceClient()
let currentAcct = "\(currentAccount.acct)@\(currentClient.server)"
return currentAcct == app.accountName ?? ""
2024-02-24 13:21:31 +01:00
}
init(app: AppAccount, loggedAccount: LoggedAccount) {
2024-02-24 13:21:31 +01:00
self.app = app
self.logged = loggedAccount
2024-02-24 13:21:31 +01:00
}
var body: some View {
ZStack {
if let acc = account {
HStack {
2024-02-29 13:33:29 +01:00
ProfilePicture(url: acc.avatar, size: 46)
2024-02-24 13:21:31 +01:00
VStack(alignment: .leading) {
Text(acc.displayName ?? "@\(acc.acct)")
.multilineTextAlignment(.leading)
Text("@\(acc.acct)")
.multilineTextAlignment(.leading)
.font(.caption)
.foregroundStyle(Color.gray)
}
Spacer()
if !currentAccount {
Button {
Task {
let c: Client = Client(server: app.server, oauthToken: app.oauthToken)
let am: AccountManager = .init(client: c)
let fetched: Account? = await am.fetchAccount()
if fetched == nil {
am.clear()
error = true
} else {
AccountManager.shared.setAccount(fetched!)
AccountManager.shared.setClient(c)
2024-02-24 13:21:31 +01:00
navigator.path = []
uniNav.selectedTab = .timeline
2024-02-24 13:21:31 +01:00
}
}
} label: {
Text("settings.account-switcher.log")
}
.buttonStyle(LargeButton(filled: true, height: 7.5, disabled: currentAccount))
.disabled(currentAccount)
} else {
Text("settings.account-switcher.current")
.foregroundStyle(Color.gray)
.font(.caption)
.padding(.horizontal)
.lineLimit(1)
}
}
.contextMenu {
2024-06-23 17:48:40 +02:00
Button {
app.saveAsCurrent()
} label: {
Label("settings.account-switcher.default", systemImage: "person.crop.circle.dashed")
}
2024-03-08 14:29:11 +01:00
if !currentAccount {
Button(role: .destructive) {
modelContext.delete(self.logged)
} label: {
Label("settings.account-switcher.remove", systemImage: "trash")
}
}
Divider()
// if connectivity.isWorking {
// Button {
// // double check in case states change in between
// if connectivity.isWorking {
// let message = GivenAccount(acct: app.accountName!, bearerToken: app.oauthToken?.accessToken ?? "")
// connectivity.session.sendMessageData(message.turnToMessage(), replyHandler: { data in
// let str = String(data: data, encoding: .utf8)
// print(str ?? "No data?")
// HapticManager.playHaptics(haptics: Haptic.success)
// })
// } else {
// print("No Watch?")
// }
// } label: {
// Label("settings.account-switcher.send-to-watch", systemImage: "applewatch.and.arrow.forward")
// }
// }
}
2024-02-24 13:21:31 +01:00
} else {
Circle()
.fill(error ? Color.red.opacity(0.45) : Color.gray.opacity(0.45))
2024-03-08 14:29:11 +01:00
.frame(width: 36, height: 36)
2024-02-24 13:21:31 +01:00
VStack(alignment: .leading) {
Text(Account.placeholder().displayName ?? "@\(Account.placeholder().acct)")
.redacted(reason: .placeholder)
.multilineTextAlignment(.leading)
Text("@\(Account.placeholder().acct)")
.redacted(reason: .placeholder)
.multilineTextAlignment(.leading)
.font(.caption)
.foregroundStyle(Color.gray)
}
Spacer()
Button {
print(acct)
} label: {
Text("settings.account-switcher.log")
.redacted(reason: .placeholder)
}
.buttonStyle(LargeButton(filled: true, height: 7.5))
}
}
.task {
account = await findAccount(acct: app.accountName!)
// connectivity.initialize()
2024-02-24 13:21:31 +01:00
}
}
private func findAccount(acct: String) async -> Account? {
guard let client = accountManager.getClient() else { return nil }
do {
try await Task.sleep(for: .milliseconds(250))
let results: SearchResults = try await client.get(endpoint: Search.search(query: acct, type: "accounts", offset: nil, following: nil), forceVersion: .v2)
return results.accounts.first
} catch {
print(error)
}
return nil
}
}
2023-12-29 11:17:37 +01:00
}