mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-06-18 05:00:35 +00:00
242 lines
8.2 KiB
Swift
242 lines
8.2 KiB
Swift
import Account
|
||
import DesignSystem
|
||
import Env
|
||
import Models
|
||
import Network
|
||
import Shimmer
|
||
import Status
|
||
import SwiftUI
|
||
|
||
public struct ExploreView: View {
|
||
@EnvironmentObject private var theme: Theme
|
||
@EnvironmentObject private var client: Client
|
||
@EnvironmentObject private var routerPath: RouterPath
|
||
|
||
@StateObject private var viewModel = ExploreViewModel()
|
||
|
||
public init() {}
|
||
|
||
public var body: some View {
|
||
List {
|
||
if !viewModel.isLoaded {
|
||
loadingView
|
||
} else if !viewModel.searchQuery.isEmpty {
|
||
if viewModel.isSearching {
|
||
HStack {
|
||
Spacer()
|
||
ProgressView()
|
||
Spacer()
|
||
}
|
||
.listRowBackground(theme.secondaryBackgroundColor)
|
||
.listRowSeparator(.hidden)
|
||
.id(UUID())
|
||
} else if let results = viewModel.results[viewModel.searchQuery] {
|
||
if results.isEmpty, !viewModel.isSearching {
|
||
EmptyView(iconName: "magnifyingglass",
|
||
title: "explore.search.empty.title",
|
||
message: "explore.search.empty.message")
|
||
.listRowBackground(theme.secondaryBackgroundColor)
|
||
.listRowSeparator(.hidden)
|
||
} else {
|
||
makeSearchResultsView(results: results)
|
||
}
|
||
}
|
||
} else if viewModel.allSectionsEmpty {
|
||
EmptyView(iconName: "magnifyingglass",
|
||
title: "explore.search.title",
|
||
message: "explore.search.message-\(client.server)")
|
||
.listRowBackground(theme.secondaryBackgroundColor)
|
||
.listRowSeparator(.hidden)
|
||
} else {
|
||
if !viewModel.trendingTags.isEmpty {
|
||
trendingTagsSection
|
||
}
|
||
if !viewModel.suggestedAccounts.isEmpty {
|
||
suggestedAccountsSection
|
||
}
|
||
if !viewModel.trendingStatuses.isEmpty {
|
||
trendingPostsSection
|
||
}
|
||
if !viewModel.trendingLinks.isEmpty {
|
||
trendingLinksSection
|
||
}
|
||
}
|
||
}
|
||
.task {
|
||
viewModel.client = client
|
||
await viewModel.fetchTrending()
|
||
}
|
||
.refreshable {
|
||
Task {
|
||
await viewModel.fetchTrending()
|
||
}
|
||
}
|
||
.listStyle(.grouped)
|
||
.scrollContentBackground(.hidden)
|
||
.background(theme.secondaryBackgroundColor)
|
||
.navigationTitle("explore.navigation-title")
|
||
.searchable(text: $viewModel.searchQuery,
|
||
prompt: Text("explore.search.prompt"))
|
||
}
|
||
|
||
private var loadingView: some View {
|
||
ForEach(Status.placeholders()) { status in
|
||
StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
|
||
.padding(.vertical, 8)
|
||
.redacted(reason: .placeholder)
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
}
|
||
}
|
||
|
||
@ViewBuilder
|
||
private func makeSearchResultsView(results: SearchResults) -> some View {
|
||
if !results.accounts.isEmpty {
|
||
Section("explore.section.users") {
|
||
ForEach(results.accounts) { account in
|
||
if let relationship = results.relationships.first(where: { $0.id == account.id }) {
|
||
AccountsListRow(viewModel: .init(account: account, relationShip: relationship))
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if !results.hashtags.isEmpty {
|
||
Section("explore.section.tags") {
|
||
ForEach(results.hashtags) { tag in
|
||
TagRowView(tag: tag)
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
.padding(.vertical, 4)
|
||
}
|
||
}
|
||
}
|
||
if !results.statuses.isEmpty {
|
||
Section("explore.section.posts") {
|
||
ForEach(results.statuses) { status in
|
||
StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
.padding(.vertical, 8)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private var suggestedAccountsSection: some View {
|
||
Section("explore.section.suggested-users") {
|
||
ForEach(viewModel.suggestedAccounts
|
||
.prefix(upTo: viewModel.suggestedAccounts.count > 3 ? 3 : viewModel.suggestedAccounts.count)) { account in
|
||
if let relationship = viewModel.suggestedAccountsRelationShips.first(where: { $0.id == account.id }) {
|
||
AccountsListRow(viewModel: .init(account: account, relationShip: relationship))
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
}
|
||
}
|
||
NavigationLink {
|
||
List {
|
||
ForEach(viewModel.suggestedAccounts) { account in
|
||
if let relationship = viewModel.suggestedAccountsRelationShips.first(where: { $0.id == account.id }) {
|
||
AccountsListRow(viewModel: .init(account: account, relationShip: relationship))
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
}
|
||
}
|
||
}
|
||
.scrollContentBackground(.hidden)
|
||
.background(theme.primaryBackgroundColor)
|
||
.listStyle(.plain)
|
||
.navigationTitle("explore.section.suggested-users")
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
} label: {
|
||
Text("see-more")
|
||
.foregroundColor(theme.tintColor)
|
||
}
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
}
|
||
}
|
||
|
||
private var trendingTagsSection: some View {
|
||
Section("explore.section.trending.tags") {
|
||
ForEach(viewModel.trendingTags
|
||
.prefix(upTo: viewModel.trendingTags.count > 5 ? 5 : viewModel.trendingTags.count)) { tag in
|
||
TagRowView(tag: tag)
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
.padding(.vertical, 4)
|
||
}
|
||
NavigationLink {
|
||
List {
|
||
ForEach(viewModel.trendingTags) { tag in
|
||
TagRowView(tag: tag)
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
.padding(.vertical, 4)
|
||
}
|
||
}
|
||
.scrollContentBackground(.hidden)
|
||
.background(theme.primaryBackgroundColor)
|
||
.listStyle(.plain)
|
||
.navigationTitle("explore.section.trending.tags")
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
} label: {
|
||
Text("see-more")
|
||
.foregroundColor(theme.tintColor)
|
||
}
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
}
|
||
}
|
||
|
||
private var trendingPostsSection: some View {
|
||
Section("explore.section.trending.posts") {
|
||
ForEach(viewModel.trendingStatuses
|
||
.prefix(upTo: viewModel.trendingStatuses.count > 3 ? 3 : viewModel.trendingStatuses.count)) { status in
|
||
StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
.padding(.vertical, 8)
|
||
}
|
||
|
||
NavigationLink {
|
||
List {
|
||
ForEach(viewModel.trendingStatuses) { status in
|
||
StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
.padding(.vertical, 8)
|
||
}
|
||
}
|
||
.scrollContentBackground(.hidden)
|
||
.background(theme.primaryBackgroundColor)
|
||
.listStyle(.plain)
|
||
.navigationTitle("explore.section.trending.posts")
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
} label: {
|
||
Text("see-more")
|
||
.foregroundColor(theme.tintColor)
|
||
}
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
}
|
||
}
|
||
|
||
private var trendingLinksSection: some View {
|
||
Section("explore.section.trending.links") {
|
||
ForEach(viewModel.trendingLinks
|
||
.prefix(upTo: viewModel.trendingLinks.count > 3 ? 3 : viewModel.trendingLinks.count)) { card in
|
||
StatusRowCardView(card: card)
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
.padding(.vertical, 8)
|
||
}
|
||
NavigationLink {
|
||
List {
|
||
ForEach(viewModel.trendingLinks) { card in
|
||
StatusRowCardView(card: card)
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
.padding(.vertical, 8)
|
||
}
|
||
}
|
||
.scrollContentBackground(.hidden)
|
||
.background(theme.primaryBackgroundColor)
|
||
.listStyle(.plain)
|
||
.navigationTitle("explore.section.trending.links")
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
} label: {
|
||
Text("see-more")
|
||
.foregroundColor(theme.tintColor)
|
||
}
|
||
.listRowBackground(theme.primaryBackgroundColor)
|
||
}
|
||
}
|
||
}
|