IceCubesApp/Packages/Explore/Sources/Explore/ExploreView.swift
2023-02-24 13:25:21 +01:00

242 lines
8.2 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}
}
}