mirror of
https://github.com/maxgoedjen/secretive.git
synced 2024-11-22 05:27:28 +00:00
Prompts for empty stores (#31)
* Preview content * Empty views. * Cleanup * Better sizing
This commit is contained in:
parent
8a6e72e73c
commit
e4178d35d8
@ -49,6 +49,7 @@
|
|||||||
50A5C18F240E4B4C00E2996C /* SecretKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50617DA823FCE4AB0099B055 /* SecretKit.framework */; };
|
50A5C18F240E4B4C00E2996C /* SecretKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50617DA823FCE4AB0099B055 /* SecretKit.framework */; };
|
||||||
50A5C190240E4B4C00E2996C /* SecretKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 50617DA823FCE4AB0099B055 /* SecretKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
50A5C190240E4B4C00E2996C /* SecretKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 50617DA823FCE4AB0099B055 /* SecretKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
50B8550D24138C4F009958AC /* DeleteSecretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B8550C24138C4F009958AC /* DeleteSecretView.swift */; };
|
50B8550D24138C4F009958AC /* DeleteSecretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B8550C24138C4F009958AC /* DeleteSecretView.swift */; };
|
||||||
|
50BB046B2418AAAE00D6E079 /* EmptyStoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BB046A2418AAAE00D6E079 /* EmptyStoreView.swift */; };
|
||||||
50C385A3240789E600AF2719 /* OpenSSHReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C385A2240789E600AF2719 /* OpenSSHReader.swift */; };
|
50C385A3240789E600AF2719 /* OpenSSHReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C385A2240789E600AF2719 /* OpenSSHReader.swift */; };
|
||||||
50C385A52407A76D00AF2719 /* SecretDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C385A42407A76D00AF2719 /* SecretDetailView.swift */; };
|
50C385A52407A76D00AF2719 /* SecretDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C385A42407A76D00AF2719 /* SecretDetailView.swift */; };
|
||||||
50C385A9240B636500AF2719 /* SetupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C385A8240B636500AF2719 /* SetupView.swift */; };
|
50C385A9240B636500AF2719 /* SetupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C385A8240B636500AF2719 /* SetupView.swift */; };
|
||||||
@ -199,6 +200,7 @@
|
|||||||
50A3B79D24026B9900D209EA /* SocketController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketController.swift; sourceTree = "<group>"; };
|
50A3B79D24026B9900D209EA /* SocketController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketController.swift; sourceTree = "<group>"; };
|
||||||
50A3B79F24026B9900D209EA /* Agent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Agent.swift; sourceTree = "<group>"; };
|
50A3B79F24026B9900D209EA /* Agent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Agent.swift; sourceTree = "<group>"; };
|
||||||
50B8550C24138C4F009958AC /* DeleteSecretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteSecretView.swift; sourceTree = "<group>"; };
|
50B8550C24138C4F009958AC /* DeleteSecretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteSecretView.swift; sourceTree = "<group>"; };
|
||||||
|
50BB046A2418AAAE00D6E079 /* EmptyStoreView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyStoreView.swift; sourceTree = "<group>"; };
|
||||||
50C385A2240789E600AF2719 /* OpenSSHReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OpenSSHReader.swift; path = SecretKit/Common/OpenSSH/OpenSSHReader.swift; sourceTree = SOURCE_ROOT; };
|
50C385A2240789E600AF2719 /* OpenSSHReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OpenSSHReader.swift; path = SecretKit/Common/OpenSSH/OpenSSHReader.swift; sourceTree = SOURCE_ROOT; };
|
||||||
50C385A42407A76D00AF2719 /* SecretDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretDetailView.swift; sourceTree = "<group>"; };
|
50C385A42407A76D00AF2719 /* SecretDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretDetailView.swift; sourceTree = "<group>"; };
|
||||||
50C385A8240B636500AF2719 /* SetupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupView.swift; sourceTree = "<group>"; };
|
50C385A8240B636500AF2719 /* SetupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupView.swift; sourceTree = "<group>"; };
|
||||||
@ -299,6 +301,7 @@
|
|||||||
50C385A42407A76D00AF2719 /* SecretDetailView.swift */,
|
50C385A42407A76D00AF2719 /* SecretDetailView.swift */,
|
||||||
5099A02323FD2AAA0062B6F2 /* CreateSecretView.swift */,
|
5099A02323FD2AAA0062B6F2 /* CreateSecretView.swift */,
|
||||||
50B8550C24138C4F009958AC /* DeleteSecretView.swift */,
|
50B8550C24138C4F009958AC /* DeleteSecretView.swift */,
|
||||||
|
50BB046A2418AAAE00D6E079 /* EmptyStoreView.swift */,
|
||||||
50C385A8240B636500AF2719 /* SetupView.swift */,
|
50C385A8240B636500AF2719 /* SetupView.swift */,
|
||||||
50617D8623FCE48E0099B055 /* Assets.xcassets */,
|
50617D8623FCE48E0099B055 /* Assets.xcassets */,
|
||||||
50617D8B23FCE48E0099B055 /* Main.storyboard */,
|
50617D8B23FCE48E0099B055 /* Main.storyboard */,
|
||||||
@ -733,6 +736,7 @@
|
|||||||
50C385A52407A76D00AF2719 /* SecretDetailView.swift in Sources */,
|
50C385A52407A76D00AF2719 /* SecretDetailView.swift in Sources */,
|
||||||
5099A02423FD2AAA0062B6F2 /* CreateSecretView.swift in Sources */,
|
5099A02423FD2AAA0062B6F2 /* CreateSecretView.swift in Sources */,
|
||||||
50B8550D24138C4F009958AC /* DeleteSecretView.swift in Sources */,
|
50B8550D24138C4F009958AC /* DeleteSecretView.swift in Sources */,
|
||||||
|
50BB046B2418AAAE00D6E079 /* EmptyStoreView.swift in Sources */,
|
||||||
50617D8323FCE48E0099B055 /* AppDelegate.swift in Sources */,
|
50617D8323FCE48E0099B055 /* AppDelegate.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -4,10 +4,10 @@ import SecretKit
|
|||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
|
|
||||||
@ObservedObject var storeList: SecretStoreList
|
@ObservedObject var storeList: SecretStoreList
|
||||||
@State var active: AnySecret.ID?
|
|
||||||
|
|
||||||
@State var showingDeletion = false
|
@State fileprivate var active: AnySecret.ID?
|
||||||
@State var deletingSecret: AnySecret?
|
@State fileprivate var showingDeletion = false
|
||||||
|
@State fileprivate var deletingSecret: AnySecret?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
@ -15,13 +15,25 @@ struct ContentView: View {
|
|||||||
ForEach(storeList.stores) { store in
|
ForEach(storeList.stores) { store in
|
||||||
if store.isAvailable {
|
if store.isAvailable {
|
||||||
Section(header: Text(store.name)) {
|
Section(header: Text(store.name)) {
|
||||||
ForEach(store.secrets) { secret in
|
if store.secrets.isEmpty {
|
||||||
NavigationLink(destination: SecretDetailView(secret: secret), tag: secret.id, selection: self.$active) {
|
if store is AnySecretStoreModifiable {
|
||||||
Text(secret.name)
|
NavigationLink(destination: EmptyStoreModifiableView()) {
|
||||||
}.contextMenu {
|
Text("No Secrets")
|
||||||
if store is AnySecretStoreModifiable {
|
}
|
||||||
Button(action: { self.delete(secret: secret) }) {
|
} else {
|
||||||
Text("Delete")
|
NavigationLink(destination: EmptyStoreView()) {
|
||||||
|
Text("No Secrets")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ForEach(store.secrets) { secret in
|
||||||
|
NavigationLink(destination: SecretDetailView(secret: secret), tag: secret.id, selection: self.$active) {
|
||||||
|
Text(secret.name)
|
||||||
|
}.contextMenu {
|
||||||
|
if store is AnySecretStoreModifiable {
|
||||||
|
Button(action: { self.delete(secret: secret) }) {
|
||||||
|
Text("Delete")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,9 +65,14 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//struct ContentView_Previews: PreviewProvider {
|
struct ContentView_Previews: PreviewProvider {
|
||||||
// static var previews: some View {
|
static var previews: some View {
|
||||||
// ContentView(store: Preview.Store(numberOfRandomSecrets: 10))
|
Group {
|
||||||
// }
|
ContentView(storeList: Preview.storeList(stores: [Preview.Store(numberOfRandomSecrets: 0)], modifiableStores: [Preview.StoreModifiable(numberOfRandomSecrets: 0)]))
|
||||||
//}
|
ContentView(storeList: Preview.storeList(stores: [Preview.Store()], modifiableStores: [Preview.StoreModifiable()]))
|
||||||
|
ContentView(storeList: Preview.storeList(stores: [Preview.Store()]))
|
||||||
|
ContentView(storeList: Preview.storeList(modifiableStores: [Preview.StoreModifiable()]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
53
Secretive/EmptyStoreView.swift
Normal file
53
Secretive/EmptyStoreView.swift
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct EmptyStoreView: View {
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
Text("No Secrets").bold()
|
||||||
|
Text("Use your Smart Card's management tool to create a secret.")
|
||||||
|
Text("Secretive only supports Elliptic Curve keys.")
|
||||||
|
}.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EmptyStoreModifiableView: View {
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
GeometryReader { windowGeometry in
|
||||||
|
VStack {
|
||||||
|
GeometryReader { g in
|
||||||
|
Path { path in
|
||||||
|
path.move(to: CGPoint(x: g.size.width / 2, y: g.size.height))
|
||||||
|
path.addCurve(to:
|
||||||
|
CGPoint(x: g.size.width * (3/4), y: g.size.height * (1/2)), control1:
|
||||||
|
CGPoint(x: g.size.width / 2, y: g.size.height * (1/2)), control2:
|
||||||
|
CGPoint(x: g.size.width * (3/4), y: g.size.height * (1/2)))
|
||||||
|
path.addCurve(to:
|
||||||
|
CGPoint(x: g.size.width, y: 0), control1:
|
||||||
|
CGPoint(x: g.size.width, y: g.size.height * (1/2)), control2:
|
||||||
|
CGPoint(x: g.size.width, y: 0))
|
||||||
|
}.stroke(style: StrokeStyle(lineWidth: 5, lineCap: .round))
|
||||||
|
Path { path in
|
||||||
|
path.move(to: CGPoint(x: g.size.width - 10, y: 0))
|
||||||
|
path.addLine(to: CGPoint(x: g.size.width, y: -10))
|
||||||
|
path.addLine(to: CGPoint(x: g.size.width + 10, y: 0))
|
||||||
|
}.fill()
|
||||||
|
}.frame(height: (windowGeometry.size.height/2) - 20).padding()
|
||||||
|
Text("No Secrets").bold()
|
||||||
|
Text("Create a new one by clicking here.")
|
||||||
|
Spacer()
|
||||||
|
}.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EmptyStoreModifiableView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
Group {
|
||||||
|
EmptyStoreView()
|
||||||
|
EmptyStoreModifiableView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,15 +23,15 @@ extension Preview {
|
|||||||
|
|
||||||
let isAvailable = true
|
let isAvailable = true
|
||||||
let id = UUID()
|
let id = UUID()
|
||||||
let name = "Preview Store"
|
var name: String { "Preview Store" }
|
||||||
@Published var secrets: [Secret] = []
|
@Published var secrets: [Secret] = []
|
||||||
|
|
||||||
init(secrets: [Secret]) {
|
init(secrets: [Secret]) {
|
||||||
self.secrets.append(contentsOf: secrets)
|
self.secrets.append(contentsOf: secrets)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(numberOfRandomSecrets: Int) {
|
init(numberOfRandomSecrets: Int = 5) {
|
||||||
let new = (0...numberOfRandomSecrets).map { Secret(name: String(describing: $0)) }
|
let new = (0..<numberOfRandomSecrets).map { Secret(name: String(describing: $0)) }
|
||||||
self.secrets.append(contentsOf: new)
|
self.secrets.append(contentsOf: new)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,9 +39,32 @@ extension Preview {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
func delete(secret: Preview.Secret) throws {
|
}
|
||||||
|
|
||||||
|
class StoreModifiable: Store, SecretStoreModifiable {
|
||||||
|
|
||||||
|
override var name: String { "Modifiable Preview Store" }
|
||||||
|
|
||||||
|
func create(name: String, requiresAuthentication: Bool) throws {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func delete(secret: Preview.Secret) throws {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Preview {
|
||||||
|
|
||||||
|
static func storeList(stores: [Store] = [], modifiableStores: [StoreModifiable] = []) -> SecretStoreList {
|
||||||
|
let list = SecretStoreList()
|
||||||
|
for store in stores {
|
||||||
|
list.add(store: store)
|
||||||
|
}
|
||||||
|
for storeModifiable in modifiableStores {
|
||||||
|
list.add(store: storeModifiable)
|
||||||
|
}
|
||||||
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user