mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 13:26:16 +00:00
added thememanager view and thempreviw
it uses a lazyhgrid
This commit is contained in:
@@ -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 */,
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
79
ShhShell/Views/Themes/ThemeManagerView.swift
Normal file
79
ShhShell/Views/Themes/ThemeManagerView.swift
Normal 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"
|
||||||
|
)
|
||||||
|
}
|
||||||
50
ShhShell/Views/Themes/ThemePreview.swift
Normal file
50
ShhShell/Views/Themes/ThemePreview.swift
Normal 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)!
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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())
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user