Added toolbar to the textfields in ContentView and you can now type zero without the app crashing

This commit is contained in:
Isaac Greene 2022-06-15 23:20:42 -04:00
parent b6677c2053
commit 7aa899ca7d
6 changed files with 228 additions and 78 deletions

View file

@ -23,7 +23,7 @@
85AAA0D827FA2DD600F4B9A1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AAA0D727FA2DD600F4B9A1 /* ContentView.swift */; };
85AAA0DA27FA2DDA00F4B9A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 85AAA0D927FA2DDA00F4B9A1 /* Assets.xcassets */; };
85AAA0DD27FA2DDA00F4B9A1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 85AAA0DC27FA2DDA00F4B9A1 /* Preview Assets.xcassets */; };
85AAA0E627FA2EB100F4B9A1 /* ModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AAA0E527FA2EB100F4B9A1 /* ModalView.swift */; };
85AAA0E627FA2EB100F4B9A1 /* HelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AAA0E527FA2EB100F4B9A1 /* HelpView.swift */; };
85AAA0E827FA2F1600F4B9A1 /* ChangeLogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AAA0E727FA2F1600F4B9A1 /* ChangeLogView.swift */; };
85AAA0EB27FA2F7000F4B9A1 /* RichTextView in Frameworks */ = {isa = PBXBuildFile; productRef = 85AAA0EA27FA2F7000F4B9A1 /* RichTextView */; };
/* End PBXBuildFile section */
@ -46,7 +46,7 @@
85AAA0D727FA2DD600F4B9A1 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
85AAA0D927FA2DDA00F4B9A1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
85AAA0DC27FA2DDA00F4B9A1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
85AAA0E527FA2EB100F4B9A1 /* ModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalView.swift; sourceTree = "<group>"; };
85AAA0E527FA2EB100F4B9A1 /* HelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpView.swift; sourceTree = "<group>"; };
85AAA0E727FA2F1600F4B9A1 /* ChangeLogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeLogView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -91,7 +91,7 @@
850F80212853F7E30094580D /* SecretView.swift */,
850F8015284A815C0094580D /* KnownIssues.swift */,
85AAA0E727FA2F1600F4B9A1 /* ChangeLogView.swift */,
85AAA0E527FA2EB100F4B9A1 /* ModalView.swift */,
85AAA0E527FA2EB100F4B9A1 /* HelpView.swift */,
850F801F2853F7790094580D /* LicenseView.swift */,
85AAA0D927FA2DDA00F4B9A1 /* Assets.xcassets */,
850F8025285437500094580D /* isaac.greene.clouds.heic */,
@ -200,7 +200,7 @@
850F8016284A815C0094580D /* KnownIssues.swift in Sources */,
859298C928592F1F00D9D6CB /* Documentation.docc in Sources */,
85AAA0E827FA2F1600F4B9A1 /* ChangeLogView.swift in Sources */,
85AAA0E627FA2EB100F4B9A1 /* ModalView.swift in Sources */,
85AAA0E627FA2EB100F4B9A1 /* HelpView.swift in Sources */,
850F80202853F7790094580D /* LicenseView.swift in Sources */,
850F8018284A83400094580D /* FeaturesView.swift in Sources */,
);

View file

