diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 1f9702935..fd58693b2 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -177,6 +177,7 @@ D8F917142A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F917132A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift */; }; D8FAAE3D2AD042E700DC1832 /* AdminTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FAAE3C2AD042E700DC1832 /* AdminTableViewCell.swift */; }; D8FAAE3F2AD0430E00DC1832 /* ContactAdminTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FAAE3E2AD0430E00DC1832 /* ContactAdminTableViewCell.swift */; }; + D8FAAE412AD0475900DC1832 /* AboutInstanceTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FAAE402AD0475900DC1832 /* AboutInstanceTableViewHeader.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 */; }; DB023D26279FFB0A005AC798 /* ShareActivityProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB023D25279FFB0A005AC798 /* ShareActivityProvider.swift */; }; @@ -841,6 +842,7 @@ D8F917132A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsDiffableTableViewDataSource.swift; sourceTree = ""; }; D8FAAE3C2AD042E700DC1832 /* AdminTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminTableViewCell.swift; sourceTree = ""; }; D8FAAE3E2AD0430E00DC1832 /* ContactAdminTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactAdminTableViewCell.swift; sourceTree = ""; }; + D8FAAE402AD0475900DC1832 /* AboutInstanceTableViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutInstanceTableViewHeader.swift; sourceTree = ""; }; DB0009A826AEE5DC009B9D2D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = ""; }; DB0009AD26AEE5E4009B9D2D /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Intents.strings; sourceTree = ""; }; DB023D25279FFB0A005AC798 /* ShareActivityProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareActivityProvider.swift; sourceTree = ""; }; @@ -1950,6 +1952,7 @@ children = ( D8FAAE3C2AD042E700DC1832 /* AdminTableViewCell.swift */, D8FAAE3E2AD0430E00DC1832 /* ContactAdminTableViewCell.swift */, + D8FAAE402AD0475900DC1832 /* AboutInstanceTableViewHeader.swift */, D81439852AD415DE0071A88F /* AboutInstance.swift */, ); path = "Table View Components"; @@ -3711,6 +3714,7 @@ DBFEEC9D279C12C1004F81DD /* ProfileFieldEditCollectionViewCell.swift in Sources */, DB3E6FEC2806D7F100B035AE /* DiscoveryNewsViewController.swift in Sources */, DBCBED1726132DB500B49291 /* UserTimelineViewModel+Diffable.swift in Sources */, + D8FAAE412AD0475900DC1832 /* AboutInstanceTableViewHeader.swift in Sources */, 2DE0FACE2615F7AD00CDF649 /* RecommendAccountSection.swift in Sources */, 2DAC9E3E262FC2400062E1A6 /* SuggestionAccountViewModel.swift in Sources */, DB603113279EBEBA00A935FE /* DataSourceFacade+Block.swift in Sources */, diff --git a/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift b/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift index 61bf336af..2f6a40a7c 100644 --- a/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift +++ b/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift @@ -14,6 +14,7 @@ class AboutInstanceViewController: UIViewController { var dataSource: UITableViewDiffableDataSource? let tableView: UITableView + let headerView: AboutInstanceTableHeaderView var instance: Mastodon.Entity.V2.Instance? init() { @@ -21,6 +22,8 @@ class AboutInstanceViewController: UIViewController { tableView.translatesAutoresizingMaskIntoConstraints = false tableView.register(ContactAdminTableViewCell.self, forCellReuseIdentifier: ContactAdminTableViewCell.reuseIdentifier) tableView.register(AdminTableViewCell.self, forCellReuseIdentifier: AdminTableViewCell.reuseIdentifier) + + headerView = AboutInstanceTableHeaderView() super.init(nibName: nil, bundle: nil) let dataSource = UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, itemIdentifier in @@ -65,6 +68,23 @@ class AboutInstanceViewController: UIViewController { NSLayoutConstraint.activate(constraints) } + override func viewDidLoad() { + super.viewDidLoad() + + tableView.tableHeaderView = headerView + } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + if let tableFooterView = tableView.tableHeaderView { + tableFooterView.frame.size = tableFooterView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) + tableView.tableHeaderView = tableFooterView + } + + super.viewWillLayoutSubviews() + } + func update(with instance: Mastodon.Entity.V2.Instance) { self.instance = instance @@ -80,20 +100,29 @@ class AboutInstanceViewController: UIViewController { } dataSource?.apply(snapshot, animatingDifferences: false) - } - //TODO: Implement + + guard let thumbnailUrlString = instance.thumbnail?.url, let thumbnailUrl = URL(string: thumbnailUrlString) else { return } + + DispatchQueue.main.async { + self.headerView.updateImage(with: thumbnailUrl) { [weak self] in + DispatchQueue.main.async { + if self?.tableView.tableHeaderView == nil { + + self?.headerView.setNeedsLayout() + self?.headerView.layoutIfNeeded() + } + } + } + } } } extension AboutInstanceViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - //TODO: Implement - guard let snapshot = dataSource?.snapshot() else { return tableView.deselectRow(at: indexPath, animated: true) } - switch snapshot.itemIdentifiers(inSection: .main)[indexPath.row] { case .adminAccount(let account): delegate?.showAdminAccount(self, account: account) @@ -101,7 +130,6 @@ extension AboutInstanceViewController: UITableViewDelegate { delegate?.sendEmailToAdmin(self, emailAddress: email) } - tableView.deselectRow(at: indexPath, animated: true) } } diff --git a/Mastodon/Scene/Settings/Server Details/Table View Components/AboutInstanceTableViewHeader.swift b/Mastodon/Scene/Settings/Server Details/Table View Components/AboutInstanceTableViewHeader.swift new file mode 100644 index 000000000..a9a7235f6 --- /dev/null +++ b/Mastodon/Scene/Settings/Server Details/Table View Components/AboutInstanceTableViewHeader.swift @@ -0,0 +1,37 @@ +// Copyright © 2023 Mastodon gGmbH. All rights reserved. + +import UIKit +import AlamofireImage + +class AboutInstanceTableHeaderView: UIView { + let thumbnailImageView: UIImageView + + init() { + thumbnailImageView = UIImageView() + thumbnailImageView.translatesAutoresizingMaskIntoConstraints = false + + super.init(frame: .zero) + + addSubview(thumbnailImageView) + + setupConstraints() + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + private func setupConstraints() { + let constraints = [ + thumbnailImageView.topAnchor.constraint(equalTo: topAnchor), + thumbnailImageView.leadingAnchor.constraint(equalTo: leadingAnchor), + trailingAnchor.constraint(equalTo: thumbnailImageView.trailingAnchor), + bottomAnchor.constraint(equalTo: thumbnailImageView.bottomAnchor, constant: 24), + thumbnailImageView.heightAnchor.constraint(equalToConstant: 188), + ] + + NSLayoutConstraint.activate(constraints) + } + + func updateImage(with thumbnailURL: URL, completion: (() -> Void)? = nil) { + thumbnailImageView.af.setImage(withURL: thumbnailURL) + } +}