You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ks...@apache.org on 2016/09/28 16:21:22 UTC

ios commit: CB-9762 Add launch storyboard support

Repository: cordova-ios
Updated Branches:
  refs/heads/master ff3df9b7e -> 42acc6837


CB-9762 Add launch storyboard support

* No default splash images are provided as they would be overwritten anyway upon
adding the platform.

* Storyboard will open in Xcode 6, but is NOT supported on Xcode 6. Xcode 7
is the minimum required version for this feature.

* Compatibility: Node 0.x versions don't understand Array.find(); used .reduce()
instead with appropriate comments in the code.

 This closes #250


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/42acc683
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/42acc683
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/42acc683

Branch: refs/heads/master
Commit: 42acc68375d8b1aecd26f6b7c56aa6037841138b
Parents: ff3df9b
Author: Kerri Shotts <ks...@apache.org>
Authored: Wed Aug 24 17:49:20 2016 -0500
Committer: Kerri Shotts <ks...@apache.org>
Committed: Wed Sep 28 11:10:00 2016 -0500

----------------------------------------------------------------------
 .../__PROJECT_NAME__/CDVLaunchScreen.storyboard |  42 +++
 .../Images.xcassets/Contents.json               |   6 +
 .../LaunchStoryboard.imageset/Contents.json     | 168 +++++++++++
 .../project/__TEMP__.xcodeproj/project.pbxproj  |   4 +
 bin/templates/scripts/cordova/lib/prepare.js    | 301 +++++++++++++++++++
 5 files changed, 521 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/42acc683/bin/templates/project/__PROJECT_NAME__/CDVLaunchScreen.storyboard
----------------------------------------------------------------------
diff --git a/bin/templates/project/__PROJECT_NAME__/CDVLaunchScreen.storyboard b/bin/templates/project/__PROJECT_NAME__/CDVLaunchScreen.storyboard
new file mode 100644
index 0000000..0cb1e66
--- /dev/null
+++ b/bin/templates/project/__PROJECT_NAME__/CDVLaunchScreen.storyboard
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <development version="6100" identifier="xcode"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="LaunchStoryboard" translatesAutoresizingMaskIntoConstraints="NO" id="2ns-9I-Qjs">
+                                <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                            </imageView>
+                        </subviews>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="trailing" secondItem="2ns-9I-Qjs" secondAttribute="trailing" id="FZL-3Z-NFz"/>
+                            <constraint firstItem="2ns-9I-Qjs" firstAttribute="bottom" secondItem="xb3-aO-Qok" secondAttribute="top" id="L9l-pw-wXj"/>
+                            <constraint firstItem="2ns-9I-Qjs" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="oGN-hc-Uzj"/>
+                            <constraint firstItem="2ns-9I-Qjs" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="rS9-Wd-zY4"/>
+                        </constraints>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="LaunchStoryboard" width="1366" height="1366"/>
+    </resources>
+</document>

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/42acc683/bin/templates/project/__PROJECT_NAME__/Images.xcassets/Contents.json
----------------------------------------------------------------------
diff --git a/bin/templates/project/__PROJECT_NAME__/Images.xcassets/Contents.json b/bin/templates/project/__PROJECT_NAME__/Images.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164
--- /dev/null
+++ b/bin/templates/project/__PROJECT_NAME__/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/42acc683/bin/templates/project/__PROJECT_NAME__/Images.xcassets/LaunchStoryboard.imageset/Contents.json
----------------------------------------------------------------------
diff --git a/bin/templates/project/__PROJECT_NAME__/Images.xcassets/LaunchStoryboard.imageset/Contents.json b/bin/templates/project/__PROJECT_NAME__/Images.xcassets/LaunchStoryboard.imageset/Contents.json
new file mode 100644
index 0000000..71f82ac
--- /dev/null
+++ b/bin/templates/project/__PROJECT_NAME__/Images.xcassets/LaunchStoryboard.imageset/Contents.json
@@ -0,0 +1,168 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "1x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "universal",
+      "height-class" : "compact",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "1x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "universal",
+      "width-class" : "compact",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "width-class" : "compact",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "universal",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "iphone",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "ipad",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/42acc683/bin/templates/project/__TEMP__.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/bin/templates/project/__TEMP__.xcodeproj/project.pbxproj b/bin/templates/project/__TEMP__.xcodeproj/project.pbxproj
index 8e210b3..52f17f7 100755
--- a/bin/templates/project/__TEMP__.xcodeproj/project.pbxproj
+++ b/bin/templates/project/__TEMP__.xcodeproj/project.pbxproj
@@ -16,6 +16,7 @@
 		3047A5121AB8059700498E2A /* build-debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 3047A50F1AB8059700498E2A /* build-debug.xcconfig */; };
 		3047A5131AB8059700498E2A /* build-release.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 3047A5101AB8059700498E2A /* build-release.xcconfig */; };
 		3047A5141AB8059700498E2A /* build.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 3047A5111AB8059700498E2A /* build.xcconfig */; };
