accent color fix

This commit is contained in:
neoarz 2025-04-09 00:06:31 -04:00
parent 6fa0f941b2
commit 2c33146039
7 changed files with 176 additions and 65 deletions

View file

@ -45,7 +45,45 @@ extension Color {
extension Color {
static let primaryBackground = Color.black
static let cardBackground = Color.white.opacity(0.2)
static let cardBackground2 = Color.blue.opacity(0.8)
// Instead of a static color, provide a function that gets the current accent color
static func dynamicAccentColor(opacity: Double = 0.8) -> Color {
let colorHex = UserDefaults.standard.string(forKey: "customAccentColor") ?? ""
if colorHex.isEmpty {
return Color.blue.opacity(opacity)
} else {
return (Color(hex: colorHex) ?? .blue).opacity(opacity)
}
}
// For backward compatibility
static var cardBackground2: Color {
return dynamicAccentColor(opacity: 0.8)
}
static let primaryText = Color.white
static let secondaryText = Color.white.opacity(0.7)
// Determine if a color is dark or light to decide text color
func isDark() -> Bool {
let uiColor = UIColor(self)
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
// Calculate perceived brightness using the formula for luminance
// 0.299*R + 0.587*G + 0.114*B
let brightness = (0.299 * red) + (0.587 * green) + (0.114 * blue)
// Return true if the color is dark (brightness < 0.5)
return brightness < 0.5
}
// Returns black or white depending on the background brightness
func contrastText() -> Color {
return self.isDark() ? .white : .black
}
}

View file

@ -9,6 +9,18 @@ import SwiftUI
import Network
import UniformTypeIdentifiers
// Add an accent color environment key
struct AccentColorKey: EnvironmentKey {
static let defaultValue: Color = .blue
}
extension EnvironmentValues {
var accentColor: Color {
get { self[AccentColorKey.self] }
set { self[AccentColorKey.self] = newValue }
}
}
let fileManager = FileManager.default
@ -442,6 +454,15 @@ func startHeartbeatInBackground() {
struct LoadingView: View {
@State private var animate = false
@Environment(\.colorScheme) private var colorScheme
@AppStorage("customAccentColor") private var customAccentColorHex: String = ""
private var accentColor: Color {
if customAccentColorHex.isEmpty {
return .blue
} else {
return Color(hex: customAccentColorHex) ?? .blue
}
}
var body: some View {
ZStack {
@ -464,8 +485,8 @@ struct LoadingView: View {
.trim(from: 0, to: 0.7)
.stroke(AngularGradient(
gradient: Gradient(colors: [
colorScheme == .dark ? Color.white.opacity(0.8) : Color.blue.opacity(0.8),
colorScheme == .dark ? Color.white.opacity(0.3) : Color.blue.opacity(0.3)
accentColor.opacity(0.8),
accentColor.opacity(0.3)
]),
center: .center
), style: StrokeStyle(lineWidth: 6, lineCap: .round))
@ -474,9 +495,7 @@ struct LoadingView: View {
.animation(Animation.linear(duration: 1.2).repeatForever(autoreverses: false), value: animate)
}
// Shadow adapts to theme
.shadow(color: colorScheme == .dark ?
.white.opacity(0.5) :
.blue.opacity(0.3),
.shadow(color: accentColor.opacity(0.4),
radius: 10, x: 0, y: 0)
.onAppear {
animate = true

View file

@ -11,9 +11,11 @@ import UIKit
struct ConsoleLogsView: View {
@Environment(\.dismiss) private var dismiss
@Environment(\.colorScheme) private var colorScheme
@Environment(\.accentColor) private var environmentAccentColor
@StateObject private var logManager = LogManager.shared
@State private var autoScroll = true
@State private var scrollView: ScrollViewProxy? = nil
@AppStorage("customAccentColor") private var customAccentColorHex: String = ""
// Alert handling
@State private var showingCustomAlert = false
@ -21,6 +23,14 @@ struct ConsoleLogsView: View {
@State private var alertTitle = ""
@State private var isError = false
private var accentColor: Color {
if customAccentColorHex.isEmpty {
return .blue
} else {
return Color(hex: customAccentColorHex) ?? .blue
}
}
var body: some View {
NavigationView {
ZStack {
@ -131,10 +141,10 @@ struct ConsoleLogsView: View {
}) {
HStack {
Text("Export Logs")
.foregroundColor(.blue)
.foregroundColor(accentColor)
Spacer()
Image(systemName: "square.and.arrow.down")
.foregroundColor(.gray)
.foregroundColor(accentColor)
}
.padding(.vertical, 14)
.padding(.horizontal, 20)
@ -172,10 +182,10 @@ struct ConsoleLogsView: View {
}) {
HStack {
Text("Copy Logs")
.foregroundColor(.blue)
.foregroundColor(accentColor)
Spacer()
Image(systemName: "doc.on.doc")
.foregroundColor(.gray)
.foregroundColor(accentColor)
}
.padding(.vertical, 14)
.padding(.horizontal, 20)
@ -209,7 +219,7 @@ struct ConsoleLogsView: View {
Text("Settings")
.fontWeight(.regular)
}
.foregroundColor(.blue)
.foregroundColor(accentColor)
}
}
@ -218,7 +228,7 @@ struct ConsoleLogsView: View {
logManager.clearLogs()
}) {
Text("Clear")
.foregroundColor(.blue)
.foregroundColor(accentColor)
}
}
}
@ -298,7 +308,7 @@ struct ConsoleLogsView: View {
case .error:
return .red
case .debug:
return .blue
return accentColor
case .warning:
return .orange
}

View file

@ -15,6 +15,15 @@ struct CustomErrorView: View {
var messageType: MessageType = .error
@Environment(\.colorScheme) private var colorScheme
@AppStorage("customAccentColor") private var customAccentColorHex: String = ""
private var accentColor: Color {
if customAccentColorHex.isEmpty {
return .blue
} else {
return Color(hex: customAccentColorHex) ?? .blue
}
}
enum MessageType {
case error
@ -51,7 +60,7 @@ struct CustomErrorView: View {
case .info:
Image(systemName: "info.circle.fill")
.font(.system(size: 32))
.foregroundColor(.blue.opacity(0.9))
.foregroundColor(accentColor.opacity(0.9))
.padding(.top, 8)
}
@ -90,7 +99,7 @@ struct CustomErrorView: View {
.frame(maxWidth: .infinity)
.background(
RoundedRectangle(cornerRadius: 10)
.fill(colorScheme == .dark ? Color.white : Color.blue)
.fill(colorScheme == .dark ? Color.white : accentColor)
)
}

View file

@ -17,10 +17,10 @@ extension UIDocumentPickerViewController {
struct HomeView: View {
@AppStorage("username") private var username = "User"
@AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = ""
@AppStorage("customAccentColor") private var customAccentColorHex: String = ""
@AppStorage("autoQuitAfterEnablingJIT") private var doAutoQuitAfterEnablingJIT = false
@State private var selectedBackgroundColor: Color = Color(hex: UserDefaults.standard.string(forKey: "customBackgroundColor") ?? "") ?? .clear
@Environment(\.colorScheme) private var colorScheme
@Environment(\.accentColor) private var environmentAccentColor
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@AppStorage("bundleID") private var bundleID: String = ""
@State private var isProcessing = false
@ -35,14 +35,18 @@ struct HomeView: View {
@State private var viewDidAppeared = false
@State private var pendingBundleIdToEnableJIT : String? = nil
private var accentColor: Color {
if customAccentColorHex.isEmpty {
return .blue
} else {
return Color(hex: customAccentColorHex) ?? .blue
}
}
var body: some View {
ZStack {
// Use the background color or default to appearance-based color if not set
(selectedBackgroundColor == .clear ?
(colorScheme == .dark ? Color.black : Color.white) :
selectedBackgroundColor)
// Use system background
Color(colorScheme == .dark ? .black : .white)
.edgesIgnoringSafeArea(.all)
VStack(spacing: 25) {
@ -88,10 +92,10 @@ struct HomeView: View {
}
.frame(maxWidth: .infinity)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.background(accentColor)
.foregroundColor(accentColor.contrastText())
.cornerRadius(16)
.shadow(color: Color.blue.opacity(0.3), radius: 8, x: 0, y: 4)
.shadow(color: accentColor.opacity(0.3), radius: 8, x: 0, y: 4)
}
.padding(.horizontal, 20)
@ -268,11 +272,8 @@ struct HomeView: View {
}
private func refreshBackground() {
if customBackgroundColorHex.isEmpty {
selectedBackgroundColor = colorScheme == .dark ? Color.black : Color.white
} else {
selectedBackgroundColor = Color(hex: customBackgroundColorHex) ?? (colorScheme == .dark ? Color.black : Color.white)
}
// This function is no longer needed for background color
// but we'll keep it empty to avoid breaking anything
}
private func startJITInBackground(with bundleID: String) {

View file

@ -8,6 +8,16 @@
import SwiftUI
struct MainTabView: View {
@AppStorage("customAccentColor") private var customAccentColorHex: String = ""
private var accentColor: Color {
if customAccentColorHex.isEmpty {
return .blue
} else {
return Color(hex: customAccentColorHex) ?? .blue
}
}
var body: some View {
TabView {
HomeView()
@ -19,5 +29,7 @@ struct MainTabView: View {
Label("Settings", systemImage: "gearshape.fill")
}
}
.accentColor(accentColor)
.environment(\.accentColor, accentColor)
}
}

View file

@ -8,14 +8,14 @@ import UniformTypeIdentifiers
struct SettingsView: View {
@AppStorage("username") private var username = "User"
@AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = ""
@AppStorage("customAccentColor") private var customAccentColorHex: String = ""
@AppStorage("selectedAppIcon") private var selectedAppIcon: String = "AppIcon"
@AppStorage("autoQuitAfterEnablingJIT") private var doAutoQuitAfterEnablingJIT = false
@AppStorage("skipGetTaskAllowCheck") private var doSkipGetTaskAllowCheck = false
@State private var isShowingPairingFilePicker = false
@Environment(\.colorScheme) private var colorScheme
@State private var selectedBackgroundColor: Color = .clear
@State private var selectedAccentColor: Color = .blue
@State private var showIconPopover = false
@State private var showPairingFileMessage = false
@State private var pairingFileIsValid = false
@ -46,6 +46,14 @@ struct SettingsView: View {
"Wynwxst": "https://github.com/Wynwxst.png"
]
private var accentColor: Color {
if customAccentColorHex.isEmpty {
return .blue
} else {
return Color(hex: customAccentColorHex) ?? .blue
}
}
var body: some View {
ZStack {
Color(UIColor.systemBackground)
@ -108,37 +116,33 @@ struct SettingsView: View {
// Theme selector with segmented control style
VStack(alignment: .leading, spacing: 10) {
Text("Background Color")
Text("Accent Color")
.font(.subheadline)
.foregroundColor(.secondary)
// Clean segmented style picker
Picker("Theme Mode", selection: Binding(
get: { customBackgroundColorHex.isEmpty },
get: { customAccentColorHex.isEmpty },
set: { newValue in
if newValue {
// System theme selected
customBackgroundColorHex = ""
selectedBackgroundColor = colorScheme == .dark ? Color.black : Color.white
} else if customBackgroundColorHex.isEmpty {
// System accent color selected
customAccentColorHex = ""
selectedAccentColor = .blue
} else if customAccentColorHex.isEmpty {
// Custom color selected - initialize with current theme color
let initialColor = colorScheme == .dark ? Color.black : Color.white
customBackgroundColorHex = initialColor.toHex() ?? "#000000"
selectedBackgroundColor = initialColor
// Don't open color picker popup automatically anymore
// User will need to press the "Change Color" button
selectedAccentColor = .blue
customAccentColorHex = selectedAccentColor.toHex() ?? "#0000FF"
}
}
)) {
Text("System").tag(true)
Text("Default").tag(true)
Text("Custom").tag(false)
}
.pickerStyle(SegmentedPickerStyle())
.padding(.vertical, 4)
// Show selection button and color picker inline when in custom mode
if !customBackgroundColorHex.isEmpty {
if !customAccentColorHex.isEmpty {
HStack {
// Left side - just text, no color preview
Text("Choose color")
@ -148,11 +152,11 @@ struct SettingsView: View {
Spacer()
// Right side - embedded color picker
ColorPicker("", selection: $selectedBackgroundColor, supportsOpacity: false)
ColorPicker("", selection: $selectedAccentColor, supportsOpacity: false)
.labelsHidden()
.scaleEffect(0.8)
.onChange(of: selectedBackgroundColor) { newColor in
saveCustomBackgroundColor(newColor)
.onChange(of: selectedAccentColor) { newColor in
saveCustomAccentColor(newColor)
}
}
.padding(.vertical, 8)
@ -160,8 +164,8 @@ struct SettingsView: View {
}
// Help text - only show for system mode
if customBackgroundColorHex.isEmpty {
Text("Uses light/dark mode system colors")
if customAccentColorHex.isEmpty {
Text("Uses default blue accent color")
.font(.caption)
.foregroundColor(.secondary)
.padding(.top, 4)
@ -171,7 +175,7 @@ struct SettingsView: View {
}
.padding(.vertical, 20)
.padding(.horizontal, 16)
.animation(.easeInOut(duration: 0.2), value: customBackgroundColorHex.isEmpty)
.animation(.easeInOut(duration: 0.2), value: customAccentColorHex.isEmpty)
}
SettingsCard {
@ -211,8 +215,8 @@ struct SettingsView: View {
}
.frame(maxWidth: .infinity)
.padding(.vertical, 14)
.foregroundColor(.white)
.background(Color.blue)
.foregroundColor(accentColor.contrastText())
.background(accentColor)
.cornerRadius(12)
}
@ -464,7 +468,7 @@ struct SettingsView: View {
Spacer()
Image(systemName: "gamecontroller")
.font(.system(size: 14))
.foregroundColor(.blue)
.foregroundColor(accentColor)
.frame(width: 24) // Keep consistent with LinkRow
}
}
@ -484,7 +488,7 @@ struct SettingsView: View {
HStack {
Image(systemName: "terminal")
.font(.system(size: 18))
.foregroundColor(.blue)
.foregroundColor(accentColor)
Text("System Logs")
.fontWeight(.medium)
.foregroundColor(.primary)
@ -597,21 +601,21 @@ struct SettingsView: View {
}
}
.onAppear {
loadCustomBackgroundColor()
loadCustomAccentColor()
}
}
private func loadCustomBackgroundColor() {
if customBackgroundColorHex.isEmpty {
selectedBackgroundColor = colorScheme == .dark ? Color.black : Color.white
private func loadCustomAccentColor() {
if customAccentColorHex.isEmpty {
selectedAccentColor = .blue
} else {
selectedBackgroundColor = Color(hex: customBackgroundColorHex) ?? (colorScheme == .dark ? Color.black : Color.white)
selectedAccentColor = Color(hex: customAccentColorHex) ?? .blue
}
}
private func saveCustomBackgroundColor(_ color: Color) {
private func saveCustomAccentColor(_ color: Color) {
// Always save the custom color if we got here (since auto theme mode is disabled)
customBackgroundColorHex = color.toHex() ?? ""
customAccentColorHex = color.toHex() ?? ""
}
private func changeAppIcon(to iconName: String) {
@ -682,6 +686,15 @@ struct LinkRow: View {
var icon: String
var title: String
var url: String
@AppStorage("customAccentColor") private var customAccentColorHex: String = ""
private var accentColor: Color {
if customAccentColorHex.isEmpty {
return .blue
} else {
return Color(hex: customAccentColorHex) ?? .blue
}
}
var body: some View {
Button(action: {
@ -695,7 +708,7 @@ struct LinkRow: View {
Spacer()
Image(systemName: icon)
.font(.system(size: 18))
.foregroundColor(.blue)
.foregroundColor(accentColor)
.frame(width: 24) // Added fixed width
}
}
@ -781,6 +794,15 @@ struct CollaboratorRow: View {
var name: String
var url: String
var imageUrl: String
@AppStorage("customAccentColor") private var customAccentColorHex: String = ""
private var accentColor: Color {
if customAccentColorHex.isEmpty {
return .blue
} else {
return Color(hex: customAccentColorHex) ?? .blue
}
}
var body: some View {
Button(action: {
@ -800,7 +822,7 @@ struct CollaboratorRow: View {
Image(systemName: "link")
.font(.system(size: 16))
.foregroundColor(.blue)
.foregroundColor(accentColor)
}
.padding(.vertical, 8)
}