Editor character count + settings instance rules

This commit is contained in:
Thomas Ricouard 2022-12-28 08:06:46 +01:00
parent 1b53180faf
commit 5b9f91abd1
5 changed files with 75 additions and 10 deletions

View file

@ -11,6 +11,7 @@ struct IceCubesApp: App {
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@StateObject private var appAccountsManager = AppAccountsManager() @StateObject private var appAccountsManager = AppAccountsManager()
@StateObject private var currenInstance = CurrentInstance()
@StateObject private var currentAccount = CurrentAccount() @StateObject private var currentAccount = CurrentAccount()
@StateObject private var watcher = StreamWatcher() @StateObject private var watcher = StreamWatcher()
@StateObject private var quickLook = QuickLook() @StateObject private var quickLook = QuickLook()
@ -56,6 +57,7 @@ struct IceCubesApp: App {
.environmentObject(appAccountsManager.currentClient) .environmentObject(appAccountsManager.currentClient)
.environmentObject(quickLook) .environmentObject(quickLook)
.environmentObject(currentAccount) .environmentObject(currentAccount)
.environmentObject(currenInstance)
.environmentObject(theme) .environmentObject(theme)
.environmentObject(watcher) .environmentObject(watcher)
.quickLookPreview($quickLook.url, in: quickLook.urls) .quickLookPreview($quickLook.url, in: quickLook.urls)
@ -67,6 +69,7 @@ struct IceCubesApp: App {
private func setNewClientsInEnv(client: Client) { private func setNewClientsInEnv(client: Client) {
currentAccount.setClient(client: client) currentAccount.setClient(client: client)
currenInstance.setClient(client: client)
watcher.setClient(client: client) watcher.setClient(client: client)
} }

View file

@ -9,12 +9,12 @@ import DesignSystem
struct SettingsTabs: View { struct SettingsTabs: View {
@Environment(\.openURL) private var openURL @Environment(\.openURL) private var openURL
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var currentInstance: CurrentInstance
@EnvironmentObject private var appAccountsManager: AppAccountsManager @EnvironmentObject private var appAccountsManager: AppAccountsManager
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@State private var signInInProgress = false @State private var signInInProgress = false
@State private var accountData: Account? @State private var accountData: Account?
@State private var instanceData: Instance?
@State private var signInServer = IceCubesApp.defaultServer @State private var signInServer = IceCubesApp.defaultServer
var body: some View { var body: some View {
@ -37,7 +37,7 @@ struct SettingsTabs: View {
if appAccountsManager.currentAccount.oauthToken != nil { if appAccountsManager.currentAccount.oauthToken != nil {
signInInProgress = true signInInProgress = true
await refreshAccountInfo() await refreshAccountInfo()
await refreshInstanceInfo() await currentInstance.fetchCurrentInstance()
signInInProgress = false signInInProgress = false
} }
} }
@ -77,7 +77,7 @@ struct SettingsTabs: View {
@ViewBuilder @ViewBuilder
private var instanceSection: some View { private var instanceSection: some View {
if let instanceData { if let instanceData = currentInstance.instance {
Section("Instance info") { Section("Instance info") {
LabeledContent("Name", value: instanceData.title) LabeledContent("Name", value: instanceData.title)
Text(instanceData.shortDescription) Text(instanceData.shortDescription)
@ -87,6 +87,12 @@ struct SettingsTabs: View {
LabeledContent("Posts", value: "\(instanceData.stats.statusCount)") LabeledContent("Posts", value: "\(instanceData.stats.statusCount)")
LabeledContent("Domains", value: "\(instanceData.stats.domainCount)") LabeledContent("Domains", value: "\(instanceData.stats.domainCount)")
} }
Section("Instance rules") {
ForEach(instanceData.rules) { rule in
Text(rule.text)
}
}
} }
} }
@ -127,7 +133,6 @@ struct SettingsTabs: View {
private var signOutButton: some View { private var signOutButton: some View {
Button { Button {
instanceData = nil
accountData = nil accountData = nil
appAccountsManager.delete(account: appAccountsManager.currentAccount) appAccountsManager.delete(account: appAccountsManager.currentAccount)
} label: { } label: {
@ -151,7 +156,7 @@ struct SettingsTabs: View {
let oauthToken = try await client.continueOauthFlow(url: url) let oauthToken = try await client.continueOauthFlow(url: url)
appAccountsManager.add(account: AppAccount(server: client.server, oauthToken: oauthToken)) appAccountsManager.add(account: AppAccount(server: client.server, oauthToken: oauthToken))
await refreshAccountInfo() await refreshAccountInfo()
await refreshInstanceInfo() await currentInstance.fetchCurrentInstance()
signInInProgress = false signInInProgress = false
} catch { } catch {
signInInProgress = false signInInProgress = false
@ -161,8 +166,4 @@ struct SettingsTabs: View {
private func refreshAccountInfo() async { private func refreshAccountInfo() async {
accountData = try? await client.get(endpoint: Accounts.verifyCredentials) accountData = try? await client.get(endpoint: Accounts.verifyCredentials)
} }
private func refreshInstanceInfo() async {
instanceData = try? await client.get(endpoint: Instances.instance)
}
} }

View file

@ -0,0 +1,28 @@
import Foundation
import Models
import Network
@MainActor
public class CurrentInstance: ObservableObject {
@Published public private(set) var instance: Instance?
private var client: Client?
public init() {
}
public func setClient(client: Client) {
self.client = client
Task {
await fetchCurrentInstance()
}
}
public func fetchCurrentInstance() async {
guard let client = client else { return }
Task {
instance = try? await client.get(endpoint: Instances.instance)
}
}
}

View file

@ -7,6 +7,28 @@ public struct Instance: Codable {
public let domainCount: Int public let domainCount: Int
} }
public struct Configuration: Codable {
public struct Statuses: Codable {
public let maxCharacters: Int
public let maxMediaAttachments: Int
}
public struct Polls: Codable {
public let maxOptions: Int
public let maxCharactersPerOption: Int
public let minExpiration: Int
public let maxExpiration: Int
}
public let statuses: Statuses
public let polls: Polls
}
public struct Rule: Codable, Identifiable {
public let id: String
public let text: String
}
public let title: String public let title: String
public let shortDescription: String public let shortDescription: String
public let email: String public let email: String
@ -15,4 +37,6 @@ public struct Instance: Codable {
public let languages: [String] public let languages: [String]
public let registrations: Bool public let registrations: Bool
public let thumbnail: URL? public let thumbnail: URL?
public let configuration: Configuration
public let rules: [Rule]
} }

View file

@ -11,6 +11,7 @@ import NukeUI
public struct StatusEditorView: View { public struct StatusEditorView: View {
@EnvironmentObject private var quicklook: QuickLook @EnvironmentObject private var quicklook: QuickLook
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var currentInstance: CurrentInstance
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@ -195,10 +196,12 @@ public struct StatusEditorView: View {
} label: { } label: {
Image(systemName: "number") Image(systemName: "number")
} }
visibilityMenu
Spacer() Spacer()
visibilityMenu characterCountView
} }
.padding(.horizontal, DS.Constants.layoutPadding) .padding(.horizontal, DS.Constants.layoutPadding)
.padding(.vertical, 12) .padding(.vertical, 12)
@ -206,6 +209,12 @@ public struct StatusEditorView: View {
} }
} }
private var characterCountView: some View {
Text("\((currentInstance.instance?.configuration.statuses.maxCharacters ?? 500) - viewModel.statusText.string.utf16.count)")
.foregroundColor(.gray)
.font(.callout)
}
private var visibilityMenu: some View { private var visibilityMenu: some View {
Menu { Menu {
ForEach(Models.Visibility.allCases, id: \.self) { visibility in ForEach(Models.Visibility.allCases, id: \.self) { visibility in