mirror of
https://github.com/metabolist/metatext.git
synced 2024-12-21 21:26:26 +00:00
View following / followers
This commit is contained in:
parent
03a4d1299d
commit
acfd127672
9 changed files with 87 additions and 14 deletions
14
Extensions/UIButton+Extensions.swift
Normal file
14
Extensions/UIButton+Extensions.swift
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIButton {
|
||||
func setAttributedLocalizedTitle(localizationKey: String, count: Int) {
|
||||
let localizedTitle = String.localizedStringWithFormat(NSLocalizedString(localizationKey, comment: ""), count)
|
||||
|
||||
setAttributedTitle(localizedTitle.countEmphasizedAttributedString(count: count), for: .normal)
|
||||
setAttributedTitle(
|
||||
localizedTitle.countEmphasizedAttributedString(count: count, highlighted: true),
|
||||
for: .highlighted)
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
"account.field.verified" = "Verified %@";
|
||||
"account.follow" = "Follow";
|
||||
"account.following" = "Following";
|
||||
"account.following-count" = "%ld Following";
|
||||
"account.hide-reblogs" = "Hide boosts";
|
||||
"account.mute" = "Mute";
|
||||
"account.request" = "Request";
|
||||
|
|
|
@ -9,6 +9,8 @@ public enum AccountsEndpoint {
|
|||
case favouritedBy(id: Status.Id)
|
||||
case mutes
|
||||
case blocks
|
||||
case accountsFollowers(id: Account.Id)
|
||||
case accountsFollowing(id: Account.Id)
|
||||
}
|
||||
|
||||
extension AccountsEndpoint: Endpoint {
|
||||
|
@ -20,6 +22,8 @@ extension AccountsEndpoint: Endpoint {
|
|||
return defaultContext + ["statuses"]
|
||||
case .mutes, .blocks:
|
||||
return defaultContext
|
||||
case .accountsFollowers, .accountsFollowing:
|
||||
return defaultContext + ["accounts"]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,6 +37,10 @@ extension AccountsEndpoint: Endpoint {
|
|||
return ["mutes"]
|
||||
case .blocks:
|
||||
return ["blocks"]
|
||||
case let .accountsFollowers(id):
|
||||
return [id, "followers"]
|
||||
case let .accountsFollowing(id):
|
||||
return [id, "following"]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
D08B8D72254246E200B1EBEF /* PollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08B8D71254246E200B1EBEF /* PollView.swift */; };
|
||||
D08B8D822544D80000B1EBEF /* PollOptionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08B8D812544D80000B1EBEF /* PollOptionButton.swift */; };
|
||||
D08B8D8D2544E6EC00B1EBEF /* PollResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08B8D8C2544E6EC00B1EBEF /* PollResultView.swift */; };
|
||||
D08E512125786A6600FA2C5F /* UIButton+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08E512025786A6600FA2C5F /* UIButton+Extensions.swift */; };
|
||||
D0A1F4F7252E7D4B004435BF /* TableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A1F4F6252E7D4B004435BF /* TableViewDataSource.swift */; };
|
||||
D0A7AC7325748BFF00E4E8AB /* ReportStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A7AC7225748BFF00E4E8AB /* ReportStatusView.swift */; };
|
||||
D0B32F50250B373600311912 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B32F4F250B373600311912 /* RegistrationView.swift */; };
|
||||
|
@ -157,6 +158,7 @@
|
|||
D08B8D71254246E200B1EBEF /* PollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollView.swift; sourceTree = "<group>"; };
|
||||
D08B8D812544D80000B1EBEF /* PollOptionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionButton.swift; sourceTree = "<group>"; };
|
||||
D08B8D8C2544E6EC00B1EBEF /* PollResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollResultView.swift; sourceTree = "<group>"; };
|
||||
D08E512025786A6600FA2C5F /* UIButton+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Extensions.swift"; sourceTree = "<group>"; };
|
||||
D0A1F4F6252E7D4B004435BF /* TableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewDataSource.swift; sourceTree = "<group>"; };
|
||||
D0A7AC7225748BFF00E4E8AB /* ReportStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportStatusView.swift; sourceTree = "<group>"; };
|
||||
D0AD03552505814D0085A466 /* Base16 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Base16; sourceTree = "<group>"; };
|
||||
|
@ -433,6 +435,7 @@
|
|||
D0C7D46B24F76169001EBDBB /* NSMutableAttributedString+Extensions.swift */,
|
||||
D0B5FE9A251583DB00478838 /* ProfileCollection+Extensions.swift */,
|
||||
D0C7D46A24F76169001EBDBB /* String+Extensions.swift */,
|
||||
D08E512025786A6600FA2C5F /* UIButton+Extensions.swift */,
|
||||
D0C7D46C24F76169001EBDBB /* UIColor+Extensions.swift */,
|
||||
D0030981250C6C8500EACB32 /* URL+Extensions.swift */,
|
||||
D0C7D46F24F76169001EBDBB /* View+Extensions.swift */,
|
||||
|
@ -674,6 +677,7 @@
|
|||
D0C7D49724F7616A001EBDBB /* IdentitiesView.swift in Sources */,
|
||||
D01EF22425182B1F00650C6B /* AccountHeaderView.swift in Sources */,
|
||||
D036AA17254CA824009094DF /* StatusBodyView.swift in Sources */,
|
||||
D08E512125786A6600FA2C5F /* UIButton+Extensions.swift in Sources */,
|
||||
D0EA59482522B8B600804347 /* ViewConstants.swift in Sources */,
|
||||
D04226FD2546AC0B000980A3 /* StartupAndSyncingPreferencesView.swift in Sources */,
|
||||
D036AA0C254B612B009094DF /* NotificationContentConfiguration.swift in Sources */,
|
||||
|
|
|
@ -90,6 +90,20 @@ public extension AccountService {
|
|||
func report(_ elements: ReportElements) -> AnyPublisher<Never, Error> {
|
||||
mastodonAPIClient.request(ReportEndpoint.create(elements)).ignoreOutput().eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func followingService() -> AccountListService {
|
||||
AccountListService(
|
||||
endpoint: .accountsFollowing(id: account.id),
|
||||
mastodonAPIClient: mastodonAPIClient,
|
||||
contentDatabase: contentDatabase)
|
||||
}
|
||||
|
||||
func followersService() -> AccountListService {
|
||||
AccountListService(
|
||||
endpoint: .accountsFollowers(id: account.id),
|
||||
mastodonAPIClient: mastodonAPIClient,
|
||||
contentDatabase: contentDatabase)
|
||||
}
|
||||
}
|
||||
|
||||
private extension AccountService {
|
||||
|
|
|
@ -19,7 +19,7 @@ final class ProfileViewController: TableViewController {
|
|||
super.viewDidLoad()
|
||||
|
||||
// Initial size is to avoid unsatisfiable constraint warning
|
||||
let accountHeaderView = AccountHeaderView(frame: .init(origin: .zero, size: .init(width: 100, height: 100)))
|
||||
let accountHeaderView = AccountHeaderView(frame: .init(origin: .zero, size: .init(width: 300, height: 300)))
|
||||
|
||||
accountHeaderView.viewModel = viewModel
|
||||
|
||||
|
|
|
@ -46,6 +46,10 @@ public extension AccountViewModel {
|
|||
|
||||
var emoji: [Emoji] { accountService.account.emojis }
|
||||
|
||||
var followingCount: Int { accountService.account.followingCount }
|
||||
|
||||
var followersCount: Int { accountService.account.followersCount }
|
||||
|
||||
var isSelf: Bool { accountService.account.id == identification.identity.account?.id }
|
||||
|
||||
func avatarURL(profile: Bool = false) -> URL {
|
||||
|
@ -66,6 +70,20 @@ public extension AccountViewModel {
|
|||
.eraseToAnyPublisher())
|
||||
}
|
||||
|
||||
func followingSelected() {
|
||||
eventsSubject.send(
|
||||
Just(.navigation(.collection(accountService.followingService())))
|
||||
.setFailureType(to: Error.self)
|
||||
.eraseToAnyPublisher())
|
||||
}
|
||||
|
||||
func followersSelected() {
|
||||
eventsSubject.send(
|
||||
Just(.navigation(.collection(accountService.followersService())))
|
||||
.setFailureType(to: Error.self)
|
||||
.eraseToAnyPublisher())
|
||||
}
|
||||
|
||||
func reportViewModel() -> ReportViewModel {
|
||||
ReportViewModel(accountService: accountService, identification: identification)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@ final class AccountHeaderView: UIView {
|
|||
let lockedImageView = UIImageView()
|
||||
let fieldsStackView = UIStackView()
|
||||
let noteTextView = TouchFallthroughTextView()
|
||||
let followStackView = UIStackView()
|
||||
let followingButton = UIButton()
|
||||
let followersButton = UIButton()
|
||||
let segmentedControl = UISegmentedControl()
|
||||
|
||||
var viewModel: ProfileViewModel? {
|
||||
|
@ -100,8 +103,17 @@ final class AccountHeaderView: UIView {
|
|||
mutableNote.resizeAttachments(toLineHeight: noteFont.lineHeight)
|
||||
noteTextView.attributedText = mutableNote
|
||||
noteTextView.isHidden = false
|
||||
|
||||
followingButton.setAttributedLocalizedTitle(
|
||||
localizationKey: "account.following-count",
|
||||
count: accountViewModel.followingCount)
|
||||
followersButton.setAttributedLocalizedTitle(
|
||||
localizationKey: "account.followers-count",
|
||||
count: accountViewModel.followersCount)
|
||||
followStackView.isHidden = false
|
||||
} else {
|
||||
noteTextView.isHidden = true
|
||||
followStackView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -264,6 +276,19 @@ private extension AccountHeaderView {
|
|||
noteTextView.isScrollEnabled = false
|
||||
noteTextView.delegate = self
|
||||
|
||||
baseStackView.addArrangedSubview(followStackView)
|
||||
followStackView.distribution = .fillEqually
|
||||
|
||||
followingButton.addAction(
|
||||
UIAction { [weak self] _ in self?.viewModel?.accountViewModel?.followingSelected() },
|
||||
for: .touchUpInside)
|
||||
followStackView.addArrangedSubview(followingButton)
|
||||
|
||||
followersButton.addAction(
|
||||
UIAction { [weak self] _ in self?.viewModel?.accountViewModel?.followersSelected() },
|
||||
for: .touchUpInside)
|
||||
followStackView.addArrangedSubview(followersButton)
|
||||
|
||||
for (index, collection) in ProfileCollection.allCases.enumerated() {
|
||||
segmentedControl.insertSegment(
|
||||
action: UIAction(title: collection.title) { [weak self] _ in
|
||||
|
|
|
@ -347,13 +347,11 @@ private extension StatusView {
|
|||
let noFavorites = viewModel.favoritesCount == 0
|
||||
let noInteractions = !isContextParent || (noReblogs && noFavorites)
|
||||
|
||||
setAttributedLocalizedTitle(
|
||||
button: rebloggedByButton,
|
||||
rebloggedByButton.setAttributedLocalizedTitle(
|
||||
localizationKey: "status.reblogs-count",
|
||||
count: viewModel.reblogsCount)
|
||||
rebloggedByButton.isHidden = noReblogs
|
||||
setAttributedLocalizedTitle(
|
||||
button: favoritedByButton,
|
||||
favoritedByButton.setAttributedLocalizedTitle(
|
||||
localizationKey: "status.favorites-count",
|
||||
count: viewModel.favoritesCount)
|
||||
favoritedByButton.isHidden = noFavorites
|
||||
|
@ -421,15 +419,6 @@ private extension StatusView {
|
|||
menuButton.setImage(UIImage(systemName: "ellipsis",
|
||||
withConfiguration: UIImage.SymbolConfiguration(scale: scale)), for: .normal)
|
||||
}
|
||||
|
||||
func setAttributedLocalizedTitle(button: UIButton, localizationKey: String, count: Int) {
|
||||
let localizedTitle = String.localizedStringWithFormat(NSLocalizedString(localizationKey, comment: ""), count)
|
||||
|
||||
button.setAttributedTitle(localizedTitle.countEmphasizedAttributedString(count: count), for: .normal)
|
||||
button.setAttributedTitle(
|
||||
localizedTitle.countEmphasizedAttributedString(count: count, highlighted: true),
|
||||
for: .highlighted)
|
||||
}
|
||||
}
|
||||
|
||||
private extension UIButton {
|
||||
|
|
Loading…
Reference in a new issue