Added more robust app documentation. Started working on an issue where entering zero as the first number in the Distance text field causes the app to crash.

This commit is contained in:
Isaac Greene 2022-06-14 22:10:13 -04:00
parent 7d6643112d
commit b6677c2053
7 changed files with 108 additions and 41 deletions

View file

@ -18,6 +18,7 @@
850F8028285437500094580D /* aiden.moore.states.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 850F8024285437500094580D /* aiden.moore.states.jpg */; };
850F8029285437500094580D /* isaac.greene.clouds.heic in Resources */ = {isa = PBXBuildFile; fileRef = 850F8025285437500094580D /* isaac.greene.clouds.heic */; };
850F802A285437500094580D /* jake.zimmerman.group.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 850F8026285437500094580D /* jake.zimmerman.group.jpg */; };
859298C928592F1F00D9D6CB /* Documentation.docc in Sources */ = {isa = PBXBuildFile; fileRef = 859298C828592F1F00D9D6CB /* Documentation.docc */; };
85AAA0D627FA2DD600F4B9A1 /* SplitsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AAA0D527FA2DD600F4B9A1 /* SplitsApp.swift */; };
85AAA0D827FA2DD600F4B9A1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AAA0D727FA2DD600F4B9A1 /* ContentView.swift */; };
85AAA0DA27FA2DDA00F4B9A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 85AAA0D927FA2DDA00F4B9A1 /* Assets.xcassets */; };
@ -39,6 +40,7 @@
850F8024285437500094580D /* aiden.moore.states.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = aiden.moore.states.jpg; path = Assets.xcassets/aiden.moore.states.jpg; sourceTree = "<group>"; };
850F8025285437500094580D /* isaac.greene.clouds.heic */ = {isa = PBXFileReference; lastKnownFileType = file; name = isaac.greene.clouds.heic; path = Assets.xcassets/isaac.greene.clouds.heic; sourceTree = "<group>"; };
850F8026285437500094580D /* jake.zimmerman.group.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = jake.zimmerman.group.jpg; path = Assets.xcassets/jake.zimmerman.group.jpg; sourceTree = "<group>"; };
859298C828592F1F00D9D6CB /* Documentation.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = Documentation.docc; sourceTree = "<group>"; };
85AAA0D227FA2DD600F4B9A1 /* Splits.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Splits.app; sourceTree = BUILT_PRODUCTS_DIR; };
85AAA0D527FA2DD600F4B9A1 /* SplitsApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitsApp.swift; sourceTree = "<group>"; };
85AAA0D727FA2DD600F4B9A1 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
@ -80,6 +82,7 @@
isa = PBXGroup;
children = (
85AAA0D527FA2DD600F4B9A1 /* SplitsApp.swift */,
859298C828592F1F00D9D6CB /* Documentation.docc */,
8502250D27FA5D0800FE8E95 /* ChangeLogData.swift */,
85AAA0D727FA2DD600F4B9A1 /* ContentView.swift */,
850062C82802328F0095F121 /* TabViewData.swift */,
@ -195,6 +198,7 @@
8502250E27FA5D0800FE8E95 /* ChangeLogData.swift in Sources */,
850F8014284A7F6A0094580D /* DocsView.swift in Sources */,
850F8016284A815C0094580D /* KnownIssues.swift in Sources */,
859298C928592F1F00D9D6CB /* Documentation.docc in Sources */,
85AAA0E827FA2F1600F4B9A1 /* ChangeLogView.swift in Sources */,
85AAA0E627FA2EB100F4B9A1 /* ModalView.swift in Sources */,
850F80202853F7790094580D /* LicenseView.swift in Sources */,

View file

