diff --git a/Bootstrap.xcodeproj/project.pbxproj b/Bootstrap.xcodeproj/project.pbxproj index 4c7942d3..4a1f53ef 100644 --- a/Bootstrap.xcodeproj/project.pbxproj +++ b/Bootstrap.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ 847099982B1D855E003FA4ED /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 847099972B1D855E003FA4ED /* main.m */; }; 847099A32B1D868F003FA4ED /* Makefile in Sources */ = {isa = PBXBuildFile; fileRef = 847099A02B1D868F003FA4ED /* Makefile */; }; 847099A52B1D9686003FA4ED /* Bootstrap.m in Sources */ = {isa = PBXBuildFile; fileRef = 847099A42B1D9686003FA4ED /* Bootstrap.m */; }; + D694DE962B8504B80025DC7F /* Haptic++.swift in Sources */ = {isa = PBXBuildFile; fileRef = D694DE952B8504B80025DC7F /* Haptic++.swift */; }; FE0633AC2B41BC3D00B94787 /* CreditsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE0633AB2B41BC3D00B94787 /* CreditsView.swift */; }; FE0633AE2B41BCD900B94787 /* OptionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE0633AD2B41BCD900B94787 /* OptionsView.swift */; }; FE84597B2B44508300DCB44E /* AppViewControllerWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE84597A2B44508300DCB44E /* AppViewControllerWrapper.swift */; }; @@ -121,6 +122,7 @@ 847099A02B1D868F003FA4ED /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; 847099A42B1D9686003FA4ED /* Bootstrap.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Bootstrap.m; sourceTree = ""; }; 8595F05E2B578D9900681FC6 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; + D694DE952B8504B80025DC7F /* Haptic++.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Haptic++.swift"; sourceTree = ""; }; FE0633AB2B41BC3D00B94787 /* CreditsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditsView.swift; sourceTree = ""; }; FE0633AD2B41BCD900B94787 /* OptionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionsView.swift; sourceTree = ""; }; FE84597A2B44508300DCB44E /* AppViewControllerWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppViewControllerWrapper.swift; sourceTree = ""; }; @@ -248,6 +250,7 @@ FE0633AD2B41BCD900B94787 /* OptionsView.swift */, FE0633AB2B41BC3D00B94787 /* CreditsView.swift */, FE895FE72B418FB800A16882 /* ContentView.swift */, + D694DE952B8504B80025DC7F /* Haptic++.swift */, ); path = Views; sourceTree = ""; @@ -357,6 +360,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D694DE962B8504B80025DC7F /* Haptic++.swift in Sources */, 847099A32B1D868F003FA4ED /* Makefile in Sources */, 8470998D2B1D855D003FA4ED /* ViewController.m in Sources */, FE895FE82B418FB900A16882 /* ContentView.swift in Sources */, diff --git a/Bootstrap.xcodeproj/xcuserdata/hariz.xcuserdatad/xcschemes/xcschememanagement.plist b/Bootstrap.xcodeproj/xcuserdata/hariz.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000..630bbe2b --- /dev/null +++ b/Bootstrap.xcodeproj/xcuserdata/hariz.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Bootstrap.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-1024.png index da281067..8c0def00 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-1024.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-1024.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png index 3c905987..39e68f5d 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png index 515daaf7..d7fbff29 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-38@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-38@2x.png index a09079ad..560dc15d 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-38@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-38@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-38@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-38@3x.png index 3ac5137d..8f130de2 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-38@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-38@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png index be945c81..01281ff1 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png index 5aff5cef..6534e335 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png index 5aff5cef..6534e335 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png index 858c8351..ccc1047e 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-64@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-64@2x.png index 5cd35994..d953ca34 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-64@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-64@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-64@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-64@3x.png index a51bf75a..5d7fe8dd 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-64@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-64@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-68@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-68@2x.png index d66d7dde..9f5e9a2c 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-68@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-68@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png index d716d58e..fa46198e 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png index 7df1d759..1618e159 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-1024.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-1024.png index 50f6e8c5..aa3220e3 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-1024.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-1024.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-38@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-38@3x.png index 7d81f3d8..73511443 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-38@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-38@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-40@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-40@3x.png index 356375d6..c1757303 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-40@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-40@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-60@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-60@2x.png index 356375d6..c1757303 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-60@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-60@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-60@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-60@3x.png index 3b4405c9..24cef183 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-60@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-60@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-64@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-64@2x.png index 136c76cc..10a33aed 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-64@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-64@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-64@3x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-64@3x.png index dc6984cc..6f918641 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-64@3x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-64@3x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-68@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-68@2x.png index 3565ea49..d5379788 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-68@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-68@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-76@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-76@2x.png index d97ff7f3..0c388f50 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-76@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-76@2x.png differ diff --git a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-83.5@2x.png b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-83.5@2x.png index 8810f4d2..cd67b1da 100644 Binary files a/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-83.5@2x.png and b/Bootstrap/Assets.xcassets/AppIcon.appiconset1/icon-83.5@2x.png differ diff --git a/Bootstrap/Assets.xcassets/Bootstrap.imageset/Bootstrap.png b/Bootstrap/Assets.xcassets/Bootstrap.imageset/Bootstrap.png index da281067..03300fad 100644 Binary files a/Bootstrap/Assets.xcassets/Bootstrap.imageset/Bootstrap.png and b/Bootstrap/Assets.xcassets/Bootstrap.imageset/Bootstrap.png differ diff --git a/Bootstrap/Views/ContentView.swift b/Bootstrap/Views/ContentView.swift index 9406259d..2a3d7b38 100644 --- a/Bootstrap/Views/ContentView.swift +++ b/Bootstrap/Views/ContentView.swift @@ -10,16 +10,26 @@ import FluidGradient @objc class SwiftUIViewWrapper: NSObject { @objc static func createSwiftUIView() -> UIViewController { - let viewController = UIHostingController(rootView: ContentView()) + let viewController = UIHostingController(rootView: MainView()) return viewController } } -struct ContentView: View { +public let niceAnimation = Animation.timingCurve(0.25, 0.1, 0.35, 1.3).speed(0.9) + +struct MainView: View { @State var LogItems: [String.SubSequence] = { return [""] }() +// let colorsWarm: [Color] = [.red, .orange, .yellow] +// let colorsCold: [Color] = [.blue, .purple, .pink] + + @State var currentBlobs: [Color] = [] + @State var currentHighlights: [Color] = [] + + @AppStorage("colorScheme") var colorScheme = 0 + @State private var showOptions = false @State private var showCredits = false @State private var showAppView = false @@ -32,12 +42,22 @@ struct ContentView: View { var body: some View { ZStack { - FluidGradient(blobs: [.red, .orange], - highlights: [.red, .yellow], + FluidGradient(blobs: currentBlobs, + highlights: currentHighlights, speed: 0.5, blur: 0.95) .background(.quaternary) .ignoresSafeArea() + .onAppear { + currentBlobs = colorScheme == 0 ? [.red, .orange] : [.blue, .purple] + currentHighlights = colorScheme == 0 ? [.red, .yellow] : [.blue, .pink] + } + .onChange(of: colorScheme) {_ in + withAnimation(.easeInOut(duration: 2.5).speed(0.5)) { + currentBlobs = colorScheme == 0 ? [.red, .orange] : [.blue, .purple] + currentHighlights = colorScheme == 0 ? [.red, .yellow] : [.blue, .pink] + } + } VStack { HStack(spacing: 15) { @@ -73,7 +93,7 @@ struct ContentView: View { VStack { Button { - UIImpactFeedbackGenerator(style: .light).impactOccurred() + Haptic.shared.play(.light) bootstrapAction() } label: { if isSystemBootstrapped() { @@ -124,7 +144,7 @@ struct ContentView: View { .frame(width: 295) .background { Color(UIColor.systemBackground) - .cornerRadius(20) + .cornerRadius(18) .opacity(0.5) } .disabled(strapButtonDisabled) @@ -133,7 +153,7 @@ struct ContentView: View { Button { showAppView.toggle() - UIImpactFeedbackGenerator(style: .light).impactOccurred() + Haptic.shared.play(.light) } label: { Label( title: { Text("App List") }, @@ -143,15 +163,15 @@ struct ContentView: View { } .background { Color(UIColor.systemBackground) - .cornerRadius(20) + .cornerRadius(18) .opacity(0.5) } .disabled(!isSystemBootstrapped() || !checkBootstrapVersion()) Button { - withAnimation { - UIImpactFeedbackGenerator(style: .light).impactOccurred() - showOptions.toggle() + withAnimation(niceAnimation) { + Haptic.shared.play(.light) + showOptions = true } } label: { Label( @@ -162,7 +182,7 @@ struct ContentView: View { } .background { Color(UIColor.systemBackground) - .cornerRadius(20) + .cornerRadius(18) .opacity(0.5) } @@ -193,7 +213,7 @@ struct ContentView: View { .padding(20) .background { Color(.black) - .cornerRadius(20) + .cornerRadius(18) .opacity(0.5) } @@ -202,11 +222,13 @@ struct ContentView: View { .opacity(0.5) } } + .scaleEffect((showOptions || showCredits) ? 0.9 : 1) } + .tint(colorScheme == 0 ? .orange : .blue) .safeAreaInset(edge: .bottom, spacing: 0) { Button { - withAnimation { - UIImpactFeedbackGenerator(style: .light).impactOccurred() + withAnimation(niceAnimation) { + Haptic.shared.play(.light) showCredits.toggle() } } label: { @@ -217,16 +239,20 @@ struct ContentView: View { } .frame(height:30, alignment: .bottom) .padding(10) - + .animation(.default, value: colorScheme) + .tint(colorScheme == 0 ? .orange : .blue) } .overlay { - if showCredits { + Group { CreditsView(showCredits: $showCredits) + .opacity(showCredits ? 1 : 0) + .allowsHitTesting(showCredits) + OptionsView(showOptions: $showOptions, tweakEnable: $tweakEnable, colorScheme: $colorScheme) + .opacity(showOptions ? 1 : 0) + .allowsHitTesting(showOptions) } - - if showOptions { - OptionsView(showOptions: $showOptions, tweakEnable: $tweakEnable) - } + .animation(.default, value: colorScheme) + .tint(colorScheme == 0 ? .orange : .blue) } .onAppear { initFromSwiftUI() @@ -263,3 +289,9 @@ struct ContentView: View { } } } + +struct MainView_Preview: PreviewProvider { + static var previews: some View { + MainView() + } +} diff --git a/Bootstrap/Views/CreditsView.swift b/Bootstrap/Views/CreditsView.swift index 258f893f..357bd661 100644 --- a/Bootstrap/Views/CreditsView.swift +++ b/Bootstrap/Views/CreditsView.swift @@ -24,15 +24,19 @@ struct CreditsView: View { .frame(maxWidth: 250, alignment: .leading) .font(Font.system(size: 35)) Button { - withAnimation { - showCredits.toggle() + Haptic.shared.play(.light) + withAnimation(niceAnimation) { + showCredits = false } } label: { Image(systemName: "xmark.circle") .resizable() - .foregroundColor(.red) + .foregroundColor(.primary) .frame(width: 25, height: 25) + .padding(6) } + .background(.ultraThinMaterial) + .cornerRadius(.infinity) } ScrollView { @@ -46,14 +50,15 @@ struct CreditsView: View { } .frame(width: 253) .padding(20) - .background { - Color(UIColor.systemBackground) - .cornerRadius(20) - .opacity(0.5) - } + } + .background { + Color(UIColor.systemBackground) + .cornerRadius(20) + .opacity(0.5) } .frame(maxHeight: 550) } + .scaleEffect(showCredits ? 1 : 0.9) } } diff --git a/Bootstrap/Views/Haptic++.swift b/Bootstrap/Views/Haptic++.swift new file mode 100644 index 00000000..a844f592 --- /dev/null +++ b/Bootstrap/Views/Haptic++.swift @@ -0,0 +1,29 @@ +// +// Haptic++.swift +// PsychicPaper +// +// Created by Hariz Shirazi on 2023-02-04. +// + +import Foundation +import UIKit + +/// Wrapper around UIKit haptics +class Haptic { + static let shared = Haptic() + private init() { } + /// Play haptic feedback + func play(_ feedbackStyle: UIImpactFeedbackGenerator.FeedbackStyle) { + UIImpactFeedbackGenerator(style: feedbackStyle).impactOccurred() + } + + /// Provide haptic user feedback for an action + func notify(_ feedbackType: UINotificationFeedbackGenerator.FeedbackType) { + UINotificationFeedbackGenerator().notificationOccurred(feedbackType) + } + + /// Play feedback for a selection + func selection() { + UISelectionFeedbackGenerator().selectionChanged() + } +} diff --git a/Bootstrap/Views/OptionsView.swift b/Bootstrap/Views/OptionsView.swift index 90f38254..e7017633 100644 --- a/Bootstrap/Views/OptionsView.swift +++ b/Bootstrap/Views/OptionsView.swift @@ -19,6 +19,8 @@ struct OptionsView: View { @Binding var tweakEnable: Bool @StateObject var opensshStatus = toggleState(state: updateOpensshStatus(false)) + @Binding var colorScheme: Int + var body: some View { ZStack { VisualEffectView(effect: UIBlurEffect(style: .regular)) @@ -32,54 +34,70 @@ struct OptionsView: View { .font(Font.system(size: 35)) Button { - withAnimation { - showOptions.toggle() + Haptic.shared.play(.light) + withAnimation(niceAnimation) { + showOptions = false } } label: { Image(systemName: "xmark.circle") .resizable() - .foregroundColor(.red) - .frame(width: 30, height: 30) + .foregroundColor(.primary) + .frame(width: 25, height: 25) + .padding(6) } + .background(.ultraThinMaterial) + .cornerRadius(.infinity) } //ScrollView { VStack { VStack { - - Toggle(isOn: $tweakEnable, label: { - Label( - title: { Text("Tweak Enable") }, - icon: { Image(systemName: "wrench.and.screwdriver") } - ) - }).padding(5) - .onChange(of: tweakEnable) { newValue in - tweaEnableAction(newValue) - } - - Toggle(isOn: Binding(get: {opensshStatus.state}, set: { - opensshStatus.state = opensshAction($0) - }), label: { - Label( - title: { Text("OpenSSH") }, - icon: { Image(systemName: "terminal") } - ) - }) - .onReceive(NotificationCenter.default.publisher(for: Notification.Name("opensshStatusNotification"))) { obj in - DispatchQueue.global(qos: .utility).async { - let newStatus = (obj.object as! NSNumber).boolValue - opensshStatus.state = newStatus + Group { + Toggle(isOn: $tweakEnable, label: { + Label( + title: { Text("Tweak Enable") }, + icon: { Image(systemName: "wrench.and.screwdriver") } + ) + }) + .onChange(of: tweakEnable) { newValue in + tweaEnableAction(newValue) + } + + Toggle(isOn: Binding(get: {opensshStatus.state}, set: { + opensshStatus.state = opensshAction($0) + }), label: { + Label( + title: { Text("OpenSSH") }, + icon: { Image(systemName: "terminal") } + ) + }) + .onReceive(NotificationCenter.default.publisher(for: Notification.Name("opensshStatusNotification"))) { obj in + DispatchQueue.global(qos: .utility).async { + let newStatus = (obj.object as! NSNumber).boolValue + opensshStatus.state = newStatus + } + } + HStack { + Label( + title: { Text("Colors") }, + icon: { Image(systemName: "paintpalette") } + ) + Spacer() + Picker(selection: $colorScheme, label: Text("")) { + Text("Warm").tag(0) + Text("Cold").tag(1) + } + .foregroundColor(.primary) } } .padding(5) - Divider().padding(10) VStack(alignment: .leading, spacing: 12, content: { Button { - UIImpactFeedbackGenerator(style: .light).impactOccurred() + Haptic.shared.play(.light) respringAction() } label: { Label( @@ -100,7 +118,7 @@ struct OptionsView: View { .disabled(!isSystemBootstrapped() || !checkBootstrapVersion()) Button { - UIImpactFeedbackGenerator(style: .light).impactOccurred() + Haptic.shared.play(.light) rebuildappsAction() } label: { Label( @@ -121,7 +139,7 @@ struct OptionsView: View { .disabled(!isSystemBootstrapped() || !checkBootstrapVersion()) Button { - UIImpactFeedbackGenerator(style: .light).impactOccurred() + Haptic.shared.play(.light) rebuildIconCacheAction() } label: { Label( @@ -142,7 +160,7 @@ struct OptionsView: View { .disabled(!isSystemBootstrapped() || !checkBootstrapVersion()) Button { - UIImpactFeedbackGenerator(style: .light).impactOccurred() + Haptic.shared.play(.light) resetMobilePassword() } label: { Label( @@ -163,7 +181,7 @@ struct OptionsView: View { .disabled(!isSystemBootstrapped() || !checkBootstrapVersion()) Button { - UIImpactFeedbackGenerator(style: .light).impactOccurred() + Haptic.shared.play(.light) reinstallPackageManager() } label: { Label( @@ -185,7 +203,7 @@ struct OptionsView: View { if isBootstrapInstalled() { Button { - UIImpactFeedbackGenerator(style: .light).impactOccurred() + Haptic.shared.play(.light) unbootstrapAction() } label: { Label( @@ -218,6 +236,7 @@ struct OptionsView: View { //} } .frame(maxHeight: 550) + .scaleEffect(showOptions ? 1 : 0.9) } } }