crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

TipsArchive.swift (2368B)


      1 import SwiftUI
      2 
      3 /// Read-only list of every tip, reached from `Settings → Tips`. Each tip is
      4 /// rendered with the same `AnnouncementBanner` chrome it gets on the Game List,
      5 /// stacked in a plain scroll view so the banners float on the background rather
      6 /// than nesting inside grouped `Form` rows. The archive shows every tip
      7 /// regardless of whether it has been dismissed on the Game List, and offers a
      8 /// way back in if the user previously chose "Never show me tips".
      9 struct TipsArchive: View {
     10     @Environment(TipStore.self) private var tips
     11     @Environment(AnnouncementCenter.self) private var announcements
     12 
     13     var body: some View {
     14         ScrollView {
     15             LazyVStack(spacing: 12) {
     16                 Toggle("Show Tips", isOn: Binding(
     17                     get: { !tips.isDisabled },
     18                     set: { tips.isDisabled = !$0 }
     19                 ))
     20                 .padding(.horizontal, 16)
     21                 .padding(.vertical, 11)
     22                 // The inset-grouped "section" fill, so the toggle reads like a
     23                 // Settings row rather than floating on the bare background.
     24                 .background(
     25                     Color(.secondarySystemGroupedBackground),
     26                     in: RoundedRectangle(cornerRadius: 10, style: .continuous)
     27                 )
     28                 .padding(.bottom, 4)
     29 
     30                 ForEach(tips.visibleTips) { tip in
     31                     AnnouncementBanner(
     32                         announcement: tip.archiveAnnouncement(),
     33                         showsIcon: false,
     34                         onDismiss: nil
     35                     )
     36                 }
     37             }
     38             .padding()
     39         }
     40         .background(Color(.systemGroupedBackground))
     41         .navigationTitle("Tips")
     42         .navigationBarTitleDisplayMode(.inline)
     43         .onDisappear {
     44             // Leaving the archive with tips turned off clears any tip still
     45             // showing on the Game List. This only un-displays it — the tip
     46             // isn't marked individually dismissed, so re-enabling later
     47             // surfaces it again on the next cold launch. Toggling off then back
     48             // on before leaving leaves the banner untouched.
     49             guard tips.isDisabled, let tip = tips.firstUndismissedTip() else { return }
     50             announcements.dismiss(id: Tip.announcementID(for: tip.id))
     51         }
     52     }
     53 }