From 0d932273e0d40b4202fe3f44d766c9c39e713d9c Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sat, 8 Mar 2025 11:40:40 -0800 Subject: [PATCH 01/19] Up & down gesture recognizers --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 10 ++++++++++ Sources/Pinnacle/Tweak.x.swift | 2 +- .../Sources/PinnaclePrefs/Main/RootView.swift | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index b9d7cdb..411ce1f 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -39,6 +39,16 @@ class SBIconViewHook: ClassHook { target.addGestureRecognizer(swipeGesture) scrollViewPanGesture?.require(toFail: swipeGesture) + + if settings!.activationGestureDirection == "both" { + let secondSwipeGesture = UISwipeGestureRecognizer() + secondSwipeGesture.direction = .up + + secondSwipeGesture.addTarget(target, action: #selector(_pinnacleHandleActivation)) + + target.addGestureRecognizer(secondSwipeGesture) + scrollViewPanGesture?.require(toFail: secondSwipeGesture) + } } // orion:new diff --git a/Sources/Pinnacle/Tweak.x.swift b/Sources/Pinnacle/Tweak.x.swift index 015ce44..528ebbe 100644 --- a/Sources/Pinnacle/Tweak.x.swift +++ b/Sources/Pinnacle/Tweak.x.swift @@ -18,7 +18,7 @@ class Pinnacle: Tweak { }) }, name, nil, .deliverImmediately) - if settings!.activationGestureDirection == "down" { + if settings!.activationGestureDirection != "up" { SpotlightHookGroup().activate() } } diff --git a/pinnacleprefs/Sources/PinnaclePrefs/Main/RootView.swift b/pinnacleprefs/Sources/PinnaclePrefs/Main/RootView.swift index 9cd451a..5839e9b 100644 --- a/pinnacleprefs/Sources/PinnaclePrefs/Main/RootView.swift +++ b/pinnacleprefs/Sources/PinnaclePrefs/Main/RootView.swift @@ -41,6 +41,7 @@ struct RootView: View { Section { Picker("Gesture Direction", selection: $preferenceStorage.activationGestureDirection) { Text("Up").tag("up") + Text("Both").tag("both") Text("Down").tag("down") }.pickerStyle(.segmented) From 20f9e69805d624492b678291ddfa5ea3446835c9 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sat, 8 Mar 2025 15:25:00 -0800 Subject: [PATCH 02/19] fix app label storage --- .../Sources/PinnaclePrefs/Main/PreferenceStorage.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pinnacleprefs/Sources/PinnaclePrefs/Main/PreferenceStorage.swift b/pinnacleprefs/Sources/PinnaclePrefs/Main/PreferenceStorage.swift index 83b1fb8..8bd531b 100644 --- a/pinnacleprefs/Sources/PinnaclePrefs/Main/PreferenceStorage.swift +++ b/pinnacleprefs/Sources/PinnaclePrefs/Main/PreferenceStorage.swift @@ -6,7 +6,7 @@ final class PreferenceStorage: ObservableObject { static let registry: String = jbRootPath("/var/mobile/Library/Preferences/dev.rugmj.pinnacleprefs.plist") @Published(key: "enabled", registry: registry) var isEnabled: Bool = true - @Published(key: "showAppLabels", registry: registry) var isEnabled: Bool = true + @Published(key: "showAppLabels", registry: registry) var showAppLabels: Bool = true @Published(key: "fadeAmount", registry: registry) var fadeAmount: Double = 0.3 @Published(key: "fadeDuration", registry: registry) var fadeDuration: Double = 0.2 @Published(key: "iconMoveDuration", registry: registry) var iconMoveDuration: Double = 0.5 From d0592824830c7f556a50a96f78f6d0752fcfe173 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sat, 8 Mar 2025 22:33:57 -0800 Subject: [PATCH 03/19] Indicators Only has grabbers right now, but since it's exporting a UIImage it'd be fairly easy to render app previews into a temporary buffer --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 88 +++++++++++++++++- Sources/Pinnacle/TweakPreferences.swift | 1 + Sources/PinnacleC/Tweak.m | 5 + Sources/PinnacleC/include/Tweak.h | 1 + .../dev.rugmj.pinnacle/grabber.png | Bin 0 -> 12590 bytes .../Main/PreferenceStorage.swift | 5 +- .../Sources/PinnaclePrefs/Main/RootView.swift | 13 ++- 7 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 layout/Library/Tweak Support/dev.rugmj.pinnacle/grabber.png diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index 411ce1f..c1ede19 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -4,6 +4,8 @@ import PinnacleC class SBIconViewHook: ClassHook { @Property var hasInit = false @Property var icon: SBApplicationIcon? + + @Property var grabberView: UIImageView? = nil @Property var row: UInt? = nil @Property var column: UInt? = nil @@ -23,6 +25,23 @@ class SBIconViewHook: ClassHook { guard !target.superview!.isKind(of: SBDockIconListView.classForCoder()) else { return } guard !target.isKind(of: PinnacleIconView.classForCoder()) else { return } + + let iconSize = _pinnacleGetImageSize() + + if (grabberView == nil) { + grabberView = UIImageView(frame: CGRectMake(iconSize.width * -0.06, iconSize.height * -0.06, iconSize.width * 1.12, iconSize.height * 1.12)) + grabberView?.isUserInteractionEnabled = false + grabberView?.contentMode = .scaleAspectFit + + grabberView?.alpha = 1 + } + + _pinnacleUpdateIndicator(bundleID: icon!.applicationBundleID()) + + if (!target.subviews.contains(grabberView!)) { + target.addSubview(grabberView!) + } + target.sendSubviewToBack(grabberView!) guard !hasInit else { return } hasInit = true @@ -50,6 +69,39 @@ class SBIconViewHook: ClassHook { scrollViewPanGesture?.require(toFail: secondSwipeGesture) } } + + // orion:new + func _pinnacleUpdateIndicator(bundleID: String) { + if settings!.indicator == "none" { + grabberView!.image = nil + return + } + + let data = getStackData(for: bundleID) + var direction = 0 + + let offsets = [ + (0, -1), // Up + (1, 0), // Right + (0, 1), // Down + (-1, 0) // Left + ] + + for (index, bundle) in data.enumerated() { + direction = (direction + 1) % 4 + let (xDir, yDir) = offsets[direction] + + if !bundle.contains("dev.rugmj.PinnaclePlaceholder") { + if settings!.indicator == "apps" { + // TODO: App previews + } else { + grabberView!.image = UIImage(contentsOfFile: grabberPath()) + return + } + } + } + grabberView!.image = nil + } // orion:new @objc func _pinnacleHandleActivation() { @@ -156,7 +208,7 @@ class SBIconViewHook: ClassHook { UIView.animate(withDuration: settings!.fadeDuration, animations: { self.target.alpha = 1 }) - + guard !target.icon.isKind(of: SBWidgetIcon.classForCoder()) else { return } if let x = originalX, let y = originalY { @@ -171,12 +223,32 @@ class SBIconViewHook: ClassHook { self.target.frame.origin.x = x } } - + + if icon!.applicationBundleID() != nil { + _pinnacleUpdateIndicator(bundleID: self.icon!.applicationBundleID()) + if (self.grabberView != nil) { + target.sendSubviewToBack(self.grabberView!) + } + } + + UIView.animate( + withDuration: settings!.iconMoveDuration, + delay: 0, + usingSpringWithDamping: settings!.springDamping, + initialSpringVelocity: settings!.springInitialVelocity + ) + { + if (self.grabberView != nil) { + self.grabberView?.alpha = 1 + } + } + for subview in target.subviews { if let iconView = subview as? PinnacleIconView { iconView._pinnacleReset() } } + } @@ -237,7 +309,17 @@ class SBIconViewHook: ClassHook { } else { yDiff *= directions[2] as! Int } - + + + UIView.animate( + withDuration: settings!.iconMoveDuration, + delay: 0, + usingSpringWithDamping: settings!.springDamping, + initialSpringVelocity: settings!.springInitialVelocity + ) + { + self.grabberView?.alpha = 0 + } _pinnacleMoveWith(x: xDiff, y: yDiff) } diff --git a/Sources/Pinnacle/TweakPreferences.swift b/Sources/Pinnacle/TweakPreferences.swift index f4b2358..a9902aa 100644 --- a/Sources/Pinnacle/TweakPreferences.swift +++ b/Sources/Pinnacle/TweakPreferences.swift @@ -27,4 +27,5 @@ struct Settings: Codable { var springInitialVelocity = 0.0 var hapticFeedback = true var activationGestureDirection = "up" + var indicator = "none" } diff --git a/Sources/PinnacleC/Tweak.m b/Sources/PinnacleC/Tweak.m index 98bad0f..cd26cf6 100644 --- a/Sources/PinnacleC/Tweak.m +++ b/Sources/PinnacleC/Tweak.m @@ -11,3 +11,8 @@ return JBROOT_PATH_NSSTRING( @"/Library/Tweak Support/dev.rugmj.pinnacle/plus-circle.png"); } + +NSString *grabberPath() { + return JBROOT_PATH_NSSTRING( + @"/Library/Tweak Support/dev.rugmj.pinnacle/grabber.png"); +} diff --git a/Sources/PinnacleC/include/Tweak.h b/Sources/PinnacleC/include/Tweak.h index 2c7d53d..e13d589 100644 --- a/Sources/PinnacleC/include/Tweak.h +++ b/Sources/PinnacleC/include/Tweak.h @@ -17,6 +17,7 @@ #import NSString *plusCirclePath(); +NSString *grabberPath(); @interface SBSearchScrollView : UIScrollView @end diff --git a/layout/Library/Tweak Support/dev.rugmj.pinnacle/grabber.png b/layout/Library/Tweak Support/dev.rugmj.pinnacle/grabber.png new file mode 100644 index 0000000000000000000000000000000000000000..c88db127c2758facc45cfeff70cbb3042987c172 GIT binary patch literal 12590 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 literal 0 HcmV?d00001 diff --git a/pinnacleprefs/Sources/PinnaclePrefs/Main/PreferenceStorage.swift b/pinnacleprefs/Sources/PinnaclePrefs/Main/PreferenceStorage.swift index 8bd531b..7444444 100644 --- a/pinnacleprefs/Sources/PinnaclePrefs/Main/PreferenceStorage.swift +++ b/pinnacleprefs/Sources/PinnaclePrefs/Main/PreferenceStorage.swift @@ -5,8 +5,8 @@ import libroot final class PreferenceStorage: ObservableObject { static let registry: String = jbRootPath("/var/mobile/Library/Preferences/dev.rugmj.pinnacleprefs.plist") - @Published(key: "enabled", registry: registry) var isEnabled: Bool = true - @Published(key: "showAppLabels", registry: registry) var showAppLabels: Bool = true + @Published(key: "enabled", registry: registry) var isEnabled: Bool = true + @Published(key: "showAppLabels", registry: registry) var showAppLabels: Bool = true @Published(key: "fadeAmount", registry: registry) var fadeAmount: Double = 0.3 @Published(key: "fadeDuration", registry: registry) var fadeDuration: Double = 0.2 @Published(key: "iconMoveDuration", registry: registry) var iconMoveDuration: Double = 0.5 @@ -14,6 +14,7 @@ final class PreferenceStorage: ObservableObject { @Published(key: "springInitialVelocity", registry: registry) var springInitialVelocity: Double = 0.0 @Published(key: "hapticFeedback", registry: registry) var hapticFeedback = true @Published(key: "activationGestureDirection", registry: registry) var activationGestureDirection = "up" + @Published(key: "indicator", registry: registry) var indicator = "none" private var cancellables: Set = [] diff --git a/pinnacleprefs/Sources/PinnaclePrefs/Main/RootView.swift b/pinnacleprefs/Sources/PinnaclePrefs/Main/RootView.swift index 5839e9b..4fa0046 100644 --- a/pinnacleprefs/Sources/PinnaclePrefs/Main/RootView.swift +++ b/pinnacleprefs/Sources/PinnaclePrefs/Main/RootView.swift @@ -41,13 +41,24 @@ struct RootView: View { Section { Picker("Gesture Direction", selection: $preferenceStorage.activationGestureDirection) { Text("Up").tag("up") - Text("Both").tag("both") Text("Down").tag("down") + Text("Either").tag("both") }.pickerStyle(.segmented) } header: { Text("Gesture") } + + Section { + Picker("Visual Indicator", selection: $preferenceStorage.indicator) { + Text("None").tag("none") + Text("Grabbers").tag("grabbers") + //Text("App Previews").tag("apps") + }.pickerStyle(.segmented) + + } header: { + Text("Indicator") + } Section { SliderWithLabel( From 39f8be72f966e8e81f8d8d3df67b8966a9f4e3c7 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sat, 8 Mar 2025 23:32:32 -0800 Subject: [PATCH 04/19] bump version --- control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control b/control index 62613e0..166f45f 100644 --- a/control +++ b/control @@ -1,6 +1,6 @@ Package: dev.rugmj.pinnacle Name: Pinnacle -Version: 1.1.0 +Version: 1.2.0 Architecture: iphoneos-arm Description: A new way to organise your apps Maintainer: rugmj From 38543b97d43214d0cdd0f16008a6d5d5d8cf6ca2 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 9 Mar 2025 09:08:30 -0700 Subject: [PATCH 05/19] fix crash bug (i think) --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index c1ede19..76054c0 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -100,6 +100,7 @@ class SBIconViewHook: ClassHook { } } } + grabberView!.image = nil } @@ -210,7 +211,7 @@ class SBIconViewHook: ClassHook { }) guard !target.icon.isKind(of: SBWidgetIcon.classForCoder()) else { return } - + if let x = originalX, let y = originalY { UIView.animate( withDuration: settings!.iconMoveDuration, @@ -226,23 +227,24 @@ class SBIconViewHook: ClassHook { if icon!.applicationBundleID() != nil { _pinnacleUpdateIndicator(bundleID: self.icon!.applicationBundleID()) - if (self.grabberView != nil) { - target.sendSubviewToBack(self.grabberView!) - } + } else { + self.grabberView!.image = nil } - UIView.animate( - withDuration: settings!.iconMoveDuration, - delay: 0, - usingSpringWithDamping: settings!.springDamping, - initialSpringVelocity: settings!.springInitialVelocity - ) - { - if (self.grabberView != nil) { + if (self.grabberView != nil) { + target.sendSubviewToBack(self.grabberView!) + UIView.animate( + withDuration: settings!.iconMoveDuration, + delay: 0, + usingSpringWithDamping: settings!.springDamping, + initialSpringVelocity: settings!.springInitialVelocity + ) + { self.grabberView?.alpha = 1 } } + for subview in target.subviews { if let iconView = subview as? PinnacleIconView { iconView._pinnacleReset() From 64fa9cd87b96a120248ad28027666ac0729a1309 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 9 Mar 2025 09:13:47 -0700 Subject: [PATCH 06/19] actually fix crash bug --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index 76054c0..b20a31d 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -225,13 +225,12 @@ class SBIconViewHook: ClassHook { } } - if icon!.applicationBundleID() != nil { - _pinnacleUpdateIndicator(bundleID: self.icon!.applicationBundleID()) - } else { - self.grabberView!.image = nil - } - if (self.grabberView != nil) { + if icon!.applicationBundleID() != nil { + _pinnacleUpdateIndicator(bundleID: self.icon!.applicationBundleID()) + } else { + self.grabberView!.image = nil + } target.sendSubviewToBack(self.grabberView!) UIView.animate( withDuration: settings!.iconMoveDuration, From dab23843ff76ee02e13934686c5a781a1b719342 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 9 Mar 2025 09:26:39 -0700 Subject: [PATCH 07/19] I don't know what's crashing help --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index b20a31d..82718ee 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -26,9 +26,9 @@ class SBIconViewHook: ClassHook { guard !target.isKind(of: PinnacleIconView.classForCoder()) else { return } - let iconSize = _pinnacleGetImageSize() - - if (grabberView == nil) { + if (!hasInit) { + let iconSize = _pinnacleGetImageSize() + grabberView = UIImageView(frame: CGRectMake(iconSize.width * -0.06, iconSize.height * -0.06, iconSize.width * 1.12, iconSize.height * 1.12)) grabberView?.isUserInteractionEnabled = false grabberView?.contentMode = .scaleAspectFit @@ -38,7 +38,7 @@ class SBIconViewHook: ClassHook { _pinnacleUpdateIndicator(bundleID: icon!.applicationBundleID()) - if (!target.subviews.contains(grabberView!)) { + if (!hasInit) { target.addSubview(grabberView!) } target.sendSubviewToBack(grabberView!) @@ -73,7 +73,7 @@ class SBIconViewHook: ClassHook { // orion:new func _pinnacleUpdateIndicator(bundleID: String) { if settings!.indicator == "none" { - grabberView!.image = nil + grabberView?.image = nil return } @@ -95,13 +95,13 @@ class SBIconViewHook: ClassHook { if settings!.indicator == "apps" { // TODO: App previews } else { - grabberView!.image = UIImage(contentsOfFile: grabberPath()) + grabberView?.image = UIImage(contentsOfFile: grabberPath()) return } } } - grabberView!.image = nil + grabberView?.image = nil } // orion:new @@ -225,11 +225,11 @@ class SBIconViewHook: ClassHook { } } - if (self.grabberView != nil) { + if self.grabberView != nil { if icon!.applicationBundleID() != nil { _pinnacleUpdateIndicator(bundleID: self.icon!.applicationBundleID()) } else { - self.grabberView!.image = nil + self.grabberView?.image = nil } target.sendSubviewToBack(self.grabberView!) UIView.animate( From f480bc5edb4a6db5ac7927d352cff9753e0438d5 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 9 Mar 2025 09:30:52 -0700 Subject: [PATCH 08/19] hopefully reduce crash issues --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index 82718ee..88c7692 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -26,7 +26,7 @@ class SBIconViewHook: ClassHook { guard !target.isKind(of: PinnacleIconView.classForCoder()) else { return } - if (!hasInit) { + if (grabberView == nil) { let iconSize = _pinnacleGetImageSize() grabberView = UIImageView(frame: CGRectMake(iconSize.width * -0.06, iconSize.height * -0.06, iconSize.width * 1.12, iconSize.height * 1.12)) From 60f2f5c86310f5c81dec1f9aaa57726ce69d10ea Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 9 Mar 2025 10:25:14 -0700 Subject: [PATCH 09/19] Reduce code redundancy --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index 88c7692..ba8fba9 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -105,7 +105,7 @@ class SBIconViewHook: ClassHook { } // orion:new - @objc func _pinnacleHandleActivation() { + @objc func _pinnacleHandleActivation() { guard !target.isFolderIcon() else { return } guard !active else { return } active = true @@ -244,11 +244,9 @@ class SBIconViewHook: ClassHook { } - for subview in target.subviews { - if let iconView = subview as? PinnacleIconView { - iconView._pinnacleReset() - } - } + _pinnacleForSubviews({(iconView: PinnacleIconView) -> Void in + iconView._pinnacleReset() + }) } From 66153203e92ebd999129339a6d4d7aabdebbb1a5 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 9 Mar 2025 13:19:12 -0700 Subject: [PATCH 10/19] fix folder icons getting grabbers for no reason --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index ba8fba9..8203c5f 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -16,7 +16,12 @@ class SBIconViewHook: ClassHook { func didMoveToSuperview() { orig.didMoveToSuperview() - guard !target.isFolderIcon() else { return } + guard !target.isFolderIcon() else { + if grabberView != nil { + grabberView?.image = nil + } + return + } guard target.icon != nil else { return } guard target.icon.isKind(of: SBApplicationIcon.classForCoder()) else { return } icon = target.icon as? SBApplicationIcon From c7e539a263158fa1839561211b23eb33051ed870 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 9 Mar 2025 13:31:32 -0700 Subject: [PATCH 11/19] fix folder icons getting grabbers for the second no reason --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index 8203c5f..4be791d 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -217,6 +217,10 @@ class SBIconViewHook: ClassHook { guard !target.icon.isKind(of: SBWidgetIcon.classForCoder()) else { return } + if target.isFolderIcon() && grabberView != nil { + grabberView?.image = nil + } + if let x = originalX, let y = originalY { UIView.animate( withDuration: settings!.iconMoveDuration, From a302b9668e4ef56012b2c239cea9a4d0ecff6970 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 16 Mar 2025 20:05:59 -0700 Subject: [PATCH 12/19] Hopefully finally fix folders getting grabbers --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index 4be791d..b00f3a8 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -18,7 +18,8 @@ class SBIconViewHook: ClassHook { guard !target.isFolderIcon() else { if grabberView != nil { - grabberView?.image = nil + grabberView?.removeFromSuperview() + grabberView = nil // ARC will catch this } return } @@ -31,7 +32,7 @@ class SBIconViewHook: ClassHook { guard !target.isKind(of: PinnacleIconView.classForCoder()) else { return } - if (grabberView == nil) { + if grabberView == nil { let iconSize = _pinnacleGetImageSize() grabberView = UIImageView(frame: CGRectMake(iconSize.width * -0.06, iconSize.height * -0.06, iconSize.width * 1.12, iconSize.height * 1.12)) @@ -217,10 +218,6 @@ class SBIconViewHook: ClassHook { guard !target.icon.isKind(of: SBWidgetIcon.classForCoder()) else { return } - if target.isFolderIcon() && grabberView != nil { - grabberView?.image = nil - } - if let x = originalX, let y = originalY { UIView.animate( withDuration: settings!.iconMoveDuration, @@ -235,20 +232,25 @@ class SBIconViewHook: ClassHook { } if self.grabberView != nil { - if icon!.applicationBundleID() != nil { - _pinnacleUpdateIndicator(bundleID: self.icon!.applicationBundleID()) + if target.isFolderIcon() { + self.grabberView?.removeFromSuperview() + self.grabberView = nil // ARC will catch this } else { - self.grabberView?.image = nil - } - target.sendSubviewToBack(self.grabberView!) - UIView.animate( - withDuration: settings!.iconMoveDuration, - delay: 0, - usingSpringWithDamping: settings!.springDamping, - initialSpringVelocity: settings!.springInitialVelocity - ) - { - self.grabberView?.alpha = 1 + if icon!.applicationBundleID() != nil { + _pinnacleUpdateIndicator(bundleID: self.icon!.applicationBundleID()) + } else { + self.grabberView?.image = nil + } + target.sendSubviewToBack(self.grabberView!) + UIView.animate( + withDuration: settings!.iconMoveDuration, + delay: 0, + usingSpringWithDamping: settings!.springDamping, + initialSpringVelocity: settings!.springInitialVelocity + ) + { + self.grabberView?.alpha = 1 + } } } From ac578bd17f49062deed6a0b881bfa9a288f1b46f Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 16 Mar 2025 20:15:38 -0700 Subject: [PATCH 13/19] get git to stop getting on my tail about .swiftpm (whatever that is) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 01cf0d1..9e84833 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /Packages /*.xcodeproj xcuserdata/ +.swiftpm .theos /packages From 2217e25cd81e3216be228e42798adfd9151c9c71 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 16 Mar 2025 20:36:12 -0700 Subject: [PATCH 14/19] Finally fix folders getting icons --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index b00f3a8..531cf46 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -19,7 +19,6 @@ class SBIconViewHook: ClassHook { guard !target.isFolderIcon() else { if grabberView != nil { grabberView?.removeFromSuperview() - grabberView = nil // ARC will catch this } return } @@ -44,7 +43,7 @@ class SBIconViewHook: ClassHook { _pinnacleUpdateIndicator(bundleID: icon!.applicationBundleID()) - if (!hasInit) { + if !grabberView!.isDescendant(of: target) { target.addSubview(grabberView!) } target.sendSubviewToBack(grabberView!) @@ -234,8 +233,10 @@ class SBIconViewHook: ClassHook { if self.grabberView != nil { if target.isFolderIcon() { self.grabberView?.removeFromSuperview() - self.grabberView = nil // ARC will catch this } else { + if !self.grabberView!.isDescendant(of: target) { + target.addSubview(self.grabberView!) + } if icon!.applicationBundleID() != nil { _pinnacleUpdateIndicator(bundleID: self.icon!.applicationBundleID()) } else { From b5820100c486bd424b66e839d290044ee5b101df Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 16 Mar 2025 21:06:25 -0700 Subject: [PATCH 15/19] Memory optimization Might also apply to placeholder icons later --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 6 +++++- Sources/Pinnacle/Tweak.x.swift | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index 531cf46..7e8e9ec 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -31,6 +31,10 @@ class SBIconViewHook: ClassHook { guard !target.isKind(of: PinnacleIconView.classForCoder()) else { return } + if grabberImage == nil { + grabberImage = UIImage(contentsOfFile: grabberPath()) + } + if grabberView == nil { let iconSize = _pinnacleGetImageSize() @@ -100,7 +104,7 @@ class SBIconViewHook: ClassHook { if settings!.indicator == "apps" { // TODO: App previews } else { - grabberView?.image = UIImage(contentsOfFile: grabberPath()) + grabberView?.image = grabberImage return } } diff --git a/Sources/Pinnacle/Tweak.x.swift b/Sources/Pinnacle/Tweak.x.swift index 528ebbe..f50fa8c 100644 --- a/Sources/Pinnacle/Tweak.x.swift +++ b/Sources/Pinnacle/Tweak.x.swift @@ -102,3 +102,5 @@ func normalise(_ number: Int) -> Int { } var settings: Settings? + +var grabberImage: UIImage? = nil From f05b418a7b6a79efd4cef1dc6055d972fdaad693 Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sun, 16 Mar 2025 21:15:17 -0700 Subject: [PATCH 16/19] More memory optimizations --- Sources/Pinnacle/PinnacleIconView.swift | 6 ++++-- Sources/Pinnacle/Tweak.x.swift | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/Pinnacle/PinnacleIconView.swift b/Sources/Pinnacle/PinnacleIconView.swift index 11afedc..fb82251 100644 --- a/Sources/Pinnacle/PinnacleIconView.swift +++ b/Sources/Pinnacle/PinnacleIconView.swift @@ -35,9 +35,11 @@ class PinnacleIconView: SBIconView { self.init() setupCommonProperties(xDir: xDir, yDir: yDir, bundle: bundle, parentBundle: parentBundle, index: index) - let image = UIImage(contentsOfFile: plusCirclePath()) + if placeholderImage == nil { + placeholderImage = UIImage(contentsOfFile: plusCirclePath()) + } - let imageView = UIImageView(image: image) + let imageView = UIImageView(image: placeholderImage) imageView.frame = CGRect(x: 0, y: 0, width: 60, height: 60) imageView.isUserInteractionEnabled = true diff --git a/Sources/Pinnacle/Tweak.x.swift b/Sources/Pinnacle/Tweak.x.swift index f50fa8c..bf059fc 100644 --- a/Sources/Pinnacle/Tweak.x.swift +++ b/Sources/Pinnacle/Tweak.x.swift @@ -104,3 +104,4 @@ func normalise(_ number: Int) -> Int { var settings: Settings? var grabberImage: UIImage? = nil +var placeholderImage: UIImage? = nil From 0b39d5965ebf62570c821adceb743768a64df03d Mon Sep 17 00:00:00 2001 From: UBC Student Date: Fri, 9 May 2025 23:27:44 -0700 Subject: [PATCH 17/19] Fix the folder crash bug (still causes weird bugs) --- Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift index ea710ab..77f3c9f 100644 --- a/Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift @@ -69,14 +69,22 @@ class SBIconListViewHook: ClassHook { // orion:new func _pinnacleForIconViews(_ action:(SBIconView) -> Void) { var iconViews: [UIView] + remLog("entered for icon views") + remLog(target) + if target.subviews.isEmpty { + remLog("no subviews") + return + } // Test fix for folder crash bug if target.subviews[0].isKind(of: SBFTouchPassThroughView.classForCoder()) { iconViews = target.subviews[0].subviews + remLog("using nested subviews") } else { iconViews = target.subviews } iconViews.forEach({ guard let iconView = $0 as? SBIconView else { return } + remLog(iconView) action(iconView) }) } From 061ddbdb2f0b8923a282b5516fa65b7f74a9269a Mon Sep 17 00:00:00 2001 From: UBC Student Date: Fri, 9 May 2025 23:45:12 -0700 Subject: [PATCH 18/19] fix code formatting --- Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift index 77f3c9f..f1d83df 100644 --- a/Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconListViewHook.x.swift @@ -68,23 +68,16 @@ class SBIconListViewHook: ClassHook { // orion:new func _pinnacleForIconViews(_ action:(SBIconView) -> Void) { + if target.subviews.isEmpty { return } // Fixes a crash issue var iconViews: [UIView] - remLog("entered for icon views") - remLog(target) - if target.subviews.isEmpty { - remLog("no subviews") - return - } // Test fix for folder crash bug if target.subviews[0].isKind(of: SBFTouchPassThroughView.classForCoder()) { iconViews = target.subviews[0].subviews - remLog("using nested subviews") } else { iconViews = target.subviews } iconViews.forEach({ guard let iconView = $0 as? SBIconView else { return } - remLog(iconView) action(iconView) }) } From e877fd7e8d42854a840afb815a703493df99761b Mon Sep 17 00:00:00 2001 From: UBC Student Date: Sat, 10 May 2025 00:14:06 -0700 Subject: [PATCH 19/19] fixed folder visual bug --- Sources/Pinnacle/Hooks/SBIconViewHook.x.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift index 7e8e9ec..efde56d 100644 --- a/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift +++ b/Sources/Pinnacle/Hooks/SBIconViewHook.x.swift @@ -41,16 +41,19 @@ class SBIconViewHook: ClassHook { grabberView = UIImageView(frame: CGRectMake(iconSize.width * -0.06, iconSize.height * -0.06, iconSize.width * 1.12, iconSize.height * 1.12)) grabberView?.isUserInteractionEnabled = false grabberView?.contentMode = .scaleAspectFit - - grabberView?.alpha = 1 } + grabberView?.alpha = 1 _pinnacleUpdateIndicator(bundleID: icon!.applicationBundleID()) if !grabberView!.isDescendant(of: target) { target.addSubview(grabberView!) } target.sendSubviewToBack(grabberView!) + + _pinnacleForSubviews({(iconView: PinnacleIconView) -> Void in + iconView.removeFromSuperview() + }) guard !hasInit else { return } hasInit = true