Dynamic color implementation (#76)
This commit is contained in:
Родитель
facaafc73d
Коммит
13e0d9db28
|
@ -4,6 +4,11 @@
|
|||
//
|
||||
|
||||
@import UIKit;
|
||||
#ifdef SWIFT_PACKAGE
|
||||
#import "DMTraitCollection.h"
|
||||
#else
|
||||
#import <FluentDarkModeKit/DMTraitCollection.h>
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
@ -14,6 +19,7 @@ NS_SWIFT_NAME(DynamicColor)
|
|||
@property (nonatomic, readonly) UIColor *darkColor;
|
||||
|
||||
- (instancetype)initWithLightColor:(UIColor *)lightColor darkColor:(UIColor *)darkColor;
|
||||
- (instancetype)initWithDynamicProvider:(UIColor * (^)(DMTraitCollection *traitCollection))dynamicProvider;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -4,12 +4,11 @@
|
|||
//
|
||||
|
||||
#import "DMDynamicColor.h"
|
||||
#import "DMTraitCollection.h"
|
||||
#import "DMNamespace.h"
|
||||
|
||||
@interface DMDynamicColorProxy : NSProxy <NSCopying>
|
||||
|
||||
@property (nonatomic, strong) UIColor *lightColor;
|
||||
@property (nonatomic, strong) UIColor *darkColor;
|
||||
@property (nonatomic, strong) UIColor *(^dynamicProvider)(DMTraitCollection *);
|
||||
|
||||
@property (nonatomic, readonly) UIColor *resolvedColor;
|
||||
|
||||
|
@ -19,25 +18,48 @@
|
|||
|
||||
// TODO: We need a more generic initializer.
|
||||
- (instancetype)initWithLightColor:(UIColor *)lightColor darkColor:(UIColor *)darkColor {
|
||||
self.lightColor = lightColor;
|
||||
self.darkColor = darkColor;
|
||||
return [self initWithDynamicProvider:^(DMTraitCollection *traitCollection){
|
||||
return traitCollection.userInterfaceStyle == DMUserInterfaceStyleDark ? darkColor : lightColor;
|
||||
}];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDynamicProvider:(UIColor * (^)(DMTraitCollection *traitCollection))dynamicProvider {
|
||||
self.dynamicProvider = dynamicProvider;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UIColor *)resolvedColor {
|
||||
if (DMTraitCollection.currentTraitCollection.userInterfaceStyle == DMUserInterfaceStyleDark) {
|
||||
return self.darkColor;
|
||||
} else {
|
||||
return self.lightColor;
|
||||
}
|
||||
return [self resolvedColorWithTraitCollection:DMTraitCollection.currentTraitCollection];
|
||||
}
|
||||
|
||||
- (UIColor *)resolvedColorWithTraitCollection:(DMTraitCollection *)traitCollection {
|
||||
return self.dynamicProvider(traitCollection);
|
||||
}
|
||||
|
||||
// MARK: UIColor
|
||||
|
||||
- (UIColor *)colorWithAlphaComponent:(CGFloat)alpha {
|
||||
return [[DMDynamicColor alloc] initWithLightColor:[self.lightColor colorWithAlphaComponent:alpha]
|
||||
darkColor:[self.darkColor colorWithAlphaComponent:alpha]];
|
||||
return [[DMDynamicColor alloc] initWithDynamicProvider:^UIColor *(DMTraitCollection *traitCollection) {
|
||||
return [self.dynamicProvider(traitCollection) colorWithAlphaComponent:alpha];
|
||||
}];
|
||||
}
|
||||
|
||||
// MARK: Methods that do not need forwarding
|
||||
|
||||
- (UIColor *)lightColor {
|
||||
return [self resolvedColorWithTraitCollection:[DMTraitCollection traitCollectionWithUserInterfaceStyle:DMUserInterfaceStyleLight]];
|
||||
}
|
||||
|
||||
- (UIColor *)darkColor {
|
||||
return [self resolvedColorWithTraitCollection:[DMTraitCollection traitCollectionWithUserInterfaceStyle:DMUserInterfaceStyleDark]];
|
||||
}
|
||||
|
||||
- (UIColor *)dm_resolvedColorWithTraitCollection:(DMTraitCollection *)traitCollection {
|
||||
return [self resolvedColorWithTraitCollection:traitCollection];;
|
||||
}
|
||||
|
||||
- (UIColor *)dm_namespace:(DMNamespace)namespace resolvedColorWithTraitCollection:(DMTraitCollection *)traitCollection {
|
||||
return [self dm_resolvedColorWithTraitCollection:traitCollection];
|
||||
}
|
||||
|
||||
// MARK: NSProxy
|
||||
|
@ -68,7 +90,7 @@
|
|||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
return [[DMDynamicColorProxy alloc] initWithLightColor:self.lightColor darkColor:self.darkColor];
|
||||
return [[DMDynamicColorProxy alloc] initWithDynamicProvider:[self.dynamicProvider copy]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -81,6 +103,10 @@
|
|||
return (DMDynamicColor *)[[DMDynamicColorProxy alloc] initWithLightColor:lightColor darkColor:darkColor];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDynamicProvider:(UIColor * _Nonnull (^)(DMTraitCollection * _Nonnull))dynamicProvider {
|
||||
return (DMDynamicColor *)[[DMDynamicColorProxy alloc] initWithDynamicProvider:dynamicProvider];
|
||||
}
|
||||
|
||||
- (UIColor *)lightColor {
|
||||
NSAssert(NO, @"This should never be called");
|
||||
return nil;
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
#ifdef SWIFT_PACKAGE
|
||||
#import "DMNamespace.h"
|
||||
#import "DMTraitCollection.h"
|
||||
#else
|
||||
#import <FluentDarkModeKit/DMNamespace.h>
|
||||
#import <FluentDarkModeKit/DMTraitCollection.h>
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
@ -16,11 +18,18 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
+ (UIColor *)dm_colorWithLightColor:(UIColor *)lightColor darkColor:(UIColor *)darkColor
|
||||
NS_SWIFT_UNAVAILABLE("Use init(_:light:dark:) instead.");
|
||||
+ (UIColor *)dm_colorWithDynamicProvider:(UIColor * (^)(DMTraitCollection *traitCollection))dynamicProvider
|
||||
NS_SWIFT_UNAVAILABLE("Use init(_:dynamicProvider:) instead.");
|
||||
- (UIColor *)dm_resolvedColorWithTraitCollection:(DMTraitCollection *)traitCollection
|
||||
NS_SWIFT_UNAVAILABLE("Use resolvedColor(_:with:) instead.");
|
||||
|
||||
#if __swift__
|
||||
+ (UIColor *)dm_namespace:(DMNamespace)namespace
|
||||
colorWithLightColor:(UIColor *)lightColor
|
||||
darkColor:(UIColor *)darkColor NS_SWIFT_NAME(init(_:light:dark:));
|
||||
+ (UIColor *)dm_namespace:(DMNamespace)namespace
|
||||
dynamicProvider:(UIColor *(^)(DMTraitCollection *traitCollection))dynamicProvider NS_SWIFT_NAME(init(_:dynamicProvider:));
|
||||
- (UIColor *)dm_namespace:(DMNamespace)namespace resolvedColorWithTraitCollection:(DMTraitCollection *)traitCollection NS_SWIFT_NAME(resolvedColor(_:with:));
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
|
|
@ -18,4 +18,23 @@
|
|||
return [UIColor dm_colorWithLightColor:lightColor darkColor:darkColor];
|
||||
}
|
||||
|
||||
+ (UIColor *)dm_colorWithDynamicProvider:(UIColor *(^)(DMTraitCollection *))dynamicProvider {
|
||||
return (UIColor *)[[DMDynamicColor alloc] initWithDynamicProvider:dynamicProvider];
|
||||
}
|
||||
|
||||
+ (UIColor *)dm_namespace:(DMNamespace)namespace dynamicProvider:(UIColor *(^)(DMTraitCollection *))dynamicProvider {
|
||||
return [self dm_colorWithDynamicProvider:dynamicProvider];
|
||||
}
|
||||
|
||||
- (UIColor *)dm_resolvedColorWithTraitCollection:(DMTraitCollection *)traitCollection {
|
||||
// Here we just need to take care of UIColor that is not DMDynamicColor
|
||||
// since DMDynamicColor methods are all forwarded, simply return self
|
||||
// before we need to bridge iOS 13's color mechanism
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UIColor *)dm_namespace:(DMNamespace)namespace resolvedColorWithTraitCollection:(DMTraitCollection *)traitCollection {
|
||||
return [self dm_resolvedColorWithTraitCollection:traitCollection];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -29,6 +29,22 @@ final class DarkModeKitTests: XCTestCase {
|
|||
_ = UIImage(.dm, light: lightImage, dark: darkImage)
|
||||
}
|
||||
|
||||
func testDynamicColor() {
|
||||
let color = UIColor(.dm) {
|
||||
$0.userInterfaceStyle == .dark ? UIColor.black : UIColor.white
|
||||
}
|
||||
|
||||
DMTraitCollection.current = DMTraitCollection(userInterfaceStyle: .light)
|
||||
XCTAssertEqual(color.rgba, UIColor.white.rgba)
|
||||
|
||||
DMTraitCollection.current = DMTraitCollection(userInterfaceStyle: .dark)
|
||||
XCTAssertEqual(color.rgba, UIColor.black.rgba)
|
||||
|
||||
// Test color fetched from specific trait collections
|
||||
XCTAssertEqual(color.resolvedColor(.dm, with: DMTraitCollection(userInterfaceStyle: .dark)).rgba, UIColor.black.rgba)
|
||||
XCTAssertEqual(color.resolvedColor(.dm, with: DMTraitCollection(userInterfaceStyle: .light)).rgba, UIColor.white.rgba)
|
||||
}
|
||||
|
||||
func testColorPropertySetters() {
|
||||
let color = UIColor(.dm, light: .white, dark: .black)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче