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
This commit is contained in:
neon443
2025-06-29 13:42:05 +01:00
parent 24ca75f8c6
commit 870ebb6fcc
4 changed files with 136 additions and 118 deletions

View File

@@ -5,7 +5,7 @@
<key>id</key>
<string>67A5D068-DC42-4C24-8058-775D7D24F8FE</string>
<key>name</key>
<string>iTerm2SolarizedDar</string>
<string>solarizedDark</string>
<key>Ansi 0 Color</key>
<dict>
<key>Alpha Component</key>

View File

@@ -5,7 +5,7 @@
<key>id</key>
<string>262CB71A-C253-4A78-959E-6E080A458EBB</string>
<key>name</key>
<string>iTerm2SolarizedLight</string>
<string>solarizedLight</string>
<key>Ansi 0 Color</key>
<dict>
<key>Alpha Component</key>

View File

@@ -19,15 +19,13 @@ 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") {
ScrollView {
if hostsManager.themes.isEmpty {
VStack(alignment: .leading) {
Image(systemName: "paintpalette")
@@ -42,53 +40,30 @@ struct ThemeManagerView: View {
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) {
LazyVGrid(columns: [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")
}
}
ThemePreview(hostsManager: hostsManager, theme: theme, canModify: true)
}
}
.padding(.horizontal)
.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) {
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)
ThemePreview(hostsManager: hostsManager, theme: theme, canModify: false)
}
}
.padding(.horizontal)
.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"))
@@ -118,12 +93,13 @@ struct ThemeManagerView: View {
}
}
}
}
}
#Preview {
NavigationStack {
ThemeManagerView(
hostsManager: HostsManager(),
importURL: "https://raw.githubusercontent.com/mbadolato/iTerm2-Color-Schemes/master/schemes/catppuccin-frappe.itermcolors"
)
}
}

View File

@@ -10,55 +10,94 @@ 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 {
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) {
VStack(spacing: 0) {
HStack(spacing: 0) {
ForEach(0..<8, id: \.self) { index in
RoundedRectangle(cornerRadius: 2)
.frame(width: 16, height: 16)
Rectangle()
.aspectRatio(CGSize(width: 1, height: 1), contentMode: .fit)
.foregroundStyle(theme.ansi[index].suiColor)
}
}
HStack(spacing: 8) {
HStack(spacing: 0) {
ForEach(8..<16, id: \.self) { index in
RoundedRectangle(cornerRadius: 2)
.frame(width: 16, height: 16)
Rectangle()
.aspectRatio(CGSize(width: 1, height: 1), contentMode: .fit)
.foregroundStyle(theme.ansi[index].suiColor)
}
}
}
.padding(8)
.clipShape(RoundedRectangle(cornerRadius: paletteR))
}
.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 = ""
}
}
}
}
@@ -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)
}