added reloading for edited themes on the fly

added a get/set SwiftUI.Color to SwiftTerm.Color
overhaul themeeditor's state stuff
updated themeeditor to use a binding
updated themepreview to use a binding
remove the massive subscript - its not needed anymore
moved all swifterm color stuff to its own file
This commit is contained in:
neon443
2025-07-08 19:48:37 +01:00
parent e5e0a47f4f
commit 19d3c495d5
9 changed files with 230 additions and 214 deletions

View File

@@ -71,6 +71,7 @@
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 */; };
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 */; };
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 */; };
@@ -192,6 +193,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>"; };
A9BA1D182E1D9AE1005BDCEF /* SwiftTerm.Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftTerm.Color.swift; sourceTree = "<group>"; };
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>"; };
@@ -522,6 +524,7 @@
A9D819282E0E904200442D38 /* Theme.swift */, A9D819282E0E904200442D38 /* Theme.swift */,
A96BE6A32E113D9400C0FEE9 /* ThemeCodable.swift */, A96BE6A32E113D9400C0FEE9 /* ThemeCodable.swift */,
A96BE6A52E113DB000C0FEE9 /* ColorCodable.swift */, A96BE6A52E113DB000C0FEE9 /* ColorCodable.swift */,
A9BA1D182E1D9AE1005BDCEF /* SwiftTerm.Color.swift */,
); );
path = Themes; path = Themes;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -735,6 +738,7 @@
A9FD375F2E14648E005319A8 /* KeyImporterView.swift in Sources */, A9FD375F2E14648E005319A8 /* KeyImporterView.swift in Sources */,
A93143C02DF61B3200FCD5DB /* Host.swift in Sources */, A93143C02DF61B3200FCD5DB /* Host.swift in Sources */,
A92538C92DEE0742007E0A18 /* ShhShellApp.swift in Sources */, A92538C92DEE0742007E0A18 /* ShhShellApp.swift in Sources */,
A9BA1D192E1D9AE1005BDCEF /* SwiftTerm.Color.swift in Sources */,
A96BE6AD2E11825800C0FEE9 /* SessionView.swift in Sources */, A96BE6AD2E11825800C0FEE9 /* SessionView.swift in Sources */,
A96C6B002E0C45FE00F377FE /* KeyDetailView.swift in Sources */, A96C6B002E0C45FE00F377FE /* KeyDetailView.swift in Sources */,
A9DA97712E0D30ED00142DDC /* HostSymbol.swift in Sources */, A9DA97712E0D30ED00142DDC /* HostSymbol.swift in Sources */,

View File

@@ -61,12 +61,16 @@ class HostsManager: ObservableObject, @unchecked Sendable {
guard let decodedThemes = try? JSONDecoder().decode([ThemeCodable].self, from: dataTheme) else { return } guard let decodedThemes = try? JSONDecoder().decode([ThemeCodable].self, from: dataTheme) else { return }
print(themes.count)
self.themes = [] self.themes = []
print(themes.count)
objectWillChange.send()
for index in 0..<decodedThemes.count { for index in 0..<decodedThemes.count {
guard let encoded = try? JSONEncoder().encode(decodedThemes[index]) else { return } guard let encoded = try? JSONEncoder().encode(decodedThemes[index]) else { return }
guard let synthedTheme = Theme.decodeTheme(data: encoded) else { return } guard let synthedTheme = Theme.decodeTheme(data: encoded) else { return }
self.themes.append(synthedTheme) self.themes.append(synthedTheme)
} }
objectWillChange.send()
guard let dataSelTheme = userDefaults.data(forKey: "selectedTheme") else { return } guard let dataSelTheme = userDefaults.data(forKey: "selectedTheme") else { return }
guard let decodedSelTheme = Theme.decodeTheme(data: dataSelTheme) else { return } guard let decodedSelTheme = Theme.decodeTheme(data: dataSelTheme) else { return }
@@ -74,6 +78,7 @@ class HostsManager: ObservableObject, @unchecked Sendable {
self.selectedTheme = decodedSelTheme self.selectedTheme = decodedSelTheme
selectedAnsi = Int(userDefaults.longLong(forKey: "selectedAnsi")) selectedAnsi = Int(userDefaults.longLong(forKey: "selectedAnsi"))
print(themes.count)
} }
func saveThemes() { func saveThemes() {
@@ -87,6 +92,7 @@ class HostsManager: ObservableObject, @unchecked Sendable {
userDefaults.set(Int64(selectedAnsi), forKey: "selectedAnsi") userDefaults.set(Int64(selectedAnsi), forKey: "selectedAnsi")
userDefaults.synchronize() userDefaults.synchronize()
loadThemes()
} }
func downloadTheme(fromUrl: URL?) { func downloadTheme(fromUrl: URL?) {

View File

@@ -60,53 +60,3 @@ extension ColorCodable {
return SwiftTerm.Color(self) return SwiftTerm.Color(self)
} }
} }
extension SwiftTerm.Color {
convenience init(_ color: SwiftUI.Color) {
var r: CGFloat = 0; var g: CGFloat = 0; var b: CGFloat = 0; var a: CGFloat = 0
let uiColor = UIColor(color)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
self.init(red: UInt16(r*65535), green: UInt16(g*65535), blue: UInt16(b*65535))
}
convenience init(_ colorCodable: ColorCodable) {
var cc = colorCodable
if cc.red < 0 { cc.red.negate() }
if cc.green < 0 { cc.green.negate() }
if cc.blue < 0 { cc.blue.negate() }
if cc.red > 1 { cc.red = 1 }
if cc.green > 1 { cc.green = 1 }
if cc.blue > 1 { cc.blue = 1 }
let red = UInt16(cc.red * 65535)
let green = UInt16(cc.green * 65535)
let blue = UInt16(cc.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)
}
var suiColor: SwiftUI.Color {
return Color(uiColor: self.uiColor)
}
var uiColor: UIColor {
let red = CGFloat(self.red)/65535
let green = CGFloat(self.green)/65535
let blue = CGFloat(self.blue)/65535
return UIColor(red: red, green: green, blue: blue, alpha: 1)
}
var luminance: Double {
let r = Double(red)/65535
let g = Double(green)/65535
let b = Double(blue)/65535
return (0.2126*r + 0.7152*g + 0.0722*b)
}
}

