mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-22 16:31:00 +00:00
New Sign In flow & instances browser
This commit is contained in:
parent
f7704b808d
commit
03a5dd9f54
6 changed files with 229 additions and 64 deletions
|
@ -10,6 +10,8 @@
|
||||||
9F24EEB829360C330042359D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9F24EEB729360C330042359D /* Preview Assets.xcassets */; };
|
9F24EEB829360C330042359D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9F24EEB729360C330042359D /* Preview Assets.xcassets */; };
|
||||||
9F295540292B6C3400E0E81B /* Timeline in Frameworks */ = {isa = PBXBuildFile; productRef = 9F29553F292B6C3400E0E81B /* Timeline */; };
|
9F295540292B6C3400E0E81B /* Timeline in Frameworks */ = {isa = PBXBuildFile; productRef = 9F29553F292B6C3400E0E81B /* Timeline */; };
|
||||||
9F2B92F6295AE04800DE16D0 /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2B92F5295AE04800DE16D0 /* Tabs.swift */; };
|
9F2B92F6295AE04800DE16D0 /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2B92F5295AE04800DE16D0 /* Tabs.swift */; };
|
||||||
|
9F2B92FA295DA7D700DE16D0 /* AddAccountsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2B92F9295DA7D700DE16D0 /* AddAccountsView.swift */; };
|
||||||
|
9F2B92FC295DA94500DE16D0 /* InstanceInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2B92FB295DA94500DE16D0 /* InstanceInfoView.swift */; };
|
||||||
9F35DB44294F9A7D00B3281A /* Status in Frameworks */ = {isa = PBXBuildFile; productRef = 9F35DB43294F9A7D00B3281A /* Status */; };
|
9F35DB44294F9A7D00B3281A /* Status in Frameworks */ = {isa = PBXBuildFile; productRef = 9F35DB43294F9A7D00B3281A /* Status */; };
|
||||||
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F35DB4629506F6600B3281A /* NotificationTab.swift */; };
|
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F35DB4629506F6600B3281A /* NotificationTab.swift */; };
|
||||||
9F35DB4A29506FA100B3281A /* Notifications in Frameworks */ = {isa = PBXBuildFile; productRef = 9F35DB4929506FA100B3281A /* Notifications */; };
|
9F35DB4A29506FA100B3281A /* Notifications in Frameworks */ = {isa = PBXBuildFile; productRef = 9F35DB4929506FA100B3281A /* Notifications */; };
|
||||||
|
@ -36,6 +38,8 @@
|
||||||
9F29553D292B67B600E0E81B /* Network */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Network; path = Packages/Network; sourceTree = "<group>"; };
|
9F29553D292B67B600E0E81B /* Network */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Network; path = Packages/Network; sourceTree = "<group>"; };
|
||||||
9F29553E292B6AF600E0E81B /* Timeline */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Timeline; path = Packages/Timeline; sourceTree = "<group>"; };
|
9F29553E292B6AF600E0E81B /* Timeline */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Timeline; path = Packages/Timeline; sourceTree = "<group>"; };
|
||||||
9F2B92F5295AE04800DE16D0 /* Tabs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = "<group>"; };
|
9F2B92F5295AE04800DE16D0 /* Tabs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = "<group>"; };
|
||||||
|
9F2B92F9295DA7D700DE16D0 /* AddAccountsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAccountsView.swift; sourceTree = "<group>"; };
|
||||||
|
9F2B92FB295DA94500DE16D0 /* InstanceInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceInfoView.swift; sourceTree = "<group>"; };
|
||||||
9F35DB42294F9A2900B3281A /* Status */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Status; path = Packages/Status; sourceTree = "<group>"; };
|
9F35DB42294F9A2900B3281A /* Status */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Status; path = Packages/Status; sourceTree = "<group>"; };
|
||||||
9F35DB45294FA04C00B3281A /* DesignSystem */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = DesignSystem; path = Packages/DesignSystem; sourceTree = "<group>"; };
|
9F35DB45294FA04C00B3281A /* DesignSystem */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = DesignSystem; path = Packages/DesignSystem; sourceTree = "<group>"; };
|
||||||
9F35DB4629506F6600B3281A /* NotificationTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTab.swift; sourceTree = "<group>"; };
|
9F35DB4629506F6600B3281A /* NotificationTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTab.swift; sourceTree = "<group>"; };
|
||||||
|
@ -170,6 +174,8 @@
|
||||||
children = (
|
children = (
|
||||||
9FAE4ACA293783B000772766 /* SettingsTab.swift */,
|
9FAE4ACA293783B000772766 /* SettingsTab.swift */,
|
||||||
9FE151A5293C90F900E9683D /* IconSelectorView.swift */,
|
9FE151A5293C90F900E9683D /* IconSelectorView.swift */,
|
||||||
|
9F2B92F9295DA7D700DE16D0 /* AddAccountsView.swift */,
|
||||||
|
9F2B92FB295DA94500DE16D0 /* InstanceInfoView.swift */,
|
||||||
);
|
);
|
||||||
path = Settings;
|
path = Settings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -259,6 +265,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
9FE151A6293C90F900E9683D /* IconSelectorView.swift in Sources */,
|
9FE151A6293C90F900E9683D /* IconSelectorView.swift in Sources */,
|
||||||
|
9F2B92FC295DA94500DE16D0 /* InstanceInfoView.swift in Sources */,
|
||||||
9F35DB4C2952005C00B3281A /* AccountTab.swift in Sources */,
|
9F35DB4C2952005C00B3281A /* AccountTab.swift in Sources */,
|
||||||
9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */,
|
9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */,
|
||||||
9FAE4AD32937A0C600772766 /* AppAccountsManager.swift in Sources */,
|
9FAE4AD32937A0C600772766 /* AppAccountsManager.swift in Sources */,
|
||||||
|
@ -266,6 +273,7 @@
|
||||||
9F398AB329360A4C00A889F2 /* TimelineTab.swift in Sources */,
|
9F398AB329360A4C00A889F2 /* TimelineTab.swift in Sources */,
|
||||||
9F398AA62935FE8A00A889F2 /* AppRouteur.swift in Sources */,
|
9F398AA62935FE8A00A889F2 /* AppRouteur.swift in Sources */,
|
||||||
9FBFE63D292A715500C250E9 /* IceCubesApp.swift in Sources */,
|
9FBFE63D292A715500C250E9 /* IceCubesApp.swift in Sources */,
|
||||||
|
9F2B92FA295DA7D700DE16D0 /* AddAccountsView.swift in Sources */,
|
||||||
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */,
|
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */,
|
||||||
9FAE4AD129379AD600772766 /* AppAccount.swift in Sources */,
|
9FAE4AD129379AD600772766 /* AppAccount.swift in Sources */,
|
||||||
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */,
|
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */,
|
||||||
|
|
137
IceCubesApp/App/Tabs/Settings/AddAccountsView.swift
Normal file
137
IceCubesApp/App/Tabs/Settings/AddAccountsView.swift
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
import SwiftUI
|
||||||
|
import Network
|
||||||
|
import Models
|
||||||
|
import Env
|
||||||
|
import DesignSystem
|
||||||
|
import NukeUI
|
||||||
|
import Shimmer
|
||||||
|
|
||||||
|
struct AddAccountView: View {
|
||||||
|
@Environment(\.openURL) private var openURL
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
|
@EnvironmentObject private var appAccountsManager: AppAccountsManager
|
||||||
|
@EnvironmentObject private var currentAccount: CurrentAccount
|
||||||
|
@EnvironmentObject private var currentInstance: CurrentInstance
|
||||||
|
@EnvironmentObject private var theme: Theme
|
||||||
|
|
||||||
|
@State private var instanceName: String = ""
|
||||||
|
@State private var instance: Instance?
|
||||||
|
@State private var isSigninIn = false
|
||||||
|
@State private var signInClient: Client?
|
||||||
|
@State private var instances: [InstanceSocial] = []
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationStack {
|
||||||
|
Form {
|
||||||
|
TextField("Instance url", text: $instanceName)
|
||||||
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
if let instance {
|
||||||
|
Button {
|
||||||
|
isSigninIn = true
|
||||||
|
Task {
|
||||||
|
await signIn()
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
if isSigninIn {
|
||||||
|
ProgressView()
|
||||||
|
} else {
|
||||||
|
Text("Sign in")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
InstanceInfoView(instance: instance)
|
||||||
|
} else {
|
||||||
|
instancesListView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formStyle(.grouped)
|
||||||
|
.navigationTitle("Add account")
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
|
.background(theme.secondaryBackgroundColor)
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .navigationBarLeading) {
|
||||||
|
Button("Cancel", action: { dismiss() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
let client = InstanceSocialClient()
|
||||||
|
Task {
|
||||||
|
self.instances = await client.fetchInstances()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: instanceName) { newValue in
|
||||||
|
let client = Client(server: newValue)
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
self.instance = try await client.get(endpoint: Instances.instance)
|
||||||
|
} catch {
|
||||||
|
self.instance = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onOpenURL(perform: { url in
|
||||||
|
Task {
|
||||||
|
await continueSignIn(url: url)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var instancesListView: some View {
|
||||||
|
Section("Suggestions") {
|
||||||
|
if instances.isEmpty {
|
||||||
|
ProgressView()
|
||||||
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
} else {
|
||||||
|
ForEach(instanceName.isEmpty ? instances : instances.filter{ $0.name.contains(instanceName.lowercased()) }) { instance in
|
||||||
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
|
Text(instance.name)
|
||||||
|
.font(.headline)
|
||||||
|
Text(instance.info?.shortDescription ?? "")
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
Text("\(instance.users) users ⸱ \(instance.statuses) posts")
|
||||||
|
.font(.footnote)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
}
|
||||||
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
.onTapGesture {
|
||||||
|
self.instanceName = instance.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func signIn() async {
|
||||||
|
do {
|
||||||
|
signInClient = .init(server: instanceName)
|
||||||
|
if let oauthURL = try await signInClient?.oauthURL() {
|
||||||
|
openURL(oauthURL)
|
||||||
|
} else {
|
||||||
|
isSigninIn = false
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
isSigninIn = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func continueSignIn(url: URL) async {
|
||||||
|
guard let client = signInClient else {
|
||||||
|
isSigninIn = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
let oauthToken = try await client.continueOauthFlow(url: url)
|
||||||
|
appAccountsManager.add(account: AppAccount(server: client.server, oauthToken: oauthToken))
|
||||||
|
await currentAccount.fetchCurrentAccount()
|
||||||
|
await currentInstance.fetchCurrentInstance()
|
||||||
|
isSigninIn = false
|
||||||
|
dismiss()
|
||||||
|
} catch {
|
||||||
|
isSigninIn = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
IceCubesApp/App/Tabs/Settings/InstanceInfoView.swift
Normal file
30
IceCubesApp/App/Tabs/Settings/InstanceInfoView.swift
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import SwiftUI
|
||||||
|
import Models
|
||||||
|
import DesignSystem
|
||||||
|
import NukeUI
|
||||||
|
|
||||||
|
struct InstanceInfoView: View {
|
||||||
|
@EnvironmentObject private var theme: Theme
|
||||||
|
|
||||||
|
let instance: Instance
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Section("Instance info") {
|
||||||
|
LabeledContent("Name", value: instance.title)
|
||||||
|
Text(instance.shortDescription)
|
||||||
|
LabeledContent("Email", value: instance.email)
|
||||||
|
LabeledContent("Version", value: instance.version)
|
||||||
|
LabeledContent("Users", value: "\(instance.stats.userCount)")
|
||||||
|
LabeledContent("Posts", value: "\(instance.stats.statusCount)")
|
||||||
|
LabeledContent("Domains", value: "\(instance.stats.domainCount)")
|
||||||
|
}
|
||||||
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
|
||||||
|
Section("Instance rules") {
|
||||||
|
ForEach(instance.rules) { rule in
|
||||||
|
Text(rule.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,16 +6,14 @@ import Account
|
||||||
import Models
|
import Models
|
||||||
import DesignSystem
|
import DesignSystem
|
||||||
|
|
||||||
struct SettingsTabs: View {
|
struct SettingsTabs: View {
|
||||||
@Environment(\.openURL) private var openURL
|
|
||||||
@EnvironmentObject private var client: Client
|
@EnvironmentObject private var client: Client
|
||||||
@EnvironmentObject private var currentAccount: CurrentAccount
|
@EnvironmentObject private var currentAccount: CurrentAccount
|
||||||
@EnvironmentObject private var currentInstance: CurrentInstance
|
@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 addAccountSheetPresented = false
|
||||||
@State private var signInServer = IceCubesApp.defaultServer
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
|
@ -25,11 +23,6 @@ struct SettingsTabs: View {
|
||||||
themeSection
|
themeSection
|
||||||
instanceSection
|
instanceSection
|
||||||
}
|
}
|
||||||
.onOpenURL(perform: { url in
|
|
||||||
Task {
|
|
||||||
await continueSignIn(url: url)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.scrollContentBackground(.hidden)
|
.scrollContentBackground(.hidden)
|
||||||
.background(theme.secondaryBackgroundColor)
|
.background(theme.secondaryBackgroundColor)
|
||||||
.navigationTitle(Text("Settings"))
|
.navigationTitle(Text("Settings"))
|
||||||
|
@ -37,10 +30,8 @@ struct SettingsTabs: View {
|
||||||
}
|
}
|
||||||
.task {
|
.task {
|
||||||
if appAccountsManager.currentAccount.oauthToken != nil {
|
if appAccountsManager.currentAccount.oauthToken != nil {
|
||||||
signInInProgress = true
|
|
||||||
await currentAccount.fetchCurrentAccount()
|
await currentAccount.fetchCurrentAccount()
|
||||||
await currentInstance.fetchCurrentInstance()
|
await currentInstance.fetchCurrentInstance()
|
||||||
signInInProgress = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,10 +51,8 @@ struct SettingsTabs: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signOutButton
|
signOutButton
|
||||||
} else {
|
|
||||||
TextField("Mastodon server", text: $signInServer)
|
|
||||||
signInButton
|
|
||||||
}
|
}
|
||||||
|
addAccountButton
|
||||||
}
|
}
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
}
|
}
|
||||||
|
@ -97,23 +86,7 @@ struct SettingsTabs: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var instanceSection: some View {
|
private var instanceSection: some View {
|
||||||
if let instanceData = currentInstance.instance {
|
if let instanceData = currentInstance.instance {
|
||||||
Section("Instance info") {
|
InstanceInfoView(instance: instanceData)
|
||||||
LabeledContent("Name", value: instanceData.title)
|
|
||||||
Text(instanceData.shortDescription)
|
|
||||||
LabeledContent("Email", value: instanceData.email)
|
|
||||||
LabeledContent("Version", value: instanceData.version)
|
|
||||||
LabeledContent("Users", value: "\(instanceData.stats.userCount)")
|
|
||||||
LabeledContent("Posts", value: "\(instanceData.stats.statusCount)")
|
|
||||||
LabeledContent("Domains", value: "\(instanceData.stats.domainCount)")
|
|
||||||
}
|
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
|
||||||
|
|
||||||
Section("Instance rules") {
|
|
||||||
ForEach(instanceData.rules) { rule in
|
|
||||||
Text(rule.text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,18 +111,14 @@ struct SettingsTabs: View {
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var signInButton: some View {
|
private var addAccountButton: some View {
|
||||||
Button {
|
Button {
|
||||||
signInInProgress = true
|
addAccountSheetPresented.toggle()
|
||||||
Task {
|
|
||||||
await signIn()
|
|
||||||
}
|
|
||||||
} label: {
|
} label: {
|
||||||
if signInInProgress {
|
Text("Add account")
|
||||||
ProgressView()
|
}
|
||||||
} else {
|
.sheet(isPresented: $addAccountSheetPresented) {
|
||||||
Text("Sign in")
|
AddAccountView()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,28 +128,5 @@ struct SettingsTabs: View {
|
||||||
} label: {
|
} label: {
|
||||||
Text("Sign out").foregroundColor(.red)
|
Text("Sign out").foregroundColor(.red)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private func signIn() async {
|
|
||||||
do {
|
|
||||||
client.server = signInServer
|
|
||||||
let oauthURL = try await client.oauthURL()
|
|
||||||
openURL(oauthURL)
|
|
||||||
} catch {
|
|
||||||
signInInProgress = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func continueSignIn(url: URL) async {
|
|
||||||
do {
|
|
||||||
let oauthToken = try await client.continueOauthFlow(url: url)
|
|
||||||
appAccountsManager.add(account: AppAccount(server: client.server, oauthToken: oauthToken))
|
|
||||||
await currentAccount.fetchCurrentAccount()
|
|
||||||
await currentInstance.fetchCurrentInstance()
|
|
||||||
signInInProgress = false
|
|
||||||
} catch {
|
|
||||||
signInInProgress = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
Packages/Models/Sources/Models/InstanceSocial.swift
Normal file
15
Packages/Models/Sources/Models/InstanceSocial.swift
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct InstanceSocial: Decodable, Identifiable {
|
||||||
|
public struct Info: Decodable {
|
||||||
|
public let shortDescription: String
|
||||||
|
}
|
||||||
|
public let id: String
|
||||||
|
public let name: String
|
||||||
|
public let dead: Bool
|
||||||
|
public let users: String
|
||||||
|
public let activeUsers: Int?
|
||||||
|
public let statuses: String
|
||||||
|
public let thumbnail: URL?
|
||||||
|
public let info: Info?
|
||||||
|
}
|
29
Packages/Network/Sources/Network/InstanceSocialClient.swift
Normal file
29
Packages/Network/Sources/Network/InstanceSocialClient.swift
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import Foundation
|
||||||
|
import Models
|
||||||
|
|
||||||
|
public struct InstanceSocialClient {
|
||||||
|
private let authorization = "Bearer 8a4xx3D7Hzu1aFnf18qlkH8oU0oZ5ulabXxoS2FtQtwOy8G0DGQhr5PjTIjBnYAmFrSBuE2CcASjFocxJBonY8XGbLySB7MXd9ssrwlRHUXTQh3Z578lE1OfUtafvhML"
|
||||||
|
private let endpoint = URL(string: "https://instances.social/api/1.0/instances/list?count=1000&include_closed=false&include_dead=false&min_active_users=500")!
|
||||||
|
|
||||||
|
struct Response: Decodable {
|
||||||
|
let instances: [InstanceSocial]
|
||||||
|
}
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public func fetchInstances() async -> [InstanceSocial] {
|
||||||
|
do {
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
var request: URLRequest = .init(url: endpoint)
|
||||||
|
request.setValue(authorization, forHTTPHeaderField: "Authorization")
|
||||||
|
let (data, _) = try await URLSession.shared.data(for: request)
|
||||||
|
let response = try decoder.decode(Response.self, from: data)
|
||||||
|
return response.instances
|
||||||
|
} catch {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue