Fix Home card style selection not persisting

The Home settings screen copies settings into local @State on appear and
saves on disappear. Pushing the card style page fired onDisappear (saving
pre-edit values), and popping back re-ran loadSettings, clobbering the
style just edited through the bindings — so the selection reverted.

Load settings only once per presentation, and persist style, palette, and
custom colors immediately from the style page via an onSave callback. The
owning view sits covered in the navigation stack where its own onChange
never fires, and swipe-dismissing the settings sheet from the style page
skips its lifecycle entirely, so saving must happen from the visible child.
This commit is contained in:
Arkadiusz Fal
2026-06-01 21:22:45 +02:00
parent eea13a6290
commit 0d56dd02b7
2 changed files with 24 additions and 2 deletions

View File

@@ -31,6 +31,11 @@ struct HomeSettingsView: View {
// Edit mode for delete functionality
@State private var isEditMode = false
// Load settings only once per presentation: pushing a child page (e.g. the
// card style view) fires onDisappear/onAppear on this view, and re-running
// loadSettings on pop-back would clobber edits made through bindings.
@State private var hasLoadedSettings = false
#if os(macOS)
// macOS: drive the style page programmatically. A List-embedded NavigationLink
// gets stuck in the selected (blue) state after popping back and can't be
@@ -59,7 +64,8 @@ struct HomeSettingsView: View {
HomeShortcutStyleView(
style: $shortcutCardStyle,
palette: $shortcutColorfulPalette,
customColors: $shortcutCustomPaletteColors
customColors: $shortcutCustomPaletteColors,
onSave: saveSettingsIfLoaded
)
}
#endif
@@ -70,6 +76,8 @@ struct HomeSettingsView: View {
.navigationBarTitleDisplayMode(.inline)
#endif
.onAppear {
guard !hasLoadedSettings else { return }
hasLoadedSettings = true
loadSettings()
}
.onDisappear {
@@ -120,7 +128,8 @@ struct HomeSettingsView: View {
HomeShortcutStyleView(
style: $shortcutCardStyle,
palette: $shortcutColorfulPalette,
customColors: $shortcutCustomPaletteColors
customColors: $shortcutCustomPaletteColors,
onSave: saveSettingsIfLoaded
)
}
#endif
@@ -340,6 +349,11 @@ struct HomeSettingsView: View {
availableSectionsByMediaSource = settings.allAvailableMediaSourceSections(sources: sources)
}
private func saveSettingsIfLoaded() {
guard hasLoadedSettings else { return }
saveSettings()
}
private func saveSettings() {
guard let settings = settingsManager else { return }
settings.homeShortcutLayout = shortcutLayout

View File

@@ -14,6 +14,11 @@ struct HomeShortcutStyleView: View {
@Binding var palette: HomeShortcutColorfulPalette
@Binding var customColors: [String]
/// Called after any value changes so the owner persists immediately. The
/// owner sits covered in the navigation stack where its own onChange never
/// fires, and swipe-dismissing the sheet from here skips its lifecycle.
var onSave: (() -> Void)? = nil
/// Editing mode for the custom palette.
private enum CustomEditMode: String, CaseIterable {
case list
@@ -87,6 +92,9 @@ struct HomeShortcutStyleView: View {
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.onChange(of: style) { onSave?() }
.onChange(of: palette) { onSave?() }
.onChange(of: customColors) { onSave?() }
}
// MARK: - Palette