From e62699749d303b5d70519041d88e26188498051c Mon Sep 17 00:00:00 2001 From: Bryce Hackel <34104885+bhackel@users.noreply.github.com> Date: Fri, 16 Aug 2024 00:25:24 -0700 Subject: [PATCH] Sensitivity and Deadzone settings --- Source/Settings.xm | 82 ++++++++++++++++++++++++++++++++++++++++++++-- YTLitePlus.h | 12 +++++++ YTLitePlus.xm | 37 ++++++++++----------- 3 files changed, 108 insertions(+), 23 deletions(-) diff --git a/Source/Settings.xm b/Source/Settings.xm index b1b1fb8..5e0cd76 100644 --- a/Source/Settings.xm +++ b/Source/Settings.xm @@ -221,7 +221,6 @@ static const NSInteger YTLiteSection = 789; } }; - // Helper to generate checkmark setting items for selecting gesture modes static YTSettingsSectionItem* (^gestureCheckmarkSettingItem)(NSInteger, NSString *) = ^(NSInteger idx, NSString *key) { return [YTSettingsSectionItemClass @@ -247,7 +246,7 @@ static const NSInteger YTLiteSection = 789; gestureCheckmarkSettingItem(1, sectionKey), gestureCheckmarkSettingItem(2, sectionKey) ]; - + // Present picker when selecting this settings item YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(sectionLabel) pickerSectionTitle:nil @@ -260,12 +259,89 @@ static const NSInteger YTLiteSection = 789; } ]; }; + // Configuration picker for deadzone to pick from 0 to 100 pixels with interval of 10 + YTSettingsSectionItem *deadzonePicker = [YTSettingsSectionItemClass + itemWithTitle:LOC(@"Deadzone (Beta)") + accessibilityIdentifier:nil + detailTextBlock:^NSString *() { + return [NSString stringWithFormat:@"%ld px", (long)GetFloat(@"playerGestureDeadzone") * 10]; + } + selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { + // Generate rows for deadzone picker + NSMutableArray *deadzoneRows = [NSMutableArray array]; + for (int i = 0; i <= 10; i++) { + [deadzoneRows addObject:[YTSettingsSectionItemClass + checkmarkItemWithTitle:[NSString stringWithFormat:@"%ld px", (long)i * 10] + selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { + [[NSUserDefaults standardUserDefaults] setInteger:i forKey:@"playerGestureDeadzone"]; + [settingsViewController reloadData]; + return YES; + } + ]]; + } + // Present deadzone picker when selecting this settings item + YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] + initWithNavTitle:LOC(@"Deadzone (Beta)") + pickerSectionTitle:nil + rows:deadzoneRows + selectedItemIndex:GetFloat(@"playerGestureDeadzone") + parentResponder:[self parentResponder] + ]; + [settingsViewController pushViewController:picker]; + return YES; + } + ]; + // Configuration picker for sensitivity to pick from 0.5 to 2.0 with interval of 0.1 + YTSettingsSectionItem *sensitivtyPicker = [YTSettingsSectionItemClass + itemWithTitle:LOC(@"Sensitivity (Beta)") + accessibilityIdentifier:nil + detailTextBlock:^NSString *() { + return [NSString stringWithFormat:@"%.1f", GetFloat(@"playerGestureSensitivity") * 0.1 + 0.5]; + } + selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { + // Generate rows for sensitivity picker + NSMutableArray *sensitivityRows = [NSMutableArray array]; + for (int i = 5; i <= 20; i++) { + [sensitivityRows addObject:[YTSettingsSectionItemClass + checkmarkItemWithTitle:[NSString stringWithFormat:@"%.1f", i * 0.1] + selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { + [[NSUserDefaults standardUserDefaults] setInteger:i forKey:@"playerGestureSensitivity"]; + [settingsViewController reloadData]; + return YES; + } + ]]; + } + // Present sensitivity picker + YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] + initWithNavTitle:LOC(@"Sensitivity (Beta)") + pickerSectionTitle:nil + rows:sensitivityRows + selectedItemIndex:GetFloat(@"playerGestureSensitivity") + parentResponder:[self parentResponder] + ]; + [settingsViewController pushViewController:picker]; + return YES; + } + ] + + // High level gestures menu YTSettingsSectionItem *playerGesturesGroup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Player Gestures (Beta)") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { NSArray *rows = @[ + // Description header item + [YTSettingsSectionItemClass + itemWithTitle:nil + accessibilityIdentifier:nil + detailTextBlock:LOC(@"Configure horizontal pan gestures for the player.") + selectBlock:nil + ], + // Pickers for each gesture section createSectionGestureSelector(@"Top Section (Beta)", @"playerGestureTopSelection"), createSectionGestureSelector(@"Middle Section (Beta)", @"playerGestureMiddleSelection"), - createSectionGestureSelector(@"Bottom Section (Beta)", @"playerGestureBottomSelection") + createSectionGestureSelector(@"Bottom Section (Beta)", @"playerGestureBottomSelection"), + // Pickers for configuration settings + deadzonePicker, + sensitivityPicker ]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Player Gestures (Beta)") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; [settingsViewController pushViewController:picker]; diff --git a/YTLitePlus.h b/YTLitePlus.h index 9261cfe..52ac085 100644 --- a/YTLitePlus.h +++ b/YTLitePlus.h @@ -58,6 +58,7 @@ // Helper methods for key retrieval #define IsEnabled(key) [[NSUserDefaults standardUserDefaults] boolForKey:key] #define GetSelection(key) [[NSUserDefaults standardUserDefaults] integerForKey:key] +#define GetFloat(key) [[NSUserDefaults standardUserDefaults] floatForKey:key] // Player Gesture selected mode enum @@ -149,6 +150,17 @@ typedef NS_ENUM(NSUInteger, GestureSection) { @property id parentResponder; @end +// Player Gestures - @bhackel +@interface YTPlayerViewController (YTLitePlus) +@property (nonatomic, retain) UIPanGestureRecognizer *YTLitePlusPanGesture; +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; +@end +@interface YTWatchFullscreenViewController : YTMultiSizeViewController +@end +@interface MPVolumeController : NSObject +@property (nonatomic, assign, readwrite) float volumeValue; +@end + // Hide Collapse Button - @arichornlover @interface YTMainAppControlsOverlayView (YTLitePlus) @property (nonatomic, assign, readwrite) YTQTMButton *watchCollapseButton; diff --git a/YTLitePlus.xm b/YTLitePlus.xm index 2055fea..fed5597 100644 --- a/YTLitePlus.xm +++ b/YTLitePlus.xm @@ -640,17 +640,6 @@ BOOL isTabSelected = NO; } %end -@interface YTPlayerViewController (YTLitePlus) -// the long press gesture that will be created and added to the player view -@property (nonatomic, retain) UIPanGestureRecognizer *YTLitePlusPanGesture; -- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; -@end -@interface YTWatchFullscreenViewController : YTMultiSizeViewController -@end -@interface MPVolumeController : NSObject -@property (nonatomic, assign, readwrite) float volumeValue; -@end - // Gestures - @bhackel %group playerGestures %hook YTWatchLayerViewController @@ -689,19 +678,21 @@ BOOL isTabSelected = NO; static CGPoint startLocation; // Variable to track the X translation when exiting the deadzone static CGFloat deadzoneStartingXTranslation; - // Constants for the deadzone radius that can be changed in the settings - static CGFloat deadzoneRadius = 20.0; + // Constant for the deadzone radius that can be changed in the settings + static CGFloat deadzoneRadius = (CGFloat)GetFloat(@"playerGesturesDeadzone"); + // Constant for the sensitivity factor that can be changed in the settings + static CGFloat sensitivityFactor = (CGFloat)GetFloat(@"playerGestureSensitivity"); /***** Helper functions *****/ // Helper function to adjust brightness void (^adjustBrightness)(CGFloat, CGFloat) = ^(CGFloat translationX, CGFloat initialBrightness) { - float newBrightness = initialBrightness + (translationX / 1000.0); + float newBrightness = initialBrightness + ((translationX / 1000.0) * sensitivityFactor); newBrightness = fmaxf(fminf(newBrightness, 1.0), 0.0); [[UIScreen mainScreen] setBrightness:newBrightness]; }; // Helper function to adjust volume void (^adjustVolume)(CGFloat, CGFloat) = ^(CGFloat translationX, CGFloat initialVolume) { - float newVolume = initialVolume + (translationX / 1000.0); + float newVolume = initialVolume + ((translationX / 1000.0) * sensitivityFactor); newVolume = fmaxf(fminf(newVolume, 1.0), 0.0); // https://stackoverflow.com/questions/50737943/how-to-change-volume-programmatically-on-ios-11-4 MPVolumeView *volumeView = [[MPVolumeView alloc] init]; @@ -769,8 +760,7 @@ BOOL isTabSelected = NO; } else if (startLocation.y <= viewHeight) { gestureSection = GestureSectionBottom; } - - // Deactive the flag + // Deactive the activity flag isValidHorizontalPan = NO; } @@ -791,6 +781,9 @@ BOOL isTabSelected = NO; initialBrightness = [UIScreen mainScreen].brightness; initialVolume = [[AVAudioSession sharedInstance] outputVolume]; currentTime = self.currentVideoMediaTime; + // Provide haptic feedback to indicate a gesture start + [feedbackGenerator prepare]; + [feedbackGenerator impactOccurred]; } else { // Cancel the gesture if the translation is not horizontal panGestureRecognizer.state = UIGestureRecognizerStateCancelled; @@ -813,7 +806,6 @@ BOOL isTabSelected = NO; } } } - if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) { if (isValidHorizontalPan) { // Provide haptic feedback upon successful gesture recognition @@ -823,13 +815,11 @@ BOOL isTabSelected = NO; } } - // allow the pan gesture to be recognized simultaneously with other gestures %new - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } - %end %end @@ -1090,4 +1080,11 @@ BOOL isTabSelected = NO; if (![allKeys containsObject:@"playerGestureBottomSelection"]) { [[NSUserDefaults standardUserDefaults] setInteger:GestureModeSeek forKey:@"playerGestureBottomSelection"]; } + // Default configuration options for gestures + if (![allKeys containsObject:@"playerGesturesDeadzone"]) { + [[NSUserDefaults standardUserDefaults] setFloat:20.0 forKey:@"playerGesturesDeadzone"]; + } + if (![allKeys containsObject:@"playerGestureSensitivity"]) { + [[NSUserDefaults standardUserDefaults] setFloat:1.0 forKey:@"playerGestureSensitivity"]; + } }