add settingsview

add setting struct
add export/importhosts fumction
This commit is contained in:
neon443
2025-08-19 16:48:36 +01:00
parent 171843c9a3
commit 78bdb60350
6 changed files with 112 additions and 19 deletions

View File

@@ -19,6 +19,8 @@
A90936B02E1AE9AB00856059 /* MesloLGS NF Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A90936A12E1AE9AB00856059 /* MesloLGS NF Italic.ttf */; }; A90936B02E1AE9AB00856059 /* MesloLGS NF Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A90936A12E1AE9AB00856059 /* MesloLGS NF Italic.ttf */; };
A90B38322E3E8FC9002B56FC /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90B38312E3E8FC9002B56FC /* AboutView.swift */; }; A90B38322E3E8FC9002B56FC /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90B38312E3E8FC9002B56FC /* AboutView.swift */; };
A90B38342E3EA046002B56FC /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90B38332E3EA046002B56FC /* Bundle.swift */; }; A90B38342E3EA046002B56FC /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90B38332E3EA046002B56FC /* Bundle.swift */; };
A91D27C72E54B97E00620B29 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A91D27C62E54B97E00620B29 /* SettingsView.swift */; };
A91D27CA2E54BED300620B29 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A91D27C92E54BED300620B29 /* AppSettings.swift */; };
A923172A2E07113100ECE1E6 /* TerminalController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92317292E07113100ECE1E6 /* TerminalController.swift */; }; A923172A2E07113100ECE1E6 /* TerminalController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92317292E07113100ECE1E6 /* TerminalController.swift */; };
A923172D2E07138000ECE1E6 /* SSHTerminalDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172C2E07138000ECE1E6 /* SSHTerminalDelegate.swift */; }; A923172D2E07138000ECE1E6 /* SSHTerminalDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172C2E07138000ECE1E6 /* SSHTerminalDelegate.swift */; };
A923172F2E08851200ECE1E6 /* ShellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172E2E08851200ECE1E6 /* ShellView.swift */; }; A923172F2E08851200ECE1E6 /* ShellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172E2E08851200ECE1E6 /* ShellView.swift */; };
@@ -149,6 +151,8 @@
A90936A52E1AE9AB00856059 /* SF-Mono-RegularItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Mono-RegularItalic.otf"; sourceTree = "<group>"; }; A90936A52E1AE9AB00856059 /* SF-Mono-RegularItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Mono-RegularItalic.otf"; sourceTree = "<group>"; };
A90B38312E3E8FC9002B56FC /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; }; A90B38312E3E8FC9002B56FC /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
A90B38332E3EA046002B56FC /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; }; A90B38332E3EA046002B56FC /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; };
A91D27C62E54B97E00620B29 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
A91D27C92E54BED300620B29 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; };
A92317292E07113100ECE1E6 /* TerminalController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalController.swift; sourceTree = "<group>"; }; A92317292E07113100ECE1E6 /* TerminalController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalController.swift; sourceTree = "<group>"; };
A923172C2E07138000ECE1E6 /* SSHTerminalDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHTerminalDelegate.swift; sourceTree = "<group>"; }; A923172C2E07138000ECE1E6 /* SSHTerminalDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHTerminalDelegate.swift; sourceTree = "<group>"; };
A923172E2E08851200ECE1E6 /* ShellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ShellView.swift; path = ShhShell/Views/Terminal/ShellView.swift; sourceTree = SOURCE_ROOT; }; A923172E2E08851200ECE1E6 /* ShellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ShellView.swift; path = ShhShell/Views/Terminal/ShellView.swift; sourceTree = SOURCE_ROOT; };
@@ -335,6 +339,14 @@
path = About; path = About;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A91D27C82E54BEC700620B29 /* Settings */ = {
isa = PBXGroup;
children = (
A91D27C92E54BED300620B29 /* AppSettings.swift */,
);
path = Settings;
sourceTree = "<group>";
};
A923172B2E0712F200ECE1E6 /* Terminal */ = { A923172B2E0712F200ECE1E6 /* Terminal */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -381,6 +393,7 @@
A9D8192A2E0E904900442D38 /* Themes */, A9D8192A2E0E904900442D38 /* Themes */,
A90936862E1AC4C600856059 /* Fonts */, A90936862E1AC4C600856059 /* Fonts */,
A93F283F2E2A5EC80092B8D5 /* Snippets */, A93F283F2E2A5EC80092B8D5 /* Snippets */,
A91D27C82E54BEC700620B29 /* Settings */,
A9C060E92E357FC400CA9374 /* Misc */, A9C060E92E357FC400CA9374 /* Misc */,
A92538D32DEE0749007E0A18 /* Views */, A92538D32DEE0749007E0A18 /* Views */,
A90936852E1AC33C00856059 /* Info.plist */, A90936852E1AC33C00856059 /* Info.plist */,
@@ -417,6 +430,7 @@
A9D8192B2E0E9EA400442D38 /* Themes */, A9D8192B2E0E9EA400442D38 /* Themes */,
A9485C742E1AF58C00209824 /* Fonts */, A9485C742E1AF58C00209824 /* Fonts */,
A93F283E2E2A5DDE0092B8D5 /* Snippets */, A93F283E2E2A5DDE0092B8D5 /* Snippets */,
A9FFD4ED2E53B032004CC4B8 /* Settings */,
A90B38302E3E8FBA002B56FC /* About */, A90B38302E3E8FBA002B56FC /* About */,
A96C6B032E0C523600F377FE /* Misc */, A96C6B032E0C523600F377FE /* Misc */,
); );
@@ -620,6 +634,14 @@
path = KeychainLayer; path = KeychainLayer;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A9FFD4ED2E53B032004CC4B8 /* Settings */ = {
isa = PBXGroup;
children = (
A91D27C62E54B97E00620B29 /* SettingsView.swift */,
);
path = Settings;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@@ -798,6 +820,7 @@
A9485C782E1BFA5000209824 /* ThemeEditorView.swift in Sources */, A9485C782E1BFA5000209824 /* ThemeEditorView.swift in Sources */,
A93143C62DF61FE300FCD5DB /* ViewModifiers.swift in Sources */, A93143C62DF61FE300FCD5DB /* ViewModifiers.swift in Sources */,
A98554632E0587DF009051BD /* HostsView.swift in Sources */, A98554632E0587DF009051BD /* HostsView.swift in Sources */,
A91D27CA2E54BED300620B29 /* AppSettings.swift in Sources */,
A96C6A8A2E0C0B1100F377FE /* SSHState.swift in Sources */, A96C6A8A2E0C0B1100F377FE /* SSHState.swift in Sources */,
A9FD37692E16A6BF005319A8 /* ShellTabView.swift in Sources */, A9FD37692E16A6BF005319A8 /* ShellTabView.swift in Sources */,
A9DA97732E0D40C100142DDC /* HostSymbolPreview.swift in Sources */, A9DA97732E0D40C100142DDC /* HostSymbolPreview.swift in Sources */,
@@ -806,6 +829,7 @@
A90B38342E3EA046002B56FC /* Bundle.swift in Sources */, A90B38342E3EA046002B56FC /* Bundle.swift in Sources */,
A9FD376B2E16DABF005319A8 /* AnsiPickerView.swift in Sources */, A9FD376B2E16DABF005319A8 /* AnsiPickerView.swift in Sources */,
A9C060ED2E3FBCD000CA9374 /* SnippetPicker.swift in Sources */, A9C060ED2E3FBCD000CA9374 /* SnippetPicker.swift in Sources */,
A91D27C72E54B97E00620B29 /* SettingsView.swift in Sources */,
A96BE6A62E113DB000C0FEE9 /* ColorCodable.swift in Sources */, A96BE6A62E113DB000C0FEE9 /* ColorCodable.swift in Sources */,
A92538C82DEE0742007E0A18 /* ContentView.swift in Sources */, A92538C82DEE0742007E0A18 /* ContentView.swift in Sources */,
A9231A572E52041500974753 /* HostPreview.swift in Sources */, A9231A572E52041500974753 /* HostPreview.swift in Sources */,

View File

@@ -32,6 +32,7 @@ class HostsManager: ObservableObject, @unchecked Sendable {
init(previews: Bool = false) { init(previews: Bool = false) {
loadHosts() loadHosts()
exportHosts()
loadThemes() loadThemes()
loadFonts() loadFonts()
loadSnippets() loadSnippets()
@@ -306,6 +307,16 @@ class HostsManager: ObservableObject, @unchecked Sendable {
} }
} }
func exportHosts() {
guard let encoded = try? JSONEncoder().encode(hosts) else { return }
print(encoded.base64EncodedString())
}
func importHosts(_ data: Data) {
guard let decoedd = try? JSONDecoder().decode([Host].self, from: data) else { return }
hosts = decoedd
}
func removeHost(_ host: Host) { func removeHost(_ host: Host) {
if let index = hosts.firstIndex(where: { $0.id == host.id }) { if let index = hosts.firstIndex(where: { $0.id == host.id }) {
let _ = withAnimation { hosts.remove(at: index) } let _ = withAnimation { hosts.remove(at: index) }

View File

@@ -381,16 +381,8 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
let data = Data(bytes: buffer, count: Int(nbytes)) let data = Data(bytes: buffer, count: Int(nbytes))
if let string = String(data: data, encoding: .utf8) { if let string = String(data: data, encoding: .utf8) {
#if DEBUG
// print(String(data: Data(bytes: buffer, count: Int(nbytes)), encoding: .utf8)!)
#endif
Task { @MainActor in Task { @MainActor in
scrollback.append(string) scrollback.append(string)
// if scrollbackSize/1024/1024 > 10 {
// scrollback.remove(at: 0)
// } else {
// scrollbackSize += Double(string.lengthOfBytes(using: .utf8))
// }
} }
return string return string
} }
@@ -420,19 +412,8 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
guard ssh_channel_is_eof(channel) == 0 else { throw .backendError("Channel is EOF") } guard ssh_channel_is_eof(channel) == 0 else { throw .backendError("Channel is EOF") }
ssh_channel_change_pty_size(channel, Int32(toCols), Int32(toRows)) ssh_channel_change_pty_size(channel, Int32(toCols), Int32(toRows))
// print("resized tty to \(toRows)rows and \(toCols)cols")
} }
// func prettyScrollbackSize() -> String {
// if (scrollbackSize/1024/1024) > 1 {
// return "\(scrollbackSize/1024/1024) MiB scrollback"
// } else if scrollbackSize/1024 > 1 {
// return "\(scrollbackSize/1024) KiB scrollback"
// } else {
// return "\(scrollbackSize) B scrollback"
// }
// }
private func logSshGetError() { private func logSshGetError() {
guard var session = self.session else { return } guard var session = self.session else { return }
logger.critical("\(String(cString: ssh_get_error(&session)))") logger.critical("\(String(cString: ssh_get_error(&session)))")

View File

@@ -0,0 +1,34 @@
//
// AppSettings.swift
// ShhShell
//
// Created by neon443 on 19/08/2025.
//
import Foundation
struct AppSettings: Codable, Sendable {
var scrollback: Int = 1_000
var cursorStyle: CursorStyle = .block
var locationPersist: Bool = false
var bellSound: Bool = false
var bellHaptic: Bool = true
var caffeinate: Bool = false
var filter: TerminalFilter = .none
var appIcon: AppIcon = .regular
}
enum CursorStyle: Codable {
case block
case bar
}
enum TerminalFilter: Codable {
case none
case crt
}
enum AppIcon: Codable {
case regular
case blueprint
}

View File

@@ -69,6 +69,11 @@ struct ContentView: View {
} }
Section { Section {
NavigationLink {
SettingsView(hostsManager: hostsManager, keyManager: keyManager)
} label: {
Label("Settings", systemImage: "gear")
}
NavigationLink { NavigationLink {
AboutView(hostsManager: hostsManager) AboutView(hostsManager: hostsManager)
} label: { } label: {

View File

@@ -0,0 +1,38 @@
//
// SettingsView.swift
// ShhShell
//
// Created by neon443 on 19/08/2025.
//
import SwiftUI
struct SettingsView: View {
@ObservedObject var hostsManager: HostsManager
@ObservedObject var keyManager: KeyManager
var body: some View {
ZStack {
hostsManager.selectedTheme.background.suiColor.opacity(0.7)
.ignoresSafeArea(.all)
List {
Section("Terminal") {
Label("Scrollback", systemImage: "scroll")
HStack {
Slider(value: .constant(0), in: 1_000...50_000, step: 1_000)
Text("\()")
}
}
}
.listStyle(.sidebar)
.scrollContentBackground(.hidden)
}
}
}
#Preview {
SettingsView(
hostsManager: HostsManager(),
keyManager: KeyManager()
)
}