LiveActivitySettingsView.swift 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // LoopFollow
  2. // LiveActivitySettingsView.swift
  3. #if !targetEnvironment(macCatalyst)
  4. import SwiftUI
  5. struct LiveActivitySettingsView: View {
  6. @State private var laEnabled: Bool = Storage.shared.laEnabled.value
  7. @State private var restartConfirmed = false
  8. @State private var slots: [LiveActivitySlotOption] = LAAppGroupSettings.slots()
  9. @State private var smallWidgetSlot: LiveActivitySlotOption = LAAppGroupSettings.smallWidgetSlot()
  10. private let slotLabels = ["Top left", "Top right", "Bottom left", "Bottom right"]
  11. var body: some View {
  12. Form {
  13. Section(header: Text("Live Activity")) {
  14. Toggle("Enable Live Activity", isOn: $laEnabled)
  15. }
  16. if laEnabled {
  17. Section {
  18. Button(restartConfirmed ? "Live Activity Restarted" : "Restart Live Activity") {
  19. LiveActivityManager.shared.forceRestart()
  20. restartConfirmed = true
  21. DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
  22. restartConfirmed = false
  23. }
  24. }
  25. .disabled(restartConfirmed)
  26. }
  27. }
  28. Section(header: Text("Grid Slots - Live Activity")) {
  29. ForEach(0 ..< 4, id: \.self) { index in
  30. Picker(slotLabels[index], selection: Binding(
  31. get: { slots[index] },
  32. set: { selectSlot($0, at: index) }
  33. )) {
  34. ForEach(LiveActivitySlotOption.allCases, id: \.self) { option in
  35. Text(option.displayName).tag(option)
  36. }
  37. }
  38. }
  39. }
  40. Section(header: Text("Grid Slot - CarPlay / Watch")) {
  41. Picker("Right slot", selection: Binding(
  42. get: { smallWidgetSlot },
  43. set: { newValue in
  44. smallWidgetSlot = newValue
  45. LAAppGroupSettings.setSmallWidgetSlot(newValue)
  46. LiveActivityManager.shared.refreshFromCurrentState(reason: "small widget slot changed")
  47. }
  48. )) {
  49. ForEach(LiveActivitySlotOption.allCases, id: \.self) { option in
  50. Text(option.displayName).tag(option)
  51. }
  52. }
  53. }
  54. }
  55. .onReceive(Storage.shared.laEnabled.$value) { newValue in
  56. if newValue != laEnabled { laEnabled = newValue }
  57. }
  58. .onChange(of: laEnabled) { newValue in
  59. Storage.shared.laEnabled.value = newValue
  60. if newValue {
  61. LiveActivityManager.shared.forceRestart()
  62. } else {
  63. LiveActivityManager.shared.end(dismissalPolicy: .immediate)
  64. }
  65. }
  66. .preferredColorScheme(Storage.shared.appearanceMode.value.colorScheme)
  67. .navigationTitle("Live Activity")
  68. .navigationBarTitleDisplayMode(.inline)
  69. }
  70. /// Selects an option for the given slot index, enforcing uniqueness:
  71. /// if the chosen option is already in another slot, that slot is cleared to `.none`.
  72. private func selectSlot(_ option: LiveActivitySlotOption, at index: Int) {
  73. if option != .none {
  74. for i in 0 ..< slots.count where i != index && slots[i] == option {
  75. slots[i] = .none
  76. }
  77. }
  78. slots[index] = option
  79. LAAppGroupSettings.setSlots(slots)
  80. LiveActivityManager.shared.refreshFromCurrentState(reason: "slot config changed")
  81. }
  82. }
  83. #endif