Sorry I am very new to SwiftUI and I do not understand how this second view is created, maybe of NavigationView.
I thought maybe only the Picker code had some importance in my problem.
Here is the full code
import SwiftUI
import HealthKit
extension String {
func index(from: Int) -> Index {
return self.index(startIndex, offsetBy: from)
}
func substring(from: Int) -> String {
let fromIndex = index(from: from)
return String(self[fromIndex...])
}
func substring(to: Int) -> String {
let toIndex = index(from: to)
return String(self[..<toIndex])
}
func substring(with r: Range<Int>) -> String {
let startIndex = index(from: r.lowerBound)
let endIndex = index(from: r.upperBound)
return String(self[startIndex..<endIndex])
}
}
struct ProgressBar: View {
@ObservedObject var wds = WorkoutDataStore()
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .leading) {
Rectangle().frame(width: geometry.size.width , height: geometry.size.height)
.opacity(0.3)
.foregroundColor(Color(UIColor.systemTeal))
Rectangle().frame(width: min(CGFloat(self.wds.progress)*geometry.size.width, geometry.size.width), height: geometry.size.height)
.foregroundColor(Color(UIColor.systemBlue))
.animation(.linear)
}.cornerRadius(45.0)
}
}
}
struct ContentView: View {
@ObservedObject var wds = WorkoutDataStore()
@State var selectedWorkout = 0
@State var lastSelection = 0
lazy var dateFormatter:DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm"
formatter.timeZone = TimeZone.current
return formatter
}()
let aspect: CGSize = CGSize(width: 234, height: 150)
var body: some View {
NavigationView {
ZStack {
Form {
Section(header: Text("\(self.wds.count) Workouts to choose from")){
Picker(selection: $selectedWorkout, label: Text("Workout")) {
ForEach(wds.workoutList, id: \.id) { workout in
HStack {
Image(uiImage: UIImage(named: "\(workout.type.description)")!)
.resizable()
.aspectRatio(self.aspect, contentMode: .fill)
.frame(width: 30, height: 30, alignment: .center)
Text("\(workout.type.description) (\(workout.distance)km) du \(workout.date.substring(to: 16))")
}
}
}
ProgressBar(wds: wds).frame(height: 20)
Button(action: {
self.sendWorkout(selected: self.selectedWorkout)
}) {
HStack {
Image(systemName: self.wds.syncError ? "exclamationmark.icloud.fill" : ( self.wds.synching ? "ellipses.bubble" : (self.wds.syncCompleted && (self.lastSelection == self.selectedWorkout) ? "hand.thumbsup" : "icloud.and.arrow.up")))
.font(.title)
Text(self.wds.syncError ? "Error" : ( self.wds.synching ? "Processing" : (self.wds.syncCompleted && (self.lastSelection == self.selectedWorkout) ? "Done" : "Sync")))
.fontWeight(.semibold)
.font(.title)
}
.frame(minWidth: 0, maxWidth: .infinity)
.padding()
.foregroundColor(.white)
.background(self.wds.syncError ? Color.red : ( self.wds.synching ? Color.yellow : (self.wds.syncCompleted && (self.lastSelection == self.selectedWorkout) ? .green : .blue)))
.cornerRadius(40)
}.disabled(self.wds.synching)
Button(action: {
self.refresh()
}) {
HStack {
Text("refresh")
.fontWeight(.semibold)
.font(.title)
}
.frame(minWidth: 0, maxWidth: .infinity)
.padding()
.foregroundColor(Color.white)
.background(Color.green)
.cornerRadius(40)
}
}
}
// The Custom Popup is on top of the screen
if self.wds.syncError {
// But it will not show unless this variable is true
ZStack {
Color.black.opacity(0.4)
.edgesIgnoringSafeArea(.vertical)
// This VStack is the popup
VStack(spacing: 20) {
Text("Popup")
.bold().padding()
.frame(maxWidth: .infinity)
.background(Color.orange)
.foregroundColor(Color.white)
Text("\(self.wds.failure)").frame(maxWidth: .infinity).background(Color.white).foregroundColor(Color.red)
Button(action: {self.wds.syncError = false})
{
Text("Close")
}.frame(minWidth: 0, maxWidth: .infinity)
.padding()
.foregroundColor(Color.white)
.background(Color.blue)
}
.frame(width: 300, height: 200)
.background(Color.white)
.cornerRadius(20).shadow(radius: 20)
}
}
}.navigationBarTitle("Settings")
}
}
func refresh()
{
self.wds.reloadWorkouts()
}
func sendWorkout(selected: Int)
{
self.lastSelection = selected
self.wds.syncWorkout(selected: selected)
}
}
struct WorkoutRow: View {
var details: WorkoutDetails
var body: some View {
Text("\(String(details.type.rawValue)) of \(details.date)")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}