diff --git a/Splits.xcodeproj/project.pbxproj b/Splits.xcodeproj/project.pbxproj
index ba68ed2..bf9fb1a 100644
--- a/Splits.xcodeproj/project.pbxproj
+++ b/Splits.xcodeproj/project.pbxproj
@@ -335,13 +335,14 @@
DEVELOPMENT_TEAM = UQJ7U8R2CV;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSFaceIDUsageDescription = "We'll need authentication before we can show sensitive data";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UIRequiresFullScreen = NO;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeRight UIInterfaceOrientationLandscapeLeft";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -370,13 +371,14 @@
DEVELOPMENT_TEAM = UQJ7U8R2CV;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSFaceIDUsageDescription = "We'll need authentication before we can show sensitive data";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UIRequiresFullScreen = NO;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeRight UIInterfaceOrientationLandscapeLeft";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
diff --git a/Splits/ChangeLogData.swift b/Splits/ChangeLogData.swift
index a361571..c28c9af 100644
--- a/Splits/ChangeLogData.swift
+++ b/Splits/ChangeLogData.swift
@@ -12,6 +12,19 @@ import SwiftUI
struct June2022: View {
var body: some View {
ScrollView {
+ //2022-06-11
+ HStack {
+ VStack (alignment: .leading) {
+ Text("2022-06-11")
+ .font(.title2)
+ Text("Version Release Candidate 2 (LVSXT10a.2)\n")
+ .font(.footnote)
+ Text("\u{2022} Added biometrics to sign in along with option for username/password")
+ }
+ Spacer()
+ }
+ .padding(30)
+
//2022-06-10
HStack {
VStack (alignment: .leading) {
diff --git a/Splits/ContentView.swift b/Splits/ContentView.swift
index 86290eb..bfd424b 100644
--- a/Splits/ContentView.swift
+++ b/Splits/ContentView.swift
@@ -21,7 +21,7 @@ struct ContentView: View {
VStack {
Spacer()
VStack {
- TextField("Enter distance here", text: $distance)
+ TextField("Enter distance", text: $distance)
.padding()
.keyboardType(.decimalPad)
.textFieldStyle(.roundedBorder)
@@ -39,7 +39,7 @@ struct ContentView: View {
HStack {
VStack {
Text("Hours")
- TextField("Enter hours here", text: $timeHours)
+ TextField("Enter hours", text: $timeHours)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
@@ -49,7 +49,7 @@ struct ContentView: View {
.padding()
VStack {
Text("Minutes")
- TextField("Enter minutes here", text: $timeMinutes)
+ TextField("Enter minutes", text: $timeMinutes)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
@@ -60,7 +60,7 @@ struct ContentView: View {
.padding()
VStack {
Text("Seconds")
- TextField("Enter seconds here", text: $timeSeconds)
+ TextField("Enter seconds", text: $timeSeconds)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
.focused($nameIsFocused)
@@ -99,10 +99,10 @@ struct PaceResults: View {
// but then my message would disappear to let you know
// what to enter in that box
- let multiplier = {selectedSystem == "mi" ? 1.609344 : 0.6213711922}()
- let notSelectedSystem = {selectedSystem == "km" ? "mi" : "km"}()
+ let multiplier = (selectedSystem == "mi" ? 1.609344 : 0.6213711922)
+ let notSelectedSystem = (selectedSystem == "km" ? "mi" : "km")
let convertedDistance = distanceDub * multiplier
- let convertedDistanceString = {distance == "" ? "" : String(format: "%.2f", convertedDistance)}()
+ let convertedDistanceString = (distance == "" ? "" : String(format: "%.2f", convertedDistance))
let convertedSeconds:Double = (Double(timeSeconds) ?? 0) * (1.6666666666666666666666666)
let timeSecondsInt:Int = Int(timeSeconds) ?? 0
@@ -164,9 +164,9 @@ struct PaceResults: View {
// 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 paceFormatted:String = {pace >= 60 ? "\(paceHours):\(properTimeMS)" : "\(properTimeMS)"}()
+ let paceFormatted:String = (pace >= 60 ? "\(paceHours):\(properTimeMS)" : "\(properTimeMS)")
- let paceFormattedOpposite:String = {paceOpposite >= 60 ? "\(paceHoursOpposite):\(properTimeMSOpposite)" : "\(properTimeMSOpposite)"}()
+ let paceFormattedOpposite:String = (paceOpposite >= 60 ? "\(paceHoursOpposite):\(properTimeMSOpposite)" : "\(properTimeMSOpposite)")
let leadingZeros:String = String(format: "%02d:%02d", timeMinutesUnderSixty, timeSecondsUnderSixty)
// this takes the minutes and the seconds and adds leading
@@ -176,15 +176,18 @@ struct PaceResults: View {
HStack {
VStack {
- Text("Distance: \(distance)\(selectedSystem)")
- Text("Distance: \(convertedDistanceString)\(notSelectedSystem)")
+ Text("\(distance)\(selectedSystem)")
+ Text("\(convertedDistanceString)\(notSelectedSystem)")
}
- Text("Total time\n\(hoursFormatted):\(leadingZeros)")
+ .frame(minWidth: 100)
+ Text("\(hoursFormatted):\(leadingZeros)")
.padding()
+ .frame(minWidth: 100)
VStack(alignment: .trailing) {
- Text("\(paceFormatted) per \(selectedSystem)")
- Text("\(paceFormattedOpposite) per \(notSelectedSystem)")
+ Text("\(paceFormatted)/\(selectedSystem)")
+ Text("\(paceFormattedOpposite)/\(notSelectedSystem)")
}
+ .frame(minWidth: 100)
}
}
}
diff --git a/Splits/DocsView.swift b/Splits/DocsView.swift
index dbb6208..183935c 100644
--- a/Splits/DocsView.swift
+++ b/Splits/DocsView.swift
@@ -6,9 +6,10 @@
//
import SwiftUI
-// this file will not have comments.
-// this code is considered simple enough to be
-// human-readable without aid, as long as
+import LocalAuthentication
+// this file will have some comments.
+// Most of this code is considered simple enough
+// to be human-readable without aid, as long as
// the reader has a basic understanding of
// Swift and/or SwiftUI.
@@ -23,7 +24,8 @@ struct DocsView: View {
@State private var pass: String = ""
@State private var user: String = ""
- @FocusState private var focusedField: Field?
+ @State private var isUnlocked = false
+ @FocusState private var focusedField: Field?
var body: some View {
NavigationView {
@@ -44,24 +46,38 @@ struct DocsView: View {
}
Section(header: Text("App Information")) {
NavigationLink("Software License", destination: LicenseView())
- Text("Version: Release Candidate (1.0.0)")
- Text("Release date: 2022-06-10")
+ Text("Version: Release Candidate 2 (1.0.0)")
+ Text("Release date: 2022-06-11")
Text("Start date: 2022-03-25")
Link("Built with SwiftUI \(Image(systemName: "swift"))", destination: URL(string: "https://developer.apple.com/xcode/swiftui")!)
}
Section(header: Text("Login")) {
- SecureField("Username", text: $user)
- .keyboardType(.alphabet)
- .textContentType(.username)
- .submitLabel(.next)
- .focused($focusedField, equals: .username)
- SecureField("Password", text: $pass)
- .keyboardType(.numbersAndPunctuation)
- .textContentType(.password)
- .submitLabel(.done)
- .focused($focusedField, equals: .password)
- if (pass == password && user == username) {
+ if (isUnlocked) {
NavigationLink("Contacts", destination: SecretView())
+ Button("Log out") {
+ pass = ""
+ user = ""
+ isUnlocked = false
+ }
+ } else {
+ if !isUnlocked {
+ Button("Log in with biometrics") {
+ authenticate()
+ }
+ }
+ SecureField("Username", text: $user)
+ .keyboardType(.alphabet)
+ .textContentType(.username)
+ .submitLabel(.next)
+ .focused($focusedField, equals: .username)
+ SecureField("Password", text: $pass)
+ .keyboardType(.numbersAndPunctuation)
+ .textContentType(.password)
+ .submitLabel(.done)
+ .focused($focusedField, equals: .password)
+ if checkPassword() {
+ NavigationLink("Contacts", destination: SecretView())
+ }
}
}
}
@@ -74,8 +90,48 @@ struct DocsView: View {
default:
()
}
+ if (pass == password && user == username) {
+ isUnlocked = true
+ }
}
}
+ func checkPassword() -> Bool {
+ if (pass == password && user == username) {
+ return true
+ } else {
+ return false
+ }
+ }
+ func checkIfUnlocked() {
+ if !isUnlocked {
+ authenticate()
+ }
+ }
+ func authenticate() {
+ let context = LAContext()
+ var error: NSError?
+
+ // check whether biometric authentication is possible
+ if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
+ // it's possible, so go ahead and use it
+ let reason = "We need authentication before we can show you sensitive data"
+
+ context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
+ // authentication has now completed
+ if success {
+ isUnlocked = true
+ } else {
+ ()
+ }
+ }
+ } else {
+ ()
+ }
+ }
+ // getting this to work came from
+ // https://www.hackingwithswift.com/books/ios-swiftui/using-touch-id-and-face-id-with-swiftui
+ // a truly epic website and it's helped me with
+ // just about all of my code questions
}
struct DocsView_Previews: PreviewProvider {
diff --git a/Splits/FeaturesView.swift b/Splits/FeaturesView.swift
index 2a03e49..130ce1e 100644
--- a/Splits/FeaturesView.swift
+++ b/Splits/FeaturesView.swift
@@ -11,6 +11,14 @@ struct NewFeatures: View {
var body: some View {
ScrollView {
VStack(alignment: .leading) {
+ Text("\u{2022} Added TouchID and FaceID to sign in")
+ Text("Implemented in Version Release Candidate 2\n")
+ .font(.footnote)
+ .italic()
+ Text("\u{2022} Implemented a way to dismiss the keyboard")
+ Text("Implemented in Version Release Candidate\n")
+ .font(.footnote)
+ .italic()
Text("\u{2022} Reformatted the Docs tabs and made the common things up at the top")
Text("Implemented in Version Prerelease LVSXT10d.2\n")
.font(.footnote)
@@ -33,15 +41,11 @@ struct NewFeatures: View {
struct InProgressFeatures: View {
var body: some View {
ScrollView {
- Text("Features In Progress")
- .font(.largeTitle)
- .bold()
- .padding(.top, 40)
Text("Note: this does not include things I have to fix\n")
.font(.footnote)
.italic()
VStack(alignment: .leading) {
- Text("\u{2022} Working on a conversion between measurements for pace and distance\n")
+ Text("\u{2022} Adding a better-formatted Contacts tab on iPad\n")
}
.padding(30)
}
@@ -52,10 +56,6 @@ struct InProgressFeatures: View {
struct DeprecatedFeatures: View {
var body: some View {
ScrollView {
- Text("Deprecated Features")
- .font(.largeTitle)
- .bold()
- .padding(.top, 40)
VStack(alignment: .leading) {
Text("\n\u{2022} Removed the picker wheel to enter total time (a truly horrible system)")
Text("Stricken before recorded history\n")
diff --git a/Splits/KnownIssues.swift b/Splits/KnownIssues.swift
index 6915b47..5ee79af 100644
--- a/Splits/KnownIssues.swift
+++ b/Splits/KnownIssues.swift
@@ -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)")
+ 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)")
}
.padding(30)
}
@@ -24,8 +24,11 @@ struct RecentlyResolved: View {
struct HighPriority: View {
var body: some View {
ScrollView {
- VStack(alignment: .leading) {
- Text("Tapping on the Contacts tab after entering correct login details causes the app to crash")
+ VStack {
+ Image(systemName: "checkmark.shield.fill")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(width: 70)
}
.padding(30)
}
@@ -36,9 +39,11 @@ struct HighPriority: View {
struct MediumPriority: View {
var body: some View {
ScrollView {
- VStack(alignment: .leading) {
- Text("Wow. Such Empty.")
- .italic()
+ VStack {
+ Image(systemName: "checkmark.shield.fill")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(width: 70)
}
.padding(30)
}
diff --git a/Splits/LicenseView.swift b/Splits/LicenseView.swift
index 05aeef8..c201d69 100644
--- a/Splits/LicenseView.swift
+++ b/Splits/LicenseView.swift
@@ -17,7 +17,6 @@ struct LicenseView: View {
// setting fontSize to a value based on that where the whole
// line can be viewed without scrolling horizontally
// or with wrapped text, ruining the required formatting I have.
- // As of 2022-06-08, I have not tested this on a phone.
var body: some View {
ScrollView {
diff --git a/Splits/SecretView.swift b/Splits/SecretView.swift
index 6878478..aa648d3 100644
--- a/Splits/SecretView.swift
+++ b/Splits/SecretView.swift
@@ -14,8 +14,8 @@ import SwiftUI
struct SecretView: View {
var body: some View {
- VStack {
- ScrollView {
+ ScrollView {
+ VStack {
VStack {
Image("jake.zimmerman.group")
.resizable()
@@ -101,9 +101,90 @@ Email: greenei@students.lakeviewspartans.org
}
.frame(minWidth: 350, minHeight: 175)
.border(.primary)
+ VStack {
+ Image(systemName: "person.crop.circle.fill")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(width: 75, height: 75)
+ Text("Pryor")
+ .font(.title2)
+ VStack (alignment: .leading) {
+ Text("""
+Name: Becky Pryor
+Email: bpryor@lakeviewspartans.org
+""")
+ HStack {
+ Text("Phone:")
+ Link("(269) 209-9906", destination: URL(string: "tel:2692099906")!)
+ }
+ }
+ }
+ .frame(minWidth: 350, minHeight: 175)
+ .border(.primary)
+ VStack {
+ Image(systemName: "person.crop.circle.fill")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(width: 75, height: 75)
+ Text("Paige")
+ .font(.title2)
+ VStack (alignment: .leading) {
+ Text("""
+Name: Paige Ratliff
+Email: ratliffp@students.lakeviewspartans.org
+""")
+ HStack {
+ Text("Phone:")
+ Link("(269) 753-8569", destination: URL(string: "tel:2697538569")!)
+ }
+ }
+ }
+ .frame(minWidth: 350, minHeight: 175)
+ .border(.primary)
+ VStack {
+ Image(systemName: "person.crop.circle.fill")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(width: 75, height: 75)
+ Text("Emma")
+ .font(.title2)
+ VStack (alignment: .leading) {
+ Text("""
+Name: Emma Kerschbaum
+Email: kerschbaume@students.lakeviewspartans.org
+""")
+ HStack {
+ Text("Phone:")
+ Link("(269) 419-7880", destination: URL(string: "tel:2694197880")!)
+ }
+ }
+ }
+ .frame(minWidth: 350, minHeight: 175)
+ .border(.primary)
+ VStack {
+ Image(systemName: "person.crop.circle.fill")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(width: 75, height: 75)
+ Text("Alyssa")
+ .font(.title2)
+ VStack (alignment: .leading) {
+ Text("""
+Name: Alyssa Hinton
+Email: hintona2@students.lakeviewspartans.org
+""")
+ HStack {
+ Text("Phone:")
+ Link("(269) 589-7609", destination: URL(string: "tel:2695897609")!)
+ }
+ }
+ }
+ .frame(minWidth: 350, minHeight: 175)
+ .border(.primary)
+
}
+ .frame(maxWidth: .infinity)
.navigationTitle("Contacts")
}
- .frame(minWidth: .infinity)
}
}
diff --git a/qerberymjthnrgbefvdcs.playground/Contents.swift b/qerberymjthnrgbefvdcs.playground/Contents.swift
new file mode 100644
index 0000000..80cb5ea
--- /dev/null
+++ b/qerberymjthnrgbefvdcs.playground/Contents.swift
@@ -0,0 +1,6 @@
+import UIKit
+var selectedSystem = "mi"
+
+let multiplier = (selectedSystem == "mi" ? 1.609344 : 0.6213711922)
+
+print(multiplier)
diff --git a/qerberymjthnrgbefvdcs.playground/contents.xcplayground b/qerberymjthnrgbefvdcs.playground/contents.xcplayground
new file mode 100644
index 0000000..cf026f2
--- /dev/null
+++ b/qerberymjthnrgbefvdcs.playground/contents.xcplayground
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/qerberymjthnrgbefvdcs.playground/playground.xcworkspace/contents.xcworkspacedata b/qerberymjthnrgbefvdcs.playground/playground.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..ca3329e
--- /dev/null
+++ b/qerberymjthnrgbefvdcs.playground/playground.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/qerberymjthnrgbefvdcs.playground/timeline.xctimeline b/qerberymjthnrgbefvdcs.playground/timeline.xctimeline
new file mode 100644
index 0000000..8510264
--- /dev/null
+++ b/qerberymjthnrgbefvdcs.playground/timeline.xctimeline
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+