mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 05:19:13 +00:00
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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user