Files
andros 78ba61034f Fix theme colors across all screens; fix Discover title on iOS 26
- Remove .toolbarBackground(.visible) from all NavigationStack views:
  this modifier suppresses large title rendering in iOS 26.
- Discover: switch to always-present List + overlay pattern so SwiftUI
  never loses the scroll context during loading transitions.
- Discover, Notifications, Groups: use .inline title mode; the tab bar
  already identifies these screens, large titles are redundant.
- RootView: add .toolbarColorScheme propagation for nav bar foreground.
- Settings sheet: apply theme background and toolbar color to the Form.
2026-05-24 21:10:04 +02:00

115 lines
4.3 KiB
Swift

import SwiftUI
import OrgSocialKit
struct DiscoverView: View {
@State private var viewModel = DiscoverViewModel()
@Environment(\.appTheme) private var theme
var body: some View {
NavigationStack {
List(viewModel.users) { user in
DiscoverUserRow(user: user, viewModel: viewModel)
.listRowBackground(theme.background)
}
.listStyle(.plain)
.scrollContentBackground(.hidden)
.background(theme.background)
.overlay {
if viewModel.isLoading && viewModel.users.isEmpty {
VStack(spacing: 16) {
ProgressView()
Text("Loading profiles from relay...")
.font(.subheadline)
.foregroundStyle(.secondary)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(theme.background)
} else if let error = viewModel.errorMessage, viewModel.users.isEmpty {
ContentUnavailableView {
Label("Discover unavailable", systemImage: "person.slash")
} description: {
Text(error)
} actions: {
Button("Retry") { Task { await viewModel.load() } }
.buttonStyle(.bordered)
}
.background(theme.background)
} else if viewModel.users.isEmpty {
ContentUnavailableView(
"No profiles found",
systemImage: "person.3",
description: Text("No other users registered on this relay.")
)
.background(theme.background)
}
}
.navigationTitle("Discover")
.navigationBarTitleDisplayMode(.inline)
.task { await viewModel.load() }
.toolbarBackground(theme.secondaryBackground, for: .navigationBar)
.navigationDestination(for: URL.self) { ProfileView(feedURL: $0) }
}
}
}
private struct DiscoverUserRow: View {
let user: DiscoverViewModel.DiscoverUser
var viewModel: DiscoverViewModel
@State private var isToggling = false
var body: some View {
HStack(spacing: 12) {
NavigationLink(value: user.feedURL) {
HStack(spacing: 12) {
AvatarView(url: user.avatar, nick: user.nick, size: 44)
VStack(alignment: .leading, spacing: 3) {
if let nick = user.nick {
Text("@\(nick)")
.font(.subheadline.weight(.semibold))
}
if let desc = user.description {
Text(desc)
.font(.caption)
.foregroundStyle(.secondary)
.lineLimit(2)
} else {
Text(user.feedURL.host ?? user.feedURL.absoluteString)
.font(.caption)
.foregroundStyle(.secondary)
.lineLimit(1)
}
}
}
}
Spacer()
if isToggling {
ProgressView()
.frame(width: 72)
} else {
Button {
isToggling = true
Task {
if user.isFollowing {
await viewModel.unfollow(user: user)
} else {
await viewModel.follow(user: user)
}
isToggling = false
}
} label: {
Text(user.isFollowing ? "Unfollow" : "Follow")
.font(.subheadline)
.fontWeight(user.isFollowing ? .regular : .semibold)
.frame(width: 72)
}
.buttonStyle(.bordered)
.tint(user.isFollowing ? .secondary : .accentColor)
}
}
.padding(.vertical, 4)
}
}