Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a centralized configuration API #747

Merged
merged 29 commits into from
Mar 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2c7e050
Update the dangerfile
Jan 15, 2018
1de26b4
Make a trivial change to test new dangerfile
Jan 15, 2018
13fccb0
Try out the new value with another trivial change
Jan 15, 2018
c4b4d09
Add a configuration API to make a unified place for pulling config fr…
Jan 15, 2018
6968445
Specify properties for delegate
Jan 15, 2018
348e5c2
Finish removing text experiment global enable
Jan 15, 2018
f7bd45a
Generate the config file
Jan 15, 2018
2233852
Clean up configuration to fix tests
Jan 15, 2018
1044620
Work on making it serializable
Jan 15, 2018
d02b36f
Merge branch 'master' into AHExperiments
Adlai-Holler Jan 15, 2018
75922a3
Finish it up
Jan 16, 2018
9801560
Fix example code
Jan 16, 2018
99b3a70
Update sample project
Jan 16, 2018
241eec9
Merge branch 'master' into AHExperiments
Adlai-Holler Jan 30, 2018
e4f6aac
Merge branch 'master' into AHExperiments
appleguy Feb 26, 2018
042d338
Clean up a few things
Feb 28, 2018
50383b5
Merge branch 'master' into AHExperiments
Mar 24, 2018
a548185
Align with new project order
Mar 24, 2018
9ab0562
Make it faster and update license header
Mar 24, 2018
0edeb2f
Add an option to specify your config at compile time
Mar 24, 2018
9938217
Update another license header
Mar 24, 2018
4363c6c
Add a version field, and bring interface state coalescing into config…
Mar 24, 2018
1d4ba50
Update CA queue code
Mar 25, 2018
5c5e93d
Update CATransactionQueue tests
Mar 25, 2018
8cb7b8e
Turn transaction queue on by default (for now, see comment)
Mar 25, 2018
681bebd
Update the tests
Mar 25, 2018
16fab3f
Update the tests AGAIN
Mar 25, 2018
331d70d
Merge branch 'master' into AHExperiments
Adlai-Holler Mar 25, 2018
73efad5
Remove unused ordered set
Mar 25, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions AsyncDisplayKit.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [ASCollectionNode] Added support for interactive item movement. [Adlai Holler](https://github.com/Adlai-Holler)
- Added an experimental "no-copy" rendering API. See ASGraphicsContext.h for info. [Adlai Holler](https://github.com/Adlai-Holler)
- Dropped support for iOS 8. [Adlai Holler](https://github.com/Adlai-Holler)
- Added a configuration API – a unified place to turn on/off experimental Texture features. See `ASConfiguration.h` for info. [Adlai Holler](https://github.com/Adlai-Holler)
- **Breaking** Changes to ASNetworkImageNode: [Adlai Holler](https://github.com/Adlai-Holler)
- Modified `ASImageDownloaderCompletion` to add an optional `id userInfo` field. Your custom downloader can pass `nil`.
- Modified the last argument to `-[ASNetworkImageNodeDelegate imageNode:didLoadImage:info:]` method from a struct to an object of new class `ASNetworkImageLoadInfo` which includes other metadata about the load operation.
Expand Down
23 changes: 23 additions & 0 deletions Schemas/configuration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"id": "configuration.json",
"title": "configuration",
"description" : "Schema definition of a Texture Configuration",
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"version" : {
"type" : "number"
},
"experimental_features": {
"type": "array",
"items": {
"type": "string",
"enum": [
"exp_graphics_contexts",
"exp_text_node",
"exp_interface_state_coalesce"
]
}
}
}
}
62 changes: 62 additions & 0 deletions Source/ASConfiguration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// ASConfiguration.h
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//

#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASBaseDefines.h>
#import <AsyncDisplayKit/ASExperimentalFeatures.h>

@protocol ASConfigurationDelegate;

NS_ASSUME_NONNULL_BEGIN

static NSInteger const ASConfigurationSchemaCurrentVersion = 1;

AS_SUBCLASSING_RESTRICTED
@interface ASConfiguration : NSObject <NSCopying>

/**
* Initialize this configuration with the provided dictionary,
* or nil to create an empty configuration.
*
* The schema is located in `schemas/configuration.json`.
*/
- (instancetype)initWithDictionary:(nullable NSDictionary *)dictionary;

/**
* The delegate for configuration-related events.
* Delegate methods are called from a serial queue.
*/
@property (nonatomic, strong, nullable) id<ASConfigurationDelegate> delegate;

/**
* The experimental features to enable in Texture.
* See ASExperimentalFeatures for functions to convert to/from a string array.
*/
@property (nonatomic) ASExperimentalFeatures experimentalFeatures;

@end

/**
* Implement this method in a category to make your
* configuration available to Texture. It will be read
* only once and copied.
*
* NOTE: To specify your configuration at compile-time, you can
* define AS_FIXED_CONFIG_JSON as a C-string of JSON. This method
* will then be implemented to parse that string and generate
* a configuration.
*/
@interface ASConfiguration (UserProvided)
+ (ASConfiguration *)textureConfiguration NS_RETURNS_RETAINED;
@end

NS_ASSUME_NONNULL_END
67 changes: 67 additions & 0 deletions Source/ASConfiguration.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// ASConfiguration.m
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//

#import <AsyncDisplayKit/ASConfiguration.h>
#import <AsyncDisplayKit/ASConfigurationInternal.h>

/// Not too performance-sensitive here.

/// Get this from C++, without the extra exception handling.
#define autotype __auto_type

@implementation ASConfiguration

- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
if (self = [super init]) {
autotype featureStrings = ASDynamicCast(dictionary[@"experimental_features"], NSArray);
autotype version = ASDynamicCast(dictionary[@"version"], NSNumber).integerValue;
if (version != ASConfigurationSchemaCurrentVersion) {
NSLog(@"Texture warning: configuration schema is old version (%zd vs %zd)", version, ASConfigurationSchemaCurrentVersion);
}
self.experimentalFeatures = ASExperimentalFeaturesFromArray(featureStrings);
}
return self;
}

- (id)copyWithZone:(NSZone *)zone
{
ASConfiguration *config = [[ASConfiguration alloc] initWithDictionary:nil];
config.experimentalFeatures = self.experimentalFeatures;
config.delegate = self.delegate;
return config;
}

@end

//#define AS_FIXED_CONFIG_JSON "{ \"version\" : 1, \"experimental_features\": [ \"exp_text_node\" ] }"

#ifdef AS_FIXED_CONFIG_JSON

@implementation ASConfiguration (UserProvided)

+ (ASConfiguration *)textureConfiguration NS_RETURNS_RETAINED
{
NSData *data = [@AS_FIXED_CONFIG_JSON dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary *d = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (!d) {
NSAssert(NO, @"Error parsing fixed config string '%s': %@", AS_FIXED_CONFIG_JSON, error);
return nil;
} else {
return [[ASConfiguration alloc] initWithDictionary:d];
}
}

@end

#endif // AS_FIXED_CONFIG_JSON
31 changes: 31 additions & 0 deletions Source/ASConfigurationDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// ASConfigurationDelegate.h
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//

#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASConfiguration.h>

NS_ASSUME_NONNULL_BEGIN

/**
* Used to communicate configuration-related events to the client.
*/
@protocol ASConfigurationDelegate <NSObject>

/**
* Texture performed its first behavior related to the feature(s).
* This can be useful for tracking the impact of the behavior (A/B testing).
*/
- (void)textureDidActivateExperimentalFeatures:(ASExperimentalFeatures)features;

@end

NS_ASSUME_NONNULL_END
6 changes: 3 additions & 3 deletions Source/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2915,7 +2915,7 @@ - (void)didExitHierarchy
}
};

if ([[ASCATransactionQueue sharedQueue] disabled]) {
if (!ASCATransactionQueue.sharedQueue.enabled) {
dispatch_async(dispatch_get_main_queue(), exitVisibleInterfaceState);
} else {
exitVisibleInterfaceState();
Expand Down Expand Up @@ -2980,7 +2980,7 @@ - (ASInterfaceState)interfaceState

- (void)setInterfaceState:(ASInterfaceState)newState
{
if ([[ASCATransactionQueue sharedQueue] disabled]) {
if (!ASCATransactionQueue.sharedQueue.enabled) {
[self applyPendingInterfaceState:newState];
} else {
ASDN::MutexLocker l(__instanceLock__);
Expand Down Expand Up @@ -3012,7 +3012,7 @@ - (void)applyPendingInterfaceState:(ASInterfaceState)newPendingState
ASDN::MutexLocker l(__instanceLock__);
// newPendingState will not be used when ASCATransactionQueue is enabled
// and use _pendingInterfaceState instead for interfaceState update.
if ([[ASCATransactionQueue sharedQueue] disabled]) {
if (!ASCATransactionQueue.sharedQueue.enabled) {
_pendingInterfaceState = newPendingState;
}
oldState = _interfaceState;
Expand Down
36 changes: 36 additions & 0 deletions Source/ASExperimentalFeatures.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// ASExperimentalFeatures.h
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//

#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASBaseDefines.h>

NS_ASSUME_NONNULL_BEGIN
ASDISPLAYNODE_EXTERN_C_BEGIN

/**
* A bit mask of features.
*/
typedef NS_OPTIONS(NSUInteger, ASExperimentalFeatures) {
ASExperimentalGraphicsContexts = 1 << 0, // exp_graphics_contexts
ASExperimentalTextNode = 1 << 1, // exp_text_node
ASExperimentalInterfaceStateCoalescing = 1 << 2, // exp_interface_state_coalesce
ASExperimentalFeatureAll = 0xFFFFFFFF
};

/// Convert flags -> name array.
NSArray<NSString *> *ASExperimentalFeaturesGetNames(ASExperimentalFeatures flags);

/// Convert name array -> flags.
ASExperimentalFeatures ASExperimentalFeaturesFromArray(NSArray<NSString *> *array);

ASDISPLAYNODE_EXTERN_C_END
NS_ASSUME_NONNULL_END
45 changes: 45 additions & 0 deletions Source/ASExperimentalFeatures.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// ASExperimentalFeatures.m
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//

#import <AsyncDisplayKit/ASExperimentalFeatures.h>

NSArray<NSString *> *ASExperimentalFeaturesGetNames(ASExperimentalFeatures flags)
{
NSArray *allNames = ASCreateOnce((@[@"exp_graphics_contexts",
@"exp_text_node",
@"exp_interface_state_coalesce"]));

if (flags == ASExperimentalFeatureAll) {
return allNames;
}

// Go through all names, testing each bit.
NSUInteger i = 0;
return ASArrayByFlatMapping(allNames, NSString *name, ({
(flags & (1 << i++)) ? name : nil;
}));
}

// O(N^2) but with counts this small, it's probably faster
// than hashing the strings.
ASExperimentalFeatures ASExperimentalFeaturesFromArray(NSArray<NSString *> *array)
{
NSArray *allNames = ASExperimentalFeaturesGetNames(ASExperimentalFeatureAll);
ASExperimentalFeatures result = 0;
for (NSString *str in array) {
NSUInteger i = [allNames indexOfObject:str];
if (i != NSNotFound) {
result |= (1 << i);
}
}
return result;
}
10 changes: 7 additions & 3 deletions Source/ASNetworkImageLoadInfo.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
//
// ASNetworkImageLoadInfo.h
// AsyncDisplayKit
// Texture
//
// Created by Adlai on 1/30/18.
// Copyright © 2018 Facebook. All rights reserved.
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//

#import <Foundation/Foundation.h>
Expand Down
10 changes: 7 additions & 3 deletions Source/ASNetworkImageLoadInfo.m
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
//
// ASNetworkImageLoadInfo.m
// AsyncDisplayKit
// Texture
//
// Created by Adlai on 1/30/18.
// Copyright © 2018 Facebook. All rights reserved.
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//

#import <AsyncDisplayKit/ASNetworkImageLoadInfo.h>
Expand Down
9 changes: 3 additions & 6 deletions Source/ASRunLoopQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ AS_SUBCLASSING_RESTRICTED
@interface ASCATransactionQueue : ASAbstractRunLoopQueue

@property (atomic, readonly) BOOL isEmpty;
@property (atomic, readonly) BOOL disabled;

@property (atomic, readonly, getter=isEnabled) BOOL enabled;

/**
* The queue to run on main run loop before CATransaction commit.
*
Expand All @@ -72,11 +74,6 @@ AS_SUBCLASSING_RESTRICTED

- (void)enqueue:(id<ASCATransactionQueueObserving>)object;

/**
* @abstract Apply a node's interfaceState immediately rather than adding to the queue.
*/
- (void)disable;

@end


Expand Down
Loading