Compare commits
1 Commits
fix/issue-
...
fix/issue-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1c824f288 |
@@ -19,11 +19,6 @@ struct IdentificationView: View {
|
|||||||
/// Tracks whether we've announced results to avoid duplicate announcements
|
/// Tracks whether we've announced results to avoid duplicate announcements
|
||||||
@State private var hasAnnouncedResults = false
|
@State private var hasAnnouncedResults = false
|
||||||
|
|
||||||
/// Local state to reliably drive the save button's enabled/disabled state.
|
|
||||||
/// Works around an @Observable + @State tracking issue where computed
|
|
||||||
/// properties in view modifiers don't always trigger re-renders.
|
|
||||||
@State private var saveEnabled = false
|
|
||||||
|
|
||||||
// MARK: - Scaled Metrics for Dynamic Type
|
// MARK: - Scaled Metrics for Dynamic Type
|
||||||
|
|
||||||
@ScaledMetric(relativeTo: .body) private var closeIconSize: CGFloat = 16
|
@ScaledMetric(relativeTo: .body) private var closeIconSize: CGFloat = 16
|
||||||
@@ -81,10 +76,8 @@ struct IdentificationView: View {
|
|||||||
announceStateChange(from: oldValue, to: newValue)
|
announceStateChange(from: oldValue, to: newValue)
|
||||||
}
|
}
|
||||||
.onChange(of: viewModel.selectedPrediction?.id) { _, _ in
|
.onChange(of: viewModel.selectedPrediction?.id) { _, _ in
|
||||||
saveEnabled = viewModel.canSaveToCollection
|
// Force view update when selection changes
|
||||||
}
|
// This ensures SwiftUI tracks @Observable property changes correctly
|
||||||
.onChange(of: viewModel.saveState) { _, _ in
|
|
||||||
saveEnabled = viewModel.canSaveToCollection
|
|
||||||
}
|
}
|
||||||
.accessibilityIdentifier(AccessibilityIdentifiers.Identification.identificationView)
|
.accessibilityIdentifier(AccessibilityIdentifiers.Identification.identificationView)
|
||||||
.alert("Plant Saved!", isPresented: .init(
|
.alert("Plant Saved!", isPresented: .init(
|
||||||
@@ -413,12 +406,12 @@ struct IdentificationView: View {
|
|||||||
.padding(.vertical, 14)
|
.padding(.vertical, 14)
|
||||||
.background(
|
.background(
|
||||||
RoundedRectangle(cornerRadius: 12)
|
RoundedRectangle(cornerRadius: 12)
|
||||||
.fill(saveEnabled ? Color.accentColor : Color.gray)
|
.fill(viewModel.canSaveToCollection ? Color.accentColor : Color.gray)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.disabled(!saveEnabled)
|
.disabled(!viewModel.canSaveToCollection)
|
||||||
.accessibilityLabel(viewModel.saveState == .saving ? "Saving plant" : "Save to Collection")
|
.accessibilityLabel(viewModel.saveState == .saving ? "Saving plant" : "Save to Collection")
|
||||||
.accessibilityHint(saveEnabled ? "Saves the selected plant to your collection" : "Select a plant first")
|
.accessibilityHint(viewModel.canSaveToCollection ? "Saves the selected plant to your collection" : "Select a plant first")
|
||||||
.accessibilityIdentifier(AccessibilityIdentifiers.Identification.saveToCollectionButton)
|
.accessibilityIdentifier(AccessibilityIdentifiers.Identification.saveToCollectionButton)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 20)
|
.padding(.horizontal, 20)
|
||||||
|
|||||||
@@ -116,6 +116,14 @@ struct PlantDetailView: View {
|
|||||||
.task {
|
.task {
|
||||||
await viewModel.loadCareInfo()
|
await viewModel.loadCareInfo()
|
||||||
}
|
}
|
||||||
|
.onAppear {
|
||||||
|
// Reload schedule from Core Data every time the view appears.
|
||||||
|
// .task only runs on first appearance; this ensures task completion
|
||||||
|
// states are always current when navigating back to this view.
|
||||||
|
Task {
|
||||||
|
await viewModel.refreshSchedule()
|
||||||
|
}
|
||||||
|
}
|
||||||
.refreshable {
|
.refreshable {
|
||||||
await viewModel.refresh()
|
await viewModel.refresh()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,12 @@ final class PlantDetailViewModel {
|
|||||||
isLoading = false
|
isLoading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reloads the care schedule from the repository.
|
||||||
|
/// Call on view reappearance to pick up persisted task completions.
|
||||||
|
func refreshSchedule() async {
|
||||||
|
await loadExistingSchedule()
|
||||||
|
}
|
||||||
|
|
||||||
/// Loads an existing care schedule from the repository
|
/// Loads an existing care schedule from the repository
|
||||||
private func loadExistingSchedule() async {
|
private func loadExistingSchedule() async {
|
||||||
do {
|
do {
|
||||||
|
|||||||
Reference in New Issue
Block a user