add snippets?? and deleete and duplicate etc

This commit is contained in:
neon443
2025-07-23 19:56:45 +01:00
parent d7aab6eaaa
commit e47b598c74
4 changed files with 127 additions and 9 deletions

View File

@@ -71,6 +71,7 @@
A985545D2E055D4D009051BD /* ConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A985545C2E055D4D009051BD /* ConnectionView.swift */; }; A985545D2E055D4D009051BD /* ConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A985545C2E055D4D009051BD /* ConnectionView.swift */; };
A98554612E058433009051BD /* HostsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98554602E058433009051BD /* HostsManager.swift */; }; A98554612E058433009051BD /* HostsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98554602E058433009051BD /* HostsManager.swift */; };
A98554632E0587DF009051BD /* HostsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98554622E0587DF009051BD /* HostsView.swift */; }; A98554632E0587DF009051BD /* HostsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98554622E0587DF009051BD /* HostsView.swift */; };
A9A2F4F62E3001D300D0AE9B /* AddSnippetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9A2F4F52E3001D300D0AE9B /* AddSnippetView.swift */; };
A9A587202E0BF220006B31E6 /* SwiftTerm in Frameworks */ = {isa = PBXBuildFile; productRef = A9A5871F2E0BF220006B31E6 /* SwiftTerm */; }; A9A587202E0BF220006B31E6 /* SwiftTerm in Frameworks */ = {isa = PBXBuildFile; productRef = A9A5871F2E0BF220006B31E6 /* SwiftTerm */; };
A9BA1D192E1D9AE1005BDCEF /* SwiftTerm.Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9BA1D182E1D9AE1005BDCEF /* SwiftTerm.Color.swift */; }; A9BA1D192E1D9AE1005BDCEF /* SwiftTerm.Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9BA1D182E1D9AE1005BDCEF /* SwiftTerm.Color.swift */; };
A9BA1D1E2E1EAD51005BDCEF /* SF-Mono-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = A9BA1D1C2E1EAD51005BDCEF /* SF-Mono-Bold.otf */; }; A9BA1D1E2E1EAD51005BDCEF /* SF-Mono-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = A9BA1D1C2E1EAD51005BDCEF /* SF-Mono-Bold.otf */; };
@@ -197,6 +198,7 @@
A985545C2E055D4D009051BD /* ConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionView.swift; sourceTree = "<group>"; }; A985545C2E055D4D009051BD /* ConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionView.swift; sourceTree = "<group>"; };
A98554602E058433009051BD /* HostsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostsManager.swift; sourceTree = "<group>"; }; A98554602E058433009051BD /* HostsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostsManager.swift; sourceTree = "<group>"; };
A98554622E0587DF009051BD /* HostsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostsView.swift; sourceTree = "<group>"; }; A98554622E0587DF009051BD /* HostsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostsView.swift; sourceTree = "<group>"; };
A9A2F4F52E3001D300D0AE9B /* AddSnippetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddSnippetView.swift; sourceTree = "<group>"; };
A9BA1D182E1D9AE1005BDCEF /* SwiftTerm.Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftTerm.Color.swift; sourceTree = "<group>"; }; A9BA1D182E1D9AE1005BDCEF /* SwiftTerm.Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftTerm.Color.swift; sourceTree = "<group>"; };
A9BA1D1C2E1EAD51005BDCEF /* SF-Mono-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Mono-Bold.otf"; sourceTree = "<group>"; }; A9BA1D1C2E1EAD51005BDCEF /* SF-Mono-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Mono-Bold.otf"; sourceTree = "<group>"; };
A9BA1D1D2E1EAD51005BDCEF /* SF-Mono-BoldItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Mono-BoldItalic.otf"; sourceTree = "<group>"; }; A9BA1D1D2E1EAD51005BDCEF /* SF-Mono-BoldItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Mono-BoldItalic.otf"; sourceTree = "<group>"; };
@@ -440,6 +442,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A93F283C2E2A5DCB0092B8D5 /* SnippetManagerView.swift */, A93F283C2E2A5DCB0092B8D5 /* SnippetManagerView.swift */,
A9A2F4F52E3001D300D0AE9B /* AddSnippetView.swift */,
); );
path = Snippets; path = Snippets;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -783,6 +786,7 @@
A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */, A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */,
A9D819312E102D8700442D38 /* HostkeysView.swift in Sources */, A9D819312E102D8700442D38 /* HostkeysView.swift in Sources */,
A98554552E05535F009051BD /* KeyManagerView.swift in Sources */, A98554552E05535F009051BD /* KeyManagerView.swift in Sources */,
A9A2F4F62E3001D300D0AE9B /* AddSnippetView.swift in Sources */,
A923172D2E07138000ECE1E6 /* SSHTerminalDelegate.swift in Sources */, A923172D2E07138000ECE1E6 /* SSHTerminalDelegate.swift in Sources */,
A90936882E1AC51100856059 /* Fonts.swift in Sources */, A90936882E1AC51100856059 /* Fonts.swift in Sources */,
A9FD37552E143D23005319A8 /* SecKeyConvertible.swift in Sources */, A9FD37552E143D23005319A8 /* SecKeyConvertible.swift in Sources */,

