forked from MacMagazine/app-iOS
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFeedRootViewModel.swift
More file actions
95 lines (72 loc) · 2.45 KB
/
FeedRootViewModel.swift
File metadata and controls
95 lines (72 loc) · 2.45 KB
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import Combine
import FeedLibrary
import Foundation
import StorageLibrary
import SwiftData
import WatchKit
@MainActor
final class FeedMainViewModel: ObservableObject {
// MARK: - Published
@Published private(set) var status: FeedViewModel.Status = .loading
@Published var selectedIndex: Int = 0
@Published var showActions: Bool = false
@Published var showContextMenu: Bool = false
@Published var selectedPostForDetail: SelectedPost?
@Published private(set) var isRefreshing: Bool = false
// MARK: - Private
private let feedViewModel: FeedViewModel
private var didLoadInitial: Bool = false
// MARK: - Init
init(feedViewModel: FeedViewModel) {
self.feedViewModel = feedViewModel
status = feedViewModel.status
}
// MARK: - Public API
func loadInitialIfNeeded(hasItems: Bool, modelContext: ModelContext) async {
guard !didLoadInitial else { return }
didLoadInitial = true
if hasItems {
status = .done
return
}
await refresh(modelContext: modelContext)
}
func refresh(modelContext: ModelContext) async {
guard !isRefreshing else { return }
isRefreshing = true
defer {
isRefreshing = false
}
_ = try? await feedViewModel.getWatchFeed()
status = feedViewModel.status
}
func toggleFavorite(post: FeedDB, modelContext: ModelContext) {
post.favorite.toggle()
try? modelContext.save()
showActions = true
}
// MARK: - Index / Helpers
func computeSelectedIndexByMidY(items: [FeedDB], positions: [String: CGPoint]) -> Int {
guard !items.isEmpty else { return 0 }
let screenMidY = WKInterfaceDevice.current().screenBounds.midY
var bestIndex = 0
var bestDistance = CGFloat.greatestFiniteMagnitude
for (index, item) in items.enumerated() {
guard let point = positions[item.postId] else { continue }
let distance = abs(point.y - screenMidY)
if distance < bestDistance {
bestDistance = distance
bestIndex = index
}
}
return bestIndex
}
func clampIndex(_ index: Int, quantity: Int) -> Int {
guard quantity > 0 else { return 0 }
return min(max(index, 0), quantity - 1)
}
@MainActor
func setStatusForPreview(_ status: FeedViewModel.Status) {
self.status = status
}
}