1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import SwiftUI
/// Every camera the explore chips only had room for the top of: a tile each,
/// two up, under a large heading that collapses as the grid scrolls.
struct CamerasView: View {
@Environment(AuthManager.self) private var auth
@Environment(Router.self) private var router
@State private var viewModel: CamerasViewModel
let client: XRPCClient
init(client: XRPCClient, viewModel: CamerasViewModel? = nil) {
self.client = client
_viewModel = State(initialValue: viewModel ?? CamerasViewModel(client: client))
}
var body: some View {
ScrollView {
if viewModel.cameras.isEmpty {
Group {
if viewModel.isLoading {
ProgressView()
} else {
Text(viewModel.failed ? "Couldn't load cameras." : "No cameras yet.")
.font(.subheadline)
.foregroundStyle(.secondary)
}
}
.frame(maxWidth: .infinity)
.padding(.vertical, 60)
} else {
LazyVGrid(columns: [GridItem(.flexible(), spacing: 2), GridItem(.flexible(), spacing: 2)], spacing: 2) {
ForEach(viewModel.cameras) { camera in
BrowseTile(
title: camera.camera,
meta: counted(camera.photoCount, "photo", "photos"),
thumbs: camera.thumbs ?? []
) {
router.push(.camera(camera.camera))
}
}
}
.padding(.top, 8)
}
}
.navigationTitle("Cameras")
.navigationBarTitleDisplayMode(.large)
.refreshable { await viewModel.load(auth: auth.authContext()) }
.task {
guard !isPreview else { return }
await viewModel.load(auth: auth.authContext())
}
}
}