View File

@@ -35,11 +35,27 @@ class HostsManager: ObservableObject, @unchecked Sendable {
loadSnippets() loadSnippets()
} }
func addSnippet(_ toAdd: Snippet) {
snippets.append(toAdd)
saveSnippets()
}
func duplicateSnippet(_ snip: Snippet) {
guard let index = snippets.firstIndex(where: { $0.id == snip.id }) else { return }
withAnimation { snippets.insert(snip, at: index+1) }
}
func deleteSnippet(_ toDel: Snippet) {
guard let index = snippets.firstIndex(where: { $0.id == toDel.id }) else { return }
snippets.remove(at: index)
saveSnippets()
}
func loadSnippets() { func loadSnippets() {
userDefaults.synchronize() userDefaults.synchronize()
guard let data = userDefaults.data(forKey: "snippets") else { return } guard let data = userDefaults.data(forKey: "snippets") else { return }
guard let decoded = try? JSONDecoder().decode([Snippet].self, from: data) else { return } guard let decoded = try? JSONDecoder().decode([Snippet].self, from: data) else { return }
self.snippets = decoded withAnimation { self.snippets = decoded }
} }
func saveSnippets() { func saveSnippets() {

View File

@@ -0,0 +1,64 @@
//
// AddSnippetView.swift
// ShhShell
//
// Created by neon443 on 22/07/2025.
//
import SwiftUI
struct AddSnippetView: View {
@ObservedObject var hostsManager: HostsManager
@State var name: String = ""
@State var content: String = ""
var snippet: Snippet {
Snippet(name: name, content: content)
}
@Environment(\.dismiss) var dismiss
@Environment(\.colorScheme) var colorScheme
var body: some View {
NavigationStack {
List {
TextBox(label: "Name", text: $name, prompt: "")
VStack {
Text("Content")
.padding(.top)
.foregroundStyle(.gray)
.listRowSeparator(.hidden)
.multilineTextAlignment(.leading)
TextEditor(text: $content)
.autocorrectionDisabled()
.textInputAutocapitalization(.never)
.background(.black)
.clipShape(RoundedRectangle(cornerRadius: 5))
.padding(.bottom)
.frame(minHeight: 50)
}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button {
dismiss()
} label: {
Label("Cancel", systemImage: "xmark")
}
}
ToolbarItem(placement: .topBarTrailing) {
Button {
hostsManager.addSnippet(snippet)
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
}
}
}
#Preview {
AddSnippetView(hostsManager: HostsManager())
}

View File

@@ -9,16 +9,50 @@ import SwiftUI
struct SnippetManagerView: View { struct SnippetManagerView: View {
@ObservedObject var hostsManager: HostsManager @ObservedObject var hostsManager: HostsManager
@State var showSnippetAdder: Bool = false
var body: some View { var body: some View {
ForEach(hostsManager.snippets) { snip in ZStack {
Text(snip.name) hostsManager.selectedTheme.background.suiColor.opacity(0.7)
.bold() .ignoresSafeArea(.all)
.font(.subheadline) NavigationStack {
Text(snip.content) List {
} ForEach(hostsManager.snippets) { snip in
.toolbar { Group {
Text(snip.name)
.bold()
.font(.subheadline)
Text(snip.content)
}
.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)
}
}
}
.scrollContentBackground(.hidden)
.sheet(isPresented: $showSnippetAdder) {
AddSnippetView(hostsManager: hostsManager)
.presentationDetents([.medium])
}
.toolbar {
Button() {
showSnippetAdder.toggle()
} label: {
Label("Add", systemImage: "plus")
}
}
}
} }
} }
} }