View File

@@ -0,0 +1,77 @@
//
// SwiftTerm.Color.swift
// ShhShell
//
// Created by neon443 on 08/07/2025.
//
import Foundation
import SwiftUI
import SwiftTerm
extension SwiftTerm.Color {
var suiColor: SwiftUI.Color {
get {
return Color(uiColor: self.uiColor)
} set {
let newOne = SwiftTerm.Color(newValue)
self.red = newOne.red
self.green = newOne.green
self.blue = newOne.blue
// let uiColor = UIColor(newValue)
// var r: CGFloat = 0; var g: CGFloat = 0; var b: CGFloat = 0
// uiColor.getRed(&r, green: &g, blue: &b, alpha: nil)
// self.red = r*65535
}
}
}
extension SwiftTerm.Color {
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)
}
var uiColor: UIColor {
let red = CGFloat(self.red)/65535
let green = CGFloat(self.green)/65535
let blue = CGFloat(self.blue)/65535
return UIColor(red: red, green: green, blue: blue, alpha: 1)
}
}
extension SwiftTerm.Color {
convenience init(_ color: SwiftUI.Color) {
var r: CGFloat = 0; var g: CGFloat = 0; var b: CGFloat = 0; var a: CGFloat = 0
let uiColor = UIColor(color)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
self.init(red: UInt16(r*65535), green: UInt16(g*65535), blue: UInt16(b*65535))
}
convenience init(_ colorCodable: ColorCodable) {
var cc = colorCodable
if cc.red < 0 { cc.red.negate() }
if cc.green < 0 { cc.green.negate() }
if cc.blue < 0 { cc.blue.negate() }
if cc.red > 1 { cc.red = 1 }
if cc.green > 1 { cc.green = 1 }
if cc.blue > 1 { cc.blue = 1 }
let red = UInt16(cc.red * 65535)
let green = UInt16(cc.green * 65535)
let blue = UInt16(cc.blue * 65535)
self.init(red: red, green: green, blue: blue)
}
}
extension SwiftTerm.Color {
var luminance: Double {
let r = Double(red)/65535
let g = Double(green)/65535
let b = Double(blue)/65535
return (0.2126*r + 0.7152*g + 0.0722*b)
}
}

View File

