mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 13:26:16 +00:00
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:
@@ -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 */,
|
||||||
|
|||||||
@@ -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?) {
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
77
ShhShell/Themes/SwiftTerm.Color.swift
Normal file
77
ShhShell/Themes/SwiftTerm.Color.swift
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user