mastodon-ios/Mastodon/Diffiable/Onboarding/PickServerSection.swift

165 lines
6.7 KiB
Swift

//
// PickServerSection.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021/3/5.
//
import UIKit
import MastodonSDK
import Kanna
import AlamofireImage
enum PickServerSection: Equatable, Hashable {
case header
case servers
}
extension PickServerSection {
static func tableViewDiffableDataSource(
for tableView: UITableView,
dependency: NeedsDependency,
pickServerCellDelegate: PickServerCellDelegate
) -> UITableViewDiffableDataSource<PickServerSection, PickServerItem> {
tableView.register(OnboardingHeadlineTableViewCell.self, forCellReuseIdentifier: String(describing: OnboardingHeadlineTableViewCell.self))
tableView.register(PickServerCell.self, forCellReuseIdentifier: String(describing: PickServerCell.self))
tableView.register(PickServerLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: PickServerLoaderTableViewCell.self))
return UITableViewDiffableDataSource(tableView: tableView) { [
weak dependency,
weak pickServerCellDelegate
] tableView, indexPath, item -> UITableViewCell? in
guard let _ = dependency else { return nil }
switch item {
case .header:
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: OnboardingHeadlineTableViewCell.self), for: indexPath) as! OnboardingHeadlineTableViewCell
return cell
case .server(let server, let attribute):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerCell.self), for: indexPath) as! PickServerCell
PickServerSection.configure(cell: cell, server: server, attribute: attribute)
cell.delegate = pickServerCellDelegate
return cell
case .loader(let attribute):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerLoaderTableViewCell.self), for: indexPath) as! PickServerLoaderTableViewCell
PickServerSection.configure(cell: cell, attribute: attribute)
return cell
}
}
}
}
extension PickServerSection {
static func configure(cell: PickServerCell, server: Mastodon.Entity.Server, attribute: PickServerItem.ServerItemAttribute) {
cell.domainLabel.text = server.domain
cell.descriptionLabel.attributedText = {
let content: String = {
guard let html = try? HTML(html: server.description, encoding: .utf8) else {
return server.description
}
return html.text ?? server.description
}()
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineHeightMultiple = 1.16
return NSAttributedString(
string: content,
attributes: [
.paragraphStyle: paragraphStyle
]
)
}()
cell.usersValueLabel.attributedText = {
let attributedString = NSMutableAttributedString()
let attachment = NSTextAttachment(image: UIImage(systemName: "person.2.fill")!)
let attachmentAttributedString = NSAttributedString(attachment: attachment)
attributedString.append(attachmentAttributedString)
attributedString.append(NSAttributedString(string: " "))
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineHeightMultiple = 1.12
let valueAttributedString = NSAttributedString(
string: parseUsersCount(server.totalUsers),
attributes: [
.paragraphStyle: paragraphStyle
]
)
attributedString.append(valueAttributedString)
return attributedString
}()
cell.langValueLabel.attributedText = {
let attributedString = NSMutableAttributedString()
let attachment = NSTextAttachment(image: UIImage(systemName: "text.bubble.fill")!)
let attachmentAttributedString = NSAttributedString(attachment: attachment)
attributedString.append(attachmentAttributedString)
attributedString.append(NSAttributedString(string: " "))
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineHeightMultiple = 1.12
let valueAttributedString = NSAttributedString(
string: server.language.uppercased(),
attributes: [
.paragraphStyle: paragraphStyle
]
)
attributedString.append(valueAttributedString)
return attributedString
}()
attribute.isLast
.receive(on: DispatchQueue.main)
.sink { [weak cell] isLast in
guard let cell = cell else { return }
if isLast {
cell.containerView.layer.maskedCorners = [
.layerMinXMaxYCorner,
.layerMaxXMaxYCorner
]
cell.containerView.layer.cornerCurve = .continuous
cell.containerView.layer.cornerRadius = MastodonPickServerAppearance.tableViewCornerRadius
cell.containerView.layer.masksToBounds = true
} else {
cell.containerView.layer.cornerRadius = 0
cell.containerView.layer.masksToBounds = false
}
}
.store(in: &cell.disposeBag)
}
private static func parseUsersCount(_ usersCount: Int) -> String {
switch usersCount {
case 0..<1000:
return "\(usersCount)"
default:
let usersCountInThousand = Float(usersCount) / 1000.0
return String(format: "%.1fK", usersCountInThousand)
}
}
}
extension PickServerSection {
static func configure(cell: PickServerLoaderTableViewCell, attribute: PickServerItem.LoaderItemAttribute) {
if attribute.isLast {
cell.containerView.layer.maskedCorners = [
.layerMinXMaxYCorner,
.layerMaxXMaxYCorner
]
cell.containerView.layer.cornerCurve = .continuous
cell.containerView.layer.cornerRadius = MastodonPickServerAppearance.tableViewCornerRadius
cell.containerView.layer.masksToBounds = true
} else {
cell.containerView.layer.cornerRadius = 0
cell.containerView.layer.masksToBounds = false
}
attribute.isNoResult ? cell.stopAnimating() : cell.startAnimating()
cell.emptyStatusLabel.isHidden = !attribute.isNoResult
}
}