Add a footerview that shows legal information (IOS-20)
This is kind of WIP as not the whole text is shown for unknown reasons
This commit is contained in:
parent
ba2f1f5f40
commit
6397a8329b
|
@ -178,6 +178,7 @@
|
|||
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 */; };
|
||||
D8FAAE432AD047B200DC1832 /* AboutInstanceTableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FAAE422AD047B200DC1832 /* AboutInstanceTableFooterView.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 */; };
|
||||
|
@ -843,6 +844,7 @@
|
|||
D8FAAE3C2AD042E700DC1832 /* AdminTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D8FAAE3E2AD0430E00DC1832 /* ContactAdminTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactAdminTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D8FAAE402AD0475900DC1832 /* AboutInstanceTableViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutInstanceTableViewHeader.swift; sourceTree = "<group>"; };
|
||||
D8FAAE422AD047B200DC1832 /* AboutInstanceTableFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutInstanceTableFooterView.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>"; };
|
||||
DB023D25279FFB0A005AC798 /* ShareActivityProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareActivityProvider.swift; sourceTree = "<group>"; };
|
||||
|
@ -1953,6 +1955,7 @@
|
|||
D8FAAE3C2AD042E700DC1832 /* AdminTableViewCell.swift */,
|
||||
D8FAAE3E2AD0430E00DC1832 /* ContactAdminTableViewCell.swift */,
|
||||
D8FAAE402AD0475900DC1832 /* AboutInstanceTableViewHeader.swift */,
|
||||
D8FAAE422AD047B200DC1832 /* AboutInstanceTableFooterView.swift */,
|
||||
D81439852AD415DE0071A88F /* AboutInstance.swift */,
|
||||
);
|
||||
path = "Table View Components";
|
||||
|
@ -3664,6 +3667,7 @@
|
|||
DBDFF1902805543100557A48 /* DiscoveryPostsViewController.swift in Sources */,
|
||||
DB697DD9278F4CED004EF2F7 /* HomeTimelineViewController+DataSourceProvider.swift in Sources */,
|
||||
DB45FAD725CA6C76005A8AC7 /* UIBarButtonItem.swift in Sources */,
|
||||
D8FAAE432AD047B200DC1832 /* AboutInstanceTableFooterView.swift in Sources */,
|
||||
D808B94E296EFBBA0031EB1E /* StatusEditHistoryTableViewCell.swift in Sources */,
|
||||
2D8434F525FF465D00EECE90 /* HomeTimelineNavigationBarTitleViewModel.swift in Sources */,
|
||||
D852C23E2AC5D03300309232 /* InstanceRulesViewController.swift in Sources */,
|
||||
|
|
|
@ -15,6 +15,8 @@ class AboutInstanceViewController: UIViewController {
|
|||
|
||||
let tableView: UITableView
|
||||
let headerView: AboutInstanceTableHeaderView
|
||||
let footerView: AboutInstanceTableFooterView
|
||||
|
||||
var instance: Mastodon.Entity.V2.Instance?
|
||||
|
||||
init() {
|
||||
|
@ -24,6 +26,8 @@ class AboutInstanceViewController: UIViewController {
|
|||
tableView.register(AdminTableViewCell.self, forCellReuseIdentifier: AdminTableViewCell.reuseIdentifier)
|
||||
|
||||
headerView = AboutInstanceTableHeaderView()
|
||||
footerView = AboutInstanceTableFooterView()
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
let dataSource = UITableViewDiffableDataSource<AboutInstanceSection, AboutInstanceItem>(tableView: tableView) { tableView, indexPath, itemIdentifier in
|
||||
|
@ -72,14 +76,23 @@ class AboutInstanceViewController: UIViewController {
|
|||
super.viewDidLoad()
|
||||
|
||||
tableView.tableHeaderView = headerView
|
||||
tableView.tableFooterView = footerView
|
||||
|
||||
headerView.frame.size.height = 1
|
||||
footerView.frame.size.height = 2
|
||||
}
|
||||
|
||||
override func viewWillLayoutSubviews() {
|
||||
super.viewWillLayoutSubviews()
|
||||
|
||||
if let tableFooterView = tableView.tableHeaderView {
|
||||
if let tableHeaderView = tableView.tableHeaderView {
|
||||
tableHeaderView.frame.size = tableHeaderView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
|
||||
tableView.tableHeaderView = tableHeaderView
|
||||
}
|
||||
|
||||
if let tableFooterView = tableView.tableFooterView {
|
||||
tableFooterView.frame.size = tableFooterView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
|
||||
tableView.tableHeaderView = tableFooterView
|
||||
tableView.tableFooterView = tableFooterView
|
||||
}
|
||||
|
||||
super.viewWillLayoutSubviews()
|
||||
|
@ -115,6 +128,16 @@ class AboutInstanceViewController: UIViewController {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateFooter(with extendedDescription: Mastodon.Entity.ExtendedDescription) {
|
||||
DispatchQueue.main.async {
|
||||
self.footerView.update(with: extendedDescription)
|
||||
if let tableFooterView = self.tableView.tableFooterView {
|
||||
tableFooterView.frame.size = tableFooterView.systemLayoutSizeFitting(UIView.layoutFittingExpandedSize)
|
||||
self.tableView.tableFooterView = tableFooterView
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AboutInstanceViewController: UITableViewDelegate {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import UIKit
|
||||
import MastodonSDK
|
||||
import MetaTextKit
|
||||
|
||||
enum ServerDetailsTab: Int, CaseIterable {
|
||||
case about = 0
|
||||
|
@ -22,10 +23,11 @@ protocol ServerDetailsViewControllerDelegate: AnyObject {
|
|||
|
||||
class ServerDetailsViewController: UIViewController {
|
||||
|
||||
weak var delegate: (ServerDetailsViewControllerDelegate & AboutInstanceViewControllerDelegate & InstanceRulesViewControllerDelegate)? {
|
||||
weak var delegate: (ServerDetailsViewControllerDelegate & AboutInstanceViewControllerDelegate & InstanceRulesViewControllerDelegate & MetaLabelDelegate)? {
|
||||
didSet {
|
||||
aboutInstanceViewController.delegate = delegate
|
||||
instanceRulesViewController.delegate = delegate
|
||||
aboutInstanceViewController.footerView.contentLabel.linkDelegate = delegate
|
||||
}
|
||||
}
|
||||
let pageController: UIPageViewController
|
||||
|
@ -121,6 +123,10 @@ class ServerDetailsViewController: UIViewController {
|
|||
aboutInstanceViewController.update(with: instance)
|
||||
instanceRulesViewController.update(with: instance)
|
||||
}
|
||||
|
||||
func updateFooter(with extendedDescription: Mastodon.Entity.ExtendedDescription) {
|
||||
aboutInstanceViewController.updateFooter(with: extendedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UIPageViewControllerDataSource
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import MetaTextKit
|
||||
import MastodonSDK
|
||||
import MastodonMeta
|
||||
import MastodonCore
|
||||
import MastodonAsset
|
||||
|
||||
class AboutInstanceTableFooterView: UIView {
|
||||
let headlineLabel: UILabel
|
||||
let contentLabel: MetaLabel
|
||||
|
||||
init() {
|
||||
|
||||
headlineLabel = UILabel()
|
||||
headlineLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
headlineLabel.font = UIFontMetrics(forTextStyle: .title2).scaledFont(for: .systemFont(ofSize: 22, weight: .bold))
|
||||
|
||||
contentLabel = MetaLabel(style: .aboutInstance)
|
||||
contentLabel.numberOfLines = 0
|
||||
contentLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
super.init(frame: .zero)
|
||||
|
||||
addSubview(headlineLabel)
|
||||
addSubview(contentLabel)
|
||||
|
||||
setupConstraints()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
|
||||
private func setupConstraints() {
|
||||
|
||||
let horizontalMargin = 16.0
|
||||
|
||||
let constraints = [
|
||||
headlineLabel.topAnchor.constraint(equalTo: topAnchor, constant: 24),
|
||||
headlineLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: horizontalMargin),
|
||||
trailingAnchor.constraint(equalTo: headlineLabel.trailingAnchor, constant: horizontalMargin),
|
||||
|
||||
contentLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: 8),
|
||||
contentLabel.leadingAnchor.constraint(equalTo: headlineLabel.leadingAnchor),
|
||||
contentLabel.trailingAnchor.constraint(equalTo: headlineLabel.trailingAnchor),
|
||||
// contentLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 3000),
|
||||
bottomAnchor.constraint(equalTo: contentLabel.bottomAnchor),
|
||||
]
|
||||
|
||||
NSLayoutConstraint.activate(constraints)
|
||||
}
|
||||
|
||||
func update(with extendedDescription: Mastodon.Entity.ExtendedDescription) {
|
||||
headlineLabel.text = "A legal notice"
|
||||
|
||||
if let metaContent = try? MastodonMetaContent.convert(document: MastodonContent(content: extendedDescription.content, emojis: [:])) {
|
||||
contentLabel.configure(content: metaContent)
|
||||
} else {
|
||||
let content = PlaintextMetaContent(string: extendedDescription.content)
|
||||
contentLabel.configure(content: content)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import MastodonCore
|
|||
import CoreDataStack
|
||||
import MastodonSDK
|
||||
import Combine
|
||||
import MetaTextKit
|
||||
|
||||
protocol SettingsCoordinatorDelegate: AnyObject {
|
||||
func logout(_ settingsCoordinator: SettingsCoordinator)
|
||||
|
@ -80,6 +81,15 @@ extension SettingsCoordinator: SettingsViewControllerDelegate {
|
|||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
appContext.apiService.extendedDescription(domain: domain)
|
||||
.sink { _ in
|
||||
|
||||
} receiveValue: { content in
|
||||
serverDetailsViewController.updateFooter(with: content.value)
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
|
||||
navigationController.pushViewController(serverDetailsViewController, animated: true)
|
||||
case .aboutMastodon:
|
||||
let aboutViewController = AboutViewController()
|
||||
|
@ -228,3 +238,29 @@ extension SettingsCoordinator: AboutInstanceViewControllerDelegate {
|
|||
extension SettingsCoordinator: InstanceRulesViewControllerDelegate {
|
||||
|
||||
}
|
||||
|
||||
extension SettingsCoordinator: MetaLabelDelegate {
|
||||
@MainActor
|
||||
func metaLabel(_ metaLabel: MetaLabel, didSelectMeta meta: Meta) {
|
||||
switch meta {
|
||||
case .url(_, _, let url, _):
|
||||
guard let url = URL(string: url) else { return }
|
||||
_ = sceneCoordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
case .mention(_, _, let userInfo):
|
||||
guard let href = userInfo?["href"] as? String,
|
||||
let url = URL(string: href) else { return }
|
||||
_ = sceneCoordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
case .hashtag(_, let hashtag, _):
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(context: appContext, authContext: authContext, hashtag: hashtag)
|
||||
_ = sceneCoordinator.present(scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel), from: nil, transition: .show)
|
||||
case .email(let email, _):
|
||||
if let emailUrl = URL(string: "mailto:\(email)"), UIApplication.shared.canOpenURL(emailUrl) {
|
||||
UIApplication.shared.open(emailUrl)
|
||||
}
|
||||
case .emoji:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ extension MetaLabel {
|
|||
case accountListUsername
|
||||
case sidebarHeadline(isSelected: Bool)
|
||||
case sidebarSubheadline(isSelected: Bool)
|
||||
case aboutInstance
|
||||
}
|
||||
|
||||
public convenience init(style: Style) {
|
||||
|
@ -129,6 +130,10 @@ extension MetaLabel {
|
|||
case .sidebarSubheadline(let isSelected):
|
||||
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 13, weight: .regular), maximumPointSize: 18)
|
||||
textColor = isSelected ? .white : Asset.Colors.Label.secondary.color
|
||||
case .aboutInstance:
|
||||
font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular))
|
||||
textColor = .label
|
||||
paragraphStyle.paragraphSpacing = 0
|
||||
}
|
||||
|
||||
self.font = font
|
||||
|
|
Loading…
Reference in New Issue