From 870ebb6fcc7845e30a419b449c129e4869757778 Mon Sep 17 00:00:00 2001 From: neon443 <69979447+neon443@users.noreply.github.com> Date: Sun, 29 Jun 2025 13:42:05 +0100 Subject: [PATCH] made the theme picker ui pretty boxes now touch and dont have spacing between vertical layout context menu actually targets correct theme the themebox is flexible and can be smaller/larger doesnt matter --- Resources/themes/iTerm2SolarizedDark.plist | 2 +- Resources/themes/iTerm2SolarizedLight.plist | 2 +- ShhShell/Views/Themes/ThemeManagerView.swift | 158 ++++++++----------- ShhShell/Views/Themes/ThemePreview.swift | 92 ++++++++--- 4 files changed, 136 insertions(+), 118 deletions(-) diff --git a/Resources/themes/iTerm2SolarizedDark.plist b/Resources/themes/iTerm2SolarizedDark.plist index 56ab13d..2412307 100644 --- a/Resources/themes/iTerm2SolarizedDark.plist +++ b/Resources/themes/iTerm2SolarizedDark.plist @@ -5,7 +5,7 @@ id 67A5D068-DC42-4C24-8058-775D7D24F8FE name - iTerm2SolarizedDar + solarizedDark Ansi 0 Color Alpha Component diff --git a/Resources/themes/iTerm2SolarizedLight.plist b/Resources/themes/iTerm2SolarizedLight.plist index 9feb1b3..8449407 100644 --- a/Resources/themes/iTerm2SolarizedLight.plist +++ b/Resources/themes/iTerm2SolarizedLight.plist @@ -5,7 +5,7 @@ id 262CB71A-C253-4A78-959E-6E080A458EBB name - iTerm2SolarizedLight + solarizedLight Ansi 0 Color Alpha Component diff --git a/ShhShell/Views/Themes/ThemeManagerView.swift b/ShhShell/Views/Themes/ThemeManagerView.swift index 7e4a4c4..7590245 100644 --- a/ShhShell/Views/Themes/ThemeManagerView.swift +++ b/ShhShell/Views/Themes/ThemeManagerView.swift @@ -19,102 +19,76 @@ struct ThemeManagerView: View { @State var rename: String = "" let grid: GridItem = GridItem( - .fixed(90), + .flexible(minimum: 100, maximum: 200), spacing: 8, alignment: .center ) var body: some View { - NavigationStack { - List { - Section("Your Themes") { - if hostsManager.themes.isEmpty { - VStack(alignment: .leading) { - Image(systemName: "paintpalette") - .resizable().scaledToFit() - .symbolRenderingMode(.multicolor) - .frame(width: 50) - Text("No themes (yet)") - .font(.title) - .padding(.vertical, 10) - .bold() - Text("Tap the Safari icon at the top right to find themes!") - Text("Once you find one that you like, copy it's link and enter it here using the link button.") - } - } else { - ScrollView(.horizontal) { - LazyHGrid(rows: [grid, grid], alignment: .center, spacing: 8) { - ForEach(hostsManager.themes) { theme in - ThemePreview(hostsManager: hostsManager, theme: theme) - .contextMenu { - Button() { - themeToRename = theme - rename = theme.name - showRenameAlert.toggle() - } label: { - Label("Rename", systemImage: "pencil") - } - Button(role: .destructive) { - hostsManager.deleteTheme(theme) - } label: { - Label("Delete", systemImage: "trash") - } - } - } - } - .animation(.default, value: hostsManager.themes) - .alert("", isPresented: $showRenameAlert) { - TextField("", text: $rename) - Button("OK") { - hostsManager.renameTheme(themeToRename, to: rename) - rename = "" - } - } - } - .fixedSize(horizontal: false, vertical: true) - .scrollIndicators(.hidden) - } - } - - Section("Builtin Themes") { - ScrollView(.horizontal) { - LazyHGrid(rows: [grid, grid], alignment: .center, spacing: 8) { - ForEach(Theme.builtinThemes) { theme in - ThemePreview(hostsManager: hostsManager, theme: theme) - } - } - .animation(.default, value: hostsManager.themes) - } - .scrollIndicators(.hidden) - .fixedSize(horizontal: false, vertical: true) - } - } - .navigationTitle("Themes") - .alert("Enter URL", isPresented: $showAlert) { - TextField("", text: $importURL, prompt: Text("URL")) - Button("Cancel") {} - Button() { - hostsManager.downloadTheme(fromUrl: URL(string: importURL)) - importURL = "" - } label: { - Label("Import", systemImage: "square.and.arrow.down") + ScrollView { + if hostsManager.themes.isEmpty { + VStack(alignment: .leading) { + Image(systemName: "paintpalette") + .resizable().scaledToFit() + .symbolRenderingMode(.multicolor) + .frame(width: 50) + Text("No themes (yet)") + .font(.title) + .padding(.vertical, 10) .bold() + Text("Tap the Safari icon at the top right to find themes!") + Text("Once you find one that you like, copy it's link and enter it here using the link button.") + } + } else { + LazyVGrid(columns: [grid, grid], alignment: .center, spacing: 8) { + ForEach(hostsManager.themes) { theme in + ThemePreview(hostsManager: hostsManager, theme: theme, canModify: true) + } + } + .padding(.horizontal) + .animation(.default, value: hostsManager.themes) + } + + HStack { + Text("Built-in Themes") + .padding(.top) + .padding(.horizontal) + .font(.headline) + Spacer() + } + LazyVGrid(columns: [grid, grid], alignment: .center, spacing: 8) { + ForEach(Theme.builtinThemes) { theme in + ThemePreview(hostsManager: hostsManager, theme: theme, canModify: false) } } - .toolbar { - ToolbarItem() { - Button() { - UIApplication.shared.open(URL(string: "https://iterm2colorschemes.com")!) - } label: { - Label("Open themes site", systemImage: "safari") - } + .padding(.horizontal) + .animation(.default, value: hostsManager.themes) + } + .navigationTitle("Themes") + .alert("Enter URL", isPresented: $showAlert) { + TextField("", text: $importURL, prompt: Text("URL")) + Button("Cancel") {} + Button() { + hostsManager.downloadTheme(fromUrl: URL(string: importURL)) + importURL = "" + } label: { + Label("Import", systemImage: "square.and.arrow.down") + .bold() + } + } + .toolbar { + 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") - } + } + ToolbarItem() { + Button() { + showAlert.toggle() + } label: { + Label("From URL", systemImage: "link") } } } @@ -122,8 +96,10 @@ struct ThemeManagerView: View { } #Preview { - ThemeManagerView( - hostsManager: HostsManager(), - importURL: "https://raw.githubusercontent.com/mbadolato/iTerm2-Color-Schemes/master/schemes/catppuccin-frappe.itermcolors" - ) + NavigationStack { + ThemeManagerView( + hostsManager: HostsManager(), + importURL: "https://raw.githubusercontent.com/mbadolato/iTerm2-Color-Schemes/master/schemes/catppuccin-frappe.itermcolors" + ) + } } diff --git a/ShhShell/Views/Themes/ThemePreview.swift b/ShhShell/Views/Themes/ThemePreview.swift index a5109f4..76251f0 100644 --- a/ShhShell/Views/Themes/ThemePreview.swift +++ b/ShhShell/Views/Themes/ThemePreview.swift @@ -10,56 +10,95 @@ import SwiftUI struct ThemePreview: View { @ObservedObject var hostsManager: HostsManager @State var theme: Theme + @State var canModify: Bool + + @State private var showRenameAlert: Bool = false + @State private var rename: String = "" var isSelected: Bool { return hostsManager.isThemeSelected(theme) } - var body: some View { + var body: some View { + let padding: CGFloat = 10 + let innerPadding: CGFloat = 5 + let outerR: CGFloat = 15 + var paletteR: CGFloat { + outerR-padding + } + var selectionR: CGFloat { + outerR-innerPadding + } + ZStack(alignment: .center) { Rectangle() .fill(Color.accentColor) Rectangle() .fill(theme.background.suiColor) - .frame( - width: isSelected ? 190 : 200, - height: isSelected ? 80 : 90 - ) .clipShape( RoundedRectangle( - cornerRadius: isSelected ? 5 : 10 + cornerRadius: isSelected ? selectionR : 0 ) ) - VStack(alignment: .leading) { + .padding(isSelected ? innerPadding : 0) + VStack { Text(theme.name) .foregroundStyle(theme.foreground.suiColor) .font(.headline) + .lineLimit(1) + Spacer() - HStack(spacing: 8) { - ForEach(0..<8, id: \.self) { index in - RoundedRectangle(cornerRadius: 2) - .frame(width: 16, height: 16) - .foregroundStyle(theme.ansi[index].suiColor) - } - } - HStack(spacing: 8) { - ForEach(8..<16, id: \.self) { index in - RoundedRectangle(cornerRadius: 2) - .frame(width: 16, height: 16) - .foregroundStyle(theme.ansi[index].suiColor) + + VStack(spacing: 0) { + HStack(spacing: 0) { + ForEach(0..<8, id: \.self) { index in + Rectangle() + .aspectRatio(CGSize(width: 1, height: 1), contentMode: .fit) + .foregroundStyle(theme.ansi[index].suiColor) + } + } + + HStack(spacing: 0) { + ForEach(8..<16, id: \.self) { index in + Rectangle() + .aspectRatio(CGSize(width: 1, height: 1), contentMode: .fit) + .foregroundStyle(theme.ansi[index].suiColor) + } } } + .clipShape(RoundedRectangle(cornerRadius: paletteR)) } - .padding(8) + .padding(padding) } - .frame(maxWidth: 200, maxHeight: 90) - .clipShape(RoundedRectangle(cornerRadius: 10)) - .animation(.spring, value: isSelected) .onTapGesture { hostsManager.selectTheme(theme) } - } + .animation(.spring, value: isSelected) + .clipShape(RoundedRectangle(cornerRadius: outerR)) + .contextMenu { + if canModify { + Button() { + rename = theme.name + showRenameAlert.toggle() + } label: { + Label("Rename", systemImage: "pencil") + } + Button(role: .destructive) { + hostsManager.deleteTheme(theme) + } label: { + Label("Delete", systemImage: "trash") + } + } + } + .alert("Rename \(theme.name)", isPresented: $showRenameAlert) { + TextField("", text: $rename) + Button("OK") { + hostsManager.renameTheme(theme, to: rename) + rename = "" + } + } + } } #Preview { @@ -68,6 +107,9 @@ struct ThemePreview: View { ThemePreview( hostsManager: HostsManager(), - theme: Theme.decodeTheme(data: data)! + theme: Theme.decodeTheme(data: data)!, + canModify: true ) + .border(Color.red) + .scaleEffect(2) }