@@ -77,17 +77,6 @@ struct Theme: Hashable, Equatable, Identifiable {
static var builtinThemes: [Theme] { static var builtinThemes: [Theme] {
return ThemesBuiltin.allCases.map({ decodeLocalTheme(fileName: $0.rawValue)! }) return ThemesBuiltin.allCases.map({ decodeLocalTheme(fileName: $0.rawValue)! })
} }
// static func ==(lhs: Theme, rhs: Theme) -> Bool {
// return lhs.ansi == rhs.ansi &&
// lhs.foreground == rhs.foreground &&
// lhs.background == rhs.background &&
// lhs.cursor == rhs.cursor &&
// lhs.cursorText == rhs.cursorText &&
// lhs.bold == rhs.bold &&
// lhs.selectedText == rhs.selectedText &&
// lhs.selection == rhs.selection
// }
} }
enum ThemesBuiltin: String, CaseIterable, Hashable, Equatable { enum ThemesBuiltin: String, CaseIterable, Hashable, Equatable {
@@ -105,3 +94,99 @@ enum ThemesBuiltin: String, CaseIterable, Hashable, Equatable {
case gruvboxDark = "gruvboxDark" case gruvboxDark = "gruvboxDark"
case ubuntu = "ubuntu" case ubuntu = "ubuntu"
} }
//extension ThemeCodable {
// subscript(ansiIndex index: Int) -> SwiftUI.Color {
// get {
// switch index {
// case 0: return ansi0.stColor.suiColor
// case 1: return ansi1.stColor.suiColor
// case 2: return ansi2.stColor.suiColor
// case 3: return ansi3.stColor.suiColor
// case 4: return ansi4.stColor.suiColor
// case 5: return ansi5.stColor.suiColor
// case 6: return ansi6.stColor.suiColor
// case 7: return ansi7.stColor.suiColor
// case 8: return ansi8.stColor.suiColor
// case 9: return ansi9.stColor.suiColor
// case 10: return ansi10.stColor.suiColor
// case 11: return ansi11.stColor.suiColor
// case 12: return ansi12.stColor.suiColor
// case 13: return ansi13.stColor.suiColor
// case 14: return ansi14.stColor.suiColor
// case 15: return ansi15.stColor.suiColor
// default: fatalError()
// }
// }
// set {
// let cc = ColorCodable(color: newValue)
// switch index {
// case 0:
// ansi0.red = cc.red
// ansi0.green = cc.green
// ansi0.blue = cc.blue
// case 1:
// ansi1.red = cc.red
// ansi1.green = cc.green
// ansi1.blue = cc.blue
// case 2:
// ansi2.red = cc.red
// ansi2.green = cc.green
// ansi2.blue = cc.blue
// case 3:
// ansi3.red = cc.red
// ansi3.green = cc.green
// ansi3.blue = cc.blue
// case 4:
// ansi4.red = cc.red
// ansi4.green = cc.green
// ansi4.blue = cc.blue
// case 5:
// ansi5.red = cc.red
// ansi5.green = cc.green
// ansi5.blue = cc.blue
// case 6:
// ansi6.red = cc.red
// ansi6.green = cc.green
// ansi6.blue = cc.blue
// case 7:
// ansi7.red = cc.red
// ansi7.green = cc.green
// ansi7.blue = cc.blue
// case 8:
// ansi8.red = cc.red
// ansi8.green = cc.green
// ansi8.blue = cc.blue
// case 9:
// ansi9.red = cc.red
// ansi9.green = cc.green
// ansi9.blue = cc.blue
// case 10:
// ansi10.red = cc.red
// ansi10.green = cc.green
// ansi10.blue = cc.blue
// case 11:
// ansi11.red = cc.red
// ansi11.green = cc.green
// ansi11.blue = cc.blue
// case 12:
// ansi12.red = cc.red
// ansi12.green = cc.green
// ansi12.blue = cc.blue
// case 13:
// ansi13.red = cc.red
// ansi13.green = cc.green
// ansi13.blue = cc.blue
// case 14:
// ansi14.red = cc.red
// ansi14.green = cc.green
// ansi14.blue = cc.blue
// case 15:
// ansi15.red = cc.red
// ansi15.green = cc.green
// ansi15.blue = cc.blue
// default: fatalError()
// }
// }
// }
//}

View File

@@ -88,99 +88,3 @@ extension ThemeCodable {
) )
} }
} }
extension ThemeCodable {
subscript(ansiIndex index: Int) -> SwiftUI.Color {
get {
switch index {
case 0: return ansi0.stColor.suiColor
case 1: return ansi1.stColor.suiColor
case 2: return ansi2.stColor.suiColor
case 3: return ansi3.stColor.suiColor
case 4: return ansi4.stColor.suiColor
case 5: return ansi5.stColor.suiColor
case 6: return ansi6.stColor.suiColor
case 7: return ansi7.stColor.suiColor
case 8: return ansi8.stColor.suiColor
case 9: return ansi9.stColor.suiColor
case 10: return ansi10.stColor.suiColor
case 11: return ansi11.stColor.suiColor
case 12: return ansi12.stColor.suiColor
case 13: return ansi13.stColor.suiColor
case 14: return ansi14.stColor.suiColor
case 15: return ansi15.stColor.suiColor
default: fatalError()
}
}
set {
let cc = ColorCodable(color: newValue)
switch index {
case 0:
ansi0.red = cc.red
ansi0.green = cc.green
ansi0.blue = cc.blue
case 1:
ansi1.red = cc.red
ansi1.green = cc.green
ansi1.blue = cc.blue
case 2:
ansi2.red = cc.red
ansi2.green = cc.green
ansi2.blue = cc.blue
case 3:
ansi3.red = cc.red
ansi3.green = cc.green
ansi3.blue = cc.blue
case 4:
ansi4.red = cc.red
ansi4.green = cc.green
ansi4.blue = cc.blue
case 5:
ansi5.red = cc.red
ansi5.green = cc.green
ansi5.blue = cc.blue
case 6:
ansi6.red = cc.red
ansi6.green = cc.green
ansi6.blue = cc.blue
case 7:
ansi7.red = cc.red
ansi7.green = cc.green
ansi7.blue = cc.blue
case 8:
ansi8.red = cc.red
ansi8.green = cc.green
ansi8.blue = cc.blue
case 9:
ansi9.red = cc.red
ansi9.green = cc.green
ansi9.blue = cc.blue
case 10:
ansi10.red = cc.red
ansi10.green = cc.green
ansi10.blue = cc.blue
case 11:
ansi11.red = cc.red
ansi11.green = cc.green
ansi11.blue = cc.blue
case 12:
ansi12.red = cc.red
ansi12.green = cc.green
ansi12.blue = cc.blue
case 13:
ansi13.red = cc.red
ansi13.green = cc.green
ansi13.blue = cc.blue
case 14:
ansi14.red = cc.red
ansi14.green = cc.green
ansi14.blue = cc.blue
case 15:
ansi15.red = cc.red
ansi15.green = cc.green
ansi15.blue = cc.blue
default: fatalError()
}
}
}
}

