#1890 (Add Auto to theme selector)

- Added an Auto option to the theme segmented controls and submenu (on Mac).
- When Auto is chosen, the theme is light or dark to match the system appearance.
- Removed the Follow System Appearance option in the Preferences/Settings, since it performed much the same function.
- If that Follow System Appearance option was enabled, the theme is set to Auto to preserve the same behavior.
- Removed the Theme popup from the Settings window on Mac, since it had multiple issues and wasn’t really needed.
This commit is contained in:
David Sinclair 2024-08-29 15:51:37 -07:00
parent 06f2a665c1
commit 6aaa2e41ab
10 changed files with 116 additions and 113 deletions

View file

@ -117,12 +117,14 @@
}
NSString *theme = [ThemeManager themeManager].theme;
if ([theme isEqualToString:@"sepia"]) {
if ([theme isEqualToString:@"light"]) {
self.themeSegment.selectedSegmentIndex = 1;
} else if ([theme isEqualToString:@"medium"]) {
} else if ([theme isEqualToString:@"sepia"]) {
self.themeSegment.selectedSegmentIndex = 2;
} else if ([theme isEqualToString:@"dark"]) {
} else if ([theme isEqualToString:@"medium"]) {
self.themeSegment.selectedSegmentIndex = 3;
} else if ([theme isEqualToString:@"dark"]) {
self.themeSegment.selectedSegmentIndex = 4;
} else {
self.themeSegment.selectedSegmentIndex = 0;
}
@ -241,15 +243,18 @@
- (IBAction)changeTheme:(id)sender {
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
NSString *theme = ThemeStyleLight;
NSString *theme = ThemeStyleAuto;
switch ([sender selectedSegmentIndex]) {
case 1:
theme = ThemeStyleSepia;
theme = ThemeStyleLight;
break;
case 2:
theme = ThemeStyleMedium;
theme = ThemeStyleSepia;
break;
case 3:
theme = ThemeStyleMedium;
break;
case 4:
theme = ThemeStyleDark;
break;
@ -559,16 +564,17 @@
cell.separatorInset = UIEdgeInsetsZero;
cell.backgroundColor = UIColorFromRGB(0xffffff);
UIImage *lightImage = [self themeImageWithName:@"theme_color_light" selected:self.themeSegment.selectedSegmentIndex == 0];
UIImage *sepiaImage = [self themeImageWithName:@"theme_color_sepia" selected:self.themeSegment.selectedSegmentIndex == 1];
UIImage *mediumImage = [self themeImageWithName:@"theme_color_medium" selected:self.themeSegment.selectedSegmentIndex == 2];
UIImage *darkImage = [self themeImageWithName:@"theme_color_dark" selected:self.themeSegment.selectedSegmentIndex == 3];
UIImage *lightImage = [self themeImageWithName:@"theme_color_light" selected:self.themeSegment.selectedSegmentIndex == 1];
UIImage *sepiaImage = [self themeImageWithName:@"theme_color_sepia" selected:self.themeSegment.selectedSegmentIndex == 2];
UIImage *mediumImage = [self themeImageWithName:@"theme_color_medium" selected:self.themeSegment.selectedSegmentIndex == 3];
UIImage *darkImage = [self themeImageWithName:@"theme_color_dark" selected:self.themeSegment.selectedSegmentIndex == 4];
self.themeSegment.frame = CGRectMake(8, 4, cell.frame.size.width - 8*2, kMenuOptionHeight - 4*2);
[self.themeSegment setImage:lightImage forSegmentAtIndex:0];
[self.themeSegment setImage:sepiaImage forSegmentAtIndex:1];
[self.themeSegment setImage:mediumImage forSegmentAtIndex:2];
[self.themeSegment setImage:darkImage forSegmentAtIndex:3];
[self.themeSegment setTitle:@"Auto" forSegmentAtIndex:0];
[self.themeSegment setImage:lightImage forSegmentAtIndex:1];
[self.themeSegment setImage:sepiaImage forSegmentAtIndex:2];
[self.themeSegment setImage:mediumImage forSegmentAtIndex:3];
[self.themeSegment setImage:darkImage forSegmentAtIndex:4];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(1, self.themeSegment.frame.size.height), NO, 0.0);
UIImage *blankImage = UIGraphicsGetImageFromCurrentImageContext();

View file

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
<device id="ipad9_7" orientation="portrait" layout="fullscreen" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15510"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -85,10 +85,11 @@
<action selector="changeAutoscroll:" destination="-1" eventType="valueChanged" id="dFh-eV-zfx"/>
</connections>
</segmentedControl>
<segmentedControl opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="2" translatesAutoresizingMaskIntoConstraints="NO" id="9Zd-0Z-SQt">
<rect key="frame" x="3" y="97" width="234" height="29"/>
<segmentedControl opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="9Zd-0Z-SQt">
<rect key="frame" x="3" y="96" width="234" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<segments>
<segment title="Auto"/>
<segment title="" image="theme_color_light.png"/>
<segment title="" image="theme_color_sepia.png"/>
<segment title="" image="theme_color_medium.png"/>

View file

@ -175,7 +175,7 @@ NSString * const MenuHandler = @"handler";
cell.backgroundColor = UIColorFromRGB(0xffffff);
NSString *theme = [ThemeManager themeManager].theme;
NSArray *values = @[ThemeStyleLight, ThemeStyleSepia, ThemeStyleMedium, ThemeStyleDark];
NSArray *values = @[ThemeStyleAuto, ThemeStyleLight, ThemeStyleSepia, ThemeStyleMedium, ThemeStyleDark];
NSUInteger valueIndex = [values indexOfObject:theme];
if (valueIndex < 0) {
@ -186,15 +186,18 @@ NSString * const MenuHandler = @"handler";
[segmentedControl addTarget:self action:@selector(changeTheme:) forControlEvents:UIControlEventValueChanged];
UIImage *lightImage = [self themeImageWithName:@"theme_color_light" selected:valueIndex == 0];
UIImage *sepiaImage = [self themeImageWithName:@"theme_color_sepia" selected:valueIndex == 1];
UIImage *mediumImage = [self themeImageWithName:@"theme_color_medium" selected:valueIndex == 2];
UIImage *darkImage = [self themeImageWithName:@"theme_color_dark" selected:valueIndex == 3];
UIImage *lightImage = [self themeImageWithName:@"theme_color_light" selected:valueIndex == 1];
UIImage *sepiaImage = [self themeImageWithName:@"theme_color_sepia" selected:valueIndex == 2];
UIImage *mediumImage = [self themeImageWithName:@"theme_color_medium" selected:valueIndex == 3];
UIImage *darkImage = [self themeImageWithName:@"theme_color_dark" selected:valueIndex == 4];
[segmentedControl insertSegmentWithImage:lightImage atIndex:0 animated: NO];
[segmentedControl insertSegmentWithImage:sepiaImage atIndex:1 animated: NO];
[segmentedControl insertSegmentWithImage:mediumImage atIndex:2 animated: NO];
[segmentedControl insertSegmentWithImage:darkImage atIndex:3 animated: NO];
[segmentedControl insertSegmentWithTitle:@"Auto" atIndex:0 animated:NO];
[segmentedControl insertSegmentWithImage:lightImage atIndex:1 animated: NO];
[segmentedControl insertSegmentWithImage:sepiaImage atIndex:2 animated: NO];
[segmentedControl insertSegmentWithImage:mediumImage atIndex:3 animated: NO];
[segmentedControl insertSegmentWithImage:darkImage atIndex:4 animated: NO];
[segmentedControl setTitleTextAttributes:@{NSFontAttributeName : [UIFont fontWithName:@"WhitneySSm-Medium" size:12.0]} forState:UIControlStateNormal];
[[ThemeManager themeManager] updateThemeSegmentedControl:segmentedControl];
@ -216,7 +219,7 @@ NSString * const MenuHandler = @"handler";
}
- (IBAction)changeTheme:(UISegmentedControl *)sender {
NSArray *values = @[ThemeStyleLight, ThemeStyleSepia, ThemeStyleMedium, ThemeStyleDark];
NSArray *values = @[ThemeStyleAuto, ThemeStyleLight, ThemeStyleSepia, ThemeStyleMedium, ThemeStyleDark];
[ThemeManager themeManager].theme = [values objectAtIndex:sender.selectedSegmentIndex];

View file

@ -964,11 +964,6 @@
if (system_font_enabled) {
[hiddenSet addObjectsFromArray:@[@"feed_list_font_size"]];
}
BOOL theme_follow_system = [[NSUserDefaults standardUserDefaults] boolForKey:@"theme_follow_system"];
if (theme_follow_system) {
[hiddenSet addObjectsFromArray:@[@"theme_auto_toggle", @"theme_auto_brightness", @"theme_style", @"theme_gesture"]];
[[ThemeManager themeManager] updateForSystemAppearance];
}
BOOL theme_auto_toggle = [[NSUserDefaults standardUserDefaults] boolForKey:@"theme_auto_toggle"];
if (theme_auto_toggle) {
[hiddenSet addObjectsFromArray:@[@"theme_style", @"theme_gesture"]];

View file

@ -18,6 +18,7 @@
#define NEWSBLUR_WHITE_COLOR 0xffffff
#define NEWSBLUR_BLACK_COLOR 0x0
extern NSString * const ThemeStyleAuto;
extern NSString * const ThemeStyleLight;
extern NSString * const ThemeStyleSepia;
extern NSString * const ThemeStyleMedium;
@ -30,6 +31,7 @@ extern NSString * const ThemeStyleDark;
@property (nonatomic, strong) NSString *theme;
@property (nonatomic, readonly) NSString *themeDisplayName;
@property (nonatomic, readonly) NSString *themeCSSSuffix;
@property (nonatomic, readonly) BOOL isAutoTheme;
@property (nonatomic, readonly) BOOL isDarkTheme;
@property (nonatomic, readonly) BOOL isSystemDark;
@property (nonatomic, readonly) BOOL isLikeSystem;

View file

@ -13,6 +13,7 @@
#import <AudioToolbox/AudioToolbox.h>
#import "NewsBlur-Swift.h"
NSString * const ThemeStyleAuto = @"auto";
NSString * const ThemeStyleLight = @"light";
NSString * const ThemeStyleSepia = @"sepia";
NSString * const ThemeStyleMedium = @"medium";
@ -42,6 +43,7 @@ NSString * const ThemeStyleDark = @"dark";
@property (nonatomic, readonly) NewsBlurAppDelegate *appDelegate;
@property (nonatomic) BOOL justToggledViaGesture;
@property (nonatomic) BOOL isAutoDark;
@end
@ -66,16 +68,13 @@ NSString * const ThemeStyleDark = @"dark";
NSString *theme = [[NSUserDefaults standardUserDefaults] objectForKey:@"theme_style"];
if (![self isValidTheme:theme]) {
theme = ThemeStyleLight;
theme = ThemeStyleAuto;
}
return theme;
}
- (void)setTheme:(NSString *)theme {
// Automatically turn off following the system appearance when manually changing the theme.
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"theme_follow_system"];
[self reallySetTheme:theme];
NSLog(@"Manually changed to theme: %@", self.themeDisplayName); // log
@ -97,8 +96,10 @@ NSString * const ThemeStyleDark = @"dark";
return @"Sepia";
} else if ([theme isEqualToString:ThemeStyleMedium]) {
return @"Medium";
} else {
} else if ([theme isEqualToString:ThemeStyleLight]) {
return @"Light";
} else {
return @"Auto";
}
}
@ -107,10 +108,14 @@ NSString * const ThemeStyleDark = @"dark";
if ([theme isEqualToString:ThemeStyleDark]) {
return @"Dark";
} else if ([theme isEqualToString:ThemeStyleSepia]) {
return @"Sepia";
} else if ([theme isEqualToString:ThemeStyleMedium]) {
return @"Medium";
} else if ([theme isEqualToString:ThemeStyleSepia]) {
return @"Sepia";
} else if ([theme isEqualToString:ThemeStyleLight]) {
return @"Light";
} else if (self.isSystemDark) {
return @"Dark";
} else {
return @"Light";
}
@ -125,14 +130,24 @@ NSString * const ThemeStyleDark = @"dark";
return ThemeStyleDark;
} else if ([theme isEqualToString:ThemeStyleSepia]) {
return ThemeStyleLight;
} else {
} else if ([theme isEqualToString:ThemeStyleLight]) {
return ThemeStyleSepia;
} else {
return ThemeStyleAuto;
}
}
- (BOOL)isAutoTheme {
return [self.theme isEqualToString:ThemeStyleAuto];
}
- (BOOL)isDarkTheme {
NSString *theme = self.theme;
if (self.isAutoTheme) {
return self.isSystemDark;
}
return [theme isEqualToString:ThemeStyleDark] || [theme isEqualToString:ThemeStyleMedium];
}
@ -145,7 +160,7 @@ NSString * const ThemeStyleDark = @"dark";
}
- (BOOL)isValidTheme:(NSString *)theme {
return [theme isEqualToString:ThemeStyleLight] || [theme isEqualToString:ThemeStyleSepia] || [theme isEqualToString:ThemeStyleMedium] || [theme isEqualToString:ThemeStyleDark];
return [theme isEqualToString:ThemeStyleAuto] || [theme isEqualToString:ThemeStyleLight] || [theme isEqualToString:ThemeStyleSepia] || [theme isEqualToString:ThemeStyleMedium] || [theme isEqualToString:ThemeStyleDark];
}
- (NewsBlurAppDelegate *)appDelegate {
@ -173,7 +188,9 @@ NSString * const ThemeStyleDark = @"dark";
- (UIColor *)colorFromLightRGB:(NSInteger)lightRGBValue sepiaRGB:(NSUInteger)sepiaRGBValue mediumRGB:(NSUInteger)mediumRGBValue darkRGB:(NSUInteger)darkRGBValue {
NSInteger rgbValue = lightRGBValue;
if ([self.theme isEqualToString:ThemeStyleSepia]) {
if (self.isAutoTheme) {
rgbValue = self.isSystemDark ? darkRGBValue : rgbValue;
} else if ([self.theme isEqualToString:ThemeStyleSepia]) {
rgbValue = sepiaRGBValue;
} else if ([self.theme isEqualToString:ThemeStyleMedium]) {
rgbValue = mediumRGBValue;
@ -193,7 +210,13 @@ NSString * const ThemeStyleDark = @"dark";
// Debug method to log all of the unique colors; leave commented out
// [self debugColor:rgbValue];
if ([theme isEqualToString:ThemeStyleDark]) {
if (self.isAutoTheme) {
if (self.isSystemDark) {
return [UIColor colorWithRed:1.0 - red green:1.0 - green blue:1.0 - blue alpha:1.0];
} else {
return [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
}
} else if ([theme isEqualToString:ThemeStyleDark]) {
return [UIColor colorWithRed:1.0 - red green:1.0 - green blue:1.0 - blue alpha:1.0];
} else if ([theme isEqualToString:ThemeStyleMedium]) {
if (rgbValue == 0x8F918B) {
@ -284,6 +307,8 @@ NSString * const ThemeStyleDark = @"dark";
}
- (void)updateThemeSegmentedControl:(UISegmentedControl *)segmentedControl {
[self updateSegmentedControl:segmentedControl];
segmentedControl.tintColor = [UIColor clearColor];
#if !TARGET_OS_MACCATALYST
segmentedControl.backgroundColor = [UIColor clearColor];
@ -304,6 +329,14 @@ NSString * const ThemeStyleDark = @"dark";
}
- (void)prepareForWindow:(UIWindow *)window {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// Can remove this once everyone has updated to version 13.1.2 or later.
if ([prefs boolForKey:@"theme_follow_system"]) {
self.theme = ThemeStyleAuto;
[prefs setBool:NO forKey:@"theme_follow_system"];
}
[self autoChangeTheme];
[self setupTheme];
[self addThemeGestureRecognizerToView:window];
@ -335,10 +368,14 @@ NSString * const ThemeStyleDark = @"dark";
NSString *theme = self.theme;
NewsBlurAppDelegate *appDelegate = self.appDelegate;
if (self.isDarkTheme) {
[prefs setObject:theme forKey:@"theme_dark"];
if (self.isAutoTheme) {
self.isAutoDark = self.isSystemDark;
} else {
[prefs setObject:theme forKey:@"theme_light"];
if (self.isDarkTheme) {
[prefs setObject:theme forKey:@"theme_dark"];
} else {
[prefs setObject:theme forKey:@"theme_light"];
}
}
[self setupTheme];
@ -459,14 +496,24 @@ NSString * const ThemeStyleDark = @"dark";
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *wantTheme = nil;
if (![prefs boolForKey:@"theme_follow_system"]) {
if (!self.isAutoTheme) {
return;
}
if (isDark) {
wantTheme = [prefs objectForKey:@"theme_dark"];
if (self.isAutoTheme) {
if (isDark != self.isAutoDark) {
[self updateTheme];
NSLog(@"System changed to %@ appearance", isDark ? @"dark" : @"light"); // log
}
return;
} else {
wantTheme = [prefs objectForKey:@"theme_light"];
if (isDark) {
wantTheme = [prefs objectForKey:@"theme_dark"];
} else {
wantTheme = [prefs objectForKey:@"theme_light"];
}
}
if (self.theme != wantTheme) {

View file

@ -619,7 +619,12 @@
</menu>
<menu title="Theme" id="k0L-se-kpA">
<children>
<command title="Light" propertyListString="light" menuElementState="on" id="nvf-Kg-GEz">
<command title="Auto" propertyListString="auto" menuElementState="on" id="Wu8-Xa-cev">
<connections>
<action selector="chooseTheme:" destination="J28-e1-gcC" id="F96-ll-QZq"/>
</connections>
</command>
<command title="Light" propertyListString="light" id="nvf-Kg-GEz">
<connections>
<action selector="chooseTheme:" destination="J28-e1-gcC" id="AGW-N1-hqV"/>
</connections>
@ -785,7 +790,7 @@
<menu id="nKV-Y3-j73">
<menuOptions key="menuOptions" displayInline="YES"/>
<children>
<command title="Next Unread Story" input="n" id="ofa-dG-qfi">
<command title="Next Unread Story" input="u" id="ofa-dG-qfi">
<keyModifierFlags key="modifierFlags" command="YES"/>
<connections>
<action selector="nextUnreadStory:" destination="J28-e1-gcC" id="us7-1R-z9P"/>

View file

@ -426,16 +426,6 @@
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Follow system appearance</string>
<key>Key</key>
<string>theme_follow_system</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
@ -469,6 +459,7 @@
<string>Current theme</string>
<key>Titles</key>
<array>
<string>Auto</string>
<string>Light</string>
<string>Sepia</string>
<string>Medium</string>
@ -478,6 +469,7 @@
<string>light</string>
<key>Values</key>
<array>
<string>auto</string>
<string>light</string>
<string>sepia</string>
<string>medium</string>

View file

@ -454,16 +454,6 @@
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Follow system appearance</string>
<key>Key</key>
<string>theme_follow_system</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
@ -497,6 +487,7 @@
<string>Current theme</string>
<key>Titles</key>
<array>
<string>Auto</string>
<string>Light</string>
<string>Sepia</string>
<string>Medium</string>
@ -506,6 +497,7 @@
<string>light</string>
<key>Values</key>
<array>
<string>auto</string>
<string>light</string>
<string>sepia</string>
<string>medium</string>

View file

@ -72,46 +72,6 @@
<key>Key</key>
<string>story_font_size</string>
</dict>
<dict>
<key>Title</key>
<string>Theme</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Follow system appearance</string>
<key>Key</key>
<string>theme_follow_system</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Current theme</string>
<key>Titles</key>
<array>
<string>Light</string>
<string>Sepia</string>
<string>Medium</string>
<string>Dark</string>
</array>
<key>DefaultValue</key>
<string>light</string>
<key>Values</key>
<array>
<string>light</string>
<string>sepia</string>
<string>medium</string>
<string>dark</string>
</array>
<key>Key</key>
<string>theme_style</string>
</dict>
<dict>
<key>Title</key>
<string>App badge</string>