├── README.md └── TwentyThreeAndMe ├── Assets ├── congratulations_chromosome_blue.imageset │ ├── Contents.json │ ├── congratulations_chromosome_blue.png │ ├── congratulations_chromosome_blue@2x.png │ └── congratulations_chromosome_blue@3x.png ├── failure_chromosome_purple.imageset │ ├── Contents.json │ ├── failure_chromosome_purple.png │ ├── failure_chromosome_purple@2x.png │ └── failure_chromosome_purple@3x.png ├── intro_23andMe_logo.imageset │ ├── Contents.json │ ├── intro_23andMe_logo.png │ ├── intro_23andMe_logo@2x.png │ └── intro_23andMe_logo@3x.png ├── intro_chromosome_green.imageset │ ├── Contents.json │ ├── intro_chromosome_green.png │ ├── intro_chromosome_green@2x.png │ └── intro_chromosome_green@3x.png ├── intro_chromosome_green_striped.imageset │ ├── Contents.json │ ├── intro_chromosome_green_striped.png │ ├── intro_chromosome_green_striped@2x.png │ └── intro_chromosome_green_striped@3x.png └── intro_chromosome_pink.imageset │ ├── Contents.json │ ├── intro_chromosome_pink.png │ ├── intro_chromosome_pink@2x.png │ └── intro_chromosome_pink@3x.png ├── Common ├── ORKOrderedTask+TwentyThreeAndMe.h ├── ORKOrderedTask+TwentyThreeAndMe.m ├── ORKResult+TwentyThreeAndMe.h ├── ORKResult+TwentyThreeAndMe.m └── ORKTwentyThreeAndMeDefines.h ├── OtherEdits.txt ├── Steps ├── Complete │ ├── ORKTwentyThreeAndMeCompleteStep.h │ ├── ORKTwentyThreeAndMeCompleteStep.m │ ├── ORKTwentyThreeAndMeCompleteViewController.h │ ├── ORKTwentyThreeAndMeCompleteViewController.m │ ├── ORKTwentyThreeAndMeFailureViewController.h │ ├── ORKTwentyThreeAndMeFailureViewController.m │ ├── ORKTwentyThreeAndMeSuccessExistingViewController.h │ ├── ORKTwentyThreeAndMeSuccessExistingViewController.m │ ├── ORKTwentyThreeAndMeSuccessNewViewController.h │ └── ORKTwentyThreeAndMeSuccessNewViewController.m ├── Connect │ ├── ORKTwentyThreeAndMeConnectStep.h │ ├── ORKTwentyThreeAndMeConnectStep.m │ ├── ORKTwentyThreeAndMeConnectStepViewController.h │ └── ORKTwentyThreeAndMeConnectStepViewController.m └── Intro │ ├── ORKTwentyThreeAndMeIntroPage1ViewController.h │ ├── ORKTwentyThreeAndMeIntroPage1ViewController.m │ ├── ORKTwentyThreeAndMeIntroPage2ViewController.h │ ├── ORKTwentyThreeAndMeIntroPage2ViewController.m │ ├── ORKTwentyThreeAndMeIntroPage3ViewController.h │ ├── ORKTwentyThreeAndMeIntroPage3ViewController.m │ ├── ORKTwentyThreeAndMeIntroStep.h │ ├── ORKTwentyThreeAndMeIntroStep.m │ ├── ORKTwentyThreeAndMeIntroViewController.h │ └── ORKTwentyThreeAndMeIntroViewController.m ├── Tasks ├── ORKTwentyThreeAndMeConnectTaskViewController.h └── ORKTwentyThreeAndMeConnectTaskViewController.m └── UIHelpers ├── UIButton+T23.h ├── UIButton+T23.m ├── UILabel+T23.h └── UILabel+T23.m /README.md: -------------------------------------------------------------------------------- 1 | 23andMe logo 2 | 3 | # 23andMe ResearchKit Module 4 | Bring genetic data to your ResearchKit-enabled research app with 23andMe. 5 | 6 | **Interested? Contact us at geneticsmodule@23andme.com** 7 | 8 | ## Introduction 9 | Seamlessly incorporate genetic data collection into your ResearchKit-enabled app. With 23andMe's ResearchKit module you can use 23andMe as a source for collecting genetic data from both existing 23andMe customers as well as other individuals who you'd like to sign up for 23andMe. 10 | 11 | 23andMe's ResearchKit module makes it easy to either: 12 | - Request that an existing 23andMe customers agree to share their genetic data with your app 13 | - Have a non-23andMe customer create a 23andMe account and profile, and agree to share their genetic data with your app, when available. 14 | 15 | ### Supported Configurations 16 | #### 23andMe Customer Types 17 | - Existing 23andMe customers only 18 | 19 | This configuration allows existing 23andMe customers to share their genotype data with your research study. 20 | - Existing and new 23andMe customers 21 | 22 | Note that this configuration requires that a researcher has a purchase agreement in place to sponsor the purchase of a 23andMe kit for participants the researcher has deemed eligible. 23 | 24 | #### Contribution of Data 25 | - Contributing genetic data required 26 | - Contributing genetic data optional 27 | 28 | #### Retreival of genetic data 29 | The module is designed to make it simple for you to gain permission to access a 23andMe customer's genetic data. While it will provide you with the credentials necessary to access a customer's data, you will need to use the 23andMe API to retreive any genetic inforamtion. **Unless you have a need for the information in your app, we recommend that you not download genomewide data directly to a participant's phone.** 30 | 31 | ## Getting Started 32 | ### Requirements 33 | - ResearchKit 1.3.0 (has not been tested against other versions) 34 | - iOS Base SDK 8.0+ 35 | 36 | ### Contact 23andMe for development environment access 37 | 23andMe has created a development environment for researchers looking to include the 23andMe module in their app. Send an email to geneticsmodule@23andme.com for more information on accessing the development environment. 38 | 39 | If your app will only accept data from existing 23andMe customers, then you may not need access to the development environment. You can create a development API account [here]. 40 | 41 | Note that development accounts are limited to 20 users. **You will need to request an API [upgrade] before you release your app.** 42 | 43 | ### Authenticating with the 23andMe API 44 | Once a user has gone through the 23andMe module, the app will return an authorization code that you can exchange for auth & refresh tokens using the 23andMe API. See the [documentation] for additional details. 45 | 46 | ### Retrieving genetic data via the API 47 | - See the [genomes] endpoint documentation for downloading genomewide data 48 | - See the [genotypes] endpoint documentation for retrieving data for selected SNPs 49 | 50 | ## Integrating the 23andMe Module 51 | ### 1. Add the ResearchKit framework to your app 52 | 53 | Follow the instructions posted at the [ResearchKit repo]. 54 | 55 | ### 2. Add the 23andMe module to your app's project 56 | 57 | Clone the 23andMe module: 58 | ```bash 59 | git clone https://github.com/23andMe/23andMeResearchKitModule.git 60 | ``` 61 | Copy the module inside your ResearchKit project. Copy the "TwentyThreeAndMe" into the ResearchKit project inside of XCode. 62 | 63 | ### 3. Update ResearchKit code 64 | 65 | See the "OtherEdits.txt" file for a summary of the required modifications. 66 | 67 | **Researchkit.h** 68 | Don't forget that when you add the following files to your project, they must have target membership set to "public" 69 | ```objc 70 | #import 71 | #import 72 | ``` 73 | 74 | **Researchkit.private** 75 | Don't forget that when you add the following files to your project, they must have target membership set to "private" 76 | ```objc 77 | #import 78 | #import 79 | ``` 80 | 81 | **Researchkit.strings - English** 82 | ```objc 83 | /* 23andMe connect task. */ 84 | "TWENTYTHREEANDME_DECLINE_PROMPT_DETAILS" = "Are you sure you want to decline adding your genetic data to %@? Declining may impact your eligibility for this study"; 85 | "TWENTYTHREEANDME_DECLINE_PROMPT_ACTION_DECLINE" = "Decline"; 86 | "TWENTYTHREEANDME_DECLINE_PROMPT_ACTION_CANCEL" = "Cancel"; 87 | 88 | "TWENTYTHREEANDME_INTRO_MAIN_SHARE" = "Add Genetic Data"; 89 | "TWENTYTHREEANDME_INTRO_MAIN_DECLINE" = "Decline"; 90 | 91 | "TWENTYTHREEANDME_INTRO_1_DESCRIPTION" = "%@ has selected 23andMe to collect genetic data for the %@ study"; 92 | 93 | "TWENTYTHREEANDME_INTRO_2_TITLE" = "About this study"; 94 | "TWENTYTHREEANDME_INTRO_2_ABOUT_REQUIRED" = "Contributing your genetic data is required for participation in the %@ study. You will need to authorize 23andMe to share that data with %@"; 95 | "TWENTYTHREEANDME_INTRO_2_ABOUT_OPTIONAL" = "In order to contribute your genetic data to the %@ study, you will need to authorize 23andMe to share that data with %@"; 96 | "TWENTYTHREEANDME_INTRO_2_ELIGIBILITY_HEADER" = "Eligibility"; 97 | "TWENTYTHREEANDME_INTRO_2_ELIGIBILITY_EXISTING" = "• Existing 23andMe users"; 98 | "TWENTYTHREEANDME_INTRO_2_ELIGIBILITY_NEW" = "• Individuals who agree to receive the 23andMe Personal Genome Service at no cost"; 99 | 100 | "TWENTYTHREEANDME_INTRO_3_TITLE" = "About 23andMe"; 101 | "TWENTYTHREEANDME_INTRO_3_MISSION" = "23andMe is a genetic service available directly to U.S. customers that includes reports that meet FDA standards for being scientifically and clinically valid. 23andMe helps people understand what’s in their DNA. The 23andMe Personal Genome Service includes more than 60 personalized genetic health, trait and ancestry reports."; 102 | "TWENTYTHREEANDME_INTRO_3_LEARN_MORE" = "Learn more about 23andMe"; 103 | "TWENTYTHREEANDME_INTRO_3_QUESTIONS" = "Questions?"; 104 | "TWENTYTHREEANDME_INTRO_3_CONTACT" = "Contact %@"; 105 | 106 | "TWENTYTHREEANDME_COMPLETE_TITLE" = "Congratulations"; 107 | "TWENTYTHREEANDME_COMPLETE_DONE_BUTTON" = "Done"; 108 | "TWENTYTHREEANDME_COMPLETE_EXISTING_DETAIL" = "Congratulations, you’ve successfully enrolled in %@. %@ is now authorized to access your genetic data."; 109 | "TWENTYTHREEANDME_COMPLETE_NEW_DETAIL" = "Congratulations, you’ve successfully enrolled in %@. %@ is now authorized to access your genetic data."; 110 | "TWENTYTHREEANDME_COMPLETE_NEW_NEXT_STEP" = "Next steps"; 111 | "TWENTYTHREEANDME_COMPLETE_NEW_NEXT_STEP_DETAIL" = "23andMe will mail you a saliva collection kit. Simply follow the instructions included with the kit, mail the sample back, and we will notify you when your reports are ready."; 112 | 113 | "TWENTYTHREEANDME_FAILURE_TITLE" = "Try again"; 114 | "TWENTYTHREEANDME_FAILURE_DESCRIPTION" = "Sorry, we weren’t able to enroll you in the genetic component of %@. Please try again, or contact %@ if you have any questions."; 115 | "TWENTYTHREEANDME_FAILURE_CONTACT" = "Contact %@"; 116 | "TWENTYTHREEANDME_FAILURE_TRY_AGAIN_BUTTON" = "Try again"; 117 | "TWENTYTHREEANDME_FAILURE_DECLINE_BUTTON" = "Decline"; 118 | ``` 119 | ### 4. Add image assets 120 | 121 | The 23andMe module includes a series of assets used to incorporate 23andMe's look and feel. In order to include those in your app, create a "TwentyThreeAndMe" folder inside of the "Artwork.xcassets" item in your project's copy of ResearchKit. Then, copy the contents of the /Assets folder into the folder you've just created. 122 | 123 | ### 5. Present the 23andMe Connect Task 124 | 125 | In the view controller where you want to present the connect to 23andMe task and receive a user's permission to access her data, include the ResearchKit libraries and set a delegate to receive the task's response: 126 | ```objc 127 | #import 128 | 129 | @interface UIViewController () 130 | ``` 131 | Create the 23andMe task's view controller with the following method: 132 | ```objc 133 | ORKTwentyThreeAndMeConnectTaskViewController *ttamTaskVC = 134 | [ORKTwentyThreeAndMeConnectTaskViewController twentyThreeAndMeTaskViewControllerWithIdentifier:@"connectWithTTAM" 135 | allowedUserMode:ORKTwentyThreeAndMeAllowedUserModeExistingAndNew 136 | studyDependency:ORKTwentyThreeAndMeStudyDependencyRequired 137 | authClientId:@"" 138 | authClientSecret:@"" 139 | authScopes:@"basic genomes" 140 | investigatorDisplayName:@"name" 141 | studyDisplayName:@"study_name" 142 | studyContactEmail:@"my_email@email.com" 143 | baseURLOverride:nil]; 144 | ``` 145 | 146 | #### Parameters: 147 | 148 | **allowedUserMode**: Either ```ORKTwentyThreeAndMeAllowedUserModeExistingAndNew``` or ```ORKTwentyThreeAndMeAllowedUserModeExistingOnly```. 149 | 150 | **studyDependency**: Either ```ORKTwentyThreeAndMeStudyDependencyRequired``` or ```ORKTwentyThreeAndMeStudyDependencyOptional```. 151 | 152 | **authClientId**: 23andMe API OAuth client ID 153 | 154 | **authClientSecret**: 23andMe API OAuth client secret 155 | 156 | **authScopes**: Space-seperated list of scopes to request from the 23andMe API. See the list of [scopes] for details on what scopes to request. 157 | 158 | **investigatorDisplayName**: User-facing investigator name. 159 | 160 | **studyDisplayName**: User-facing study name. 161 | 162 | **studyContactEmail**: User-facing contact email address. 163 | 164 | **baseURLOverride**: Either ```nil``` or a URL to override the default 23andMe API URL. Use this override URL to access the sandbox environment. For access to the sandbox environment, contact us at geneticsmodule@23andme.com 165 | 166 | #### Set the delegate and present the 23andMe view controller: 167 | ```objc 168 | ttamTaskVC.twentyThreeAndMeConnectDelegate = self; 169 | 170 | [self presentViewController:ttamTaskVC animated:NO completion:nil]; 171 | ``` 172 | ### 6. Implement the delegate method to receive a response 173 | 174 | ```objc 175 | - (void)twentyThreeAndMeConnectTaskViewController:(ORKTwentyThreeAndMeConnectTaskViewController *)twentyThreeAndMeConnectTaskViewController 176 | didFinishWithResults:(NSDictionary *)results 177 | error:(nullable NSError *)error 178 | ``` 179 | The ```results``` dictionary contains: 180 | 181 | **completionType**: If the user successfully auth'd (and, for new 23andMe users, created an account) this will be set to ```success```. Otherwise, this will be set to ```cancelled```. 182 | 183 | **authToken**: 23andMe Auth Token for the user's 23andMe profile. Only set if ```completionType == success```. 184 | 185 | **refreshToken**: 23andMe Refresh Token for the user's 23andMe profile. Only set if ```completionType == success```. 186 | 187 | On access and refresh tokens: 188 | >Access tokens expire after 1 day. If you need to access a user's data past that, you can request another token using the last ```refresh_token``` that you were issued. Using the refresh token means you don't have to send the user through the "Accept" screen all over again. Requesting a new token set will invalidate your old ```refresh_token```. Be sure to specify the full scope when requesting a new access token. 189 | 190 | #### 7. Use the 23andMe API to retrieve user data 191 | Once you've retrieved an access token, you can use the API to access the information that the user agreed to share with you as it is available. _Access tokens retrieved via the 23andMe ResearchKit module are only valid for individual profiles, so be sure to keep track of the profile ID that's associated with the token._ 192 | 193 | ## Questions? 194 | **Questions about 23andMe, the 23andMe API, or interested in setting up a project with us?** Contact us at geneticsmodule@23andme.com. 195 | 196 | **See something in our code or documentation?** Create an issue on GitHub and we'll take a look. 197 | 198 | # License 199 | The source in the _23andMeResearchKitModule_ repository is made available under the following license unless another license is explicitly identified: 200 | ``` 201 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 202 | 203 | Redistribution and use in source and binary forms, with or without modification, 204 | are permitted provided that the following conditions are met: 205 | 206 | 1. Redistributions of source code must retain the above copyright notice, this 207 | list of conditions and the following disclaimer. 208 | 209 | 2. Redistributions in binary form must reproduce the above copyright notice, 210 | this list of conditions and the following disclaimer in the documentation and/or 211 | other materials provided with the distribution. 212 | 213 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 214 | may be used to endorse or promote products derived from this software without 215 | specific prior written permission. No license is granted to the trademarks of 216 | the copyright holders even if such marks are included in this software. 217 | 218 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 219 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 220 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 221 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 222 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 223 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 224 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 225 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 226 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 227 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 228 | ``` 229 | 230 | [documentation]: https://api.23andme.com/docs/authentication/ 231 | [genomes]: https://api.23andme.com/docs/reference/#genomes 232 | [genotypes]: https://api.23andme.com/docs/reference/#genotypes 233 | [here]: https://api.23andme.com/ 234 | [upgrade]: https://api.23andme.com/overview/ 235 | [ResearchKit repo]: https://github.com/researchkit/researchkit#adding-the-researchkit-framework-to-your-app 236 | [scopes]: https://api.23andme.com/docs/authentication/#scopes 237 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/congratulations_chromosome_blue.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "congratulations_chromosome_blue.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "congratulations_chromosome_blue@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "congratulations_chromosome_blue@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/congratulations_chromosome_blue.imageset/congratulations_chromosome_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/congratulations_chromosome_blue.imageset/congratulations_chromosome_blue.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/congratulations_chromosome_blue.imageset/congratulations_chromosome_blue@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/congratulations_chromosome_blue.imageset/congratulations_chromosome_blue@2x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/congratulations_chromosome_blue.imageset/congratulations_chromosome_blue@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/congratulations_chromosome_blue.imageset/congratulations_chromosome_blue@3x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/failure_chromosome_purple.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "failure_chromosome_purple.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "failure_chromosome_purple@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "failure_chromosome_purple@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/failure_chromosome_purple.imageset/failure_chromosome_purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/failure_chromosome_purple.imageset/failure_chromosome_purple.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/failure_chromosome_purple.imageset/failure_chromosome_purple@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/failure_chromosome_purple.imageset/failure_chromosome_purple@2x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/failure_chromosome_purple.imageset/failure_chromosome_purple@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/failure_chromosome_purple.imageset/failure_chromosome_purple@3x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_23andMe_logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "intro_23andMe_logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "intro_23andMe_logo@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "intro_23andMe_logo@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_23andMe_logo.imageset/intro_23andMe_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_23andMe_logo.imageset/intro_23andMe_logo.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_23andMe_logo.imageset/intro_23andMe_logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_23andMe_logo.imageset/intro_23andMe_logo@2x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_23andMe_logo.imageset/intro_23andMe_logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_23andMe_logo.imageset/intro_23andMe_logo@3x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_green.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "intro_chromosome_green.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "intro_chromosome_green@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "intro_chromosome_green@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_green.imageset/intro_chromosome_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_chromosome_green.imageset/intro_chromosome_green.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_green.imageset/intro_chromosome_green@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_chromosome_green.imageset/intro_chromosome_green@2x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_green.imageset/intro_chromosome_green@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_chromosome_green.imageset/intro_chromosome_green@3x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_green_striped.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "intro_chromosome_green_striped.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "intro_chromosome_green_striped@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "intro_chromosome_green_striped@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_green_striped.imageset/intro_chromosome_green_striped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_chromosome_green_striped.imageset/intro_chromosome_green_striped.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_green_striped.imageset/intro_chromosome_green_striped@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_chromosome_green_striped.imageset/intro_chromosome_green_striped@2x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_green_striped.imageset/intro_chromosome_green_striped@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_chromosome_green_striped.imageset/intro_chromosome_green_striped@3x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_pink.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "intro_chromosome_pink.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "intro_chromosome_pink@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "intro_chromosome_pink@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_pink.imageset/intro_chromosome_pink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_chromosome_pink.imageset/intro_chromosome_pink.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_pink.imageset/intro_chromosome_pink@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_chromosome_pink.imageset/intro_chromosome_pink@2x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Assets/intro_chromosome_pink.imageset/intro_chromosome_pink@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/23andMe/23andMeResearchKitModule/9c7a0b2be813607b83991b20616fdfcffda7083b/TwentyThreeAndMe/Assets/intro_chromosome_pink.imageset/intro_chromosome_pink@3x.png -------------------------------------------------------------------------------- /TwentyThreeAndMe/Common/ORKOrderedTask+TwentyThreeAndMe.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | NS_ASSUME_NONNULL_BEGIN 34 | 35 | @interface ORKOrderedTask (TwentyThreeAndMe) 36 | 37 | /** 38 | * Returns a predefined task that connects a participant with 23andMe 39 | * 40 | * @param identifier The task identifier to use for this task, appropriate to the study. 41 | * @param allowedUserMode Identify the type of users to allow for the module 42 | * @param studyDependency Whether the study requires the module to be succesfully completed. Changes flow/text. 43 | * @param clientId oauth client id 44 | * @param clientSecret oauth client secret 45 | * @param scopes oauth scopes string (will be url encoded) 46 | * @param investigatorDisplayName User facing investigator name 47 | * @param studyDisplayName User facing study name 48 | * @param studyContactEmail Study contact email used in module 49 | * @param baseURLOverride Optional override for connection URL. 50 | * 51 | * @return ORKOrderedTask 52 | */ 53 | + (ORKOrderedTask *)twentyThreeAndMeTaskWithIdentifier:(NSString *)identifier 54 | allowedUserMode:(ORKTwentyThreeAndMeAllowedUserMode)allowedUserMode 55 | studyDependency:(ORKTwentyThreeAndMeStudyDependency)studyDependency 56 | authClientId:(NSString *)clientId 57 | authClientSecret:(NSString *)clientSecret 58 | authScopes:(NSString *)scopes 59 | investigatorDisplayName:(NSString *)investigatorDisplayName 60 | studyDisplayName:(NSString *)studyDisplayName 61 | studyContactEmail:(NSString *)studyContactEmail 62 | baseURLOverride:(nullable NSString *)baseURLOverride; 63 | 64 | @end 65 | 66 | NS_ASSUME_NONNULL_END 67 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Common/ORKOrderedTask+TwentyThreeAndMe.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKOrderedTask+TwentyThreeAndMe.h" 32 | 33 | #import "ORKTwentyThreeAndMeIntroStep.h" 34 | #import "ORKTwentyThreeAndMeConnectStep.h" 35 | #import "ORKTwentyThreeAndMeCompleteStep.h" 36 | 37 | @implementation ORKOrderedTask (TwentyThreeAndMe) 38 | 39 | NSString * const ORKTwentyThreeAndMeIntroStepIdentifier = @"twentyThreeAndMe.intro"; 40 | NSString * const ORKTwentyThreeAndMeConnectStepIdentifier = @"twentyThreeAndMe.connect"; 41 | NSString * const ORKTwentyThreeAndMeCompleteStepIdentifier = @"twentyThreeAndMe.complete"; 42 | 43 | + (ORKOrderedTask *)twentyThreeAndMeTaskWithIdentifier:(NSString *)identifier 44 | allowedUserMode:(ORKTwentyThreeAndMeAllowedUserMode)allowedUserMode 45 | studyDependency:(ORKTwentyThreeAndMeStudyDependency)studyDependency 46 | authClientId:(NSString *)clientId 47 | authClientSecret:(NSString *)clientSecret 48 | authScopes:(NSString *)scopes 49 | investigatorDisplayName:(NSString *)investigatorDisplayName 50 | studyDisplayName:(NSString *)studyDisplayName 51 | studyContactEmail:(NSString *)studyContactEmail 52 | baseURLOverride:(nullable NSString *)baseURLOverride 53 | { 54 | NSMutableArray *steps = [NSMutableArray array]; 55 | 56 | { 57 | ORKTwentyThreeAndMeIntroStep *step = [[ORKTwentyThreeAndMeIntroStep alloc] initWithIdentifier:ORKTwentyThreeAndMeIntroStepIdentifier]; 58 | step.investigatorDisplayName = investigatorDisplayName; 59 | step.studyDisplayName = studyDisplayName; 60 | step.studyContactEmail = studyContactEmail; 61 | step.allowedUserMode = allowedUserMode; 62 | step.studyDependency = studyDependency; 63 | ORKStepArrayAddStep(steps, step); 64 | } 65 | 66 | { 67 | ORKTwentyThreeAndMeConnectStep *step = [[ORKTwentyThreeAndMeConnectStep alloc] initWithIdentifier:ORKTwentyThreeAndMeConnectStepIdentifier]; 68 | step.baseURL = baseURLOverride ? baseURLOverride : @"https://api.23andme.com"; 69 | step.redirectURI = @"http://localhost:5000/receive_code/&response_type=code"; 70 | step.clientId = clientId; 71 | step.clientSecret = clientSecret; 72 | step.scopes = [scopes stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; 73 | step.studyDisplayNameParam = [studyDisplayName stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];; 74 | step.allowedUserMode = allowedUserMode; 75 | ORKStepArrayAddStep(steps, step); 76 | } 77 | 78 | { 79 | ORKTwentyThreeAndMeCompleteStep *step = [[ORKTwentyThreeAndMeCompleteStep alloc] initWithIdentifier:ORKTwentyThreeAndMeCompleteStepIdentifier]; 80 | step.studyDisplayName = studyDisplayName; 81 | step.studyContactEmail = studyContactEmail; 82 | step.allowedUserMode = allowedUserMode; 83 | ORKStepArrayAddStep(steps, step); 84 | } 85 | 86 | ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; 87 | 88 | return task; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Common/ORKResult+TwentyThreeAndMe.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | NS_ASSUME_NONNULL_BEGIN 34 | 35 | @class ORKTwentyThreeAndMeConnectResult; 36 | 37 | /** 38 | The 'ORKTwentyThreeAndMeConnectResult' class represents the results of the 23andMe signup connection step. 39 | 40 | AuthToken and RefreshToken are generated at the end of generation. Failed flow results will 41 | not contain these. 42 | 43 | newUserFlow is YES when this step finished using the new user flow. NO otherwise. 44 | */ 45 | ORK_CLASS_AVAILABLE 46 | @interface ORKTwentyThreeAndMeConnectResult : ORKResult 47 | 48 | /** 49 | * Auth Token from oauth with 23andMe 50 | */ 51 | @property (nonatomic, copy, nullable) NSString *authToken; 52 | 53 | /** 54 | * Refresh Token from oauth with 23andMe 55 | */ 56 | @property (nonatomic, copy, nullable) NSString *refreshToken; 57 | 58 | /** 59 | * Whether the new customer flow was used to generate the tokens above. 60 | */ 61 | @property (nonatomic) BOOL newUserFlow; 62 | 63 | @end 64 | 65 | NS_ASSUME_NONNULL_END 66 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Common/ORKResult+TwentyThreeAndMe.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKResult+TwentyThreeAndMe.h" 32 | 33 | #import "ORKHelpers.h" 34 | 35 | @implementation ORKTwentyThreeAndMeConnectResult 36 | 37 | + (BOOL)supportsSecureCoding { 38 | return YES; 39 | } 40 | 41 | - (void)encodeWithCoder:(NSCoder *)aCoder { 42 | ORK_ENCODE_OBJ(aCoder, authToken); 43 | } 44 | 45 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 46 | self = [super init]; 47 | if (self) { 48 | ORK_DECODE_OBJ_CLASS(aDecoder, authToken, NSString); 49 | } 50 | return self; 51 | } 52 | 53 | - (BOOL)isEqual:(id)object { 54 | BOOL isParentSame = [super isEqual:object]; 55 | 56 | __typeof(self) castObject = object; 57 | return (isParentSame && 58 | ORKEqualObjects(self.authToken, castObject.authToken)); 59 | } 60 | 61 | - (instancetype)copyWithZone:(NSZone *)zone { 62 | ORKTwentyThreeAndMeConnectResult *result = [super copyWithZone:zone]; 63 | result.authToken = [self.authToken copy]; 64 | return result; 65 | } 66 | 67 | - (NSString *)description { 68 | return [NSString stringWithFormat:@"%@ %@", [super description], self.authToken]; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Common/ORKTwentyThreeAndMeDefines.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | #ifndef ORKTwentyThreeAndMeDefines_h 34 | #define ORKTwentyThreeAndMeDefines_h 35 | 36 | /** 37 | Identify what type of users should be serviced by this module 38 | */ 39 | typedef NS_ENUM(NSInteger, ORKTwentyThreeAndMeAllowedUserMode) { 40 | /// Existing 23andMe customers only 41 | ORKTwentyThreeAndMeAllowedUserModeExistingOnly, 42 | 43 | /// Existing 23andMe customers, and new customers who will receive kits furnished by the study. 44 | ORKTwentyThreeAndMeAllowedUserModeExistingAndNew, 45 | } ORK_ENUM_AVAILABLE; 46 | 47 | /** 48 | Identify whether completion of the module successfully is required for participation in the study 49 | */ 50 | typedef NS_ENUM(NSInteger, ORKTwentyThreeAndMeStudyDependency) { 51 | /// Successful completion is required 52 | ORKTwentyThreeAndMeStudyDependencyRequired, 53 | 54 | /// Successful completion is optional 55 | ORKTwentyThreeAndMeStudyDependencyOptional, 56 | } ORK_ENUM_AVAILABLE; 57 | 58 | 59 | #endif /* ORKTwentyThreeAndMeDefines_h */ 60 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/OtherEdits.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | 32 | /** 33 | * Add to ResearchKit.strings - English 34 | */ 35 | 36 | /* 23andMe connect task. */ 37 | "TWENTYTHREEANDME_DECLINE_PROMPT_DETAILS" = "Are you sure you want to decline adding your genetic data to %@? Declining may impact your eligibility for this study"; 38 | "TWENTYTHREEANDME_DECLINE_PROMPT_ACTION_DECLINE" = "Decline"; 39 | "TWENTYTHREEANDME_DECLINE_PROMPT_ACTION_CANCEL" = "Cancel"; 40 | 41 | "TWENTYTHREEANDME_INTRO_MAIN_SHARE" = "Add Genetic Data"; 42 | "TWENTYTHREEANDME_INTRO_MAIN_DECLINE" = "Decline"; 43 | 44 | "TWENTYTHREEANDME_INTRO_1_DESCRIPTION" = "%@ has selected 23andMe to collect genetic data for the %@ study"; 45 | 46 | "TWENTYTHREEANDME_INTRO_2_TITLE" = "About this study"; 47 | "TWENTYTHREEANDME_INTRO_2_ABOUT_REQUIRED" = "Contributing your genetic data is required for participation in the %@ study. You will need to authorize 23andMe to share that data with %@"; 48 | "TWENTYTHREEANDME_INTRO_2_ABOUT_OPTIONAL" = "In order to contribute your genetic data to the %@ study, you will need to authorize 23andMe to share that data with %@"; 49 | "TWENTYTHREEANDME_INTRO_2_ELIGIBILITY_HEADER" = "Eligibility"; 50 | "TWENTYTHREEANDME_INTRO_2_ELIGIBILITY_EXISTING" = "• Existing 23andMe users"; 51 | "TWENTYTHREEANDME_INTRO_2_ELIGIBILITY_NEW" = "• Individuals who agree to receive the 23andMe Personal Genome Service at no cost"; 52 | 53 | "TWENTYTHREEANDME_INTRO_3_TITLE" = "About 23andMe"; 54 | "TWENTYTHREEANDME_INTRO_3_MISSION" = "23andMe is a genetic service available directly to U.S. customers that includes reports that meet FDA standards for being scientifically and clinically valid. 23andMe helps people understand what’s in their DNA. The 23andMe Personal Genome Service includes more than 60 personalized genetic health, trait and ancestry reports."; 55 | "TWENTYTHREEANDME_INTRO_3_LEARN_MORE" = "Learn more about 23andMe"; 56 | "TWENTYTHREEANDME_INTRO_3_QUESTIONS" = "Questions?"; 57 | "TWENTYTHREEANDME_INTRO_3_CONTACT" = "Contact %@"; 58 | 59 | "TWENTYTHREEANDME_COMPLETE_TITLE" = "Congratulations"; 60 | "TWENTYTHREEANDME_COMPLETE_DONE_BUTTON" = "Done"; 61 | "TWENTYTHREEANDME_COMPLETE_EXISTING_DETAIL" = "Congratulations, you’ve successfully enrolled in %@. %@ is now authorized to access your genetic data."; 62 | "TWENTYTHREEANDME_COMPLETE_NEW_DETAIL" = "Congratulations, you’ve successfully enrolled in %@. %@ is now authorized to access your genetic data."; 63 | "TWENTYTHREEANDME_COMPLETE_NEW_NEXT_STEP" = "Next steps"; 64 | "TWENTYTHREEANDME_COMPLETE_NEW_NEXT_STEP_DETAIL" = "23andMe will mail you a saliva collection kit. Simply follow the instructions included with the kit, mail the sample back, and we will notify you when your reports are ready."; 65 | 66 | "TWENTYTHREEANDME_FAILURE_TITLE" = "Try again"; 67 | "TWENTYTHREEANDME_FAILURE_DESCRIPTION" = "Sorry, we weren’t able to enroll you in the genetic component of %@. Please try again, or contact %@ if you have any questions."; 68 | "TWENTYTHREEANDME_FAILURE_CONTACT" = "Contact %@"; 69 | "TWENTYTHREEANDME_FAILURE_TRY_AGAIN_BUTTON" = "Try again"; 70 | "TWENTYTHREEANDME_FAILURE_DECLINE_BUTTON" = "Decline"; 71 | 72 | /** 73 | * Add to ResearchKit.h 74 | * 75 | * Don't forget that when you add the following files to your project, they must have target 76 | * membership set to "public" 77 | */ 78 | 79 | #import 80 | #import 81 | 82 | /** 83 | * Add to ResearchKit_Private.h 84 | * 85 | * Don't forget that when you add the following files to your project, they must have target 86 | * membership set to "private" 87 | */ 88 | 89 | #import 90 | #import -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeCompleteStep.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | ORK_CLASS_AVAILABLE 34 | @interface ORKTwentyThreeAndMeCompleteStep : ORKStep 35 | 36 | /** 37 | * The display name of the study 38 | */ 39 | @property (nonatomic, copy, nullable) NSString *studyDisplayName; 40 | 41 | /** 42 | * The contact email for the study 43 | */ 44 | @property (nonatomic, copy, nullable) NSString *studyContactEmail; 45 | 46 | /** 47 | * Allowed User Mode for the module 48 | */ 49 | @property (nonatomic) ORKTwentyThreeAndMeAllowedUserMode allowedUserMode; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeCompleteStep.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeCompleteStep.h" 32 | 33 | #import "ORKTwentyThreeAndMeCompleteViewController.h" 34 | 35 | @implementation ORKTwentyThreeAndMeCompleteStep 36 | 37 | + (Class)stepViewControllerClass { 38 | return [ORKTwentyThreeAndMeCompleteViewController class]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeCompleteViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | ORK_CLASS_AVAILABLE 34 | @interface ORKTwentyThreeAndMeCompleteViewController : ORKStepViewController 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeCompleteViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeCompleteViewController.h" 32 | 33 | #import "ORKTwentyThreeAndMeCompleteStep.h" 34 | #import "ORKTwentyThreeAndMeSuccessExistingViewController.h" 35 | #import "ORKTwentyThreeAndMeSuccessNewViewController.h" 36 | #import "ORKTwentyThreeAndMeFailureViewController.h" 37 | 38 | 39 | @interface ORKTwentyThreeAndMeCompleteViewController() 40 | 41 | @property (nonatomic) ORKTwentyThreeAndMeSuccessExistingViewController *successExistingViewController; 42 | 43 | @property (nonatomic) ORKTwentyThreeAndMeSuccessNewViewController *successNewViewController; 44 | 45 | @property (nonatomic) ORKTwentyThreeAndMeFailureViewController *failureViewController; 46 | 47 | @end 48 | 49 | @implementation ORKTwentyThreeAndMeCompleteViewController 50 | 51 | - (ORKTwentyThreeAndMeCompleteStep *)completeStep { 52 | return (ORKTwentyThreeAndMeCompleteStep *)self.step; 53 | } 54 | 55 | - (void)successExistingDoneButtonPressed { 56 | [self goForward]; 57 | } 58 | 59 | - (void)successNewDoneButtonPressed { 60 | [self goForward]; 61 | } 62 | 63 | - (void)failureTryAgainButtonPressed { 64 | [self goBackward]; 65 | } 66 | 67 | - (void)failureDeclineButtonPressed { 68 | [self.taskViewController.delegate taskViewController:self.taskViewController 69 | didFinishWithReason:ORKTaskViewControllerFinishReasonDiscarded 70 | error:nil]; 71 | } 72 | 73 | - (void)viewDidLoad { 74 | [super viewDidLoad]; 75 | 76 | ORKTwentyThreeAndMeCompleteStep *completeStep = [self completeStep]; 77 | NSString *studyDisplayName = completeStep.studyDisplayName; 78 | NSString *studyContactEmail = completeStep.studyContactEmail; 79 | 80 | self.successExistingViewController = [[ORKTwentyThreeAndMeSuccessExistingViewController alloc] init]; 81 | self.successExistingViewController.delegate = self; 82 | self.successExistingViewController.studyDisplayName = studyDisplayName; 83 | 84 | self.successNewViewController = [[ORKTwentyThreeAndMeSuccessNewViewController alloc] init]; 85 | self.successNewViewController.delegate = self; 86 | self.successNewViewController.studyDisplayName = studyDisplayName; 87 | 88 | self.failureViewController = [[ORKTwentyThreeAndMeFailureViewController alloc] init]; 89 | self.failureViewController.delegate = self; 90 | self.failureViewController.studyDisplayName = studyDisplayName; 91 | self.failureViewController.studyContactEmail = studyContactEmail; 92 | 93 | self.cancelButtonItem = nil; 94 | self.backButtonItem = nil; 95 | } 96 | 97 | - (void)viewWillAppear:(BOOL)animated { 98 | [super viewWillAppear:animated]; 99 | 100 | // Use Results to Determine What To Show 101 | ORKTaskResult *taskResult = [self.taskViewController result]; 102 | ORKCollectionResult *connectResultCollection = (ORKCollectionResult *)[taskResult resultForIdentifier:@"twentyThreeAndMe.connect"]; 103 | ORKTwentyThreeAndMeConnectResult *connectResult = (ORKTwentyThreeAndMeConnectResult *)[connectResultCollection.results firstObject]; 104 | if( connectResult.authToken && 105 | connectResult.refreshToken ) { 106 | [self hideFailureViewController]; 107 | if( connectResult.newUserFlow ) 108 | { 109 | [self showSuccessNewViewController]; 110 | } 111 | else 112 | { 113 | [self showSuccessExistingViewController]; 114 | } 115 | } 116 | else { 117 | [self hideSuccessExistingViewController]; 118 | [self showFailureViewController]; 119 | } 120 | } 121 | 122 | - (void)showSuccessExistingViewController { 123 | [self addChildViewController:self.successExistingViewController]; 124 | [self.view addSubview:self.successExistingViewController.view]; 125 | [self.successExistingViewController didMoveToParentViewController:self]; 126 | } 127 | 128 | - (void)hideSuccessExistingViewController { 129 | [self.successExistingViewController willMoveToParentViewController:nil]; 130 | [self.successExistingViewController.view removeFromSuperview]; 131 | [self.successExistingViewController removeFromParentViewController]; 132 | } 133 | 134 | - (void)showSuccessNewViewController { 135 | [self addChildViewController:self.successNewViewController]; 136 | [self.view addSubview:self.successNewViewController.view]; 137 | [self.successNewViewController didMoveToParentViewController:self]; 138 | } 139 | 140 | - (void)hideSuccessNewViewController { 141 | [self.successNewViewController willMoveToParentViewController:nil]; 142 | [self.successNewViewController.view removeFromSuperview]; 143 | [self.successNewViewController removeFromParentViewController]; 144 | } 145 | 146 | - (void)showFailureViewController { 147 | [self addChildViewController:self.failureViewController]; 148 | [self.view addSubview:self.failureViewController.view]; 149 | [self.failureViewController didMoveToParentViewController:self]; 150 | } 151 | 152 | - (void)hideFailureViewController { 153 | [self.failureViewController willMoveToParentViewController:nil]; 154 | [self.failureViewController.view removeFromSuperview]; 155 | [self.failureViewController removeFromParentViewController]; 156 | } 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeFailureViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | @protocol ORKTwentyThreeAndMeFailureViewControllerDelegate 34 | 35 | /** 36 | * Callback when try again button pressed 37 | */ 38 | - (void)failureTryAgainButtonPressed; 39 | 40 | /** 41 | * Callback when decline button pressed 42 | */ 43 | - (void)failureDeclineButtonPressed; 44 | 45 | @end 46 | 47 | ORK_CLASS_AVAILABLE 48 | @interface ORKTwentyThreeAndMeFailureViewController : UIViewController 49 | 50 | /** 51 | The delegate for this view controller. 52 | */ 53 | @property (nonatomic, weak, nullable) id delegate; 54 | 55 | /** 56 | * The display name of the study 57 | */ 58 | @property (nonatomic, nullable) NSString *studyDisplayName; 59 | 60 | /** 61 | * The contact email for the study 62 | */ 63 | @property (nonatomic, nullable) NSString *studyContactEmail; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeFailureViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeFailureViewController.h" 32 | 33 | #import "UIButton+T23.h" 34 | #import "UILabel+T23.h" 35 | 36 | @interface ORKTwentyThreeAndMeFailureViewController () 37 | 38 | @end 39 | 40 | @implementation ORKTwentyThreeAndMeFailureViewController 41 | 42 | - (void)viewDidLoad { 43 | [super viewDidLoad]; 44 | 45 | [self setupAppearance]; 46 | } 47 | 48 | - (void)tryAgainButtonPressed:(UIButton *)sender { 49 | [self.delegate failureTryAgainButtonPressed]; 50 | } 51 | 52 | - (void)declineButtonPressed:(UIButton *)sender { 53 | [self.delegate failureDeclineButtonPressed]; 54 | } 55 | 56 | - (void)contactStudyButtonPressed:(UIButton *)sender { 57 | NSString *contactStudyByMail = [NSString stringWithFormat:@"mailto:?to=%@&subject=%@&body=%@", 58 | [self.studyContactEmail stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding], 59 | [self.studyDisplayName stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding], 60 | @""]; 61 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:contactStudyByMail]]; 62 | } 63 | 64 | - (void)setupAppearance { 65 | //-------------------- 66 | // Style 67 | self.view.backgroundColor = [UIColor whiteColor]; 68 | 69 | //-------------------- 70 | // Gene Pill Image View 71 | UIImage *genePillImage = [UIImage imageNamed:@"failure_chromosome_purple" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; 72 | UIImageView *genePillImageView = [[UIImageView alloc] initWithImage:genePillImage]; 73 | [self.view addSubview:genePillImageView]; 74 | genePillImageView.translatesAutoresizingMaskIntoConstraints = NO; 75 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:genePillImageView 76 | attribute:NSLayoutAttributeTop 77 | relatedBy:NSLayoutRelationEqual 78 | toItem:self.view 79 | attribute:NSLayoutAttributeTop 80 | multiplier:1.0 81 | constant:0.0]]; 82 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:genePillImageView 83 | attribute:NSLayoutAttributeTrailing 84 | relatedBy:NSLayoutRelationEqual 85 | toItem:self.view 86 | attribute:NSLayoutAttributeTrailing 87 | multiplier:1.0 88 | constant:0.0]]; 89 | 90 | //-------------------- 91 | // Text Content View 92 | UIView *textContentView = [[UIView alloc] init]; 93 | [self.view addSubview:textContentView]; 94 | textContentView.translatesAutoresizingMaskIntoConstraints = NO; 95 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:textContentView 96 | attribute:NSLayoutAttributeLeading 97 | relatedBy:NSLayoutRelationEqual 98 | toItem:self.view 99 | attribute:NSLayoutAttributeLeading 100 | multiplier:1.0 101 | constant:0.0]]; 102 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:textContentView 103 | attribute:NSLayoutAttributeTrailing 104 | relatedBy:NSLayoutRelationEqual 105 | toItem:self.view 106 | attribute:NSLayoutAttributeTrailing 107 | multiplier:1.0 108 | constant:0.0]]; 109 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:textContentView 110 | attribute:NSLayoutAttributeCenterY 111 | relatedBy:NSLayoutRelationEqual 112 | toItem:self.view 113 | attribute:NSLayoutAttributeCenterY 114 | multiplier:1.0 115 | constant:-20.0]]; 116 | 117 | //-------------------- 118 | // Title Label 119 | UILabel *titleLabel = [UILabel t23HeaderLabelWithText:ORKLocalizedString(@"TWENTYTHREEANDME_FAILURE_TITLE", nil)]; 120 | [textContentView addSubview:titleLabel]; 121 | titleLabel.translatesAutoresizingMaskIntoConstraints = NO; 122 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 123 | attribute:NSLayoutAttributeTop 124 | relatedBy:NSLayoutRelationEqual 125 | toItem:textContentView 126 | attribute:NSLayoutAttributeTop 127 | multiplier:1.0 128 | constant:0.0]]; 129 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 130 | attribute:NSLayoutAttributeLeading 131 | relatedBy:NSLayoutRelationEqual 132 | toItem:textContentView 133 | attribute:NSLayoutAttributeLeading 134 | multiplier:1.0 135 | constant:15.0]]; 136 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 137 | attribute:NSLayoutAttributeTrailing 138 | relatedBy:NSLayoutRelationEqual 139 | toItem:textContentView 140 | attribute:NSLayoutAttributeTrailing 141 | multiplier:1.0 142 | constant:-15.0]]; 143 | 144 | //-------------------- 145 | // Description Label 146 | NSString *descriptionLabelText = [NSString stringWithFormat:ORKLocalizedString(@"TWENTYTHREEANDME_FAILURE_DESCRIPTION", nil), self.studyDisplayName, self.studyDisplayName]; 147 | UILabel *descriptionLabel = [UILabel t23BodyLabelWithText:descriptionLabelText]; 148 | [textContentView addSubview:descriptionLabel]; 149 | descriptionLabel.translatesAutoresizingMaskIntoConstraints = NO; 150 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 151 | attribute:NSLayoutAttributeTop 152 | relatedBy:NSLayoutRelationEqual 153 | toItem:titleLabel 154 | attribute:NSLayoutAttributeBottom 155 | multiplier:1.0 156 | constant:20.0]]; 157 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 158 | attribute:NSLayoutAttributeLeading 159 | relatedBy:NSLayoutRelationEqual 160 | toItem:textContentView 161 | attribute:NSLayoutAttributeLeading 162 | multiplier:1.0 163 | constant:15.0]]; 164 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 165 | attribute:NSLayoutAttributeTrailing 166 | relatedBy:NSLayoutRelationEqual 167 | toItem:textContentView 168 | attribute:NSLayoutAttributeTrailing 169 | multiplier:1.0 170 | constant:-15.0]]; 171 | 172 | UIButton *contactStudyButton = [[UIButton alloc] init]; 173 | NSString *contactStudyText = [NSString stringWithFormat:ORKLocalizedString(@"TWENTYTHREEANDME_FAILURE_CONTACT", nil), self.studyDisplayName]; 174 | [contactStudyButton addTarget:self action:@selector(contactStudyButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 175 | [contactStudyButton setTitle:contactStudyText forState:UIControlStateNormal]; 176 | UIColor *t23BlueColor = [UIColor colorWithRed:53.0/255.0 green:149.0/255.0 blue:214.0/255.0 alpha:1.0]; 177 | [contactStudyButton setTitleColor:t23BlueColor forState:UIControlStateNormal]; 178 | contactStudyButton.titleLabel.font = [UIFont systemFontOfSize:16.0]; 179 | [textContentView addSubview:contactStudyButton]; 180 | contactStudyButton.translatesAutoresizingMaskIntoConstraints = NO; 181 | [contactStudyButton addConstraint:[NSLayoutConstraint constraintWithItem:contactStudyButton 182 | attribute:NSLayoutAttributeHeight 183 | relatedBy:NSLayoutRelationEqual 184 | toItem:nil 185 | attribute:NSLayoutAttributeNotAnAttribute 186 | multiplier:1.0 187 | constant:45.0]]; 188 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:contactStudyButton 189 | attribute:NSLayoutAttributeTop 190 | relatedBy:NSLayoutRelationEqual 191 | toItem:descriptionLabel 192 | attribute:NSLayoutAttributeBottom 193 | multiplier:1.0 194 | constant:-10.0]]; 195 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:contactStudyButton 196 | attribute:NSLayoutAttributeLeading 197 | relatedBy:NSLayoutRelationEqual 198 | toItem:textContentView 199 | attribute:NSLayoutAttributeLeading 200 | multiplier:1.0 201 | constant:15.0]]; 202 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:contactStudyButton 203 | attribute:NSLayoutAttributeBottom 204 | relatedBy:NSLayoutRelationEqual 205 | toItem:textContentView 206 | attribute:NSLayoutAttributeBottom 207 | multiplier:1.0 208 | constant:0.0]]; 209 | 210 | //-------------------- 211 | // Try Again Button 212 | UIButton *tryAgainButton = [UIButton t23ButtonWithText:ORKLocalizedString(@"TWENTYTHREEANDME_FAILURE_TRY_AGAIN_BUTTON", nil) andHasBorder:YES]; 213 | [self.view addSubview:tryAgainButton]; 214 | [tryAgainButton addTarget:self action:@selector(tryAgainButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 215 | tryAgainButton.translatesAutoresizingMaskIntoConstraints = NO; 216 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:tryAgainButton 217 | attribute:NSLayoutAttributeCenterX 218 | relatedBy:NSLayoutRelationEqual 219 | toItem:self.view 220 | attribute:NSLayoutAttributeCenterX 221 | multiplier:1.0 222 | constant:0.0]]; 223 | 224 | //-------------------- 225 | // Decline Button 226 | UIButton *declineButton = [UIButton t23ButtonWithText:ORKLocalizedString(@"TWENTYTHREEANDME_FAILURE_DECLINE_BUTTON", nil) andHasBorder:NO]; 227 | [self.view addSubview:declineButton]; 228 | [declineButton addTarget:self action:@selector(declineButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 229 | declineButton.translatesAutoresizingMaskIntoConstraints = NO; 230 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:declineButton 231 | attribute:NSLayoutAttributeTop 232 | relatedBy:NSLayoutRelationEqual 233 | toItem:tryAgainButton 234 | attribute:NSLayoutAttributeBottom 235 | multiplier:1.0 236 | constant:5.0]]; 237 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:declineButton 238 | attribute:NSLayoutAttributeCenterX 239 | relatedBy:NSLayoutRelationEqual 240 | toItem:self.view 241 | attribute:NSLayoutAttributeCenterX 242 | multiplier:1.0 243 | constant:0.0]]; 244 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:declineButton 245 | attribute:NSLayoutAttributeBottom 246 | relatedBy:NSLayoutRelationEqual 247 | toItem:self.view 248 | attribute:NSLayoutAttributeBottom 249 | multiplier:1.0 250 | constant:-10.0]]; 251 | } 252 | 253 | @end 254 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeSuccessExistingViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | @protocol ORKTwentyThreeAndMeSuccessExistingViewControllerDelegate 34 | 35 | /** 36 | * Delegate callback when done button is pressed 37 | */ 38 | - (void)successExistingDoneButtonPressed; 39 | 40 | @end 41 | 42 | ORK_CLASS_AVAILABLE 43 | @interface ORKTwentyThreeAndMeSuccessExistingViewController : UIViewController 44 | 45 | /** 46 | The delegate for this view controller. 47 | */ 48 | @property (nonatomic, weak, nullable) id delegate; 49 | 50 | /** 51 | * The display name of the study 52 | */ 53 | @property (nonatomic, nullable) NSString *studyDisplayName; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeSuccessExistingViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeSuccessExistingViewController.h" 32 | 33 | #import "UIButton+T23.h" 34 | #import "UILabel+T23.h" 35 | 36 | @implementation ORKTwentyThreeAndMeSuccessExistingViewController 37 | 38 | - (void)viewDidLoad { 39 | [super viewDidLoad]; 40 | 41 | [self setupAppearance]; 42 | } 43 | 44 | - (void)doneButtonPressed:(UIButton *)sender { 45 | [self.delegate successExistingDoneButtonPressed]; 46 | } 47 | 48 | - (void)setupAppearance { 49 | //-------------------- 50 | // Style 51 | self.view.backgroundColor = [UIColor whiteColor]; 52 | 53 | //-------------------- 54 | // Gene Pill Image View 55 | UIImage *genePillImage = [UIImage imageNamed:@"congratulations_chromosome_blue" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; 56 | UIImageView *genePillImageView = [[UIImageView alloc] initWithImage:genePillImage]; 57 | [self.view addSubview:genePillImageView]; 58 | genePillImageView.translatesAutoresizingMaskIntoConstraints = NO; 59 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:genePillImageView 60 | attribute:NSLayoutAttributeTop 61 | relatedBy:NSLayoutRelationEqual 62 | toItem:self.view 63 | attribute:NSLayoutAttributeTop 64 | multiplier:1.0 65 | constant:0.0]]; 66 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:genePillImageView 67 | attribute:NSLayoutAttributeLeading 68 | relatedBy:NSLayoutRelationEqual 69 | toItem:self.view 70 | attribute:NSLayoutAttributeLeading 71 | multiplier:1.0 72 | constant:0.0]]; 73 | 74 | //-------------------- 75 | // Text Content View 76 | UIView *textContentView = [[UIView alloc] init]; 77 | [self.view addSubview:textContentView]; 78 | textContentView.translatesAutoresizingMaskIntoConstraints = NO; 79 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:textContentView 80 | attribute:NSLayoutAttributeLeading 81 | relatedBy:NSLayoutRelationEqual 82 | toItem:self.view 83 | attribute:NSLayoutAttributeLeading 84 | multiplier:1.0 85 | constant:0.0]]; 86 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:textContentView 87 | attribute:NSLayoutAttributeTrailing 88 | relatedBy:NSLayoutRelationEqual 89 | toItem:self.view 90 | attribute:NSLayoutAttributeTrailing 91 | multiplier:1.0 92 | constant:0.0]]; 93 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:textContentView 94 | attribute:NSLayoutAttributeCenterY 95 | relatedBy:NSLayoutRelationEqual 96 | toItem:self.view 97 | attribute:NSLayoutAttributeCenterY 98 | multiplier:1.0 99 | constant:0.0]]; 100 | 101 | //-------------------- 102 | // Title Label 103 | UILabel *titleLabel = [UILabel t23HeaderLabelWithText:ORKLocalizedString(@"TWENTYTHREEANDME_COMPLETE_TITLE", nil)]; 104 | [textContentView addSubview:titleLabel]; 105 | titleLabel.translatesAutoresizingMaskIntoConstraints = NO; 106 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 107 | attribute:NSLayoutAttributeTop 108 | relatedBy:NSLayoutRelationEqual 109 | toItem:textContentView 110 | attribute:NSLayoutAttributeTop 111 | multiplier:1.0 112 | constant:0.0]]; 113 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 114 | attribute:NSLayoutAttributeLeading 115 | relatedBy:NSLayoutRelationEqual 116 | toItem:textContentView 117 | attribute:NSLayoutAttributeLeading 118 | multiplier:1.0 119 | constant:15.0]]; 120 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 121 | attribute:NSLayoutAttributeTrailing 122 | relatedBy:NSLayoutRelationEqual 123 | toItem:textContentView 124 | attribute:NSLayoutAttributeTrailing 125 | multiplier:1.0 126 | constant:-15.0]]; 127 | 128 | //-------------------- 129 | // Description Label 130 | NSString *descriptionLabelText = [NSString stringWithFormat:ORKLocalizedString(@"TWENTYTHREEANDME_COMPLETE_EXISTING_DETAIL", nil), self.studyDisplayName, self.studyDisplayName]; 131 | UILabel *descriptionLabel = [UILabel t23BodyLabelWithText:descriptionLabelText]; 132 | [textContentView addSubview:descriptionLabel]; 133 | descriptionLabel.translatesAutoresizingMaskIntoConstraints = NO; 134 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 135 | attribute:NSLayoutAttributeTop 136 | relatedBy:NSLayoutRelationEqual 137 | toItem:titleLabel 138 | attribute:NSLayoutAttributeBottom 139 | multiplier:1.0 140 | constant:20.0]]; 141 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 142 | attribute:NSLayoutAttributeLeading 143 | relatedBy:NSLayoutRelationEqual 144 | toItem:textContentView 145 | attribute:NSLayoutAttributeLeading 146 | multiplier:1.0 147 | constant:15.0]]; 148 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 149 | attribute:NSLayoutAttributeTrailing 150 | relatedBy:NSLayoutRelationEqual 151 | toItem:textContentView 152 | attribute:NSLayoutAttributeTrailing 153 | multiplier:1.0 154 | constant:-15.0]]; 155 | [textContentView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 156 | attribute:NSLayoutAttributeBottom 157 | relatedBy:NSLayoutRelationEqual 158 | toItem:textContentView 159 | attribute:NSLayoutAttributeBottom 160 | multiplier:1.0 161 | constant:0.0]]; 162 | 163 | //-------------------- 164 | // Done Button 165 | UIButton *doneButton = [UIButton t23ButtonWithText:ORKLocalizedString(@"TWENTYTHREEANDME_COMPLETE_DONE_BUTTON", nil) andHasBorder:YES]; 166 | [self.view addSubview:doneButton]; 167 | [doneButton addTarget:self action:@selector(doneButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 168 | doneButton.translatesAutoresizingMaskIntoConstraints = NO; 169 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:doneButton 170 | attribute:NSLayoutAttributeBottom 171 | relatedBy:NSLayoutRelationEqual 172 | toItem:self.view 173 | attribute:NSLayoutAttributeBottom 174 | multiplier:1.0 175 | constant:-30.0]]; 176 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:doneButton 177 | attribute:NSLayoutAttributeCenterX 178 | relatedBy:NSLayoutRelationEqual 179 | toItem:self.view 180 | attribute:NSLayoutAttributeCenterX 181 | multiplier:1.0 182 | constant:0.0]]; 183 | } 184 | 185 | 186 | @end 187 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeSuccessNewViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | @protocol ORKTwentyThreeAndMeSuccessNewViewControllerDelegate 34 | 35 | /** 36 | * Delegate callback when done button is pressed 37 | */ 38 | - (void)successNewDoneButtonPressed; 39 | 40 | @end 41 | 42 | ORK_CLASS_AVAILABLE 43 | @interface ORKTwentyThreeAndMeSuccessNewViewController : UIViewController 44 | 45 | /** 46 | The delegate for this view controller. 47 | */ 48 | @property (nonatomic, weak, nullable) id delegate; 49 | 50 | /** 51 | * The display name of the study 52 | */ 53 | @property (nonatomic, nullable) NSString *studyDisplayName; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Complete/ORKTwentyThreeAndMeSuccessNewViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeSuccessNewViewController.h" 32 | 33 | #import "UIButton+T23.h" 34 | #import "UILabel+T23.h" 35 | 36 | @implementation ORKTwentyThreeAndMeSuccessNewViewController 37 | 38 | - (void)viewDidLoad { 39 | [super viewDidLoad]; 40 | 41 | [self setupAppearance]; 42 | } 43 | 44 | - (void)doneButtonPressed:(UIButton *)sender { 45 | [self.delegate successNewDoneButtonPressed]; 46 | } 47 | 48 | - (void)setupAppearance { 49 | //-------------------- 50 | // Style 51 | self.view.backgroundColor = [UIColor whiteColor]; 52 | 53 | //-------------------- 54 | // Scroll View 55 | UIScrollView *scrollView = [[UIScrollView alloc] init]; 56 | [self.view addSubview:scrollView]; 57 | scrollView.translatesAutoresizingMaskIntoConstraints = NO; 58 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 59 | attribute:NSLayoutAttributeTop 60 | relatedBy:NSLayoutRelationEqual 61 | toItem:self.view 62 | attribute:NSLayoutAttributeTop 63 | multiplier:1.0 64 | constant:0.0]]; 65 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 66 | attribute:NSLayoutAttributeLeading 67 | relatedBy:NSLayoutRelationEqual 68 | toItem:self.view 69 | attribute:NSLayoutAttributeLeading 70 | multiplier:1.0 71 | constant:0.0]]; 72 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 73 | attribute:NSLayoutAttributeTrailing 74 | relatedBy:NSLayoutRelationEqual 75 | toItem:self.view 76 | attribute:NSLayoutAttributeTrailing 77 | multiplier:1.0 78 | constant:0.0]]; 79 | 80 | //-------------------- 81 | // - Gene Pill Image View 82 | UIImage *genePillImage = [UIImage imageNamed:@"congratulations_chromosome_blue" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; 83 | UIImageView *genePillImageView = [[UIImageView alloc] initWithImage:genePillImage]; 84 | [scrollView addSubview:genePillImageView]; 85 | genePillImageView.translatesAutoresizingMaskIntoConstraints = NO; 86 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:genePillImageView 87 | attribute:NSLayoutAttributeTop 88 | relatedBy:NSLayoutRelationEqual 89 | toItem:scrollView 90 | attribute:NSLayoutAttributeTop 91 | multiplier:1.0 92 | constant:0.0]]; 93 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:genePillImageView 94 | attribute:NSLayoutAttributeLeading 95 | relatedBy:NSLayoutRelationEqual 96 | toItem:scrollView 97 | attribute:NSLayoutAttributeLeading 98 | multiplier:1.0 99 | constant:0.0]]; 100 | 101 | //-------------------- 102 | // - Title Label 103 | UILabel *titleLabel = [UILabel t23HeaderLabelWithText:ORKLocalizedString(@"TWENTYTHREEANDME_COMPLETE_TITLE", nil)]; 104 | [scrollView addSubview:titleLabel]; 105 | titleLabel.translatesAutoresizingMaskIntoConstraints = NO; 106 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 107 | attribute:NSLayoutAttributeTop 108 | relatedBy:NSLayoutRelationEqual 109 | toItem:genePillImageView 110 | attribute:NSLayoutAttributeBottom 111 | multiplier:1.0 112 | constant:10.0]]; 113 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 114 | attribute:NSLayoutAttributeLeading 115 | relatedBy:NSLayoutRelationEqual 116 | toItem:scrollView 117 | attribute:NSLayoutAttributeLeading 118 | multiplier:1.0 119 | constant:15.0]]; 120 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 121 | attribute:NSLayoutAttributeTrailing 122 | relatedBy:NSLayoutRelationEqual 123 | toItem:scrollView 124 | attribute:NSLayoutAttributeTrailing 125 | multiplier:1.0 126 | constant:-15.0]]; 127 | 128 | //-------------------- 129 | // - Scroll View Width Behavior 130 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:titleLabel 131 | attribute:NSLayoutAttributeWidth 132 | relatedBy:NSLayoutRelationEqual 133 | toItem:scrollView 134 | attribute:NSLayoutAttributeWidth 135 | multiplier:1.0 136 | constant:-30.0]]; 137 | 138 | //-------------------- 139 | // - Description Label 140 | NSString *descriptionLabelText = [NSString stringWithFormat:ORKLocalizedString(@"TWENTYTHREEANDME_COMPLETE_NEW_DETAIL", nil), self.studyDisplayName, self.studyDisplayName]; 141 | UILabel *descriptionLabel = [UILabel t23BodyLabelWithText:descriptionLabelText]; 142 | [scrollView addSubview:descriptionLabel]; 143 | descriptionLabel.translatesAutoresizingMaskIntoConstraints = NO; 144 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 145 | attribute:NSLayoutAttributeTop 146 | relatedBy:NSLayoutRelationEqual 147 | toItem:titleLabel 148 | attribute:NSLayoutAttributeBottom 149 | multiplier:1.0 150 | constant:20.0]]; 151 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 152 | attribute:NSLayoutAttributeLeading 153 | relatedBy:NSLayoutRelationEqual 154 | toItem:scrollView 155 | attribute:NSLayoutAttributeLeading 156 | multiplier:1.0 157 | constant:15.0]]; 158 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 159 | attribute:NSLayoutAttributeTrailing 160 | relatedBy:NSLayoutRelationEqual 161 | toItem:scrollView 162 | attribute:NSLayoutAttributeTrailing 163 | multiplier:1.0 164 | constant:-15.0]]; 165 | 166 | //-------------------- 167 | // - Next Steps Title 168 | UILabel *nextStepsHeaderLabel = [UILabel t23SubheaderLabelWithText:ORKLocalizedString(@"TWENTYTHREEANDME_COMPLETE_NEW_NEXT_STEP", nil)]; 169 | [scrollView addSubview:nextStepsHeaderLabel]; 170 | nextStepsHeaderLabel.translatesAutoresizingMaskIntoConstraints = NO; 171 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:nextStepsHeaderLabel 172 | attribute:NSLayoutAttributeTop 173 | relatedBy:NSLayoutRelationEqual 174 | toItem:descriptionLabel 175 | attribute:NSLayoutAttributeBottom 176 | multiplier:1.0 177 | constant:15.0]]; 178 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:nextStepsHeaderLabel 179 | attribute:NSLayoutAttributeLeading 180 | relatedBy:NSLayoutRelationEqual 181 | toItem:scrollView 182 | attribute:NSLayoutAttributeLeading 183 | multiplier:1.0 184 | constant:15.0]]; 185 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:nextStepsHeaderLabel 186 | attribute:NSLayoutAttributeTrailing 187 | relatedBy:NSLayoutRelationEqual 188 | toItem:scrollView 189 | attribute:NSLayoutAttributeTrailing 190 | multiplier:1.0 191 | constant:-15.0]]; 192 | 193 | //-------------------- 194 | // - Next Steps Details 195 | NSString *nextStepsDetailsText = ORKLocalizedString(@"TWENTYTHREEANDME_COMPLETE_NEW_NEXT_STEP_DETAIL", nil); 196 | UILabel *nextStepsDetailsLabel = [UILabel t23BodyLabelWithText:nextStepsDetailsText]; 197 | [scrollView addSubview:nextStepsDetailsLabel]; 198 | nextStepsDetailsLabel.translatesAutoresizingMaskIntoConstraints = NO; 199 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:nextStepsDetailsLabel 200 | attribute:NSLayoutAttributeTop 201 | relatedBy:NSLayoutRelationEqual 202 | toItem:nextStepsHeaderLabel 203 | attribute:NSLayoutAttributeBottom 204 | multiplier:1.0 205 | constant:10.0]]; 206 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:nextStepsDetailsLabel 207 | attribute:NSLayoutAttributeLeading 208 | relatedBy:NSLayoutRelationEqual 209 | toItem:scrollView 210 | attribute:NSLayoutAttributeLeading 211 | multiplier:1.0 212 | constant:15.0]]; 213 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:nextStepsDetailsLabel 214 | attribute:NSLayoutAttributeTrailing 215 | relatedBy:NSLayoutRelationEqual 216 | toItem:scrollView 217 | attribute:NSLayoutAttributeTrailing 218 | multiplier:1.0 219 | constant:-15.0]]; 220 | 221 | //-------------------- 222 | // - Bottom Constraint 223 | [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:nextStepsDetailsLabel 224 | attribute:NSLayoutAttributeBottom 225 | relatedBy:NSLayoutRelationEqual 226 | toItem:scrollView 227 | attribute:NSLayoutAttributeBottom 228 | multiplier:1.0 229 | constant:0.0]]; 230 | 231 | //-------------------- 232 | // Divider View 233 | UIView *dividerView = [[UIView alloc] init]; 234 | dividerView.backgroundColor = [UIColor colorWithRed:227.0/255.0 green:229.0/255.0 blue:230.0/255.0 alpha:1.0]; 235 | [self.view addSubview:dividerView]; 236 | dividerView.translatesAutoresizingMaskIntoConstraints = NO; 237 | [dividerView addConstraint:[NSLayoutConstraint constraintWithItem:dividerView 238 | attribute:NSLayoutAttributeHeight 239 | relatedBy:NSLayoutRelationEqual 240 | toItem:nil 241 | attribute:NSLayoutAttributeNotAnAttribute 242 | multiplier:1.0 243 | constant:1.0]]; 244 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dividerView 245 | attribute:NSLayoutAttributeTop 246 | relatedBy:NSLayoutRelationEqual 247 | toItem:scrollView 248 | attribute:NSLayoutAttributeBottom 249 | multiplier:1.0 250 | constant:0.0]]; 251 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dividerView 252 | attribute:NSLayoutAttributeLeading 253 | relatedBy:NSLayoutRelationEqual 254 | toItem:self.view 255 | attribute:NSLayoutAttributeLeading 256 | multiplier:1.0 257 | constant:0.0]]; 258 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dividerView 259 | attribute:NSLayoutAttributeTrailing 260 | relatedBy:NSLayoutRelationEqual 261 | toItem:self.view 262 | attribute:NSLayoutAttributeTrailing 263 | multiplier:1.0 264 | constant:0.0]]; 265 | 266 | //-------------------- 267 | // Done Button 268 | UIButton *doneButton = [UIButton t23ButtonWithText:ORKLocalizedString(@"TWENTYTHREEANDME_COMPLETE_DONE_BUTTON", nil) andHasBorder:YES]; 269 | [self.view addSubview:doneButton]; 270 | [doneButton addTarget:self action:@selector(doneButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 271 | doneButton.translatesAutoresizingMaskIntoConstraints = NO; 272 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:doneButton 273 | attribute:NSLayoutAttributeTop 274 | relatedBy:NSLayoutRelationEqual 275 | toItem:dividerView 276 | attribute:NSLayoutAttributeBottom 277 | multiplier:1.0 278 | constant:20.0]]; 279 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:doneButton 280 | attribute:NSLayoutAttributeBottom 281 | relatedBy:NSLayoutRelationEqual 282 | toItem:self.view 283 | attribute:NSLayoutAttributeBottom 284 | multiplier:1.0 285 | constant:-20.0]]; 286 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:doneButton 287 | attribute:NSLayoutAttributeCenterX 288 | relatedBy:NSLayoutRelationEqual 289 | toItem:self.view 290 | attribute:NSLayoutAttributeCenterX 291 | multiplier:1.0 292 | constant:0.0]]; 293 | } 294 | 295 | 296 | @end 297 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Connect/ORKTwentyThreeAndMeConnectStep.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | NS_ASSUME_NONNULL_BEGIN 34 | 35 | 36 | /** 37 | * An `ORKTwentyThreeAndMeConnectStep` object allows the participant to connect 38 | * with 23andMe and share their data with the investigators. 39 | */ 40 | ORK_CLASS_AVAILABLE 41 | @interface ORKTwentyThreeAndMeConnectStep : ORKStep 42 | 43 | /** 44 | * RedirectURI used by auth. Should match what is in developer portal. 45 | */ 46 | @property (nonatomic, copy, nullable) NSString *redirectURI; 47 | 48 | /** 49 | * ClientId used by auth. Should match what is in developer portal. 50 | */ 51 | @property (nonatomic, copy, nullable) NSString *clientId; 52 | 53 | /** 54 | * ClientSecret used by auth. Should match what is in developer portal. 55 | */ 56 | @property (nonatomic, copy, nullable) NSString *clientSecret; 57 | 58 | /** 59 | * Scopes used by auth. 60 | */ 61 | @property (nonatomic, copy, nullable) NSString *scopes; 62 | 63 | /** 64 | * Base URL to use for connections 65 | */ 66 | @property (nonatomic, copy, nullable) NSString *baseURL; 67 | 68 | /** 69 | * The display name of the study 70 | */ 71 | @property (nonatomic, copy, nullable) NSString *studyDisplayNameParam; 72 | 73 | /** 74 | * Allowed User Mode for the module 75 | */ 76 | @property (nonatomic) ORKTwentyThreeAndMeAllowedUserMode allowedUserMode; 77 | 78 | @end 79 | 80 | NS_ASSUME_NONNULL_END -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Connect/ORKTwentyThreeAndMeConnectStep.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeConnectStep.h" 32 | 33 | #import "ORKTwentyThreeAndMeConnectStepViewController.h" 34 | 35 | @implementation ORKTwentyThreeAndMeConnectStep 36 | 37 | + (Class)stepViewControllerClass { 38 | return [ORKTwentyThreeAndMeConnectStepViewController class]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Connect/ORKTwentyThreeAndMeConnectStepViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | @import WebKit; 34 | 35 | /** 36 | * StepViewController for Connecting to 23andMe auth with a wrapped webview 37 | */ 38 | ORK_CLASS_AVAILABLE 39 | @interface ORKTwentyThreeAndMeConnectStepViewController : ORKStepViewController 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Connect/ORKTwentyThreeAndMeConnectStepViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeConnectStepViewController.h" 32 | 33 | #import "ORKTwentyThreeAndMeConnectStep.h" 34 | 35 | @interface ORKTwentyThreeAndMeConnectStepViewController () 36 | 37 | @property (nonatomic, strong) WKWebView *webView; 38 | 39 | @property (strong, nonatomic) NSMutableData *receivedData; 40 | 41 | @property (nonatomic, strong) NSString *authToken; 42 | 43 | @property (nonatomic, strong) NSString *refreshToken; 44 | 45 | @property (nonatomic) BOOL newUserFlow; 46 | 47 | @end 48 | 49 | @implementation ORKTwentyThreeAndMeConnectStepViewController 50 | 51 | - (ORKTwentyThreeAndMeConnectStep *)connectStep { 52 | return (ORKTwentyThreeAndMeConnectStep *)self.step; 53 | } 54 | 55 | - (void)viewDidLoad { 56 | [super viewDidLoad]; 57 | 58 | WKWebViewConfiguration *wkConfiguration = [[WKWebViewConfiguration alloc] init]; 59 | self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:wkConfiguration]; 60 | self.webView.navigationDelegate = self; 61 | [self.view addSubview:self.webView]; 62 | self.webView.translatesAutoresizingMaskIntoConstraints = NO; 63 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.webView 64 | attribute:NSLayoutAttributeTop 65 | relatedBy:NSLayoutRelationEqual 66 | toItem:self.view 67 | attribute:NSLayoutAttributeTop 68 | multiplier:1.0 69 | constant:0.0]]; 70 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.webView 71 | attribute:NSLayoutAttributeBottom 72 | relatedBy:NSLayoutRelationEqual 73 | toItem:self.view 74 | attribute:NSLayoutAttributeBottom 75 | multiplier:1.0 76 | constant:0.0]]; 77 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.webView 78 | attribute:NSLayoutAttributeLeading 79 | relatedBy:NSLayoutRelationEqual 80 | toItem:self.view 81 | attribute:NSLayoutAttributeLeading 82 | multiplier:1.0 83 | constant:0.0]]; 84 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.webView 85 | attribute:NSLayoutAttributeTrailing 86 | relatedBy:NSLayoutRelationEqual 87 | toItem:self.view 88 | attribute:NSLayoutAttributeTrailing 89 | multiplier:1.0 90 | constant:0.0]]; 91 | 92 | [self loadAuthorizationRequest]; 93 | } 94 | 95 | - (void)loadAuthorizationRequest 96 | { 97 | NSString *signupParams = ([self connectStep].allowedUserMode == ORKTwentyThreeAndMeAllowedUserModeExistingOnly) ? 98 | @"hide_signup=true" : 99 | @"enroll_signup=true"; 100 | NSString *contentURLString = [NSString stringWithFormat:@"%@/authorize/?redirect_uri=%@&client_id=%@&%@&select_profile=true&scope=%@&client_name=%@", [self connectStep].baseURL, [self connectStep].redirectURI, [self connectStep].clientId, signupParams, [self connectStep].scopes, [self connectStep].studyDisplayNameParam]; 101 | NSURL *contentURL = [NSURL URLWithString:contentURLString]; 102 | NSURLRequest *nsRequest=[NSURLRequest requestWithURL:contentURL]; 103 | [self.webView loadRequest:nsRequest]; 104 | } 105 | 106 | #pragma mark - ORKStepResult 107 | 108 | - (ORKStepResult *)result { 109 | ORKStepResult *sResult = [super result]; 110 | 111 | // "Now" is the end time of the result, which is either actually now, 112 | // or the last time we were in the responder chain. 113 | NSDate *now = sResult.endDate; 114 | 115 | NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; 116 | 117 | ORKTwentyThreeAndMeConnectResult *connectResult = [[ORKTwentyThreeAndMeConnectResult alloc] initWithIdentifier:self.step.identifier]; 118 | connectResult.startDate = sResult.startDate; 119 | connectResult.endDate = now; 120 | connectResult.authToken = self.authToken; 121 | connectResult.refreshToken = self.refreshToken; 122 | connectResult.newUserFlow = self.newUserFlow; 123 | 124 | [results addObject:connectResult]; 125 | sResult.results = [results copy]; 126 | 127 | return sResult; 128 | } 129 | 130 | #pragma mark - WebViewDelegate 131 | 132 | - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { 133 | NSURLRequest *request = navigationAction.request; 134 | if ([[[request URL] host] isEqualToString:@"localhost"]) { 135 | // Extract oauth_verifier from URL query 136 | NSString *authCode = nil; 137 | NSString *errorCode = nil; 138 | NSArray* urlParams = [[[request URL] query] componentsSeparatedByString:@"&"]; 139 | for (NSString* param in urlParams) { 140 | NSArray* keyValue = [param componentsSeparatedByString:@"="]; 141 | NSString* key = [keyValue objectAtIndex:0]; 142 | if ([key isEqualToString:@"code"]) { 143 | authCode = [keyValue objectAtIndex:1]; 144 | break; 145 | } 146 | else if([key isEqualToString:@"error"]) { 147 | errorCode = [keyValue objectAtIndex:1]; 148 | break; 149 | } 150 | 151 | if([key isEqualToString:@"new_user"] ) { 152 | id keyValueElement = [keyValue objectAtIndex:1]; 153 | if( [keyValueElement isKindOfClass:[NSString class]] ) { 154 | NSString *newUserParamValue = ((NSString *)keyValueElement).lowercaseString; 155 | if( [newUserParamValue isEqualToString:@"true"] ) 156 | { 157 | self.newUserFlow = YES; 158 | } 159 | } 160 | } 161 | } 162 | 163 | if (authCode) { 164 | NSString *data = [NSString stringWithFormat:@"client_id=%@&client_secret=%@&grant_type=authorization_code&code=%@&redirect_uri=%@&scope=%@", [self connectStep].clientId, [self connectStep].clientSecret, authCode, [self connectStep].redirectURI, [self connectStep].scopes]; 165 | NSString *tokenURL = [NSString stringWithFormat:@"%@/token/", [self connectStep].baseURL]; 166 | NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:tokenURL]]; 167 | [request setHTTPMethod:@"POST"]; 168 | [request setHTTPBody:[data dataUsingEncoding:NSUTF8StringEncoding]]; 169 | 170 | self.receivedData = [[NSMutableData alloc] init]; 171 | NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 172 | [theConnection start]; 173 | } 174 | else if (errorCode && [errorCode isEqualToString:@"access_denied"]) { 175 | [self goForward]; 176 | } 177 | else 178 | { 179 | // Error. 180 | [self goForward]; 181 | } 182 | 183 | decisionHandler(WKNavigationActionPolicyCancel); 184 | } 185 | else { 186 | decisionHandler(WKNavigationActionPolicyAllow); 187 | } 188 | } 189 | 190 | - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error 191 | { 192 | // Error 193 | } 194 | 195 | - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error 196 | { 197 | // Error 198 | } 199 | 200 | #pragma mark - NSURLConnectionDelegate - Handles Code to Token Connection 201 | 202 | -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 203 | { 204 | if( self.receivedData ) { 205 | [self.receivedData appendData:data]; 206 | } 207 | } 208 | 209 | -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 210 | { 211 | // Error 212 | [self goForward]; 213 | } 214 | 215 | -(void)connectionDidFinishLoading:(NSURLConnection *)connection 216 | { 217 | if( self.receivedData ) { 218 | 219 | // DEBUGGING for Parse Issues 220 | const unsigned char *ptr = [self.receivedData bytes]; 221 | NSString *jsonParsed = @""; 222 | for(int i=0; i<[self.receivedData length]; ++i) { 223 | unsigned char c = *ptr++; 224 | jsonParsed = [jsonParsed stringByAppendingFormat:@"%c", c]; 225 | } 226 | 227 | NSError *localError = nil; 228 | NSDictionary *parsedData = [NSJSONSerialization JSONObjectWithData:self.receivedData options:NSJSONReadingAllowFragments error:&localError]; 229 | if( parsedData ) { 230 | self.authToken = parsedData[@"access_token"]; 231 | self.refreshToken = parsedData[@"refresh_token"]; 232 | } 233 | 234 | // Success! 235 | [self goForward]; 236 | } 237 | } 238 | 239 | @end 240 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Intro/ORKTwentyThreeAndMeIntroPage1ViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | ORK_CLASS_AVAILABLE 34 | @interface ORKTwentyThreeAndMeIntroPage1ViewController : UIViewController 35 | 36 | /** 37 | * The display name of the investigator 38 | */ 39 | @property (nonatomic) NSString *investigatorDisplayName; 40 | 41 | /** 42 | * The display name of the study 43 | */ 44 | @property (nonatomic) NSString *studyDisplayName; 45 | 46 | /** 47 | * The contact email for the study 48 | */ 49 | @property (nonatomic) NSString *studyContactEmail; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Intro/ORKTwentyThreeAndMeIntroPage1ViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeIntroPage1ViewController.h" 32 | 33 | #import "UIButton+T23.h" 34 | #import "UILabel+T23.h" 35 | 36 | @interface ORKTwentyThreeAndMeIntroPage1ViewController () 37 | 38 | @end 39 | 40 | @implementation ORKTwentyThreeAndMeIntroPage1ViewController 41 | 42 | - (void)viewDidLoad { 43 | [super viewDidLoad]; 44 | 45 | [self setupAppearance]; 46 | } 47 | 48 | - (void)setupAppearance { 49 | //-------------------- 50 | // Style 51 | self.view.backgroundColor = [UIColor whiteColor]; 52 | 53 | //-------------------- 54 | // 23andMe Logo Image View 55 | UIImage *logoImage = [UIImage imageNamed:@"intro_23andMe_logo" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; 56 | UIImageView *logoImageView = [[UIImageView alloc] initWithImage:logoImage]; 57 | [self.view addSubview:logoImageView]; 58 | logoImageView.translatesAutoresizingMaskIntoConstraints = NO; 59 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:logoImageView 60 | attribute:NSLayoutAttributeTop 61 | relatedBy:NSLayoutRelationEqual 62 | toItem:self.view 63 | attribute:NSLayoutAttributeTop 64 | multiplier:1.0 65 | constant:0.0]]; 66 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:logoImageView 67 | attribute:NSLayoutAttributeCenterX 68 | relatedBy:NSLayoutRelationEqual 69 | toItem:self.view 70 | attribute:NSLayoutAttributeCenterX 71 | multiplier:1.0 72 | constant:15.0]]; 73 | 74 | //-------------------- 75 | // Spacer Above 76 | UIView *spacerAboveDescription = [[UIView alloc] init]; 77 | [self.view addSubview:spacerAboveDescription]; 78 | spacerAboveDescription.translatesAutoresizingMaskIntoConstraints = NO; 79 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:spacerAboveDescription 80 | attribute:NSLayoutAttributeTop 81 | relatedBy:NSLayoutRelationEqual 82 | toItem:logoImageView 83 | attribute:NSLayoutAttributeBottom 84 | multiplier:1.0 85 | constant:0.0]]; 86 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:spacerAboveDescription 87 | attribute:NSLayoutAttributeLeading 88 | relatedBy:NSLayoutRelationEqual 89 | toItem:self.view 90 | attribute:NSLayoutAttributeLeading 91 | multiplier:1.0 92 | constant:0.0]]; 93 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:spacerAboveDescription 94 | attribute:NSLayoutAttributeTrailing 95 | relatedBy:NSLayoutRelationEqual 96 | toItem:self.view 97 | attribute:NSLayoutAttributeTrailing 98 | multiplier:1.0 99 | constant:0.0]]; 100 | 101 | //-------------------- 102 | // Description Label 103 | NSString *descriptionText = [NSString stringWithFormat:ORKLocalizedString(@"TWENTYTHREEANDME_INTRO_1_DESCRIPTION", nil), self.investigatorDisplayName, self.studyDisplayName]; 104 | UILabel *descriptionLabel = [UILabel t23BodyLabelWithText:descriptionText]; 105 | [self.view addSubview:descriptionLabel]; 106 | descriptionLabel.translatesAutoresizingMaskIntoConstraints = NO; 107 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 108 | attribute:NSLayoutAttributeTop 109 | relatedBy:NSLayoutRelationEqual 110 | toItem:spacerAboveDescription 111 | attribute:NSLayoutAttributeBottom 112 | multiplier:1.0 113 | constant:0.0]]; 114 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 115 | attribute:NSLayoutAttributeLeading 116 | relatedBy:NSLayoutRelationEqual 117 | toItem:self.view 118 | attribute:NSLayoutAttributeLeading 119 | multiplier:1.0 120 | constant:15.0]]; 121 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:descriptionLabel 122 | attribute:NSLayoutAttributeTrailing 123 | relatedBy:NSLayoutRelationEqual 124 | toItem:self.view 125 | attribute:NSLayoutAttributeTrailing 126 | multiplier:1.0 127 | constant:-15.0]]; 128 | 129 | //-------------------- 130 | // Spacer Below 131 | UIView *spacerBelowDescription = [[UIView alloc] init]; 132 | [self.view addSubview:spacerBelowDescription]; 133 | spacerBelowDescription.translatesAutoresizingMaskIntoConstraints = NO; 134 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:spacerBelowDescription 135 | attribute:NSLayoutAttributeTop 136 | relatedBy:NSLayoutRelationEqual 137 | toItem:descriptionLabel 138 | attribute:NSLayoutAttributeBottom 139 | multiplier:1.0 140 | constant:0.0]]; 141 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:spacerBelowDescription 142 | attribute:NSLayoutAttributeHeight 143 | relatedBy:NSLayoutRelationEqual 144 | toItem:spacerAboveDescription 145 | attribute:NSLayoutAttributeHeight 146 | multiplier:1.0 147 | constant:0.0]]; 148 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:spacerBelowDescription 149 | attribute:NSLayoutAttributeLeading 150 | relatedBy:NSLayoutRelationEqual 151 | toItem:self.view 152 | attribute:NSLayoutAttributeLeading 153 | multiplier:1.0 154 | constant:0.0]]; 155 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:spacerBelowDescription 156 | attribute:NSLayoutAttributeTrailing 157 | relatedBy:NSLayoutRelationEqual 158 | toItem:self.view 159 | attribute:NSLayoutAttributeTrailing 160 | multiplier:1.0 161 | constant:0.0]]; 162 | 163 | //-------------------- 164 | // Gene Pill Image View 165 | UIImage *genePillImage = [UIImage imageNamed:@"intro_chromosome_green_striped" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; 166 | UIImageView *genePillImageView = [[UIImageView alloc] initWithImage:genePillImage]; 167 | [self.view addSubview:genePillImageView]; 168 | genePillImageView.translatesAutoresizingMaskIntoConstraints = NO; 169 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:genePillImageView 170 | attribute:NSLayoutAttributeTrailing 171 | relatedBy:NSLayoutRelationEqual 172 | toItem:self.view 173 | attribute:NSLayoutAttributeTrailing 174 | multiplier:1.0 175 | constant:0.0]]; 176 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:genePillImageView 177 | attribute:NSLayoutAttributeTop 178 | relatedBy:NSLayoutRelationEqual 179 | toItem:spacerBelowDescription 180 | attribute:NSLayoutAttributeBottom 181 | multiplier:1.0 182 | constant:0.0]]; 183 | 184 | //-------------------- 185 | // Divider View 186 | UIView *dividerView = [[UIView alloc] init]; 187 | dividerView.backgroundColor = [UIColor colorWithRed:227.0/255.0 green:229.0/255.0 blue:230.0/255.0 alpha:1.0]; 188 | [self.view addSubview:dividerView]; 189 | dividerView.translatesAutoresizingMaskIntoConstraints = NO; 190 | [dividerView addConstraint:[NSLayoutConstraint constraintWithItem:dividerView 191 | attribute:NSLayoutAttributeHeight 192 | relatedBy:NSLayoutRelationEqual 193 | toItem:nil 194 | attribute:NSLayoutAttributeNotAnAttribute 195 | multiplier:1.0 196 | constant:1.0]]; 197 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dividerView 198 | attribute:NSLayoutAttributeTop 199 | relatedBy:NSLayoutRelationEqual 200 | toItem:genePillImageView 201 | attribute:NSLayoutAttributeBottom 202 | multiplier:1.0 203 | constant:24.0]]; 204 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dividerView 205 | attribute:NSLayoutAttributeLeading 206 | relatedBy:NSLayoutRelationEqual 207 | toItem:self.view 208 | attribute:NSLayoutAttributeLeading 209 | multiplier:1.0 210 | constant:0.0]]; 211 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dividerView 212 | attribute:NSLayoutAttributeTrailing 213 | relatedBy:NSLayoutRelationEqual 214 | toItem:self.view 215 | attribute:NSLayoutAttributeTrailing 216 | multiplier:1.0 217 | constant:0.0]]; 218 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dividerView 219 | attribute:NSLayoutAttributeBottom 220 | relatedBy:NSLayoutRelationEqual 221 | toItem:self.view 222 | attribute:NSLayoutAttributeBottom 223 | multiplier:1.0 224 | constant:0.0]]; 225 | } 226 | 227 | @end 228 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Intro/ORKTwentyThreeAndMeIntroPage2ViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | ORK_CLASS_AVAILABLE 34 | @interface ORKTwentyThreeAndMeIntroPage2ViewController : UIViewController 35 | 36 | /** 37 | * The display name of the investigator 38 | */ 39 | @property (nonatomic) NSString *investigatorDisplayName; 40 | 41 | /** 42 | * The display name of the study 43 | */ 44 | @property (nonatomic) NSString *studyDisplayName; 45 | 46 | /** 47 | * The contact email for the study 48 | */ 49 | @property (nonatomic) NSString *studyContactEmail; 50 | 51 | /** 52 | * Allowed User Mode for the module 53 | */ 54 | @property (nonatomic) ORKTwentyThreeAndMeAllowedUserMode allowedUserMode; 55 | 56 | /** 57 | * Study Dependency on Module 58 | */ 59 | @property (nonatomic) ORKTwentyThreeAndMeStudyDependency studyDependency; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Intro/ORKTwentyThreeAndMeIntroPage3ViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | ORK_CLASS_AVAILABLE 34 | @interface ORKTwentyThreeAndMeIntroPage3ViewController : UIViewController 35 | 36 | /** 37 | * The display name of the investigator 38 | */ 39 | @property (nonatomic) NSString *investigatorDisplayName; 40 | 41 | /** 42 | * The display name of the study 43 | */ 44 | @property (nonatomic) NSString *studyDisplayName; 45 | 46 | /** 47 | * The contact email for the study 48 | */ 49 | @property (nonatomic) NSString *studyContactEmail; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Intro/ORKTwentyThreeAndMeIntroStep.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | ORK_CLASS_AVAILABLE 34 | @interface ORKTwentyThreeAndMeIntroStep : ORKStep 35 | 36 | /** 37 | * The display name of the investigator 38 | */ 39 | @property (nonatomic, copy, nullable) NSString *investigatorDisplayName; 40 | 41 | /** 42 | * The display name of the study 43 | */ 44 | @property (nonatomic, copy, nullable) NSString *studyDisplayName; 45 | 46 | /** 47 | * The contact email for the study 48 | */ 49 | @property (nonatomic, copy, nullable) NSString *studyContactEmail; 50 | 51 | /** 52 | * Allowed User Mode for the module 53 | */ 54 | @property (nonatomic) ORKTwentyThreeAndMeAllowedUserMode allowedUserMode; 55 | 56 | /** 57 | * Study Dependency on Module 58 | */ 59 | @property (nonatomic) ORKTwentyThreeAndMeStudyDependency studyDependency; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Intro/ORKTwentyThreeAndMeIntroStep.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeIntroStep.h" 32 | 33 | #import "ORKTwentyThreeAndMeIntroViewController.h" 34 | 35 | @implementation ORKTwentyThreeAndMeIntroStep 36 | 37 | + (Class)stepViewControllerClass { 38 | return [ORKTwentyThreeAndMeIntroViewController class]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Intro/ORKTwentyThreeAndMeIntroViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | ORK_CLASS_AVAILABLE 34 | @interface ORKTwentyThreeAndMeIntroViewController : ORKStepViewController 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/Steps/Intro/ORKTwentyThreeAndMeIntroViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeIntroViewController.h" 32 | 33 | #import "UIButton+T23.h" 34 | #import "UILabel+T23.h" 35 | #import "ORKTwentyThreeAndMeIntroStep.h" 36 | #import "ORKTwentyThreeAndMeIntroPage1ViewController.h" 37 | #import "ORKTwentyThreeAndMeIntroPage2ViewController.h" 38 | #import "ORKTwentyThreeAndMeIntroPage3ViewController.h" 39 | 40 | 41 | @interface ORKTwentyThreeAndMeIntroViewController() 42 | 43 | @property (nonatomic) UIPageViewController *pageViewController; 44 | 45 | @property (nonatomic) NSArray *pages; 46 | 47 | @property (nonatomic) NSString *investigatorDisplayName; 48 | @property (nonatomic) NSString *studyDisplayName; 49 | @property (nonatomic) NSString *studyContactEmail; 50 | @property (nonatomic) ORKTwentyThreeAndMeAllowedUserMode allowedUserMode; 51 | @property (nonatomic) ORKTwentyThreeAndMeStudyDependency studyDependency; 52 | 53 | @end 54 | 55 | @implementation ORKTwentyThreeAndMeIntroViewController 56 | 57 | - (ORKTwentyThreeAndMeIntroStep *)introStep { 58 | return (ORKTwentyThreeAndMeIntroStep *)self.step; 59 | } 60 | 61 | - (void)viewDidLoad { 62 | [super viewDidLoad]; 63 | 64 | ORKTwentyThreeAndMeIntroStep *introStep = [self introStep]; 65 | self.investigatorDisplayName = introStep.investigatorDisplayName; 66 | self.studyDisplayName = introStep.studyDisplayName; 67 | self.studyContactEmail = introStep.studyContactEmail; 68 | self.allowedUserMode = introStep.allowedUserMode; 69 | self.studyDependency = introStep.studyDependency; 70 | 71 | ORKTwentyThreeAndMeIntroPage1ViewController *pageVC1 = [[ORKTwentyThreeAndMeIntroPage1ViewController alloc] init]; 72 | pageVC1.investigatorDisplayName = self.investigatorDisplayName; 73 | pageVC1.studyDisplayName = self.studyDisplayName; 74 | pageVC1.studyContactEmail = self.studyContactEmail; 75 | ORKTwentyThreeAndMeIntroPage2ViewController *pageVC2 = [[ORKTwentyThreeAndMeIntroPage2ViewController alloc] init]; 76 | pageVC2.investigatorDisplayName = self.investigatorDisplayName; 77 | pageVC2.studyDisplayName = self.studyDisplayName; 78 | pageVC2.studyContactEmail = self.studyContactEmail; 79 | pageVC2.allowedUserMode = self.allowedUserMode; 80 | pageVC2.studyDependency = self.studyDependency; 81 | ORKTwentyThreeAndMeIntroPage3ViewController *pageVC3 = [[ORKTwentyThreeAndMeIntroPage3ViewController alloc] init]; 82 | pageVC3.investigatorDisplayName = self.investigatorDisplayName; 83 | pageVC3.studyDisplayName = self.studyDisplayName; 84 | pageVC3.studyContactEmail = self.studyContactEmail; 85 | self.pages = @[pageVC1, pageVC2, pageVC3]; 86 | 87 | [self setupAppearance]; 88 | 89 | [self.pageViewController setViewControllers:@[pageVC1] 90 | direction:UIPageViewControllerNavigationDirectionForward 91 | animated:NO 92 | completion:nil]; 93 | 94 | self.cancelButtonItem = nil; 95 | self.backButtonItem = nil; 96 | } 97 | 98 | - (void)shareButtonPressed:(UIButton *)sender { 99 | [self goForward]; 100 | } 101 | 102 | - (void)declineButtonPressed:(UIButton *)sender { 103 | NSString *alertMessage = [NSString stringWithFormat:ORKLocalizedString(@"TWENTYTHREEANDME_DECLINE_PROMPT_DETAILS", nil), self.studyDisplayName]; 104 | UIAlertController *alertViewController = [UIAlertController alertControllerWithTitle:nil 105 | message:alertMessage 106 | preferredStyle:UIAlertControllerStyleAlert]; 107 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:ORKLocalizedString(@"TWENTYTHREEANDME_DECLINE_PROMPT_ACTION_CANCEL", nil) 108 | style:UIAlertActionStyleDefault 109 | handler:nil]; 110 | UIAlertAction *declineAction = [UIAlertAction actionWithTitle:ORKLocalizedString(@"TWENTYTHREEANDME_DECLINE_PROMPT_ACTION_DECLINE", nil) 111 | style:UIAlertActionStyleDefault 112 | handler:^(UIAlertAction * _Nonnull action) { 113 | [self.taskViewController.delegate taskViewController:self.taskViewController didFinishWithReason:ORKTaskViewControllerFinishReasonDiscarded error:nil]; 114 | 115 | }]; 116 | [alertViewController addAction:cancelAction]; 117 | [alertViewController addAction:declineAction]; 118 | [self presentViewController:alertViewController animated:YES completion:nil]; 119 | } 120 | 121 | - (void)setupAppearance { 122 | //-------------------- 123 | // Style 124 | self.view.backgroundColor = [UIColor whiteColor]; 125 | 126 | //-------------------- 127 | // Page View Controller Control Appearance 128 | UIPageControl *pageControl = nil; 129 | if( [UIPageControl instancesRespondToSelector:@selector(appearanceWhenContainedInInstancesOfClasses:)] ) { 130 | pageControl = [UIPageControl appearanceWhenContainedInInstancesOfClasses:@[[ORKTwentyThreeAndMeIntroViewController class]]]; 131 | } 132 | else { 133 | pageControl = [UIPageControl appearance]; 134 | } 135 | pageControl.pageIndicatorTintColor = [UIColor lightGrayColor]; 136 | pageControl.currentPageIndicatorTintColor = [UIColor colorWithRed:51.0/255.0 green:52.0/255.0 blue:53.0/255.0 alpha:1.0]; 137 | pageControl.backgroundColor = [UIColor whiteColor]; 138 | 139 | //-------------------- 140 | // Page View Controller 141 | self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll 142 | navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal 143 | options:nil]; 144 | self.pageViewController.delegate = self; 145 | self.pageViewController.dataSource = self; 146 | [self addChildViewController:self.pageViewController]; 147 | [self.view addSubview:self.pageViewController.view]; 148 | [self.pageViewController didMoveToParentViewController:self]; 149 | 150 | self.pageViewController.view.translatesAutoresizingMaskIntoConstraints = NO; 151 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.pageViewController.view 152 | attribute:NSLayoutAttributeTop 153 | relatedBy:NSLayoutRelationEqual 154 | toItem:self.view 155 | attribute:NSLayoutAttributeTop 156 | multiplier:1.0 157 | constant:0.0]]; 158 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.pageViewController.view 159 | attribute:NSLayoutAttributeLeading 160 | relatedBy:NSLayoutRelationEqual 161 | toItem:self.view 162 | attribute:NSLayoutAttributeLeading 163 | multiplier:1.0 164 | constant:0.0]]; 165 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.pageViewController.view 166 | attribute:NSLayoutAttributeTrailing 167 | relatedBy:NSLayoutRelationEqual 168 | toItem:self.view 169 | attribute:NSLayoutAttributeTrailing 170 | multiplier:1.0 171 | constant:0.0]]; 172 | 173 | //-------------------- 174 | // Share Button 175 | UIButton *shareButton = [UIButton t23ButtonWithText:ORKLocalizedString(@"TWENTYTHREEANDME_INTRO_MAIN_SHARE", nil) andHasBorder:YES]; 176 | [self.view addSubview:shareButton]; 177 | [shareButton addTarget:self action:@selector(shareButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 178 | shareButton.translatesAutoresizingMaskIntoConstraints = NO; 179 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:shareButton 180 | attribute:NSLayoutAttributeTop 181 | relatedBy:NSLayoutRelationEqual 182 | toItem:self.pageViewController.view 183 | attribute:NSLayoutAttributeBottom 184 | multiplier:1.0 185 | constant:0.0]]; 186 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:shareButton 187 | attribute:NSLayoutAttributeCenterX 188 | relatedBy:NSLayoutRelationEqual 189 | toItem:self.view 190 | attribute:NSLayoutAttributeCenterX 191 | multiplier:1.0 192 | constant:0.0]]; 193 | 194 | //-------------------- 195 | // Decline Button 196 | UIButton *declineButton = [UIButton t23ButtonWithText:ORKLocalizedString(@"TWENTYTHREEANDME_INTRO_MAIN_DECLINE", nil) andHasBorder:NO]; 197 | [self.view addSubview:declineButton]; 198 | [declineButton addTarget:self action:@selector(declineButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 199 | declineButton.translatesAutoresizingMaskIntoConstraints = NO; 200 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:declineButton 201 | attribute:NSLayoutAttributeTop 202 | relatedBy:NSLayoutRelationEqual 203 | toItem:shareButton 204 | attribute:NSLayoutAttributeBottom 205 | multiplier:1.0 206 | constant:0.0]]; 207 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:declineButton 208 | attribute:NSLayoutAttributeCenterX 209 | relatedBy:NSLayoutRelationEqual 210 | toItem:self.view 211 | attribute:NSLayoutAttributeCenterX 212 | multiplier:1.0 213 | constant:0.0]]; 214 | 215 | //-------------------- 216 | // Bottom 217 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:declineButton 218 | attribute:NSLayoutAttributeBottom 219 | relatedBy:NSLayoutRelationEqual 220 | toItem:self.view 221 | attribute:NSLayoutAttributeBottom 222 | multiplier:1.0 223 | constant:0.0]]; 224 | } 225 | 226 | - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController 227 | viewControllerBeforeViewController:(UIViewController *)viewController { 228 | NSInteger indexOfCurrentPage = (NSInteger)[self.pages indexOfObject:viewController]; 229 | if( indexOfCurrentPage - 1 >= 0 ) { 230 | return self.pages[indexOfCurrentPage - 1]; 231 | } 232 | 233 | return nil; 234 | } 235 | 236 | - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController 237 | viewControllerAfterViewController:(UIViewController *)viewController { 238 | NSInteger indexOfCurrentPage = (NSInteger)[self.pages indexOfObject:viewController]; 239 | if( indexOfCurrentPage + 1 < [self.pages count] ) { 240 | return self.pages[indexOfCurrentPage + 1]; 241 | } 242 | 243 | return nil; 244 | } 245 | 246 | - (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController { 247 | return [self.pages count]; 248 | } 249 | 250 | - (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController { 251 | 252 | UIViewController *currentPageViewController = [pageViewController.viewControllers firstObject]; 253 | if( currentPageViewController ) { 254 | return [self.pages indexOfObject:currentPageViewController]; 255 | 256 | } 257 | return 0; 258 | } 259 | 260 | 261 | @end -------------------------------------------------------------------------------- /TwentyThreeAndMe/Tasks/ORKTwentyThreeAndMeConnectTaskViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | NS_ASSUME_NONNULL_BEGIN 34 | 35 | @class ORKTwentyThreeAndMeConnectTaskViewController; 36 | 37 | /** 38 | The task view controller delegate is responsible for processing the results 39 | of the task, exerting some control over how the controller behaves, and providing 40 | auxiliary content as needed. 41 | */ 42 | @protocol ORKTwentyThreeAndMeConnectTaskViewControllerDelegate 43 | 44 | /** 45 | Tells the delegate that the task has finished. 46 | */ 47 | - (void)twentyThreeAndMeConnectTaskViewController:(ORKTwentyThreeAndMeConnectTaskViewController *)twentyThreeAndMeConnectTaskViewController 48 | didFinishWithResults:(NSDictionary *)results 49 | error:(nullable NSError *)error; 50 | 51 | @end 52 | 53 | /** 54 | * 55 | */ 56 | ORK_CLASS_AVAILABLE 57 | @interface ORKTwentyThreeAndMeConnectTaskViewController : ORKTaskViewController 58 | 59 | /** 60 | The delegate for the connect task view controller. 61 | */ 62 | @property (nonatomic, weak, nullable) id twentyThreeAndMeConnectDelegate; 63 | 64 | /** 65 | * Returns a predefined task view controller that connects a participant with 23andMe 66 | * Questions/Help: researchkit@23andme.com 67 | * 68 | * @param identifier Task identifier 69 | * @param allowedUserMode Identify the type of users to allow for the module 70 | * @param studyDependency Whether the study requires the module to be succesfully completed. Changes flow/text. 71 | * @param clientId oauth client id 72 | * @param clientSecret oauth client secret 73 | * @param scopes oauth scopes string (will be url encoded) 74 | * @param investigatorDisplayName User facing investigator name 75 | * @param studyDisplayName User facing study name 76 | * @param studyContactEmail Study contact email used in module 77 | * 78 | * @return ORKTwentyThreeAndMeConnectTaskViewController 79 | */ 80 | + (ORKTwentyThreeAndMeConnectTaskViewController *)twentyThreeAndMeTaskViewControllerWithIdentifier:(NSString *)identifier 81 | allowedUserMode:(ORKTwentyThreeAndMeAllowedUserMode)allowedUserMode 82 | studyDependency:(ORKTwentyThreeAndMeStudyDependency)studyDependency 83 | authClientId:(NSString *)clientId 84 | authClientSecret:(NSString *)clientSecret 85 | authScopes:(NSString *)scopes 86 | investigatorDisplayName:(NSString *)investigatorDisplayName 87 | studyDisplayName:(NSString *)studyDisplayName 88 | studyContactEmail:(NSString *)studyContactEmail 89 | baseURLOverride:(nullable NSString *)baseURLOverride; 90 | 91 | @end 92 | 93 | NS_ASSUME_NONNULL_END -------------------------------------------------------------------------------- /TwentyThreeAndMe/Tasks/ORKTwentyThreeAndMeConnectTaskViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "ORKTwentyThreeAndMeConnectTaskViewController.h" 32 | 33 | #import "ORKOrderedTask+TwentyThreeAndMe.h" 34 | #import "ORKResult+TwentyThreeAndMe.h" 35 | 36 | @interface ORKTwentyThreeAndMeConnectTaskViewController () 37 | 38 | @end 39 | 40 | @implementation ORKTwentyThreeAndMeConnectTaskViewController 41 | 42 | + (ORKTwentyThreeAndMeConnectTaskViewController *)twentyThreeAndMeTaskViewControllerWithIdentifier:(NSString *)identifier 43 | allowedUserMode:(ORKTwentyThreeAndMeAllowedUserMode)allowedUserMode 44 | studyDependency:(ORKTwentyThreeAndMeStudyDependency)studyDependency 45 | authClientId:(NSString *)clientId 46 | authClientSecret:(NSString *)clientSecret 47 | authScopes:(NSString *)scopes 48 | investigatorDisplayName:(NSString *)investigatorDisplayName 49 | studyDisplayName:(NSString *)studyDisplayName 50 | studyContactEmail:(NSString *)studyContactEmail 51 | baseURLOverride:(nullable NSString *)baseURLOverride { 52 | ORKOrderedTask *ttamTask = [ORKOrderedTask twentyThreeAndMeTaskWithIdentifier:identifier 53 | allowedUserMode:allowedUserMode 54 | studyDependency:studyDependency 55 | authClientId:clientId 56 | authClientSecret:clientSecret 57 | authScopes:scopes 58 | investigatorDisplayName:investigatorDisplayName 59 | studyDisplayName:studyDisplayName 60 | studyContactEmail:studyContactEmail 61 | baseURLOverride:baseURLOverride]; 62 | 63 | ORKTwentyThreeAndMeConnectTaskViewController *ttamTaskViewController = [[ORKTwentyThreeAndMeConnectTaskViewController alloc] initWithTask:ttamTask 64 | taskRunUUID:nil]; 65 | ttamTaskViewController.delegate = ttamTaskViewController; 66 | ttamTaskViewController.showsProgressInNavigationBar = NO; 67 | 68 | return ttamTaskViewController; 69 | } 70 | 71 | #pragma mark Protocol ORKTaskViewControllerDelegate 72 | 73 | - (void)taskViewController:(ORKTaskViewController *)taskViewController 74 | didFinishWithReason:(ORKTaskViewControllerFinishReason)reason 75 | error:(nullable NSError *)error { 76 | NSMutableDictionary *resultDict = [NSMutableDictionary dictionary]; 77 | if( reason == ORKTaskViewControllerFinishReasonDiscarded ) { 78 | if( self.twentyThreeAndMeConnectDelegate ) { 79 | [resultDict setObject:@"cancelled" forKey:@"completionType"]; 80 | [self.twentyThreeAndMeConnectDelegate twentyThreeAndMeConnectTaskViewController:self didFinishWithResults:resultDict error:nil]; 81 | } 82 | } 83 | else if( reason == ORKTaskViewControllerFinishReasonCompleted ) { 84 | if( self.twentyThreeAndMeConnectDelegate ) { 85 | ORKTaskResult *taskResult = [taskViewController result]; 86 | ORKCollectionResult *connectResultCollection = (ORKCollectionResult *)[taskResult resultForIdentifier:@"twentyThreeAndMe.connect"]; 87 | ORKTwentyThreeAndMeConnectResult *connectResult = (ORKTwentyThreeAndMeConnectResult *)[connectResultCollection.results firstObject]; 88 | if( connectResult ) { 89 | [resultDict setObject:connectResult.authToken forKey:@"authToken"]; 90 | [resultDict setObject:connectResult.refreshToken forKey:@"refreshToken"]; 91 | } 92 | 93 | [resultDict setObject:@"success" forKey:@"completionType"]; 94 | [self.twentyThreeAndMeConnectDelegate twentyThreeAndMeConnectTaskViewController:self didFinishWithResults:resultDict error:nil]; 95 | } 96 | } 97 | } 98 | 99 | - (void)taskViewController:(ORKTaskViewController *)taskViewController stepViewControllerWillAppear:(ORKStepViewController *)stepViewController { 100 | [stepViewController.backButtonItem setTintColor:[UIColor colorWithRed:146.0/255.0 green:199.0/255.0 blue:70.0/255.0 alpha:1.0]]; 101 | [stepViewController.cancelButtonItem setTintColor:[UIColor colorWithRed:146.0/255.0 green:199.0/255.0 blue:70.0/255.0 alpha:1.0]]; 102 | } 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/UIHelpers/UIButton+T23.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | 32 | #import 33 | 34 | @interface UIButton (T23) 35 | 36 | /** 37 | * Helper to build a styled button for 23andMe module content 38 | * 39 | * @param text Button Text string 40 | * @param hasBorder Whether this button should have a styled border 41 | * 42 | * @return UIButton 43 | */ 44 | + (UIButton *)t23ButtonWithText:(NSString *)text andHasBorder:(BOOL)hasBorder; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/UIHelpers/UIButton+T23.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "UIButton+T23.h" 32 | 33 | @implementation UIButton (T23) 34 | 35 | + (UIButton *)t23ButtonWithText:(NSString *)text andHasBorder:(BOOL)hasBorder { 36 | UIButton *button = [[UIButton alloc] init]; 37 | [button setTitle:text forState:UIControlStateNormal]; 38 | button.titleLabel.font = [UIFont systemFontOfSize:16.0]; 39 | UIColor *t23ButtonGreen = [UIColor colorWithRed:146.0/255.0 green:199.0/255.0 blue:70.0/255.0 alpha:1.0]; 40 | [button setTitleColor:t23ButtonGreen forState:UIControlStateNormal]; 41 | button.contentEdgeInsets = UIEdgeInsetsMake(0.0, 24.0, 0.0, 24.0); 42 | if( hasBorder ) { 43 | button.layer.cornerRadius = 3.0; 44 | button.layer.borderColor = t23ButtonGreen.CGColor; 45 | button.layer.borderWidth = 1.0; 46 | } 47 | button.translatesAutoresizingMaskIntoConstraints = NO; 48 | [button addConstraint:[NSLayoutConstraint constraintWithItem:button 49 | attribute:NSLayoutAttributeHeight 50 | relatedBy:NSLayoutRelationEqual 51 | toItem:nil 52 | attribute:NSLayoutAttributeNotAnAttribute 53 | multiplier:1.0 54 | constant:45.0]]; 55 | return button; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/UIHelpers/UILabel+T23.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import 32 | 33 | @interface UILabel (T23) 34 | 35 | /** 36 | * Helper to generate styled labels for 23andMe module 37 | * 38 | * @param text Text for label to display 39 | * 40 | * @return Styled UILabel 41 | */ 42 | + (UILabel *)t23HeaderLabelWithText:(NSString *)text; 43 | 44 | /** 45 | * Helper to generate styled labels for 23andMe module 46 | * 47 | * @param text Text for label to display 48 | * 49 | * @return Styled UILabel 50 | */ 51 | + (UILabel *)t23SubheaderLabelWithText:(NSString *)text; 52 | 53 | /** 54 | * Helper to generate styled labels for 23andMe module 55 | * 56 | * @param text Text for label to display 57 | * 58 | * @return Styled UILabel 59 | */ 60 | + (UILabel *)t23BodyLabelWithText:(NSString *)text; 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /TwentyThreeAndMe/UIHelpers/UILabel+T23.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, 23andMe, Inc. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder(s) nor the names of any contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. No license is granted to the trademarks of 17 | the copyright holders even if such marks are included in this software. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #import "UILabel+T23.h" 32 | 33 | @implementation UILabel (T23) 34 | 35 | + (UILabel *)t23HeaderLabelWithText:(NSString *)text 36 | { 37 | UILabel *label = [[UILabel alloc] init]; 38 | if( [UIFont instancesRespondToSelector:@selector(systemFontOfSize:weight:)] ) { 39 | label.font = [UIFont systemFontOfSize:22.0 weight:UIFontWeightSemibold]; 40 | } 41 | else { 42 | label.font = [UIFont boldSystemFontOfSize:22.0]; 43 | } 44 | label.numberOfLines = 1; 45 | label.textColor = [UIColor colorWithRed:51.0/255.0 green:52.0/255.0 blue:53.0/255.0 alpha:1.0]; 46 | label.text = text; 47 | label.textAlignment = NSTextAlignmentCenter; 48 | return label; 49 | } 50 | 51 | + (UILabel *)t23SubheaderLabelWithText:(NSString *)text 52 | { 53 | UILabel *label = [[UILabel alloc] init]; 54 | if( [UIFont instancesRespondToSelector:@selector(systemFontOfSize:weight:)] ) { 55 | label.font = [UIFont systemFontOfSize:16.0 weight:UIFontWeightSemibold]; 56 | } 57 | else { 58 | label.font = [UIFont boldSystemFontOfSize:16.0]; 59 | } 60 | label.numberOfLines = 1; 61 | label.textColor = [UIColor colorWithRed:51.0/255.0 green:52.0/255.0 blue:53.0/255.0 alpha:1.0]; 62 | label.text = text; 63 | label.textAlignment = NSTextAlignmentLeft; 64 | return label; 65 | } 66 | 67 | + (UILabel *)t23BodyLabelWithText:(NSString *)text 68 | { 69 | UILabel *label = [[UILabel alloc] init]; 70 | label.font = [UIFont systemFontOfSize:16.0]; 71 | label.numberOfLines = 0; 72 | label.textColor = [UIColor colorWithRed:51.0/255.0 green:52.0/255.0 blue:53.0/255.0 alpha:1.0]; 73 | label.text = text; 74 | label.textAlignment = NSTextAlignmentLeft; 75 | return label; 76 | } 77 | 78 | @end 79 | --------------------------------------------------------------------------------