View File

@@ -11,63 +11,60 @@ import SwiftTerm
struct ThemeEditorView: View { struct ThemeEditorView: View {
@ObservedObject var hostsManager: HostsManager @ObservedObject var hostsManager: HostsManager
// @State var theme: Theme @Binding var theme: Theme
@State var themeCodable: ThemeCodable
init(hostsManager: HostsManager, theme: Theme) { @Environment(\.dismiss) var dismiss
self.hostsManager = hostsManager
// self.theme = theme
self.themeCodable = theme.themeCodable
}
var body: some View { var body: some View {
NavigationStack { NavigationStack {
List { List {
TextField(
"Name", Section("Preview") {
text: Binding(get: { themeCodable.name ?? "Theme" }, set: { themeCodable.name = $0 }) // ThemePreview(hostsManager: HostsManager(), theme: themeCodable.toTheme(), canModify: false)
) // .id(themeCodable)
}
Section("Name") {
TextField("Name", text: $theme.name)
.textFieldStyle(.roundedBorder) .textFieldStyle(.roundedBorder)
}
ThemePreview(hostsManager: HostsManager(), theme: themeCodable.toTheme(), canModify: false) Section("Main Colors") {
.id(themeCodable)
Group { ColorPicker("Text", selection: $theme.foreground.suiColor, supportsOpacity: false)
HStack { .labelsHidden()
Rectangle() ColorPicker("Background", selection: $theme.background.suiColor, supportsOpacity: false)
.fill(themeCodable.foreground.suiColor) .labelsHidden()
Text("Foreground") ColorPicker("Cursor", selection: $theme.cursor.suiColor, supportsOpacity: false)
Spacer() .labelsHidden()
ColorPicker("", selection: $themeCodable.foreground.suiColor, supportsOpacity: false) ColorPicker("Cusor Text", selection: $theme.cursorText.suiColor, supportsOpacity: false)
.labelsHidden()
ColorPicker("Bold Text", selection: $theme.bold.suiColor, supportsOpacity: false)
.labelsHidden()
ColorPicker("Selection", selection: $theme.selection.suiColor, supportsOpacity: false)
.labelsHidden()
ColorPicker("Selected Text", selection: $theme.selectedText.suiColor, supportsOpacity: false)
.labelsHidden() .labelsHidden()
} }
Rectangle()
.fill(themeCodable.background.suiColor)
Rectangle()
.fill(themeCodable.bold.suiColor)
Rectangle()
.fill(themeCodable.cursor.suiColor)
Rectangle()
.fill(themeCodable.cursorText.suiColor)
Rectangle()
.fill(themeCodable.selection.suiColor)
Rectangle()
.fill(themeCodable.selectedText.suiColor)
}
Section("Ansi Colors") {
ForEach(0...1, id: \.self) { row in ForEach(0...1, id: \.self) { row in
HStack { HStack {
ForEach(1...8, id: \.self) { col in ForEach(1...8, id: \.self) { col in
let index = (col + (row * 8)) - 1 let index = (col + (row * 8)) - 1
ColorPicker("Ansi \(index+1)", selection: $themeCodable[ansiIndex: index], supportsOpacity: false) ColorPicker("", selection: $theme.ansi[index].suiColor, supportsOpacity: false)
.labelsHidden()
}
} }
} }
} }
} }
.navigationTitle("Edit Theme") .navigationTitle("Edit Theme")
.navigationBarTitleDisplayMode(.inline)
.toolbar { .toolbar {
Button() { Button() {
hostsManager.updateTheme(themeCodable.toTheme()) hostsManager.updateTheme(theme)
dismiss()
} label: { } label: {
Label("Done", systemImage: "checkmark") Label("Done", systemImage: "checkmark")
} }
@@ -77,5 +74,5 @@ struct ThemeEditorView: View {
} }
#Preview { #Preview {
ThemeEditorView(hostsManager: HostsManager(), theme: Theme.defaultTheme) ThemeEditorView(hostsManager: HostsManager(), theme: .constant(Theme.defaultTheme))
} }

View File

@@ -14,10 +14,6 @@ struct ThemeManagerView: View {
@State var importURL: String = "" @State var importURL: String = ""
@State var toImportName: String = "" @State var toImportName: String = ""
@State var showRenameAlert: Bool = false
@State var themeToRename: Theme?
@State var rename: String = ""
var minColWidth: CGFloat {150} var minColWidth: CGFloat {150}
var spacing: CGFloat {8} var spacing: CGFloat {8}
var grid: GridItem { var grid: GridItem {
@@ -72,8 +68,8 @@ struct ThemeManagerView: View {
} }
} else { } else {
LazyVGrid(columns: layout, alignment: .center, spacing: 8) { LazyVGrid(columns: layout, alignment: .center, spacing: 8) {
ForEach(hostsManager.themes) { theme in ForEach($hostsManager.themes) { $theme in
ThemePreview(hostsManager: hostsManager, theme: theme, canModify: true) ThemePreview(hostsManager: hostsManager, theme: $theme, canModify: true)
} }
} }
.padding(.horizontal) .padding(.horizontal)
@@ -89,7 +85,7 @@ struct ThemeManagerView: View {
} }
LazyVGrid(columns: layout, alignment: .center, spacing: 8) { LazyVGrid(columns: layout, alignment: .center, spacing: 8) {
ForEach(Theme.builtinThemes) { theme in ForEach(Theme.builtinThemes) { theme in
ThemePreview(hostsManager: hostsManager, theme: theme, canModify: false) ThemePreview(hostsManager: hostsManager, theme: .constant(theme), canModify: false)
} }
} }
.padding(.horizontal) .padding(.horizontal)

View File

@@ -9,7 +9,7 @@ import SwiftUI
struct ThemePreview: View { struct ThemePreview: View {
@ObservedObject var hostsManager: HostsManager @ObservedObject var hostsManager: HostsManager
@State var theme: Theme @Binding var theme: Theme
@State var canModify: Bool @State var canModify: Bool
@State private var showRenameAlert: Bool = false @State private var showRenameAlert: Bool = false
@@ -79,7 +79,7 @@ struct ThemePreview: View {
.contextMenu { .contextMenu {
if canModify { if canModify {
NavigationLink { NavigationLink {
ThemeEditorView(hostsManager: hostsManager, theme: theme) ThemeEditorView(hostsManager: hostsManager, theme: $theme)
} label: { } label: {
Label("Edit", systemImage: "pencil") Label("Edit", systemImage: "pencil")
} }
@@ -107,12 +107,9 @@ struct ThemePreview: View {
} }
#Preview { #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( ThemePreview(
hostsManager: HostsManager(), hostsManager: HostsManager(),
theme: Theme.decodeTheme(data: data)!, theme: .constant(Theme.defaultTheme),
canModify: true canModify: true
) )
.border(Color.red) .border(Color.red)