From e7864f7089504ae83d9943de7b9c8fef688fd846 Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Tue, 9 Jan 2024 13:28:51 +0100 Subject: [PATCH] Add following search fix #1846 --- .../AccountsList/AccountsListView.swift | 196 +++++++++++------- .../AccountsList/AccountsListViewModel.swift | 27 +++ 2 files changed, 144 insertions(+), 79 deletions(-) diff --git a/Packages/Account/Sources/Account/AccountsList/AccountsListView.swift b/Packages/Account/Sources/Account/AccountsList/AccountsListView.swift index 7a9dc1e0..93819ad1 100644 --- a/Packages/Account/Sources/Account/AccountsList/AccountsListView.swift +++ b/Packages/Account/Sources/Account/AccountsList/AccountsListView.swift @@ -18,85 +18,7 @@ public struct AccountsListView: View { } public var body: some View { - List { - switch viewModel.state { - case .loading: - ForEach(Account.placeholders()) { _ in - AccountsListRow(viewModel: .init(account: .placeholder(), relationShip: .placeholder())) - .redacted(reason: .placeholder) - .allowsHitTesting(false) - .shimmering() - #if !os(visionOS) - .listRowBackground(theme.primaryBackgroundColor) - #endif - } - case let .display(accounts, relationships, nextPageState): - if case .followers = viewModel.mode, - !currentAccount.followRequests.isEmpty - { - Section( - header: Text("account.follow-requests.pending-requests"), - footer: Text("account.follow-requests.instructions") - .font(.scaledFootnote) - .foregroundColor(.secondary) - .offset(y: -8) - ) { - ForEach(currentAccount.followRequests) { account in - AccountsListRow( - viewModel: .init(account: account), - isFollowRequest: true, - requestUpdated: { - Task { - await viewModel.fetch() - } - } - ) - #if !os(visionOS) - .listRowBackground(theme.primaryBackgroundColor) - #endif - } - } - } - Section { - ForEach(accounts) { account in - if let relationship = relationships.first(where: { $0.id == account.id }) { - AccountsListRow(viewModel: .init(account: account, - relationShip: relationship)) - #if !os(visionOS) - .listRowBackground(theme.primaryBackgroundColor) - #endif - } - } - } - - switch nextPageState { - case .hasNextPage: - loadingRow - #if !os(visionOS) - .listRowBackground(theme.primaryBackgroundColor) - #endif - .onAppear { - Task { - await viewModel.fetchNextPage() - } - } - - case .loadingNextPage: - loadingRow - #if !os(visionOS) - .listRowBackground(theme.primaryBackgroundColor) - #endif - case .none: - EmptyView() - } - - case let .error(error): - Text(error.localizedDescription) - #if !os(visionOS) - .listRowBackground(theme.primaryBackgroundColor) - #endif - } - } + listView #if !os(visionOS) .scrollContentBackground(.hidden) .background(theme.primaryBackgroundColor) @@ -124,6 +46,122 @@ public struct AccountsListView: View { await viewModel.fetch() } } + + @ViewBuilder + private var listView: some View { + if currentAccount.account?.id == viewModel.accountId { + searchableList + } else { + standardList + } + } + + private var searchableList: some View { + List { + listContent + } + .searchable(text: $viewModel.searchQuery, + placement: .navigationBarDrawer(displayMode: .always)) + .task(id: viewModel.searchQuery) { + if !viewModel.searchQuery.isEmpty { + await viewModel.search() + } + } + .onChange(of: viewModel.searchQuery) { _, newValue in + if newValue.isEmpty { + Task { + await viewModel.fetch() + } + } + } + } + + private var standardList: some View { + List { + listContent + } + } + + @ViewBuilder + private var listContent: some View { + switch viewModel.state { + case .loading: + ForEach(Account.placeholders()) { _ in + AccountsListRow(viewModel: .init(account: .placeholder(), relationShip: .placeholder())) + .redacted(reason: .placeholder) + .allowsHitTesting(false) + .shimmering() + #if !os(visionOS) + .listRowBackground(theme.primaryBackgroundColor) + #endif + } + case let .display(accounts, relationships, nextPageState): + if case .followers = viewModel.mode, + !currentAccount.followRequests.isEmpty + { + Section( + header: Text("account.follow-requests.pending-requests"), + footer: Text("account.follow-requests.instructions") + .font(.scaledFootnote) + .foregroundColor(.secondary) + .offset(y: -8) + ) { + ForEach(currentAccount.followRequests) { account in + AccountsListRow( + viewModel: .init(account: account), + isFollowRequest: true, + requestUpdated: { + Task { + await viewModel.fetch() + } + } + ) + #if !os(visionOS) + .listRowBackground(theme.primaryBackgroundColor) + #endif + } + } + } + Section { + ForEach(accounts) { account in + if let relationship = relationships.first(where: { $0.id == account.id }) { + AccountsListRow(viewModel: .init(account: account, + relationShip: relationship)) + #if !os(visionOS) + .listRowBackground(theme.primaryBackgroundColor) + #endif + } + } + } + + switch nextPageState { + case .hasNextPage: + loadingRow + #if !os(visionOS) + .listRowBackground(theme.primaryBackgroundColor) + #endif + .onAppear { + Task { + await viewModel.fetchNextPage() + } + } + + case .loadingNextPage: + loadingRow + #if !os(visionOS) + .listRowBackground(theme.primaryBackgroundColor) + #endif + case .none: + EmptyView() + } + + case let .error(error): + Text(error.localizedDescription) + #if !os(visionOS) + .listRowBackground(theme.primaryBackgroundColor) + #endif + } + } private var loadingRow: some View { HStack { diff --git a/Packages/Account/Sources/Account/AccountsList/AccountsListViewModel.swift b/Packages/Account/Sources/Account/AccountsList/AccountsListViewModel.swift index 1d5f2787..dd598f28 100644 --- a/Packages/Account/Sources/Account/AccountsList/AccountsListViewModel.swift +++ b/Packages/Account/Sources/Account/AccountsList/AccountsListViewModel.swift @@ -47,6 +47,9 @@ public enum AccountsListMode { var state = State.loading var totalCount: Int? + var accountId: String? + + var searchQuery: String = "" private var nextPageId: String? @@ -66,6 +69,7 @@ public enum AccountsListMode { (accounts, link) = try await client.getWithLink(endpoint: Accounts.followers(id: accountId, maxId: nil)) case let .following(accountId): + self.accountId = accountId let account: Account = try await client.get(endpoint: Accounts.accounts(id: accountId)) totalCount = account.followingCount (accounts, link) = try await client.getWithLink(endpoint: Accounts.following(id: accountId, @@ -125,4 +129,27 @@ public enum AccountsListMode { print(error) } } + + func search() async { + guard let client, !searchQuery.isEmpty else { return } + do { + state = .loading + try await Task.sleep(for: .milliseconds(250)) + var results: SearchResults = try await client.get(endpoint: Search.search(query: searchQuery, + type: "accounts", + offset: nil, + following: true), + forceVersion: .v2) + let relationships: [Relationship] = + try await client.get(endpoint: Accounts.relationships(ids: results.accounts.map(\.id))) + results.relationships = relationships + withAnimation { + state = .display(accounts: results.accounts, + relationships: relationships, + nextPageState: .none) + } + } catch { + + } + } }