2022-05-16 13:42:03 +02:00
|
|
|
//
|
|
|
|
// FamiliarFollowersDashboardView+ViewModel.swift
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Created by MainasuK on 2022-5-16.
|
|
|
|
//
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
import Combine
|
2022-05-17 11:40:19 +02:00
|
|
|
import CoreDataStack
|
2023-03-20 08:02:41 +01:00
|
|
|
import Meta
|
2022-10-08 07:43:06 +02:00
|
|
|
import MastodonCore
|
2022-05-17 11:40:19 +02:00
|
|
|
import MastodonMeta
|
2022-05-17 17:27:58 +02:00
|
|
|
import MastodonLocalization
|
2022-05-16 13:42:03 +02:00
|
|
|
|
|
|
|
extension FamiliarFollowersDashboardView {
|
|
|
|
public final class ViewModel: ObservableObject {
|
|
|
|
public var disposeBag = Set<AnyCancellable>()
|
|
|
|
|
|
|
|
@Published var avatarURLs: [URL?] = []
|
|
|
|
@Published var names: [String] = []
|
2022-05-17 11:40:19 +02:00
|
|
|
@Published var emojis: MastodonContent.Emojis = [:]
|
2022-05-16 13:42:03 +02:00
|
|
|
@Published var backgroundColor: UIColor?
|
2023-03-20 08:02:41 +01:00
|
|
|
|
|
|
|
@Published var label: MetaContent?
|
2022-05-16 13:42:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension FamiliarFollowersDashboardView.ViewModel {
|
|
|
|
func bind(view: FamiliarFollowersDashboardView) {
|
2022-05-17 11:40:19 +02:00
|
|
|
Publishers.CombineLatest3(
|
2022-05-16 13:42:03 +02:00
|
|
|
$avatarURLs,
|
2022-05-17 11:40:19 +02:00
|
|
|
$backgroundColor,
|
|
|
|
UIContentSizeCategory.publisher
|
2022-05-16 13:42:03 +02:00
|
|
|
)
|
2022-05-17 11:40:19 +02:00
|
|
|
.sink { avatarURLs, backgroundColor, contentSizeCategory in
|
2022-05-17 17:27:58 +02:00
|
|
|
// only using first 4 items
|
|
|
|
let avatarURLs = avatarURLs.prefix(4)
|
|
|
|
|
2022-05-16 13:42:03 +02:00
|
|
|
view.avatarContainerView.subviews.forEach { $0.removeFromSuperview() }
|
2022-05-17 11:40:19 +02:00
|
|
|
|
|
|
|
let initialOffset = min(12 * 1.5, UIFontMetrics(forTextStyle: .headline).scaledValue(for: 12)) // max 1.5x
|
|
|
|
let offset = min(20 * 1.5, UIFontMetrics(forTextStyle: .headline).scaledValue(for: 20))
|
|
|
|
let dimension = min(32 * 1.5, UIFontMetrics(forTextStyle: .headline).scaledValue(for: 32))
|
|
|
|
let borderWidth = min(1.5, UIFontMetrics.default.scaledValue(for: 1))
|
|
|
|
|
2022-05-16 13:42:03 +02:00
|
|
|
for (i, avatarURL) in avatarURLs.enumerated() {
|
|
|
|
let avatarButton = AvatarButton()
|
2022-05-17 11:40:19 +02:00
|
|
|
let origin = CGPoint(x: offset * CGFloat(i), y: 0)
|
|
|
|
let size = CGSize(width: dimension, height: dimension)
|
2022-05-16 13:42:03 +02:00
|
|
|
avatarButton.size = size
|
|
|
|
avatarButton.frame = CGRect(origin: origin, size: size)
|
|
|
|
view.avatarContainerView.addSubview(avatarButton)
|
2022-05-17 11:40:19 +02:00
|
|
|
avatarButton.avatarImageView.configure(
|
|
|
|
configuration: .init(
|
|
|
|
url: avatarURL,
|
|
|
|
placeholder: .placeholder(color: .systemGray3)
|
|
|
|
)
|
|
|
|
)
|
2022-05-16 13:42:03 +02:00
|
|
|
avatarButton.avatarImageView.configure(
|
|
|
|
cornerConfiguration: .init(
|
|
|
|
corner: .fixed(radius: 7),
|
|
|
|
border: .init(
|
|
|
|
color: backgroundColor ?? .clear,
|
2022-05-17 11:40:19 +02:00
|
|
|
width: borderWidth
|
2022-05-16 13:42:03 +02:00
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-05-17 11:40:19 +02:00
|
|
|
let avatarContainerViewWidth = initialOffset + offset * CGFloat(avatarURLs.count)
|
|
|
|
view.avatarContainerViewWidthLayoutConstraint.constant = avatarContainerViewWidth
|
|
|
|
view.avatarContainerViewHeightLayoutConstraint.constant = dimension
|
2022-05-16 13:42:03 +02:00
|
|
|
}
|
|
|
|
.store(in: &disposeBag)
|
|
|
|
|
2023-03-20 08:02:41 +01:00
|
|
|
let label = Publishers.CombineLatest(
|
2022-05-17 11:40:19 +02:00
|
|
|
$names,
|
|
|
|
$emojis
|
|
|
|
)
|
2023-03-20 08:02:41 +01:00
|
|
|
.map { (names, emojis) -> MetaContent in
|
2022-05-17 11:40:19 +02:00
|
|
|
let content: String = {
|
|
|
|
guard names.count > 0 else { return " " }
|
|
|
|
|
|
|
|
let count = names.count
|
|
|
|
let firstTwoNames = names.prefix(2).joined(separator: ", ")
|
|
|
|
|
|
|
|
switch names.count {
|
|
|
|
case 1..<3:
|
2022-05-17 17:27:58 +02:00
|
|
|
return L10n.Scene.Familiarfollowers.followedByNames(firstTwoNames)
|
2022-05-17 11:40:19 +02:00
|
|
|
default:
|
2022-05-17 17:27:58 +02:00
|
|
|
// Note: SwiftGen generates wrong formate argv for "%1$@"
|
2022-05-17 11:40:19 +02:00
|
|
|
let remains = count - 2
|
2022-05-17 17:27:58 +02:00
|
|
|
let format = MastodonLocalization.bundle.localizedString(forKey: "plural.count.followed_by_and_mutual", value: nil, table: "Localizable")
|
|
|
|
return String(format: format, locale: .current, arguments: [firstTwoNames, remains])
|
2022-05-17 11:40:19 +02:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
let document = MastodonContent(content: content, emojis: emojis)
|
|
|
|
do {
|
2023-03-20 08:02:41 +01:00
|
|
|
return try MastodonMetaContent.convert(document: document)
|
2022-05-17 11:40:19 +02:00
|
|
|
} catch {
|
|
|
|
assertionFailure()
|
2023-03-20 08:02:41 +01:00
|
|
|
return PlaintextMetaContent(string: content)
|
2022-05-17 11:40:19 +02:00
|
|
|
}
|
|
|
|
}
|
2023-03-20 08:02:41 +01:00
|
|
|
|
|
|
|
label
|
|
|
|
.sink { [weak self] metaContent in
|
|
|
|
view.descriptionMetaLabel.configure(content: metaContent)
|
|
|
|
self?.label = metaContent
|
|
|
|
}
|
|
|
|
.store(in: &disposeBag)
|
2022-05-16 13:42:03 +02:00
|
|
|
}
|
|
|
|
}
|