Add preliminary onboarding views
This commit is contained in:
@@ -359,6 +359,7 @@
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -415,6 +416,7 @@
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
|
||||
57
Yeti/Assets/Localizable.xcstrings
Normal file
57
Yeti/Assets/Localizable.xcstrings
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"sourceLanguage" : "en",
|
||||
"strings" : {
|
||||
"Add a key" : {
|
||||
"comment" : "Button to add a key."
|
||||
},
|
||||
"Add your key" : {
|
||||
"comment" : "Title of view to add the user’s private key."
|
||||
},
|
||||
"Approve basic actions" : {
|
||||
"comment" : "Name of event signing policy that approves basic actions."
|
||||
},
|
||||
"Create a key" : {
|
||||
"comment" : "Button to create a key."
|
||||
},
|
||||
"Done" : {
|
||||
"comment" : "Button to go to the next view that adds the user's entered private key."
|
||||
},
|
||||
"Got it!" : {
|
||||
"comment" : "Button to go to the next view that adds the user’s entered private key."
|
||||
},
|
||||
"Hooo-raaaayyy!" : {
|
||||
"comment" : "Title of view that confirms the user’s selection of the signing policy."
|
||||
},
|
||||
"Manually approve each app" : {
|
||||
"comment" : "Name of event signing policy that requires manual approval to sign each event."
|
||||
},
|
||||
"Next" : {
|
||||
"comment" : "Button to go to the next view that adds the user’s entered private key."
|
||||
},
|
||||
"nsec / private key" : {
|
||||
"comment" : "Prompt asking user to enter in a Nostr private key."
|
||||
},
|
||||
"Recommended for most people. This policy will minimize the number of interruptions during your app usage." : {
|
||||
"comment" : "Description of event signing policy that approves basic actions."
|
||||
},
|
||||
"Recommended for privacy-minded people who would like control over each app.\nChoosing this policy will prompt you to set a preference every time you try a new app." : {
|
||||
"comment" : "Description of event signing policy that requires manual approval to sign each event."
|
||||
},
|
||||
"Select a signing policy" : {
|
||||
"comment" : "Title of view to select a signing policy."
|
||||
},
|
||||
"Yeti: Nostr Helper" : {
|
||||
"comment" : "Application title."
|
||||
},
|
||||
"You’re all set! I’ll take care of most of the approval for you.\nIf I see an event I don’t recognize, I’ll ask you to review it." : {
|
||||
"comment" : "Description of what the user should expect after selecting the basic signing policy."
|
||||
},
|
||||
"You’re set for now. You’ll need to come back here with every new app and approve some nostr events." : {
|
||||
"comment" : "Description of what the user should expect after selecting the manual signing policy."
|
||||
},
|
||||
"Your private key is stored locally. Only you can see it." : {
|
||||
"comment" : "Footer text explaining that the private key is stored locally and only the user can see it."
|
||||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// Yeti
|
||||
//
|
||||
// Created by Terry Yiu on 1/19/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SwiftData
|
||||
|
||||
struct ContentView: View {
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
@Query private var items: [Item]
|
||||
|
||||
var body: some View {
|
||||
NavigationSplitView {
|
||||
List {
|
||||
ForEach(items) { item in
|
||||
NavigationLink {
|
||||
Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
|
||||
} label: {
|
||||
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
|
||||
}
|
||||
}
|
||||
.onDelete(perform: deleteItems)
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
EditButton()
|
||||
}
|
||||
ToolbarItem {
|
||||
Button(action: addItem) {
|
||||
Label("Add Item", systemImage: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
} detail: {
|
||||
Text("Select an item")
|
||||
}
|
||||
}
|
||||
|
||||
private func addItem() {
|
||||
withAnimation {
|
||||
let newItem = Item(timestamp: Date())
|
||||
modelContext.insert(newItem)
|
||||
}
|
||||
}
|
||||
|
||||
private func deleteItems(offsets: IndexSet) {
|
||||
withAnimation {
|
||||
for index in offsets {
|
||||
modelContext.delete(items[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
.modelContainer(for: Item.self, inMemory: true)
|
||||
}
|
||||
53
Yeti/Views/AddKeyView.swift
Normal file
53
Yeti/Views/AddKeyView.swift
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// AddKeyView.swift
|
||||
// Yeti
|
||||
//
|
||||
// Created by Terry Yiu on 1/19/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct AddKeyView: View {
|
||||
@State private var key: String = ""
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
Form {
|
||||
Text("Add your key", comment: "Title of view to add the user’s private key.")
|
||||
.font(.title)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
|
||||
.listRowInsets(EdgeInsets())
|
||||
.background(Color(UIColor.systemGroupedBackground))
|
||||
|
||||
Section(
|
||||
content: {
|
||||
SecureField(
|
||||
String(
|
||||
localized: "nsec / private key",
|
||||
comment: "Prompt asking user to enter in a Nostr private key."
|
||||
),
|
||||
text: $key
|
||||
)
|
||||
},
|
||||
footer: {
|
||||
Text(
|
||||
"Your private key is stored locally. Only you can see it.",
|
||||
comment:
|
||||
"""
|
||||
Footer text explaining that the private key is stored locally and only the user can see it.
|
||||
"""
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
NavigationLink(destination: SigningPolicySelectionView()) {
|
||||
Text("Next", comment: "Button to go to the next view that adds the user’s entered private key.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
AddKeyView()
|
||||
}
|
||||
46
Yeti/Views/ContentView.swift
Normal file
46
Yeti/Views/ContentView.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// Yeti
|
||||
//
|
||||
// Created by Terry Yiu on 1/19/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SwiftData
|
||||
|
||||
struct ContentView: View {
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
Text("Yeti: Nostr Helper", comment: "Application title.")
|
||||
|
||||
HStack {
|
||||
NavigationLink(
|
||||
destination: {
|
||||
AddKeyView()
|
||||
},
|
||||
label: {
|
||||
Text("Add a key", comment: "Button to add a key.")
|
||||
}
|
||||
)
|
||||
.buttonStyle(.bordered)
|
||||
|
||||
NavigationLink(
|
||||
destination: {
|
||||
AddKeyView()
|
||||
},
|
||||
label: {
|
||||
Text("Create a key", comment: "Button to create a key.")
|
||||
}
|
||||
)
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
.modelContainer(for: Item.self, inMemory: true)
|
||||
}
|
||||
41
Yeti/Views/SigningPolicyConfirmationView.swift
Normal file
41
Yeti/Views/SigningPolicyConfirmationView.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// SigningPolicyConfirmationView.swift
|
||||
// Yeti
|
||||
//
|
||||
// Created by Terry Yiu on 1/20/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct SigningPolicyConfirmationView: View {
|
||||
let signingPolicy: SigningPolicy
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Text("Hooo-raaaayyy!", comment: "Title of view that confirms the user’s selection of the signing policy.")
|
||||
.font(.title)
|
||||
|
||||
switch signingPolicy {
|
||||
case .basic:
|
||||
Text(
|
||||
"""
|
||||
You’re all set! I’ll take care of most of the approval for you.
|
||||
If I see an event I don’t recognize, I’ll ask you to review it.
|
||||
""",
|
||||
comment: "Description of what the user should expect after selecting the basic signing policy."
|
||||
)
|
||||
case .manual:
|
||||
Text(
|
||||
"""
|
||||
You’re set for now. You’ll need to come back here with every new app and approve some nostr events.
|
||||
""",
|
||||
comment: "Description of what the user should expect after selecting the manual signing policy."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
SigningPolicyConfirmationView(signingPolicy: .basic)
|
||||
}
|
||||
95
Yeti/Views/SigningPolicySelectionView.swift
Normal file
95
Yeti/Views/SigningPolicySelectionView.swift
Normal file
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// SigningPolicySelectionView.swift
|
||||
// Yeti
|
||||
//
|
||||
// Created by Terry Yiu on 1/20/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct SigningPolicySelectionView: View {
|
||||
@State var signingPolicy: SigningPolicy = .basic
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
Form {
|
||||
Text("Select a signing policy", comment: "Title of view to select a signing policy.")
|
||||
.font(.title)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
|
||||
.listRowInsets(EdgeInsets())
|
||||
.background(Color(UIColor.systemGroupedBackground))
|
||||
|
||||
Section(
|
||||
content: {
|
||||
Picker(
|
||||
selection: $signingPolicy,
|
||||
content: {
|
||||
ForEach(SigningPolicy.allCases, id: \.self) { signingPolicy in
|
||||
Text(signingPolicy.name)
|
||||
.tag(signingPolicy)
|
||||
}
|
||||
},
|
||||
label: {
|
||||
EmptyView()
|
||||
}
|
||||
)
|
||||
.pickerStyle(.inline)
|
||||
},
|
||||
footer: {
|
||||
Text(signingPolicy.description)
|
||||
}
|
||||
)
|
||||
|
||||
NavigationLink(destination: SigningPolicyConfirmationView(signingPolicy: signingPolicy)) {
|
||||
Text("Done", comment: "Button to go to the next view that adds the user’s entered private key.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum SigningPolicy: CaseIterable {
|
||||
case basic
|
||||
case manual
|
||||
|
||||
var name: String {
|
||||
switch self {
|
||||
case .basic:
|
||||
return String(
|
||||
localized: "Approve basic actions",
|
||||
comment: "Name of event signing policy that approves basic actions."
|
||||
)
|
||||
case .manual:
|
||||
return String(
|
||||
localized: "Manually approve each app",
|
||||
comment: "Name of event signing policy that requires manual approval to sign each event."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .basic:
|
||||
return String(
|
||||
localized:
|
||||
"""
|
||||
Recommended for most people. This policy will minimize the number of interruptions during your app usage.
|
||||
""",
|
||||
comment: "Description of event signing policy that approves basic actions."
|
||||
)
|
||||
case .manual:
|
||||
return String(
|
||||
localized:
|
||||
"""
|
||||
Recommended for privacy-minded people who would like control over each app.
|
||||
Choosing this policy will prompt you to set a preference every time you try a new app.
|
||||
""",
|
||||
comment: "Description of event signing policy that requires manual approval to sign each event."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
SigningPolicySelectionView()
|
||||
}
|
||||
Reference in New Issue
Block a user