aboutsummaryrefslogtreecommitdiff
path: root/LibreSecrets
diff options
context:
space:
mode:
authorChristian Cleberg <hello@cleberg.net>2024-01-13 20:53:07 -0600
committerChristian Cleberg <hello@cleberg.net>2024-01-13 20:53:07 -0600
commitd26ff0c96da53faa850b02176f8fc3dce3fdfd0c (patch)
treeb23a36ec33c61ff378ba6020f479ec9a84c593b4 /LibreSecrets
parent39eb969101d2e9b4136da4c1ced3cfc99344b8e6 (diff)
downloadlibre-secrets-d26ff0c96da53faa850b02176f8fc3dce3fdfd0c.tar.gz
libre-secrets-d26ff0c96da53faa850b02176f8fc3dce3fdfd0c.tar.bz2
libre-secrets-d26ff0c96da53faa850b02176f8fc3dce3fdfd0c.zip
fix: refactor project to LibreSecrets
Diffstat (limited to 'LibreSecrets')
-rw-r--r--LibreSecrets/ContentView.swift164
1 files changed, 159 insertions, 5 deletions
diff --git a/LibreSecrets/ContentView.swift b/LibreSecrets/ContentView.swift
index c4de5a2..25c34c4 100644
--- a/LibreSecrets/ContentView.swift
+++ b/LibreSecrets/ContentView.swift
@@ -2,18 +2,172 @@
// ContentView.swift
// LibreSecrets
//
-// Created by Christian Cleberg on 2024-01-13.
+// Created by Christian Cleberg on 2024-01-10.
//
import SwiftUI
+import UniformTypeIdentifiers
struct ContentView: View {
+ // Create initial variables
+ @State private var speed = 50.0
+ @State private var isEditing = false
+ @State private var enableNumbers = false
+ @State private var enableSpecial = false
+ @State private var enableCapitalization = false
+ @State private var isCopied: Bool = false
+
+ // Create Picker options to choose password type
+ enum PasswordType: String, CaseIterable, Identifiable {
+ case random, xkcd
+ var id: Self { self }
+ }
+ @State private var passwordType: PasswordType = .random
+
+ // Generates a random string of alphanumeric, numeric (optional), and special (optional) characters per user-determined length
+ func randomString(length: Int) -> String {
+ var characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ if enableNumbers {
+ characters.append("0123456789")
+ }
+ if enableSpecial {
+ characters.append("!%&()*+,-./:;<=>?@[^_`{|}~")
+ }
+ return String((0..<length).map{ _ in characters.randomElement()! })
+ }
+
+ // Generates a series of words separated by "-", including a digit (optional), and capitalization (optional) per user-determined length
+ func randomWord(length: Int) -> String {
+ var randomLine = ""
+ for i in 1...length {
+ if let wordsFilePath = Bundle.main.path(forResource: "words", ofType: nil) {
+ do {
+ let wordsString = try String(contentsOfFile: wordsFilePath)
+ let wordLines = wordsString.components(separatedBy: .newlines)
+ if enableCapitalization {
+ randomLine += wordLines[numericCast(arc4random_uniform(numericCast(wordLines.count)))].capitalized
+ } else {
+ randomLine += wordLines[numericCast(arc4random_uniform(numericCast(wordLines.count)))]
+ }
+ if i != length {
+ randomLine += "-"
+ }
+ if i == length && enableNumbers {
+ randomLine += String(Int.random(in: 0..<9))
+ }
+ } catch { // contentsOfFile throws an error
+ print("Error: \(error)")
+ }
+ }
+ }
+ return randomLine
+ }
+
+ // Generate the view
var body: some View {
VStack {
- Image(systemName: "globe")
- .imageScale(.large)
- .foregroundStyle(.tint)
- Text("Hello, world!")
+
+ VStack {
+ Text("Password Generator")
+ .font(.largeTitle)
+ Text("Save your password somewhere safe!")
+ .font(.caption)
+ }
+
+ Form {
+ Section(header: Text("Password Type")) {
+ Picker("Type", selection: $passwordType) {
+ Text("Random").tag(PasswordType.random)
+ Text("XKCD").tag(PasswordType.xkcd)
+ }
+ }
+
+ if passwordType == .random {
+ Section(header: Text("Random Password")) {
+ Slider(
+ value: $speed,
+ in: 8...36,
+ step: 1
+ ) {
+ Text("Characters")
+ } minimumValueLabel: {
+ Text("8")
+ } maximumValueLabel: {
+ Text("36")
+ } onEditingChanged: { editing in
+ isEditing = editing
+ }
+ .onAppear {
+ self.speed = 12
+ }
+ Toggle("Numbers", isOn: $enableNumbers)
+ Toggle("Special Characters", isOn: $enableSpecial)
+ }
+
+ let password = randomString(length: Int(speed))
+
+ Text("\(password)")
+ .onTapGesture {
+ let clipboard = UIPasteboard.general
+ clipboard.setValue(password, forPasteboardType: UTType.plainText.identifier)
+ withAnimation {
+ isCopied = true
+ }
+ DispatchQueue.main.asyncAfter(wallDeadline: .now() + 3) {
+ withAnimation {
+ isCopied = false
+ }
+ }
+ }
+ } else {
+ Section(header: Text("XKCD Password")) {
+ Slider(
+ value: $speed,
+ in: 1...10,
+ step: 1
+ ) {
+ Text("Words")
+ } minimumValueLabel: {
+ Text("1")
+ } maximumValueLabel: {
+ Text("10")
+ } onEditingChanged: { editing in
+ isEditing = editing
+ }
+ .onAppear {
+ self.speed = 4
+ }
+ Toggle("Numbers", isOn: $enableNumbers)
+ Toggle("Capitalize Words", isOn: $enableCapitalization)
+ }
+
+ let password = randomWord(length: Int(speed))
+
+ Text("\(password)")
+ .onTapGesture {
+ let clipboard = UIPasteboard.general
+ clipboard.setValue(password, forPasteboardType: UTType.plainText.identifier)
+ withAnimation {
+ isCopied = true
+ }
+ DispatchQueue.main.asyncAfter(wallDeadline: .now() + 3) {
+ withAnimation {
+ isCopied = false
+ }
+ }
+ }
+ }
+ }
+
+ if isCopied {
+ Text("Copied successfully!")
+ .foregroundColor(.white)
+ .bold()
+ .font(.footnote)
+ .frame(width: 140, height: 30)
+ .background(Color.indigo.cornerRadius(7))
+ }
+
}
.padding()
}