mirror of
https://github.com/SoPat712/YTLitePlus.git
synced 2025-10-30 12:33:57 -04:00
added files via upload
This commit is contained in:
3
Tweaks/YTHoldForSpeed/.gitignore
vendored
Normal file
3
Tweaks/YTHoldForSpeed/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.theos
|
||||
.DS_Store
|
||||
packages
|
||||
14
Tweaks/YTHoldForSpeed/Makefile
Normal file
14
Tweaks/YTHoldForSpeed/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
TARGET := iphone:clang:15.5:14.0
|
||||
INSTALL_TARGET_PROCESSES = YouTube
|
||||
|
||||
include $(THEOS)/makefiles/common.mk
|
||||
|
||||
TWEAK_NAME = ytholdforspeed
|
||||
|
||||
ytholdforspeed_FILES = YTHFSTweak.x YTHFSSettings.x YTHFSPrefsManager.m
|
||||
ytholdforspeed_CFLAGS = -fobjc-arc
|
||||
|
||||
THEOS_PACKAGE_BASE_VERSION = 1.0.3
|
||||
_THEOS_INTERNAL_PACKAGE_VERSION = 1.0.3
|
||||
|
||||
include $(THEOS_MAKE_PATH)/tweak.mk
|
||||
120
Tweaks/YTHoldForSpeed/YTHFSHeaders.h
Normal file
120
Tweaks/YTHoldForSpeed/YTHFSHeaders.h
Normal file
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// YTHFSHeaders.h
|
||||
//
|
||||
// Created by Joshua Seltzer on 12/5/22.
|
||||
//
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <rootless.h>
|
||||
|
||||
@interface YTDoubleTapToSeekView : UIView
|
||||
|
||||
// shows feedback with the given title text and direction
|
||||
- (void)showCenteredSeekFeedbackWithTitle:(NSString *)title direction:(NSInteger)direction;
|
||||
|
||||
@end
|
||||
|
||||
@interface YTMainAppVideoPlayerOverlayView : UIView
|
||||
|
||||
// the view that is used to display that the double tap to seek gesture was invoked
|
||||
@property (readonly, nonatomic) YTDoubleTapToSeekView *doubleTapToSeekView;
|
||||
|
||||
@end
|
||||
|
||||
// the controller responsible for handling changes to the playback speed
|
||||
@interface YTVarispeedSwitchController : NSObject
|
||||
@end
|
||||
|
||||
@interface YTPlayerView : UIView
|
||||
|
||||
// the overlay view which includes the double tap to seek view
|
||||
@property (retain, nonatomic) UIView *overlayView;
|
||||
|
||||
@end
|
||||
|
||||
@interface YTPlayerViewController : UIViewController
|
||||
|
||||
// the main view for viewing videos
|
||||
@property (readonly, nonatomic) YTPlayerView *playerView;
|
||||
|
||||
// the controller responsible for allowing the user to switch the playback speed
|
||||
@property (readonly, nonatomic) YTVarispeedSwitchController *varispeedController;
|
||||
|
||||
// the overlay controller that will be used to potentially hide the player controls
|
||||
@property (readonly, nonatomic) UIViewController *contentVideoPlayerOverlay;
|
||||
|
||||
// returns whether or not the play controls are currently hidden or visible
|
||||
- (BOOL)arePlayerControlsHidden;
|
||||
|
||||
// returns the current playback speed
|
||||
- (float)currentPlaybackRateForVarispeedSwitchController:(YTVarispeedSwitchController *)varispeedSwitchController;
|
||||
|
||||
// invoked whenever the playback speed selection is changed
|
||||
- (void)varispeedSwitchController:(YTVarispeedSwitchController *)varispeedSwitchController didSelectRate:(float)rate;
|
||||
|
||||
@end
|
||||
|
||||
@interface YTMainAppVideoPlayerOverlayViewController : UIViewController
|
||||
|
||||
// indicates whether or not the playback speed of the video can be changed
|
||||
@property (readonly, nonatomic) BOOL isVarispeedAvailable;
|
||||
|
||||
// hide the player controls programatically
|
||||
- (void)hidePlayerControlsAnimated:(BOOL)animated;
|
||||
|
||||
@end
|
||||
|
||||
// controller which is updated with the launch and dismissal of the player view controller
|
||||
@interface YTWatchController : NSObject
|
||||
@end
|
||||
|
||||
// manager responsible for handling the app's preferences
|
||||
@interface YTSettingsSectionItemManager : NSObject
|
||||
|
||||
// required when creating setting sections that have user selection
|
||||
- (id)parentResponder;
|
||||
|
||||
@end
|
||||
|
||||
// view controller that displays settings information
|
||||
@interface YTStyledViewController
|
||||
@end
|
||||
@interface YTSettingsViewController : YTStyledViewController
|
||||
|
||||
// reloads the setting sections in the settings view controller
|
||||
- (void)reloadData;
|
||||
|
||||
// push a new controller on the navigation stack
|
||||
- (void)pushViewController:(id)viewController;
|
||||
|
||||
// sets the array of section items for a given settings category
|
||||
- (void)setSectionItems:(NSArray *)sectionItems forCategory:(NSInteger)categoryId title:(NSString *)title titleDescription:(NSString *)titleDescription headerHidden:(BOOL)hidden;
|
||||
|
||||
@end
|
||||
|
||||
// view controller that displays selectable settings
|
||||
@interface YTSettingsPickerViewController : YTStyledViewController
|
||||
|
||||
// initialize a new picker view controller
|
||||
- (id)initWithNavTitle:(NSString *)navTitle pickerSectionTitle:(NSString *)pickerSectionTitle rows:(NSArray *)rows selectedItemIndex:(NSUInteger)index parentResponder:(id)responder;
|
||||
|
||||
@end
|
||||
|
||||
// a cell in the settings view controller
|
||||
@interface YTSettingsCell
|
||||
@end
|
||||
|
||||
// an item which defines a section inside a settings controller
|
||||
@interface YTSettingsSectionItem : NSObject
|
||||
|
||||
// create a new setting item with an on/off switch, title, and optional description
|
||||
+ (id)switchItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(id)identifier switchOn:(BOOL)enabled switchBlock:(id)switchBlock settingItemId:(NSInteger)itemId;
|
||||
|
||||
// create a new item with a title, selected detail text, and a selection block which can push another instance of a settings controller
|
||||
+ (id)itemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(id)identifier detailTextBlock:(id)detailTextBlock selectBlock:(id)selectBlock;
|
||||
|
||||
// create a checkmark item with a title and select block
|
||||
+ (id)checkmarkItemWithTitle:(NSString *)title selectBlock:(id)selectBlock;
|
||||
|
||||
@end
|
||||
76
Tweaks/YTHoldForSpeed/YTHFSPrefsManager.h
Normal file
76
Tweaks/YTHoldForSpeed/YTHFSPrefsManager.h
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// YTHFSPrefsManager.h
|
||||
//
|
||||
// Created by Joshua Seltzer on 12/5/22.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
// enum to define the options for the hold duration
|
||||
typedef enum YTHFSHoldDurationOption : NSInteger {
|
||||
kYTHFSHoldDurationOption025,
|
||||
kYTHFSHoldDurationOption050,
|
||||
kYTHFSHoldDurationOption075,
|
||||
kYTHFSHoldDurationOption100,
|
||||
kYTHFSHoldDurationOption125,
|
||||
kYTHFSHoldDurationOption150,
|
||||
kYTHFSHoldDurationOption175,
|
||||
kYTHFSHoldDurationOption200
|
||||
} YTHFSHoldDurationOption;
|
||||
|
||||
// enum to define the options for the playback rate
|
||||
typedef enum YTHFSPlaybackRateOption : NSInteger {
|
||||
kYTHFSPlaybackRateOption025,
|
||||
kYTHFSPlaybackRateOption050,
|
||||
kYTHFSPlaybackRateOption075,
|
||||
kYTHFSPlaybackRateOption125,
|
||||
kYTHFSPlaybackRateOption150,
|
||||
kYTHFSPlaybackRateOption175,
|
||||
kYTHFSPlaybackRateOption200
|
||||
} YTHFSPlaybackRateOption;
|
||||
|
||||
// manager that manages the preferences for the tweak
|
||||
@interface YTHFSPrefsManager : NSObject
|
||||
|
||||
// return a localized string with a given default value from the localization files in the tweak bundle
|
||||
+ (NSString *)localizedStringForKey:(NSString *)key withDefaultValue:(NSString *)defaultValue;
|
||||
|
||||
// intended to be invoked when the tweak is initialized to ensure all of the default values are available
|
||||
+ (void)registerDefaults;
|
||||
|
||||
// returns whether or not the device supports haptic feedback
|
||||
+ (BOOL)supportsHapticFeedback;
|
||||
|
||||
// return the value that corresponds to the given hold duration option
|
||||
+ (CGFloat)holdDurationValueForOption:(YTHFSHoldDurationOption)holdDurationOption;
|
||||
|
||||
// return the value that corresponds to the given playback rate option
|
||||
+ (CGFloat)playbackRateValueForOption:(YTHFSPlaybackRateOption)playbackRateOption;
|
||||
|
||||
// return the hold playback option for the given value
|
||||
+ (YTHFSHoldDurationOption)holdDurationOptionForValue:(CGFloat)value;
|
||||
|
||||
// return the playback rate option for the given value
|
||||
+ (YTHFSPlaybackRateOption)playbackRateOptionForValue:(CGFloat)value;
|
||||
|
||||
// return the appropriate string representation of the hold duration for the given value
|
||||
+ (NSString *)holdDurationStringForValue:(CGFloat)value;
|
||||
|
||||
// return the appropriate string representation of the playback rate for the given value
|
||||
+ (NSString *)playbackRateStringForValue:(CGFloat)value;
|
||||
|
||||
// setters and getters for the tweak preferences
|
||||
+ (BOOL)holdGestureEnabled;
|
||||
+ (void)setHoldGestureEnabled:(BOOL)enabled;
|
||||
+ (BOOL)autoApplyRateEnabled;
|
||||
+ (void)setAutoApplyRateEnabled:(BOOL)enabled;
|
||||
+ (CGFloat)togglePlaybackRate;
|
||||
+ (void)setTogglePlaybackRate:(CGFloat)playbackRate;
|
||||
+ (CGFloat)holdDuration;
|
||||
+ (void)setHoldDuration:(CGFloat)holdDuration;
|
||||
+ (BOOL)hapticFeedbackEnabled;
|
||||
+ (void)setHapticFeedbackEnabled:(BOOL)enabled;
|
||||
|
||||
@end
|
||||
194
Tweaks/YTHoldForSpeed/YTHFSPrefsManager.m
Normal file
194
Tweaks/YTHoldForSpeed/YTHFSPrefsManager.m
Normal file
@@ -0,0 +1,194 @@
|
||||
//
|
||||
// YTHFSPrefsManager.m
|
||||
//
|
||||
// Created by Joshua Seltzer on 12/5/22.
|
||||
//
|
||||
//
|
||||
|
||||
#import "YTHFSPrefsManager.h"
|
||||
#import <CoreHaptics/CoreHaptics.h>
|
||||
#import <sys/utsname.h>
|
||||
#import <rootless.h>
|
||||
|
||||
// define constants for the keys used to interact with the settings within user defaults
|
||||
#define kYTHFSHoldGestureEnabledKey @"YTHFSHoldGestureEnabled"
|
||||
#define kYTHFSAutoApplyRateEnabledKey @"YTHFSAutoApplyRateEnabled"
|
||||
#define kYTHFSTogglePlaybackRateKey @"YTHFSTogglePlaybackRate"
|
||||
#define kYTHFSHoldDurationKey @"YTHFSHoldDuration"
|
||||
#define kYTHFSHapticFeedbackEnabledKey @"YTHFSHapticFeedbackEnabled"
|
||||
|
||||
// define some constants to define the default preference values
|
||||
#define kYTHFSDefaultHoldGestureEnabled YES
|
||||
#define kYTHFSDefaultAutoApplyRateEnabled NO
|
||||
#define kYTHFSDefaultTogglePlaybackRate 1.5
|
||||
#define kYTHFSDefaultHoldDuration 1.0
|
||||
|
||||
// create static variables that will be determined once
|
||||
static NSBundle *sYTHFSBundle;
|
||||
static BOOL sYTHFSSupportsHapticFeedback;
|
||||
static NSNumberFormatter *sYTHFSDecimalNumberFormatter;
|
||||
|
||||
@implementation YTHFSPrefsManager
|
||||
|
||||
// return a localized string with a given default value from the localization files in the tweak bundle
|
||||
+ (NSString *)localizedStringForKey:(NSString *)key withDefaultValue:(NSString *)defaultValue
|
||||
{
|
||||
NSBundle *tweakBundle = [YTHFSPrefsManager bundle];
|
||||
if (tweakBundle != nil) {
|
||||
return [tweakBundle localizedStringForKey:key value:defaultValue table:@"Localizable"];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
// intended to be invoked when the tweak is initialized to ensure all of the default values are available
|
||||
+ (void)registerDefaults
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] registerDefaults:@{kYTHFSHoldGestureEnabledKey:[NSNumber numberWithBool:kYTHFSDefaultHoldGestureEnabled],
|
||||
kYTHFSAutoApplyRateEnabledKey:[NSNumber numberWithBool:kYTHFSDefaultAutoApplyRateEnabled],
|
||||
kYTHFSTogglePlaybackRateKey:[NSNumber numberWithFloat:kYTHFSDefaultTogglePlaybackRate],
|
||||
kYTHFSHoldDurationKey:[NSNumber numberWithFloat:kYTHFSDefaultHoldDuration],
|
||||
kYTHFSHapticFeedbackEnabledKey:[NSNumber numberWithBool:[YTHFSPrefsManager supportsHapticFeedback]]}];
|
||||
}
|
||||
|
||||
// returns whether or not the device supports haptic feedback
|
||||
+ (BOOL)supportsHapticFeedback
|
||||
{
|
||||
static dispatch_once_t pred;
|
||||
dispatch_once(&pred, ^{
|
||||
// determine if the current device is able to support haptic feedback
|
||||
if (!CHHapticEngine.capabilitiesForHardware.supportsHaptics) {
|
||||
// ensure we are not on an iPhone 7 family device, since those devices are not covered under
|
||||
// the supportsHaptics call as of 2022-12-08 / iOS 16.1 SDK
|
||||
struct utsname systemInfo;
|
||||
uname(&systemInfo);
|
||||
NSString *currentDeviceIdentifier = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
|
||||
if ([currentDeviceIdentifier isEqualToString:@"iPhone9,1"] ||
|
||||
[currentDeviceIdentifier isEqualToString:@"iPhone9,3"] ||
|
||||
[currentDeviceIdentifier isEqualToString:@"iPhone9,2"] ||
|
||||
[currentDeviceIdentifier isEqualToString:@"iPhone9,4"]) {
|
||||
sYTHFSSupportsHapticFeedback = YES;
|
||||
} else {
|
||||
sYTHFSSupportsHapticFeedback = NO;
|
||||
}
|
||||
} else {
|
||||
sYTHFSSupportsHapticFeedback = YES;
|
||||
}
|
||||
});
|
||||
return sYTHFSSupportsHapticFeedback;
|
||||
}
|
||||
|
||||
// return the value that corresponds to the given hold duration option
|
||||
+ (CGFloat)holdDurationValueForOption:(YTHFSHoldDurationOption)holdDurationOption
|
||||
{
|
||||
return (holdDurationOption + 1) * 0.25;
|
||||
}
|
||||
|
||||
// return the value that corresponds to the given playback rate option
|
||||
+ (CGFloat)playbackRateValueForOption:(YTHFSPlaybackRateOption)playbackRateOption
|
||||
{
|
||||
CGFloat playbackRateOffset = 0.25;
|
||||
if (playbackRateOption > kYTHFSPlaybackRateOption075) {
|
||||
playbackRateOffset = playbackRateOffset * 2;
|
||||
}
|
||||
return playbackRateOption * 0.25 + playbackRateOffset;
|
||||
}
|
||||
|
||||
// return the hold playback option for the given value
|
||||
+ (YTHFSHoldDurationOption)holdDurationOptionForValue:(CGFloat)value
|
||||
{
|
||||
return MAX(MIN((NSInteger)(value / 0.25) - 1, kYTHFSHoldDurationOption200), kYTHFSHoldDurationOption025);
|
||||
}
|
||||
|
||||
// return the playback rate option for the given value
|
||||
+ (YTHFSPlaybackRateOption)playbackRateOptionForValue:(CGFloat)value
|
||||
{
|
||||
NSInteger playbackRateOptionOffset = 1;
|
||||
if (value > 1.00) {
|
||||
++playbackRateOptionOffset;
|
||||
}
|
||||
return MAX(MIN((NSInteger)(value / 0.25) - playbackRateOptionOffset, kYTHFSPlaybackRateOption200), kYTHFSPlaybackRateOption025);
|
||||
}
|
||||
|
||||
// return the appropriate string representation of the hold duration for the given value
|
||||
+ (NSString *)holdDurationStringForValue:(CGFloat)value
|
||||
{
|
||||
return [NSString stringWithFormat:[YTHFSPrefsManager localizedStringForKey:@"X_SECONDS" withDefaultValue:@"%@ seconds"], [[YTHFSPrefsManager decimalNumberFormatter] stringFromNumber:[NSNumber numberWithFloat:value]]];
|
||||
}
|
||||
|
||||
// return the appropriate string representation of the playback rate for the given value
|
||||
+ (NSString *)playbackRateStringForValue:(CGFloat)value
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@x", [[YTHFSPrefsManager decimalNumberFormatter] stringFromNumber:[NSNumber numberWithFloat:value]]];
|
||||
}
|
||||
|
||||
// setters and getters for the tweak preferences
|
||||
+ (BOOL)holdGestureEnabled
|
||||
{
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:kYTHFSHoldGestureEnabledKey];
|
||||
}
|
||||
+ (void)setHoldGestureEnabled:(BOOL)enabled
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:kYTHFSHoldGestureEnabledKey];
|
||||
}
|
||||
+ (BOOL)autoApplyRateEnabled
|
||||
{
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:kYTHFSAutoApplyRateEnabledKey];
|
||||
}
|
||||
+ (void)setAutoApplyRateEnabled:(BOOL)enabled
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:kYTHFSAutoApplyRateEnabledKey];
|
||||
}
|
||||
+ (CGFloat)togglePlaybackRate
|
||||
{
|
||||
return [[NSUserDefaults standardUserDefaults] floatForKey:kYTHFSTogglePlaybackRateKey];
|
||||
}
|
||||
+ (void)setTogglePlaybackRate:(CGFloat)playbackRate
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setFloat:playbackRate forKey:kYTHFSTogglePlaybackRateKey];
|
||||
}
|
||||
+ (CGFloat)holdDuration
|
||||
{
|
||||
return [[NSUserDefaults standardUserDefaults] floatForKey:kYTHFSHoldDurationKey];
|
||||
}
|
||||
+ (void)setHoldDuration:(CGFloat)holdDuration
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setFloat:holdDuration forKey:kYTHFSHoldDurationKey];
|
||||
}
|
||||
+ (BOOL)hapticFeedbackEnabled
|
||||
{
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:kYTHFSHapticFeedbackEnabledKey];
|
||||
}
|
||||
+ (void)setHapticFeedbackEnabled:(BOOL)hapticFeedbackEnabled
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setBool:hapticFeedbackEnabled forKey:kYTHFSHapticFeedbackEnabledKey];
|
||||
}
|
||||
|
||||
// return the bundle for the tweak which can be different depending on the jailbreak / installation method
|
||||
+ (NSBundle *)bundle
|
||||
{
|
||||
static dispatch_once_t pred;
|
||||
dispatch_once(&pred, ^{
|
||||
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"YTHoldForSpeed" ofType:@"bundle"];
|
||||
if (bundlePath) {
|
||||
sYTHFSBundle = [NSBundle bundleWithPath:bundlePath];
|
||||
} else {
|
||||
sYTHFSBundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/YTHoldForSpeed.bundle")];
|
||||
}
|
||||
});
|
||||
return sYTHFSBundle;
|
||||
}
|
||||
|
||||
// return the number formatter that will be used to create strings for the playback rate and hold duration
|
||||
+ (NSNumberFormatter *)decimalNumberFormatter
|
||||
{
|
||||
static dispatch_once_t pred;
|
||||
dispatch_once(&pred, ^{
|
||||
sYTHFSDecimalNumberFormatter = [[NSNumberFormatter alloc] init];
|
||||
[sYTHFSDecimalNumberFormatter setMinimumFractionDigits:1];
|
||||
[sYTHFSDecimalNumberFormatter setMaximumFractionDigits:2];
|
||||
});
|
||||
return sYTHFSDecimalNumberFormatter;
|
||||
}
|
||||
|
||||
@end
|
||||
164
Tweaks/YTHoldForSpeed/YTHFSSettings.x
Normal file
164
Tweaks/YTHoldForSpeed/YTHFSSettings.x
Normal file
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// YTHFSSettings.x
|
||||
//
|
||||
// Created by Joshua Seltzer on 12/11/22.
|
||||
//
|
||||
//
|
||||
|
||||
#import "YTHFSHeaders.h"
|
||||
#import "YTHFSPrefsManager.h"
|
||||
|
||||
@interface YTSettingsSectionItemManager (YTHFS)
|
||||
|
||||
// create a new method that will be used to add the tweak's settings
|
||||
- (void)YTHFSUpdateHoldForSpeedSectionWithEntry:(id)entry;
|
||||
|
||||
@end
|
||||
|
||||
// define the section number that is used to indicate the tweak's settings
|
||||
#define kYTHFSHoldForSpeedSection 2168
|
||||
|
||||
%hook YTAppSettingsPresentationData
|
||||
|
||||
// set the order of the settings and insert our custom settings for the tweak
|
||||
+ (NSArray *)settingsCategoryOrder
|
||||
{
|
||||
NSArray *order = %orig;
|
||||
NSMutableArray *mutableOrder = [order mutableCopy];
|
||||
NSUInteger insertIndex = [order indexOfObject:@(1)];
|
||||
if (insertIndex != NSNotFound) {
|
||||
[mutableOrder insertObject:@(kYTHFSHoldForSpeedSection) atIndex:insertIndex + 1];
|
||||
}
|
||||
return [mutableOrder copy];
|
||||
}
|
||||
|
||||
%end
|
||||
|
||||
%hook YTSettingsSectionItemManager
|
||||
|
||||
// override to add our custom entries for the hold for speed section in the settings
|
||||
- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry
|
||||
{
|
||||
if (category == kYTHFSHoldForSpeedSection) {
|
||||
[self YTHFSUpdateHoldForSpeedSectionWithEntry:entry];
|
||||
return;
|
||||
}
|
||||
%orig;
|
||||
}
|
||||
|
||||
// logic which creates the section items for the tweak's preferences
|
||||
%new
|
||||
- (void)YTHFSUpdateHoldForSpeedSectionWithEntry:(id)entry {
|
||||
NSMutableArray *mainSectionItems = [NSMutableArray array];
|
||||
Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem);
|
||||
YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"];
|
||||
|
||||
// create a settings section to enable or disable the hold gesture
|
||||
YTSettingsSectionItem *holdGestureSection = [YTSettingsSectionItemClass switchItemWithTitle:[YTHFSPrefsManager localizedStringForKey:@"HOLD_GESTURE" withDefaultValue:@"Hold gesture"]
|
||||
titleDescription:[YTHFSPrefsManager localizedStringForKey:@"HOLD_GESTURE_DESC" withDefaultValue:@"Tap and hold anywhere in the video player to toggle the playback speed between \"Normal\" (i.e. 1.0x) and the selected toggle speed.\n\nPlease be aware that by enabling this feature, the stock \"seek anywhere\" gesture will be disabled."]
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:[YTHFSPrefsManager holdGestureEnabled]
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[YTHFSPrefsManager setHoldGestureEnabled:enabled];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0];
|
||||
[mainSectionItems addObject:holdGestureSection];
|
||||
|
||||
// create a settings section to enable or disable the hold gesture
|
||||
YTSettingsSectionItem *autoApplySpeedSection = [YTSettingsSectionItemClass switchItemWithTitle:[YTHFSPrefsManager localizedStringForKey:@"AUTO_APPLY_SPEED" withDefaultValue:@"Automatically apply speed"]
|
||||
titleDescription:[YTHFSPrefsManager localizedStringForKey:@"AUTO_APPLY_SPEED_DESC" withDefaultValue:@"When enabled, the selected playback speed will automatically be applied when a new video player is launched."]
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:[YTHFSPrefsManager autoApplyRateEnabled]
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[YTHFSPrefsManager setAutoApplyRateEnabled:enabled];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:1];
|
||||
[mainSectionItems addObject:autoApplySpeedSection];
|
||||
|
||||
// create a settings section that allows the selection of the playback rate
|
||||
NSString *playbackRateTitle = [YTHFSPrefsManager localizedStringForKey:@"TOGGLE_SPEED" withDefaultValue:@"Toggle speed"];
|
||||
YTSettingsSectionItem *toggleRateSection = [YTSettingsSectionItemClass itemWithTitle:playbackRateTitle
|
||||
titleDescription:[YTHFSPrefsManager localizedStringForKey:@"TOGGLE_SPEED_DESC" withDefaultValue:@"The speed that the video player will toggle between when the hold gesture is invoked."]
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return [YTHFSPrefsManager playbackRateStringForValue:[YTHFSPrefsManager togglePlaybackRate]];
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
// create a new section item for each toggle rate option that the user can select
|
||||
NSMutableArray *playbackRateSectionRows = [NSMutableArray array];
|
||||
for (NSInteger currentRow = kYTHFSPlaybackRateOption025; currentRow <= kYTHFSPlaybackRateOption200; ++currentRow) {
|
||||
CGFloat playbackRateForRow = [YTHFSPrefsManager playbackRateValueForOption:currentRow];
|
||||
YTSettingsSectionItem *rateSection = [YTSettingsSectionItemClass checkmarkItemWithTitle:[YTHFSPrefsManager playbackRateStringForValue:playbackRateForRow]
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[YTHFSPrefsManager setTogglePlaybackRate:playbackRateForRow];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}];
|
||||
[playbackRateSectionRows addObject:rateSection];
|
||||
}
|
||||
YTSettingsPickerViewController *playbackRatePicker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:playbackRateTitle
|
||||
pickerSectionTitle:[playbackRateTitle uppercaseString]
|
||||
rows:playbackRateSectionRows
|
||||
selectedItemIndex:[YTHFSPrefsManager playbackRateOptionForValue:[YTHFSPrefsManager togglePlaybackRate]]
|
||||
parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:playbackRatePicker];
|
||||
return YES;
|
||||
}];
|
||||
[mainSectionItems addObject:toggleRateSection];
|
||||
|
||||
// create a settings section that allows the selection of the hold duration
|
||||
NSString *holdDurationTitle = [YTHFSPrefsManager localizedStringForKey:@"HOLD_DURATION" withDefaultValue:@"Hold duration"];
|
||||
YTSettingsSectionItem *holdDurationSection = [YTSettingsSectionItemClass itemWithTitle:holdDurationTitle
|
||||
titleDescription:[YTHFSPrefsManager localizedStringForKey:@"HOLD_DURATION_DESC" withDefaultValue:@"The amount of time (in seconds) that is required for the hold gesture to toggle the speed of the video player."]
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return [YTHFSPrefsManager holdDurationStringForValue:[YTHFSPrefsManager holdDuration]];
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
// create a new section item for each hold duration option that the user can select
|
||||
NSMutableArray *holdDurationSectionRows = [NSMutableArray array];
|
||||
for (NSInteger currentRow = kYTHFSHoldDurationOption025; currentRow <= kYTHFSHoldDurationOption200; ++currentRow) {
|
||||
CGFloat holdDurationForRow = [YTHFSPrefsManager holdDurationValueForOption:currentRow];
|
||||
YTSettingsSectionItem *holdDurationSection = [YTSettingsSectionItemClass checkmarkItemWithTitle:[YTHFSPrefsManager holdDurationStringForValue:holdDurationForRow]
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[YTHFSPrefsManager setHoldDuration:holdDurationForRow];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}];
|
||||
[holdDurationSectionRows addObject:holdDurationSection];
|
||||
}
|
||||
YTSettingsPickerViewController *holdDurationPicker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:holdDurationTitle
|
||||
pickerSectionTitle:[holdDurationTitle uppercaseString]
|
||||
rows:holdDurationSectionRows
|
||||
selectedItemIndex:[YTHFSPrefsManager holdDurationOptionForValue:[YTHFSPrefsManager holdDuration]]
|
||||
parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:holdDurationPicker];
|
||||
return YES;
|
||||
}];
|
||||
[mainSectionItems addObject:holdDurationSection];
|
||||
|
||||
// if available, add a settings section to enable or disable haptic feedback
|
||||
if ([YTHFSPrefsManager supportsHapticFeedback]) {
|
||||
YTSettingsSectionItem *hapticFeedbackSection = [YTSettingsSectionItemClass switchItemWithTitle:[YTHFSPrefsManager localizedStringForKey:@"HAPTIC_FEEDBACK" withDefaultValue:@"Haptic feedback"]
|
||||
titleDescription:[YTHFSPrefsManager localizedStringForKey:@"HAPTIC_FEEDBACK_DESC" withDefaultValue:@"Use haptic feedback to indicate that the speed of the video player was toggled."]
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:[YTHFSPrefsManager hapticFeedbackEnabled]
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[YTHFSPrefsManager setHapticFeedbackEnabled:enabled];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:4];
|
||||
[mainSectionItems addObject:hapticFeedbackSection];
|
||||
}
|
||||
|
||||
// add all of our settings item to the main settings list
|
||||
[settingsViewController setSectionItems:mainSectionItems
|
||||
forCategory:kYTHFSHoldForSpeedSection
|
||||
title:[YTHFSPrefsManager localizedStringForKey:@"HOLD_FOR_SPEED" withDefaultValue:@"Hold for speed"]
|
||||
titleDescription:nil
|
||||
headerHidden:NO];
|
||||
}
|
||||
|
||||
%end
|
||||
195
Tweaks/YTHoldForSpeed/YTHFSTweak.x
Normal file
195
Tweaks/YTHoldForSpeed/YTHFSTweak.x
Normal file
@@ -0,0 +1,195 @@
|
||||
//
|
||||
// YTHFSTweak.x
|
||||
//
|
||||
// Created by Joshua Seltzer on 12/5/22.
|
||||
//
|
||||
//
|
||||
|
||||
#import "YTHFSHeaders.h"
|
||||
#import "YTHFSPrefsManager.h"
|
||||
|
||||
@interface YTPlayerViewController (YTHFS)
|
||||
|
||||
// the long press gesture that will be created and added to the player view
|
||||
@property (nonatomic, retain) UILongPressGestureRecognizer *YTHFSLongPressGesture;
|
||||
|
||||
// switch between the user-selected playback rate and the normal playback rate, invoked either via the hold gesture or
|
||||
// automatically when the video starts (dependent on settings)
|
||||
- (void)YTHFSSwitchPlaybackRate;
|
||||
|
||||
@end
|
||||
|
||||
// define some non-configurable defaults for the long press gesture
|
||||
#define kYTHFSNormalPlaybackRate 1.0
|
||||
#define kYTHFSNumTouchesRequired 1
|
||||
#define kYTHFSAllowableMovement 50
|
||||
|
||||
// the static variables to keep track of the settings which shall persist until the YTPlayerViewController is recreated
|
||||
static CGFloat sYTHFSTogglePlaybackRate;
|
||||
static BOOL sYTHFSHapticFeedbackEnabled;
|
||||
static BOOL sYTHFSAutoApplyRateEnabled;
|
||||
|
||||
// enum to define the direction of the playback rate feedback indicator
|
||||
typedef enum YTHFSFeedbackDirection : NSInteger {
|
||||
kYTHFSFeedbackDirectionForward,
|
||||
kYTHFSFeedbackDirectionBackward
|
||||
} YTHFSFeedbackDirection;
|
||||
|
||||
%hook YTWatchLayerViewController
|
||||
|
||||
// invoked when the player view controller is either created or destroyed
|
||||
- (void)watchController:(YTWatchController *)watchController didSetPlayerViewController:(YTPlayerViewController *)playerViewController
|
||||
{
|
||||
if (playerViewController) {
|
||||
// grab the state of the settings for this instance of the player view controller
|
||||
sYTHFSTogglePlaybackRate = [YTHFSPrefsManager togglePlaybackRate];
|
||||
sYTHFSHapticFeedbackEnabled = [YTHFSPrefsManager hapticFeedbackEnabled];
|
||||
|
||||
// check to see if the toggle rate should automatically be applied when the video starts
|
||||
sYTHFSAutoApplyRateEnabled = [YTHFSPrefsManager autoApplyRateEnabled];
|
||||
|
||||
// add a long press gesture to configure the playback rate
|
||||
if ([YTHFSPrefsManager holdGestureEnabled]) {
|
||||
// check to see if the long press gesture is already created
|
||||
if (!playerViewController.YTHFSLongPressGesture) {
|
||||
playerViewController.YTHFSLongPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:playerViewController
|
||||
action:@selector(YTHFSHandleLongPressGesture:)];
|
||||
playerViewController.YTHFSLongPressGesture.numberOfTouchesRequired = kYTHFSNumTouchesRequired;
|
||||
playerViewController.YTHFSLongPressGesture.allowableMovement = kYTHFSAllowableMovement;
|
||||
[playerViewController.playerView addGestureRecognizer:playerViewController.YTHFSLongPressGesture];
|
||||
}
|
||||
|
||||
// update the minimum press duration with whatever the user set in the settings
|
||||
playerViewController.YTHFSLongPressGesture.minimumPressDuration = [YTHFSPrefsManager holdDuration];
|
||||
}
|
||||
}
|
||||
|
||||
%orig;
|
||||
}
|
||||
|
||||
%end
|
||||
|
||||
%hook YTPlayerViewController
|
||||
|
||||
// the long press gesture that will be created and added to the player view
|
||||
%property (nonatomic, retain) UILongPressGestureRecognizer *YTHFSLongPressGesture;
|
||||
|
||||
%new
|
||||
- (void)YTHFSHandleLongPressGesture:(UILongPressGestureRecognizer *)longPressGestureRecognizer
|
||||
{
|
||||
if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan && [self.contentVideoPlayerOverlay isKindOfClass:objc_getClass("YTMainAppVideoPlayerOverlayViewController")]) {
|
||||
YTMainAppVideoPlayerOverlayViewController *overlayViewController = (YTMainAppVideoPlayerOverlayViewController *)self.contentVideoPlayerOverlay;
|
||||
if (overlayViewController.isVarispeedAvailable) {
|
||||
[self YTHFSSwitchPlaybackRate];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%new
|
||||
- (void)YTHFSSwitchPlaybackRate
|
||||
{
|
||||
NSString *feedbackTitle = nil;
|
||||
YTHFSFeedbackDirection feedbackDirection = kYTHFSFeedbackDirectionForward;
|
||||
CGFloat currentPlaybackRate = [self currentPlaybackRateForVarispeedSwitchController:self.varispeedController];
|
||||
if (currentPlaybackRate != sYTHFSTogglePlaybackRate) {
|
||||
// change to the toggle rate if the current playback rate is any other speed
|
||||
[self varispeedSwitchController:self.varispeedController didSelectRate:sYTHFSTogglePlaybackRate];
|
||||
feedbackTitle = [YTHFSPrefsManager playbackRateStringForValue:sYTHFSTogglePlaybackRate];
|
||||
if (currentPlaybackRate > sYTHFSTogglePlaybackRate) {
|
||||
feedbackDirection = kYTHFSFeedbackDirectionBackward;
|
||||
}
|
||||
} else {
|
||||
// otherwise switch back to the default rate
|
||||
[self varispeedSwitchController:self.varispeedController didSelectRate:kYTHFSNormalPlaybackRate];
|
||||
feedbackTitle = [YTHFSPrefsManager localizedStringForKey:@"NORMAL" withDefaultValue:@"Normal"];
|
||||
if (currentPlaybackRate > kYTHFSNormalPlaybackRate) {
|
||||
feedbackDirection = kYTHFSFeedbackDirectionBackward;
|
||||
}
|
||||
}
|
||||
|
||||
// if the overlay controls are displayed, ensure to hide them before displaying the visual indicator
|
||||
if (![self arePlayerControlsHidden] && [self.contentVideoPlayerOverlay isKindOfClass:objc_getClass("YTMainAppVideoPlayerOverlayViewController")]) {
|
||||
YTMainAppVideoPlayerOverlayViewController *overlayViewController = (YTMainAppVideoPlayerOverlayViewController *)self.contentVideoPlayerOverlay;
|
||||
[overlayViewController hidePlayerControlsAnimated:YES];
|
||||
}
|
||||
|
||||
// trigger the double tap to seek view to visibly indicate that the playback rate has changed
|
||||
if ([self.playerView.overlayView isKindOfClass:objc_getClass("YTMainAppVideoPlayerOverlayView")]) {
|
||||
YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)self.playerView.overlayView;
|
||||
[overlayView.doubleTapToSeekView showCenteredSeekFeedbackWithTitle:feedbackTitle direction:feedbackDirection];
|
||||
}
|
||||
|
||||
// fire off haptic feedback to indicate that the playback rate changed (only applies to supported devices if enabled)
|
||||
if (sYTHFSHapticFeedbackEnabled) {
|
||||
UINotificationFeedbackGenerator *feedbackGenerator = [[UINotificationFeedbackGenerator alloc] init];
|
||||
[feedbackGenerator notificationOccurred:UINotificationFeedbackTypeSuccess];
|
||||
feedbackGenerator = nil;
|
||||
}
|
||||
}
|
||||
|
||||
// invoked when a video (or ad) is activated inside the player
|
||||
- (void)playbackController:(id)localPlaybackController didActivateVideo:(id)singleVideoController withPlaybackData:(id)playbackData
|
||||
{
|
||||
%orig;
|
||||
|
||||
if (sYTHFSAutoApplyRateEnabled && [self.contentVideoPlayerOverlay isKindOfClass:objc_getClass("YTMainAppVideoPlayerOverlayViewController")]) {
|
||||
YTMainAppVideoPlayerOverlayViewController *overlayViewController = (YTMainAppVideoPlayerOverlayViewController *)self.contentVideoPlayerOverlay;
|
||||
if (overlayViewController.isVarispeedAvailable) {
|
||||
// regardless of the current playback rate, at this point we know that the toggle rate will be applied
|
||||
sYTHFSAutoApplyRateEnabled = NO;
|
||||
|
||||
// compare whether or not the current playback rate is what the user selected and if not, change to it now
|
||||
if ([self currentPlaybackRateForVarispeedSwitchController:self.varispeedController] != sYTHFSTogglePlaybackRate) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self YTHFSSwitchPlaybackRate];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
// remove and destroy the gesture recognizer if it exists
|
||||
if (self.YTHFSLongPressGesture) {
|
||||
[self.playerView removeGestureRecognizer:self.YTHFSLongPressGesture];
|
||||
self.YTHFSLongPressGesture = nil;
|
||||
}
|
||||
|
||||
%orig;
|
||||
}
|
||||
|
||||
%end
|
||||
|
||||
%hook YTMainAppVideoPlayerOverlayView
|
||||
|
||||
// override the long press gesture recognizer that is used to invoke the seek gesture
|
||||
- (void)setSeekAnywhereLongPressGestureRecognizer:(UILongPressGestureRecognizer *)longPressGestureRecognizer
|
||||
{
|
||||
if (![YTHFSPrefsManager holdGestureEnabled]) {
|
||||
%orig;
|
||||
}
|
||||
}
|
||||
|
||||
// override the pan gesture recognizer that is used to invoke the seek gesture
|
||||
- (void)setSeekAnywherePanGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognzier
|
||||
{
|
||||
if (![YTHFSPrefsManager holdGestureEnabled]) {
|
||||
%orig;
|
||||
}
|
||||
}
|
||||
|
||||
// override the long press gesture recognizer that is used to invoke the seek gesture (introduced with YouTube 18.05.2)
|
||||
- (void)setLongPressGestureRecognizer:(UILongPressGestureRecognizer *)longPressGestureRecognizer
|
||||
{
|
||||
if (![YTHFSPrefsManager holdGestureEnabled]) {
|
||||
%orig;
|
||||
}
|
||||
}
|
||||
|
||||
%end
|
||||
|
||||
%ctor {
|
||||
// ensure that the default preferences are available
|
||||
[YTHFSPrefsManager registerDefaults];
|
||||
}
|
||||
BIN
Tweaks/YTHoldForSpeed/assets/Screenshot_1.png
Normal file
BIN
Tweaks/YTHoldForSpeed/assets/Screenshot_1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 MiB |
BIN
Tweaks/YTHoldForSpeed/assets/Screenshot_2.png
Normal file
BIN
Tweaks/YTHoldForSpeed/assets/Screenshot_2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 341 KiB |
BIN
Tweaks/YTHoldForSpeed/assets/banner.psd
Normal file
BIN
Tweaks/YTHoldForSpeed/assets/banner.psd
Normal file
Binary file not shown.
119
Tweaks/YTHoldForSpeed/assets/forward.svg
Normal file
119
Tweaks/YTHoldForSpeed/assets/forward.svg
Normal file
@@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="700pt" height="700pt" version="1.1" viewBox="0 0 700 700" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<symbol id="w" overflow="visible">
|
||||
<path d="m18.766-1.125c-0.96875 0.5-1.9805 0.875-3.0312 1.125-1.043 0.25781-2.1367 0.39062-3.2812 0.39062-3.3984 0-6.0898-0.94531-8.0781-2.8438-1.9922-1.9062-2.9844-4.4844-2.9844-7.7344 0-3.2578 0.99219-5.8359 2.9844-7.7344 1.9883-1.9062 4.6797-2.8594 8.0781-2.8594 1.1445 0 2.2383 0.13281 3.2812 0.39062 1.0508 0.25 2.0625 0.625 3.0312 1.125v4.2188c-0.98047-0.65625-1.9453-1.1406-2.8906-1.4531-0.94922-0.3125-1.9492-0.46875-3-0.46875-1.875 0-3.3516 0.60547-4.4219 1.8125-1.0742 1.1992-1.6094 2.8555-1.6094 4.9688 0 2.1055 0.53516 3.7617 1.6094 4.9688 1.0703 1.1992 2.5469 1.7969 4.4219 1.7969 1.0508 0 2.0508-0.14844 3-0.45312 0.94531-0.3125 1.9102-0.80078 2.8906-1.4688z"/>
|
||||
</symbol>
|
||||
<symbol id="b" overflow="visible">
|
||||
<path d="m13.734-11.141c-0.4375-0.19531-0.87109-0.34375-1.2969-0.4375-0.41797-0.10156-0.83984-0.15625-1.2656-0.15625-1.2617 0-2.2305 0.40625-2.9062 1.2188-0.67969 0.80469-1.0156 1.9531-1.0156 3.4531v7.0625h-4.8906v-15.312h4.8906v2.5156c0.625-1 1.3438-1.7266 2.1562-2.1875 0.82031-0.46875 1.8008-0.70312 2.9375-0.70312 0.16406 0 0.34375 0.011719 0.53125 0.03125 0.19531 0.011719 0.47656 0.039062 0.84375 0.078125z"/>
|
||||
</symbol>
|
||||
<symbol id="a" overflow="visible">
|
||||
<path d="m17.641-7.7031v1.4062h-11.453c0.125 1.1484 0.53906 2.0078 1.25 2.5781 0.70703 0.57422 1.7031 0.85938 2.9844 0.85938 1.0312 0 2.082-0.14844 3.1562-0.45312 1.082-0.3125 2.1914-0.77344 3.3281-1.3906v3.7656c-1.1562 0.4375-2.3125 0.76562-3.4688 0.98438-1.1562 0.22656-2.3125 0.34375-3.4688 0.34375-2.7734 0-4.9297-0.70312-6.4688-2.1094-1.5312-1.4062-2.2969-3.3789-2.2969-5.9219 0-2.5 0.75391-4.4609 2.2656-5.8906 1.5078-1.4375 3.582-2.1562 6.2188-2.1562 2.4062 0 4.332 0.73047 5.7812 2.1875 1.4453 1.4492 2.1719 3.3828 2.1719 5.7969zm-5.0312-1.625c0-0.92578-0.27344-1.6719-0.8125-2.2344-0.54297-0.57031-1.25-0.85938-2.125-0.85938-0.94922 0-1.7188 0.26562-2.3125 0.79688s-0.96484 1.2969-1.1094 2.2969z"/>
|
||||
</symbol>
|
||||
<symbol id="g" overflow="visible">
|
||||
<path d="m9.2188-6.8906c-1.0234 0-1.793 0.17188-2.3125 0.51562-0.51172 0.34375-0.76562 0.85547-0.76562 1.5312 0 0.625 0.20703 1.1172 0.625 1.4688 0.41406 0.34375 0.98828 0.51562 1.7188 0.51562 0.92578 0 1.7031-0.32812 2.3281-0.98438 0.63281-0.66406 0.95312-1.4922 0.95312-2.4844v-0.5625zm7.4688-1.8438v8.7344h-4.9219v-2.2656c-0.65625 0.92969-1.3984 1.6055-2.2188 2.0312-0.82422 0.41406-1.8242 0.625-3 0.625-1.5859 0-2.8711-0.45703-3.8594-1.375-0.99219-0.92578-1.4844-2.1289-1.4844-3.6094 0-1.7891 0.61328-3.1016 1.8438-3.9375 1.2383-0.84375 3.1797-1.2656 5.8281-1.2656h2.8906v-0.39062c0-0.76953-0.30859-1.332-0.92188-1.6875-0.61719-0.36328-1.5703-0.54688-2.8594-0.54688-1.0547 0-2.0312 0.10547-2.9375 0.3125-0.89844 0.21094-1.7305 0.52344-2.5 0.9375v-3.7344c1.0391-0.25 2.0859-0.44141 3.1406-0.57812 1.0625-0.13281 2.125-0.20312 3.1875-0.20312 2.7578 0 4.75 0.54688 5.9688 1.6406 1.2266 1.0859 1.8438 2.8555 1.8438 5.3125z"/>
|
||||
</symbol>
|
||||
<symbol id="d" overflow="visible">
|
||||
<path d="m7.7031-19.656v4.3438h5.0469v3.5h-5.0469v6.5c0 0.71094 0.14062 1.1875 0.42188 1.4375s0.83594 0.375 1.6719 0.375h2.5156v3.5h-4.1875c-1.9375 0-3.3125-0.39844-4.125-1.2031-0.80469-0.8125-1.2031-2.1797-1.2031-4.1094v-6.5h-2.4219v-3.5h2.4219v-4.3438z"/>
|
||||
</symbol>
|
||||
<symbol id="f" overflow="visible">
|
||||
<path d="m12.766-13.078v-8.2031h4.9219v21.281h-4.9219v-2.2188c-0.66797 0.90625-1.4062 1.5703-2.2188 1.9844s-1.7578 0.625-2.8281 0.625c-1.8867 0-3.4336-0.75-4.6406-2.25-1.2109-1.5-1.8125-3.4258-1.8125-5.7812 0-2.3633 0.60156-4.2969 1.8125-5.7969 1.207-1.5 2.7539-2.25 4.6406-2.25 1.0625 0 2 0.21484 2.8125 0.64062 0.82031 0.42969 1.5664 1.0859 2.2344 1.9688zm-3.2188 9.9219c1.0391 0 1.8359-0.37891 2.3906-1.1406 0.55078-0.76953 0.82812-1.8828 0.82812-3.3438 0-1.457-0.27734-2.5664-0.82812-3.3281-0.55469-0.76953-1.3516-1.1562-2.3906-1.1562-1.043 0-1.8398 0.38672-2.3906 1.1562-0.55469 0.76172-0.82812 1.8711-0.82812 3.3281 0 1.4609 0.27344 2.5742 0.82812 3.3438 0.55078 0.76172 1.3477 1.1406 2.3906 1.1406z"/>
|
||||
</symbol>
|
||||
<symbol id="k" overflow="visible">
|
||||
<path d="m10.5-3.1562c1.0508 0 1.8516-0.37891 2.4062-1.1406 0.55078-0.76953 0.82812-1.8828 0.82812-3.3438 0-1.457-0.27734-2.5664-0.82812-3.3281-0.55469-0.76953-1.3555-1.1562-2.4062-1.1562-1.0547 0-1.8594 0.38672-2.4219 1.1562-0.55469 0.77344-0.82812 1.8828-0.82812 3.3281 0 1.4492 0.27344 2.5586 0.82812 3.3281 0.5625 0.77344 1.3672 1.1562 2.4219 1.1562zm-3.25-9.9219c0.67578-0.88281 1.4219-1.5391 2.2344-1.9688 0.82031-0.42578 1.7656-0.64062 2.8281-0.64062 1.8945 0 3.4453 0.75 4.6562 2.25 1.207 1.5 1.8125 3.4336 1.8125 5.7969 0 2.3555-0.60547 4.2812-1.8125 5.7812-1.2109 1.5-2.7617 2.25-4.6562 2.25-1.0625 0-2.0078-0.21094-2.8281-0.625-0.8125-0.42578-1.5586-1.0859-2.2344-1.9844v2.2188h-4.8906v-21.281h4.8906z"/>
|
||||
</symbol>
|
||||
<symbol id="j" overflow="visible">
|
||||
<path d="m0.34375-15.312h4.8906l4.125 10.391 3.5-10.391h4.8906l-6.4375 16.766c-0.64844 1.6953-1.4023 2.8828-2.2656 3.5625-0.86719 0.6875-2 1.0312-3.4062 1.0312h-2.8438v-3.2188h1.5312c0.83203 0 1.4375-0.13672 1.8125-0.40625 0.38281-0.26172 0.67969-0.73047 0.89062-1.4062l0.14062-0.42188z"/>
|
||||
</symbol>
|
||||
<symbol id="i" overflow="visible">
|
||||
<path d="m14.953-3.7188h-8.2188l-1.3125 3.7188h-5.2812l7.5625-20.406h6.2656l7.5625 20.406h-5.2812zm-6.9062-3.7812h5.5781l-2.7812-8.125z"/>
|
||||
</symbol>
|
||||
<symbol id="e" overflow="visible">
|
||||
<path d="m17.75-9.3281v9.3281h-4.9219v-7.1406c0-1.3203-0.03125-2.2344-0.09375-2.7344s-0.16797-0.86719-0.3125-1.1094c-0.1875-0.3125-0.44922-0.55469-0.78125-0.73438-0.32422-0.17578-0.69531-0.26562-1.1094-0.26562-1.0234 0-1.8242 0.39844-2.4062 1.1875-0.58594 0.78125-0.875 1.8711-0.875 3.2656v7.5312h-4.8906v-15.312h4.8906v2.2344c0.73828-0.88281 1.5195-1.5391 2.3438-1.9688 0.83203-0.42578 1.75-0.64062 2.75-0.64062 1.7695 0 3.1133 0.54688 4.0312 1.6406 0.91406 1.0859 1.375 2.6562 1.375 4.7188z"/>
|
||||
</symbol>
|
||||
<symbol id="v" overflow="visible">
|
||||
<path d="m14.312-14.828v3.7188c-1.043-0.4375-2.0547-0.76562-3.0312-0.98438-0.98047-0.21875-1.9023-0.32812-2.7656-0.32812-0.92969 0-1.6211 0.11719-2.0781 0.34375-0.44922 0.23047-0.67188 0.58984-0.67188 1.0781 0 0.38672 0.17188 0.68359 0.51562 0.89062 0.34375 0.21094 0.95703 0.36719 1.8438 0.46875l0.85938 0.125c2.5078 0.32422 4.1953 0.85156 5.0625 1.5781 0.86328 0.73047 1.2969 1.8711 1.2969 3.4219 0 1.6367-0.60547 2.8672-1.8125 3.6875-1.1992 0.8125-2.9922 1.2188-5.375 1.2188-1.0234 0-2.0742-0.078125-3.1562-0.23438-1.0742-0.15625-2.1797-0.39453-3.3125-0.71875v-3.7188c0.96875 0.48047 1.9609 0.83984 2.9844 1.0781 1.0312 0.23047 2.0781 0.34375 3.1406 0.34375 0.95703 0 1.6758-0.12891 2.1562-0.39062 0.47656-0.26953 0.71875-0.66406 0.71875-1.1875 0-0.4375-0.16797-0.75781-0.5-0.96875-0.33594-0.21875-0.99609-0.38281-1.9844-0.5l-0.85938-0.10938c-2.1797-0.26953-3.7031-0.77344-4.5781-1.5156-0.875-0.73828-1.3125-1.8594-1.3125-3.3594 0-1.625 0.55078-2.8281 1.6562-3.6094 1.1133-0.78906 2.8203-1.1875 5.125-1.1875 0.89453 0 1.8359 0.074219 2.8281 0.21875 1 0.13672 2.082 0.35156 3.25 0.64062z"/>
|
||||
</symbol>
|
||||
<symbol id="c" overflow="visible">
|
||||
<path d="m9.6406-12.188c-1.0859 0-1.9141 0.39062-2.4844 1.1719-0.57422 0.78125-0.85938 1.9062-0.85938 3.375s0.28516 2.5938 0.85938 3.375c0.57031 0.77344 1.3984 1.1562 2.4844 1.1562 1.0625 0 1.875-0.38281 2.4375-1.1562 0.57031-0.78125 0.85938-1.9062 0.85938-3.375s-0.28906-2.5938-0.85938-3.375c-0.5625-0.78125-1.375-1.1719-2.4375-1.1719zm0-3.5c2.6328 0 4.6914 0.71484 6.1719 2.1406 1.4766 1.418 2.2188 3.3867 2.2188 5.9062 0 2.5117-0.74219 4.4805-2.2188 5.9062-1.4805 1.418-3.5391 2.125-6.1719 2.125-2.6484 0-4.7148-0.70703-6.2031-2.125-1.4922-1.4258-2.2344-3.3945-2.2344-5.9062 0-2.5195 0.74219-4.4883 2.2344-5.9062 1.4883-1.4258 3.5547-2.1406 6.2031-2.1406z"/>
|
||||
</symbol>
|
||||
<symbol id="u" overflow="visible">
|
||||
<path d="m10.047-11.359c1.1016 0 1.8945-0.20312 2.375-0.60938 0.47656-0.41406 0.71875-1.0938 0.71875-2.0312 0-0.92578-0.24219-1.5859-0.71875-1.9844-0.48047-0.40625-1.2734-0.60938-2.375-0.60938h-2.2188v5.2344zm-2.2188 3.6406v7.7188h-5.25v-20.406h8.0312c2.6875 0 4.6562 0.45312 5.9062 1.3594 1.2578 0.89844 1.8906 2.3203 1.8906 4.2656 0 1.3555-0.32812 2.4648-0.98438 3.3281-0.64844 0.86719-1.625 1.5-2.9375 1.9062 0.71875 0.16797 1.3594 0.54297 1.9219 1.125 0.57031 0.57422 1.1484 1.4492 1.7344 2.625l2.8594 5.7969h-5.6094l-2.4844-5.0781c-0.5-1.0195-1.0117-1.7109-1.5312-2.0781-0.51172-0.375-1.1953-0.5625-2.0469-0.5625z"/>
|
||||
</symbol>
|
||||
<symbol id="h" overflow="visible">
|
||||
<path d="m16.547-12.766c0.61328-0.94531 1.3477-1.6719 2.2031-2.1719 0.85156-0.5 1.7891-0.75 2.8125-0.75 1.7578 0 3.0977 0.54688 4.0156 1.6406 0.92578 1.0859 1.3906 2.6562 1.3906 4.7188v9.3281h-4.9219v-7.9844-0.35938c0.007813-0.13281 0.015625-0.32031 0.015625-0.5625 0-1.082-0.16406-1.8633-0.48438-2.3438-0.3125-0.48828-0.82422-0.73438-1.5312-0.73438-0.92969 0-1.6484 0.38672-2.1562 1.1562-0.51172 0.76172-0.77344 1.8672-0.78125 3.3125v7.5156h-4.9219v-7.9844c0-1.6953-0.14844-2.7852-0.4375-3.2656-0.29297-0.48828-0.8125-0.73438-1.5625-0.73438-0.9375 0-1.6641 0.38672-2.1719 1.1562-0.51172 0.76172-0.76562 1.8594-0.76562 3.2969v7.5312h-4.9219v-15.312h4.9219v2.2344c0.60156-0.86328 1.2891-1.5156 2.0625-1.9531 0.78125-0.4375 1.6406-0.65625 2.5781-0.65625 1.0625 0 2 0.25781 2.8125 0.76562 0.8125 0.51172 1.4258 1.2305 1.8438 2.1562z"/>
|
||||
</symbol>
|
||||
<symbol id="t" overflow="visible">
|
||||
<path d="m2.3594-15.312h4.8906v15.312h-4.8906zm0-5.9688h4.8906v4h-4.8906z"/>
|
||||
</symbol>
|
||||
<symbol id="s" overflow="visible">
|
||||
<path d="m1.5938-15.312h13.359v3.4219l-8.0625 8.3906h8.0625v3.5h-13.688v-3.4219l8.0625-8.3906h-7.7344z"/>
|
||||
</symbol>
|
||||
<symbol id="r" overflow="visible">
|
||||
<path d="m12.422-21.281v3.2188h-2.7031c-0.6875 0-1.1719 0.125-1.4531 0.375-0.27344 0.25-0.40625 0.6875-0.40625 1.3125v1.0625h4.1875v3.5h-4.1875v11.812h-4.8906v-11.812h-2.4375v-3.5h2.4375v-1.0625c0-1.6641 0.46094-2.8984 1.3906-3.7031 0.92578-0.80078 2.3672-1.2031 4.3281-1.2031z"/>
|
||||
</symbol>
|
||||
<symbol id="q" overflow="visible">
|
||||
<path d="m17.75-9.3281v9.3281h-4.9219v-7.1094c0-1.3438-0.03125-2.2656-0.09375-2.7656s-0.16797-0.86719-0.3125-1.1094c-0.1875-0.3125-0.44922-0.55469-0.78125-0.73438-0.32422-0.17578-0.69531-0.26562-1.1094-0.26562-1.0234 0-1.8242 0.39844-2.4062 1.1875-0.58594 0.78125-0.875 1.8711-0.875 3.2656v7.5312h-4.8906v-21.281h4.8906v8.2031c0.73828-0.88281 1.5195-1.5391 2.3438-1.9688 0.83203-0.42578 1.75-0.64062 2.75-0.64062 1.7695 0 3.1133 0.54688 4.0312 1.6406 0.91406 1.0859 1.375 2.6562 1.375 4.7188z"/>
|
||||
</symbol>
|
||||
<symbol id="p" overflow="visible">
|
||||
<path d="m2.5781-20.406h5.875l7.4219 14v-14h4.9844v20.406h-5.875l-7.4219-14v14h-4.9844z"/>
|
||||
</symbol>
|
||||
<symbol id="o" overflow="visible">
|
||||
<path d="m2.1875-5.9688v-9.3438h4.9219v1.5312c0 0.83594-0.007813 1.875-0.015625 3.125-0.011719 1.25-0.015625 2.0859-0.015625 2.5 0 1.2422 0.03125 2.1328 0.09375 2.6719 0.070313 0.54297 0.17969 0.93359 0.32812 1.1719 0.20703 0.32422 0.47266 0.57422 0.79688 0.75 0.32031 0.16797 0.69141 0.25 1.1094 0.25 1.0195 0 1.8203-0.39062 2.4062-1.1719 0.58203-0.78125 0.875-1.8672 0.875-3.2656v-7.5625h4.8906v15.312h-4.8906v-2.2188c-0.74219 0.89844-1.5234 1.5586-2.3438 1.9844-0.82422 0.41406-1.7344 0.625-2.7344 0.625-1.7617 0-3.1055-0.53906-4.0312-1.625-0.92969-1.082-1.3906-2.6602-1.3906-4.7344z"/>
|
||||
</symbol>
|
||||
<symbol id="n" overflow="visible">
|
||||
<path d="m2.5781-20.406h8.7344c2.5938 0 4.582 0.57812 5.9688 1.7344 1.3945 1.1484 2.0938 2.7891 2.0938 4.9219 0 2.1367-0.69922 3.7812-2.0938 4.9375-1.3867 1.1562-3.375 1.7344-5.9688 1.7344h-3.4844v7.0781h-5.25zm5.25 3.8125v5.7031h2.9219c1.0195 0 1.8047-0.25 2.3594-0.75 0.5625-0.5 0.84375-1.2031 0.84375-2.1094 0-0.91406-0.28125-1.6172-0.84375-2.1094-0.55469-0.48828-1.3398-0.73438-2.3594-0.73438z"/>
|
||||
</symbol>
|
||||
<symbol id="m" overflow="visible">
|
||||
<path d="m2.3594-15.312h4.8906v15.031c0 2.0508-0.49609 3.6172-1.4844 4.7031-0.98047 1.082-2.4062 1.625-4.2812 1.625h-2.4219v-3.2188h0.85938c0.92578 0 1.5625-0.21094 1.9062-0.625 0.35156-0.41797 0.53125-1.2461 0.53125-2.4844zm0-5.9688h4.8906v4h-4.8906z"/>
|
||||
</symbol>
|
||||
<symbol id="l" overflow="visible">
|
||||
<path d="m14.719-14.828v3.9844c-0.65625-0.45703-1.3242-0.79688-2-1.0156-0.66797-0.21875-1.3594-0.32812-2.0781-0.32812-1.3672 0-2.4336 0.40234-3.2031 1.2031-0.76172 0.79297-1.1406 1.9062-1.1406 3.3438 0 1.4297 0.37891 2.543 1.1406 3.3438 0.76953 0.79297 1.8359 1.1875 3.2031 1.1875 0.75781 0 1.4844-0.10938 2.1719-0.32812 0.6875-0.22656 1.3203-0.56641 1.9062-1.0156v4c-0.76172 0.28125-1.5391 0.48828-2.3281 0.625-0.78125 0.14453-1.5742 0.21875-2.375 0.21875-2.7617 0-4.9219-0.70703-6.4844-2.125-1.5547-1.4141-2.3281-3.3828-2.3281-5.9062 0-2.5312 0.77344-4.5039 2.3281-5.9219 1.5625-1.4141 3.7227-2.125 6.4844-2.125 0.80078 0 1.5938 0.074219 2.375 0.21875 0.78125 0.13672 1.5547 0.35156 2.3281 0.64062z"/>
|
||||
</symbol>
|
||||
</defs>
|
||||
<g>
|
||||
<path d="m518 112h-352.8c-36.961 0-67.199 30.238-67.199 67.199v201.6c0 36.961 30.238 67.199 67.199 67.199h352.8c36.961 0 67.199-30.238 67.199-67.199v-201.6c0-36.961-30.238-67.199-67.199-67.199zm-20.719 169.68-143.92 82.879c-1.6797 1.1211-4.4805 0-4.4805-2.2383v-77.84l-138.88 80.078c-1.6797 1.1211-4.4805 0-4.4805-2.2383v-166.32c0-2.2383 2.2383-3.3594 4.4805-2.2383l138.88 80.078v-77.84c0-2.2383 2.2383-3.3594 4.4805-2.2383l143.92 82.879c1.6797 1.1211 1.6797 3.918 0 5.0391z"/>
|
||||
<use x="70" y="644" xlink:href="#w"/>
|
||||
<use x="90.550781" y="644" xlink:href="#b"/>
|
||||
<use x="104.359375" y="644" xlink:href="#a"/>
|
||||
<use x="123.347656" y="644" xlink:href="#g"/>
|
||||
<use x="142.242188" y="644" xlink:href="#d"/>
|
||||
<use x="155.628906" y="644" xlink:href="#a"/>
|
||||
<use x="174.617188" y="644" xlink:href="#f"/>
|
||||
<use x="204.410156" y="644" xlink:href="#k"/>
|
||||
<use x="224.453125" y="644" xlink:href="#j"/>
|
||||
<use x="252.453125" y="644" xlink:href="#i"/>
|
||||
<use x="274.121094" y="644" xlink:href="#e"/>
|
||||
<use x="294.054688" y="644" xlink:href="#f"/>
|
||||
<use x="314.097656" y="644" xlink:href="#a"/>
|
||||
<use x="333.085938" y="644" xlink:href="#b"/>
|
||||
<use x="346.898438" y="644" xlink:href="#v"/>
|
||||
<use x="363.5625" y="644" xlink:href="#c"/>
|
||||
<use x="382.796875" y="644" xlink:href="#e"/>
|
||||
<use x="412.480469" y="644" xlink:href="#u"/>
|
||||
<use x="434.039062" y="644" xlink:href="#g"/>
|
||||
<use x="452.9375" y="644" xlink:href="#h"/>
|
||||
<use x="482.109375" y="644" xlink:href="#t"/>
|
||||
<use x="491.710937" y="644" xlink:href="#b"/>
|
||||
<use x="505.515625" y="644" xlink:href="#a"/>
|
||||
<use x="524.507812" y="644" xlink:href="#s"/>
|
||||
<use x="70" y="672" xlink:href="#r"/>
|
||||
<use x="82.183594" y="672" xlink:href="#b"/>
|
||||
<use x="95.992188" y="672" xlink:href="#c"/>
|
||||
<use x="115.226562" y="672" xlink:href="#h"/>
|
||||
<use x="154.152344" y="672" xlink:href="#d"/>
|
||||
<use x="167.535156" y="672" xlink:href="#q"/>
|
||||
<use x="187.46875" y="672" xlink:href="#a"/>
|
||||
<use x="216.207031" y="672" xlink:href="#p"/>
|
||||
<use x="239.640625" y="672" xlink:href="#c"/>
|
||||
<use x="258.878906" y="672" xlink:href="#o"/>
|
||||
<use x="278.8125" y="672" xlink:href="#e"/>
|
||||
<use x="308.492188" y="672" xlink:href="#n"/>
|
||||
<use x="329.015625" y="672" xlink:href="#b"/>
|
||||
<use x="342.820312" y="672" xlink:href="#c"/>
|
||||
<use x="362.058594" y="672" xlink:href="#m"/>
|
||||
<use x="371.65625" y="672" xlink:href="#a"/>
|
||||
<use x="390.648438" y="672" xlink:href="#l"/>
|
||||
<use x="407.242188" y="672" xlink:href="#d"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
BIN
Tweaks/YTHoldForSpeed/assets/icon.psd
Normal file
BIN
Tweaks/YTHoldForSpeed/assets/icon.psd
Normal file
Binary file not shown.
11
Tweaks/YTHoldForSpeed/build_release.sh
Normal file
11
Tweaks/YTHoldForSpeed/build_release.sh
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
# rootful (iphoneos-arm)
|
||||
export PREFIX=$THEOS/toolchain/Xcode11.xctoolchain/usr/bin/
|
||||
make clean
|
||||
make package FINALPACKAGE=1
|
||||
|
||||
# rootless (iphoneos-arm64)
|
||||
export -n PREFIX
|
||||
make clean
|
||||
make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless
|
||||
9
Tweaks/YTHoldForSpeed/control
Normal file
9
Tweaks/YTHoldForSpeed/control
Normal file
@@ -0,0 +1,9 @@
|
||||
Package: com.joshuaseltzer.ytholdforspeed
|
||||
Name: YTHoldForSpeed
|
||||
Version: 1.0.3
|
||||
Architecture: iphoneos-arm
|
||||
Description: Tap and hold on the YouTube video player to toggle a selected playback speed. Preferences for the tweak are configured within the YouTube app.
|
||||
Maintainer: Joshua Seltzer <joshua.seltzer90@gmail.com>
|
||||
Author: Joshua Seltzer <joshua.seltzer90@gmail.com>
|
||||
Section: Tweaks
|
||||
Depends: mobilesubstrate (>= 0.9.5000)
|
||||
@@ -0,0 +1,13 @@
|
||||
"HOLD_FOR_SPEED" = "Hold for speed";
|
||||
"NORMAL" = "Normal";
|
||||
"X_SECONDS" = "%@ seconds";
|
||||
"HOLD_GESTURE" = "Hold gesture";
|
||||
"HOLD_GESTURE_DESC" = "Tap and hold anywhere in the video player to toggle the playback speed between \"Normal\" (i.e. 1.0x) and the selected toggle speed.\n\nPlease be aware that by enabling this feature, the stock \"seek anywhere\" gesture will be disabled.";
|
||||
"AUTO_APPLY_SPEED" = "Automatically apply speed";
|
||||
"AUTO_APPLY_SPEED_DESC" = "When enabled, the selected playback speed will automatically be applied when a new video player is launched.";
|
||||
"TOGGLE_SPEED" = "Toggle speed";
|
||||
"TOGGLE_SPEED_DESC" = "The speed that the video player will toggle between when the hold gesture is invoked.";
|
||||
"HOLD_DURATION" = "Hold duration";
|
||||
"HOLD_DURATION_DESC" = "The amount of time (in seconds) that is required for the hold gesture to toggle the speed of the video player.";
|
||||
"HAPTIC_FEEDBACK" = "Haptic feedback";
|
||||
"HAPTIC_FEEDBACK_DESC" = "Use haptic feedback to indicate that the speed of the video player was toggled.";
|
||||
1
Tweaks/YTHoldForSpeed/ytholdforspeed.plist
Normal file
1
Tweaks/YTHoldForSpeed/ytholdforspeed.plist
Normal file
@@ -0,0 +1 @@
|
||||
{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; }
|
||||
Reference in New Issue
Block a user