mirror of
https://github.com/SoPat712/YTLitePlus.git
synced 2025-08-22 02:38:45 -04:00
added files via upload
This commit is contained in:
42
Source/Download.xm.bak
Normal file
42
Source/Download.xm.bak
Normal file
@@ -0,0 +1,42 @@
|
||||
// Code has been disabled due to some compiling errors.
|
||||
|
||||
#import "../Header.h"
|
||||
|
||||
%ctor {
|
||||
void $YTPlayerView_downloadVideo_register();
|
||||
void $YTPlayerView_layoutSubviews$_register();
|
||||
}
|
||||
|
||||
#ifndef YTPLAYERVIEW_DOWNLOADVIDEO_REGISTER
|
||||
#ifndef YTPLAYERVIEW_LAYOUTSUBVIEWS_REGISTER
|
||||
#define YTPLAYERVIEW_DOWNLOADVIDEO_REGISTER
|
||||
#define YTPLAYERVIEW_LAYOUTSUBVIEWS_REGISTER
|
||||
|
||||
void $YTPlayerView_downloadVideo_register();
|
||||
void $YTPlayerView_layoutSubviews$_register();
|
||||
|
||||
#endif
|
||||
|
||||
// YouTube Video Downloading
|
||||
CHDeclareClass(YTPlayerView);
|
||||
|
||||
CHOptimizedMethod1(self, void, YTPlayerView, layoutSubviews, BOOL, arg1)
|
||||
{
|
||||
CHSuper1(YTPlayerView, layoutSubviews, arg1);
|
||||
CGRect downloadButtonFrame = CGRectMake(0, 0, 100, 50);
|
||||
UIButton *downloadButton = [[UIButton alloc] initWithFrame:downloadButtonFrame];
|
||||
[downloadButton setTitle:@"Download" forState:UIControlStateNormal];
|
||||
[downloadButton addTarget:self action:@selector(downloadVideo) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self addSubview:downloadButton];
|
||||
}
|
||||
|
||||
CHOptimizedMethod0(self, void, YTPlayerView, downloadVideo)
|
||||
{
|
||||
NSString *videoUrlString = @"[Insert YouTube video URL here]";
|
||||
NSURL *videoUrl = [NSURL URLWithString:videoUrlString];
|
||||
NSData *videoData = [NSData dataWithContentsOfURL:videoUrl];
|
||||
|
||||
// Save the video data to a file
|
||||
NSString *filePath = @"[Insert file path here]";
|
||||
[videoData writeToFile:filePath atomically:YES];
|
||||
}
|
1160
Source/LowContrastMode.xm
Normal file
1160
Source/LowContrastMode.xm
Normal file
File diff suppressed because it is too large
Load Diff
746
Source/Settings.xm
Normal file
746
Source/Settings.xm
Normal file
@@ -0,0 +1,746 @@
|
||||
#import "../Tweaks/YouTubeHeader/YTSettingsViewController.h"
|
||||
#import "../Tweaks/YouTubeHeader/YTSearchableSettingsViewController.h"
|
||||
#import "../Tweaks/YouTubeHeader/YTSettingsSectionItem.h"
|
||||
#import "../Tweaks/YouTubeHeader/YTSettingsSectionItemManager.h"
|
||||
#import "../Tweaks/YouTubeHeader/YTUIUtils.h"
|
||||
#import "../Tweaks/YouTubeHeader/YTSettingsPickerViewController.h"
|
||||
#import "../Header.h"
|
||||
|
||||
static BOOL IsEnabled(NSString *key) {
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:key];
|
||||
}
|
||||
static int GetSelection(NSString *key) {
|
||||
return [[NSUserDefaults standardUserDefaults] integerForKey:key];
|
||||
}
|
||||
static int colorContrastMode() {
|
||||
return [[NSUserDefaults standardUserDefaults] integerForKey:@"lcmColor"];
|
||||
}
|
||||
static const NSInteger YTLitePlusSection = 500;
|
||||
|
||||
@interface YTSettingsSectionItemManager (YTLitePlus)
|
||||
- (void)updateYTLitePlusSectionWithEntry:(id)entry;
|
||||
@end
|
||||
|
||||
extern NSBundle *YTLitePlusBundle();
|
||||
|
||||
// Settings
|
||||
%hook YTAppSettingsPresentationData
|
||||
+ (NSArray *)settingsCategoryOrder {
|
||||
NSArray *order = %orig;
|
||||
NSMutableArray *mutableOrder = [order mutableCopy];
|
||||
NSUInteger insertIndex = [order indexOfObject:@(1)];
|
||||
if (insertIndex != NSNotFound)
|
||||
[mutableOrder insertObject:@(YTLitePlusSection) atIndex:insertIndex + 1];
|
||||
return mutableOrder;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTSettingsSectionController
|
||||
|
||||
- (void)setSelectedItem:(NSUInteger)selectedItem {
|
||||
if (selectedItem != NSNotFound) %orig;
|
||||
}
|
||||
|
||||
%end
|
||||
|
||||
%hook YTSettingsSectionItemManager
|
||||
%new(v@:@)
|
||||
- (void)updateYTLitePlusSectionWithEntry:(id)entry {
|
||||
NSMutableArray *sectionItems = [NSMutableArray array];
|
||||
NSBundle *tweakBundle = YTLitePlusBundle();
|
||||
Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem);
|
||||
YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"];
|
||||
|
||||
YTSettingsSectionItem *main = [%c(YTSettingsSectionItem)
|
||||
itemWithTitle:[NSString stringWithFormat:LOC(@"VERSION"), @(OS_STRINGIFY(TWEAK_VERSION))]
|
||||
titleDescription:LOC(@"VERSION_CHECK")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:nil
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/Balackburn/YTLitePlusExtra/releases/latest"]];
|
||||
}];
|
||||
[sectionItems addObject:main];
|
||||
|
||||
# pragma mark - VideoPlayer
|
||||
YTSettingsSectionItem *videoPlayerGroup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"VIDEO_PLAYER_OPTIONS") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"AUTO_FULLSCREEN")
|
||||
titleDescription:LOC(@"AUTO_FULLSCREEN_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"autoFull_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"autoFull_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"TAP_TO_SKIP")
|
||||
titleDescription:LOC(@"TAP_TO_SKIP_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"tapToSkip_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"tapToSkip_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"SNAP_TO_CHAPTER")
|
||||
titleDescription:LOC(@"SNAP_TO_CHAPTER_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"snapToChapter_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"snapToChapter_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"PINCH_TO_ZOOM")
|
||||
titleDescription:LOC(@"PINCH_TO_ZOOM_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"pinchToZoom_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"pinchToZoom_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"YT_MINIPLAYER")
|
||||
titleDescription:LOC(@"YT_MINIPLAYER_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"ytMiniPlayer_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"ytMiniPlayer_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"STOCK_VOLUME_HUD")
|
||||
titleDescription:LOC(@"STOCK_VOLUME_HUD_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"stockVolumeHUD_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"stockVolumeHUD_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0]
|
||||
];
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"VIDEO_PLAYER_OPTIONS") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:videoPlayerGroup];
|
||||
|
||||
# pragma mark - Video Controls Overlay Options
|
||||
YTSettingsSectionItem *videoControlOverlayGroup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"VIDEO_CONTROLS_OVERLAY_OPTIONS") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"ENABLE_SHARE_BUTTON")
|
||||
titleDescription:LOC(@"ENABLE_SHARE_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"enableShareButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"enableShareButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"ENABLE_SAVE_TO_PLAYLIST_BUTTON")
|
||||
titleDescription:LOC(@"ENABLE_SAVE_TO_PLAYLIST_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"enableSaveToButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"enableSaveToButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_AUTOPLAY_SWITCH")
|
||||
titleDescription:LOC(@"HIDE_AUTOPLAY_SWITCH_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideAutoplaySwitch_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideAutoplaySwitch_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SUBTITLES_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_SUBTITLES_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideCC_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideCC_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_HUD_MESSAGES")
|
||||
titleDescription:LOC(@"HIDE_HUD_MESSAGES_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideHUD_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideHUD_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_PAID_PROMOTION_CARDS")
|
||||
titleDescription:LOC(@"HIDE_PAID_PROMOTION_CARDS_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hidePaidPromotionCard_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hidePaidPromotionCard_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_CHANNEL_WATERMARK")
|
||||
titleDescription:LOC(@"HIDE_CHANNEL_WATERMARK_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideChannelWatermark_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideChannelWatermark_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SHADOW_OVERLAY_BUTTONS")
|
||||
titleDescription:LOC(@"HIDE_SHADOW_OVERLAY_BUTTONS_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideVideoPlayerShadowOverlayButtons_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideVideoPlayerShadowOverlayButtons_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_PREVIOUS_AND_NEXT_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_PREVIOUS_AND_NEXT_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hidePreviousAndNextButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hidePreviousAndNextButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"REPLACE_PREVIOUS_NEXT_BUTTON")
|
||||
titleDescription:LOC(@"REPLACE_PREVIOUS_NEXT_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"replacePreviousAndNextButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"replacePreviousAndNextButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"RED_PROGRESS_BAR")
|
||||
titleDescription:LOC(@"RED_PROGRESS_BAR_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"redProgressBar_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"redProgressBar_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"DISABLE_VIDEO_PLAYER_ZOOM")
|
||||
titleDescription:LOC(@"DISABLE_VIDEO_PLAYER_ZOOM")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"disableVideoPlayerZoom_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"disableVideoPlayerZoom_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_HOVER_CARD")
|
||||
titleDescription:LOC(@"HIDE_HOVER_CARD_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideHoverCards_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideHoverCards_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_RIGHT_PANEL")
|
||||
titleDescription:LOC(@"HIDE_RIGHT_PANEL_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideRightPanel_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideRightPanel_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_HEATWAVES")
|
||||
titleDescription:LOC(@"HIDE_HEATWAVES_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideHeatwaves_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideHeatwaves_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_DARK_OVERLAY_BACKGROUND")
|
||||
titleDescription:LOC(@"HIDE_DARK_OVERLAY_BACKGROUND_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideOverlayDarkBackground_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideOverlayDarkBackground_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0]
|
||||
];
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"VIDEO_CONTROLS_OVERLAY_OPTIONS") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:videoControlOverlayGroup];
|
||||
|
||||
# pragma mark - Shorts Controls Overlay Options
|
||||
YTSettingsSectionItem *shortsControlOverlayGroup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"SHORTS_CONTROLS_OVERLAY_OPTIONS") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SHORTS_VIDEOS")
|
||||
titleDescription:LOC(@"HIDE_SHORTS_VIDEOS_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideShorts_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideShorts_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SHORTS_CHANNEL_AVATAR")
|
||||
titleDescription:LOC(@"HIDE_SHORTS_CHANNEL_AVATAR_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideShortsChannelAvatar_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideShortsChannelAvatar_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SHORTS_LIKE_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_SHORTS_LIKE_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideShortsLikeButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideShortsLikeButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SHORTS_DISLIKE_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_SHORTS_DISLIKE_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideShortsDislikeButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideShortsDislikeButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SHORTS_COMMENT_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_SHORTS_COMMENT_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideShortsCommentButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideShortsCommentButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SHORTS_REMIX_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_SHORTS_REMIX_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideShortsRemixButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideShortsRemixButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SHORTS_SHARE_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_SHORTS_SHARE_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideShortsShareButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideShortsShareButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SUPER_THANKS")
|
||||
titleDescription:LOC(@"HIDE_SUPER_THANKS_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideBuySuperThanks_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideBuySuperThanks_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SUBSCRIPTIONS")
|
||||
titleDescription:LOC(@"HIDE_SUBSCRIPTIONS_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideSubscriptions_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideSubscriptions_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0]
|
||||
];
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"SHORTS_CONTROLS_OVERLAY_OPTIONS") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:shortsControlOverlayGroup];
|
||||
|
||||
# pragma mark - LowContrastMode
|
||||
YTSettingsSectionItem *lowContrastModeSection = [YTSettingsSectionItemClass itemWithTitle:LOC(@"LCM_CHOOSE_COLOR")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
switch (colorContrastMode()) {
|
||||
case 1:
|
||||
return LOC(@"RED_UI");
|
||||
case 2:
|
||||
return LOC(@"BLUE_UI");
|
||||
case 3:
|
||||
return LOC(@"GREEN_UI");
|
||||
case 4:
|
||||
return LOC(@"YELLOW_UI");
|
||||
case 5:
|
||||
return LOC(@"ORANGE_UI");
|
||||
case 6:
|
||||
return LOC(@"PURPLE_UI");
|
||||
case 7:
|
||||
return LOC(@"VIOLET_UI");
|
||||
case 8:
|
||||
return LOC(@"PINK_UI");
|
||||
case 0:
|
||||
default:
|
||||
return LOC(@"DEFAULT_UI");
|
||||
}
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"DEFAULT_UI") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"lcmColor"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"RED_UI") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:@"lcmColor"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"BLUE_UI") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:2 forKey:@"lcmColor"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"GREEN_UI") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:3 forKey:@"lcmColor"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"YELLOW_UI") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:4 forKey:@"lcmColor"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"ORANGE_UI") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:5 forKey:@"lcmColor"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"PURPLE_UI") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:6 forKey:@"lcmColor"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"VIOLET_UI") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:7 forKey:@"lcmColor"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"PINK_UI") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:8 forKey:@"lcmColor"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}]
|
||||
];
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"LCM_CHOOSE_COLOR") pickerSectionTitle:nil rows:rows selectedItemIndex:colorContrastMode() parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
|
||||
# pragma mark - Theme
|
||||
YTSettingsSectionItem *themeGroup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"THEME_OPTIONS")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
switch (GetSelection(@"appTheme")) {
|
||||
case 1:
|
||||
return LOC(@"OLED_DARK_THEME_2");
|
||||
case 2:
|
||||
return LOC(@"OLD_DARK_THEME");
|
||||
case 0:
|
||||
default:
|
||||
return LOC(@"DEFAULT_THEME");
|
||||
}
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"DEFAULT_THEME") titleDescription:LOC(@"DEFAULT_THEME_DESC") selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"appTheme"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"OLED_DARK_THEME") titleDescription:LOC(@"OLED_DARK_THEME_DESC") selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:@"appTheme"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"OLD_DARK_THEME") titleDescription:LOC(@"OLD_DARK_THEME_DESC") selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:2 forKey:@"appTheme"];
|
||||
[settingsViewController reloadData];
|
||||
return YES;
|
||||
}],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"OLED_KEYBOARD")
|
||||
titleDescription:LOC(@"OLED_KEYBOARD_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"oledKeyBoard_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"oledKeyBoard_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"LOW_CONTRAST_MODE")
|
||||
titleDescription:LOC(@"LOW_CONTRAST_MODE_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"lowContrastMode_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"lowContrastMode_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0], lowContrastModeSection];
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"THEME_OPTIONS") pickerSectionTitle:nil rows:rows selectedItemIndex:GetSelection(@"appTheme") parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:themeGroup];
|
||||
|
||||
# pragma mark - Miscellaneous
|
||||
YTSettingsSectionItem *miscellaneousGroup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"MISCELLANEOUS") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"ENABLE_YT_STARTUP_ANIMATION")
|
||||
titleDescription:LOC(@"ENABLE_YT_STARTUP_ANIMATION_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"ytStartupAnimation_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"ytStartupAnimation_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_YOUTUBE_LOGO")
|
||||
titleDescription:LOC(@"HIDE_YOUTUBE_LOGO_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideYouTubeLogo_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideYouTubeLogo_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_CHIP_BAR")
|
||||
titleDescription:LOC(@"HIDE_CHIP_BAR_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideChipBar_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideChipBar_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_MODERN_INTERFACE")
|
||||
titleDescription:LOC(@"HIDE_MODERN_INTERFACE_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"ytNoModernUI_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"ytNoModernUI_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"IPAD_LAYOUT")
|
||||
titleDescription:LOC(@"IPAD_LAYOUT_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"iPadLayout_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"iPadLayout_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"IPHONE_LAYOUT")
|
||||
titleDescription:LOC(@"IPHONE_LAYOUT_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"iPhoneLayout_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"iPhoneLayout_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"CAST_CONFIRM")
|
||||
titleDescription:LOC(@"CAST_CONFIRM_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"castConfirm_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"castConfirm_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"DISABLE_HINTS")
|
||||
titleDescription:LOC(@"DISABLE_HINTS_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"disableHints_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"disableHints_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"NEW_MINIPLAYER_STYLE")
|
||||
titleDescription:LOC(@"NEW_MINIPLAYER_STYLE_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"bigYTMiniPlayer_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"bigYTMiniPlayer_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_CAST_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_CAST_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideCastButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideCastButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_NOTIFICATION_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_NOTIFICATION_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideNotificationButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideNotificationButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_SPONSORBLOCK_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_SPONSORBLOCK_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideSponsorBlockButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideSponsorBlockButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_CERCUBE_BUTTON")
|
||||
titleDescription:LOC(@"")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideCercubeButton_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideCercubeButton_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_CERCUBE_PIP_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_CERCUBE_PIP_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideCercubePiP_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"hideCercubePiP_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HIDE_CERCUBE_DOWNLOAD_BUTTON")
|
||||
titleDescription:LOC(@"HIDE_CERCUBE_DOWNLOAD_BUTTON_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"hideCercubeDownload_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL disabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"hideCercubeDownload_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"DISABLE_WIFI_RELATED_SETTINGS")
|
||||
titleDescription:LOC(@"DISABLE_WIFI_RELATED_SETTINGS_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"disableWifiRelatedSettings_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"disableWifiRelatedSettings_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"YT_RE_EXPLORE")
|
||||
titleDescription:LOC(@"YT_RE_EXPLORE_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"reExplore_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"reExplore_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"YT_SPEED")
|
||||
titleDescription:LOC(@"YT_SPEED_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"ytSpeed_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"ytSpeed_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0],
|
||||
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"ENABLE_FLEX")
|
||||
titleDescription:LOC(@"ENABLE_FLEX_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IsEnabled(@"flex_enabled")
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"flex_enabled"];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0]
|
||||
];
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"MISCELLANEOUS") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:miscellaneousGroup];
|
||||
|
||||
[settingsViewController setSectionItems:sectionItems forCategory:YTLitePlusSection title:@"YTLitePlus" titleDescription:LOC(@"TITLE DESCRIPTION") headerHidden:YES];
|
||||
}
|
||||
|
||||
- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry {
|
||||
if (category == YTLitePlusSection) {
|
||||
[self updateYTLitePlusSectionWithEntry:entry];
|
||||
return;
|
||||
}
|
||||
%orig;
|
||||
}
|
||||
%end
|
466
Source/Themes.xm
Normal file
466
Source/Themes.xm
Normal file
@@ -0,0 +1,466 @@
|
||||
#import "../Header.h"
|
||||
|
||||
static BOOL IsEnabled(NSString *key) {
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:key];
|
||||
}
|
||||
static BOOL isDarkMode() {
|
||||
return ([[NSUserDefaults standardUserDefaults] integerForKey:@"page_style"] == 1);
|
||||
}
|
||||
static BOOL oledDarkTheme() {
|
||||
return ([[NSUserDefaults standardUserDefaults] integerForKey:@"appTheme"] == 1);
|
||||
}
|
||||
static BOOL oldDarkTheme() {
|
||||
return ([[NSUserDefaults standardUserDefaults] integerForKey:@"appTheme"] == 2);
|
||||
}
|
||||
|
||||
// Themes.xm - Theme Options
|
||||
// Old dark theme (gray)
|
||||
%group gOldDarkTheme
|
||||
%hook YTAsyncCollectionView
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0] : %orig;
|
||||
}
|
||||
- (UIColor *)darkBackgroundColor {
|
||||
return [UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0];
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTAppView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
%orig([UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0]);
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTPivotBarView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
%orig([UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0]);
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTAsyncCollectionView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
%orig([UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0]);
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTAppViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTNavigationBar
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTInnerTubeCollectionViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTColdConfig
|
||||
- (BOOL)uiSystemsClientGlobalConfigUseDarkerPaletteBgColorForNative { return NO; }
|
||||
- (BOOL)uiSystemsClientGlobalConfigUseDarkerPaletteTextColorForNative { return NO; }
|
||||
- (BOOL)enableCinematicContainerOnClient { return NO; }
|
||||
%end
|
||||
|
||||
%hook _ASDisplayView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.comment_composer"]) { self.backgroundColor = [UIColor clearColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.video_list_entry"]) { self.backgroundColor = [UIColor clearColor]; }
|
||||
}
|
||||
%end
|
||||
|
||||
%hook ASCollectionView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
self.superview.backgroundColor = [UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0];
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTFullscreenEngagementOverlayView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
self.subviews[0].backgroundColor = [UIColor clearColor];
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTRelatedVideosView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
self.subviews[0].backgroundColor = [UIColor clearColor];
|
||||
}
|
||||
%end
|
||||
%end
|
||||
|
||||
// OLED dark mode by BandarHL
|
||||
UIColor* raisedColor = [UIColor colorWithRed:0.035 green:0.035 blue:0.035 alpha:1.0];
|
||||
%group gOLED
|
||||
%hook YTCommonColorPalette
|
||||
- (UIColor *)brandBackgroundSolid {
|
||||
return self.pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
- (UIColor *)brandBackgroundPrimary {
|
||||
return self.pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
- (UIColor *)brandBackgroundSecondary {
|
||||
return self.pageStyle == 1 ? [[UIColor blackColor] colorWithAlphaComponent:0.9] : %orig;
|
||||
}
|
||||
- (UIColor *)raisedBackground {
|
||||
return self.pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
- (UIColor *)staticBrandBlack {
|
||||
return self.pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
- (UIColor *)generalBackgroundA {
|
||||
return self.pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTAppView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
%orig([UIColor blackColor]);
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTPivotBarView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
%orig([UIColor blackColor]);
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTAsyncCollectionView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
%orig([UIColor blackColor]);
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTAppViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTNavigationBar
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
BOOL areColorsEqual(UIColor *color1, UIColor *color2, CGFloat tolerance) {
|
||||
CGFloat r1, g1, b1, a1, r2, g2, b2, a2;
|
||||
[color1 getRed:&r1 green:&g1 blue:&b1 alpha:&a1];
|
||||
[color2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2];
|
||||
|
||||
return (fabs(r1 - r2) <= tolerance) &&
|
||||
(fabs(g1 - g2) <= tolerance) &&
|
||||
(fabs(b1 - b2) <= tolerance) &&
|
||||
(fabs(a1 - a2) <= tolerance);
|
||||
}
|
||||
|
||||
%hook UIView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
UIColor *targetColor = [UIColor colorWithRed:0.0588235 green:0.0588235 blue:0.0588235 alpha:1];
|
||||
CGFloat tolerance = 0.01; // Adjust this value as needed
|
||||
|
||||
if (areColorsEqual(color, targetColor, tolerance)) {
|
||||
color = [UIColor blackColor];
|
||||
}
|
||||
%orig(color);
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTCollectionViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTChannelMobileHeaderViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTELMView
|
||||
- (UIColor *)backgroundColor {
|
||||
return [UIColor blackColor];
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTHeaderViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
- (UIColor *)barTintColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTInnerTubeCollectionViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTSettingsCell
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTSearchViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTSectionListViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTWatchMiniBarViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTWrapperSplitViewController
|
||||
- (UIColor *)backgroundColor:(NSInteger)pageStyle {
|
||||
return pageStyle == 1 ? [UIColor blackColor] : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
// Explore
|
||||
%hook ASScrollView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
if (isDarkMode()) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
// Your videos
|
||||
%hook ASCollectionView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
if (isDarkMode() && [self.nextResponder isKindOfClass:%c(_ASDisplayView)]) {
|
||||
self.superview.backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
// Sub?
|
||||
%hook ELMView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
if (isDarkMode()) {
|
||||
self.subviews[0].backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
// iSponsorBlock
|
||||
%hook SponsorBlockSettingsController
|
||||
- (void)viewDidLoad {
|
||||
if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
|
||||
%orig;
|
||||
self.tableView.backgroundColor = [UIColor blackColor];
|
||||
} else { return %orig; }
|
||||
}
|
||||
%end
|
||||
|
||||
%hook SponsorBlockViewController
|
||||
- (void)viewDidLoad {
|
||||
if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
|
||||
%orig;
|
||||
self.view.backgroundColor = [UIColor blackColor];
|
||||
} else { return %orig; }
|
||||
}
|
||||
%end
|
||||
|
||||
// Search View
|
||||
%hook YTSearchBarView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig([UIColor blackColor]) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
// History Search view
|
||||
%hook YTSearchBoxView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig([UIColor blackColor]) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
// Comment view
|
||||
%hook YTCommentView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig([UIColor blackColor]) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTCreateCommentAccessoryView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig([UIColor blackColor]) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTCreateCommentTextView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig([UIColor blackColor]) : %orig;
|
||||
}
|
||||
- (void)setTextColor:(UIColor *)color { // fix black text in #Shorts video's comment
|
||||
return isDarkMode() ? %orig([UIColor whiteColor]) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTCommentDetailHeaderCell
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
if (isDarkMode()) {
|
||||
self.subviews[2].backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTFormattedStringLabel // YT is werid...
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig([UIColor clearColor]) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
// Live chat comment
|
||||
%hook YCHLiveChatActionPanelView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig([UIColor blackColor]) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTEmojiTextView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig([UIColor blackColor]) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YCHLiveChatView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
if (isDarkMode()) {
|
||||
self.subviews[1].backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
//
|
||||
%hook YTBackstageCreateRepostDetailView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig([UIColor blackColor]) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
// Others
|
||||
%hook _ASDisplayView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
if (isDarkMode()) {
|
||||
if ([self.nextResponder isKindOfClass:%c(ASScrollView)]) { self.backgroundColor = [UIColor clearColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"eml.cvr"]) { self.backgroundColor = [UIColor blackColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"rich_header"]) { self.backgroundColor = [UIColor blackColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.ui.comment_cell"]) { self.backgroundColor = [UIColor blackColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.ui.cancel.button"]) { self.superview.backgroundColor = [UIColor clearColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.comment_composer"]) { self.backgroundColor = [UIColor blackColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.video_list_entry"]) { self.backgroundColor = [UIColor blackColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.comment.guidelines_text"]) { self.superview.backgroundColor = [UIColor blackColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.comment.channel_guidelines_bottom_sheet_container"]) { self.backgroundColor = [UIColor blackColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.comment.channel_guidelines_entry_banner_container"]) { self.backgroundColor = [UIColor blackColor]; }
|
||||
if ([self.accessibilityIdentifier isEqualToString:@"id.comment.comment_group_detail_container"]) { self.backgroundColor = [UIColor clearColor]; }
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
// Open link with...
|
||||
%hook ASWAppSwitchingSheetHeaderView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig(raisedColor) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook ASWAppSwitchingSheetFooterView
|
||||
- (void)setBackgroundColor:(UIColor *)color {
|
||||
return isDarkMode() ? %orig(raisedColor) : %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook ASWAppSwitcherCollectionViewCell
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
if (isDarkMode()) {
|
||||
self.backgroundColor = raisedColor;
|
||||
self.subviews[1].backgroundColor = raisedColor;
|
||||
self.superview.backgroundColor = raisedColor;
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
// Incompatibility with the new YT Dark theme
|
||||
%hook YTColdConfig
|
||||
- (BOOL)uiSystemsClientGlobalConfigUseDarkerPaletteBgColorForNative { return NO; }
|
||||
%end
|
||||
%end
|
||||
|
||||
// OLED keyboard by @ichitaso <3 - http://gist.github.com/ichitaso/935100fd53a26f18a9060f7195a1be0e
|
||||
%group gOLEDKB
|
||||
%hook UIPredictionViewController
|
||||
- (void)loadView {
|
||||
%orig;
|
||||
[self.view setBackgroundColor:[UIColor blackColor]];
|
||||
}
|
||||
%end
|
||||
|
||||
%hook UICandidateViewController
|
||||
- (void)loadView {
|
||||
%orig;
|
||||
[self.view setBackgroundColor:[UIColor blackColor]];
|
||||
}
|
||||
%end
|
||||
|
||||
%hook UIKeyboardDockView
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
self.backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
%end
|
||||
|
||||
%hook UIKeyboardLayoutStar
|
||||
- (void)didMoveToWindow {
|
||||
%orig;
|
||||
self.backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
%end
|
||||
|
||||
%hook UIKBRenderConfig // Prediction text color
|
||||
- (void)setLightKeyboard:(BOOL)arg1 { %orig(NO); }
|
||||
%end
|
||||
%end
|
||||
|
||||
# pragma mark - ctor
|
||||
%ctor {
|
||||
%init;
|
||||
if (IsEnabled(@"oledKeyBoard_enabled")) {
|
||||
%init(gOLEDKB);
|
||||
}
|
||||
if (oledDarkTheme()) {
|
||||
%init(gOLED);
|
||||
}
|
||||
if (oldDarkTheme()) {
|
||||
%init(gOldDarkTheme);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user