From 87e49b9b88bcb55dd1b62a8354619f7f43513df9 Mon Sep 17 00:00:00 2001 From: neoarz Date: Wed, 2 Apr 2025 12:46:33 -0400 Subject: [PATCH] custom theme and system theme --- StikJIT/Extensions & Stuff/Color.swift | 29 ++++++----- StikJIT/Views/HomeView.swift | 22 +++++++-- StikJIT/Views/SettingsView.swift | 68 ++++++++++++++++++++++---- 3 files changed, 95 insertions(+), 24 deletions(-) diff --git a/StikJIT/Extensions & Stuff/Color.swift b/StikJIT/Extensions & Stuff/Color.swift index 0da0839..6393435 100644 --- a/StikJIT/Extensions & Stuff/Color.swift +++ b/StikJIT/Extensions & Stuff/Color.swift @@ -19,18 +19,25 @@ extension Color { } init?(hex: String) { - let r, g, b: CGFloat - let start = hex.index(hex.startIndex, offsetBy: 1) - let hexColor = String(hex[start...]) - - if hexColor.count == 6, let hexNumber = Int(hexColor, radix: 16) { - r = CGFloat((hexNumber & 0xff0000) >> 16) / 255 - g = CGFloat((hexNumber & 0x00ff00) >> 8) / 255 - b = CGFloat(hexNumber & 0x0000ff) / 255 - self.init(red: r, green: g, blue: b) - return + if hex.isEmpty || hex.count < 2 { + return nil } - + + let r, g, b: CGFloat + + if hex.hasPrefix("#") && hex.count >= 7 { + let start = hex.index(hex.startIndex, offsetBy: 1) + let hexColor = String(hex[start...]) + + if hexColor.count == 6, let hexNumber = Int(hexColor, radix: 16) { + r = CGFloat((hexNumber & 0xff0000) >> 16) / 255 + g = CGFloat((hexNumber & 0x00ff00) >> 8) / 255 + b = CGFloat(hexNumber & 0x0000ff) / 255 + self.init(red: r, green: g, blue: b) + return + } + } + return nil } } diff --git a/StikJIT/Views/HomeView.swift b/StikJIT/Views/HomeView.swift index 39bedbf..08c0003 100644 --- a/StikJIT/Views/HomeView.swift +++ b/StikJIT/Views/HomeView.swift @@ -17,9 +17,10 @@ extension UIDocumentPickerViewController { struct HomeView: View { @AppStorage("username") private var username = "User" - @AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = Color.primaryBackground.toHex() ?? "#000000" + @AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = "" @AppStorage("autoQuitAfterEnablingJIT") private var doAutoQuitAfterEnablingJIT = false - @State private var selectedBackgroundColor: Color = Color(hex: UserDefaults.standard.string(forKey: "customBackgroundColor") ?? "#000000") ?? Color.primaryBackground + @State private var selectedBackgroundColor: Color = Color(hex: UserDefaults.standard.string(forKey: "customBackgroundColor") ?? "") ?? .clear + @Environment(\.colorScheme) private var colorScheme let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() @AppStorage("bundleID") private var bundleID: String = "" @State private var isProcessing = false @@ -38,7 +39,11 @@ struct HomeView: View { var body: some View { ZStack { - selectedBackgroundColor.edgesIgnoringSafeArea(.all) + // Use the background color or default to appearance-based color if not set + (selectedBackgroundColor == .clear ? + (colorScheme == .dark ? Color.black : Color.white) : + selectedBackgroundColor) + .edgesIgnoringSafeArea(.all) VStack(spacing: 25) { Spacer() @@ -145,6 +150,11 @@ struct HomeView: View { } .onAppear { checkPairingFileExists() + // Don't initialize specific color value when empty - empty means "use system theme" + // This was causing the toggle to turn off when returning to settings + + // Initialize background color + refreshBackground() } .onReceive(timer) { _ in refreshBackground() @@ -258,7 +268,11 @@ struct HomeView: View { } private func refreshBackground() { - selectedBackgroundColor = Color(hex: customBackgroundColorHex) ?? Color.primaryBackground + if customBackgroundColorHex.isEmpty { + selectedBackgroundColor = colorScheme == .dark ? Color.black : Color.white + } else { + selectedBackgroundColor = Color(hex: customBackgroundColorHex) ?? (colorScheme == .dark ? Color.black : Color.white) + } } private func startJITInBackground(with bundleID: String) { diff --git a/StikJIT/Views/SettingsView.swift b/StikJIT/Views/SettingsView.swift index 888772f..589b16a 100644 --- a/StikJIT/Views/SettingsView.swift +++ b/StikJIT/Views/SettingsView.swift @@ -8,12 +8,13 @@ import UniformTypeIdentifiers struct SettingsView: View { @AppStorage("username") private var username = "User" - @AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = Color.primaryBackground.toHex() ?? "#000000" + @AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = "" @AppStorage("selectedAppIcon") private var selectedAppIcon: String = "AppIcon" @AppStorage("autoQuitAfterEnablingJIT") private var doAutoQuitAfterEnablingJIT = false @State private var isShowingPairingFilePicker = false + @Environment(\.colorScheme) private var colorScheme - @State private var selectedBackgroundColor: Color = Color.primaryBackground + @State private var selectedBackgroundColor: Color = .clear @State private var showIconPopover = false @State private var showPairingFileMessage = false @State private var pairingFileIsValid = false @@ -98,15 +99,59 @@ struct SettingsView: View { .foregroundColor(.primary) .padding(.bottom, 4) - ColorPicker("Background Color", selection: $selectedBackgroundColor) - .onChange(of: selectedBackgroundColor) { newColor in - saveCustomBackgroundColor(newColor) + // Theme selector with segmented control style + VStack(alignment: .leading, spacing: 10) { + Text("Background Color") + .font(.subheadline) + .foregroundColor(.secondary) + + // Clean segmented style picker + Picker("Theme Mode", selection: Binding( + get: { customBackgroundColorHex.isEmpty }, + set: { newValue in + if newValue { + // System theme selected + customBackgroundColorHex = "" + selectedBackgroundColor = colorScheme == .dark ? Color.black : Color.white + } else if customBackgroundColorHex.isEmpty { + // Custom color selected - initialize with current theme color + let initialColor = colorScheme == .dark ? Color.black : Color.white + customBackgroundColorHex = initialColor.toHex() ?? "#000000" + selectedBackgroundColor = initialColor + } + } + )) { + Text("System").tag(true) + Text("Custom").tag(false) } - .foregroundColor(.primary) - .padding(.vertical, 6) + .pickerStyle(SegmentedPickerStyle()) + .padding(.vertical, 4) + + // Show color picker only in custom mode with a nice transition + if !customBackgroundColorHex.isEmpty { + ColorPicker("", selection: $selectedBackgroundColor) + .onChange(of: selectedBackgroundColor) { newColor in + saveCustomBackgroundColor(newColor) + } + .labelsHidden() + .frame(maxWidth: .infinity, alignment: .center) + .padding(.top, 4) + .transition(.opacity) + } + + // Help text + Text(customBackgroundColorHex.isEmpty ? + "Uses light/dark mode system colors" : + "Select your preferred background color") + .font(.caption) + .foregroundColor(.secondary) + .padding(.top, 4) + } + .padding(.vertical, 6) } .padding(.vertical, 20) .padding(.horizontal, 16) + .animation(.easeInOut(duration: 0.2), value: customBackgroundColorHex.isEmpty) } SettingsCard { @@ -534,11 +579,16 @@ struct SettingsView: View { } private func loadCustomBackgroundColor() { - selectedBackgroundColor = Color(hex: customBackgroundColorHex) ?? Color.primaryBackground + if customBackgroundColorHex.isEmpty { + selectedBackgroundColor = colorScheme == .dark ? Color.black : Color.white + } else { + selectedBackgroundColor = Color(hex: customBackgroundColorHex) ?? (colorScheme == .dark ? Color.black : Color.white) + } } private func saveCustomBackgroundColor(_ color: Color) { - customBackgroundColorHex = color.toHex() ?? "#000000" + // Always save the custom color if we got here (since auto theme mode is disabled) + customBackgroundColorHex = color.toHex() ?? "" } private func changeAppIcon(to iconName: String) {