+		6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -50,6 +51,7 @@
 		3047A5101AB8059700498E2A /* build-release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "build-release.xcconfig"; path = cordova/build-release.xcconfig; sourceTree = SOURCE_ROOT; };
 		3047A5111AB8059700498E2A /* build.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = build.xcconfig; path = cordova/build.xcconfig; sourceTree = SOURCE_ROOT; };
 		32CA4F630368D1EE00C91783 /* __PROJECT_NAME__-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "__PROJECT_NAME__-Prefix.pch"; sourceTree = "<group>"; };
+		6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = CDVLaunchScreen.storyboard; path = "__PROJECT_NAME__/CDVLaunchScreen.storyboard"; sourceTree = SOURCE_ROOT; };
 		8D1107310486CEB800E47090 /* __PROJECT_NAME__-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "__PROJECT_NAME__-Info.plist"; path = "__PROJECT_NAME__/__PROJECT_NAME__-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = SOURCE_ROOT; };
 		EB87FDF31871DA8E0020F90C /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; name = www; path = ../../www; sourceTree = "<group>"; };
 		EB87FDF41871DAF40020F90C /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = ../../config.xml; sourceTree = "<group>"; };
@@ -124,6 +126,7 @@
 				0207DA571B56EA530066E2B4 /* Images.xcassets */,
 				3047A50E1AB8057F00498E2A /* config */,
 				8D1107310486CEB800E47090 /* __PROJECT_NAME__-Info.plist */,
+				6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */,
 			);
 			name = Resources;
 			path = "__PROJECT_NAME__/Resources";
