Added TouchID/FaceID to sign in
This commit is contained in:
parent
5c4d4f8059
commit
7d6643112d
12 changed files with 239 additions and 52 deletions
|
|
@ -335,13 +335,14 @@
|
||||||
DEVELOPMENT_TEAM = UQJ7U8R2CV;
|
DEVELOPMENT_TEAM = UQJ7U8R2CV;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = 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_UIApplicationSceneManifest_Generation = YES;
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UIRequiresFullScreen = NO;
|
INFOPLIST_KEY_UIRequiresFullScreen = NO;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeRight UIInterfaceOrientationLandscapeLeft";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeRight UIInterfaceOrientationLandscapeLeft";
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
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;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
|
@ -370,13 +371,14 @@
|
||||||
DEVELOPMENT_TEAM = UQJ7U8R2CV;
|
DEVELOPMENT_TEAM = UQJ7U8R2CV;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = 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_UIApplicationSceneManifest_Generation = YES;
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UIRequiresFullScreen = NO;
|
INFOPLIST_KEY_UIRequiresFullScreen = NO;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeRight UIInterfaceOrientationLandscapeLeft";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeRight UIInterfaceOrientationLandscapeLeft";
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
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;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,19 @@ import SwiftUI
|
||||||
struct June2022: View {
|
struct June2022: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
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
|
//2022-06-10
|
||||||
HStack {
|
HStack {
|
||||||
VStack (alignment: .leading) {
|
VStack (alignment: .leading) {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ struct ContentView: View {
|
||||||
VStack {
|
VStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
VStack {
|
VStack {
|
||||||
TextField("Enter distance here", text: $distance)
|
TextField("Enter distance", text: $distance)
|
||||||
.padding()
|
.padding()
|
||||||
.keyboardType(.decimalPad)
|
.keyboardType(.decimalPad)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
|
|
@ -39,7 +39,7 @@ struct ContentView: View {
|
||||||
HStack {
|
HStack {
|
||||||
VStack {
|
VStack {
|
||||||
Text("Hours")
|
Text("Hours")
|
||||||
TextField("Enter hours here", text: $timeHours)
|
TextField("Enter hours", text: $timeHours)
|
||||||
.keyboardType(.numberPad)
|
.keyboardType(.numberPad)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
.focused($nameIsFocused)
|
.focused($nameIsFocused)
|
||||||
|
|
@ -49,7 +49,7 @@ struct ContentView: View {
|
||||||
.padding()
|
.padding()
|
||||||
VStack {
|
VStack {
|
||||||
Text("Minutes")
|
Text("Minutes")
|
||||||
TextField("Enter minutes here", text: $timeMinutes)
|
TextField("Enter minutes", text: $timeMinutes)
|
||||||
.keyboardType(.numberPad)
|
.keyboardType(.numberPad)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
.focused($nameIsFocused)
|
.focused($nameIsFocused)
|
||||||
|
|
@ -60,7 +60,7 @@ struct ContentView: View {
|
||||||
.padding()
|
.padding()
|
||||||
VStack {
|
VStack {
|
||||||
Text("Seconds")
|
Text("Seconds")
|
||||||
TextField("Enter seconds here", text: $timeSeconds)
|
TextField("Enter seconds", text: $timeSeconds)
|
||||||
.keyboardType(.numberPad)
|
.keyboardType(.numberPad)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
.focused($nameIsFocused)
|
.focused($nameIsFocused)
|
||||||
|
|
@ -99,10 +99,10 @@ struct PaceResults: View {
|
||||||
// but then my message would disappear to let you know
|
// but then my message would disappear to let you know
|
||||||
// what to enter in that box
|
// what to enter in that box
|
||||||
|
|
||||||
let multiplier = {selectedSystem == "mi" ? 1.609344 : 0.6213711922}()
|
let multiplier = (selectedSystem == "mi" ? 1.609344 : 0.6213711922)
|
||||||
let notSelectedSystem = {selectedSystem == "km" ? "mi" : "km"}()
|
let notSelectedSystem = (selectedSystem == "km" ? "mi" : "km")
|
||||||
let convertedDistance = distanceDub * multiplier
|
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 convertedSeconds:Double = (Double(timeSeconds) ?? 0) * (1.6666666666666666666666666)
|
||||||
let timeSecondsInt:Int = Int(timeSeconds) ?? 0
|
let timeSecondsInt:Int = Int(timeSeconds) ?? 0
|
||||||
|
|
@ -164,9 +164,9 @@ struct PaceResults: View {
|
||||||
// and the hours calculated in the previous section
|
// and the hours calculated in the previous section
|
||||||
// and adds them together to get our total number of hours.
|
// and adds them together to get our total number of hours.
|
||||||
let hoursFormatted:String = String(format: "%.0f", totalHours)
|
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)
|
let leadingZeros:String = String(format: "%02d:%02d", timeMinutesUnderSixty, timeSecondsUnderSixty)
|
||||||
// this takes the minutes and the seconds and adds leading
|
// this takes the minutes and the seconds and adds leading
|
||||||
|
|
@ -176,15 +176,18 @@ struct PaceResults: View {
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
VStack {
|
VStack {
|
||||||
Text("Distance: \(distance)\(selectedSystem)")
|
Text("\(distance)\(selectedSystem)")
|
||||||
Text("Distance: \(convertedDistanceString)\(notSelectedSystem)")
|
Text("\(convertedDistanceString)\(notSelectedSystem)")
|
||||||
}
|
}
|
||||||
Text("Total time\n\(hoursFormatted):\(leadingZeros)")
|
.frame(minWidth: 100)
|
||||||
|
Text("\(hoursFormatted):\(leadingZeros)")
|
||||||
.padding()
|
.padding()
|
||||||
|
.frame(minWidth: 100)
|
||||||
VStack(alignment: .trailing) {
|
VStack(alignment: .trailing) {
|
||||||
Text("\(paceFormatted) per \(selectedSystem)")
|
Text("\(paceFormatted)/\(selectedSystem)")
|
||||||
Text("\(paceFormattedOpposite) per \(notSelectedSystem)")
|
Text("\(paceFormattedOpposite)/\(notSelectedSystem)")
|
||||||
}
|
}
|
||||||
|
.frame(minWidth: 100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,10 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
// this file will not have comments.
|
import LocalAuthentication
|
||||||
// this code is considered simple enough to be
|
// this file will have some comments.
|
||||||
// human-readable without aid, as long as
|
// Most of this code is considered simple enough
|
||||||
|
// to be human-readable without aid, as long as
|
||||||
// the reader has a basic understanding of
|
// the reader has a basic understanding of
|
||||||
// Swift and/or SwiftUI.
|
// Swift and/or SwiftUI.
|
||||||
|
|
||||||
|
|
@ -23,7 +24,8 @@ struct DocsView: View {
|
||||||
|
|
||||||
@State private var pass: String = ""
|
@State private var pass: String = ""
|
||||||
@State private var user: 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 {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
|
|
@ -44,24 +46,38 @@ struct DocsView: View {
|
||||||
}
|
}
|
||||||
Section(header: Text("App Information")) {
|
Section(header: Text("App Information")) {
|
||||||
NavigationLink("Software License", destination: LicenseView())
|
NavigationLink("Software License", destination: LicenseView())
|
||||||
Text("Version: Release Candidate (1.0.0)")
|
Text("Version: Release Candidate 2 (1.0.0)")
|
||||||
Text("Release date: 2022-06-10")
|
Text("Release date: 2022-06-11")
|
||||||
Text("Start date: 2022-03-25")
|
Text("Start date: 2022-03-25")
|
||||||
Link("Built with SwiftUI \(Image(systemName: "swift"))", destination: URL(string: "https://developer.apple.com/xcode/swiftui")!)
|
Link("Built with SwiftUI \(Image(systemName: "swift"))", destination: URL(string: "https://developer.apple.com/xcode/swiftui")!)
|
||||||
}
|
}
|
||||||
Section(header: Text("Login")) {
|
Section(header: Text("Login")) {
|
||||||
SecureField("Username", text: $user)
|
if (isUnlocked) {
|
||||||
.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) {
|
|
||||||
NavigationLink("Contacts", destination: SecretView())
|
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:
|
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 {
|
struct DocsView_Previews: PreviewProvider {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,14 @@ struct NewFeatures: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading) {
|
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("\u{2022} Reformatted the Docs tabs and made the common things up at the top")
|
||||||
Text("Implemented in Version Prerelease LVSXT10d.2\n")
|
Text("Implemented in Version Prerelease LVSXT10d.2\n")
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
|
|
@ -33,15 +41,11 @@ struct NewFeatures: View {
|
||||||
struct InProgressFeatures: View {
|
struct InProgressFeatures: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
Text("Features In Progress")
|
|
||||||
.font(.largeTitle)
|
|
||||||
.bold()
|
|
||||||
.padding(.top, 40)
|
|
||||||
Text("Note: this does not include things I have to fix\n")
|
Text("Note: this does not include things I have to fix\n")
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
.italic()
|
.italic()
|
||||||
VStack(alignment: .leading) {
|
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)
|
.padding(30)
|
||||||
}
|
}
|
||||||
|
|
@ -52,10 +56,6 @@ struct InProgressFeatures: View {
|
||||||
struct DeprecatedFeatures: View {
|
struct DeprecatedFeatures: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
Text("Deprecated Features")
|
|
||||||
.font(.largeTitle)
|
|
||||||
.bold()
|
|
||||||
.padding(.top, 40)
|
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("\n\u{2022} Removed the picker wheel to enter total time (a truly horrible system)")
|
Text("\n\u{2022} Removed the picker wheel to enter total time (a truly horrible system)")
|
||||||
Text("Stricken before recorded history\n")
|
Text("Stricken before recorded history\n")
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ struct RecentlyResolved: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading) {
|
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)
|
.padding(30)
|
||||||
}
|
}
|
||||||
|
|
@ -24,8 +24,11 @@ struct RecentlyResolved: View {
|
||||||
struct HighPriority: View {
|
struct HighPriority: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading) {
|
VStack {
|
||||||
Text("Tapping on the Contacts tab after entering correct login details causes the app to crash")
|
Image(systemName: "checkmark.shield.fill")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 70)
|
||||||
}
|
}
|
||||||
.padding(30)
|
.padding(30)
|
||||||
}
|
}
|
||||||
|
|
@ -36,9 +39,11 @@ struct HighPriority: View {
|
||||||
struct MediumPriority: View {
|
struct MediumPriority: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading) {
|
VStack {
|
||||||
Text("Wow. Such Empty.")
|
Image(systemName: "checkmark.shield.fill")
|
||||||
.italic()
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 70)
|
||||||
}
|
}
|
||||||
.padding(30)
|
.padding(30)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ struct LicenseView: View {
|
||||||
// setting fontSize to a value based on that where the whole
|
// setting fontSize to a value based on that where the whole
|
||||||
// line can be viewed without scrolling horizontally
|
// line can be viewed without scrolling horizontally
|
||||||
// or with wrapped text, ruining the required formatting I have.
|
// 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 {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ import SwiftUI
|
||||||
|
|
||||||
struct SecretView: View {
|
struct SecretView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
ScrollView {
|
||||||
ScrollView {
|
VStack {
|
||||||
VStack {
|
VStack {
|
||||||
Image("jake.zimmerman.group")
|
Image("jake.zimmerman.group")
|
||||||
.resizable()
|
.resizable()
|
||||||
|
|
@ -101,9 +101,90 @@ Email: greenei@students.lakeviewspartans.org
|
||||||
}
|
}
|
||||||
.frame(minWidth: 350, minHeight: 175)
|
.frame(minWidth: 350, minHeight: 175)
|
||||||
.border(.primary)
|
.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")
|
.navigationTitle("Contacts")
|
||||||
}
|
}
|
||||||
.frame(minWidth: .infinity)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
qerberymjthnrgbefvdcs.playground/Contents.swift
Normal file
6
qerberymjthnrgbefvdcs.playground/Contents.swift
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import UIKit
|
||||||
|
var selectedSystem = "mi"
|
||||||
|
|
||||||
|
let multiplier = (selectedSystem == "mi" ? 1.609344 : 0.6213711922)
|
||||||
|
|
||||||
|
print(multiplier)
|
||||||
4
qerberymjthnrgbefvdcs.playground/contents.xcplayground
Normal file
4
qerberymjthnrgbefvdcs.playground/contents.xcplayground
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<playground version='5.0' target-platform='ios' buildActiveScheme='true' importAppTypes='true'>
|
||||||
|
<timeline fileName='timeline.xctimeline'/>
|
||||||
|
</playground>
|
||||||
7
qerberymjthnrgbefvdcs.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
qerberymjthnrgbefvdcs.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
11
qerberymjthnrgbefvdcs.playground/timeline.xctimeline
Normal file
11
qerberymjthnrgbefvdcs.playground/timeline.xctimeline
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Timeline
|
||||||
|
version = "3.0">
|
||||||
|
<TimelineItems>
|
||||||
|
<LoggerValueHistoryTimelineItem
|
||||||
|
documentLocation = "file:///Users/ericgreene1/Desktop/IsaacSchool/Xcode/Splits/Splits/qerberymjthnrgbefvdcs.playground#CharacterRangeLen=17&CharacterRangeLoc=110&EndingColumnNumber=0&EndingLineNumber=6&StartingColumnNumber=1&StartingLineNumber=5&Timestamp=676683411.20383"
|
||||||
|
selectedRepresentationIndex = "0"
|
||||||
|
shouldTrackSuperviewWidth = "NO">
|
||||||
|
</LoggerValueHistoryTimelineItem>
|
||||||
|
</TimelineItems>
|
||||||
|
</Timeline>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue