Show profile-page for suggested accounts in search (IOS-141)
This commit is contained in:
parent
1afecc85ea
commit
a304fb2108
|
@ -39,30 +39,31 @@ extension UserSection {
|
|||
|
||||
return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in
|
||||
switch item {
|
||||
case .user(let record):
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UserTableViewCell.self), for: indexPath) as! UserTableViewCell
|
||||
context.managedObjectContext.performAndWait {
|
||||
guard let user = record.object(in: context.managedObjectContext) else { return }
|
||||
configure(
|
||||
context: context,
|
||||
authContext: authContext,
|
||||
tableView: tableView,
|
||||
cell: cell,
|
||||
viewModel: UserTableViewCell.ViewModel(value: .user(user),
|
||||
followedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followingUserIds.eraseToAnyPublisher(),
|
||||
blockedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$blockedUserIds.eraseToAnyPublisher(),
|
||||
followRequestedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followRequestedUserIDs.eraseToAnyPublisher()
|
||||
),
|
||||
configuration: configuration
|
||||
)
|
||||
}
|
||||
case .user(let record):
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UserTableViewCell.self), for: indexPath) as! UserTableViewCell
|
||||
context.managedObjectContext.performAndWait {
|
||||
guard let user = record.object(in: context.managedObjectContext) else { return }
|
||||
configure(
|
||||
context: context,
|
||||
authContext: authContext,
|
||||
tableView: tableView,
|
||||
cell: cell,
|
||||
viewModel: UserTableViewCell.ViewModel(
|
||||
user: user,
|
||||
followedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followingUserIds.eraseToAnyPublisher(),
|
||||
blockedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$blockedUserIds.eraseToAnyPublisher(),
|
||||
followRequestedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followRequestedUserIDs.eraseToAnyPublisher()
|
||||
),
|
||||
configuration: configuration
|
||||
)
|
||||
}
|
||||
|
||||
return cell
|
||||
case .bottomLoader:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell
|
||||
cell.startAnimating()
|
||||
return cell
|
||||
case .bottomHeader(let text):
|
||||
return cell
|
||||
case .bottomLoader:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell
|
||||
cell.startAnimating()
|
||||
return cell
|
||||
case .bottomHeader(let text):
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineFooterTableViewCell.self), for: indexPath) as! TimelineFooterTableViewCell
|
||||
cell.messageLabel.text = text
|
||||
return cell
|
||||
|
|
|
@ -33,7 +33,7 @@ extension DataSourceFacade {
|
|||
|
||||
@MainActor
|
||||
static func coordinateToProfileScene(
|
||||
provider: DataSourceProvider & AuthContextProvider,
|
||||
provider: NeedsDependency & UIViewController & AuthContextProvider,
|
||||
user: ManagedObjectRecord<MastodonUser>
|
||||
) async {
|
||||
guard let user = user.object(in: provider.context.managedObjectContext) else {
|
||||
|
|
|
@ -51,36 +51,52 @@ class SearchResultsOverviewTableViewController: UIViewController, NeedsDependenc
|
|||
|
||||
case .suggestion(let suggestion):
|
||||
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: SearchResultDefaultSectionTableViewCell.reuseIdentifier, for: indexPath) as? SearchResultDefaultSectionTableViewCell else { fatalError() }
|
||||
switch suggestion {
|
||||
|
||||
cell.configure(item: suggestion)
|
||||
return cell
|
||||
case .hashtag(let hashtag):
|
||||
|
||||
// switch suggestion {
|
||||
//
|
||||
// case .hashtag(let hashtag):
|
||||
//
|
||||
// case .profile(let profile):
|
||||
// //TODO: Use `UserFetchedResultsController` or `Persistence.MastodonUser.fetch` ???
|
||||
//
|
||||
// guard let cell = tableView.dequeueReusableCell(withIdentifier: UserTableViewCell.reuseIdentifier, for: indexPath) as? UserTableViewCell else { fatalError() }
|
||||
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: SearchResultDefaultSectionTableViewCell.reuseIdentifier, for: indexPath) as? SearchResultDefaultSectionTableViewCell else { fatalError() }
|
||||
|
||||
cell.configure(item: .hashtag(tag: hashtag))
|
||||
return cell
|
||||
|
||||
//
|
||||
case .profile(let profile):
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: UserTableViewCell.reuseIdentifier, for: indexPath) as? UserTableViewCell else { fatalError() }
|
||||
|
||||
// how the fuck do I get a MastodonUser???
|
||||
// try await managedObjectContext.perform {
|
||||
// Persistence.MastodonUser.fetch(in: managedObjectContext,
|
||||
// context: Persistence.MastodonUser.PersistContext(
|
||||
// domain: domain,
|
||||
// entity: profile.value,
|
||||
// cache: nil,
|
||||
// networkDate: profile.netwo
|
||||
// ))
|
||||
// }
|
||||
//
|
||||
let managedObjectContext = appContext.managedObjectContext
|
||||
Task {
|
||||
do {
|
||||
|
||||
// cell.configure(me: <#T##MastodonUser?#>, tableView: <#T##UITableView#>, viewModel: <#T##UserTableViewCell.ViewModel#>, delegate: <#T##UserTableViewCellDelegate?#>)
|
||||
try await managedObjectContext.perform {
|
||||
guard let user = Persistence.MastodonUser.fetch(in: managedObjectContext,
|
||||
context: Persistence.MastodonUser.PersistContext(
|
||||
domain: authContext.mastodonAuthenticationBox.domain,
|
||||
entity: profile,
|
||||
cache: nil,
|
||||
networkDate: Date()
|
||||
)) else { return }
|
||||
|
||||
// return cell
|
||||
// }
|
||||
cell.configure(
|
||||
me: authContext.mastodonAuthenticationBox.authenticationRecord.object(in: managedObjectContext)?.user,
|
||||
tableView: tableView,
|
||||
viewModel: UserTableViewCell.ViewModel(
|
||||
user: user,
|
||||
followedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followingUserIds.eraseToAnyPublisher(),
|
||||
blockedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$blockedUserIds.eraseToAnyPublisher(),
|
||||
followRequestedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followRequestedUserIDs.eraseToAnyPublisher()),
|
||||
delegate: nil)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,6 +199,28 @@ class SearchResultsOverviewTableViewController: UIViewController, NeedsDependenc
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
func showProfile(for account: Mastodon.Entity.Account) {
|
||||
let managedObjectContext = context.managedObjectContext
|
||||
let domain = authContext.mastodonAuthenticationBox.domain
|
||||
|
||||
Task {
|
||||
let user = try await managedObjectContext.perform {
|
||||
return Persistence.MastodonUser.fetch(in: managedObjectContext,
|
||||
context: Persistence.MastodonUser.PersistContext(
|
||||
domain: domain,
|
||||
entity: account,
|
||||
cache: nil,
|
||||
networkDate: Date()
|
||||
))
|
||||
}
|
||||
|
||||
if let user {
|
||||
await DataSourceFacade.coordinateToProfileScene(provider:self,
|
||||
user: user.asRecord)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: UITableViewDelegate
|
||||
|
@ -198,8 +236,10 @@ extension SearchResultsOverviewTableViewController: UITableViewDelegate {
|
|||
case .default(let defaultSectionEntry):
|
||||
switch defaultSectionEntry {
|
||||
case .posts(let hashtag):
|
||||
//FIXME: Show statuses instead of tag-content. Reuse SearchResultsViewController with statuses here?
|
||||
showPosts(tag: Mastodon.Entity.Tag(name: hashtag, url: authContext.mastodonAuthenticationBox.domain))
|
||||
case .people(let string):
|
||||
//FIXME: Invoke SearchResultsViewController with people-scope here
|
||||
delegate?.showPeople(self)
|
||||
case .profile(let profile, let instanceName):
|
||||
delegate?.showProfile(self)
|
||||
|
@ -211,8 +251,8 @@ extension SearchResultsOverviewTableViewController: UITableViewDelegate {
|
|||
|
||||
case .hashtag(let tag):
|
||||
showPosts(tag: tag)
|
||||
case .profile(_):
|
||||
delegate?.showProfile(self)
|
||||
case .profile(let account):
|
||||
showProfile(for: account)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ extension SearchResultSection {
|
|||
authContext: authContext,
|
||||
tableView: tableView,
|
||||
cell: cell,
|
||||
viewModel: UserTableViewCell.ViewModel(value: .user(user),
|
||||
viewModel: UserTableViewCell.ViewModel(user: user,
|
||||
followedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followingUserIds.eraseToAnyPublisher(),
|
||||
blockedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$blockedUserIds.eraseToAnyPublisher(),
|
||||
followRequestedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followRequestedUserIDs.eraseToAnyPublisher()),
|
||||
|
|
|
@ -12,72 +12,63 @@ import Combine
|
|||
|
||||
extension UserTableViewCell {
|
||||
final class ViewModel {
|
||||
let value: Value
|
||||
let user: MastodonUser
|
||||
|
||||
let followedUsers: AnyPublisher<[String], Never>
|
||||
let blockedUsers: AnyPublisher<[String], Never>
|
||||
let followRequestedUsers: AnyPublisher<[String], Never>
|
||||
|
||||
init(value: Value, followedUsers: AnyPublisher<[String], Never>, blockedUsers: AnyPublisher<[String], Never>, followRequestedUsers: AnyPublisher<[String], Never>) {
|
||||
self.value = value
|
||||
init(user: MastodonUser, followedUsers: AnyPublisher<[String], Never>, blockedUsers: AnyPublisher<[String], Never>, followRequestedUsers: AnyPublisher<[String], Never>) {
|
||||
self.user = user
|
||||
self.followedUsers = followedUsers
|
||||
self.followRequestedUsers = followRequestedUsers
|
||||
self.blockedUsers = blockedUsers
|
||||
}
|
||||
|
||||
enum Value {
|
||||
case user(MastodonUser)
|
||||
// case status(Status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UserTableViewCell {
|
||||
|
||||
func configure(
|
||||
me: MastodonUser?,
|
||||
me: MastodonUser? = nil,
|
||||
tableView: UITableView,
|
||||
viewModel: ViewModel,
|
||||
delegate: UserTableViewCellDelegate?
|
||||
) {
|
||||
switch viewModel.value {
|
||||
case .user(let user):
|
||||
userView.configure(user: user, delegate: delegate)
|
||||
|
||||
guard let me = me else {
|
||||
return userView.setButtonState(.none)
|
||||
}
|
||||
|
||||
if user == me {
|
||||
userView.setButtonState(.none)
|
||||
} else {
|
||||
userView.setButtonState(.loading)
|
||||
}
|
||||
|
||||
Publishers.CombineLatest3(
|
||||
viewModel.followedUsers,
|
||||
viewModel.followRequestedUsers,
|
||||
viewModel.blockedUsers
|
||||
)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] followed, requested, blocked in
|
||||
if blocked.contains(user.id) {
|
||||
self?.userView.setButtonState(.blocked)
|
||||
} else if followed.contains(user.id) {
|
||||
self?.userView.setButtonState(.unfollow)
|
||||
} else if requested.contains(user.id) {
|
||||
self?.userView.setButtonState(.pending)
|
||||
} else if user.locked {
|
||||
self?.userView.setButtonState(.request)
|
||||
} else if user != me {
|
||||
self?.userView.setButtonState(.follow)
|
||||
}
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
userView.configure(user: viewModel.user, delegate: delegate)
|
||||
|
||||
guard let me = me else {
|
||||
return userView.setButtonState(.none)
|
||||
}
|
||||
|
||||
self.delegate = delegate
|
||||
if viewModel.user == me {
|
||||
userView.setButtonState(.none)
|
||||
} else {
|
||||
userView.setButtonState(.loading)
|
||||
}
|
||||
|
||||
Publishers.CombineLatest3(
|
||||
viewModel.followedUsers,
|
||||
viewModel.followRequestedUsers,
|
||||
viewModel.blockedUsers
|
||||
)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] followed, requested, blocked in
|
||||
if blocked.contains(viewModel.user.id) {
|
||||
self?.userView.setButtonState(.blocked)
|
||||
} else if followed.contains(viewModel.user.id) {
|
||||
self?.userView.setButtonState(.unfollow)
|
||||
} else if requested.contains(viewModel.user.id) {
|
||||
self?.userView.setButtonState(.pending)
|
||||
} else if viewModel.user.locked {
|
||||
self?.userView.setButtonState(.request)
|
||||
} else if viewModel.user != me {
|
||||
self?.userView.setButtonState(.follow)
|
||||
}
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
self.delegate = delegate
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue