Begin implementing verified link in UserView (IOS-140)
This commit is contained in:
parent
c638d86cb7
commit
645542c581
|
@ -46,5 +46,18 @@ extension UserView {
|
|||
.map { $0 as String? }
|
||||
.assign(to: \.authorUsername, on: viewModel)
|
||||
.store(in: &disposeBag)
|
||||
|
||||
user.publisher(for: \.followersCount)
|
||||
.map { Int($0) }
|
||||
.assign(to: \.authorFollowers, on: viewModel)
|
||||
.store(in: &disposeBag)
|
||||
|
||||
user.publisher(for: \.fields)
|
||||
.map { fields in
|
||||
let firstVerified = fields.first(where: { $0.verifiedAt != nil })
|
||||
return firstVerified?.value
|
||||
}
|
||||
.assign(to: \.authorVerifiedLink, on: viewModel)
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension NSAttributedString {
|
||||
convenience init(format: NSAttributedString, args: NSAttributedString...) {
|
||||
let mutableNSAttributedString = NSMutableAttributedString(attributedString: format)
|
||||
|
||||
args.forEach { attributedString in
|
||||
let range = NSString(string: mutableNSAttributedString.string).range(of: "%@")
|
||||
mutableNSAttributedString.replaceCharacters(in: range, with: attributedString)
|
||||
}
|
||||
|
||||
self.init(attributedString: mutableNSAttributedString)
|
||||
}
|
||||
}
|
|
@ -10,6 +10,8 @@ import UIKit
|
|||
import Combine
|
||||
import MetaTextKit
|
||||
import MastodonCore
|
||||
import MastodonMeta
|
||||
import MastodonAsset
|
||||
|
||||
extension UserView {
|
||||
public final class ViewModel: ObservableObject {
|
||||
|
@ -22,6 +24,8 @@ extension UserView {
|
|||
@Published public var authorAvatarImageURL: URL?
|
||||
@Published public var authorName: MetaContent?
|
||||
@Published public var authorUsername: String?
|
||||
@Published public var authorFollowers: Int?
|
||||
@Published public var authorVerifiedLink: String?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,5 +78,43 @@ extension UserView.ViewModel {
|
|||
}
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
$authorFollowers
|
||||
.sink { count in
|
||||
guard let count = count else {
|
||||
userView.authorFollowersLabel.text = nil
|
||||
return
|
||||
}
|
||||
userView.authorFollowersLabel.attributedText = NSAttributedString(
|
||||
format: NSAttributedString(string: "%@ followers", attributes: [.font: Font.systemFont(ofSize: 15, weight: .regular)]),
|
||||
args: NSAttributedString(string: count.formatted(), attributes: [.font: Font.systemFont(ofSize: 15, weight: .bold)])
|
||||
)
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
$authorVerifiedLink
|
||||
.sink { link in
|
||||
userView.authorVerifiedImageView.image = link == nil ? UIImage(systemName: "questionmark.circle") : UIImage(systemName: "checkmark")
|
||||
|
||||
switch link {
|
||||
case let .some(link):
|
||||
userView.authorVerifiedImageView.tintColor = Asset.Colors.brand.color
|
||||
userView.authorVerifiedLabel.textColor = Asset.Colors.brand.color
|
||||
do {
|
||||
let mastodonContent = MastodonContent(content: link, emojis: [:])
|
||||
let content = try MastodonMetaContent.convert(document: mastodonContent)
|
||||
userView.authorVerifiedLabel.configure(content: content)
|
||||
} catch {
|
||||
let content = PlaintextMetaContent(string: link)
|
||||
userView.authorVerifiedLabel.configure(content: content)
|
||||
}
|
||||
case .none:
|
||||
userView.authorVerifiedImageView.tintColor = .secondaryLabel
|
||||
userView.authorVerifiedLabel.configure(content: PlaintextMetaContent(string: "No verified link"))
|
||||
userView.authorVerifiedLabel.textColor = .secondaryLabel
|
||||
}
|
||||
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
import UIKit
|
||||
import Combine
|
||||
import MetaTextKit
|
||||
import MastodonAsset
|
||||
import os
|
||||
|
||||
public final class UserView: UIView {
|
||||
|
||||
|
@ -38,6 +40,44 @@ public final class UserView: UIView {
|
|||
// author username
|
||||
public let authorUsernameLabel = MetaLabel(style: .statusUsername)
|
||||
|
||||
public let authorFollowersLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.textColor = .secondaryLabel
|
||||
return label
|
||||
}()
|
||||
|
||||
public let authorVerifiedLabel: MetaLabel = {
|
||||
let label = MetaLabel(style: .profileFieldValue)
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.textAttributes = [
|
||||
.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular)),
|
||||
.foregroundColor: UIColor.secondaryLabel
|
||||
]
|
||||
label.linkAttributes = [
|
||||
.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold)),
|
||||
.foregroundColor: Asset.Colors.brand.color
|
||||
]
|
||||
label.isUserInteractionEnabled = false
|
||||
return label
|
||||
}()
|
||||
|
||||
public let authorVerifiedImageView: UIImageView = {
|
||||
let imageView = UIImageView()
|
||||
imageView.setContentHuggingPriority(.required, for: .horizontal)
|
||||
imageView.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
|
||||
imageView.setContentHuggingPriority(.required, for: .vertical)
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
return imageView
|
||||
}()
|
||||
|
||||
public let verifiedStackView: UIStackView = {
|
||||
let stackView = UIStackView()
|
||||
stackView.axis = .horizontal
|
||||
stackView.alignment = .center
|
||||
return stackView
|
||||
}()
|
||||
|
||||
public func prepareForReuse() {
|
||||
disposeBag.removeAll()
|
||||
|
||||
|
@ -82,11 +122,38 @@ extension UserView {
|
|||
labelStackView.axis = .vertical
|
||||
containerStackView.addArrangedSubview(labelStackView)
|
||||
|
||||
labelStackView.addArrangedSubview(authorNameLabel)
|
||||
labelStackView.addArrangedSubview(authorUsernameLabel)
|
||||
authorNameLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical)
|
||||
authorUsernameLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical)
|
||||
let nameStackView = UIStackView()
|
||||
nameStackView.axis = .horizontal
|
||||
|
||||
let nameSpacer = UIView()
|
||||
nameSpacer.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
||||
|
||||
nameStackView.addArrangedSubview(authorNameLabel)
|
||||
nameStackView.addArrangedSubview(authorUsernameLabel)
|
||||
nameStackView.addArrangedSubview(nameSpacer)
|
||||
|
||||
authorNameLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical)
|
||||
authorNameLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
|
||||
|
||||
authorUsernameLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical)
|
||||
authorUsernameLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
|
||||
|
||||
labelStackView.addArrangedSubview(nameStackView)
|
||||
labelStackView.addArrangedSubview(authorFollowersLabel)
|
||||
|
||||
let verifiedSpacerView = UIView()
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
authorVerifiedImageView.widthAnchor.constraint(equalToConstant: 15),
|
||||
verifiedSpacerView.widthAnchor.constraint(equalToConstant: 2)
|
||||
])
|
||||
|
||||
verifiedStackView.addArrangedSubview(authorVerifiedImageView)
|
||||
verifiedStackView.addArrangedSubview(verifiedSpacerView)
|
||||
verifiedStackView.addArrangedSubview(authorVerifiedLabel)
|
||||
|
||||
labelStackView.addArrangedSubview(verifiedStackView)
|
||||
|
||||
avatarButton.isUserInteractionEnabled = false
|
||||
authorNameLabel.isUserInteractionEnabled = false
|
||||
authorUsernameLabel.isUserInteractionEnabled = false
|
||||
|
|
Loading…
Reference in New Issue