Begin implementing verified link in UserView (IOS-140)

This commit is contained in:
Marcus Kida 2023-04-20 16:28:30 +02:00
parent c638d86cb7
commit 645542c581
No known key found for this signature in database
GPG Key ID: 19FF64E08013CA40
4 changed files with 142 additions and 4 deletions

View File

@ -46,5 +46,18 @@ extension UserView {
.map { $0 as String? } .map { $0 as String? }
.assign(to: \.authorUsername, on: viewModel) .assign(to: \.authorUsername, on: viewModel)
.store(in: &disposeBag) .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)
} }
} }

View File

@ -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)
}
}

View File

@ -10,6 +10,8 @@ import UIKit
import Combine import Combine
import MetaTextKit import MetaTextKit
import MastodonCore import MastodonCore
import MastodonMeta
import MastodonAsset
extension UserView { extension UserView {
public final class ViewModel: ObservableObject { public final class ViewModel: ObservableObject {
@ -22,6 +24,8 @@ extension UserView {
@Published public var authorAvatarImageURL: URL? @Published public var authorAvatarImageURL: URL?
@Published public var authorName: MetaContent? @Published public var authorName: MetaContent?
@Published public var authorUsername: String? @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) .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)
} }
} }

View File

@ -8,6 +8,8 @@
import UIKit import UIKit
import Combine import Combine
import MetaTextKit import MetaTextKit
import MastodonAsset
import os
public final class UserView: UIView { public final class UserView: UIView {
@ -38,6 +40,44 @@ public final class UserView: UIView {
// author username // author username
public let authorUsernameLabel = MetaLabel(style: .statusUsername) 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() { public func prepareForReuse() {
disposeBag.removeAll() disposeBag.removeAll()
@ -82,10 +122,37 @@ extension UserView {
labelStackView.axis = .vertical labelStackView.axis = .vertical
containerStackView.addArrangedSubview(labelStackView) containerStackView.addArrangedSubview(labelStackView)
labelStackView.addArrangedSubview(authorNameLabel) let nameStackView = UIStackView()
labelStackView.addArrangedSubview(authorUsernameLabel) 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(.required - 1, for: .vertical)
authorNameLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
authorUsernameLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical) 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 avatarButton.isUserInteractionEnabled = false
authorNameLabel.isUserInteractionEnabled = false authorNameLabel.isUserInteractionEnabled = false