From 3cb5fbad7767d798c8f255154c40e6df12858011 Mon Sep 17 00:00:00 2001 From: Stephen <158498287+0-Blu@users.noreply.github.com> Date: Thu, 27 Mar 2025 14:15:56 -0400 Subject: [PATCH] Better UI --- StikJIT/Extensions & Stuff/Color.swift | 44 ++++++++ StikJIT/Extensions & Stuff/Font.swift | 14 +++ StikJIT/StikJITApp.swift | 2 +- StikJIT/Views/DebugView.swift | 32 ------ StikJIT/Views/HomeView.swift | 62 ++++++----- StikJIT/Views/MainTabView.swift | 4 +- StikJIT/Views/SettingsView.swift | 143 +++++++++++++++++++++++++ 7 files changed, 234 insertions(+), 67 deletions(-) create mode 100644 StikJIT/Extensions & Stuff/Color.swift create mode 100644 StikJIT/Extensions & Stuff/Font.swift delete mode 100644 StikJIT/Views/DebugView.swift create mode 100644 StikJIT/Views/SettingsView.swift diff --git a/StikJIT/Extensions & Stuff/Color.swift b/StikJIT/Extensions & Stuff/Color.swift new file mode 100644 index 0000000..0da0839 --- /dev/null +++ b/StikJIT/Extensions & Stuff/Color.swift @@ -0,0 +1,44 @@ +// +// Color.swift +// StikJIT +// +// Created by Stephen on 3/27/25. +// + + +import SwiftUI + +extension Color { + func toHex() -> String? { + let components = UIColor(self).cgColor.components + let r = Float(components?[0] ?? 0) + let g = Float(components?[1] ?? 0) + let b = Float(components?[2] ?? 0) + let hex = String(format: "%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255)) + return "#" + hex + } + + 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 + } + + return nil + } +} + +extension Color { + static let primaryBackground = Color.black + static let cardBackground = Color.white.opacity(0.2) + static let cardBackground2 = Color.blue.opacity(0.8) + static let primaryText = Color.white + static let secondaryText = Color.white.opacity(0.7) +} diff --git a/StikJIT/Extensions & Stuff/Font.swift b/StikJIT/Extensions & Stuff/Font.swift new file mode 100644 index 0000000..2e74d79 --- /dev/null +++ b/StikJIT/Extensions & Stuff/Font.swift @@ -0,0 +1,14 @@ +// +// Font.swift +// StikJIT +// +// Created by Stephen on 3/27/25. +// + +import SwiftUI + +extension Font { + static let titleFont = Font.system(size: 24, weight: .bold) + static let bodyFont = Font.system(size: 18, weight: .regular) + static let captionFont = Font.system(size: 14, weight: .medium) +} diff --git a/StikJIT/StikJITApp.swift b/StikJIT/StikJITApp.swift index ac8f15b..0891180 100644 --- a/StikJIT/StikJITApp.swift +++ b/StikJIT/StikJITApp.swift @@ -12,7 +12,7 @@ import em_proxy struct HeartbeatApp: App { var body: some Scene { WindowGroup { - HomeView() + MainTabView() .onAppear { startProxy() startHeartbeatInBackground() diff --git a/StikJIT/Views/DebugView.swift b/StikJIT/Views/DebugView.swift deleted file mode 100644 index 53497a6..0000000 --- a/StikJIT/Views/DebugView.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// DebugView.swift -// StikJIT -// -// Created by Stephen on 3/27/25. -// - -import SwiftUI - -struct DebugView: View { - var body: some View { - VStack { - Spacer() - Text("Welcome to StikJIT") - .font(.largeTitle) - .bold() - .padding() - - Text("Use the Debug tab to monitor the logs.") - .font(.body) - .foregroundColor(.secondary) - .padding() - Spacer() - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color(.systemBackground)) - } -} - -#Preview { - DebugView() -} diff --git a/StikJIT/Views/HomeView.swift b/StikJIT/Views/HomeView.swift index a7842ce..2deaf1d 100644 --- a/StikJIT/Views/HomeView.swift +++ b/StikJIT/Views/HomeView.swift @@ -8,63 +8,44 @@ import SwiftUI struct HomeView: View { + @AppStorage("username") private var username = "User" + @AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = Color.primaryBackground.toHex() ?? "#000000" + @State private var selectedBackgroundColor: Color = Color(hex: UserDefaults.standard.string(forKey: "customBackgroundColor") ?? "#000000") ?? Color.primaryBackground + let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() @AppStorage("bundleID") private var bundleID: String = "" @State private var isProcessing = false @State private var isShowingInstalledApps = false var body: some View { ZStack { - Color(.systemGroupedBackground) - .edgesIgnoringSafeArea(.all) + selectedBackgroundColor .edgesIgnoringSafeArea(.all) VStack(spacing: 25) { Spacer() VStack(spacing: 5) { - Text("StikJIT") + Text("Welcome to StikJIT \(username)!") .font(.system(.largeTitle, design: .rounded)) .fontWeight(.bold) - Text("Enter the app's Bundle ID and enable JIT.") + Text("Click enable jit to get started") .font(.system(.subheadline, design: .rounded)) .foregroundStyle(.secondary) .multilineTextAlignment(.center) } .padding(.top, 40) - RoundedTextField(placeholder: "Enter Bundle ID", text: $bundleID) - .padding(.horizontal, 20) - - Button(action: { - HapticFeedbackHelper.trigger() - startJITInBackground(with: bundleID) - }) { - Label(isProcessing ? "Enabling..." : "Enable JIT", - systemImage: isProcessing ? "hourglass" : "bolt.fill") - .font(.system(.title3, design: .rounded)) - .fontWeight(.semibold) - .frame(maxWidth: .infinity) - .padding() - .background(isProcessing ? Color.gray.opacity(0.6) : Color.blue) - .foregroundColor(.white) - .cornerRadius(16) - .shadow(color: .blue.opacity(0.3), radius: 8, x: 0, y: 4) - .animation(.easeInOut(duration: 0.2), value: isProcessing) - } - .disabled(isProcessing) - .padding(.horizontal, 20) - Button(action: { isShowingInstalledApps = true }) { - Label("View Installed Apps", systemImage: "list.bullet") + Label("Enable JIT", systemImage: "list.bullet") .font(.system(.title3, design: .rounded)) .fontWeight(.semibold) .frame(maxWidth: .infinity) .padding() - .background(Color.green) + .background(Color.blue) .foregroundColor(.white) .cornerRadius(16) - .shadow(color: Color.green.opacity(0.3), radius: 8, x: 0, y: 4) + .shadow(color: Color.blue.opacity(0.3), radius: 8, x: 0, y: 4) } .padding(.horizontal, 20) @@ -72,6 +53,9 @@ struct HomeView: View { } .padding() } + .onReceive(timer) { _ in + refreshBackground() + } .sheet(isPresented: $isShowingInstalledApps) { InstalledAppsListView { selectedBundle in bundleID = selectedBundle @@ -82,6 +66,10 @@ struct HomeView: View { } } + private func refreshBackground() { + selectedBackgroundColor = Color(hex: customBackgroundColorHex) ?? Color.primaryBackground + } + private func startJITInBackground(with bundleID: String) { isProcessing = true DispatchQueue.global(qos: .background).async { @@ -130,6 +118,10 @@ class InstalledAppsViewModel: ObservableObject { } struct InstalledAppsListView: View { + @AppStorage("username") private var username = "User" + @AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = Color.primaryBackground.toHex() ?? "#000000" + @State private var selectedBackgroundColor: Color = Color(hex: UserDefaults.standard.string(forKey: "customBackgroundColor") ?? "#000000") ?? Color.primaryBackground + let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() @StateObject var viewModel = InstalledAppsViewModel() @Environment(\.dismiss) var dismiss @State private var searchText: String = "" @@ -147,8 +139,7 @@ struct InstalledAppsListView: View { var body: some View { NavigationView { ZStack { - Color(.systemGroupedBackground) - .edgesIgnoringSafeArea(.all) + selectedBackgroundColor .edgesIgnoringSafeArea(.all) List { ForEach(filteredApps, id: \.self) { app in @@ -172,12 +163,19 @@ struct InstalledAppsListView: View { } } } - .searchable(text: $searchText, prompt: "Search Bundle IDs") + .searchable(text: $searchText, prompt: "Search Apps") + } + .onReceive(timer) { _ in + refreshBackground() } } } + private func refreshBackground() { + selectedBackgroundColor = Color(hex: customBackgroundColorHex) ?? Color.primaryBackground + } } + #Preview { HomeView() } diff --git a/StikJIT/Views/MainTabView.swift b/StikJIT/Views/MainTabView.swift index 486956c..2f87d68 100644 --- a/StikJIT/Views/MainTabView.swift +++ b/StikJIT/Views/MainTabView.swift @@ -14,9 +14,9 @@ struct MainTabView: View { .tabItem { Label("Home", systemImage: "house") } - DebugView() + SettingsView() .tabItem { - Label("Debug", systemImage: "ladybug") + Label("Swttings", systemImage: "gearshape.fill") } } } diff --git a/StikJIT/Views/SettingsView.swift b/StikJIT/Views/SettingsView.swift new file mode 100644 index 0000000..353f1f8 --- /dev/null +++ b/StikJIT/Views/SettingsView.swift @@ -0,0 +1,143 @@ +// +// SettingsView.swift +// StikJIT +// +// Created by Stephen on 3/27/25. +// + +import SwiftUI + +struct SettingsView: View { + @AppStorage("username") private var username = "User" + @AppStorage("customBackgroundColor") private var customBackgroundColorHex: String = Color.primaryBackground.toHex() ?? "#000000" + @AppStorage("selectedAppIcon") private var selectedAppIcon: String = "AppIcon" + + @State private var selectedBackgroundColor: Color = Color.primaryBackground + @State private var showIconPopover = false + + var body: some View { + ZStack { + selectedBackgroundColor + .ignoresSafeArea() + + Form { + Section(header: Text("General").font(.headline).foregroundColor(.primaryText)) { + HStack { + Label("", systemImage: "person.fill") + .foregroundColor(.primaryText) + Spacer() + TextField("Username", text: $username) + .foregroundColor(.primaryText) + .padding(10) + .background(Color.cardBackground) + .cornerRadius(10) + .overlay( + RoundedRectangle(cornerRadius: 10) + .stroke(selectedBackgroundColor, lineWidth: 1) + ) + } + .listRowBackground(Color.cardBackground) + } + + Section(header: Text("Appearance").font(.headline).foregroundColor(.primaryText)) { + ColorPicker("Background Color", selection: $selectedBackgroundColor) + .onChange(of: selectedBackgroundColor) { newColor in + saveCustomBackgroundColor(newColor) + } + .listRowBackground(Color.cardBackground) + .foregroundColor(.primaryText) + } + + Section(header: Text("About").font(.headline).foregroundColor(.primaryText)) { + HStack { + Text("Version:") + .foregroundColor(.secondaryText) + Spacer() + Text("1.0") + .foregroundColor(.primaryText) + } + .listRowBackground(Color.cardBackground) + + HStack { + Text("App Creator:") + .foregroundColor(.secondaryText) + Spacer() + Text("Stephen") + .foregroundColor(.primaryText) + } + .listRowBackground(Color.cardBackground) + + HStack { + Text("idevice & em_proxy Creator:") + .foregroundColor(.secondaryText) + Spacer() + Text("jkcoxson") + .foregroundColor(.primaryText) + } + + .listRowBackground(Color.cardBackground) + Button(action: { + if let url = URL(string: "https://github.com/0-Blu/StikJIT") { + UIApplication.shared.open(url) + } + }) { + HStack { + Text("View Source Code") + .foregroundColor(.secondaryText) + Spacer() + Image(systemName: "arrow.up.right.square") + .foregroundColor(.primaryText) + } + } + .listRowBackground(Color.cardBackground) + } + } + .background(selectedBackgroundColor) + .scrollContentBackground(.hidden) + .navigationBarTitle("Settings") + .font(.bodyFont) + .accentColor(.accentColor) + } + .onAppear { + loadCustomBackgroundColor() + } + } + + private func loadCustomBackgroundColor() { + selectedBackgroundColor = Color(hex: customBackgroundColorHex) ?? Color.primaryBackground + } + + private func saveCustomBackgroundColor(_ color: Color) { + customBackgroundColorHex = color.toHex() ?? "#000000" + } + + private func changeAppIcon(to iconName: String) { + selectedAppIcon = iconName + UIApplication.shared.setAlternateIconName(iconName == "AppIcon" ? nil : iconName) { error in + if let error = error { + print("Error changing app icon: \(error.localizedDescription)") + } + } + } + + private func iconButton(_ label: String, icon: String) -> some View { + Button(action: { + changeAppIcon(to: icon) + showIconPopover = false + }) { + HStack { + Image(uiImage: UIImage(named: icon) ?? UIImage()) + .resizable() + .frame(width: 24, height: 24) + .clipShape(RoundedRectangle(cornerRadius: 5)) + Text(label) + .foregroundColor(.primaryText) + Spacer() + } + .padding() + .background(Color.white.opacity(0.2)) + .cornerRadius(10) + } + .padding(.horizontal) + } +}