mirror of
https://github.com/metabolist/metatext.git
synced 2024-12-22 05:26:30 +00:00
Account statuses wip
This commit is contained in:
parent
92bc777a7e
commit
55ba5f856a
16 changed files with 236 additions and 39 deletions
|
@ -114,6 +114,16 @@ public extension ContentDatabase {
|
|||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func insert(accounts: [Account]) -> AnyPublisher<Never, Error> {
|
||||
databaseQueue.writePublisher {
|
||||
for account in accounts {
|
||||
try account.save($0)
|
||||
}
|
||||
}
|
||||
.ignoreOutput()
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func setLists(_ lists: [MastodonList]) -> AnyPublisher<Never, Error> {
|
||||
databaseQueue.writePublisher {
|
||||
for list in lists {
|
||||
|
@ -246,6 +256,20 @@ public extension ContentDatabase {
|
|||
.publisher(in: databaseQueue)
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func accountObservation(id: String) -> AnyPublisher<Account?, Error> {
|
||||
ValueObservation.tracking(AccountRecord.filter(Column("id") == id).accountResultRequest.fetchOne)
|
||||
.removeDuplicates()
|
||||
.publisher(in: databaseQueue)
|
||||
.map {
|
||||
if let result = $0 {
|
||||
return Account(result: result)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
||||
private extension ContentDatabase {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public enum AccountStatusCollection: String, Codable {
|
||||
public enum AccountStatusCollection: String, Codable, CaseIterable {
|
||||
case statuses
|
||||
case statusesAndReplies
|
||||
case media
|
||||
|
|
17
Extensions/AccountStatusCollection+Extensions.swift
Normal file
17
Extensions/AccountStatusCollection+Extensions.swift
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import ViewModels
|
||||
|
||||
extension AccountStatusCollection {
|
||||
var title: String {
|
||||
switch self {
|
||||
case .statuses:
|
||||
return NSLocalizedString("account.statuses", comment: "")
|
||||
case .statusesAndReplies:
|
||||
return NSLocalizedString("account.statuses-and-replies", comment: "")
|
||||
case .media:
|
||||
return NSLocalizedString("account.media", comment: "")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
"account.statuses" = "Posts";
|
||||
"account.statuses-and-replies" = "Posts & Replies";
|
||||
"account.media" = "Media";
|
||||
"add" = "Add";
|
||||
"apns-default-message" = "New notification";
|
||||
"add-identity.instance-url" = "Instance URL";
|
||||
|
|
|
@ -6,6 +6,7 @@ import Mastodon
|
|||
|
||||
public enum AccountEndpoint {
|
||||
case verifyCredentials
|
||||
case accounts(id: String)
|
||||
}
|
||||
|
||||
extension AccountEndpoint: Endpoint {
|
||||
|
@ -18,12 +19,13 @@ extension AccountEndpoint: Endpoint {
|
|||
public var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .verifyCredentials: return ["verify_credentials"]
|
||||
case let .accounts(id): return [id]
|
||||
}
|
||||
}
|
||||
|
||||
public var method: HTTPMethod {
|
||||
switch self {
|
||||
case .verifyCredentials: return .get
|
||||
case .verifyCredentials, .accounts: return .get
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
D0030982250C6C8500EACB32 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0030981250C6C8500EACB32 /* URL+Extensions.swift */; };
|
||||
D01EF22425182B1F00650C6B /* AccountHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01EF22325182B1F00650C6B /* AccountHeaderView.swift */; };
|
||||
D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */; };
|
||||
D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41E224F8889700D55A2D /* AttachmentsView.swift */; };
|
||||
D02E1F95250B13210071AD56 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02E1F94250B13210071AD56 /* SafariView.swift */; };
|
||||
|
@ -16,6 +17,7 @@
|
|||
D0625E5F250F0CFF00502611 /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0625E5E250F0CFF00502611 /* StatusView.swift */; };
|
||||
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = D06B492224D4611300642749 /* KingfisherSwiftUI */; };
|
||||
D0B32F50250B373600311912 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B32F4F250B373600311912 /* RegistrationView.swift */; };
|
||||
D0B5FE9B251583DB00478838 /* AccountStatusCollection+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B5FE9A251583DB00478838 /* AccountStatusCollection+Extensions.swift */; };
|
||||
D0B7434925100DBB00C13DB6 /* StatusView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D0B7434825100DBB00C13DB6 /* StatusView.xib */; };
|
||||
D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */; };
|
||||
D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */; };
|
||||
|
@ -84,6 +86,7 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
D0030981250C6C8500EACB32 /* URL+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Extensions.swift"; sourceTree = "<group>"; };
|
||||
D01EF22325182B1F00650C6B /* AccountHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountHeaderView.swift; sourceTree = "<group>"; };
|
||||
D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TouchFallthroughTextView.swift; sourceTree = "<group>"; };
|
||||
D01F41E224F8889700D55A2D /* AttachmentsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentsView.swift; sourceTree = "<group>"; };
|
||||
D02E1F94250B13210071AD56 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = "<group>"; };
|
||||
|
@ -96,6 +99,7 @@
|
|||
D085C3BB25008DEC008A6C5E /* DB */ = {isa = PBXFileReference; lastKnownFileType = folder; path = DB; sourceTree = "<group>"; };
|
||||
D0AD03552505814D0085A466 /* Base16 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Base16; sourceTree = "<group>"; };
|
||||
D0B32F4F250B373600311912 /* RegistrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationView.swift; sourceTree = "<group>"; };
|
||||
D0B5FE9A251583DB00478838 /* AccountStatusCollection+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountStatusCollection+Extensions.swift"; sourceTree = "<group>"; };
|
||||
D0B7434825100DBB00C13DB6 /* StatusView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StatusView.xib; sourceTree = "<group>"; };
|
||||
D0BDF66524FD7A6400C7FA1C /* ServiceLayer */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ServiceLayer; sourceTree = "<group>"; };
|
||||
D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentView.swift; sourceTree = "<group>"; };
|
||||
|
@ -222,7 +226,6 @@
|
|||
D0625E58250F092900502611 /* StatusListCell.swift */,
|
||||
D0625E5E250F0CFF00502611 /* StatusView.swift */,
|
||||
D0B7434825100DBB00C13DB6 /* StatusView.xib */,
|
||||
D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */,
|
||||
);
|
||||
path = Status;
|
||||
sourceTree = "<group>";
|
||||
|
@ -254,7 +257,7 @@
|
|||
D0C7D42024F76169001EBDBB /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0625E55250F086B00502611 /* Status */,
|
||||
D01EF22325182B1F00650C6B /* AccountHeaderView.swift */,
|
||||
D0C7D42424F76169001EBDBB /* AddIdentityView.swift */,
|
||||
D01F41E024F8885900D55A2D /* Attachments */,
|
||||
D0C7D42324F76169001EBDBB /* CustomEmojiText.swift */,
|
||||
|
@ -270,8 +273,10 @@
|
|||
D0C7D42724F76169001EBDBB /* RootView.swift */,
|
||||
D02E1F94250B13210071AD56 /* SafariView.swift */,
|
||||
D0C7D42924F76169001EBDBB /* SecondaryNavigationView.swift */,
|
||||
D0625E55250F086B00502611 /* Status */,
|
||||
D0C7D42524F76169001EBDBB /* StatusListView.swift */,
|
||||
D0C7D42E24F76169001EBDBB /* TabNavigationView.swift */,
|
||||
D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
@ -305,12 +310,13 @@
|
|||
D0C7D46824F76169001EBDBB /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0B5FE9A251583DB00478838 /* AccountStatusCollection+Extensions.swift */,
|
||||
D0C7D46E24F76169001EBDBB /* KingfisherOptionsInfo+Extensions.swift */,
|
||||
D0C7D46B24F76169001EBDBB /* NSMutableAttributedString+Extensions.swift */,
|
||||
D0C7D46A24F76169001EBDBB /* String+Extensions.swift */,
|
||||
D0C7D46C24F76169001EBDBB /* UIColor+Extensions.swift */,
|
||||
D0C7D46F24F76169001EBDBB /* View+Extensions.swift */,
|
||||
D0030981250C6C8500EACB32 /* URL+Extensions.swift */,
|
||||
D0C7D46F24F76169001EBDBB /* View+Extensions.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
|
@ -506,6 +512,7 @@
|
|||
D0625E5F250F0CFF00502611 /* StatusView.swift in Sources */,
|
||||
D0625E59250F092900502611 /* StatusListCell.swift in Sources */,
|
||||
D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.swift in Sources */,
|
||||
D0B5FE9B251583DB00478838 /* AccountStatusCollection+Extensions.swift in Sources */,
|
||||
D0C7D49E24F7616A001EBDBB /* SecondaryNavigationView.swift in Sources */,
|
||||
D0C7D4DA24F7616A001EBDBB /* View+Extensions.swift in Sources */,
|
||||
D0C7D4D524F7616A001EBDBB /* String+Extensions.swift in Sources */,
|
||||
|
@ -514,6 +521,7 @@
|
|||
D0C7D4D924F7616A001EBDBB /* KingfisherOptionsInfo+Extensions.swift in Sources */,
|
||||
D0BEB1FF24F9E5BB001B0F04 /* ListsView.swift in Sources */,
|
||||
D0C7D49724F7616A001EBDBB /* IdentitiesView.swift in Sources */,
|
||||
D01EF22425182B1F00650C6B /* AccountHeaderView.swift in Sources */,
|
||||
D0C7D49824F7616A001EBDBB /* CustomEmojiText.swift in Sources */,
|
||||
D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */,
|
||||
D0BEB21124FA2A91001B0F04 /* EditFilterView.swift in Sources */,
|
||||
|
|
|
@ -19,7 +19,12 @@ public struct AccountStatusesService {
|
|||
}
|
||||
|
||||
public extension AccountStatusesService {
|
||||
func statusListService(collectionPublisher: AnyPublisher<AccountStatusCollection, Never>) -> StatusListService {
|
||||
func accountObservation() -> AnyPublisher<Account?, Error> {
|
||||
contentDatabase.accountObservation(id: accountID)
|
||||
}
|
||||
|
||||
func statusListService(
|
||||
collectionPublisher: CurrentValueSubject<AccountStatusCollection, Never>) -> StatusListService {
|
||||
StatusListService(
|
||||
accountID: accountID,
|
||||
collection: collectionPublisher,
|
||||
|
@ -37,4 +42,10 @@ public extension AccountStatusesService {
|
|||
.flatMap { contentDatabase.insert(pinnedStatuses: $0, accountID: accountID) }
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func fetchAccount() -> AnyPublisher<Never, Error> {
|
||||
mastodonAPIClient.request(AccountEndpoint.accounts(id: accountID))
|
||||
.flatMap { contentDatabase.insert(accounts: [$0]) }
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ extension StatusListService {
|
|||
|
||||
init(
|
||||
accountID: String,
|
||||
collection: AnyPublisher<AccountStatusCollection, Never>,
|
||||
collection: CurrentValueSubject<AccountStatusCollection, Never>,
|
||||
mastodonAPIClient: MastodonAPIClient,
|
||||
contentDatabase: ContentDatabase) {
|
||||
self.init(
|
||||
|
@ -63,33 +63,29 @@ extension StatusListService {
|
|||
filterContext: .account,
|
||||
mastodonAPIClient: mastodonAPIClient,
|
||||
contentDatabase: contentDatabase) { maxID, minID in
|
||||
Just((maxID, minID)).combineLatest(collection).flatMap { params -> AnyPublisher<Never, Error> in
|
||||
let ((maxID, minID), collection) = params
|
||||
let excludeReplies: Bool
|
||||
let onlyMedia: Bool
|
||||
let excludeReplies: Bool
|
||||
let onlyMedia: Bool
|
||||
|
||||
switch collection {
|
||||
case .statuses:
|
||||
excludeReplies = true
|
||||
onlyMedia = false
|
||||
case .statusesAndReplies:
|
||||
excludeReplies = false
|
||||
onlyMedia = false
|
||||
case .media:
|
||||
excludeReplies = true
|
||||
onlyMedia = true
|
||||
}
|
||||
|
||||
let endpoint = StatusesEndpoint.accountsStatuses(
|
||||
id: accountID,
|
||||
excludeReplies: excludeReplies,
|
||||
onlyMedia: onlyMedia,
|
||||
pinned: false)
|
||||
return mastodonAPIClient.request(Paged(endpoint, maxID: maxID, minID: minID))
|
||||
.flatMap { contentDatabase.insert(statuses: $0, accountID: accountID, collection: collection) }
|
||||
.eraseToAnyPublisher()
|
||||
switch collection.value {
|
||||
case .statuses:
|
||||
excludeReplies = true
|
||||
onlyMedia = false
|
||||
case .statusesAndReplies:
|
||||
excludeReplies = false
|
||||
onlyMedia = false
|
||||
case .media:
|
||||
excludeReplies = true
|
||||
onlyMedia = true
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
|
||||
let endpoint = StatusesEndpoint.accountsStatuses(
|
||||
id: accountID,
|
||||
excludeReplies: excludeReplies,
|
||||
onlyMedia: onlyMedia,
|
||||
pinned: false)
|
||||
return mastodonAPIClient.request(Paged(endpoint, maxID: maxID, minID: minID))
|
||||
.flatMap { contentDatabase.insert(statuses: $0, accountID: accountID, collection: collection.value) }
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import SafariServices
|
|||
import SwiftUI
|
||||
import ViewModels
|
||||
|
||||
final class StatusListViewController: UITableViewController {
|
||||
class StatusListViewController: UITableViewController {
|
||||
private let viewModel: StatusListViewModel
|
||||
private let loadingTableFooterView = LoadingTableFooterView()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
@ -77,6 +77,21 @@ final class StatusListViewController: UITableViewController {
|
|||
self.sizeTableHeaderFooterViews()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
if let accountsStatusesViewModel = viewModel as? AccountStatusesViewModel {
|
||||
// Initial size is to avoid unsatisfiable constraint warning
|
||||
let accountHeaderView = AccountHeaderView(
|
||||
frame: .init(
|
||||
origin: .zero,
|
||||
size: .init(width: 100, height: 100)))
|
||||
accountHeaderView.viewModel = accountsStatusesViewModel
|
||||
accountsStatusesViewModel.$account.dropFirst().receive(on: DispatchQueue.main).sink { [weak self] _ in
|
||||
accountHeaderView.viewModel = accountsStatusesViewModel
|
||||
self?.sizeTableHeaderFooterViews()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
tableView.tableHeaderView = accountHeaderView
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
|
|
|
@ -6,20 +6,25 @@ import Mastodon
|
|||
import ServiceLayer
|
||||
|
||||
public class AccountStatusesViewModel: StatusListViewModel {
|
||||
@Published var collection: AccountStatusCollection
|
||||
@Published public private(set) var account: Account?
|
||||
@Published public var collection = AccountStatusCollection.statuses
|
||||
private let accountStatusesService: AccountStatusesService
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
init(accountStatusesService: AccountStatusesService) {
|
||||
self.accountStatusesService = accountStatusesService
|
||||
|
||||
var collection = Published(initialValue: AccountStatusCollection.statuses)
|
||||
|
||||
_collection = collection
|
||||
let collectionSubject = CurrentValueSubject<AccountStatusCollection, Never>(.statuses)
|
||||
|
||||
super.init(
|
||||
statusListService: accountStatusesService.statusListService(
|
||||
collectionPublisher: collection.projectedValue.eraseToAnyPublisher()))
|
||||
collectionPublisher: collectionSubject))
|
||||
|
||||
$collection.sink(receiveValue: collectionSubject.send).store(in: &cancellables)
|
||||
|
||||
accountStatusesService.accountObservation()
|
||||
.assignErrorsToAlertItem(to: \.alertItem, on: self)
|
||||
.assign(to: &$account)
|
||||
}
|
||||
|
||||
public override func request(maxID: String? = nil, minID: String? = nil) {
|
||||
|
@ -37,3 +42,12 @@ public class AccountStatusesViewModel: StatusListViewModel {
|
|||
collection == .statuses && statusIDs.first?.contains(status.id) ?? false
|
||||
}
|
||||
}
|
||||
|
||||
public extension AccountStatusesViewModel {
|
||||
func fetchAccount() {
|
||||
accountStatusesService.fetchAccount()
|
||||
.assignErrorsToAlertItem(to: \.alertItem, on: self)
|
||||
.sink { _ in }
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import ServiceLayer
|
||||
|
||||
public typealias AccountStatusCollection = ServiceLayer.AccountStatusCollection
|
|
@ -28,7 +28,7 @@ public class StatusListViewModel: ObservableObject {
|
|||
.handleEvents(receiveOutput: { [weak self] in
|
||||
self?.determineIfScrollPositionShouldBeMaintained(newStatusSections: $0)
|
||||
self?.cleanViewModelCache(newStatusSections: $0)
|
||||
self?.statuses = Dictionary(uniqueKeysWithValues: $0.reduce([], +).map { ($0.id, $0) })
|
||||
self?.statuses = Dictionary(uniqueKeysWithValues: Set($0.reduce([], +)).map { ($0.id, $0) })
|
||||
})
|
||||
.receive(on: DispatchQueue.main)
|
||||
.assignErrorsToAlertItem(to: \.alertItem, on: self)
|
||||
|
|
|
@ -123,6 +123,13 @@ public extension StatusViewModel {
|
|||
.eraseToAnyPublisher())
|
||||
}
|
||||
|
||||
func accountSelected() {
|
||||
eventsSubject.send(
|
||||
Just(Event.navigation(.accountID(statusService.status.displayStatus.account.id)))
|
||||
.setFailureType(to: Error.self)
|
||||
.eraseToAnyPublisher())
|
||||
}
|
||||
|
||||
func toggleFavorited() {
|
||||
eventsSubject.send(statusService.toggleFavorited().map { _ in Event.ignorableOutput }.eraseToAnyPublisher())
|
||||
}
|
||||
|
|
91
Views/AccountHeaderView.swift
Normal file
91
Views/AccountHeaderView.swift
Normal file
|
@ -0,0 +1,91 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Kingfisher
|
||||
import UIKit
|
||||
import ViewModels
|
||||
|
||||
class AccountHeaderView: UIView {
|
||||
let headerImageView = UIImageView()
|
||||
let noteTextView = TouchFallthroughTextView()
|
||||
let segmentedControl = UISegmentedControl()
|
||||
|
||||
var viewModel: AccountStatusesViewModel? {
|
||||
didSet {
|
||||
if let account = viewModel?.account {
|
||||
headerImageView.kf.setImage(with: account.header)
|
||||
|
||||
let noteFont = UIFont.preferredFont(forTextStyle: .callout)
|
||||
let mutableNote = NSMutableAttributedString(attributedString: account.note.attributed)
|
||||
let noteRange = NSRange(location: 0, length: mutableNote.length)
|
||||
mutableNote.removeAttribute(.font, range: noteRange)
|
||||
mutableNote.addAttributes(
|
||||
[.font: noteFont as Any,
|
||||
.foregroundColor: UIColor.label],
|
||||
range: noteRange)
|
||||
mutableNote.insert(emoji: account.emojis, view: noteTextView)
|
||||
mutableNote.resizeAttachments(toLineHeight: noteFont.lineHeight)
|
||||
noteTextView.attributedText = mutableNote
|
||||
noteTextView.isHidden = false
|
||||
} else {
|
||||
noteTextView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
initializationActions()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
private extension AccountHeaderView {
|
||||
func initializationActions() {
|
||||
let baseStackView = UIStackView()
|
||||
|
||||
addSubview(headerImageView)
|
||||
addSubview(baseStackView)
|
||||
headerImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
baseStackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
baseStackView.axis = .vertical
|
||||
|
||||
noteTextView.isScrollEnabled = false
|
||||
baseStackView.addArrangedSubview(noteTextView)
|
||||
|
||||
for (index, collection) in AccountStatusCollection.allCases.enumerated() {
|
||||
segmentedControl.insertSegment(
|
||||
action: UIAction(title: collection.title) { [weak self] _ in
|
||||
self?.viewModel?.collection = collection
|
||||
self?.viewModel?.request()
|
||||
},
|
||||
at: index,
|
||||
animated: false)
|
||||
}
|
||||
|
||||
segmentedControl.selectedSegmentIndex = 0
|
||||
|
||||
baseStackView.addArrangedSubview(segmentedControl)
|
||||
|
||||
let headerImageAspectRatioConstraint = headerImageView.heightAnchor.constraint(
|
||||
equalTo: headerImageView.widthAnchor,
|
||||
multiplier: 9 / 16)
|
||||
|
||||
headerImageAspectRatioConstraint.priority = .init(999)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
headerImageAspectRatioConstraint,
|
||||
headerImageView.topAnchor.constraint(equalTo: topAnchor),
|
||||
headerImageView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||
headerImageView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
||||
baseStackView.topAnchor.constraint(equalTo: headerImageView.bottomAnchor),
|
||||
baseStackView.leadingAnchor.constraint(equalTo: readableContentGuide.leadingAnchor),
|
||||
baseStackView.trailingAnchor.constraint(equalTo: readableContentGuide.trailingAnchor),
|
||||
baseStackView.bottomAnchor.constraint(equalTo: bottomAnchor)
|
||||
])
|
||||
}
|
||||
}
|
|
@ -145,6 +145,10 @@ private extension StatusView {
|
|||
avatarButton.setBackgroundImage(highlightedButtonBackgroundImage, for: .highlighted)
|
||||
contextParentAvatarButton.setBackgroundImage(highlightedButtonBackgroundImage, for: .highlighted)
|
||||
|
||||
let accountAction = UIAction { [weak self] _ in self?.statusConfiguration.viewModel.accountSelected() }
|
||||
|
||||
avatarButton.addAction(accountAction, for: .touchUpInside)
|
||||
|
||||
let favoriteAction = UIAction { [weak self] _ in self?.statusConfiguration.viewModel.toggleFavorited() }
|
||||
|
||||
favoriteButton.addAction(favoriteAction, for: .touchUpInside)
|
||||
|
|
Loading…
Reference in a new issue