mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 13:26:16 +00:00
added downloadtheme funciton to download and import a theme from an iterm2colorschemes.com link
added import theme to import a theme updated loadthemes updated themesview to add import buttons and updated the view fix themesview making a new instance of hostsmanager added suiColor to get a swiftui color from a swiftterm color fix uicolor returning black all the time
This commit is contained in:
@@ -17,6 +17,7 @@ class HostsManager: ObservableObject, @unchecked Sendable {
|
||||
|
||||
init() {
|
||||
loadSavedHosts()
|
||||
loadThemes()
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +29,31 @@ class HostsManager: ObservableObject, @unchecked Sendable {
|
||||
guard let decodedThemeNames = try? JSONDecoder().decode([String].self, from: dataThemeNames) else { return }
|
||||
|
||||
for index in 0..<decodedThemes.count {
|
||||
if let encoded = try? JSONEncoder().encode(decodedThemes) {
|
||||
if let synthedTheme = Theme.fromiTermColors(name: decodedThemeNames[index], data: encoded) {
|
||||
self.themes.append(synthedTheme)
|
||||
}
|
||||
guard let encoded = try? JSONEncoder().encode(decodedThemes) else { return }
|
||||
guard let synthedTheme = Theme.decodeTheme(name: decodedThemeNames[index], data: encoded) else { return }
|
||||
self.themes.append(synthedTheme)
|
||||
}
|
||||
}
|
||||
|
||||
func downloadTheme(fromUrl: URL?) {
|
||||
guard let fromUrl else { return }
|
||||
let task = URLSession.shared.dataTask(with: fromUrl) { data, response, error in
|
||||
guard let data else { return }
|
||||
let name = fromUrl.lastPathComponent.replacingOccurrences(of: ".itermcolors", with: "")
|
||||
DispatchQueue.main.async {
|
||||
self.importTheme(name: name, data: data)
|
||||
}
|
||||
}
|
||||
|
||||
task.resume()
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func importTheme(name: String, data: Data?) {
|
||||
guard let data else { return }
|
||||
guard let theme = Theme.decodeTheme(name: name, data: data) else { return }
|
||||
self.themes.append(theme)
|
||||
saveThemes()
|
||||
}
|
||||
|
||||
func saveThemes() {
|
||||
|
||||
@@ -21,224 +21,6 @@ struct ShhShellApp: App {
|
||||
keyManager: keyManager
|
||||
)
|
||||
.colorScheme(.dark)
|
||||
.onAppear {
|
||||
let data = """
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Ansi 0 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.0</real>
|
||||
</dict>
|
||||
<key>Ansi 1 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.40000000000000002</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.40000000000000002</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.80000000000000004</real>
|
||||
</dict>
|
||||
<key>Ansi 10 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.40784313729999999</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.74117647060000003</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.70980392160000005</real>
|
||||
</dict>
|
||||
<key>Ansi 11 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.4549019608</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.77647058820000003</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.94117647059999998</real>
|
||||
</dict>
|
||||
<key>Ansi 12 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.74509803919999995</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.63529411759999999</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.50588235290000005</real>
|
||||
</dict>
|
||||
<key>Ansi 13 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.73333333329999995</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.58039215690000001</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.69803921570000005</real>
|
||||
</dict>
|
||||
<key>Ansi 14 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.71764705880000002</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.74509803919999995</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.54117647059999996</real>
|
||||
</dict>
|
||||
<key>Ansi 15 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.99999129772186279</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.99997437000274658</real>
|
||||
<key>Red Component</key>
|
||||
<real>1</real>
|
||||
</dict>
|
||||
<key>Ansi 2 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.40784313725490196</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.74117647058823533</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.70980392156862748</real>
|
||||
</dict>
|
||||
<key>Ansi 3 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.45490196078431372</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.77647058823529413</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.94117647058823528</real>
|
||||
</dict>
|
||||
<key>Ansi 4 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.74509803921568629</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.63529411764705879</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.50588235294117645</real>
|
||||
</dict>
|
||||
<key>Ansi 5 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.73333333333333328</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.58039215686274503</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.69803921568627447</real>
|
||||
</dict>
|
||||
<key>Ansi 6 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.71764705882352942</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.74509803921568629</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.54117647058823526</real>
|
||||
</dict>
|
||||
<key>Ansi 7 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.99999129772186279</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.99997437000274658</real>
|
||||
<key>Red Component</key>
|
||||
<real>1</real>
|
||||
</dict>
|
||||
<key>Ansi 8 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.0</real>
|
||||
</dict>
|
||||
<key>Ansi 9 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.40000000000000002</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.40000000000000002</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.80000000000000004</real>
|
||||
</dict>
|
||||
<key>Background Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.12941177189350128</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.12156862765550613</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.11372549086809158</real>
|
||||
</dict>
|
||||
<key>Bold Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.77647058820000003</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.7843137255</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.7725490196</real>
|
||||
</dict>
|
||||
<key>Cursor Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.77647058820000003</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.7843137255</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.7725490196</real>
|
||||
</dict>
|
||||
<key>Cursor Text Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.12941177189350128</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.12156862765550613</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.11372549086809158</real>
|
||||
</dict>
|
||||
<key>Foreground Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.77647058823529413</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.78431372549019607</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.77254901960784317</real>
|
||||
</dict>
|
||||
<key>Selected Text Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.77647058820000003</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.7843137255</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.7725490196</real>
|
||||
</dict>
|
||||
<key>Selection Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.25490196078431371</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.23137254901960785</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.21568627450980393</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
""".data(using: .utf8)
|
||||
print("theme \(Theme.fromiTermColors(name: "tomorrow night", data: data))")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,13 +49,16 @@ struct Theme: Hashable, Equatable, Identifiable {
|
||||
)
|
||||
}
|
||||
|
||||
static func fromiTermColors(name: String, data: Data?) -> Theme? {
|
||||
static func decodeTheme(name: String, data: Data?) -> Theme? {
|
||||
guard let data else { return nil }
|
||||
|
||||
let decoder = PropertyListDecoder()
|
||||
|
||||
guard let decoded = try? decoder.decode(ThemeCodable.self, from: data) else { return nil }
|
||||
let plistDecoder = PropertyListDecoder()
|
||||
let jsonDecoder = JSONDecoder()
|
||||
|
||||
guard let decoded =
|
||||
(try? plistDecoder.decode(ThemeCodable.self, from: data)) ??
|
||||
(try? jsonDecoder.decode(ThemeCodable.self, from: data))
|
||||
else { return nil }
|
||||
let theme = Theme(
|
||||
name: name,
|
||||
ansi: decoded.ansi,
|
||||
@@ -161,10 +164,14 @@ extension SwiftTerm.Color {
|
||||
}
|
||||
|
||||
extension SwiftTerm.Color {
|
||||
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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ struct HostsView: View {
|
||||
|
||||
Section() {
|
||||
NavigationLink {
|
||||
ThemesView(hostsManager: HostsManager())
|
||||
ThemesView(hostsManager: hostsManager)
|
||||
} label: {
|
||||
Label("Themes", systemImage: "swatchpalette")
|
||||
}
|
||||
|
||||
@@ -10,10 +10,83 @@ 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 {
|
||||
ForEach(hostsManager.themes) { theme in
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
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)
|
||||
.foregroundStyle(theme.ansi[index].suiColor)
|
||||
.onAppear {
|
||||
print(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
ForEach(8..<16, id: \.self) { index in
|
||||
Rectangle()
|
||||
.frame(width: 12)
|
||||
.foregroundStyle(theme.ansi[index].suiColor)
|
||||
.onAppear {
|
||||
print(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user