// // ProfileHeaderViewModel.swift // Mastodon // // Created by MainasuK Cirno on 2021-4-9. // import UIKit import Combine import CoreDataStack import Kanna import MastodonSDK import MastodonMeta import MastodonCore import MastodonUI final class ProfileHeaderViewModel { static let avatarImageMaxSizeInPixel = CGSize(width: 400, height: 400) static let bannerImageMaxSizeInPixel = CGSize(width: 1500, height: 500) static let maxProfileFieldCount = 4 var disposeBag = Set() // input let context: AppContext let authContext: AuthContext @Published var me: Mastodon.Entity.Account @Published var account: Mastodon.Entity.Account @Published var relationship: Mastodon.Entity.Relationship? @Published var isMyself = false @Published var isEditing = false @Published var isUpdating = false @Published var accountForEdit: Mastodon.Entity.Account? // let needsFiledCollectionViewHidden = CurrentValueSubject(false) // output let profileInfo = ProfileInfo() let profileInfoEditing = ProfileInfo() @Published var isTitleViewDisplaying = false @Published var isTitleViewContentOffsetSet = false init(context: AppContext, authContext: AuthContext, account: Mastodon.Entity.Account, me: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?) { self.context = context self.authContext = authContext self.account = account self.me = me self.relationship = relationship $accountForEdit .receive(on: DispatchQueue.main) .sink { [weak self] account in guard let self = self else { return } guard let account = account else { return } // banner self.profileInfo.header = nil self.profileInfoEditing.header = nil // avatar self.profileInfo.avatar = nil self.profileInfoEditing.avatar = nil // name let name = account.displayNameWithFallback self.profileInfo.name = name self.profileInfoEditing.name = name // bio let note = ProfileHeaderViewModel.normalize(note: account.note) self.profileInfo.note = note self.profileInfoEditing.note = note } .store(in: &disposeBag) } } extension ProfileHeaderViewModel { class ProfileInfo { // input @Published var header: UIImage? @Published var avatar: UIImage? @Published var name: String? @Published var note: String? } } extension ProfileHeaderViewModel { static func normalize(note: String?) -> String? { let _note = note?.replacingOccurrences(of: "
|
", with: "\u{2028}", options: .regularExpression, range: nil) .replacingOccurrences(of: "

", with: "

\u{2029}", range: nil) .trimmingCharacters(in: .whitespacesAndNewlines) guard let note = _note, !note.isEmpty else { return nil } let html = try? HTML(html: note, encoding: .utf8) return html?.text } } // MARK: - ProfileViewModelEditable extension ProfileHeaderViewModel: ProfileViewModelEditable { var isEdited: Bool { guard isEditing else { return false } guard profileInfoEditing.header == nil else { return true } guard profileInfoEditing.avatar == nil else { return true } guard profileInfo.name == profileInfoEditing.name else { return true } guard profileInfo.note == profileInfoEditing.note else { return true } return false } }