@ -10,6 +10,19 @@ import SwiftUI
struct June2022: View {
var body: some View {
ScrollView {
//2022-06-15
HStack {
VStack (alignment: .leading) {
Text("2022-06-15")
.font(.title2)
Text("Version Prerelease Build LVSXT10a.3\n")
.font(.footnote)
Text("\u{2022} Fixed an issue where typing zero for the distance caused the app to crash\n\u{2022} Implemented a way to navigate between text fields and redid the Done button to make it fit better")
}
Spacer()
}
.padding(30)
//2022-06-14
HStack {
VStack (alignment: .leading) {
@ -17,18 +30,19 @@ struct June2022: View {
.font(.title2)
Text("Version Prerelease Build LVSXT10a.3\n")
.font(.footnote)
Text("\u{2022} Optimized some code to allow for future development\n\u{2022} Starting on fixing an issue where putting a zero as the first number in the Distance field causes the app to crash\n\u{2022} Partially added more robust app documentation")
Text("\u{2022} Optimized some code to allow for future development\n\u{2022} Starting on fixing an issue where putting a zero as the first number in the Distance field causes the app to crash\n\u{2022} Started work on more robust app documentation")
}
Spacer()
}
.padding(30)
//2022-06-11
// LVSXT10a.2
HStack {
VStack (alignment: .leading) {
Text("2022-06-11")
.font(.title2)
Text("Version Release Candidate 2 (LVSXT10a.2)\n")
Text("Version Release Candidate 2\n")
.font(.footnote)
Text("\u{2022} Added biometrics to sign in along with option for username/password")
}
@ -37,11 +51,12 @@ struct June2022: View {
.padding(30)
//2022-06-10
// LVSXT10a
HStack {
VStack (alignment: .leading) {
Text("2022-06-10")
.font(.title2)
Text("Version Release Candidate (LVSXT10a)\n")
Text("Version Release Candidate\n")
.font(.footnote)
Text("\u{2022} Got the conversion of paces to work, so a 5:00/km pace will also show as 8:03/mi\n\u{2022} This app is now considered \"Finished\" and will transition to Version Numbers\n\u{2022} FINALLY MADE A WAY TO DISMISS THE KEYBOARD\n\t\u{2022} (as with most of the other solutions I've had to use for other problems in this app, the fix was remarkably easy)\n\u{2022} Made several small quality-of-life improvements")
}

View file

@ -12,7 +12,15 @@ import Foundation
///
/// e
struct ContentView: View {
enum Field {
case distance
case hours
case minutes
case seconds
}
@FocusState private var nameIsFocused: Bool
@FocusState private var focusedField: Field?
var SISystem = ["km","mi"]
@State var timeHours: String = ""
@State var timeMinutes: String = ""
@ -21,66 +29,82 @@ struct ContentView: View {
@State var distance: String = ""
var body: some View {
VStack {
Spacer()
NavigationView {
VStack {
TextField("Enter distance", text: $distance)
.padding()
.keyboardType(.decimalPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
}
VStack {
Text("Unit of measurement:")
Picker("System of measurement", selection: $selectedSystem, content: {
ForEach(SISystem, id: \.self, content: { unit in
Text(unit)
VStack {
TextField("Enter distance", text: $distance)
.padding()
.keyboardType(.decimalPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
.focused($focusedField, equals: .distance)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Button("Done") {
nameIsFocused = false
}
Button("Next") {
if focusedField == .distance {
focusedField = .hours
} else if focusedField == .hours {
focusedField = .minutes
} else if focusedField == .minutes {
focusedField = .seconds
} else {
focusedField = nil
}
}
}
}
}
VStack {
Text("Unit of measurement:")
Picker("System of measurement", selection: $selectedSystem, content: {
ForEach(SISystem, id: \.self, content: { unit in
Text(unit)
})
})
})
.pickerStyle(.segmented)
.frame(minWidth: 60, maxWidth: 300)
HStack {
VStack {
Text("Hours")
TextField("Enter hours", text: $timeHours)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
}
.frame(minWidth: 100)
.padding(.trailing, -15)
.padding()
VStack {
Text("Minutes")
TextField("Enter minutes", text: $timeMinutes)
.pickerStyle(.segmented)
.frame(minWidth: 60, maxWidth: 300)
HStack {
VStack {
Text("Hours")
TextField("Enter hours", text: $timeHours)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
.focused($focusedField, equals: .hours)
}
.frame(minWidth: 100)
.padding(.trailing, -15)
.padding()
VStack {
Text("Minutes")
TextField("Enter minutes", text: $timeMinutes)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
.focused($focusedField, equals: .minutes)
}
.frame(minWidth: 100)
.padding(.trailing, -15)
.padding(.leading, -15)
.padding()
VStack {
Text("Seconds")
TextField("Enter seconds", text: $timeSeconds)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
.focused($focusedField, equals: .seconds)
}
.frame(minWidth: 100)
.padding(.leading, -15)
.padding()
}
.frame(minWidth: 100)
.padding(.trailing, -15)
.padding(.leading, -15)
.padding()
VStack {
Text("Seconds")
TextField("Enter seconds", text: $timeSeconds)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
}
.frame(minWidth: 100)
.padding(.leading, -15)
.padding()
}
PaceResults(timeHours: $timeHours, timeMinutes: $timeMinutes, timeSeconds: $timeSeconds, selectedSystem: $selectedSystem, distance: $distance)
}
Spacer()
if nameIsFocused == true {
Button("Done") {
nameIsFocused = false
}
.padding()
}
}
}
}
@ -93,7 +117,7 @@ struct PaceResults: View {
@Binding var distance: String
var body: some View {
let distanceDub = Double(distance) ?? 1.0
let distanceDub:Double = Double(removeLeadingZeros(distance: &distance)) ?? 1.0
// because of some conversions I have to do,
// this constant is a double just to make things easier.
// this has to be one because the pace is calculated
@ -106,7 +130,7 @@ struct PaceResults: View {
let notSelectedSystem = (selectedSystem == "km" ? "mi" : "km")
let convertedDistanceString:String = {
let convertedDistance = distanceDub * multiplier
return (distance == "" || distance.starts(with: "0") ? "0" : String(format: "%.3f", convertedDistance))
return (distance == "" ? "0" : String(format: "%.3f", convertedDistance))
}()
let convertedSeconds:Double = (Double(timeSeconds) ?? 0) * (1.6666666666666666666666666)
@ -127,11 +151,11 @@ struct PaceResults: View {
let timeMinutesInt:Int = (Int(timeMinutes) ?? 0) + (timeSecondsToMinutes)
let timeMinutesUnderSixty:Int = timeMinutesInt % 60
let timeMinutesToHours:Int = (timeMinutesInt - timeMinutesUnderSixty) / 60
// this section tales the minutes (which it combines the
// this section takes the minutes (which it combines the
// minutes with the timeSecondsToMinutes) then finds out how
// many hours (multiples of 60) are in the minutes value
// and saves the hours in timeMinutesToHours and the remaining
// minutes in timeMinutesUnderSixty
// minutes in `timeMinutesUnderSixty`
let timeMinutesDouble:Double = Double(timeMinutes) ?? 0.0
// this line of code takes the binding $timeMinutes which
@ -141,13 +165,14 @@ struct PaceResults: View {
// if the text field contains anything other than a number
// or a single decimal, this value instantly becomes 0.0
let actualTime:Double = timeMinutesDouble + (convertedSeconds / 100) + ((Double(timeHours) ?? 0) * 60)
// adds the minutes, hours, and seconds all together to get
// a single value in terms of minutes, so that 1:08:45
// becomes 68.75 which is a nice number we can do math on
// and this number is never directly seen by the user
let pace = actualTime / distanceDub
let pace:Double = {
let actualTime:Double = timeMinutesDouble + (convertedSeconds / 100) + ((Double(timeHours) ?? 0) * 60)
// adds the minutes, hours, and seconds all together to get
// a single value in terms of minutes, so that 1:08:45
// becomes 68.75 which is a nice number we can do math on
// and this number is never directly seen by the user
return actualTime / distanceDub
}()
let paceFormatted:String = {
let paceSeconds = pace.truncatingRemainder(dividingBy: 1.0)
@ -168,12 +193,13 @@ struct PaceResults: View {
return (paceOpposite >= 60 ? "\(paceHoursOpposite):\(properTimeMSOpposite)" : "\(properTimeMSOpposite)")
}()
//let paceString:String = String(format: "%.2f", pace)
let totalHours:Double = Double(timeMinutesToHours) + (Double(timeHours) ?? 0)
// this takes the number of hours in the binding $timeHours
// and the hours calculated in the previous section
// and adds them together to get our total number of hours.
let hoursFormatted:String = String(format: "%.0f", totalHours)
let hoursFormatted:String = {
let totalHours:Double = Double(timeMinutesToHours) + (Double(timeHours) ?? 0)
// this takes the number of hours in the binding $timeHours
// and the hours calculated in the previous section
// and adds them together to get our total number of hours.
return String(format: "%.0f", totalHours)
}()
let leadingZeros:String = String(format: "%02d:%02d", timeMinutesUnderSixty, timeSecondsUnderSixty)
@ -198,6 +224,12 @@ struct PaceResults: View {
.frame(minWidth: 100)
}
}
func removeLeadingZeros(distance: inout String) -> String {
while distance.starts(with: "0") {
distance = distance.removing(prefix: "0")
}
return distance
}
}
struct ContentView_Previews: PreviewProvider {

View file

@ -63,7 +63,7 @@ struct DocsView: View {
Section(header: Text("App Information")) {
NavigationLink("Software License", destination: LicenseView())
Text("Version: Prerelease Build LVSXT10a.3")
Text("Release date: 2022-06-14")
Text("Release date: 2022-06-15")
Text("Start date: 2022-03-25")
Link("Built with SwiftUI \(Image(systemName: "swift"))", destination: URL(string: "https://developer.apple.com/xcode/swiftui")!)
}

103
Splits/HelpView.swift Normal file
View file

@ -0,0 +1,103 @@
//
// ModalView.swift
// Splits
//
// Created by Isaac Greene on 4/3/22.
//
import SwiftUI
import RichTextView
struct HelpView: View {
@State var mathSheet = false
@State var problemSheet = false
var body: some View {
ScrollView {
VStack {
Text("Help")
.font(.largeTitle)
.bold()
.padding(.top, 40)
Text("Due to limitations in the system, you can only use kilometers and miles at this time. \nSmaller units like meters and feet are not supported. \nYou can, however, use decimals, such as .2km or .8mi.\n\nI apologize for any inconvenience. In the future, I hope to make our app easier to use.\n\nI'm currently looking to add help articles about running to this page and it'll have loads of stuff about running and pace and all that stuff to actually help you with running. If I do, the purpose of this app might change.")
.padding()
Button("See our math", action: {
self.mathSheet.toggle()
})
.padding(30)
.sheet(isPresented: self.$mathSheet, content: {
algorithmView()
})
}
}
}
}
struct algorithmView: View {
var body: some View {
Text("The Algorithm")
.font(.largeTitle)
.bold()
VStack(alignment: .leading, spacing: 0) {
Text("Calculating pace is fairly straightforward, and does not change with increased complexity. The standard formula is simply this:\n")
mathView()
Text("\nWhere:\n")
HStack {
Text("\"t\"")
.font(.custom("Charter", size: 18))
Text("is total time")
}
HStack{
Text("\"d\"")
.font(.custom("Charter", size: 18))
Text("is distance")
}
HStack {
Text("\"p\"")
.font(.custom("Charter", size: 18))
Text("is the resulting pace")
}
}
.padding()
}
}
struct mathView: View {
@State var mathString:String = "[math] \\frac{t}{d} &= p [/math]"
var body: some View {
mathLaTeX_inator(mathString: $mathString)
.padding(30)
.frame(maxHeight: 300)
}
}
struct mathLaTeX_inator: UIViewRepresentable {
@Environment(\.colorScheme) var colorScheme
@Binding var mathString:String
func makeUIView(context: Context) -> RichTextView {
let richTextView = RichTextView(
input: mathString,
latexParser: LatexParser(),
font: UIFont.systemFont(ofSize: UIFont.systemFontSize),
textColor: (colorScheme == .dark ? UIColor.white : UIColor.black),
frame: CGRect.zero,
completion: nil
)
return richTextView
}
func updateUIView(_ uiView: RichTextView, context: Context) {
uiView.update(
input: mathString,
latexParser: LatexParser(),
font: UIFont.systemFont(ofSize: UIFont.systemFontSize),
textColor: (colorScheme == .dark ? UIColor.white : UIColor.black),
completion: nil
)
}
}

View file

@ -13,7 +13,7 @@ struct RecentlyResolved: View {
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("\u{2022} Implemented an easy way to dismiss the keyboard in the main view of Calculator (it only took 2 1/2 months)\n\u{2022} Opening the contacts tab no longer causes the app to crash (RC 2)")
Text("\u{2022} Implemented an easy way to dismiss the keyboard in the main view of Calculator (it only took 2 1/2 months)\n\u{2022} Opening the contacts tab no longer causes the app to crash (RC 2)\n\u{2022} Typing zero as the first number for the distance no longer causes the app to crash")
}
.padding(30)
}
@ -25,7 +25,7 @@ struct HighPriority: View {
var body: some View {
ScrollView {
VStack {
Text("\u{2022} Putting a zero as the first number in the Distance text field causes the app to crash\n\t\u{2022} **Workaround:** Just don't put zero first. You can still use decimals (like .7km and .24mi)")
Text("\u{2022} Entering a distance of less than 0.1 per unit causes the app to crash\n\t**Workaround:** RIP to you if this applies")
}
.padding(30)
}