forked from shadowfacts/Tusker
Add scope to search following accounts when editing list
Also fixes crash when loading or editing list Closes #216 Closes #221
This commit is contained in:
parent
d8bf770902
commit
523fb91b21
|
@ -82,14 +82,14 @@ public final class Account: AccountProtocol, Decodable {
|
|||
return Request<Empty>(method: .delete, path: "/api/v1/suggestions/\(account.id)")
|
||||
}
|
||||
|
||||
public static func getFollowers(_ account: Account, range: RequestRange = .default) -> Request<[Account]> {
|
||||
var request = Request<[Account]>(method: .get, path: "/api/v1/accounts/\(account.id)/followers")
|
||||
public static func getFollowers(_ accountID: String, range: RequestRange = .default) -> Request<[Account]> {
|
||||
var request = Request<[Account]>(method: .get, path: "/api/v1/accounts/\(accountID)/followers")
|
||||
request.range = range
|
||||
return request
|
||||
}
|
||||
|
||||
public static func getFollowing(_ account: Account, range: RequestRange = .default) -> Request<[Account]> {
|
||||
var request = Request<[Account]>(method: .get, path: "/api/v1/accounts/\(account.id)/following")
|
||||
public static func getFollowing(_ accountID: String, range: RequestRange = .default) -> Request<[Account]> {
|
||||
var request = Request<[Account]>(method: .get, path: "/api/v1/accounts/\(accountID)/following")
|
||||
request.range = range
|
||||
return request
|
||||
}
|
||||
|
|
|
@ -310,6 +310,8 @@
|
|||
D6F0B17524A3A1AA001E48C3 /* MainSidebarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F0B17424A3A1AA001E48C3 /* MainSidebarViewController.swift */; };
|
||||
D6F2E965249E8BFD005846BB /* IssueReporterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F2E963249E8BFD005846BB /* IssueReporterViewController.swift */; };
|
||||
D6F2E966249E8BFD005846BB /* IssueReporterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6F2E964249E8BFD005846BB /* IssueReporterViewController.xib */; };
|
||||
D6F6A54C291EF6FE00F496A8 /* EditListSearchResultsContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F6A54B291EF6FE00F496A8 /* EditListSearchResultsContainerViewController.swift */; };
|
||||
D6F6A54E291EF7E100F496A8 /* EditListSearchFollowingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F6A54D291EF7E100F496A8 /* EditListSearchFollowingViewController.swift */; };
|
||||
D6F953F021251A2900CF0F2B /* MastodonController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EF21251A2900CF0F2B /* MastodonController.swift */; };
|
||||
D6FF9860255C717400845181 /* AccountSwitchingContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6FF985F255C717400845181 /* AccountSwitchingContainerViewController.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -675,6 +677,8 @@
|
|||
D6F0B17424A3A1AA001E48C3 /* MainSidebarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainSidebarViewController.swift; sourceTree = "<group>"; };
|
||||
D6F2E963249E8BFD005846BB /* IssueReporterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueReporterViewController.swift; sourceTree = "<group>"; };
|
||||
D6F2E964249E8BFD005846BB /* IssueReporterViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IssueReporterViewController.xib; sourceTree = "<group>"; };
|
||||
D6F6A54B291EF6FE00F496A8 /* EditListSearchResultsContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditListSearchResultsContainerViewController.swift; sourceTree = "<group>"; };
|
||||
D6F6A54D291EF7E100F496A8 /* EditListSearchFollowingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditListSearchFollowingViewController.swift; sourceTree = "<group>"; };
|
||||
D6F953EF21251A2900CF0F2B /* MastodonController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonController.swift; sourceTree = "<group>"; };
|
||||
D6FF985F255C717400845181 /* AccountSwitchingContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSwitchingContainerViewController.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
@ -833,6 +837,8 @@
|
|||
children = (
|
||||
D627944C23A9A03D00D38C68 /* ListTimelineViewController.swift */,
|
||||
D627944E23A9C99800D38C68 /* EditListAccountsViewController.swift */,
|
||||
D6F6A54B291EF6FE00F496A8 /* EditListSearchResultsContainerViewController.swift */,
|
||||
D6F6A54D291EF7E100F496A8 /* EditListSearchFollowingViewController.swift */,
|
||||
);
|
||||
path = Lists;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1751,6 +1757,7 @@
|
|||
D6285B5321EA708700FE4B39 /* StatusFormat.swift in Sources */,
|
||||
D6DD353D22F28CD000A9563A /* ContentWarningCopyMode.swift in Sources */,
|
||||
0427033A22B31269000D31B6 /* AdvancedPrefsView.swift in Sources */,
|
||||
D6F6A54C291EF6FE00F496A8 /* EditListSearchResultsContainerViewController.swift in Sources */,
|
||||
D662AEEF263A3B880082A153 /* PollFinishedTableViewCell.swift in Sources */,
|
||||
D626493C23C1000300612E6E /* AlbumTableViewCell.swift in Sources */,
|
||||
D62275A624F1C81800B82A16 /* ComposeReplyView.swift in Sources */,
|
||||
|
@ -1982,6 +1989,7 @@
|
|||
D68E6F5F253C9B2D001A1B4C /* BaseEmojiLabel.swift in Sources */,
|
||||
D6F0B12B24A3071C001E48C3 /* MainSplitViewController.swift in Sources */,
|
||||
D6AEBB3E2321638100E5038B /* UIActivity+Types.swift in Sources */,
|
||||
D6F6A54E291EF7E100F496A8 /* EditListSearchFollowingViewController.swift in Sources */,
|
||||
D61AC1D5232E9FA600C54D2D /* InstanceSelectorTableViewController.swift in Sources */,
|
||||
D681E4D9246E346E0053414F /* AccountActivityItemSource.swift in Sources */,
|
||||
D626493F23C101C500612E6E /* AlbumAssetCollectionViewController.swift in Sources */,
|
||||
|
|
|
@ -221,10 +221,11 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
|||
}
|
||||
}
|
||||
|
||||
func addAll(accounts: [Account], completion: (() -> Void)? = nil) {
|
||||
backgroundContext.perform {
|
||||
accounts.forEach { self.upsert(account: $0, in: self.backgroundContext) }
|
||||
self.save(context: self.backgroundContext)
|
||||
func addAll(accounts: [Account], in context: NSManagedObjectContext? = nil, completion: (() -> Void)? = nil) {
|
||||
let context = context ?? backgroundContext
|
||||
context.perform {
|
||||
accounts.forEach { self.upsert(account: $0, in: context) }
|
||||
self.save(context: context)
|
||||
completion?()
|
||||
accounts.forEach { self.accountSubject.send($0.id) }
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class EditListAccountsViewController: EnhancedTableViewController {
|
|||
|
||||
var nextRange: RequestRange?
|
||||
|
||||
var searchResultsController: SearchResultsViewController!
|
||||
var searchResultsController: EditListSearchResultsContainerViewController!
|
||||
var searchController: UISearchController!
|
||||
|
||||
init(list: List, mastodonController: MastodonController) {
|
||||
|
@ -53,14 +53,23 @@ class EditListAccountsViewController: EnhancedTableViewController {
|
|||
})
|
||||
dataSource.editListAccountsController = self
|
||||
|
||||
searchResultsController = SearchResultsViewController(mastodonController: mastodonController, resultTypes: [.accounts])
|
||||
searchResultsController.delegate = self
|
||||
searchResultsController = EditListSearchResultsContainerViewController(mastodonController: mastodonController) { [unowned self] accountID in
|
||||
Task {
|
||||
await self.addAccount(id: accountID)
|
||||
}
|
||||
}
|
||||
searchController = UISearchController(searchResultsController: searchResultsController)
|
||||
searchController.hidesNavigationBarDuringPresentation = false
|
||||
searchController.searchResultsUpdater = searchResultsController
|
||||
if #available(iOS 16.0, *) {
|
||||
searchController.scopeBarActivation = .onSearchActivation
|
||||
} else {
|
||||
searchController.automaticallyShowsScopeBar = true
|
||||
}
|
||||
searchController.searchBar.autocapitalizationType = .none
|
||||
searchController.searchBar.placeholder = NSLocalizedString("Search for accounts to add", comment: "edit list search field placeholder")
|
||||
searchController.searchBar.delegate = searchResultsController
|
||||
searchController.searchBar.scopeButtonTitles = ["Everyone", "People You Follow"]
|
||||
definesPresentationContext = true
|
||||
|
||||
navigationItem.searchController = searchController
|
||||
|
@ -68,28 +77,66 @@ class EditListAccountsViewController: EnhancedTableViewController {
|
|||
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("Rename", comment: "rename list button title"), style: .plain, target: self, action: #selector(renameButtonPressed))
|
||||
|
||||
loadAccounts()
|
||||
Task {
|
||||
await loadAccounts()
|
||||
}
|
||||
}
|
||||
|
||||
func loadAccounts() {
|
||||
func loadAccounts() async {
|
||||
do {
|
||||
let request = List.getAccounts(list)
|
||||
mastodonController.run(request) { (response) in
|
||||
guard case let .success(accounts, pagination) = response else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
let (accounts, pagination) = try await mastodonController.run(request)
|
||||
self.nextRange = pagination?.older
|
||||
|
||||
self.mastodonController.persistentContainer.addAll(accounts: accounts) {
|
||||
var snapshot = self.dataSource.snapshot()
|
||||
snapshot.deleteSections([.accounts])
|
||||
snapshot.appendSections([.accounts])
|
||||
snapshot.appendItems(accounts.map { .account(id: $0.id) })
|
||||
await withCheckedContinuation { continuation in
|
||||
mastodonController.persistentContainer.addAll(accounts: accounts) {
|
||||
continuation.resume()
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.dataSource.apply(snapshot)
|
||||
var snapshot = self.dataSource.snapshot()
|
||||
if snapshot.indexOfSection(.accounts) == nil {
|
||||
snapshot.appendSections([.accounts])
|
||||
} else {
|
||||
snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .accounts))
|
||||
}
|
||||
snapshot.appendItems(accounts.map { .account(id: $0.id) })
|
||||
await dataSource.apply(snapshot)
|
||||
} catch {
|
||||
let config = ToastConfiguration(from: error, with: "Error Loading Accounts", in: self) { [unowned self] toast in
|
||||
toast.dismissToast(animated: true)
|
||||
await self.loadAccounts()
|
||||
}
|
||||
self.showToast(configuration: config, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
private func addAccount(id: String) async {
|
||||
do {
|
||||
let req = List.add(list, accounts: [id])
|
||||
_ = try await mastodonController.run(req)
|
||||
self.searchController.isActive = false
|
||||
await self.loadAccounts()
|
||||
} catch {
|
||||
let config = ToastConfiguration(from: error, with: "Error Adding Account", in: self) { [unowned self] toast in
|
||||
toast.dismissToast(animated: true)
|
||||
await self.addAccount(id: id)
|
||||
}
|
||||
self.showToast(configuration: config, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
private func removeAccount(id: String) async {
|
||||
do {
|
||||
let request = List.remove(list, accounts: [id])
|
||||
_ = try await mastodonController.run(request)
|
||||
await self.loadAccounts()
|
||||
} catch {
|
||||
let config = ToastConfiguration(from: error, with: "Error Removing Account", in: self) { [unowned self] toast in
|
||||
toast.dismissToast(animated: true)
|
||||
await self.removeAccount(id: id)
|
||||
}
|
||||
self.showToast(configuration: config, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,29 +192,8 @@ extension EditListAccountsViewController {
|
|||
return
|
||||
}
|
||||
|
||||
let request = List.remove(editListAccountsController!.list, accounts: [id])
|
||||
editListAccountsController!.mastodonController.run(request) { (response) in
|
||||
guard case .success(_, _) = response else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
self.editListAccountsController?.loadAccounts()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension EditListAccountsViewController: SearchResultsViewControllerDelegate {
|
||||
func selectedSearchResult(account accountID: String) {
|
||||
let request = List.add(list, accounts: [accountID])
|
||||
mastodonController.run(request) { (response) in
|
||||
guard case .success(_, _) = response else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
self.loadAccounts()
|
||||
DispatchQueue.main.async {
|
||||
self.searchController.isActive = false
|
||||
Task {
|
||||
await self.editListAccountsController?.removeAccount(id: id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
//
|
||||
// EditListSearchFollowingViewController.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 11/11/22.
|
||||
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Pachyderm
|
||||
|
||||
class EditListSearchFollowingViewController: EnhancedTableViewController {
|
||||
|
||||
private let mastodonController: MastodonController
|
||||
private let didSelectAccount: (String) -> Void
|
||||
|
||||
private var dataSource: UITableViewDiffableDataSource<Section, String>!
|
||||
|
||||
private var query: String?
|
||||
private var accountIDs: [String] = []
|
||||
private var nextRange: RequestRange?
|
||||
|
||||
init(mastodonController: MastodonController, didSelectAccount: @escaping (String) -> Void) {
|
||||
self.mastodonController = mastodonController
|
||||
self.didSelectAccount = didSelectAccount
|
||||
|
||||
super.init(style: .grouped)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tableView.register(UINib(nibName: "AccountTableViewCell", bundle: .main), forCellReuseIdentifier: "accountCell")
|
||||
dataSource = UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, itemIdentifier in
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "accountCell", for: indexPath) as! AccountTableViewCell
|
||||
cell.delegate = self
|
||||
cell.updateUI(accountID: itemIdentifier)
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
if dataSource.snapshot().numberOfItems == 0 {
|
||||
Task {
|
||||
await load()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||
print("will display: \(indexPath)")
|
||||
if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
|
||||
Task {
|
||||
await load()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
guard let id = dataSource.itemIdentifier(for: indexPath) else {
|
||||
return
|
||||
}
|
||||
didSelectAccount(id)
|
||||
}
|
||||
|
||||
private func load() async {
|
||||
do {
|
||||
let ownAccount = try await mastodonController.getOwnAccount()
|
||||
let req = Account.getFollowing(ownAccount.id, range: nextRange ?? .default)
|
||||
let (following, pagination) = try await mastodonController.run(req)
|
||||
await withCheckedContinuation { continuation in
|
||||
mastodonController.persistentContainer.addAll(accounts: following) {
|
||||
continuation.resume()
|
||||
}
|
||||
}
|
||||
accountIDs.append(contentsOf: following.lazy.map(\.id))
|
||||
nextRange = pagination?.older
|
||||
updateDataSource(appending: following.map(\.id))
|
||||
} catch {
|
||||
let config = ToastConfiguration(from: error, with: "Error Loading Following", in: self) { toast in
|
||||
toast.dismissToast(animated: true)
|
||||
await self.load()
|
||||
}
|
||||
self.showToast(configuration: config, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateDataSourceForQueryChanged() {
|
||||
guard let query, !query.isEmpty else {
|
||||
let snapshot = NSDiffableDataSourceSnapshot<Section, String>()
|
||||
dataSource.apply(snapshot, animatingDifferences: true)
|
||||
return
|
||||
}
|
||||
|
||||
let ids = filterAccounts(ids: accountIDs, with: query)
|
||||
|
||||
var snapshot = dataSource.snapshot()
|
||||
if snapshot.indexOfSection(.accounts) == nil {
|
||||
snapshot.appendSections([.accounts])
|
||||
} else {
|
||||
snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .accounts))
|
||||
}
|
||||
snapshot.appendItems(ids)
|
||||
dataSource.apply(snapshot, animatingDifferences: true)
|
||||
|
||||
// if there aren't any results for the current query, try to load more
|
||||
if ids.isEmpty {
|
||||
Task {
|
||||
await load()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func updateDataSource(appending ids: [String]) {
|
||||
guard let query, !query.isEmpty else {
|
||||
let snapshot = NSDiffableDataSourceSnapshot<Section, String>()
|
||||
dataSource.apply(snapshot, animatingDifferences: true)
|
||||
return
|
||||
}
|
||||
|
||||
let ids = filterAccounts(ids: ids, with: query)
|
||||
|
||||
var snapshot = dataSource.snapshot()
|
||||
if snapshot.indexOfSection(.accounts) == nil {
|
||||
snapshot.appendSections([.accounts])
|
||||
}
|
||||
let existing = snapshot.itemIdentifiers(inSection: .accounts)
|
||||
snapshot.appendItems(ids.filter { !existing.contains($0) })
|
||||
dataSource.apply(snapshot, animatingDifferences: true)
|
||||
|
||||
// if there aren't any results for the current query, try to load more
|
||||
if ids.isEmpty {
|
||||
Task {
|
||||
await load()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func filterAccounts(ids: [String], with query: String) -> [String] {
|
||||
let req = AccountMO.fetchRequest()
|
||||
req.predicate = NSPredicate(format: "id in %@", ids)
|
||||
let accounts = try! mastodonController.persistentContainer.viewContext.fetch(req)
|
||||
|
||||
return accounts
|
||||
.map { (account) -> (AccountMO, Bool) in
|
||||
let displayNameMatch = FuzzyMatcher.match(pattern: query, str: account.displayNameWithoutCustomEmoji)
|
||||
let usernameMatch = FuzzyMatcher.match(pattern: query, str: account.acct)
|
||||
return (account, displayNameMatch.matched || usernameMatch.matched)
|
||||
}
|
||||
.filter(\.1)
|
||||
.map(\.0.id)
|
||||
}
|
||||
|
||||
func updateQuery(_ query: String) {
|
||||
self.query = query
|
||||
updateDataSourceForQueryChanged()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension EditListSearchFollowingViewController {
|
||||
enum Section {
|
||||
case accounts
|
||||
}
|
||||
}
|
||||
|
||||
extension EditListSearchFollowingViewController: TuskerNavigationDelegate {
|
||||
var apiController: MastodonController! { mastodonController }
|
||||
}
|
||||
|
||||
extension EditListSearchFollowingViewController: MenuActionProvider {
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// EditListSearchResultsContainerViewController.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 11/11/22.
|
||||
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
class EditListSearchResultsContainerViewController: UIViewController {
|
||||
|
||||
private let mastodonController: MastodonController
|
||||
private let didSelectAccount: (String) -> Void
|
||||
|
||||
private let searchResultsController: SearchResultsViewController
|
||||
private let searchFollowingController: EditListSearchFollowingViewController
|
||||
|
||||
var mode = Mode.search {
|
||||
willSet {
|
||||
currentViewController.removeViewAndController()
|
||||
}
|
||||
didSet {
|
||||
embedChild(currentViewController)
|
||||
}
|
||||
}
|
||||
var currentViewController: UIViewController {
|
||||
switch mode {
|
||||
case .search:
|
||||
return searchResultsController
|
||||
case .following:
|
||||
return searchFollowingController
|
||||
}
|
||||
}
|
||||
|
||||
private var currentQuery: String?
|
||||
private var searchSubject = PassthroughSubject<String?, Never>()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
init(mastodonController: MastodonController, didSelectAccount: @escaping (String) -> Void) {
|
||||
self.mastodonController = mastodonController
|
||||
self.didSelectAccount = didSelectAccount
|
||||
|
||||
self.searchResultsController = SearchResultsViewController(mastodonController: mastodonController, resultTypes: [.accounts])
|
||||
self.searchFollowingController = EditListSearchFollowingViewController(mastodonController: mastodonController, didSelectAccount: didSelectAccount)
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
self.searchResultsController.delegate = self
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
embedChild(currentViewController)
|
||||
|
||||
searchSubject
|
||||
.debounce(for: .milliseconds(500), scheduler: RunLoop.main)
|
||||
.sink { [unowned self] in self.performSearch(query: $0) }
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func performSearch(query: String?) {
|
||||
guard var query = query?.trimmingCharacters(in: .whitespacesAndNewlines) else {
|
||||
return
|
||||
}
|
||||
if query.starts(with: "@") {
|
||||
query = String(query.dropFirst())
|
||||
}
|
||||
guard query != self.currentQuery else {
|
||||
return
|
||||
}
|
||||
self.currentQuery = query
|
||||
|
||||
switch mode {
|
||||
case .search:
|
||||
searchResultsController.performSearch(query: query)
|
||||
case .following:
|
||||
searchFollowingController.updateQuery(query)
|
||||
}
|
||||
}
|
||||
|
||||
enum Mode: Equatable {
|
||||
case search, following
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension EditListSearchResultsContainerViewController: UISearchResultsUpdating {
|
||||
func updateSearchResults(for searchController: UISearchController) {
|
||||
searchSubject.send(searchController.searchBar.text)
|
||||
}
|
||||
}
|
||||
|
||||
extension EditListSearchResultsContainerViewController: UISearchBarDelegate {
|
||||
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
|
||||
performSearch(query: searchBar.text)
|
||||
}
|
||||
|
||||
func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
|
||||
mode = selectedScope == 0 ? .search : .following
|
||||
performSearch(query: searchBar.text)
|
||||
}
|
||||
}
|
||||
|
||||
extension EditListSearchResultsContainerViewController: SearchResultsViewControllerDelegate {
|
||||
func selectedSearchResult(account accountID: String) {
|
||||
didSelectAccount(accountID)
|
||||
}
|
||||
}
|
|
@ -69,6 +69,7 @@ class AccountTableViewCell: UITableViewCell {
|
|||
|
||||
let accountID = self.accountID
|
||||
|
||||
avatarImageView.image = nil
|
||||
if let avatarURL = account.avatar {
|
||||
avatarRequest = ImageCache.avatars.get(avatarURL) { [weak self] (_, image) in
|
||||
guard let self = self else { return }
|
||||
|
|
Loading…
Reference in New Issue