diff --git a/ShhShell.xcodeproj/project.pbxproj b/ShhShell.xcodeproj/project.pbxproj index eafaf95..0c30221 100644 --- a/ShhShell.xcodeproj/project.pbxproj +++ b/ShhShell.xcodeproj/project.pbxproj @@ -40,6 +40,7 @@ A9C4140C2E096DB7005E3047 /* SSHError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C4140B2E096DB7005E3047 /* SSHError.swift */; }; A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */; }; A9D819292E0E904200442D38 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D819282E0E904200442D38 /* Theme.swift */; }; + A9D8192D2E0E9EB500442D38 /* ThemesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D8192C2E0E9EB500442D38 /* ThemesView.swift */; }; A9DA97712E0D30ED00142DDC /* HostSymbol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DA97702E0D30ED00142DDC /* HostSymbol.swift */; }; A9DA97732E0D40C100142DDC /* SymbolPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DA97722E0D40C100142DDC /* SymbolPreview.swift */; }; /* End PBXBuildFile section */ @@ -114,6 +115,7 @@ A9C4140B2E096DB7005E3047 /* SSHError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHError.swift; sourceTree = ""; }; A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHHandler.swift; sourceTree = ""; }; A9D819282E0E904200442D38 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; + A9D8192C2E0E9EB500442D38 /* ThemesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemesView.swift; sourceTree = ""; }; A9DA97702E0D30ED00142DDC /* HostSymbol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostSymbol.swift; sourceTree = ""; }; A9DA97722E0D40C100142DDC /* SymbolPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SymbolPreview.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -217,6 +219,7 @@ isa = PBXGroup; children = ( A92538C52DEE0742007E0A18 /* ContentView.swift */, + A9D8192B2E0E9EA400442D38 /* Themes */, A98554532E05534F009051BD /* Keys */, A96C6B042E0C523E00F377FE /* Hosts */, A923172B2E0712F200ECE1E6 /* Terminal */, @@ -321,6 +324,14 @@ path = Themes; sourceTree = ""; }; + A9D8192B2E0E9EA400442D38 /* Themes */ = { + isa = PBXGroup; + children = ( + A9D8192C2E0E9EB500442D38 /* ThemesView.swift */, + ); + path = Themes; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -467,6 +478,7 @@ A923172F2E08851200ECE1E6 /* ShellView.swift in Sources */, A985545F2E056EDD009051BD /* KeychainLayer.swift in Sources */, A9D819292E0E904200442D38 /* Theme.swift in Sources */, + A9D8192D2E0E9EB500442D38 /* ThemesView.swift in Sources */, A93143C62DF61FE300FCD5DB /* ViewModifiers.swift in Sources */, A98554632E0587DF009051BD /* HostsView.swift in Sources */, A96C6A8A2E0C0B1100F377FE /* SSHState.swift in Sources */, diff --git a/ShhShell/Host/HostsManager.swift b/ShhShell/Host/HostsManager.swift index afa9cca..8078360 100644 --- a/ShhShell/Host/HostsManager.swift +++ b/ShhShell/Host/HostsManager.swift @@ -13,15 +13,39 @@ class HostsManager: ObservableObject, @unchecked Sendable { private let userDefaults = NSUbiquitousKeyValueStore.default @Published var savedHosts: [Host] = [] + @Published var themes: [Theme] = [] init() { loadSavedHosts() } - /// get the index of a matching host in saved hosts - /// - Parameter host: input a host - /// - Returns: if an item in savedHosts has a matching uuid to the parameter, it returns the index - /// else returns nil + + func loadThemes() { + guard let dataTheme = userDefaults.data(forKey: "themes") else { return } + guard let dataThemeNames = userDefaults.data(forKey: "themeNames") else { return } + + guard let decodedThemes = try? JSONDecoder().decode([ThemeCodable].self, from: dataTheme) else { return } + guard let decodedThemeNames = try? JSONDecoder().decode([String].self, from: dataThemeNames) else { return } + + for index in 0.. Int? { if let index = savedHosts.firstIndex(where: { $0.id == hostSearchingFor.id }) { return index diff --git a/ShhShell/Themes/Theme.swift b/ShhShell/Themes/Theme.swift index 67c54e2..5f648c4 100644 --- a/ShhShell/Themes/Theme.swift +++ b/ShhShell/Themes/Theme.swift @@ -9,7 +9,8 @@ import Foundation import SwiftTerm import SwiftUI -struct Theme: Hashable, Equatable { +struct Theme: Hashable, Equatable, Identifiable { + var id = UUID() var name: String var ansi: [SwiftTerm.Color] var foreground: SwiftTerm.Color @@ -20,6 +21,34 @@ struct Theme: Hashable, Equatable { var selectedText: SwiftTerm.Color var selection: SwiftTerm.Color + var themeCodable: ThemeCodable { + return ThemeCodable( + ansi0: ansi[0].colorCodable, + ansi1: ansi[1].colorCodable, + ansi2: ansi[2].colorCodable, + ansi3: ansi[3].colorCodable, + ansi4: ansi[4].colorCodable, + ansi5: ansi[5].colorCodable, + ansi6: ansi[6].colorCodable, + ansi7: ansi[7].colorCodable, + ansi8: ansi[8].colorCodable, + ansi9: ansi[9].colorCodable, + ansi10: ansi[10].colorCodable, + ansi11: ansi[11].colorCodable, + ansi12: ansi[12].colorCodable, + ansi13: ansi[13].colorCodable, + ansi14: ansi[14].colorCodable, + ansi15: ansi[15].colorCodable, + foreground: foreground.colorCodable, + background: background.colorCodable, + cursor: cursor.colorCodable, + cursorText: cursorText.colorCodable, + bold: bold.colorCodable, + selectedText: selectedText.colorCodable, + selection: selection.colorCodable + ) + } + static func fromiTermColors(name: String, data: Data?) -> Theme? { guard let data else { return nil } @@ -122,6 +151,13 @@ extension SwiftTerm.Color { let blue = UInt16(colorCodable.blue * 65535) self.init(red: red, green: green, blue: blue) } + + var colorCodable: ColorCodable { + let red = Double(self.red)/65535 + let green = Double(self.green)/65535 + let blue = Double(self.blue)/65535 + return ColorCodable(red: red, green: green, blue: blue) + } } extension SwiftTerm.Color { diff --git a/ShhShell/Views/Hosts/HostsView.swift b/ShhShell/Views/Hosts/HostsView.swift index eafde56..a1b2df8 100644 --- a/ShhShell/Views/Hosts/HostsView.swift +++ b/ShhShell/Views/Hosts/HostsView.swift @@ -65,6 +65,14 @@ struct HostsView: View { .onMove(perform: { hostsManager.moveHost(from: $0, to: $1) }) + + Section() { + NavigationLink { + ThemesView(hostsManager: HostsManager()) + } label: { + Label("Themes", systemImage: "swatchpalette") + } + } } .transition(.opacity) .toolbar { diff --git a/ShhShell/Views/Themes/ThemesView.swift b/ShhShell/Views/Themes/ThemesView.swift new file mode 100644 index 0000000..ba2aa49 --- /dev/null +++ b/ShhShell/Views/Themes/ThemesView.swift @@ -0,0 +1,24 @@ +// +// ThemesView.swift +// ShhShell +// +// Created by neon443 on 27/06/2025. +// + +import SwiftUI + +struct ThemesView: View { + @ObservedObject var hostsManager: HostsManager + + var body: some View { + ForEach(hostsManager.themes) { theme in + ZStack { + RoundedRectangle(cornerRadius: 10) + } + } + } +} + +#Preview { + ThemesView(hostsManager: HostsManager()) +}