Download and show server list (#540)
This commit is contained in:
parent
cc6ec42c5c
commit
ea78f884ab
|
@ -89,6 +89,8 @@
|
|||
87FFDA5D898A5C42ADCB35E7 /* Pods_Mastodon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4ABE34829701A4496C5BB64 /* Pods_Mastodon.framework */; };
|
||||
C24C97032922F30500BAE8CB /* RefreshControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = C24C97022922F30500BAE8CB /* RefreshControl.swift */; };
|
||||
D87BFC8B291D5C6B00FEE264 /* MastodonLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87BFC8A291D5C6B00FEE264 /* MastodonLoginView.swift */; };
|
||||
D87BFC8D291EB81200FEE264 /* MastodonLoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87BFC8C291EB81200FEE264 /* MastodonLoginViewModel.swift */; };
|
||||
D87BFC8F291EC26A00FEE264 /* MastodonLoginServerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87BFC8E291EC26A00FEE264 /* MastodonLoginServerTableViewCell.swift */; };
|
||||
D8A6AB6C291C5136003AB663 /* MastodonLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A6AB6B291C5136003AB663 /* MastodonLoginViewController.swift */; };
|
||||
DB0009A626AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; settings = {ATTRIBUTES = (codegen, ); }; };
|
||||
DB0009A726AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; };
|
||||
|
@ -611,6 +613,8 @@
|
|||
CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D7D7CF93E262178800077512 /* Pods-Mastodon-AppShared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-AppShared.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-AppShared/Pods-Mastodon-AppShared.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D87BFC8A291D5C6B00FEE264 /* MastodonLoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginView.swift; sourceTree = "<group>"; };
|
||||
D87BFC8C291EB81200FEE264 /* MastodonLoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginViewModel.swift; sourceTree = "<group>"; };
|
||||
D87BFC8E291EC26A00FEE264 /* MastodonLoginServerTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginServerTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D8A6AB6B291C5136003AB663 /* MastodonLoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginViewController.swift; sourceTree = "<group>"; };
|
||||
DB0009A826AEE5DC009B9D2D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = "<group>"; };
|
||||
DB0009AD26AEE5E4009B9D2D /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Intents.strings; sourceTree = "<group>"; };
|
||||
|
@ -1503,6 +1507,8 @@
|
|||
children = (
|
||||
D8A6AB6B291C5136003AB663 /* MastodonLoginViewController.swift */,
|
||||
D87BFC8A291D5C6B00FEE264 /* MastodonLoginView.swift */,
|
||||
D87BFC8C291EB81200FEE264 /* MastodonLoginViewModel.swift */,
|
||||
D87BFC8E291EC26A00FEE264 /* MastodonLoginServerTableViewCell.swift */,
|
||||
);
|
||||
path = Login;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3185,6 +3191,7 @@
|
|||
DB5B54A32833BD1A00DEF8B2 /* UserListViewModel.swift in Sources */,
|
||||
DBF156DF2701B17600EC00B7 /* SidebarAddAccountCollectionViewCell.swift in Sources */,
|
||||
DB0617F1278413D00030EE79 /* PickServerServerSectionTableHeaderView.swift in Sources */,
|
||||
D87BFC8F291EC26A00FEE264 /* MastodonLoginServerTableViewCell.swift in Sources */,
|
||||
DB0FCB7E27958957006C02E2 /* StatusThreadRootTableViewCell+ViewModel.swift in Sources */,
|
||||
DB789A0B25F9F2950071ACA0 /* ComposeViewController.swift in Sources */,
|
||||
DB938F0926240F3C00E5B6C1 /* RemoteThreadViewModel.swift in Sources */,
|
||||
|
@ -3307,6 +3314,7 @@
|
|||
DB0618012785732C0030EE79 /* ServerRulesTableViewCell.swift in Sources */,
|
||||
DB98EB5C27B10A730082E365 /* ReportSupplementaryViewModel.swift in Sources */,
|
||||
DB0617EF277F12720030EE79 /* NavigationActionView.swift in Sources */,
|
||||
D87BFC8D291EB81200FEE264 /* MastodonLoginViewModel.swift in Sources */,
|
||||
DB1FD43625F26899004CFCFC /* MastodonPickServerViewModel+LoadIndexedServerState.swift in Sources */,
|
||||
2D939AE825EE1CF80076FA61 /* MastodonRegisterViewController+Avatar.swift in Sources */,
|
||||
DB1D186C25EF5BA7003F1F23 /* PollTableView.swift in Sources */,
|
||||
|
|
|
@ -406,7 +406,7 @@ private extension SceneCoordinator {
|
|||
_viewController.viewModel = viewModel
|
||||
viewController = _viewController
|
||||
case .mastodonLogin:
|
||||
let loginViewController = MastodonLoginViewController()
|
||||
let loginViewController = MastodonLoginViewController(appContext: appContext, authenticationViewModel: AuthenticationViewModel(context: appContext, coordinator: self, isAuthenticationExist: false))
|
||||
loginViewController.delegate = self
|
||||
|
||||
viewController = loginViewController
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
//
|
||||
// MastodonLoginServerTableViewCell.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by Nathan Mattes on 11.11.22.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class MastodonLoginServerTableViewCell: UITableViewCell {
|
||||
static let reuseIdentifier = "MastodonLoginServerTableViewCell"
|
||||
}
|
|
@ -49,7 +49,6 @@ class MastodonLoginView: UIView {
|
|||
|
||||
tableView = UITableView()
|
||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||
tableView.backgroundColor = .green
|
||||
//TODO: @zeitchlag Cell
|
||||
|
||||
navigationActionView = NavigationActionView()
|
||||
|
|
|
@ -6,25 +6,38 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import MastodonSDK
|
||||
import MastodonCore
|
||||
|
||||
protocol MastodonLoginViewControllerDelegate: AnyObject {
|
||||
func backButtonPressed(_ viewController: MastodonLoginViewController)
|
||||
func nextButtonPressed(_ viewController: MastodonLoginViewController)
|
||||
}
|
||||
|
||||
enum MastodonLoginViewSection: Hashable {
|
||||
case servers
|
||||
}
|
||||
|
||||
class MastodonLoginViewController: UIViewController {
|
||||
|
||||
// back-button, next-button (enabled if user selectes a server or url is valid
|
||||
// next-button does MastodonPickServerViewController.doSignIn()
|
||||
|
||||
weak var delegate: MastodonLoginViewControllerDelegate?
|
||||
var dataSource: UITableViewDiffableDataSource<MastodonLoginViewSection, Mastodon.Entity.Server>?
|
||||
let viewModel: MastodonLoginViewModel
|
||||
let authenticationViewModel: AuthenticationViewModel
|
||||
weak var appContext: AppContext?
|
||||
|
||||
var contentView: MastodonLoginView {
|
||||
view as! MastodonLoginView
|
||||
}
|
||||
|
||||
init() {
|
||||
init(appContext: AppContext, authenticationViewModel: AuthenticationViewModel) {
|
||||
|
||||
viewModel = MastodonLoginViewModel(appContext: appContext)
|
||||
self.authenticationViewModel = authenticationViewModel
|
||||
self.appContext = appContext
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
viewModel.delegate = self
|
||||
|
||||
navigationItem.hidesBackButton = true
|
||||
}
|
||||
|
@ -37,8 +50,9 @@ class MastodonLoginViewController: UIViewController {
|
|||
loginView.navigationActionView.nextButton.addTarget(self, action: #selector(MastodonLoginViewController.nextButtonPressed(_:)), for: .touchUpInside)
|
||||
loginView.navigationActionView.backButton.addTarget(self, action: #selector(MastodonLoginViewController.backButtonPressed(_:)), for: .touchUpInside)
|
||||
loginView.searchTextField.addTarget(self, action: #selector(MastodonLoginViewController.textfieldDidChange(_:)), for: .editingChanged)
|
||||
|
||||
//TODO: Set tableView.delegate and tableView.dataSource
|
||||
loginView.tableView.delegate = self
|
||||
loginView.tableView.register(MastodonLoginServerTableViewCell.self, forCellReuseIdentifier: MastodonLoginServerTableViewCell.reuseIdentifier)
|
||||
loginView.navigationActionView.nextButton.isEnabled = false
|
||||
|
||||
view = loginView
|
||||
}
|
||||
|
@ -46,10 +60,35 @@ class MastodonLoginViewController: UIViewController {
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
let dataSource = UITableViewDiffableDataSource<MastodonLoginViewSection, Mastodon.Entity.Server>(tableView: contentView.tableView) { [weak self] tableView, indexPath, itemIdentifier in
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: MastodonLoginServerTableViewCell.reuseIdentifier, for: indexPath) as? MastodonLoginServerTableViewCell,
|
||||
let self = self else {
|
||||
fatalError("Wrong cell")
|
||||
}
|
||||
|
||||
let server = self.viewModel.serverList[indexPath.row]
|
||||
var configuration = cell.defaultContentConfiguration()
|
||||
configuration.text = server.domain
|
||||
|
||||
cell.contentConfiguration = configuration
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
contentView.tableView.dataSource = dataSource
|
||||
self.dataSource = dataSource
|
||||
|
||||
defer { setupNavigationBarBackgroundView() }
|
||||
setupOnboardingAppearance()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
viewModel.updateServers()
|
||||
}
|
||||
|
||||
//MARK: - Actions
|
||||
|
||||
@objc func backButtonPressed(_ sender: Any) {
|
||||
|
@ -108,10 +147,36 @@ class MastodonLoginViewController: UIViewController {
|
|||
|
||||
@objc func textfieldDidChange(_ textField: UITextField) {
|
||||
print(textField.text ?? "---")
|
||||
//TODO: @zeitschlag filter server-list, update tableview
|
||||
|
||||
contentView.navigationActionView.nextButton.isEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - OnboardingViewControllerAppearance
|
||||
extension MastodonLoginViewController: OnboardingViewControllerAppearance { }
|
||||
|
||||
//MARK: - UITableViewDelegate
|
||||
extension MastodonLoginViewController: UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let server = viewModel.serverList[indexPath.row]
|
||||
viewModel.selectedServer = server
|
||||
|
||||
contentView.searchTextField.text = server.domain
|
||||
//TODO: @zeitschlag filter server list
|
||||
|
||||
contentView.navigationActionView.nextButton.isEnabled = true
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
extension MastodonLoginViewController: MastodonLoginViewModelDelegate {
|
||||
func serversUpdated(_ viewModel: MastodonLoginViewModel) {
|
||||
var snapshot = NSDiffableDataSourceSnapshot<MastodonLoginViewSection, Mastodon.Entity.Server>()
|
||||
|
||||
snapshot.appendSections([MastodonLoginViewSection.servers])
|
||||
snapshot.appendItems(viewModel.serverList)
|
||||
|
||||
dataSource?.applySnapshot(snapshot, animated: true)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// MastodonLoginViewModel.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by Nathan Mattes on 11.11.22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonSDK
|
||||
import MastodonCore
|
||||
import Combine
|
||||
|
||||
protocol MastodonLoginViewModelDelegate: AnyObject {
|
||||
func serversUpdated(_ viewModel: MastodonLoginViewModel)
|
||||
}
|
||||
|
||||
class MastodonLoginViewModel {
|
||||
|
||||
var serverList: [Mastodon.Entity.Server] = []
|
||||
var selectedServer: Mastodon.Entity.Server?
|
||||
|
||||
weak var appContext: AppContext?
|
||||
weak var delegate: MastodonLoginViewModelDelegate?
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
init(appContext: AppContext) {
|
||||
self.appContext = appContext
|
||||
}
|
||||
|
||||
func updateServers() {
|
||||
appContext?.apiService.servers().sink(receiveCompletion: { [weak self] completion in
|
||||
switch completion {
|
||||
case .finished:
|
||||
guard let self = self else { return }
|
||||
|
||||
self.delegate?.serversUpdated(self)
|
||||
case .failure(let error):
|
||||
print(error)
|
||||
}
|
||||
}, receiveValue: { content in
|
||||
let servers = content.value
|
||||
self.serverList = servers
|
||||
}).store(in: &disposeBag)
|
||||
}
|
||||
}
|
|
@ -12,8 +12,8 @@ import MastodonSDK
|
|||
extension APIService {
|
||||
|
||||
public func servers(
|
||||
language: String?,
|
||||
category: String?
|
||||
language: String? = nil,
|
||||
category: String? = nil
|
||||
) -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Server]>, Error> {
|
||||
let query = Mastodon.API.Onboarding.ServersQuery(language: language, category: category)
|
||||
return Mastodon.API.Onboarding.servers(session: session, query: query)
|
||||
|
|
|
@ -9,7 +9,7 @@ import Foundation
|
|||
|
||||
extension Mastodon.Entity {
|
||||
|
||||
public struct Server: Codable, Equatable {
|
||||
public struct Server: Codable, Equatable, Hashable {
|
||||
public let domain: String
|
||||
public let version: String
|
||||
public let description: String
|
||||
|
@ -22,7 +22,7 @@ extension Mastodon.Entity {
|
|||
public let approvalRequired: Bool
|
||||
public let language: String
|
||||
public let category: String
|
||||
//TODO: @zeitschlag Is there a way to figure out in advance if a server accepts new registrations? Right now we'd have to query the server and it responts with a `AuthenticationViewModel.AuthenticationError.registrationClosed`
|
||||
//TODO: @zeitschlag Is there a way to figure out in advance if a server accepts new registrations? Right now we'd have to query the server and it responds with a `AuthenticationViewModel.AuthenticationError.registrationClosed`
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case domain
|
||||
|
|
Loading…
Reference in New Issue