diff --git a/.gitignore b/.gitignore index 3fb9b7906e..368862e7fd 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ playground.xcworkspace node_modules Example/Pods Example/compile_commands.json +Example/Emission/Configuration.h \ No newline at end of file diff --git a/Example/Emission.xcodeproj/project.pbxproj b/Example/Emission.xcodeproj/project.pbxproj index ab161c6ff6..4b22d428de 100644 --- a/Example/Emission.xcodeproj/project.pbxproj +++ b/Example/Emission.xcodeproj/project.pbxproj @@ -55,6 +55,7 @@ 510E94FC1CCA828900BDF098 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 510E95131CCEB84F00BDF098 /* TestHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestHelper.m; sourceTree = ""; }; 510E95151CCEC22C00BDF098 /* TestHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestHelper.h; sourceTree = ""; }; + 51E682F51D2DAE24008BC152 /* Configuration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Configuration.h; sourceTree = ""; }; 51F3E9A21CF3B8A4004A2013 /* RotationNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RotationNavigationController.h; sourceTree = ""; }; 51F3E9A31CF3B8A4004A2013 /* RotationNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RotationNavigationController.m; sourceTree = ""; }; 77CEB1618D840E2C430A8D7A /* libPods-Emission.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Emission.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -98,6 +99,7 @@ isa = PBXGroup; children = ( 510E94FB1CCA828900BDF098 /* LaunchScreen.xib */, + 51E682F51D2DAE24008BC152 /* Configuration.h */, 510DCB131CCA69EC0075E8CB /* AppDelegate.h */, 510DCB141CCA69EC0075E8CB /* AppDelegate.m */, 510DCB1C1CCA69EC0075E8CB /* Assets.xcassets */, diff --git a/Example/Emission/AppDelegate.m b/Example/Emission/AppDelegate.m index 37833a133e..4fb60cbacd 100644 --- a/Example/Emission/AppDelegate.m +++ b/Example/Emission/AppDelegate.m @@ -1,6 +1,8 @@ #import "AppDelegate.h" #import "RotationNavigationController.h" +#import "Configuration.h" + #import #import #import @@ -54,11 +56,11 @@ - (void)setupEmission; AREmission *emission = nil; #ifdef ENABLE_DEV_MODE NSURL *packagerURL = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"]; - emission = [[AREmission alloc] initWithPackagerURL:packagerURL]; - [AREmission setSharedInstance:emission]; + emission = [[AREmission alloc] initWithAuthenticationToken:OAUTH_TOKEN packagerURL:packagerURL]; #else - emission = [AREmission sharedInstance]; + emission = [[AREmission alloc] initWithAuthenticationToken:OAUTH_TOKEN]; #endif + [AREmission setSharedInstance:emission]; emission.APIModule.artistFollowStatusProvider = ^(NSString *artistID, RCTResponseSenderBlock block) { NSNumber *following = @(randomBOOL()); diff --git a/Example/Emission/Configuration.h.sample b/Example/Emission/Configuration.h.sample new file mode 100644 index 0000000000..ac2800a587 --- /dev/null +++ b/Example/Emission/Configuration.h.sample @@ -0,0 +1,8 @@ +// As per the Artsy API docs at https://developers.artsy.net/docs/authentication, generate a OAuth token for your user +// account with the following command: +// +// $ curl -X POST "https://api.artsy.net/oauth2/access_token?client_id=e750db60ac506978fc70&client_secret=3a33d2085cbd1176153f99781bbce7c6&grant_type=credentials&scope=offline_access&email=...&password=..." +// +// (The client ID & secret are of Eigen OSS: https://github.com/artsy/eigen/blob/0e193d1b/Makefile#L36-L37) + +#define OAUTH_TOKEN @"token goes here" \ No newline at end of file diff --git a/Pod/Classes/Core/AREmission.h b/Pod/Classes/Core/AREmission.h index 756c4ec6a0..de73bc88c5 100644 --- a/Pod/Classes/Core/AREmission.h +++ b/Pod/Classes/Core/AREmission.h @@ -14,7 +14,10 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)sharedInstance; + (void)setSharedInstance:(AREmission *)instance; -- (instancetype)initWithPackagerURL:(nullable NSURL *)packagerURL NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithAuthenticationToken:(NSString *)authenticationToken; +- (instancetype)initWithAuthenticationToken:(NSString *)authenticationToken packagerURL:(nullable NSURL *)packagerURL NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; @end diff --git a/Pod/Classes/Core/AREmission.m b/Pod/Classes/Core/AREmission.m index 124aa915e2..655b620ca3 100644 --- a/Pod/Classes/Core/AREmission.m +++ b/Pod/Classes/Core/AREmission.m @@ -4,6 +4,28 @@ #import "ARTemporaryAPIModule.h" #import +#import + + +@interface AREmissionConfiguration : NSObject +@property (nonatomic, strong, readwrite) NSString *authenticationToken; +@end + +@implementation AREmissionConfiguration + +RCT_EXPORT_MODULE(Emission); + +- (NSDictionary *)constantsToExport +{ + return @{ @"authenticationToken": self.authenticationToken }; +} + +@end + + +@interface AREmission () +@property (nonatomic, strong, readwrite) AREmissionConfiguration *configurationModule; +@end @implementation AREmission @@ -16,29 +38,29 @@ + (void)setSharedInstance:(AREmission *)instance; + (instancetype)sharedInstance; { - if (_sharedInstance == nil) { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - _sharedInstance = [self new]; - }); - } + NSParameterAssert(_sharedInstance); return _sharedInstance; } -- (instancetype)init; +- (instancetype)initWithAuthenticationToken:(NSString *)authenticationToken; { - return [self initWithPackagerURL:nil]; + return [self initWithAuthenticationToken:authenticationToken packagerURL:nil]; } -- (instancetype)initWithPackagerURL:(NSURL *)packagerURL; +- (instancetype)initWithAuthenticationToken:(NSString *)authenticationToken packagerURL:(NSURL *)packagerURL; { if ((self = [super init])) { _eventsModule = [AREventsModule new]; _switchBoardModule = [ARSwitchBoardModule new]; _APIModule = [ARTemporaryAPIModule new]; + + _configurationModule = [AREmissionConfiguration new]; + _configurationModule.authenticationToken = authenticationToken; + + NSArray *modules = @[_APIModule, _configurationModule, _eventsModule, _switchBoardModule]; _bridge = [[RCTBridge alloc] initWithBundleURL:(packagerURL ?: self.releaseBundleURL) - moduleProvider:^{ return @[_eventsModule, _switchBoardModule, _APIModule]; } + moduleProvider:^{ return modules; } launchOptions:nil]; } return self; diff --git a/README.md b/README.md index b170fb43ca..e16ed402cd 100644 --- a/README.md +++ b/README.md @@ -13,20 +13,23 @@ * `$ brew link pcre` * `$ brew install watchman --HEAD` 3. Install NPM modules: `$ npm install` -4. Install Pods: `cd Example && pod install` +4. Install Pods: `$ cd Example && pod install` +5. Configure secrets: + * Copy configuration file: `$ cd Example/Emission && cp Configuration.h.sample Configuration.h` + * Edit the configuration file as per the instructions inside. ### Development 1. Run `$ npm start` from the top directory, which will: - - Clean the example app’s Xcode build dir. - - Start the example app’s React Native packager. + * Clean the example app’s Xcode build dir. + * Start the example app’s React Native packager. 2. Now from Xcode you can run the app in `Example/Emission.xcworkspace`. 3. We vendor some data from other repositories that you will sometimes need to update. You can either update all of them with `$ npm run sync-externals` or individually: - - The GraphQL schema of metaphysics that Relay uses to generate queries from: `$ npm run sync-schema` - - The colors defined in Artsy’s style-guide: `$ npm run sync-colors` + * The GraphQL schema of metaphysics that Relay uses to generate queries from: `$ npm run sync-schema` + * The colors defined in Artsy’s style-guide: `$ npm run sync-colors` ### Using Relay diff --git a/lib/relay/config.js b/lib/relay/config.js index 7f0feb601b..0ac9347575 100644 --- a/lib/relay/config.js +++ b/lib/relay/config.js @@ -2,6 +2,8 @@ 'use strict'; import Relay from 'react-relay'; +import { NativeModules } from 'react-native'; +const { Emission } = NativeModules; // FIXME: Currently staging is pretty much useless for our purposes, as it doesn’t include partner data and thus the // shows tab of the artist view has nothing to display. @@ -18,10 +20,11 @@ let metaphysicsURL; export { metaphysicsURL }; Relay.injectNetworkLayer( - new Relay.DefaultNetworkLayer(metaphysicsURL) - // headers: { - // Authorization: 'Basic SECRET' - // }) + new Relay.DefaultNetworkLayer(metaphysicsURL, { + headers: { + 'X-ACCESS-TOKEN': Emission.authenticationToken, + } + }) ); // Disable the native polyfill during development, which will make network requests show-up in the Chrome dev-tools.