From 70a7f38d1fba63969c732ca0a0152ed8179a8854 Mon Sep 17 00:00:00 2001 From: Daniel Eden Date: Thu, 21 Sep 2023 15:19:15 +0100 Subject: [PATCH] Fix watchOS time machine view and watchOS 9 crash --- Localizable.xcstrings | 29 ++++++++++++- .../AccentColor.colorset/Contents.json | 7 ---- Solstice/Detail View/DetailView.swift | 41 +++++++++++-------- Solstice/Extensions/Solar++.swift | 2 - Solstice/SolsticeApp.swift | 6 +-- Solstice/TimeMachineView.swift | 37 +++++++++++++---- watchOS/ContentView.swift | 35 ++++++++-------- 7 files changed, 99 insertions(+), 58 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 6e1045271..d3105d3a4 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -22,7 +22,14 @@ } }, "%@" : { - + "localizations" : { + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@" + } + } + } }, "%@ (%@)" : { "localizations" : { @@ -141,7 +148,14 @@ } }, "%@ Location required" : { - + "localizations" : { + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Posizione richiesta" + } + } + } }, "%@ of daylight" : { "localizations" : { @@ -231,6 +245,17 @@ } } }, + "%lld" : { + "comment" : "Number of days in the past or future for Time Travel on Apple Watch", + "localizations" : { + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" + } + } + } + }, "%lld days in the %@" : { "localizations" : { "en" : { diff --git a/Solstice/Assets.xcassets/AccentColor.colorset/Contents.json b/Solstice/Assets.xcassets/AccentColor.colorset/Contents.json index 4ddf489f6..78c270fa9 100644 --- a/Solstice/Assets.xcassets/AccentColor.colorset/Contents.json +++ b/Solstice/Assets.xcassets/AccentColor.colorset/Contents.json @@ -11,13 +11,6 @@ } }, "idiom" : "universal" - }, - { - "color" : { - "platform" : "watchos", - "reference" : "systemYellowColor" - }, - "idiom" : "watch" } ], "info" : { diff --git a/Solstice/Detail View/DetailView.swift b/Solstice/Detail View/DetailView.swift index 17ce46507..bfba10f63 100644 --- a/Solstice/Detail View/DetailView.swift +++ b/Solstice/Detail View/DetailView.swift @@ -115,28 +115,33 @@ struct DetailView: View { Solar(for: timeMachine.date, coordinate: location.coordinate) } + var toolbarItemPlacement: ToolbarItemPlacement { + if #available(watchOS 10, *) { + return .topBarTrailing + } else { + return .automatic + } + } + @ToolbarContentBuilder var toolbarItems: some ToolbarContent { #if os(watchOS) - if #available(watchOS 10, *) { - ToolbarItem(id: "timeMachineToggle", placement: .topBarTrailing) { - Button { - timeMachine.controlsVisible.toggle() - } label: { - Label("Time Travel", systemImage: "clock.arrow.2.circlepath") - .symbolEffect(.pulse, isActive: timeMachine.isOn) + ToolbarItem(id: "timeMachineToggle", placement: toolbarItemPlacement) { + Button { + timeMachine.controlsVisible.toggle() + } label: { + Label("Time Travel", systemImage: "clock.arrow.2.circlepath") + } + .sheet(isPresented: $timeMachine.controlsVisible) { + Form { + TimeMachineView() } - .sheet(isPresented: $timeMachine.controlsVisible) { - Form { - TimeMachineView() - } - .toolbar { - ToolbarItem(placement: .cancellationAction) { - Button { - timeMachine.controlsVisible.toggle() - } label: { - Label("Close", systemImage: "xmark") - } + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button { + timeMachine.controlsVisible.toggle() + } label: { + Label("Close", systemImage: "xmark") } } } diff --git a/Solstice/Extensions/Solar++.swift b/Solstice/Extensions/Solar++.swift index b348b9dd4..39f960a64 100644 --- a/Solstice/Extensions/Solar++.swift +++ b/Solstice/Extensions/Solar++.swift @@ -60,7 +60,6 @@ extension Solar { let comparator = date.isToday ? yesterday : Solar(coordinate: self.coordinate)! let difference = daylightDuration - comparator.daylightDuration let differenceString = Duration.seconds(abs(difference)).formatted(.units(maximumUnitCount: 2)) - var string = (daylightDuration - comparator.daylightDuration).localizedString let moreOrLess = difference >= 0 ? NSLocalizedString("more", comment: "More daylight middle of sentence") : NSLocalizedString("less", comment: "Less daylight middle of sentence") @@ -74,7 +73,6 @@ extension Solar { } let comparatorDate = comparator.date - let comparatorDateString = formatter.string(from: comparatorDate) return LocalizedStringKey("\(differenceString) \(moreOrLess) daylight \(baseDateString) compared to \(formatter.string(from: comparatorDate))") } diff --git a/Solstice/SolsticeApp.swift b/Solstice/SolsticeApp.swift index 60336da3c..23813ee9d 100644 --- a/Solstice/SolsticeApp.swift +++ b/Solstice/SolsticeApp.swift @@ -6,13 +6,13 @@ // import SwiftUI -import UserNotifications import StoreKit @main struct SolsticeApp: App { @Environment(\.scenePhase) var phase @StateObject private var currentLocation = CurrentLocation() + @StateObject private var timeMachine = TimeMachine() private let persistenceController = PersistenceController.shared @@ -20,16 +20,14 @@ struct SolsticeApp: App { WindowGroup { ContentView() .environmentObject(currentLocation) + .environmentObject(timeMachine) .environment(\.managedObjectContext, persistenceController.container.viewContext) .task { for await result in Transaction.updates { switch result { case .verified(let transaction): print("Transaction verified in listener") - await transaction.finish() - - // Update the user's purchases... case .unverified: print("Transaction unverified") } diff --git a/Solstice/TimeMachineView.swift b/Solstice/TimeMachineView.swift index a1b7a73c6..1de123347 100644 --- a/Solstice/TimeMachineView.swift +++ b/Solstice/TimeMachineView.swift @@ -34,14 +34,11 @@ struct TimeMachineView: View { @ViewBuilder var controls: some View { - if #available(watchOS 10, iOS 15, macOS 13, *) { - DatePicker(selection: $timeMachine.targetDate, displayedComponents: .date) { - Text("\(Image(systemName: "clock.arrow.2.circlepath")) Time Travel") - } - #if os(watchOS) - .datePickerStyle(.wheel) - #endif + #if !os(watchOS) + DatePicker(selection: $timeMachine.targetDate, displayedComponents: .date) { + Text("\(Image(systemName: "clock.arrow.2.circlepath")) Time Travel") } + #endif #if os(iOS) || os(macOS) Slider(value: timeMachine.offset, @@ -55,6 +52,32 @@ struct TimeMachineView: View { .tint(Color(UIColor.systemFill)) #endif .foregroundStyle(.secondary) + #elseif os(watchOS) + Stepper( + value: timeMachine.offset, + in: -365...365, + step: 1 + ) { + Text("\(Int(timeMachine.offset.wrappedValue))", comment: "Number of days in the past or future for Time Travel on Apple Watch") + .font(.largeTitle) + } + .foregroundStyle(.secondary) + + VStack(alignment: .leading) { + Text(timeMachine.date, style: .date) + Text("\(Int(abs(timeMachine.offset.wrappedValue))) days in the \(timeMachine.offset.wrappedValue >= 0 ? Text("future") : Text("past"))") + .font(.footnote) + .foregroundStyle(.secondary) + } + + Button { + withAnimation { + timeMachine.offset.wrappedValue = 0 + } + } label: { + Label("Reset", systemImage: "gobackward") + } + .disabled(timeMachine.offset.wrappedValue == 0) #endif } } diff --git a/watchOS/ContentView.swift b/watchOS/ContentView.swift index cf53bac15..911dd81d5 100644 --- a/watchOS/ContentView.swift +++ b/watchOS/ContentView.swift @@ -10,7 +10,7 @@ import SwiftUI struct ContentView: View { @Environment(\.scenePhase) var scenePhase @EnvironmentObject var currentLocation: CurrentLocation - @StateObject var timeMachine = TimeMachine() + @EnvironmentObject var timeMachine: TimeMachine private let timer = Timer.publish(every: 60, on: RunLoop.main, in: .common).autoconnect() @@ -27,27 +27,26 @@ struct ContentView: View { fatalError() } } - .environmentObject(timeMachine) - .navigationTitle(Text(verbatim: "Solstice")) - .onChange(of: scenePhase) { _ in - timeMachine.referenceDate = Date() - if currentLocation.isAuthorized, - scenePhase != .background { - currentLocation.requestLocation() - } + .navigationTitle(Text(verbatim: "Solstice")) + .onChange(of: scenePhase) { _ in + timeMachine.referenceDate = Date() + if currentLocation.isAuthorized, + scenePhase != .background { + currentLocation.requestLocation() } - .onReceive(timer) { _ in - timeMachine.referenceDate = Date() - if currentLocation.isAuthorized { - currentLocation.requestLocation() - } + } + .onReceive(timer) { _ in + timeMachine.referenceDate = Date() + if currentLocation.isAuthorized { + currentLocation.requestLocation() } + } } } -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } +#Preview { + ContentView() + .environmentObject(TimeMachine.preview) + .environmentObject(CurrentLocation()) }