added thememanager view and thempreviw

it uses a lazyhgrid
This commit is contained in:
neon443
2025-06-27 20:48:41 +01:00
parent c343066fb5
commit 3698232a51
5 changed files with 138 additions and 96 deletions

View File

@@ -40,7 +40,8 @@
A9C4140C2E096DB7005E3047 /* SSHError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C4140B2E096DB7005E3047 /* SSHError.swift */; }; A9C4140C2E096DB7005E3047 /* SSHError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C4140B2E096DB7005E3047 /* SSHError.swift */; };
A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */; }; A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */; };
A9D819292E0E904200442D38 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D819282E0E904200442D38 /* Theme.swift */; }; A9D819292E0E904200442D38 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D819282E0E904200442D38 /* Theme.swift */; };
A9D8192D2E0E9EB500442D38 /* ThemesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D8192C2E0E9EB500442D38 /* ThemesView.swift */; }; A9D8192D2E0E9EB500442D38 /* ThemeManagerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D8192C2E0E9EB500442D38 /* ThemeManagerView.swift */; };
A9D8192F2E0F1BEE00442D38 /* ThemePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D8192E2E0F1BEE00442D38 /* ThemePreview.swift */; };
A9DA97712E0D30ED00142DDC /* HostSymbol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DA97702E0D30ED00142DDC /* HostSymbol.swift */; }; A9DA97712E0D30ED00142DDC /* HostSymbol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DA97702E0D30ED00142DDC /* HostSymbol.swift */; };
A9DA97732E0D40C100142DDC /* SymbolPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DA97722E0D40C100142DDC /* SymbolPreview.swift */; }; A9DA97732E0D40C100142DDC /* SymbolPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DA97722E0D40C100142DDC /* SymbolPreview.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@@ -115,7 +116,8 @@
A9C4140B2E096DB7005E3047 /* SSHError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHError.swift; sourceTree = "<group>"; }; A9C4140B2E096DB7005E3047 /* SSHError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHError.swift; sourceTree = "<group>"; };
A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHHandler.swift; sourceTree = "<group>"; }; A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHHandler.swift; sourceTree = "<group>"; };
A9D819282E0E904200442D38 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; }; A9D819282E0E904200442D38 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
A9D8192C2E0E9EB500442D38 /* ThemesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemesView.swift; sourceTree = "<group>"; }; A9D8192C2E0E9EB500442D38 /* ThemeManagerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeManagerView.swift; sourceTree = "<group>"; };
A9D8192E2E0F1BEE00442D38 /* ThemePreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemePreview.swift; sourceTree = "<group>"; };
A9DA97702E0D30ED00142DDC /* HostSymbol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostSymbol.swift; sourceTree = "<group>"; }; A9DA97702E0D30ED00142DDC /* HostSymbol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostSymbol.swift; sourceTree = "<group>"; };
A9DA97722E0D40C100142DDC /* SymbolPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SymbolPreview.swift; sourceTree = "<group>"; }; A9DA97722E0D40C100142DDC /* SymbolPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SymbolPreview.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@@ -327,7 +329,8 @@
A9D8192B2E0E9EA400442D38 /* Themes */ = { A9D8192B2E0E9EA400442D38 /* Themes */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A9D8192C2E0E9EB500442D38 /* ThemesView.swift */, A9D8192C2E0E9EB500442D38 /* ThemeManagerView.swift */,
A9D8192E2E0F1BEE00442D38 /* ThemePreview.swift */,
); );
path = Themes; path = Themes;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -474,11 +477,12 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A9D8192F2E0F1BEE00442D38 /* ThemePreview.swift in Sources */,
A96C6B022E0C49E800F377FE /* CenteredLabel.swift in Sources */, A96C6B022E0C49E800F377FE /* CenteredLabel.swift in Sources */,
A923172F2E08851200ECE1E6 /* ShellView.swift in Sources */, A923172F2E08851200ECE1E6 /* ShellView.swift in Sources */,
A985545F2E056EDD009051BD /* KeychainLayer.swift in Sources */, A985545F2E056EDD009051BD /* KeychainLayer.swift in Sources */,
A9D819292E0E904200442D38 /* Theme.swift in Sources */, A9D819292E0E904200442D38 /* Theme.swift in Sources */,
A9D8192D2E0E9EB500442D38 /* ThemesView.swift in Sources */, A9D8192D2E0E9EB500442D38 /* ThemeManagerView.swift in Sources */,
A93143C62DF61FE300FCD5DB /* ViewModifiers.swift in Sources */, A93143C62DF61FE300FCD5DB /* ViewModifiers.swift in Sources */,
A98554632E0587DF009051BD /* HostsView.swift in Sources */, A98554632E0587DF009051BD /* HostsView.swift in Sources */,
A96C6A8A2E0C0B1100F377FE /* SSHState.swift in Sources */, A96C6A8A2E0C0B1100F377FE /* SSHState.swift in Sources */,

View File