@ -6,12 +6,23 @@
//
import SwiftUI
// this file will not have comments.
// it is considered self-explanatory and best viewed in-app
struct June2022: View {
var body: some View {
ScrollView {
//2022-06-14
HStack {
VStack (alignment: .leading) {
Text("2022-06-14")
.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")
}
Spacer()
}
.padding(30)
//2022-06-11
HStack {
VStack (alignment: .leading) {
@ -43,7 +54,7 @@ struct June2022: View {
VStack (alignment: .leading) {
Text("2022-06-09")
.font(.title2)
Text("Version Prerelease LVSXT10c.2\n")
Text("Version Prerelease Build LVSXT10c.2\n")
.font(.footnote)
Text("\u{2022} Worked on a simple login page to view contact info\n\t\u{2022} Spent *way* too long on it")
}
@ -63,6 +74,7 @@ struct June2022: View {
Spacer()
}
.padding(30)
//2022-06-05
HStack {
VStack (alignment: .leading) {
@ -70,9 +82,11 @@ struct June2022: View {
.font(.title2)
Text("Version Prerelease Build LVSXT10d.3\n")
.font(.footnote)
Text("\u{2022} Started work on converting the pace to a more understandable format\n\u{2022} ")
Text("\u{2022} Started work on converting the pace to a more understandable format")
}
}
.padding(30)
//2022-06-04
HStack {
VStack (alignment: .leading) {
@ -118,6 +132,7 @@ struct June2022: View {
}
}
// done adding content to these
struct May2022: View {
var body: some View {
ScrollView {

View file

@ -8,6 +8,9 @@
import SwiftUI
import Foundation
/// Creates the primary tab of ``SplitsApp``
///
/// e
struct ContentView: View {
@FocusState private var nameIsFocused: Bool
var SISystem = ["km","mi"]
@ -101,8 +104,10 @@ struct PaceResults: View {
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:String = {
let convertedDistance = distanceDub * multiplier
return (distance == "" || distance.starts(with: "0") ? "0" : String(format: "%.3f", convertedDistance))
}()
let convertedSeconds:Double = (Double(timeSeconds) ?? 0) * (1.6666666666666666666666666)
let timeSecondsInt:Int = Int(timeSeconds) ?? 0
@ -141,22 +146,27 @@ struct PaceResults: View {
// 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 paceOpposite = (selectedSystem == "km" ? (pace * 1.609344) : (pace * 0.6213711922))
let paceSeconds = pace.truncatingRemainder(dividingBy: 1.0)
let paceMinutes = (pace.truncatingRemainder(dividingBy: 60.0) - paceSeconds)
let paceHours = String(format: "%.0f", ((pace - paceMinutes) / 60))
let reConvertedSeconds = (paceSeconds / 1.666666666666666666) * 100
let paceFormatted:String = {
let paceSeconds = pace.truncatingRemainder(dividingBy: 1.0)
let paceMinutes = (pace.truncatingRemainder(dividingBy: 60.0) - paceSeconds)
let paceHours = String(format: "%.0f", ((pace - paceMinutes) / 60))
let reConvertedSeconds = (paceSeconds / 1.666666666666666666) * 100
let properTimeMS = String(format: "%02d:%02d", Int(paceMinutes), Int(reConvertedSeconds.rounded()))
return (pace >= 60 ? "\(paceHours):\(properTimeMS)" : "\(properTimeMS)")
}()
let properTimeMS = String(format: "%02d:%02d", Int(paceMinutes), Int(reConvertedSeconds.rounded()))
let paceSecondsOpposite = paceOpposite.truncatingRemainder(dividingBy: 1.0)
let paceMinutesOpposite = (paceOpposite.truncatingRemainder(dividingBy: 60.0) - paceSecondsOpposite)
let paceHoursOpposite = String(format: "%.0f", ((paceOpposite - paceMinutesOpposite) / 60))
let reConvertedSecondsOpposite = (paceSecondsOpposite / 1.666666666666666666) * 100
let properTimeMSOpposite = String(format: "%02d:%02d", Int(paceMinutesOpposite), Int(reConvertedSecondsOpposite.rounded()))
let paceFormattedOpposite:String = {
let paceOpposite = (selectedSystem == "km" ? (pace * 1.609344) : (pace * 0.6213711922))
let paceSecondsOpposite = paceOpposite.truncatingRemainder(dividingBy: 1.0)
let paceMinutesOpposite = (paceOpposite.truncatingRemainder(dividingBy: 60.0) - paceSecondsOpposite)
let paceHoursOpposite = String(format: "%.0f", ((paceOpposite - paceMinutesOpposite) / 60))
let reConvertedSecondsOpposite = (paceSecondsOpposite / 1.666666666666666666) * 100
let properTimeMSOpposite = String(format: "%02d:%02d", Int(paceMinutesOpposite), Int(reConvertedSecondsOpposite.rounded()))
return (paceOpposite >= 60 ? "\(paceHoursOpposite):\(properTimeMSOpposite)" : "\(properTimeMSOpposite)")
}()
//let paceString:String = String(format: "%.2f", pace)
let totalHours:Double = Double(timeMinutesToHours) + (Double(timeHours) ?? 0)
@ -164,18 +174,16 @@ 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 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
// zeros to them, so that 5 minutes 7 seconds will show
// as 05:07 which is a format most people, and certainly
// the people this app is intended for, will understand
HStack {
VStack {
VStack (alignment: .leading) {
Text("\(distance)\(selectedSystem)")
Text("\(convertedDistanceString)\(notSelectedSystem)")
}

View file

@ -13,9 +13,25 @@ import LocalAuthentication
// the reader has a basic understanding of
// Swift and/or SwiftUI.
/// The system username for the app
/// - Note: This is not a secure way to do it
/// or in any way good practice
/// but this is mainly to test out `SecureField`
let username = "admin"
/// The system password associated with ``username``
///
/// I'm thinking about hashing them, but that would take work.
///
/// It would be more secure though.
/// - Note: Just as with `username` you should not define
/// these unencrypted like they are right now.
let password = "123"
/// Holds the views and login for the Docs tab in-app
///
/// Mostly just a long list of sections and calling views
/// - Note: New views are best called in this `struct`
struct DocsView: View {
enum Field: Hashable {
case username
@ -46,8 +62,8 @@ struct DocsView: View {
}
Section(header: Text("App Information")) {
NavigationLink("Software License", destination: LicenseView())
Text("Version: Release Candidate 2 (1.0.0)")
Text("Release date: 2022-06-11")
Text("Version: Prerelease Build LVSXT10a.3")
Text("Release date: 2022-06-14")
Text("Start date: 2022-03-25")
Link("Built with SwiftUI \(Image(systemName: "swift"))", destination: URL(string: "https://developer.apple.com/xcode/swiftui")!)
}
@ -60,21 +76,21 @@ struct DocsView: View {
isUnlocked = false
}
} else {
if !isUnlocked {
Button("Log in with biometrics") {
authenticate()
}
Button("Log in with biometrics") {
authenticate()
}
SecureField("Username", text: $user)
.keyboardType(.alphabet)
.textContentType(.username)
.submitLabel(.next)
.focused($focusedField, equals: .username)
.textContentType(.username)
SecureField("Password", text: $pass)
.keyboardType(.numbersAndPunctuation)
.textContentType(.password)
.submitLabel(.done)
.focused($focusedField, equals: .password)
.textContentType(.password)
if checkPassword() {
NavigationLink("Contacts", destination: SecretView())
}
@ -90,11 +106,19 @@ struct DocsView: View {
default:
()
}
if (pass == password && user == username) {
if checkPassword() {
isUnlocked = true
}
}
}
/// Compares the `user` SecureField and the `pass` SecureField against ``username`` and ``password``
///
/// - Note: come back to this
///
///
/// - Returns: `true` if `user` equals `username` *and* `pass` equals `password`, `false` if one or both checks return false.
func checkPassword() -> Bool {
if (pass == password && user == username) {
return true
@ -102,11 +126,15 @@ struct DocsView: View {
return false
}
}
func checkIfUnlocked() {
if !isUnlocked {
authenticate()
}
}
/// Checks wether the user can use biometrics to sign in
/// and (if true) prompts the user to sign with either FaceID or TouchID
/// depending on the device.
///
/// If the prompt was shown, and the user authenticated correctly
/// `isUnlocked` is set to `true`
///
/// - Note: `authenticate()` has to be called to show the sign-in sheet
func authenticate() {
let context = LAContext()
var error: NSError?

View file

@ -0,0 +1,14 @@
# ``Splits``
Splits is a revolutionary new app to calculate paces.
It takes a value, in kilometers or miles, and converts
## Overview
<!--@START_MENU_TOKEN@-->Text<!--@END_MENU_TOKEN@-->
## Topics
### Getting Started
- <!--@START_MENU_TOKEN@-->``Symbol``<!--@END_MENU_TOKEN@-->

View file

@ -25,10 +25,7 @@ struct HighPriority: View {
var body: some View {
ScrollView {
VStack {
Image(systemName: "checkmark.shield.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 70)
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)")
}
.padding(30)
}
@ -55,7 +52,7 @@ struct LowPriority: View {
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("\u{2022} Space between the equation and explanation in the \"Help\" tab is too large\n\u{2022} App has no custom icon")
Text("\u{2022} Space between the equation and explanation in the \"Help\" tab is too large\n\u{2022} App has no custom icon\n\u{2022} In some circumstances, the pace will show xx:60/unit as a pace, when the 60 should equal one minute")
}
.padding(30)
}

View file

@ -13,6 +13,7 @@ import SwiftUI
// Swift and/or SwiftUI.
@main
/// Builds the main view of the app (``TabViewData``)
struct SplitsApp: App {
var body: some Scene {
WindowGroup {