diff --git a/CordovaLib/Classes/Public/CDVViewController.h b/CordovaLib/Classes/Public/CDVViewController.h index 24072ae25..4b5e423a4 100644 --- a/CordovaLib/Classes/Public/CDVViewController.h +++ b/CordovaLib/Classes/Public/CDVViewController.h @@ -62,7 +62,7 @@ - (NSString*)appURLScheme; - (NSURL*)errorURL; -- (UIColor*)colorFromColorString:(NSString*)colorString; +- (UIColor*)colorFromColorString:(NSString*)colorString CDV_DEPRECATED(7.0.0, "Use BackgroundColor in xcassets"); - (NSArray*)parseInterfaceOrientations:(NSArray*)orientations; - (BOOL)supportsOrientation:(UIInterfaceOrientation)orientation; diff --git a/CordovaLib/Classes/Public/CDVViewController.m b/CordovaLib/Classes/Public/CDVViewController.m index 552c06ddf..0d7eb8b7b 100644 --- a/CordovaLib/Classes/Public/CDVViewController.m +++ b/CordovaLib/Classes/Public/CDVViewController.m @@ -333,8 +333,7 @@ - (void)viewDidLoad } // ///////////////// - NSString* bgColorString = [self.settings cordovaSettingForKey:@"BackgroundColor"]; - UIColor* bgColor = [self colorFromColorString:bgColorString]; + UIColor* bgColor = [UIColor colorNamed:@"BackgroundColor"] ?: UIColor.whiteColor; [self.launchView setBackgroundColor:bgColor]; [self.webView setBackgroundColor:bgColor]; } @@ -522,14 +521,13 @@ - (void)createLaunchView webViewBounds.origin = self.view.bounds.origin; UIView* view = [[UIView alloc] initWithFrame:webViewBounds]; - view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); NSString* launchStoryboardName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchStoryboardName"]; if (launchStoryboardName != nil) { UIStoryboard* storyboard = [UIStoryboard storyboardWithName:launchStoryboardName bundle:[NSBundle mainBundle]]; UIViewController* vc = [storyboard instantiateInitialViewController]; - [view addSubview:[vc.view snapshotViewAfterScreenUpdates:true]]; + [view addSubview:vc.view]; } self.launchView = view; diff --git a/bin/templates/project/__PROJECT_NAME__/CDVLaunchScreen.storyboard b/bin/templates/project/__PROJECT_NAME__/CDVLaunchScreen.storyboard index 2d2e99e0c..924392e34 100644 --- a/bin/templates/project/__PROJECT_NAME__/CDVLaunchScreen.storyboard +++ b/bin/templates/project/__PROJECT_NAME__/CDVLaunchScreen.storyboard @@ -22,6 +22,7 @@ + @@ -41,7 +42,7 @@ - + @@ -57,5 +58,8 @@ + + + diff --git a/bin/templates/project/__PROJECT_NAME__/Images.xcassets/BackgroundColor.colorset/Contents.json b/bin/templates/project/__PROJECT_NAME__/Images.xcassets/BackgroundColor.colorset/Contents.json new file mode 100644 index 000000000..462830f8c --- /dev/null +++ b/bin/templates/project/__PROJECT_NAME__/Images.xcassets/BackgroundColor.colorset/Contents.json @@ -0,0 +1,15 @@ +{ + "colors" : [ + { + "color" : { + "platform" : "ios", + "reference" : "systemBackgroundColor" + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/bin/templates/scripts/cordova/lib/prepare.js b/bin/templates/scripts/cordova/lib/prepare.js index ffa444069..5758ec2cd 100644 --- a/bin/templates/scripts/cordova/lib/prepare.js +++ b/bin/templates/scripts/cordova/lib/prepare.js @@ -51,6 +51,7 @@ module.exports.prepare = function (cordovaProject, options) { .then(() => { updateIcons(cordovaProject, this.locations); updateLaunchStoryboardImages(cordovaProject, this.locations); + updateBackgroundColor(cordovaProject, this.locations); updateFileResources(cordovaProject, this.locations); }) .then(() => { @@ -79,6 +80,7 @@ module.exports.clean = function (options) { cleanWww(projectRoot, this.locations); cleanIcons(projectRoot, projectConfig, this.locations); cleanLaunchStoryboardImages(projectRoot, projectConfig, this.locations); + cleanBackgroundColor(projectRoot, projectConfig, this.locations); cleanFileResources(projectRoot, projectConfig, this.locations); }); }; @@ -398,6 +400,123 @@ function cleanIcons (projectRoot, projectConfig, locations) { } } +/** + * Returns the directory for the BackgroundColor.colorset asset, or null if no + * xcassets exist. + * + * @param {string} projectRoot The project's root directory + * @param {string} platformProjDir The platform's project directory + */ +function getBackgroundColorDir (projectRoot, platformProjDir) { + if (folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'))) { + return path.join(platformProjDir, 'Images.xcassets', 'BackgroundColor.colorset'); + } else { + return null; + } +} + +function colorPreferenceToComponents (pref) { + if (!pref || !pref.match(/^(#[0-9A-F]{3}|(0x|#)([0-9A-F]{2})?[0-9A-F]{6})$/)) { + return { + platform: 'ios', + reference: 'systemBackgroundColor' + }; + } + + let red = 'FF'; + let green = 'FF'; + let blue = 'FF'; + let alpha = 1.0; + + if (pref[0] === '#' && pref.length === 4) { + red = pref[1] + pref[1]; + green = pref[2] + pref[2]; + blue = pref[3] + pref[3]; + } + + if (pref.length >= 7 && (pref[0] === '#' || pref.substring(0, 2) === '0x')) { + let offset = pref[0] === '#' ? 1 : 2; + + if (pref.substring(offset).length === 8) { + alpha = parseInt(pref.substring(offset, offset + 2), 16) / 255.0; + offset += 2; + } + + red = pref.substring(offset, offset + 2); + green = pref.substring(offset + 2, offset + 4); + blue = pref.substring(offset + 4, offset + 6); + } + + return { + 'color-space': 'srgb', + components: { + red: '0x' + red, + green: '0x' + green, + blue: '0x' + blue, + alpha: alpha.toFixed(3) + } + }; +} + +/** + * Update the background color Contents.json in xcassets. + * + * @param {Object} cordovaProject The cordova project + * @param {Object} locations A dictionary containing useful location paths + */ +function updateBackgroundColor (cordovaProject, locations) { + const pref = cordovaProject.projectConfig.getPreference('BackgroundColor', 'ios') || ''; + + const platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj); + const backgroundColorDir = getBackgroundColorDir(cordovaProject.root, platformProjDir); + + if (backgroundColorDir) { + const contentsJSON = { + colors: [{ + idiom: 'universal', + color: colorPreferenceToComponents(pref) + }], + info: { + author: 'Xcode', + version: 1 + } + }; + + events.emit('verbose', 'Updating Background Color color set Contents.json'); + fs.writeFileSync(path.join(cordovaProject.root, backgroundColorDir, 'Contents.json'), + JSON.stringify(contentsJSON, null, 2)); + } +} + +/** + * Resets the background color Contents.json in xcassets to default. + * + * @param {string} projectRoot Path to the project root + * @param {Object} projectConfig The project's config.xml + * @param {Object} locations A dictionary containing useful location paths + */ +function cleanBackgroundColor (projectRoot, projectConfig, locations) { + const platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj); + const backgroundColorDir = getBackgroundColorDir(projectRoot, platformProjDir); + + if (backgroundColorDir) { + const contentsJSON = { + colors: [{ + idiom: 'universal', + color: colorPreferenceToComponents(null) + }], + info: { + author: 'Xcode', + version: 1 + } + }; + + events.emit('verbose', 'Cleaning Background Color color set Contents.json'); + fs.writeFileSync(path.join(projectRoot, backgroundColorDir, 'Contents.json'), + JSON.stringify(contentsJSON, null, 2)); + } +} + function updateFileResources (cordovaProject, locations) { const platformDir = path.relative(cordovaProject.root, locations.root); const files = cordovaProject.projectConfig.getFileResources('ios'); diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/BackgroundColor.colorset/Contents.json b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/BackgroundColor.colorset/Contents.json new file mode 100644 index 000000000..462830f8c --- /dev/null +++ b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/BackgroundColor.colorset/Contents.json @@ -0,0 +1,15 @@ +{ + "colors" : [ + { + "color" : { + "platform" : "ios", + "reference" : "systemBackgroundColor" + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/Contents.json b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/Contents.json index da4a164c9..2d92bd53f 100644 --- a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/Contents.json +++ b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/Contents.json @@ -3,4 +3,4 @@ "version" : 1, "author" : "xcode" } -} \ No newline at end of file +} diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Contents.json b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Contents.json deleted file mode 100644 index 175f378c6..000000000 --- a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Contents.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "images" : [ - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "Default-736h.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "Default-Landscape-736h.png", - "minimum-system-version" : "8.0", - "orientation" : "landscape", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "667h", - "filename" : "Default-667h.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "filename" : "Default@2x~iphone.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "retina4", - "filename" : "Default-568h@2x~iphone.png", - "minimum-system-version" : "7.0", - "orientation" : "portrait", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "filename" : "Default-Portrait~ipad.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "filename" : "Default-Landscape~ipad.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "filename" : "Default-Portrait@2x~ipad.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "filename" : "Default-Landscape@2x~ipad.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "filename" : "Default~iphone.png", - "extent" : "full-screen", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "filename" : "Default@2x~iphone.png", - "extent" : "full-screen", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "filename" : "Default-568h@2x~iphone.png", - "extent" : "full-screen", - "subtype" : "retina4", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "to-status-bar", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "filename" : "Default-Portrait~ipad.png", - "extent" : "full-screen", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "to-status-bar", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "to-status-bar", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "filename" : "Default-Portrait@2x~ipad.png", - "extent" : "full-screen", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "to-status-bar", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-568h@2x~iphone.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-568h@2x~iphone.png deleted file mode 100644 index 10ed683c5..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-568h@2x~iphone.png and /dev/null differ diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-667h.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-667h.png deleted file mode 100644 index d9bcf61d5..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-667h.png and /dev/null differ diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-736h.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-736h.png deleted file mode 100644 index 1fcef229f..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-736h.png and /dev/null differ diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h.png deleted file mode 100644 index eae0792db..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h.png and /dev/null differ diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x~ipad.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x~ipad.png deleted file mode 100644 index 1fc8c7dbf..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x~ipad.png and /dev/null differ diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Landscape~ipad.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Landscape~ipad.png deleted file mode 100644 index 58ea2fbd3..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Landscape~ipad.png and /dev/null differ diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x~ipad.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x~ipad.png deleted file mode 100644 index 1570b37d5..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x~ipad.png and /dev/null differ diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Portrait~ipad.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Portrait~ipad.png deleted file mode 100644 index 223e75d08..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default-Portrait~ipad.png and /dev/null differ diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png deleted file mode 100644 index 0098dc73a..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png and /dev/null differ diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default~iphone.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default~iphone.png deleted file mode 100644 index 42b8fdea5..000000000 Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Images.xcassets/LaunchImage.launchimage/Default~iphone.png and /dev/null differ diff --git a/tests/spec/unit/prepare.spec.js b/tests/spec/unit/prepare.spec.js index 3aa601e91..a1ec9fdb4 100644 --- a/tests/spec/unit/prepare.spec.js +++ b/tests/spec/unit/prepare.spec.js @@ -343,6 +343,107 @@ describe('prepare', () => { }); }); + describe('colorPreferenceToComponents', () => { + const colorPreferenceToComponents = prepare.__get__('colorPreferenceToComponents'); + + it('should handle #FAB', () => { + expect(colorPreferenceToComponents('#FAB')).toEqual(jasmine.objectContaining({ + components: { + red: '0xFF', + green: '0xAA', + blue: '0xBB', + alpha: '1.000' + } + })); + }); + + it('should handle #FFAABB', () => { + expect(colorPreferenceToComponents('#FFAABB')).toEqual(jasmine.objectContaining({ + components: { + red: '0xFF', + green: '0xAA', + blue: '0xBB', + alpha: '1.000' + } + })); + }); + + it('should handle 0xFFAABB', () => { + expect(colorPreferenceToComponents('0xFFAABB')).toEqual(jasmine.objectContaining({ + components: { + red: '0xFF', + green: '0xAA', + blue: '0xBB', + alpha: '1.000' + } + })); + }); + + it('should handle #99FFAABB', () => { + expect(colorPreferenceToComponents('#99FFAABB')).toEqual(jasmine.objectContaining({ + components: { + red: '0xFF', + green: '0xAA', + blue: '0xBB', + alpha: '0.600' + } + })); + }); + + it('should handle 0x99FFAABB', () => { + expect(colorPreferenceToComponents('0x99FFAABB')).toEqual(jasmine.objectContaining({ + components: { + red: '0xFF', + green: '0xAA', + blue: '0xBB', + alpha: '0.600' + } + })); + }); + + it('should handle null with default', () => { + expect(colorPreferenceToComponents(null)).toEqual(jasmine.objectContaining({ + reference: 'systemBackgroundColor' + })); + }); + + it('should handle black with default', () => { + expect(colorPreferenceToComponents('black')).toEqual(jasmine.objectContaining({ + reference: 'systemBackgroundColor' + })); + }); + + it('should handle 0xFAB with default', () => { + expect(colorPreferenceToComponents('0xFAB')).toEqual(jasmine.objectContaining({ + reference: 'systemBackgroundColor' + })); + }); + + it('should handle #1234 with default', () => { + expect(colorPreferenceToComponents('#1234')).toEqual(jasmine.objectContaining({ + reference: 'systemBackgroundColor' + })); + }); + + it('should handle #12345 with default', () => { + expect(colorPreferenceToComponents('#12345')).toEqual(jasmine.objectContaining({ + reference: 'systemBackgroundColor' + })); + }); + + it('should handle #1234567 with default', () => { + expect(colorPreferenceToComponents('#1234567')).toEqual(jasmine.objectContaining({ + reference: 'systemBackgroundColor' + })); + }); + + it('should handle #NOTHEX with default', () => { + expect(colorPreferenceToComponents('#NOTHEX')).toEqual(jasmine.objectContaining({ + reference: 'systemBackgroundColor' + })); + }); + }); + describe('updateProject method', () => { /* eslint-disable no-unused-vars */ let update_name;