@@ -237,6 +240,7 @@
 			files = (
 				302D95F214D2391D003F00A1 /* MainViewController.xib in Resources */,
 				0207DA581B56EA530066E2B4 /* Images.xcassets in Resources */,
+				6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/42acc683/bin/templates/scripts/cordova/lib/prepare.js
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/lib/prepare.js b/bin/templates/scripts/cordova/lib/prepare.js
index 10d1c41..873297a 100644
--- a/bin/templates/scripts/cordova/lib/prepare.js
+++ b/bin/templates/scripts/cordova/lib/prepare.js
@@ -53,6 +53,7 @@ module.exports.prepare = function (cordovaProject, options) {
     .then(function () {
         updateIcons(cordovaProject, self.locations);
         updateSplashScreens(cordovaProject, self.locations);
+        updateLaunchStoryboardImages(cordovaProject, self.locations);
     })
     .then(function () {
         events.emit('verbose', 'Prepared iOS project successfully');
@@ -78,6 +79,7 @@ module.exports.clean = function (options) {
         cleanWww(projectRoot, self.locations);
         cleanIcons(projectRoot, projectConfig, self.locations);
         cleanSplashScreens(projectRoot, projectConfig, self.locations);
+        cleanLaunchStoryboardImages(projectRoot, projectConfig, self.locations);
     });
 };
 
@@ -205,6 +207,7 @@ function updateProject(platformConfig, locations) {
     }
 
     handleOrientationSettings(platformConfig, infoPlist);
+    updateProjectPlistForLaunchStoryboard(platformConfig, infoPlist);
 
     var info_contents = plist.build(infoPlist);
     info_contents = info_contents.replace(/<string>[\s\r\n]*<\/string>/g,'<string></string>');
@@ -438,6 +441,304 @@ function cleanSplashScreens(projectRoot, projectConfig, locations) {
 }
 
 /**
+ * Returns an array of images for each possible idiom, scale, and size class. The images themselves are
+ * located in the platform's splash images by their pattern (@scale~idiom~sizesize). All possible
+ * combinations are returned, but not all will have a `filename` property. If the latter isn't present,
+ * the device won't attempt to load an image matching the same traits. If the filename is present,
+ * the device will try to load the image if it corresponds to the traits.
+ * 
+ * The resulting return looks like this:
+ * 
+ *     [
+ *         {
+ *             idiom: 'universal|ipad|iphone',
+ *             scale: '1x|2x|3x',
+ *             width: 'any|com',
+ *             height: 'any|com',
+ *             filename: undefined|'Default@scale~idiom~widthheight.png',
+ *             src: undefined|'path/to/original/matched/image/from/splash/screens.png',
+ *             target: undefined|'path/to/asset/library/Default@scale~idiom~widthheight.png'
+ *         }, ...
+ *     ]
+ * 
+ * @param  {Array<Object>} splashScreens         splash screens as defined in config.xml for this platform
+ * @param  {string} launchStoryboardImagesDir    project-root/Images.xcassets/LaunchStoryboard.imageset/
+ * @return {Array<Object>}
+ */
+function mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir) {
+    var platformLaunchStoryboardImages = [];
+    var idioms = ['universal', 'ipad', 'iphone'];
+    var scalesForIdiom = {
+        universal: ['1x', '2x', '3x'],
+        ipad: ['1x', '2x'],
+        iphone: ['1x', '2x', '3x']
+    };
+    var sizes = ['com', 'any'];
+
+    idioms.forEach(function (idiom) {
+        scalesForIdiom[idiom].forEach(function (scale) {
+            sizes.forEach(function(width) {
+                sizes.forEach(function(height) {
+                    var item = {
+                        idiom: idiom,
+                        scale: scale,
+                        width: width,
+                        height: height
+                    };
+
+                    /* examples of the search pattern:
+                     *    scale   ~  idiom    ~   width    height 
+                     *     @2x    ~ universal ~    any      any
+                     *     @3x    ~  iphone   ~    com      any
+                     *     @2x    ~   ipad    ~    com      any
+                     */
+                    var searchPattern = '@' + scale + '~' + idiom + '~' + width + height;
+
+                    /* because old node versions don't have Array.find, the below is
+                     * functionally equivalent to this:
+                     *     var launchStoryboardImage = splashScreens.find(function(item) {
+                     *         return item.src.indexOf(searchPattern) >= 0;
+                     *     });
+                     */
+                    var launchStoryboardImage = splashScreens.reduce(function (p, c) {
+                        return (c.src.indexOf(searchPattern) >= 0) ? c : p;
+                    }, undefined);
+
+                    if (launchStoryboardImage) {
+                        item.filename = 'Default' + searchPattern + '.png';
+                        item.src = launchStoryboardImage.src;
+                        item.target = path.join(launchStoryboardImagesDir, item.filename);
+                    }
+
+                    platformLaunchStoryboardImages.push(item);
+                });
+            });
+        });
+    });
+    return platformLaunchStoryboardImages;
+}
+
+/**
+ * Returns a dictionary representing the source and destination paths for the launch storyboard images
+ * that need to be copied. 
+ * 
+ * The resulting return looks like this:
+ * 
+ *     {
+ *         'target-path': 'source-path',
+ *         ...
+ *     }
+ * 
+ * @param  {Array<Object>} splashScreens         splash screens as defined in config.xml for this platform
+ * @param  {string} launchStoryboardImagesDir    project-root/Images.xcassets/LaunchStoryboard.imageset/
+ * @return {Object}
+ */
+function mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir) {
+    var platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir);
+    var pathMap = {};
+    platformLaunchStoryboardImages.forEach(function (item) {
+        if (item.target) {
+            pathMap[item.target] = item.src;
+        }
+    });
+    return pathMap;
+}
+
+/**
+ * Builds the object that represents the contents.json file for the LaunchStoryboard image set. 
+ * 
+ * The resulting return looks like this:
+ * 
+ *     {
+ *         images: [
+ *             {
+ *                 idiom: 'universal|ipad|iphone',
+ *                 scale: '1x|2x|3x',
+ *                 width-class: undefined|'compact',
+ *                 height-class: undefined|'compact'
+ *             }, ...
+ *         ],
+ *         info: {
+ *             author: 'Xcode',
+ *             version: 1
+ *         }
+ *     }
+ * 
+ * A bit of minor logic is used to map from the array of images returned from mapLaunchStoryboardContents
+ * to the format requried by Xcode.
+ * 
+ * @param  {Array<Object>} splashScreens         splash screens as defined in config.xml for this platform
+ * @param  {string} launchStoryboardImagesDir    project-root/Images.xcassets/LaunchStoryboard.imageset/
+ * @return {Object}
+ */
+function getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir) {
+    var IMAGESET_COMPACT_SIZE_CLASS = 'compact';
+    var CDV_ANY_SIZE_CLASS = 'any';
+
+    var platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir);
+    var contentsJSON = {
+        images: [],
+        info: {
+            author: 'Xcode',
+            version: 1
+        }
+    };
+    contentsJSON.images = platformLaunchStoryboardImages.map(function(item) {
+        var newItem = {
+            idiom: item.idiom,
+            scale: item.scale
+        };
+
+        // Xcode doesn't want any size class property if the class is "any"
+        // If our size class is "com", Xcode wants "compact". 
+        if (item.width !== CDV_ANY_SIZE_CLASS) {
+            newItem['width-class'] = IMAGESET_COMPACT_SIZE_CLASS;
+        }
+        if (item.height !== CDV_ANY_SIZE_CLASS) {
+            newItem['height-class'] = IMAGESET_COMPACT_SIZE_CLASS;
+        }
+
+        // Xcode doesn't want a filename property if there's no image for these traits       
+        if (item.filename) {
+            newItem.filename = item.filename;
+        }
+        return newItem;
+    });
+    return contentsJSON;
+}
+
+/**
+ * Updates the project's plist based upon our launch storyboard images. If there are no images, then we should
+ * fall back to the regular launch images that might be supplied (that is, our app will be scaled on an iPad Pro),
+ * and if there are some images, we need to alter the UILaunchStoryboardName property to point to 
+ * CDVLaunchScreen.
+ * 
+ * There's some logic here to avoid overwriting changes the user might have made to their plist if they are using
+ * their own launch storyboard.
+ */
+function updateProjectPlistForLaunchStoryboard(platformConfig, infoPlist) {
+    var UI_LAUNCH_STORYBOARD_NAME = 'UILaunchStoryboardName';
+    var CDV_LAUNCH_STORYBOARD_NAME = 'CDVLaunchScreen';
+
+    var splashScreens = platformConfig.getSplashScreens('ios');
+    var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, '');  // note: we don't need a file path here; we're just counting
+    var currentLaunchStoryboard = infoPlist[UI_LAUNCH_STORYBOARD_NAME];
+
+    events.emit('verbose', 'Current launch storyboard ' + currentLaunchStoryboard);
+
+
+    /* do we have any launch images do we have for our launch storyboard?
+     * Again, for old Node versions, the below code is equivalent to this:
+     *     var hasLaunchStoryboardImages = !!contentsJSON.images.find(function (item) {
+     *        return item.filename !== undefined;
+     *     });
+     */
+    var hasLaunchStoryboardImages = !!contentsJSON.images.reduce(function (p, c) {
+        return (c.filename !== undefined) ? c : p;
+    }, undefined);
+
+    if (hasLaunchStoryboardImages && !currentLaunchStoryboard) {
+        // only change the launch storyboard if we have images to use AND the current value is blank
+        // if it's not blank, we've either done this before, or the user has their own launch storyboard
+        events.emit('verbose', 'Changing project to use our launch storyboard');
+        infoPlist[UI_LAUNCH_STORYBOARD_NAME] = CDV_LAUNCH_STORYBOARD_NAME;
+        return;
+    }
+
+    if (!hasLaunchStoryboardImages && currentLaunchStoryboard === CDV_LAUNCH_STORYBOARD_NAME) {
+        // only revert to using the launch images if we have don't have any images for the launch storyboard
+        // but only clear it if current launch storyboard is our storyboard; the user might be using their
+        // own storyboard instead.
+        events.emit('verbose', 'Changing project to use launch images');
+        infoPlist[UI_LAUNCH_STORYBOARD_NAME] = undefined;
+        return;
+    }
+    events.emit('verbose', 'Not changing launch storyboard setting.');
+}
+
+/**
+ * Returns the directory for the Launch Storyboard image set, if image sets are being used. If they aren't
+ * being used, returns null.
+ * 
+ * @param  {string} projectRoot        The project's root directory
+ * @param  {string} platformProjDir    The platform's project directory
+ */
+function getLaunchStoryboardImagesDir(projectRoot, platformProjDir) {
+    var launchStoryboardImagesDir;
+    var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'));
+
+    if (xcassetsExists) {
+        launchStoryboardImagesDir = path.join(platformProjDir, 'Images.xcassets/LaunchStoryboard.imageset/');
+    } else {
+        // if we don't have a asset library for images, we can't do the storyboard.
+        launchStoryboardImagesDir = null;
+    }
+
+    return launchStoryboardImagesDir;
+}
+
+/**
+ * Update the images for the Launch Storyboard and updates the image set's contents.json file appropriately.
+ * 
+ * @param  {Object} cordovaProject     The cordova project
+ * @param  {Object} locations          A dictionary containing useful location paths
+ */
+function updateLaunchStoryboardImages(cordovaProject, locations) {
+    var splashScreens = cordovaProject.projectConfig.getSplashScreens('ios');
+    var platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
+    var launchStoryboardImagesDir = getLaunchStoryboardImagesDir(cordovaProject.root, platformProjDir);
+
+    if (launchStoryboardImagesDir) {
+        var resourceMap = mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir);
+        var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir);
+
+        events.emit('verbose', 'Updating launch storyboard images at ' + launchStoryboardImagesDir);
+        FileUpdater.updatePaths(
+            resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+        
+        events.emit('verbose', 'Updating Storyboard image set contents.json');
+        fs.writeFileSync(path.join(launchStoryboardImagesDir, 'contents.json'),
+                        JSON.stringify(contentsJSON, null, 2));
+    }
+}
+
+/**
+ * Removes the images from the launch storyboard's image set and updates the image set's contents.json
+ * file appropriately.
+ *
+ * @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 cleanLaunchStoryboardImages(projectRoot, projectConfig, locations) {
+    var splashScreens = projectConfig.getSplashScreens('ios');
+    var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
+    var launchStoryboardImagesDir = getLaunchStoryboardImagesDir(projectRoot, platformProjDir);
+    if (launchStoryboardImagesDir) {
+        var resourceMap = mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir);
+        var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir);
+
+        Object.keys(resourceMap).forEach(function (targetPath) {
+            resourceMap[targetPath] = null;
+        });
+        events.emit('verbose', 'Cleaning storyboard image set at ' + launchStoryboardImagesDir);
+
+        // Source paths are removed from the map, so updatePaths() will delete the target files.
+        FileUpdater.updatePaths(
+            resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+
+        // delete filename from contents.json
+        contentsJSON.images.forEach(function(image) {
+            image.filename = undefined;
+        });
+
+        events.emit('verbose', 'Updating Storyboard image set contents.json');
+        fs.writeFileSync(path.join(launchStoryboardImagesDir, 'contents.json'),
+                        JSON.stringify(contentsJSON, null, 2));
+    }
+}
+
+/**
  * Queries ConfigParser object for the orientation <preference> value. Warns if
  *   global preference value is not supported by platform.
  *


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org