mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 05:19:13 +00:00
fix the key, hostskeys, snippet views being black sometimes
This commit is contained in:
@@ -14,58 +14,56 @@ struct HostkeysView: View {
|
||||
ZStack {
|
||||
hostsManager.selectedTheme.background.suiColor.opacity(0.7)
|
||||
.ignoresSafeArea(.all)
|
||||
NavigationStack {
|
||||
List {
|
||||
if hostsManager.hosts.isEmpty {
|
||||
List {
|
||||
if hostsManager.hosts.isEmpty {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Looking empty 'round here...")
|
||||
.font(.title3)
|
||||
.bold()
|
||||
.padding(.bottom)
|
||||
VStack(alignment: .leading) {
|
||||
Text("Looking empty 'round here...")
|
||||
.font(.title3)
|
||||
.bold()
|
||||
Text("Connect to some hosts to collect more hostkeys!")
|
||||
.padding(.bottom)
|
||||
VStack(alignment: .leading) {
|
||||
Text("Connect to some hosts to collect more hostkeys!")
|
||||
.padding(.bottom)
|
||||
Text("ShhShell remembers hostkey fingerprints for you, and will alert you if they change.")
|
||||
.font(.subheadline)
|
||||
Text("This could be due a man in the middle attack, where a bad actor tries to impersonate your server.")
|
||||
.font(.subheadline)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ForEach($hostsManager.hosts) { $host in
|
||||
VStack(alignment: .leading) {
|
||||
if !host.name.isEmpty {
|
||||
Text("name")
|
||||
.foregroundStyle(.gray)
|
||||
.font(.caption)
|
||||
Text(host.name)
|
||||
.bold()
|
||||
}
|
||||
Text("address")
|
||||
.foregroundStyle(.gray)
|
||||
.font(.caption)
|
||||
Text(host.address)
|
||||
.bold()
|
||||
Text(host.key ?? "nil")
|
||||
}
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
|
||||
Button(/*role: .destructive*/) {
|
||||
host.key = nil
|
||||
hostsManager.updateHost(host)
|
||||
} label: {
|
||||
Label("Forget", systemImage: "trash")
|
||||
}
|
||||
Text("ShhShell remembers hostkey fingerprints for you, and will alert you if they change.")
|
||||
.font(.subheadline)
|
||||
Text("This could be due a man in the middle attack, where a bad actor tries to impersonate your server.")
|
||||
.font(.subheadline)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ForEach($hostsManager.hosts) { $host in
|
||||
VStack(alignment: .leading) {
|
||||
if !host.name.isEmpty {
|
||||
Text("name")
|
||||
.foregroundStyle(.gray)
|
||||
.font(.caption)
|
||||
Text(host.name)
|
||||
.bold()
|
||||
}
|
||||
Text("address")
|
||||
.foregroundStyle(.gray)
|
||||
.font(.caption)
|
||||
Text(host.address)
|
||||
.bold()
|
||||
Text(host.key ?? "nil")
|
||||
}
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
|
||||
Button(/*role: .destructive*/) {
|
||||
host.key = nil
|
||||
hostsManager.updateHost(host)
|
||||
} label: {
|
||||
Label("Forget", systemImage: "trash")
|
||||
}
|
||||
}
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.navigationTitle("Hostkeys")
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.navigationTitle("Hostkeys")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
HostkeysView(hostsManager: HostsManager())
|
||||
HostkeysView(hostsManager: HostsManager())
|
||||
}
|
||||
|
||||
@@ -17,59 +17,57 @@ struct KeyManagerView: View {
|
||||
ZStack {
|
||||
hostsManager.selectedTheme.background.suiColor.opacity(0.7)
|
||||
.ignoresSafeArea(.all)
|
||||
NavigationStack {
|
||||
List {
|
||||
Section() {
|
||||
ForEach(keyManager.keypairs) { kp in
|
||||
NavigationLink {
|
||||
KeyDetailView(
|
||||
hostsManager: hostsManager,
|
||||
keyManager: keyManager,
|
||||
keypair: kp
|
||||
)
|
||||
List {
|
||||
Section() {
|
||||
ForEach(keyManager.keypairs) { kp in
|
||||
NavigationLink {
|
||||
KeyDetailView(
|
||||
hostsManager: hostsManager,
|
||||
keyManager: keyManager,
|
||||
keypair: kp
|
||||
)
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "key")
|
||||
if kp.label.isEmpty {
|
||||
Text(kp.id.uuidString)
|
||||
} else {
|
||||
Text(kp.label)
|
||||
}
|
||||
Spacer()
|
||||
Text(kp.type.description)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
}
|
||||
.swipeActions(edge: .trailing) {
|
||||
Button(role: .destructive) {
|
||||
keyManager.deleteKey(kp)
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "key")
|
||||
if kp.label.isEmpty {
|
||||
Text(kp.id.uuidString)
|
||||
} else {
|
||||
Text(kp.label)
|
||||
}
|
||||
Spacer()
|
||||
Text(kp.type.description)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
}
|
||||
.swipeActions(edge: .trailing) {
|
||||
Button(role: .destructive) {
|
||||
keyManager.deleteKey(kp)
|
||||
} label: {
|
||||
Label("Delete", systemImage: "trash")
|
||||
}
|
||||
Label("Delete", systemImage: "trash")
|
||||
}
|
||||
}
|
||||
.id(keyManager.keypairs)
|
||||
}
|
||||
|
||||
CenteredLabel(title: "Generate a key", systemName: "plus")
|
||||
.onTapGesture {
|
||||
let comment = UIDevice().model + " at " + Date().formatted(date: .numeric, time: .omitted)
|
||||
keyManager.generateKey(type: .ed25519, comment: comment)
|
||||
}
|
||||
.listRowSeparator(.hidden)
|
||||
|
||||
CenteredLabel(title: "Import a key", systemName: "square.and.arrow.down")
|
||||
.onTapGesture {
|
||||
showImporter.toggle()
|
||||
}
|
||||
.sheet(isPresented: $showImporter) {
|
||||
KeyImporterView(keyManager: keyManager)
|
||||
.colorScheme(hostsManager.selectedTheme.background.luminance > 0.5 ? .light : .dark)
|
||||
}
|
||||
.id(keyManager.keypairs)
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.navigationTitle("Keys")
|
||||
|
||||
CenteredLabel(title: "Generate a key", systemName: "plus")
|
||||
.onTapGesture {
|
||||
let comment = UIDevice().model + " at " + Date().formatted(date: .numeric, time: .omitted)
|
||||
keyManager.generateKey(type: .ed25519, comment: comment)
|
||||
}
|
||||
.listRowSeparator(.hidden)
|
||||
|
||||
CenteredLabel(title: "Import a key", systemName: "square.and.arrow.down")
|
||||
.onTapGesture {
|
||||
showImporter.toggle()
|
||||
}
|
||||
.sheet(isPresented: $showImporter) {
|
||||
KeyImporterView(keyManager: keyManager)
|
||||
.colorScheme(hostsManager.selectedTheme.background.luminance > 0.5 ? .light : .dark)
|
||||
}
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.navigationTitle("Keys")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,79 +11,77 @@ struct SnippetManagerView: View {
|
||||
@ObservedObject var hostsManager: HostsManager
|
||||
@State var showSnippetAdder: Bool = false
|
||||
|
||||
var body: some View {
|
||||
var body: some View {
|
||||
ZStack {
|
||||
hostsManager.selectedTheme.background.suiColor.opacity(0.7)
|
||||
.ignoresSafeArea(.all)
|
||||
NavigationStack {
|
||||
List {
|
||||
if hostsManager.snippets.isEmpty {
|
||||
VStack(alignment: .leading) {
|
||||
Image(systemName: "questionmark.square.dashed")
|
||||
.resizable().scaledToFit()
|
||||
.frame(width: 75)
|
||||
.foregroundStyle(hostsManager.tint)
|
||||
.shadow(color: hostsManager.tint, radius: 2)
|
||||
.padding(.bottom, 10)
|
||||
Text("No Snippets")
|
||||
.font(.title)
|
||||
.monospaced()
|
||||
Text("Snippets are strings of commands that can be run at once in a terminal.")
|
||||
.padding(.bottom)
|
||||
.foregroundStyle(.gray)
|
||||
.foregroundStyle(.foreground.opacity(0.7))
|
||||
}
|
||||
}
|
||||
ForEach(hostsManager.snippets) { snip in
|
||||
VStack(alignment: .leading) {
|
||||
Text(snip.name)
|
||||
.bold()
|
||||
.foregroundStyle(.gray)
|
||||
.font(.subheadline)
|
||||
Text(snip.content)
|
||||
.lineLimit(3)
|
||||
}
|
||||
.swipeActions(edge: .trailing) {
|
||||
Button(role: .destructive) {
|
||||
hostsManager.deleteSnippet(snip)
|
||||
} label: {
|
||||
Label("Delete", systemImage: "trash")
|
||||
}
|
||||
.tint(.red)
|
||||
Button {
|
||||
hostsManager.duplicateSnippet(snip)
|
||||
} label: {
|
||||
Label("Duplicate", systemImage: "square.filled.on.square")
|
||||
}
|
||||
.tint(.blue)
|
||||
Button {
|
||||
UIPasteboard().string = snip.content
|
||||
} label: {
|
||||
Label("Copy", systemImage: "doc.on.clipboard")
|
||||
}
|
||||
.tint(.blue)
|
||||
}
|
||||
List {
|
||||
if hostsManager.snippets.isEmpty {
|
||||
VStack(alignment: .leading) {
|
||||
Image(systemName: "questionmark.square.dashed")
|
||||
.resizable().scaledToFit()
|
||||
.frame(width: 75)
|
||||
.foregroundStyle(hostsManager.tint)
|
||||
.shadow(color: hostsManager.tint, radius: 2)
|
||||
.padding(.bottom, 10)
|
||||
Text("No Snippets")
|
||||
.font(.title)
|
||||
.monospaced()
|
||||
Text("Snippets are strings of commands that can be run at once in a terminal.")
|
||||
.padding(.bottom)
|
||||
.foregroundStyle(.gray)
|
||||
.foregroundStyle(.foreground.opacity(0.7))
|
||||
}
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.sheet(isPresented: $showSnippetAdder) {
|
||||
AddSnippetView(hostsManager: hostsManager)
|
||||
.presentationDetents([.medium])
|
||||
}
|
||||
.toolbar {
|
||||
Button() {
|
||||
showSnippetAdder.toggle()
|
||||
} label: {
|
||||
Label("Add", systemImage: "plus")
|
||||
ForEach(hostsManager.snippets) { snip in
|
||||
VStack(alignment: .leading) {
|
||||
Text(snip.name)
|
||||
.bold()
|
||||
.foregroundStyle(.gray)
|
||||
.font(.subheadline)
|
||||
Text(snip.content)
|
||||
.lineLimit(3)
|
||||
}
|
||||
.swipeActions(edge: .trailing) {
|
||||
Button(role: .destructive) {
|
||||
hostsManager.deleteSnippet(snip)
|
||||
} label: {
|
||||
Label("Delete", systemImage: "trash")
|
||||
}
|
||||
.tint(.red)
|
||||
Button {
|
||||
hostsManager.duplicateSnippet(snip)
|
||||
} label: {
|
||||
Label("Duplicate", systemImage: "square.filled.on.square")
|
||||
}
|
||||
.tint(.blue)
|
||||
Button {
|
||||
UIPasteboard().string = snip.content
|
||||
} label: {
|
||||
Label("Copy", systemImage: "doc.on.clipboard")
|
||||
}
|
||||
.tint(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.sheet(isPresented: $showSnippetAdder) {
|
||||
AddSnippetView(hostsManager: hostsManager)
|
||||
.presentationDetents([.medium])
|
||||
}
|
||||
.toolbar {
|
||||
Button() {
|
||||
showSnippetAdder.toggle()
|
||||
} label: {
|
||||
Label("Add", systemImage: "plus")
|
||||
}
|
||||
}
|
||||
.navigationTitle("Snippets")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
SnippetManagerView(hostsManager: HostsManager())
|
||||
SnippetManagerView(hostsManager: HostsManager())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user