TelemetryStepView.swift 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // LoopFollow
  2. // TelemetryStepView.swift
  3. import SwiftUI
  4. /// In-flow telemetry consent. Mirrors `TelemetryConsentView` but records the
  5. /// decision and continues the wizard instead of dismissing a sheet.
  6. struct TelemetryStepView: View {
  7. @ObservedObject var viewModel: OnboardingViewModel
  8. @State private var showPreview = false
  9. var body: some View {
  10. VStack(spacing: 0) {
  11. VStack(alignment: .leading, spacing: 16) {
  12. Image(systemName: "chart.bar.doc.horizontal")
  13. .font(.system(size: 44, weight: .semibold))
  14. .foregroundStyle(Color.accentColor)
  15. Text("Help us help you")
  16. .font(.title2.weight(.bold))
  17. Text("You can choose to share anonymous information with the developers to help improve LoopFollow — such as app and iOS version, device type, which app you're following, and a few settings. Your health data, credentials, time zone, and logs remain on your device.")
  18. .font(.body)
  19. .foregroundColor(.secondary)
  20. .multilineTextAlignment(.leading)
  21. Button { showPreview = true } label: {
  22. Label("See exactly what's sent", systemImage: "doc.text.magnifyingglass")
  23. .font(.subheadline)
  24. }
  25. Text("You can change this any time in Settings → General → Diagnostics.")
  26. .font(.subheadline)
  27. .foregroundColor(.secondary)
  28. }
  29. .frame(maxWidth: .infinity, alignment: .leading)
  30. .padding(.horizontal)
  31. .padding(.top, 8)
  32. Spacer()
  33. VStack(spacing: 12) {
  34. Button { decide(true) } label: {
  35. Text("Yes, send anonymous stats")
  36. .font(.body.weight(.semibold))
  37. .frame(maxWidth: .infinity)
  38. .padding(.vertical, 4)
  39. }
  40. .buttonStyle(.borderedProminent)
  41. Button { decide(false) } label: {
  42. Text("No thanks")
  43. .font(.body.weight(.medium))
  44. }
  45. }
  46. .padding(.horizontal, 24)
  47. .padding(.bottom, 24)
  48. }
  49. .frame(maxWidth: .infinity, maxHeight: .infinity)
  50. .sheet(isPresented: $showPreview) {
  51. NavigationStack {
  52. TelemetryPreviewView()
  53. }
  54. }
  55. }
  56. private func decide(_ enabled: Bool) {
  57. Storage.shared.telemetryEnabled.value = enabled
  58. Storage.shared.telemetryConsentDecisionMade.value = true
  59. if enabled {
  60. // Fire the inaugural ping immediately, then start the 24h cadence.
  61. Task.detached {
  62. await TelemetryClient.shared.maybeSend()
  63. TelemetryClient.shared.scheduleRecurring()
  64. }
  65. }
  66. viewModel.advance()
  67. }
  68. }