|
|
|
|
@ -20,7 +20,8 @@ class BoringContext : ObservableObject { |
|
|
|
|
struct ContentView<T : AbstractTimer>: View { |
|
|
|
|
|
|
|
|
|
@StateObject var boringContext: BoringContext = BoringContext() |
|
|
|
|
|
|
|
|
|
@EnvironmentObject var conductor: Conductor |
|
|
|
|
|
|
|
|
|
@Environment(\.managedObjectContext) private var viewContext |
|
|
|
|
|
|
|
|
|
@FetchRequest( |
|
|
|
|
@ -45,22 +46,43 @@ struct ContentView<T : AbstractTimer>: View { |
|
|
|
|
GeometryReader { reader in |
|
|
|
|
let width: CGFloat = reader.size.width / 2 - 10.0 |
|
|
|
|
|
|
|
|
|
LazyVGrid( |
|
|
|
|
columns: columns, |
|
|
|
|
spacing: itemSpacing |
|
|
|
|
) { |
|
|
|
|
ZStack(alignment: .bottom) { |
|
|
|
|
|
|
|
|
|
ReorderableForEach(items: timersArray) { timer in |
|
|
|
|
ScrollView { |
|
|
|
|
|
|
|
|
|
DialView(timer: timer, frameSize: width) .environment(\.managedObjectContext, viewContext) |
|
|
|
|
.environmentObject(boringContext) |
|
|
|
|
LazyVGrid( |
|
|
|
|
columns: columns, |
|
|
|
|
spacing: itemSpacing |
|
|
|
|
) { |
|
|
|
|
|
|
|
|
|
ReorderableForEach(items: timersArray) { timer in |
|
|
|
|
|
|
|
|
|
DialView(timer: timer, frameSize: width) .environment(\.managedObjectContext, viewContext) |
|
|
|
|
.environmentObject(Conductor.maestro) |
|
|
|
|
.environmentObject(boringContext) |
|
|
|
|
|
|
|
|
|
} moveAction: { from, to in |
|
|
|
|
self._reorder(from: from, to: to) |
|
|
|
|
} moveAction: { from, to in |
|
|
|
|
self._reorder(from: from, to: to) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if Conductor.maestro.soundPlayer != nil { |
|
|
|
|
Button { |
|
|
|
|
Conductor.maestro.stopSoundIfPossible() |
|
|
|
|
} label: { |
|
|
|
|
Text("STOP") |
|
|
|
|
.frame(minWidth: 0.0, maxWidth: .infinity, minHeight: 75.0, maxHeight: 75.0) |
|
|
|
|
.foregroundColor(.white) |
|
|
|
|
.background(.red) |
|
|
|
|
.cornerRadius(16.0) |
|
|
|
|
}.padding() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}.padding(itemSpacing) |
|
|
|
|
|
|
|
|
|
}.padding(.horizontal, itemSpacing) |
|
|
|
|
.navigationTitle("\(String(describing: T.self))") |
|
|
|
|
.alert(boringContext.error?.localizedDescription ?? "missing error", isPresented: $boringContext.showDefaultAlert) { |
|
|
|
|
Button("OK", role: .cancel) { } |
|
|
|
|
@ -96,7 +118,6 @@ struct ContentView<T : AbstractTimer>: View { |
|
|
|
|
self._askPermissions() |
|
|
|
|
} |
|
|
|
|
.onOpenURL { url in |
|
|
|
|
print("open URL = \(url)") |
|
|
|
|
self._performActionIfPossible(url: url) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -139,22 +160,29 @@ struct ContentView<T : AbstractTimer>: View { |
|
|
|
|
|
|
|
|
|
fileprivate func _performActionIfPossible(url: URL) { |
|
|
|
|
|
|
|
|
|
print("_performActionIfPossible") |
|
|
|
|
|
|
|
|
|
let urlString = url.absoluteString |
|
|
|
|
if let timer = viewContext.object(stringId: urlString) as? AbstractTimer { |
|
|
|
|
|
|
|
|
|
TimerRouter.performAction(timer: timer) { result in |
|
|
|
|
switch result { |
|
|
|
|
case .success: |
|
|
|
|
break |
|
|
|
|
case .failure(let failure): |
|
|
|
|
switch failure { |
|
|
|
|
case TimerError.notificationAuthorizationMissing: |
|
|
|
|
self.boringContext.showPermissionAlert = true |
|
|
|
|
default: |
|
|
|
|
self.boringContext.error = failure |
|
|
|
|
self.boringContext.showDefaultAlert = true |
|
|
|
|
if timer is T { |
|
|
|
|
print("performAction") |
|
|
|
|
|
|
|
|
|
TimerRouter.performAction(timer: timer) { result in |
|
|
|
|
switch result { |
|
|
|
|
case .success: |
|
|
|
|
break |
|
|
|
|
case .failure(let failure): |
|
|
|
|
switch failure { |
|
|
|
|
case TimerError.notificationAuthorizationMissing: |
|
|
|
|
self.boringContext.showPermissionAlert = true |
|
|
|
|
default: |
|
|
|
|
self.boringContext.error = failure |
|
|
|
|
self.boringContext.showDefaultAlert = true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// print("Start countdown: \(countdown.name ?? ""), \(countdown.duration)") |
|
|
|
|
@ -222,6 +250,7 @@ fileprivate extension Countdown { |
|
|
|
|
|
|
|
|
|
struct ContentView_Previews: PreviewProvider { |
|
|
|
|
static var previews: some View { |
|
|
|
|
ContentView<Countdown>().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext) |
|
|
|
|
ContentView<Countdown>().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext) .environmentObject(Conductor.maestro) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|