@@ -68,7 +68,7 @@ struct HostsView: View {
Section() { Section() {
NavigationLink { NavigationLink {
ThemesView(hostsManager: hostsManager) ThemeManagerView(hostsManager: hostsManager)
} label: { } label: {
Label("Themes", systemImage: "swatchpalette") Label("Themes", systemImage: "swatchpalette")
} }

View File

@@ -0,0 +1,79 @@
//
// ThemesView.swift
// ShhShell
//
// Created by neon443 on 27/06/2025.
//
import SwiftUI
struct ThemeManagerView: View {
@ObservedObject var hostsManager: HostsManager
@State var showAlert: Bool = false
@State var importURL: String = ""
@State var toImportName: String = ""
let grid = GridItem(
.adaptive(minimum: 80, maximum: 150),
spacing: 0,
alignment: .center
)
var body: some View {
GeometryReader { geo in
NavigationStack {
let columns = Int(geo.size.width/150)
ScrollView(.horizontal) {
LazyHGrid(rows: Array(repeating: grid, count: columns), alignment: .center, spacing: 0) {
ForEach(hostsManager.themes) { theme in
ThemePreview(theme: theme)
}
}
}
.scrollIndicators(.hidden)
.alert("Enter URL", isPresented: $showAlert) {
TextField("", text: $importURL, prompt: Text("URL"))
Button() {
hostsManager.downloadTheme(fromUrl: URL(string: importURL))
importURL = ""
} label: {
Label("Import", systemImage: "square.and.arrow.down")
}
}
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button() {
if let pasteboard = UIPasteboard().string {
hostsManager.importTheme(name: toImportName, data: pasteboard.data(using: .utf8))
}
} label: {
Label("Import", systemImage: "plus")
}
}
ToolbarItem() {
Button() {
UIApplication.shared.open(URL(string: "https://iterm2colorschemes.com")!)
} label: {
Label("Open themes site", systemImage: "safari")
}
}
ToolbarItem() {
Button() {
showAlert.toggle()
} label: {
Label("From URL", systemImage: "link")
}
}
}
}
}
}
}
#Preview {
ThemeManagerView(
hostsManager: HostsManager(),
importURL: "https://raw.githubusercontent.com/mbadolato/iTerm2-Color-Schemes/master/schemes/catppuccin-frappe.itermcolors"
)
}

View File

@@ -0,0 +1,50 @@
//
// ThemePreview.swift
// ShhShell
//
// Created by neon443 on 27/06/2025.
//
import SwiftUI
struct ThemePreview: View {
@State var theme: Theme
var body: some View {
ZStack(alignment: .center) {
RoundedRectangle(cornerRadius: 5)
.fill(theme.background.suiColor)
VStack(alignment: .leading) {
Text(theme.name)
.foregroundStyle(theme.foreground.suiColor)
.font(.headline)
HStack {
ForEach(0..<8, id: \.self) { index in
Rectangle()
.frame(width: 15, height: 15)
.foregroundStyle(theme.ansi[index].suiColor)
}
}
HStack {
ForEach(8..<16, id: \.self) { index in
Rectangle()
.frame(width: 15, height: 15)
.foregroundStyle(theme.ansi[index].suiColor)
}
}
}
.padding(5)
}
.fixedSize()
.frame(maxWidth: 150, maxHeight: 80)
}
}
#Preview {
let url = URL(string: "https://raw.githubusercontent.com/mbadolato/iTerm2-Color-Schemes/master/schemes/catppuccin-frappe.itermcolors")!
let data = try! Data(contentsOf: url)
ThemePreview(
theme: Theme.decodeTheme(name: "theme", data: data)!
)
}

View File

@@ -1,91 +0,0 @@
//
// ThemesView.swift
// ShhShell
//
// Created by neon443 on 27/06/2025.
//
import SwiftUI
struct ThemesView: View {
@ObservedObject var hostsManager: HostsManager
@State var showAlert: Bool = false
@State var importURL: String = ""
@State var toImportName: String = ""
var body: some View {
NavigationStack {
List {
ScrollView(.horizontal) {
HStack {
ForEach(hostsManager.themes) { theme in
ZStack(alignment: .center) {
RoundedRectangle(cornerRadius: 10)
.fill(theme.background.suiColor)
VStack(alignment: .leading) {
Text(theme.name)
.foregroundStyle(theme.foreground.suiColor)
HStack {
ForEach(0..<8, id: \.self) { index in
Rectangle()
.frame(width: 12, height: 12)
.foregroundStyle(theme.ansi[index].suiColor)
}
}
HStack {
ForEach(8..<16, id: \.self) { index in
Rectangle()
.frame(width: 12, height: 12)
.foregroundStyle(theme.ansi[index].suiColor)
}
}
}
}
.frame(width: 100, height: 100)
}
}
}
.scrollIndicators(.hidden)
}
.alert("Enter URL of your theme", isPresented: $showAlert) {
TextField("", text: $importURL, prompt: Text("from iterm2colorschemes.com"))
Button() {
hostsManager.downloadTheme(fromUrl: URL(string: importURL))
importURL = ""
} label: {
Label("Import", systemImage: "square.and.arrow.down")
}
}
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button() {
if let pasteboard = UIPasteboard().string {
hostsManager.importTheme(name: toImportName, data: pasteboard.data(using: .utf8))
}
} label: {
Label("Import", systemImage: "plus")
}
}
ToolbarItem() {
Button() {
UIApplication.shared.open(URL(string: "https://iterm2colorschemes.com")!)
} label: {
Label("Open themes site", systemImage: "safari")
}
}
ToolbarItem() {
Button() {
showAlert.toggle()
} label: {
Label("From URL", systemImage: "link")
}
}
}
}
}
}
#Preview {
ThemesView(hostsManager: HostsManager())
}