From f6c79bd56c05b3f2dee7cee1680a691065ac846b Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Sat, 16 Nov 2024 18:53:36 -0500 Subject: [PATCH] repeated nav on L/R hold Signed-off-by: Joseph Mattiello --- .../PVSwiftUI/Consoles/ConsoleGamesView.swift | 2 +- .../GamepadManager.swift | 4 +-- PVUI/Sources/PVSwiftUI/Home/HomeView.swift | 2 +- .../RootView/PVRootViewController.swift | 32 +++++++++++++++++++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/PVUI/Sources/PVSwiftUI/Consoles/ConsoleGamesView.swift b/PVUI/Sources/PVSwiftUI/Consoles/ConsoleGamesView.swift index b1a19f0fa6..d487fa9093 100644 --- a/PVUI/Sources/PVSwiftUI/Consoles/ConsoleGamesView.swift +++ b/PVUI/Sources/PVSwiftUI/Consoles/ConsoleGamesView.swift @@ -545,7 +545,7 @@ struct ConsoleGamesView: SwiftUI.View, GameContextMenuDelegate { } } } - case .horizontalNavigation(let value): + case .horizontalNavigation(let value, _): handleHorizontalNavigation(value) case .start: if let focusedItem = focusedItemInSection { diff --git a/PVUI/Sources/PVSwiftUI/GameControllerNavigation/GamepadManager.swift b/PVUI/Sources/PVSwiftUI/GameControllerNavigation/GamepadManager.swift index f8c2271eca..8625bcc10a 100644 --- a/PVUI/Sources/PVSwiftUI/GameControllerNavigation/GamepadManager.swift +++ b/PVUI/Sources/PVSwiftUI/GameControllerNavigation/GamepadManager.swift @@ -7,7 +7,7 @@ public enum GamepadEvent { case buttonPress case buttonB case verticalNavigation(Float, Bool) - case horizontalNavigation(Float) + case horizontalNavigation(Float, Bool) case menuToggle case shoulderLeft case shoulderRight @@ -80,7 +80,7 @@ public class GamepadManager: ObservableObject { if abs(yValue) == 1.0 { self?.eventSubject.send(.verticalNavigation(yValue, dpad.up.isPressed || dpad.down.isPressed)) } else if abs(xValue) == 1.0 { - self?.eventSubject.send(.horizontalNavigation(xValue)) + self?.eventSubject.send(.horizontalNavigation(xValue, dpad.left.isPressed || dpad.right.isPressed)) } } } diff --git a/PVUI/Sources/PVSwiftUI/Home/HomeView.swift b/PVUI/Sources/PVSwiftUI/Home/HomeView.swift index 9bf911d454..ad43cd6064 100644 --- a/PVUI/Sources/PVSwiftUI/Home/HomeView.swift +++ b/PVUI/Sources/PVSwiftUI/Home/HomeView.swift @@ -174,7 +174,7 @@ struct HomeView: SwiftUI.View { } } } - case .horizontalNavigation(let value): + case .horizontalNavigation(let value, _): handleHorizontalNavigation(value) case .start: if let focusedItem = focusedItemInSection { diff --git a/PVUI/Sources/PVSwiftUI/RootView/PVRootViewController.swift b/PVUI/Sources/PVSwiftUI/RootView/PVRootViewController.swift index 0268bb42f2..ea24b56527 100644 --- a/PVUI/Sources/PVSwiftUI/RootView/PVRootViewController.swift +++ b/PVUI/Sources/PVSwiftUI/RootView/PVRootViewController.swift @@ -69,6 +69,10 @@ public class PVRootViewController: UIViewController, GameLaunchingViewController private var gameController: GCController? private var controllerObserver: Any? + private var navigationTimer: Timer? + private let initialDelay: TimeInterval = 0.5 + private let repeatDelay: TimeInterval = 0.15 + public static func instantiate(updatesController: PVGameLibraryUpdatesController, gameLibrary: PVGameLibrary, gameImporter: GameImporter, viewModel: PVRootViewModel) -> PVRootViewController { let controller = PVRootViewController() controller.updatesController = updatesController @@ -103,6 +107,7 @@ public class PVRootViewController: UIViewController, GameLaunchingViewController public override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(controllerObserver as Any) + navigationTimer?.invalidate() gameController = nil } @@ -184,10 +189,37 @@ public class PVRootViewController: UIViewController, GameLaunchingViewController self.showMenu() } case .shoulderLeft: + // Cancel existing timer + navigationTimer?.invalidate() + navigationTimer = nil + + // Initial navigation navigateToPrevious() + + // Setup continuous navigation + navigationTimer = Timer.scheduledTimer(withTimeInterval: initialDelay, repeats: false) { [self] _ in + self.navigationTimer = Timer.scheduledTimer(withTimeInterval: self.repeatDelay, repeats: true) { [self] _ in + self.navigateToPrevious() + } + } case .shoulderRight: + // Cancel existing timer + navigationTimer?.invalidate() + navigationTimer = nil + + // Initial navigation navigateToNext() + + // Setup continuous navigation + navigationTimer = Timer.scheduledTimer(withTimeInterval: initialDelay, repeats: false) { [self] _ in + self.navigationTimer = Timer.scheduledTimer(withTimeInterval: self.repeatDelay, repeats: true) { [self] _ in + self.navigateToNext() + } + } default: + // Cancel any existing timer when other buttons are pressed + navigationTimer?.invalidate() + navigationTimer = nil break } }