Add list with instance servers.
This commit is contained in:
parent
da3db13bc4
commit
9e642b3c15
|
@ -16,6 +16,8 @@
|
|||
F802884F297AEED5000BDD51 /* DatabaseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F802884E297AEED5000BDD51 /* DatabaseError.swift */; };
|
||||
F80864112975537F009F035C /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80864102975537F009F035C /* NotificationService.swift */; };
|
||||
F808641429756666009F035C /* NotificationRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F808641329756666009F035C /* NotificationRow.swift */; };
|
||||
F8121CA5298A819100B466C7 /* InstanceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8121CA4298A819100B466C7 /* InstanceService.swift */; };
|
||||
F8121CA8298A86D600B466C7 /* InstanceRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8121CA7298A86D600B466C7 /* InstanceRow.swift */; };
|
||||
F8163776297C3E3D00E6E04A /* PublicTimelineService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8163775297C3E3D00E6E04A /* PublicTimelineService.swift */; };
|
||||
F8210DCF2966B600001D9973 /* ImageRowAsync.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DCE2966B600001D9973 /* ImageRowAsync.swift */; };
|
||||
F8210DD52966BB7E001D9973 /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = F8210DD42966BB7E001D9973 /* Nuke */; };
|
||||
|
@ -133,6 +135,8 @@
|
|||
F802884E297AEED5000BDD51 /* DatabaseError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseError.swift; sourceTree = "<group>"; };
|
||||
F80864102975537F009F035C /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
|
||||
F808641329756666009F035C /* NotificationRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationRow.swift; sourceTree = "<group>"; };
|
||||
F8121CA4298A819100B466C7 /* InstanceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceService.swift; sourceTree = "<group>"; };
|
||||
F8121CA7298A86D600B466C7 /* InstanceRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceRow.swift; sourceTree = "<group>"; };
|
||||
F8163775297C3E3D00E6E04A /* PublicTimelineService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicTimelineService.swift; sourceTree = "<group>"; };
|
||||
F8210DCE2966B600001D9973 /* ImageRowAsync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRowAsync.swift; sourceTree = "<group>"; };
|
||||
F8210DDC2966CF17001D9973 /* StatusData+Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusData+Status.swift"; sourceTree = "<group>"; };
|
||||
|
@ -273,6 +277,14 @@
|
|||
path = NotificationsView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F8121CA6298A86B300B466C7 /* SignInView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F8121CA7298A86D600B466C7 /* InstanceRow.swift */,
|
||||
);
|
||||
path = SignInView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F8210DE82966E4D8001D9973 /* Modifiers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -362,9 +374,10 @@
|
|||
F83901A2295D863B00456AE2 /* Widgets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F8121CA6298A86B300B466C7 /* SignInView */,
|
||||
F808641229756583009F035C /* NotificationsView */,
|
||||
F89D6C4829718868001DA3D4 /* StatusView */,
|
||||
F89D6C4729718822001DA3D4 /* UserProfile */,
|
||||
F89D6C4729718822001DA3D4 /* UserProfileView */,
|
||||
F89D6C4029717FC0001DA3D4 /* SettingsView */,
|
||||
F83901A5295D8EC000456AE2 /* LabelIcon.swift */,
|
||||
F85D4972296406E700751DF7 /* BottomRight.swift */,
|
||||
|
@ -475,6 +488,7 @@
|
|||
F88E4D59297ECEE60057491A /* SearchService.swift */,
|
||||
F8C7EDBE298169EE002843BC /* TagsService.swift */,
|
||||
F829193B2983012400367CE2 /* ImageSizeService.swift */,
|
||||
F8121CA4298A819100B466C7 /* InstanceService.swift */,
|
||||
);
|
||||
path = Services;
|
||||
sourceTree = "<group>";
|
||||
|
@ -505,13 +519,13 @@
|
|||
path = SettingsView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F89D6C4729718822001DA3D4 /* UserProfile */ = {
|
||||
F89D6C4729718822001DA3D4 /* UserProfileView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F86B7213296BFDCE00EE59EC /* UserProfileHeader.swift */,
|
||||
F86B7215296BFFDA00EE59EC /* UserProfileStatuses.swift */,
|
||||
);
|
||||
path = UserProfile;
|
||||
path = UserProfileView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F89D6C4829718868001DA3D4 /* StatusView */ = {
|
||||
|
@ -667,6 +681,7 @@
|
|||
F8B1E6512973FB7E00EE0D10 /* ToastrService.swift in Sources */,
|
||||
F88E4D48297E90CD0057491A /* TrendStatusesView.swift in Sources */,
|
||||
F89992CE296D92E7005994BF /* AttachmentModel.swift in Sources */,
|
||||
F8121CA5298A819100B466C7 /* InstanceService.swift in Sources */,
|
||||
F800480A2961EA1900E6868A /* AttachmentDataHandler.swift in Sources */,
|
||||
F80048032961850500E6868A /* AttachmentData+CoreDataClass.swift in Sources */,
|
||||
F897978D2968369600B22335 /* HapticService.swift in Sources */,
|
||||
|
@ -701,6 +716,7 @@
|
|||
F8C14392296AF0B3001FE31D /* String+Exif.swift in Sources */,
|
||||
F85E1320297409CD006A051D /* ErrorsService.swift in Sources */,
|
||||
F88C246C295C37B80006098B /* VernissageApp.swift in Sources */,
|
||||
F8121CA8298A86D600B466C7 /* InstanceRow.swift in Sources */,
|
||||
F802884F297AEED5000BDD51 /* DatabaseError.swift in Sources */,
|
||||
F85D4971296402DC00751DF7 /* AuthorizationService.swift in Sources */,
|
||||
F88E4D56297EAD6E0057491A /* AppRouteur.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Pixelfed.jpg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Pixelfed@2x.jpg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Pixelfed@3x.jpg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class InstanceService {
|
||||
public static let shared = InstanceService()
|
||||
private init() { }
|
||||
|
||||
func instances(urls: [String]) async -> [Instance] {
|
||||
var instances: [Instance] = []
|
||||
|
||||
await withTaskGroup(of: Instance?.self) { group in
|
||||
for url in urls {
|
||||
group.addTask {
|
||||
do {
|
||||
if let baseUrl = URL(string: url) {
|
||||
let client = MastodonClient(baseURL: baseUrl)
|
||||
return try await client.readInstanceInformation()
|
||||
}
|
||||
|
||||
return nil
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Cannot download instance information: \(url.string)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for await instance in group {
|
||||
if let instance {
|
||||
instances.append(instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return instances
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import MastodonKit
|
||||
import AuthenticationServices
|
||||
|
||||
struct SignInView: View {
|
||||
|
@ -13,10 +14,12 @@ struct SignInView: View {
|
|||
@EnvironmentObject var applicationState: ApplicationState
|
||||
|
||||
@State private var serverAddress: String = String.empty()
|
||||
@State private var pixelfedInstances: [String] = [
|
||||
"pixelfed.de", "pixelfed.social", "pxlmo.com", "metapixl.com", "pixey.org",
|
||||
"pixel.tchncs.de", "pixelfed.tokyo", "pixelfed.fr", "pixelfed.nz", "pixelfed.au",
|
||||
"pixelfed.eus", "pixelfed.bachgau.social"
|
||||
@State private var instances: [Instance] = []
|
||||
|
||||
private let pixelfedInstances: [String] = [
|
||||
"https://pixelfed.de", "https://pixelfed.social", "https://pxlmo.com", "https://metapixl.com", "https://pixey.org",
|
||||
"https://pixel.tchncs.de", "https://pixelfed.tokyo", "https://pixelfed.fr", "https://pixelfed.nz", "https://pixelfed.au",
|
||||
"https://pixelfed.eus", "https://pixelfed.bachgau.social"
|
||||
]
|
||||
|
||||
var onSignInStateChenge: ((_ applicationViewMode: ApplicationViewMode) -> Void)?
|
||||
|
@ -30,44 +33,55 @@ struct SignInView: View {
|
|||
HStack(alignment: .center, spacing: 4) {
|
||||
TextField("Server address", text: $serverAddress)
|
||||
.onSubmit {
|
||||
self.signIn()
|
||||
let baseAddress = self.getServerAddress(uri: self.serverAddress)
|
||||
self.signIn(baseAddress: baseAddress)
|
||||
}
|
||||
.textInputAutocapitalization(.never)
|
||||
.keyboardType(.URL)
|
||||
.disableAutocorrection(true)
|
||||
|
||||
Button("Sign in") {
|
||||
self.signIn()
|
||||
}.buttonStyle(.borderedProminent)
|
||||
let baseAddress = self.getServerAddress(uri: self.serverAddress)
|
||||
self.signIn(baseAddress: baseAddress)
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// List of predefined servers.
|
||||
Section("Pixelfed servers") {
|
||||
ForEach(pixelfedInstances, id: \.self) { address in
|
||||
NavigationLink(value: RouteurDestinations.signIn) {
|
||||
VStack {
|
||||
Text(address)
|
||||
}
|
||||
if self.instances.isEmpty {
|
||||
HStack {
|
||||
Spacer()
|
||||
LoadingIndicator()
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
|
||||
ForEach(self.instances, id: \.uri) { instance in
|
||||
InstanceRow(instance: instance) { uri in
|
||||
let baseAddress = self.getServerAddress(uri: uri)
|
||||
self.signIn(baseAddress: baseAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.task {
|
||||
|
||||
.onFirstAppear {
|
||||
self.instances = await InstanceService.shared.instances(urls: self.pixelfedInstances)
|
||||
}
|
||||
.navigationBarTitle("Sign in to Pixelfed")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
|
||||
private func signIn() {
|
||||
private func signIn(baseAddress: String) {
|
||||
Task {
|
||||
do {
|
||||
|
||||
let authorizationSession = AuthorizationSession()
|
||||
try await AuthorizationService.shared.sign(in: self.getServerAddress(),
|
||||
try await AuthorizationService.shared.sign(in: baseAddress,
|
||||
session: authorizationSession) { accountData in
|
||||
DispatchQueue.main.async {
|
||||
self.applicationState.account = AccountModel(accountData: accountData)
|
||||
|
@ -84,11 +98,11 @@ struct SignInView: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func getServerAddress() -> String {
|
||||
if !serverAddress.starts(with: "https://") {
|
||||
return "https://\(serverAddress)"
|
||||
private func getServerAddress(uri: String) -> String {
|
||||
if !uri.starts(with: "https://") {
|
||||
return "https://\(uri)"
|
||||
}
|
||||
|
||||
return serverAddress
|
||||
return uri
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import MastodonKit
|
||||
import NukeUI
|
||||
|
||||
struct InstanceRow: View {
|
||||
private let instance: Instance
|
||||
private let action: (String) -> Void
|
||||
|
||||
public init(instance: Instance, action: @escaping (String) -> Void) {
|
||||
self.instance = instance
|
||||
self.action = action
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack(alignment: .center) {
|
||||
LazyImage(url: instance.thumbnail) { state in
|
||||
if let image = state.image {
|
||||
image
|
||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||
.aspectRatio(contentMode: .fit)
|
||||
} else if state.isLoading {
|
||||
placeholderView
|
||||
} else {
|
||||
placeholderView
|
||||
}
|
||||
}
|
||||
.priority(.high)
|
||||
.frame(width: 50, height: 50)
|
||||
|
||||
HStack(alignment: .center) {
|
||||
VStack(alignment: .leading) {
|
||||
Text(instance.title ?? "")
|
||||
.font(.headline)
|
||||
.fontWeight(.bold)
|
||||
Text(instance.uri)
|
||||
.font(.subheadline)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Button("Sign in") {
|
||||
self.action(instance.uri)
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
}
|
||||
|
||||
Text(instance.description ?? "")
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private var placeholderView: some View {
|
||||
Image("PixelfedInstance")
|
||||
.resizable()
|
||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 50, height: 50)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue