diff --git a/ShhShell.xcodeproj/project.pbxproj b/ShhShell.xcodeproj/project.pbxproj index bf2baa7..6edd96a 100644 --- a/ShhShell.xcodeproj/project.pbxproj +++ b/ShhShell.xcodeproj/project.pbxproj @@ -33,6 +33,7 @@ A9485C712E1AECD000209824 /* JetBrainsMonoNerdFontMono-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A9485C702E1AECD000209824 /* JetBrainsMonoNerdFontMono-Italic.ttf */; }; A9485C722E1AECD000209824 /* JetBrainsMonoNerdFontMono-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A9485C6E2E1AECD000209824 /* JetBrainsMonoNerdFontMono-Bold.ttf */; }; A9485C732E1AECD000209824 /* JetBrainsMonoNerdFontMono-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A9485C6F2E1AECD000209824 /* JetBrainsMonoNerdFontMono-BoldItalic.ttf */; }; + A9485C762E1AF59F00209824 /* FontManagerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9485C752E1AF59F00209824 /* FontManagerView.swift */; }; A95FAA472DF3884B00DE2F5A /* Config.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = A95FAA462DF3884B00DE2F5A /* Config.xcconfig */; }; A95FAA542DF4B62900DE2F5A /* LibSSH.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A95FAA502DF4B62100DE2F5A /* LibSSH.xcframework */; }; A95FAA552DF4B62900DE2F5A /* LibSSH.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A95FAA502DF4B62100DE2F5A /* LibSSH.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -152,6 +153,7 @@ A9485C6E2E1AECD000209824 /* JetBrainsMonoNerdFontMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "JetBrainsMonoNerdFontMono-Bold.ttf"; sourceTree = ""; }; A9485C6F2E1AECD000209824 /* JetBrainsMonoNerdFontMono-BoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "JetBrainsMonoNerdFontMono-BoldItalic.ttf"; sourceTree = ""; }; A9485C702E1AECD000209824 /* JetBrainsMonoNerdFontMono-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "JetBrainsMonoNerdFontMono-Italic.ttf"; sourceTree = ""; }; + A9485C752E1AF59F00209824 /* FontManagerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontManagerView.swift; sourceTree = ""; }; A95FAA462DF3884B00DE2F5A /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = SOURCE_ROOT; }; A95FAA502DF4B62100DE2F5A /* LibSSH.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = LibSSH.xcframework; path = Frameworks/LibSSH.xcframework; sourceTree = ""; }; A95FAA512DF4B62100DE2F5A /* openssl.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = openssl.xcframework; path = Frameworks/openssl.xcframework; sourceTree = ""; }; @@ -368,6 +370,7 @@ isa = PBXGroup; children = ( A92538C52DEE0742007E0A18 /* ContentView.swift */, + A9485C742E1AF58C00209824 /* Fonts */, A96BE6AB2E11824B00C0FEE9 /* Sessions */, A9D8192B2E0E9EA400442D38 /* Themes */, A98554532E05534F009051BD /* Keys */, @@ -419,6 +422,14 @@ path = SSH; sourceTree = ""; }; + A9485C742E1AF58C00209824 /* Fonts */ = { + isa = PBXGroup; + children = ( + A9485C752E1AF59F00209824 /* FontManagerView.swift */, + ); + path = Fonts; + sourceTree = ""; + }; A95FAA582DF4B71F00DE2F5A /* ci_scripts */ = { isa = PBXGroup; children = ( @@ -730,6 +741,7 @@ A98554612E058433009051BD /* HostsManager.swift in Sources */, A985545D2E055D4D009051BD /* ConnectionView.swift in Sources */, A9FD37592E143D74005319A8 /* GenericPasswordConvertible.swift in Sources */, + A9485C762E1AF59F00209824 /* FontManagerView.swift in Sources */, A9835C3E2E17E9C100969508 /* invert.metal in Sources */, A98554592E0553AA009051BD /* KeyManager.swift in Sources */, A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */, diff --git a/ShhShell/Host/HostsManager.swift b/ShhShell/Host/HostsManager.swift index 5783f7d..9befb64 100644 --- a/ShhShell/Host/HostsManager.swift +++ b/ShhShell/Host/HostsManager.swift @@ -19,6 +19,7 @@ class HostsManager: ObservableObject, @unchecked Sendable { @Published var selectedAnsi: Int = 1 @Published var fonts: [UIFont] = [] + @Published var selectedFont: String = "Menlo" var tint: SwiftUI.Color { selectedTheme.ansi[selectedAnsi].suiColor @@ -34,15 +35,24 @@ class HostsManager: ObservableObject, @unchecked Sendable { var customFonts: [UIFont] = [] for family in UIFont.familyNames.sorted() { if FontFamilies.allCasesRaw.contains(family) { - if let family = FontFamilies(rawValue: family) { - if let customFont = UIFont(name: family.description, size: UIFont.systemFontSize) { - customFonts.append(customFont) - } - } + guard let family = FontFamilies(rawValue: family) else { return } + guard let customFont = UIFont(name: family.description, size: UIFont.systemFontSize) else { return } + customFonts.append(customFont) } } - print(customFonts) self.fonts = customFonts + + self.selectedFont = userDefaults.string(forKey: "selectedFontName") ?? "Menlo" + } + + func selectFont(_ fontName: String) { + guard fonts.map({ $0.familyName }).contains(fontName) else { return } + withAnimation { selectedFont = fontName } + saveFonts() + } + + func saveFonts() { + userDefaults.set(selectedFont, forKey: "selectedFontName") } func loadThemes() { diff --git a/ShhShell/Views/ContentView.swift b/ShhShell/Views/ContentView.swift index 412e09a..3da16c7 100644 --- a/ShhShell/Views/ContentView.swift +++ b/ShhShell/Views/ContentView.swift @@ -30,6 +30,19 @@ struct ContentView: View { keyManager: keyManager ) + Section() { + NavigationLink { + ThemeManagerView(hostsManager: hostsManager) + } label: { + Label("Themes", systemImage: "swatchpalette") + } + NavigationLink { + FontManagerView(hostsManager: hostsManager) + } label: { + Label("Fonts", systemImage: "textformat") + } + } + NavigationLink { KeyManagerView(hostsManager: hostsManager, keyManager: keyManager) } label: { diff --git a/ShhShell/Views/Fonts/FontManagerView.swift b/ShhShell/Views/Fonts/FontManagerView.swift new file mode 100644 index 0000000..18b9333 --- /dev/null +++ b/ShhShell/Views/Fonts/FontManagerView.swift @@ -0,0 +1,50 @@ +// +// FontManagerView.swift +// ShhShell +// +// Created by neon443 on 06/07/2025. +// + +import SwiftUI + +struct FontManagerView: View { + @ObservedObject var hostsManager: HostsManager + + @State var testLine: String = "the lazy bronw fox jumps over the lazy dog" + + var body: some View { + List { + ForEach(FontFamilies.allCasesRaw, id: \.self) { fontName in + let selected = hostsManager.selectedFont == fontName + Button() { + hostsManager.selectFont(fontName) + } label: { + VStack(alignment: .leading, spacing: 5) { + Text(fontName) + .foregroundStyle(.gray) + HStack { + Circle() + .frame(width: 20) + .opacity(selected ? 1 : 0) + .foregroundStyle(.green) + .animation(.spring, value: selected) + .transition(.scale) + Text("the lazy bronw fox jumps over the lazy dog") + .font(.custom(fontName, size: 15)) + .bold(selected) + .opacity(selected ? 1 : 0.8) + } + } + } + } + + Section("Test String") { + TextEditor(text: $testLine) + } + } + } +} + +#Preview { + FontManagerView(hostsManager: HostsManager()) +} diff --git a/ShhShell/Views/Hosts/HostsView.swift b/ShhShell/Views/Hosts/HostsView.swift index 61eaca6..8dd035f 100644 --- a/ShhShell/Views/Hosts/HostsView.swift +++ b/ShhShell/Views/Hosts/HostsView.swift @@ -38,26 +38,19 @@ struct HostsView: View { } label: { Label("Delete", systemImage: "trash") } + .tint(.red) Button() { hostsManager.duplicateHost(host) } label: { Label("Duplicate", systemImage: "square.filled.on.square") } - .foregroundStyle(.blue) + .tint(.blue) } } .onMove(perform: { hostsManager.moveHost(from: $0, to: $1) }) } - - Section() { - NavigationLink { - ThemeManagerView(hostsManager: hostsManager) - } label: { - Label("Themes", systemImage: "swatchpalette") - } - } .transition(.opacity) .navigationTitle("ShhShell") .toolbar { diff --git a/ShhShell/Views/Terminal/SSHTerminalDelegate.swift b/ShhShell/Views/Terminal/SSHTerminalDelegate.swift index 7ca7a0a..8d78d84 100644 --- a/ShhShell/Views/Terminal/SSHTerminalDelegate.swift +++ b/ShhShell/Views/Terminal/SSHTerminalDelegate.swift @@ -26,8 +26,7 @@ final class SSHTerminalDelegate: TerminalView, Sendable, @preconcurrency Termina if window != nil { restoreScrollback() if let hostsManager { -// font = hostsManager.fonts.randomElement() ?? UIFont.systemFont(ofSize: UIFont.systemFontSize) - font = UIFont(name: "JetBrainsMono Nerd Font Mono", size: UIFont.systemFontSize)! + font = UIFont(name: hostsManager.selectedFont, size: UIFont.systemFontSize)! } applySelectedTheme() }