From 70ea79b14d2cdbe5f3158126be9cb90660354a61 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Sat, 8 Jun 2019 10:47:26 +0700 Subject: [PATCH 1/9] Added androidBackgroundColor to Splash Screen plugin. --- .../capacitor/src/main/java/com/getcapacitor/Splash.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/android/capacitor/src/main/java/com/getcapacitor/Splash.java b/android/capacitor/src/main/java/com/getcapacitor/Splash.java index daccf4375b..d2ca1944cd 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Splash.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Splash.java @@ -3,6 +3,7 @@ import android.animation.Animator; import android.app.Activity; import android.content.Context; +import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; @@ -52,6 +53,13 @@ private static void buildViews(Context c) { // https://stackoverflow.com/a/21847579/32140 splashImage.setDrawingCacheEnabled(true); + String backgroundColor = Config.getString(CONFIG_KEY_PREFIX + "androidBackgroundColor"); + try { + splashImage.setBackgroundColor(Color.parseColor(backgroundColor)); + } catch (IllegalArgumentException ex) { + // Do not apply any background color. + } + String scaleTypeName = Config.getString(CONFIG_KEY_PREFIX + "androidScaleType", "FIT_XY"); ImageView.ScaleType scaleType = null; try { From bc1f4953bbb9c492fb3fa52b47d1149521e4c0e1 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Sat, 8 Jun 2019 13:44:06 +0700 Subject: [PATCH 2/9] Added backgroundColor for iOS splash screen. --- .../Capacitor/Plugins/SplashScreen.swift | 71 +++++++++++++++++-- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift b/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift index 9d825333ef..fd33b41b99 100644 --- a/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift +++ b/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift @@ -1,6 +1,59 @@ import Foundation import AudioToolbox +// https://stackoverflow.com/questions/24263007/how-to-use-hex-color-values +extension UIColor { + convenience init(r: Int, g: Int, b: Int, a: Int = 0xFF) { + self.init( + red: CGFloat(r) / 255.0, + green: CGFloat(g) / 255.0, + blue: CGFloat(b) / 255.0, + alpha: CGFloat(a) / 255.0 + ) + } + + // let's suppose alpha is the first component (ARGB) + convenience init(argb: UInt32) { + self.init( + red: CGFloat((argb >> 16) & 0xFF), + green: CGFloat((argb >> 8) & 0xFF), + blue: CGFloat(argb & 0xFF), + alpha: CGFloat((argb >> 24) & 0xFF) + ) + } + + // https://cocoacasts.com/from-hex-to-uicolor-and-back-in-swift + convenience init?(hex: String) { + let hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: "#", with: "") + + var argb: UInt32 = 0 + + var r: CGFloat = 0.0 + var g: CGFloat = 0.0 + var b: CGFloat = 0.0 + var a: CGFloat = 1.0 + + guard Scanner(string: hexSanitized).scanHexInt32(&argb) else { return nil } + + if ((hexSanitized.count) == 6) { + r = CGFloat((argb & 0xFF0000) >> 16) / 255.0 + g = CGFloat((argb & 0x00FF00) >> 8) / 255.0 + b = CGFloat(argb & 0x0000FF) / 255.0 + + } else if ((hexSanitized.count) == 8) { + r = CGFloat((argb & 0xFF000000) >> 24) / 255.0 + g = CGFloat((argb & 0x00FF0000) >> 16) / 255.0 + b = CGFloat((argb & 0x0000FF00) >> 8) / 255.0 + a = CGFloat(argb & 0x000000FF) / 255.0 + + } else { + return nil + } + + self.init(red: r, green: g, blue: b, alpha: a) + } +} + @objc(CAPSplashScreenPlugin) public class CAPSplashScreenPlugin : CAPPlugin { var imageView = UIImageView() @@ -11,7 +64,7 @@ public class CAPSplashScreenPlugin : CAPPlugin { let launchShowDuration = 3000 let launchAutoHide = true - + let defaultFadeInDuration = 200 let defaultFadeOutDuration = 200 let defaultShowDuration = 3000 @@ -35,8 +88,9 @@ public class CAPSplashScreenPlugin : CAPPlugin { let fadeInDuration = call.get("fadeInDuration", Int.self, defaultFadeInDuration)! let fadeOutDuration = call.get("fadeOutDuration", Int.self, defaultFadeOutDuration)! let autoHide = call.get("autoHide", Bool.self, defaultAutoHide)! - - showSplash(showDuration: showDuration, fadeInDuration: fadeInDuration, fadeOutDuration: fadeOutDuration, autoHide: autoHide, completion: { + let backgroundColor = call.get("backgroundColor", String.self) + + showSplash(showDuration: showDuration, fadeInDuration: fadeInDuration, fadeOutDuration: fadeOutDuration, autoHide: autoHide, backgroundColor: backgroundColor, completion: { call.success() }, isLaunchSplash: false) } @@ -97,14 +151,19 @@ public class CAPSplashScreenPlugin : CAPPlugin { self.bridge.viewController.view.addSubview(self.imageView) let launchShowDurationConfig = getConfigValue("launchShowDuration") as? Int ?? launchShowDuration let launchAutoHideConfig = getConfigValue("launchAutoHide") as? Bool ?? launchAutoHide - showSplash(showDuration: launchShowDurationConfig, fadeInDuration: 0, fadeOutDuration: defaultFadeOutDuration, autoHide: launchAutoHideConfig, completion: { + let launchBackgroundColorConfig = getConfigValue("launchBackgroundColor") as? String ?? nil + + showSplash(showDuration: launchShowDurationConfig, fadeInDuration: 0, fadeOutDuration: defaultFadeOutDuration, autoHide: launchAutoHideConfig, backgroundColor: launchBackgroundColorConfig, completion: { }, isLaunchSplash: true) } - func showSplash(showDuration: Int, fadeInDuration: Int, fadeOutDuration: Int, autoHide: Bool, completion: @escaping () -> Void, isLaunchSplash: Bool) { + func showSplash(showDuration: Int, fadeInDuration: Int, fadeOutDuration: Int, autoHide: Bool, backgroundColor: String?, completion: @escaping () -> Void, isLaunchSplash: Bool) { DispatchQueue.main.async { - + if (backgroundColor != nil) { + self.imageView.backgroundColor = UIColor(hex: backgroundColor!) + } + if !isLaunchSplash { self.bridge.viewController.view.addSubview(self.imageView) } From 094175ec1b17577a6112d6639c54840171064584 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Sat, 8 Jun 2019 13:46:50 +0700 Subject: [PATCH 3/9] Fixed naming of configuration key. --- .gitignore | 9 ++++++--- .../capacitor/src/main/java/com/getcapacitor/Splash.java | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 579cb06ded..a4e832ed03 100644 --- a/.gitignore +++ b/.gitignore @@ -28,8 +28,11 @@ local.properties contents.xcworkspacedata .stencil/ android-template/.gradle/ -android-template/app/app.iml -*.js -*.json +android-template/app/app.iml +*.js +*.json /site/.env /site/.firebase +.gradle/ +.settings/ +.project diff --git a/android/capacitor/src/main/java/com/getcapacitor/Splash.java b/android/capacitor/src/main/java/com/getcapacitor/Splash.java index d2ca1944cd..6e0a903e1d 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Splash.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Splash.java @@ -53,7 +53,7 @@ private static void buildViews(Context c) { // https://stackoverflow.com/a/21847579/32140 splashImage.setDrawingCacheEnabled(true); - String backgroundColor = Config.getString(CONFIG_KEY_PREFIX + "androidBackgroundColor"); + String backgroundColor = Config.getString(CONFIG_KEY_PREFIX + "backgroundColor"); try { splashImage.setBackgroundColor(Color.parseColor(backgroundColor)); } catch (IllegalArgumentException ex) { From 898fca739bfaaf08bad294b394cf65eacf2452a5 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 11 Jun 2019 13:51:54 +0700 Subject: [PATCH 4/9] Fixed issue with missing backgroundColor configuration. --- android/capacitor/src/main/java/com/getcapacitor/Splash.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/Splash.java b/android/capacitor/src/main/java/com/getcapacitor/Splash.java index 6e0a903e1d..9719c58756 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Splash.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Splash.java @@ -55,7 +55,9 @@ private static void buildViews(Context c) { String backgroundColor = Config.getString(CONFIG_KEY_PREFIX + "backgroundColor"); try { - splashImage.setBackgroundColor(Color.parseColor(backgroundColor)); + if (backgroundColor != null) { + splashImage.setBackgroundColor(Color.parseColor(backgroundColor)); + } } catch (IllegalArgumentException ex) { // Do not apply any background color. } From ff1bc2e488749f48fea845c896e21f61f8fd757c Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 11 Jun 2019 17:59:19 +0700 Subject: [PATCH 5/9] Added fallback for backgroundColor on launch. --- .../Capacitor/Plugins/SplashScreen.swift | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift b/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift index fd33b41b99..b182b334b2 100644 --- a/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift +++ b/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift @@ -11,7 +11,7 @@ extension UIColor { alpha: CGFloat(a) / 255.0 ) } - + // let's suppose alpha is the first component (ARGB) convenience init(argb: UInt32) { self.init( @@ -21,35 +21,35 @@ extension UIColor { alpha: CGFloat((argb >> 24) & 0xFF) ) } - + // https://cocoacasts.com/from-hex-to-uicolor-and-back-in-swift convenience init?(hex: String) { let hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: "#", with: "") - + var argb: UInt32 = 0 - + var r: CGFloat = 0.0 var g: CGFloat = 0.0 var b: CGFloat = 0.0 var a: CGFloat = 1.0 - + guard Scanner(string: hexSanitized).scanHexInt32(&argb) else { return nil } - + if ((hexSanitized.count) == 6) { r = CGFloat((argb & 0xFF0000) >> 16) / 255.0 g = CGFloat((argb & 0x00FF00) >> 8) / 255.0 b = CGFloat(argb & 0x0000FF) / 255.0 - + } else if ((hexSanitized.count) == 8) { r = CGFloat((argb & 0xFF000000) >> 24) / 255.0 g = CGFloat((argb & 0x00FF0000) >> 16) / 255.0 b = CGFloat((argb & 0x0000FF00) >> 8) / 255.0 a = CGFloat(argb & 0x000000FF) / 255.0 - + } else { return nil } - + self.init(red: r, green: g, blue: b, alpha: a) } } @@ -61,7 +61,7 @@ public class CAPSplashScreenPlugin : CAPPlugin { var call: CAPPluginCall? var hideTask: Any? var isVisible: Bool = false - + let launchShowDuration = 3000 let launchAutoHide = true @@ -69,21 +69,21 @@ public class CAPSplashScreenPlugin : CAPPlugin { let defaultFadeOutDuration = 200 let defaultShowDuration = 3000 let defaultAutoHide = true - + public override func load() { buildViews() showOnLaunch() } - + // Show the splash screen @objc public func show(_ call: CAPPluginCall) { self.call = call - + if image == nil { call.error("No image named \"Splash\" found. Please check your Assets.xcassets for a file named Splash") return } - + let showDuration = call.get("showDuration", Int.self, defaultShowDuration)! let fadeInDuration = call.get("fadeInDuration", Int.self, defaultFadeInDuration)! let fadeOutDuration = call.get("fadeOutDuration", Int.self, defaultFadeOutDuration)! @@ -94,7 +94,7 @@ public class CAPSplashScreenPlugin : CAPPlugin { call.success() }, isLaunchSplash: false) } - + // Hide the splash screen @objc public func hide(_ call: CAPPluginCall) { self.call = call @@ -102,30 +102,30 @@ public class CAPSplashScreenPlugin : CAPPlugin { hideSplash(fadeOutDuration: fadeDuration) call.success() } - + func buildViews() { // Find the image asset named "Splash" // TODO: Find a way to not hard code this? image = UIImage.init(named: "Splash") - + if image == nil { print("Unable to find splash screen image. Make sure an image called Splash exists in your assets") } - + // Observe for changes on fram and bounds to handle rotation resizing let parentView = self.bridge.viewController.view parentView?.addObserver(self, forKeyPath: "frame", options: .new, context: nil) parentView?.addObserver(self, forKeyPath: "bounds", options: .new, context: nil) - + self.updateSplashImageBounds() } - + func tearDown() { self.isVisible = false bridge.viewController.view.isUserInteractionEnabled = true self.imageView.removeFromSuperview() } - + // Update the bounds for the splash image. This will also be called when // the parent view observers fire func updateSplashImageBounds() { @@ -142,23 +142,23 @@ public class CAPSplashScreenPlugin : CAPPlugin { imageView.frame = CGRect.init(origin: CGPoint.init(x: 0, y: 0), size: window.bounds.size) imageView.contentMode = .scaleAspectFill } - + public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { updateSplashImageBounds() } - + func showOnLaunch() { self.bridge.viewController.view.addSubview(self.imageView) let launchShowDurationConfig = getConfigValue("launchShowDuration") as? Int ?? launchShowDuration let launchAutoHideConfig = getConfigValue("launchAutoHide") as? Bool ?? launchAutoHide - let launchBackgroundColorConfig = getConfigValue("launchBackgroundColor") as? String ?? nil + let launchBackgroundColorConfig = getConfigValue("launchBackgroundColor") as? String ?? getConfigValue("backgroundColor") as? String ?? nil showSplash(showDuration: launchShowDurationConfig, fadeInDuration: 0, fadeOutDuration: defaultFadeOutDuration, autoHide: launchAutoHideConfig, backgroundColor: launchBackgroundColorConfig, completion: { }, isLaunchSplash: true) } - + func showSplash(showDuration: Int, fadeInDuration: Int, fadeOutDuration: Int, autoHide: Bool, backgroundColor: String?, completion: @escaping () -> Void, isLaunchSplash: Bool) { - + DispatchQueue.main.async { if (backgroundColor != nil) { self.imageView.backgroundColor = UIColor(hex: backgroundColor!) @@ -188,7 +188,7 @@ public class CAPSplashScreenPlugin : CAPPlugin { func hideSplash(fadeOutDuration: Int) { self.hideSplash(fadeOutDuration: fadeOutDuration, isLaunchSplash: false); } - + func hideSplash(fadeOutDuration: Int, isLaunchSplash: Bool) { if(isLaunchSplash && isVisible) { print("SplashScreen.hideSplash: SplashScreen was automatically hidden after default timeout. " + @@ -205,4 +205,3 @@ public class CAPSplashScreenPlugin : CAPPlugin { } } } - From c88fb7914245adcff5ea4906b796769f852744a9 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Fri, 14 Jun 2019 12:04:47 +0700 Subject: [PATCH 6/9] Added documentation for backgroundColor. --- .../Capacitor/Plugins/SplashScreen.swift | 61 ++---------------- ios/Capacitor/Capacitor/UIColor.swift | 62 +++++++++++++++---- site/docs-md/apis/splash-screen/index.md | 14 ++++- 3 files changed, 64 insertions(+), 73 deletions(-) diff --git a/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift b/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift index b182b334b2..cc9600c5e8 100644 --- a/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift +++ b/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift @@ -1,58 +1,5 @@ -import Foundation import AudioToolbox - -// https://stackoverflow.com/questions/24263007/how-to-use-hex-color-values -extension UIColor { - convenience init(r: Int, g: Int, b: Int, a: Int = 0xFF) { - self.init( - red: CGFloat(r) / 255.0, - green: CGFloat(g) / 255.0, - blue: CGFloat(b) / 255.0, - alpha: CGFloat(a) / 255.0 - ) - } - - // let's suppose alpha is the first component (ARGB) - convenience init(argb: UInt32) { - self.init( - red: CGFloat((argb >> 16) & 0xFF), - green: CGFloat((argb >> 8) & 0xFF), - blue: CGFloat(argb & 0xFF), - alpha: CGFloat((argb >> 24) & 0xFF) - ) - } - - // https://cocoacasts.com/from-hex-to-uicolor-and-back-in-swift - convenience init?(hex: String) { - let hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: "#", with: "") - - var argb: UInt32 = 0 - - var r: CGFloat = 0.0 - var g: CGFloat = 0.0 - var b: CGFloat = 0.0 - var a: CGFloat = 1.0 - - guard Scanner(string: hexSanitized).scanHexInt32(&argb) else { return nil } - - if ((hexSanitized.count) == 6) { - r = CGFloat((argb & 0xFF0000) >> 16) / 255.0 - g = CGFloat((argb & 0x00FF00) >> 8) / 255.0 - b = CGFloat(argb & 0x0000FF) / 255.0 - - } else if ((hexSanitized.count) == 8) { - r = CGFloat((argb & 0xFF000000) >> 24) / 255.0 - g = CGFloat((argb & 0x00FF0000) >> 16) / 255.0 - b = CGFloat((argb & 0x0000FF00) >> 8) / 255.0 - a = CGFloat(argb & 0x000000FF) / 255.0 - - } else { - return nil - } - - self.init(red: r, green: g, blue: b, alpha: a) - } -} +import Foundation @objc(CAPSplashScreenPlugin) public class CAPSplashScreenPlugin : CAPPlugin { @@ -151,7 +98,7 @@ public class CAPSplashScreenPlugin : CAPPlugin { self.bridge.viewController.view.addSubview(self.imageView) let launchShowDurationConfig = getConfigValue("launchShowDuration") as? Int ?? launchShowDuration let launchAutoHideConfig = getConfigValue("launchAutoHide") as? Bool ?? launchAutoHide - let launchBackgroundColorConfig = getConfigValue("launchBackgroundColor") as? String ?? getConfigValue("backgroundColor") as? String ?? nil + let launchBackgroundColorConfig = getConfigValue("backgroundColor") as? String ?? nil showSplash(showDuration: launchShowDurationConfig, fadeInDuration: 0, fadeOutDuration: defaultFadeOutDuration, autoHide: launchAutoHideConfig, backgroundColor: launchBackgroundColorConfig, completion: { }, isLaunchSplash: true) @@ -160,8 +107,8 @@ public class CAPSplashScreenPlugin : CAPPlugin { func showSplash(showDuration: Int, fadeInDuration: Int, fadeOutDuration: Int, autoHide: Bool, backgroundColor: String?, completion: @escaping () -> Void, isLaunchSplash: Bool) { DispatchQueue.main.async { - if (backgroundColor != nil) { - self.imageView.backgroundColor = UIColor(hex: backgroundColor!) + if backgroundColor != nil { + self.imageView.backgroundColor = UIColor(fromHex: backgroundColor!) } if !isLaunchSplash { diff --git a/ios/Capacitor/Capacitor/UIColor.swift b/ios/Capacitor/Capacitor/UIColor.swift index d507b60ec1..08a38a9cf8 100644 --- a/ios/Capacitor/Capacitor/UIColor.swift +++ b/ios/Capacitor/Capacitor/UIColor.swift @@ -1,19 +1,55 @@ +// https://stackoverflow.com/questions/24263007/how-to-use-hex-color-values extension UIColor { - convenience init(fromHex hex: String) { - var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() - - if (cString.hasPrefix("#")) { - cString.remove(at: cString.startIndex) - } + convenience init(r: Int, g: Int, b: Int, a: Int = 0xFF) { + self.init( + red: CGFloat(r) / 255.0, + green: CGFloat(g) / 255.0, + blue: CGFloat(b) / 255.0, + alpha: CGFloat(a) / 255.0 + ) + } - var rgbValue:UInt32 = 0 - Scanner(string: cString).scanHexInt32(&rgbValue) - + // let's suppose alpha is the first component (ARGB) + convenience init(argb: UInt32) { self.init( - red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, - green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, - blue: CGFloat(rgbValue & 0x0000FF) / 255.0, - alpha: CGFloat(1.0) + red: CGFloat((argb >> 16) & 0xFF), + green: CGFloat((argb >> 8) & 0xFF), + blue: CGFloat(argb & 0xFF), + alpha: CGFloat((argb >> 24) & 0xFF) ) } + + // https://cocoacasts.com/from-hex-to-uicolor-and-back-in-swift + convenience init?(fromHex: String) { + let hexString = fromHex.trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences( + of: "#", + with: "" + ) + + var argb: UInt32 = 0 + + var r: CGFloat = 0.0 + var g: CGFloat = 0.0 + var b: CGFloat = 0.0 + var a: CGFloat = 1.0 + + guard Scanner(string: hexString).scanHexInt32(&argb) else { return nil } + + if hexString.count == 6 { + r = CGFloat((argb & 0xFF0000) >> 16) / 255.0 + g = CGFloat((argb & 0x00FF00) >> 8) / 255.0 + b = CGFloat(argb & 0x0000FF) / 255.0 + + } else if hexString.count == 8 { + r = CGFloat((argb & 0xFF00_0000) >> 24) / 255.0 + g = CGFloat((argb & 0x00FF0000) >> 16) / 255.0 + b = CGFloat((argb & 0x0000FF00) >> 8) / 255.0 + a = CGFloat(argb & 0x000000FF) / 255.0 + + } else { + return nil + } + + self.init(red: r, green: g, blue: b, alpha: a) + } } diff --git a/site/docs-md/apis/splash-screen/index.md b/site/docs-md/apis/splash-screen/index.md index 17a3caf70a..9337f991d8 100644 --- a/site/docs-md/apis/splash-screen/index.md +++ b/site/docs-md/apis/splash-screen/index.md @@ -5,6 +5,7 @@ url: /docs/apis/splash-screen contributors: - mlynch - jcesarmobile + - trancee --- @@ -69,6 +70,12 @@ If you want to be sure the splash never hides before the app is fully loaded, se Then run `npx cap copy` to apply these changes. +## Background Color + +In certain conditions, especially if the splash screen does not fully cover the device screen, it might happen that the app screen is visible around the corners (due to transparency). + +Possible values for `backgroundColor` in your `capacitor.config.json` are either `#RGB` or `#ARGB`. + ## Configuration These config parameters are available in `capacitor.config.json`: @@ -79,6 +86,7 @@ These config parameters are available in `capacitor.config.json`: "SplashScreen": { "launchShowDuration": 3000, "launchAutoHide": true, + "backgroundColor": "#ffffffff", "androidSplashResourceName": "splash", "androidScaleType": "CENTER_CROP" } @@ -90,7 +98,7 @@ These config parameters are available in `capacitor.config.json`: If your splash screen images aren't named "splash.png" but for example "screen.png" you have to change `"androidSplashResourceName": "screen"` in `capacitor.config.json` and change the following files in you're Android app as well: -`android/app/src/main/res/drawable/launch_splash.xml` +`android/app/src/main/res/drawable/launch_splash.xml` replace ```xml @@ -107,7 +115,7 @@ with /> ``` -`android/app/src/main/res/values/styles.xml` +`android/app/src/main/res/values/styles.xml` replace ```xml @@ -130,4 +138,4 @@ with ## API - \ No newline at end of file + From e0dcd4b8f9794af51bb071c8cf9c1dfdaeaa6488 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Fri, 14 Jun 2019 12:07:58 +0700 Subject: [PATCH 7/9] Added code formatting. --- .../Capacitor/Plugins/SplashScreen.swift | 111 +++++++++++++----- 1 file changed, 83 insertions(+), 28 deletions(-) diff --git a/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift b/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift index cc9600c5e8..a70a7d7875 100644 --- a/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift +++ b/ios/Capacitor/Capacitor/Plugins/SplashScreen.swift @@ -2,7 +2,7 @@ import AudioToolbox import Foundation @objc(CAPSplashScreenPlugin) -public class CAPSplashScreenPlugin : CAPPlugin { +public class CAPSplashScreenPlugin: CAPPlugin { var imageView = UIImageView() var image: UIImage? var call: CAPPluginCall? @@ -27,7 +27,9 @@ public class CAPSplashScreenPlugin : CAPPlugin { self.call = call if image == nil { - call.error("No image named \"Splash\" found. Please check your Assets.xcassets for a file named Splash") + call.error( + "No image named \"Splash\" found. Please check your Assets.xcassets for a file named Splash" + ) return } @@ -37,9 +39,17 @@ public class CAPSplashScreenPlugin : CAPPlugin { let autoHide = call.get("autoHide", Bool.self, defaultAutoHide)! let backgroundColor = call.get("backgroundColor", String.self) - showSplash(showDuration: showDuration, fadeInDuration: fadeInDuration, fadeOutDuration: fadeOutDuration, autoHide: autoHide, backgroundColor: backgroundColor, completion: { - call.success() - }, isLaunchSplash: false) + showSplash( + showDuration: showDuration, + fadeInDuration: fadeInDuration, + fadeOutDuration: fadeOutDuration, + autoHide: autoHide, + backgroundColor: backgroundColor, + completion: { + call.success() + }, + isLaunchSplash: false + ) } // Hide the splash screen @@ -56,7 +66,9 @@ public class CAPSplashScreenPlugin : CAPPlugin { image = UIImage.init(named: "Splash") if image == nil { - print("Unable to find splash screen image. Make sure an image called Splash exists in your assets") + print( + "Unable to find splash screen image. Make sure an image called Splash exists in your assets" + ) } // Observe for changes on fram and bounds to handle rotation resizing @@ -77,12 +89,18 @@ public class CAPSplashScreenPlugin : CAPPlugin { // the parent view observers fire func updateSplashImageBounds() { guard let delegate = UIApplication.shared.delegate else { - bridge.modulePrint(self, "Unable to find root window object for SplashScreen bounds. Please file an issue") + bridge.modulePrint( + self, + "Unable to find root window object for SplashScreen bounds. Please file an issue" + ) return } guard let window = delegate.window as? UIWindow else { - bridge.modulePrint(self, "Unable to find root window object for SplashScreen bounds. Please file an issue") + bridge.modulePrint( + self, + "Unable to find root window object for SplashScreen bounds. Please file an issue" + ) return } imageView.image = image @@ -90,21 +108,43 @@ public class CAPSplashScreenPlugin : CAPPlugin { imageView.contentMode = .scaleAspectFill } - public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { + public override func observeValue( + forKeyPath keyPath: String?, + of object: Any?, + change: [NSKeyValueChangeKey: Any]?, + context: UnsafeMutableRawPointer? + ) { updateSplashImageBounds() } func showOnLaunch() { self.bridge.viewController.view.addSubview(self.imageView) - let launchShowDurationConfig = getConfigValue("launchShowDuration") as? Int ?? launchShowDuration + let launchShowDurationConfig = getConfigValue("launchShowDuration") as? Int + ?? launchShowDuration let launchAutoHideConfig = getConfigValue("launchAutoHide") as? Bool ?? launchAutoHide let launchBackgroundColorConfig = getConfigValue("backgroundColor") as? String ?? nil - showSplash(showDuration: launchShowDurationConfig, fadeInDuration: 0, fadeOutDuration: defaultFadeOutDuration, autoHide: launchAutoHideConfig, backgroundColor: launchBackgroundColorConfig, completion: { - }, isLaunchSplash: true) + showSplash( + showDuration: launchShowDurationConfig, + fadeInDuration: 0, + fadeOutDuration: defaultFadeOutDuration, + autoHide: launchAutoHideConfig, + backgroundColor: launchBackgroundColorConfig, + completion: { + }, + isLaunchSplash: true + ) } - func showSplash(showDuration: Int, fadeInDuration: Int, fadeOutDuration: Int, autoHide: Bool, backgroundColor: String?, completion: @escaping () -> Void, isLaunchSplash: Bool) { + func showSplash( + showDuration: Int, + fadeInDuration: Int, + fadeOutDuration: Int, + autoHide: Bool, + backgroundColor: String?, + completion: @escaping () -> Void, + isLaunchSplash: Bool + ) { DispatchQueue.main.async { if backgroundColor != nil { @@ -117,36 +157,51 @@ public class CAPSplashScreenPlugin : CAPPlugin { self.bridge.viewController.view.isUserInteractionEnabled = false - UIView.transition(with: self.imageView, duration: TimeInterval(Double(fadeInDuration) / 1000), options: .curveLinear, animations: { - self.imageView.alpha = 1 - }) { (finished: Bool) in + UIView.transition( + with: self.imageView, + duration: TimeInterval(Double(fadeInDuration) / 1000), + options: .curveLinear, + animations: { + self.imageView.alpha = 1 + } + ) { (finished: Bool) in self.isVisible = true if autoHide { - self.hideTask = DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + (Double(showDuration) / 1000), execute: { - self.hideSplash(fadeOutDuration: fadeOutDuration, isLaunchSplash: isLaunchSplash) - completion() - }) + self.hideTask = DispatchQueue.main.asyncAfter( + deadline: DispatchTime.now() + (Double(showDuration) / 1000), + execute: { + self.hideSplash(fadeOutDuration: fadeOutDuration, isLaunchSplash: isLaunchSplash) + completion() + } + ) } } } } func hideSplash(fadeOutDuration: Int) { - self.hideSplash(fadeOutDuration: fadeOutDuration, isLaunchSplash: false); + self.hideSplash(fadeOutDuration: fadeOutDuration, isLaunchSplash: false) } func hideSplash(fadeOutDuration: Int, isLaunchSplash: Bool) { - if(isLaunchSplash && isVisible) { - print("SplashScreen.hideSplash: SplashScreen was automatically hidden after default timeout. " + - "You should call `SplashScreen.hide()` as soon as your web app is loaded (or increase the timeout). " + - "Read more at https://capacitor.ionicframework.com/docs/apis/splash-screen/#hiding-the-splash-screen"); + if isLaunchSplash && isVisible { + print( + "SplashScreen.hideSplash: SplashScreen was automatically hidden after default timeout. " + + "You should call `SplashScreen.hide()` as soon as your web app is loaded (or increase the timeout). " + + "Read more at https://capacitor.ionicframework.com/docs/apis/splash-screen/#hiding-the-splash-screen" + ) } if !isVisible { return } DispatchQueue.main.async { - UIView.transition(with: self.imageView, duration: TimeInterval(Double(fadeOutDuration) / 1000), options: .curveLinear, animations: { - self.imageView.alpha = 0 - }) { (finished: Bool) in + UIView.transition( + with: self.imageView, + duration: TimeInterval(Double(fadeOutDuration) / 1000), + options: .curveLinear, + animations: { + self.imageView.alpha = 0 + } + ) { (finished: Bool) in self.tearDown() } } From e9492bba46e3aec0dcfc11a472e9589050a43765 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Thu, 20 Jun 2019 19:33:15 +0700 Subject: [PATCH 8/9] Rebased. --- .../cordova/MockCordovaWebViewImpl.java | 2 +- .../com/getcapacitor/plugin/Filesystem.java | 30 ++- cli/src/android/open.ts | 15 +- cli/src/config.ts | 24 ++- cli/src/electron/add.ts | 9 +- cli/src/electron/copy.ts | 5 - cli/src/electron/open.ts | 27 +++ cli/src/tasks/open.ts | 3 + core/native-bridge.js | 91 --------- electron-template/gitignore | 6 + electron-template/index.js | 11 +- electron-template/package.json | 3 +- electron/index.js | 9 +- electron/src/runtime.ts | 2 +- .../IonicRunner.xcodeproj/project.pbxproj | 4 +- example/ios/IonicRunner/Podfile.lock | 12 +- example/package-lock.json | 175 +++++++++++++----- example/package.json | 2 +- example/www/index.html | 5 +- .../Capacitor/CAPBridgeViewController.swift | 2 +- ios/Capacitor/Capacitor/Plugins/Toast.swift | 2 + .../Classes/Public/CDVPlugin.h | 1 + .../Classes/Public/CDVPlugin.m | 1 + .../Classes/Public/CDVViewController.h | 1 + .../Classes/Public/CDVViewController.m | 1 + site/docs-md/android/updating.md | 6 +- site/docs-md/community/plugins.md | 2 +- site/docs-md/electron/index.md | 5 +- site/docs-md/electron/updating.md | 25 +++ site/docs-md/ios/updating.md | 8 +- site/src/components/blog-page/blog-page.tsx | 2 +- .../components/site-header/site-header.tsx | 2 +- 32 files changed, 275 insertions(+), 218 deletions(-) create mode 100644 cli/src/electron/open.ts create mode 100644 electron-template/gitignore create mode 100644 site/docs-md/electron/updating.md diff --git a/android/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java b/android/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java index 270abd92dc..d8da6f19f1 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java +++ b/android/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java @@ -275,7 +275,7 @@ public ICordovaCookieManager getCookieManager() { @Override public String getUrl() { - return null; + return webView.getUrl(); } @Override diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java index b2e9faa7d3..662d46d0da 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java @@ -17,7 +17,6 @@ import com.getcapacitor.PluginRequestCodes; import org.json.JSONException; -import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; @@ -26,7 +25,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -114,29 +112,23 @@ private InputStream getInputStream(String path, String directory) throws IOExcep File androidDirectory = this.getDirectory(directory); if (androidDirectory == null) { - return null; + throw new IOException("Directory not found"); } return new FileInputStream(new File(androidDirectory, path)); } - private String readFileAsString(InputStream is, Charset charset) throws IOException { - final StringBuilder text = new StringBuilder(); + private String readFileAsString(InputStream is, String encoding) throws IOException { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + byte[] buffer = new byte[1024]; + int length = 0; - BufferedReader br = new BufferedReader( - new InputStreamReader( - is, - charset - ) - ); - String line; + while ((length = is.read(buffer)) != -1) { + outputStream.write(buffer, 0, length); + }; - while ((line = br.readLine()) != null) { - text.append(line); - text.append('\n'); - } - br.close(); - return text.toString(); + return outputStream.toString(encoding); } private String readFileAsBase64EncodedData(InputStream is) throws IOException { @@ -174,7 +166,7 @@ public void readFile(PluginCall call) { InputStream is = getInputStream(file, directory); String dataStr; if (charset != null) { - dataStr = readFileAsString(is, charset); + dataStr = readFileAsString(is, charset.name()); } else { dataStr = readFileAsBase64EncodedData(is); } diff --git a/cli/src/android/open.ts b/cli/src/android/open.ts index 19e2a30f94..9217d60622 100644 --- a/cli/src/android/open.ts +++ b/cli/src/android/open.ts @@ -20,17 +20,10 @@ export async function openAndroid(config: Config) { await opn(dir, { app: 'android studio', wait: false }); break; case OS.Windows: - try { - await opn(dir, { app: config.windows.androidStudioPath, wait: false }); - } catch (e) { - logError('Unable to launch Android Studio. Make sure the latest version of Android Studio is installed, or,' + - 'if you\'ve installed Android Studio in a custom location, configure "windowsAndroidStudioPath" ' + - 'your capacitor.config.json to point to the location of studio64.exe, using JavaScript-escaped paths:\n' + - - 'Example:\n' + - '{\n' + - ' "windowsAndroidStudioPath": "H:\\\\Android Studio\\\\bin\\\\studio64.exe"\n' + - '}'); + if (config.windows.androidStudioPath) { + opn(dir, { app: config.windows.androidStudioPath, wait: false }); + } else { + logError('Unable to launch Android Studio. Make sure the latest version of Android Studio is installed') } break; case OS.Linux: diff --git a/cli/src/config.ts b/cli/src/config.ts index c1ee569f6a..2245af4641 100644 --- a/cli/src/config.ts +++ b/cli/src/config.ts @@ -1,7 +1,8 @@ -import { accessSync, readFileSync } from 'fs'; +import { accessSync, existsSync, readFileSync } from 'fs'; import { basename, join, resolve } from 'path'; import { logFatal, readJSON } from './common'; import { CliConfig, ExternalConfig, OS, PackageJson } from './definitions'; +import { execSync } from 'child_process'; let Package: PackageJson; let ExtConfig: ExternalConfig; @@ -193,7 +194,24 @@ export class Config implements CliConfig { } private initWindowsConfig() { - this.windows.androidStudioPath = this.app.windowsAndroidStudioPath && this.app.windowsAndroidStudioPath; + if (this.cli.os !== OS.Windows) { + return; + } + if (this.app.windowsAndroidStudioPath) { + try { + if (!existsSync(this.app.windowsAndroidStudioPath)) { + const buffer = execSync('REG QUERY "HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio" /v Path'); + const bufferString = buffer.toString('utf-8').replace(/(\r\n|\n|\r)/gm, ''); + const ix = bufferString.indexOf('REG_SZ'); + if (ix > 0) { + this.app.windowsAndroidStudioPath = bufferString.substring(ix + 6).trim() + '\\bin\\studio64.exe'; + } + } + this.windows.androidStudioPath = this.app.windowsAndroidStudioPath; + } catch (e) { + this.windows.androidStudioPath = ''; + } + } } private initLinuxConfig() { @@ -328,7 +346,7 @@ export class Config implements CliConfig { if (platformName === 'web') { logFatal(`Could not find the web platform directory. Make sure ${chalk.bold(this.app.webDir)} exists.`); } - logFatal(`${chalk.bold(platformName)}" platform has not been created. Use "capacitor add ${platformName}" to add the platform project.`); + logFatal(`${chalk.bold(platformName)}" platform has not been created. Use "npx cap add ${platformName}" to add the platform project.`); } } diff --git a/cli/src/electron/add.ts b/cli/src/electron/add.ts index 461022ed6c..94ddaad6ff 100644 --- a/cli/src/electron/add.ts +++ b/cli/src/electron/add.ts @@ -1,6 +1,6 @@ import { exec } from 'child_process'; import { Config } from '../config'; -import { copyTemplate, hasYarn, runTask } from '../common'; +import { copyTemplate, installDeps, hasYarn, runTask } from '../common'; export async function addElectron(config: Config) { @@ -16,14 +16,11 @@ export async function addElectron(config: Config) { function installNpmDeps(config: Config) { const pathToElectronPackageJson = config.electron.platformDir; return new Promise(async (resolve, reject) => { - console.log('Installing NPM Dependencies...'); - exec(`${await hasYarn(config) ? 'yarn' : 'npm'} install`, {cwd: pathToElectronPackageJson}, (error, stdout, stderr) => { + exec(`${await hasYarn(config) ? 'yarn' : 'npm'} install`, {cwd: pathToElectronPackageJson}, async (error, stdout, stderr) => { if (error) { reject(error); } - console.log(`${stdout}`); - console.log(`${stderr}`); - console.log(`NPM Dependencies installed!`); + await installDeps(pathToElectronPackageJson, ['@capacitor/electron'], config); resolve(); }); }); diff --git a/cli/src/electron/copy.ts b/cli/src/electron/copy.ts index eb1acf681c..d823222bb2 100644 --- a/cli/src/electron/copy.ts +++ b/cli/src/electron/copy.ts @@ -8,13 +8,8 @@ export async function copyElectron(config: Config) { const webAbsDir = config.app.webDirAbs; const webRelDir = basename(webAbsDir); const nativeRelDir = relative(config.app.rootDir, config.electron.webDirAbs); - // const runtimePath = resolveNode(config, '@capacitor/core', 'dist', 'capacitor.js'); return await runTask(`Copying web assets from ${chalk.bold(webRelDir)} to ${chalk.bold(nativeRelDir)}`, async () => { - console.log(`Cleaning ${config.electron.webDirAbs}...`); await removeAsync(config.electron.webDirAbs); - console.log(`Copying web assets...`); return copyTemplate(webAbsDir, config.electron.webDirAbs); - // console.log(`Copying runtime...`); - // return copy(runtimePath, join(config.electron.webDirAbs, 'capacitor.js')); }); } diff --git a/cli/src/electron/open.ts b/cli/src/electron/open.ts new file mode 100644 index 0000000000..4a9f521790 --- /dev/null +++ b/cli/src/electron/open.ts @@ -0,0 +1,27 @@ +import { exec } from 'child_process'; +import { Config } from '../config'; +import { logInfo } from '../common'; +import { existsAsync } from '../util/fs'; +import { resolve } from 'path'; + +export async function openElectron(config: Config) { + + const dir = config.electron.platformDir; + + logInfo(`Opening Electron project at ${dir}`); + + if (!await existsAsync(resolve(config.app.rootDir, dir))) { + throw new Error('Electron project does not exist. Create one with "npx cap add electron"'); + } + + return new Promise(async (resolve, reject) => { + exec(`npm run electron:start`, {cwd: dir}, (error) => { + if (error) { + reject(error); + return; + } + resolve(); + }); + }); + +} diff --git a/cli/src/tasks/open.ts b/cli/src/tasks/open.ts index 337b5f25ac..df933a9168 100644 --- a/cli/src/tasks/open.ts +++ b/cli/src/tasks/open.ts @@ -1,6 +1,7 @@ import { Config } from '../config'; import { logFatal, logInfo, runTask } from '../common'; import { openAndroid } from '../android/open'; +import { openElectron } from '../electron/open'; import { openIOS } from '../ios/open'; export async function openCommand(config: Config, selectedPlatform: string) { @@ -33,6 +34,8 @@ export async function open(config: Config, platformName: string) { return openAndroid(config); } else if (platformName === config.web.name) { return Promise.resolve(); + } else if (platformName === config.electron.name) { + return openElectron(config); } else { throw `Platform ${platformName} is not valid.`; } diff --git a/core/native-bridge.js b/core/native-bridge.js index 3464aac1e7..b4a763920b 100644 --- a/core/native-bridge.js +++ b/core/native-bridge.js @@ -340,20 +340,8 @@ capacitor.handleError = function(error) { console.error(error); - - if (!Capacitor.DEBUG) { - return; - } - - if(!errorModal) { - errorModal = makeErrorModal(error); - } - - errorModal.style.display = 'block'; - updateErrorModal(error); } - capacitor.handleWindowError = function (msg, url, lineNo, columnNo, error) { var string = msg.toLowerCase(); var substring = "script error"; @@ -440,85 +428,6 @@ window.onerror = capacitor.handleWindowError; } - function injectCSS() { - var css = '\n ._avc-modal {\n ' + (capacitor.isIOS ? '\n font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";\n ' : '\n font-family: "Roboto", "Helvetica Neue", sans-serif;\n ') + '\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 9999;\n }\n ._avc-modal-wrap {\n position: relative;\n width: 100%;\n height: 100%;\n }\n ._avc-modal-header {\n font-size: 16px;\n position: relative;\n ' + (capacitor.isIOS ? '\n padding: 32px 15px;\n -webkit-backdrop-filter: blur(10px);\n background-color: rgba(255, 255, 255, 0.5);\n ' : '\n background-color: #eee;\n height: 60px;\n padding: 15px;\n ') + '\n }\n ._avc-modal-content {\n width: 100%;\n height: 100%;\n padding: 15px;\n -webkit-backdrop-filter: blur(10px);\n ' + (capacitor.isIOS ? '\n background-color: rgba(255, 255, 255, 0.5);\n ' : '\n background-color: white;\n ') + '\n overflow: auto;\n -webkit-overflow-scrolling: touch;\n }\n ._avc-modal-header-button {\n position: absolute;\n font-size: 16px;\n right: 15px;\n padding: 0px 10px;\n ' + (capacitor.isIOS ? '\n top: 30px;\n ' : '\n top: 10px;\n height: 40px;\n ') + '\n }\n ._avc-modal-title {\n ' + (capacitor.isIOS ? '\n position: absolute;\n text-align: center;\n width: 100px;\n left: 50%;\n margin-left: -50px;\n ' : '\n margin-top: 7px;\n ') + '\n font-weight: 600;\n }\n ._avc-error-content {\n font-size: 14px;\n margin-bottom: 50px;\n }\n ._avc-error-message {\n font-size: 16px;\n font-weight: 600;\n margin-bottom: 10px;\n }\n ._avc-button {\n padding: 15px;\n font-size: 14px;\n border-radius: 3px;\n background-color: #222;\n }\n #_avc-copy-error {\n position: absolute;\n bottom: 0;\n left: 15px;\n right: 15px;\n ' + (capacitor.isAndroid ? '\n bottom: 15px;\n width: calc(100% - 30px);\n ' : '') + '\n background-color: #e83d3d;\n color: #fff;\n font-weight: bold;\n margin-top: 15px;\n }\n '; - var style = document.createElement('style'); - style.innerHTML = css; - document.head.appendChild(style); - } - - function makeModal() { - injectCSS(); - var html = '\n
\n
\n
Error
\n \n
\n
\n
\n
\n \n
\n '; - var el = document.createElement('div'); - el.innerHTML = html; - el.className ="_avc-modal"; - - var closeButton = el.querySelector('#_avc-modal-close'); - closeButton.addEventListener('click', function(e) { - el.style.display = 'none'; - }) - - var copyButton = el.querySelector('#_avc-copy-error'); - copyButton.addEventListener('click', function(e) { - if(lastError) { - Capacitor.Plugins.Clipboard.write({ - string: lastError.message + '\n' + lastError.stack - }); - } - }); - - return el; - } - - function makeErrorModal(error) { - var modalEl = makeModal(); - modalEl.id = "_avc-error"; - document.body.appendChild(modalEl); - return modalEl; - } - - function updateErrorModal(error) { - if(!errorModal) { return; } - - if (typeof error === 'string') { - return; - } - - lastError = error; - - var message = error.message; - if(error.rejection) { - message = 'Promise rejected: ' + error.rejection.message + "
" + message; - } - - var stack = error.stack; - var stackLines = cleanStack(stack); - var stackHTML = stackLines.join('
'); - - var content = errorModal.querySelector('._avc-error-output'); - content.innerHTML = '\n
\n
\n
\n
\n '; - var messageEl = content.querySelector('._avc-error-message'); - var stackEl = content.querySelector('._avc-error-stack'); - messageEl.innerHTML = message; - stackEl.innerHTML = stackHTML; - } - - function cleanStack(stack) { - var lines = stack.split('\n'); - return lines.map(function (line) { - var atIndex = line.indexOf('@'); - var appIndex = line.indexOf('.app'); - - // Remove the big long iOS path - if(atIndex >= 0 && appIndex >= 0) { - //var badSubstr = line.substring(atIndex, appIndex + 5); - line = '' + line.substring(0, atIndex) + '' + '@' + line.substring(appIndex + 5); - } - return line; - }); - } - win.Ionic = win.Ionic || {}; win.Ionic.WebView = win.Ionic.WebView || {}; diff --git a/electron-template/gitignore b/electron-template/gitignore new file mode 100644 index 0000000000..b4fdeec7c3 --- /dev/null +++ b/electron-template/gitignore @@ -0,0 +1,6 @@ +# NPM renames .gitignore to .npmignore +# In order to prevent that, we remove the initial "." +# And the CLI then renames it + +app/ +node_modules/ diff --git a/electron-template/index.js b/electron-template/index.js index c57e3bfc7a..fbea5739d2 100644 --- a/electron-template/index.js +++ b/electron-template/index.js @@ -1,9 +1,8 @@ const { app, BrowserWindow, Menu } = require('electron'); const isDevMode = require('electron-is-dev'); -const { injectCapacitor, CapacitorSplashScreen } = require('@capacitor/electron'); +const { CapacitorSplashScreen } = require('@capacitor/electron'); const path = require('path'); -global.__basedir = path.resolve(__dirname); // Place holders for our windows so they don't get garbage collected. let mainWindow = null; @@ -35,6 +34,10 @@ async function createWindow () { height: 920, width: 1600, show: false, + webPreferences: { + nodeIntegration: true, + preload: path.join(__dirname, 'node_modules', '@capacitor', 'electron', 'dist', 'electron-bridge.js') + } }); if (isDevMode) { @@ -46,9 +49,9 @@ async function createWindow () { if(useSplashScreen) { splashScreen = new CapacitorSplashScreen(mainWindow); - splashScreen.init(); + splashScreen.init(false); } else { - mainWindow.loadURL(await injectCapacitor(`file://${__dirname}/app/index.html`), {baseURLForDataURL: `file://${__dirname}/app/`}); + mainWindow.loadURL(`file://${__dirname}/app/index.html`); mainWindow.webContents.on('dom-ready', () => { mainWindow.show(); }); diff --git a/electron-template/package.json b/electron-template/package.json index 14ec484318..13191e20cb 100644 --- a/electron-template/package.json +++ b/electron-template/package.json @@ -7,8 +7,7 @@ "electron:start": "electron ./" }, "dependencies": { - "@capacitor/electron": "^1.0.0", - "electron-is-dev": "^0.3.0" + "electron-is-dev": "^1.1.0" }, "devDependencies": { "electron": "^4.0.0" diff --git a/electron/index.js b/electron/index.js index 55568cce09..168fd8cddd 100644 --- a/electron/index.js +++ b/electron/index.js @@ -14,6 +14,7 @@ function getURLFileContents(path) { } const injectCapacitor = async function(url) { + console.warn('\nWARNING: injectCapacitor method is deprecated and will be removed in next major release. Check release notes for migration instructions\n') try { let urlFileContents = await getURLFileContents(url.substr(url.indexOf('://') + 3)); let pathing = path.join(url.substr(url.indexOf('://') + 3), '../../node_modules/@capacitor/electron/dist/electron-bridge.js'); @@ -89,7 +90,7 @@ class CapacitorSplashScreen { }); } - init() { + init(inject = true) { let rootPath = app.getAppPath(); @@ -120,7 +121,11 @@ class CapacitorSplashScreen { this.splashWindow.webContents.on('dom-ready', async () => { this.splashWindow.show(); setTimeout(async () => { - this.mainWindowRef.loadURL(await injectCapacitor(`file://${rootPath}/app/index.html`), {baseURLForDataURL: `file://${rootPath}/app/`}); + if (inject) { + this.mainWindowRef.loadURL(await injectCapacitor(`file://${rootPath}/app/index.html`), {baseURLForDataURL: `file://${rootPath}/app/`}); + } else { + this.mainWindowRef.loadURL(`file://${rootPath}/app/index.html`); + } }, 4500); }); diff --git a/electron/src/runtime.ts b/electron/src/runtime.ts index 643e291185..36c5952afa 100644 --- a/electron/src/runtime.ts +++ b/electron/src/runtime.ts @@ -27,7 +27,7 @@ export class CapacitorElectron { } pluginMethodNoop(_target: any, _prop: PropertyKey, pluginName: string) { - return Promise.reject(`${pluginName} does not have web implementation.`); + return Promise.reject(`${pluginName} does not have electron implementation.`); } getPlatform() { diff --git a/example/ios/IonicRunner/IonicRunner.xcodeproj/project.pbxproj b/example/ios/IonicRunner/IonicRunner.xcodeproj/project.pbxproj index 9618797486..a87c3156a2 100644 --- a/example/ios/IonicRunner/IonicRunner.xcodeproj/project.pbxproj +++ b/example/ios/IonicRunner/IonicRunner.xcodeproj/project.pbxproj @@ -252,7 +252,7 @@ files = ( ); inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-IonicRunner/Pods-IonicRunner-frameworks.sh", + "${PODS_ROOT}/Target Support Files/Pods-IonicRunner/Pods-IonicRunner-frameworks.sh", "${BUILT_PRODUCTS_DIR}/Capacitor/Capacitor.framework", "${BUILT_PRODUCTS_DIR}/CapacitorCordova/Cordova.framework", ); @@ -263,7 +263,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-IonicRunner/Pods-IonicRunner-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-IonicRunner/Pods-IonicRunner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 62F96EECC323BD73A7ACF894 /* [CP] Check Pods Manifest.lock */ = { diff --git a/example/ios/IonicRunner/Podfile.lock b/example/ios/IonicRunner/Podfile.lock index b80ed1eaf9..d00183685a 100644 --- a/example/ios/IonicRunner/Podfile.lock +++ b/example/ios/IonicRunner/Podfile.lock @@ -1,7 +1,7 @@ PODS: - - Capacitor (1.0.0-beta.14): - - CapacitorCordova (= 1.0.0-beta.14) - - CapacitorCordova (1.0.0-beta.14) + - Capacitor (1.0.0): + - CapacitorCordova (= 1.0.0) + - CapacitorCordova (1.0.0) DEPENDENCIES: - Capacitor (from `../../../`) @@ -14,9 +14,9 @@ EXTERNAL SOURCES: :path: "../../../" SPEC CHECKSUMS: - Capacitor: 45813ccadddccc4b41d37c6e28d55091ea0dc0b5 - CapacitorCordova: 5035eb0fecfd8624456ad05aa1d07285a3847cd5 + Capacitor: 48e6d22d3d2fe9fd95f6c128136a7b538b7fd50d + CapacitorCordova: dd5a5a6ca827445b1f97ed0bb9ca4dbf424802c3 PODFILE CHECKSUM: cf3dd73a42bef0923c014a1179dc29d10aa5cae0 -COCOAPODS: 1.5.0 +COCOAPODS: 1.6.2 diff --git a/example/package-lock.json b/example/package-lock.json index cd0fc8781e..5c3e2d9691 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -469,7 +469,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -490,12 +491,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -510,17 +513,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -637,7 +643,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -649,6 +656,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -663,6 +671,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -670,12 +679,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -694,6 +705,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -774,7 +786,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -786,6 +799,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -871,7 +885,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -907,6 +922,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -926,6 +942,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -969,12 +986,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -2967,7 +2986,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.1.1", @@ -3010,7 +3030,8 @@ }, "balanced-match": { "version": "0.4.2", - "bundled": true + "bundled": true, + "optional": true }, "bcrypt-pbkdf": { "version": "1.0.1", @@ -3023,6 +3044,7 @@ "block-stream": { "version": "0.0.9", "bundled": true, + "optional": true, "requires": { "inherits": "~2.0.0" } @@ -3030,6 +3052,7 @@ "boom": { "version": "2.10.1", "bundled": true, + "optional": true, "requires": { "hoek": "2.x.x" } @@ -3037,6 +3060,7 @@ "brace-expansion": { "version": "1.1.7", "bundled": true, + "optional": true, "requires": { "balanced-match": "^0.4.1", "concat-map": "0.0.1" @@ -3044,7 +3068,8 @@ }, "buffer-shims": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "caseless": { "version": "0.12.0", @@ -3058,30 +3083,36 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "combined-stream": { "version": "1.0.5", "bundled": true, + "optional": true, "requires": { "delayed-stream": "~1.0.0" } }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "cryptiles": { "version": "2.0.5", "bundled": true, + "optional": true, "requires": { "boom": "2.x.x" } @@ -3116,7 +3147,8 @@ }, "delayed-stream": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "delegates": { "version": "1.0.0", @@ -3143,7 +3175,8 @@ }, "extsprintf": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "forever-agent": { "version": "0.6.1", @@ -3162,11 +3195,13 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "fstream": { "version": "1.0.11", "bundled": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -3217,6 +3252,7 @@ "glob": { "version": "7.1.2", "bundled": true, + "optional": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3228,7 +3264,8 @@ }, "graceful-fs": { "version": "4.1.11", - "bundled": true + "bundled": true, + "optional": true }, "har-schema": { "version": "1.0.5", @@ -3252,6 +3289,7 @@ "hawk": { "version": "3.1.3", "bundled": true, + "optional": true, "requires": { "boom": "2.x.x", "cryptiles": "2.x.x", @@ -3261,7 +3299,8 @@ }, "hoek": { "version": "2.16.3", - "bundled": true + "bundled": true, + "optional": true }, "http-signature": { "version": "1.1.1", @@ -3276,6 +3315,7 @@ "inflight": { "version": "1.0.6", "bundled": true, + "optional": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -3283,7 +3323,8 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.4", @@ -3293,6 +3334,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3304,7 +3346,8 @@ }, "isarray": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "isstream": { "version": "0.1.2", @@ -3367,11 +3410,13 @@ }, "mime-db": { "version": "1.27.0", - "bundled": true + "bundled": true, + "optional": true }, "mime-types": { "version": "2.1.15", "bundled": true, + "optional": true, "requires": { "mime-db": "~1.27.0" } @@ -3379,17 +3424,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -3439,7 +3487,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "oauth-sign": { "version": "0.8.2", @@ -3454,6 +3503,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3479,7 +3529,8 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "performance-now": { "version": "0.2.0", @@ -3488,7 +3539,8 @@ }, "process-nextick-args": { "version": "1.0.7", - "bundled": true + "bundled": true, + "optional": true }, "punycode": { "version": "1.4.1", @@ -3521,6 +3573,7 @@ "readable-stream": { "version": "2.2.9", "bundled": true, + "optional": true, "requires": { "buffer-shims": "~1.0.0", "core-util-is": "~1.0.0", @@ -3563,13 +3616,15 @@ "rimraf": { "version": "2.6.1", "bundled": true, + "optional": true, "requires": { "glob": "^7.0.5" } }, "safe-buffer": { "version": "5.0.1", - "bundled": true + "bundled": true, + "optional": true }, "semver": { "version": "5.3.0", @@ -3589,6 +3644,7 @@ "sntp": { "version": "1.0.9", "bundled": true, + "optional": true, "requires": { "hoek": "2.x.x" } @@ -3619,6 +3675,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3628,6 +3685,7 @@ "string_decoder": { "version": "1.0.1", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -3640,6 +3698,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3652,6 +3711,7 @@ "tar": { "version": "2.2.1", "bundled": true, + "optional": true, "requires": { "block-stream": "*", "fstream": "^1.0.2", @@ -3701,7 +3761,8 @@ }, "util-deprecate": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "uuid": { "version": "3.0.1", @@ -3726,7 +3787,8 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true } } }, @@ -4094,9 +4156,9 @@ "dev": true }, "ionic-angular": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/ionic-angular/-/ionic-angular-3.9.2.tgz", - "integrity": "sha512-BEZ6magY1i5GwM9ki/MOpszUz62+g518HsGICtw9TE1D4v9Eb6n/o7e+X0vtvpK4TdouFjQ8r5XA9VPAKW9/+Q==" + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/ionic-angular/-/ionic-angular-3.9.6.tgz", + "integrity": "sha512-rUmRQHtupbB+oyUm4UusguUtop3QSZq2I7+gKWXIFYrT/x6+pp0vteH2ayIeBmWDsL2zRv+/iQaz+Kx6KnkaUg==" }, "ionicons": { "version": "3.0.0", @@ -7749,7 +7811,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -7770,12 +7833,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7790,17 +7855,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -7917,7 +7985,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -7929,6 +7998,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7943,6 +8013,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7950,12 +8021,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7974,6 +8047,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -8054,7 +8128,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -8066,6 +8141,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -8151,7 +8227,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -8187,6 +8264,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -8206,6 +8284,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -8249,12 +8328,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, diff --git a/example/package.json b/example/package.json index a54095b213..f007112c16 100644 --- a/example/package.json +++ b/example/package.json @@ -29,7 +29,7 @@ "@ionic-native/splash-screen": "4.4.0", "@ionic-native/status-bar": "4.4.0", "@ionic/storage": "2.1.3", - "ionic-angular": "3.9.2", + "ionic-angular": "^3.9.6", "ionicons": "3.0.0", "rxjs": "5.5.2", "sw-toolbox": "3.6.0", diff --git a/example/www/index.html b/example/www/index.html index 63a2346d3d..d1432d63e6 100644 --- a/example/www/index.html +++ b/example/www/index.html @@ -2,7 +2,7 @@ Ionic App @@ -14,7 +14,8 @@ - + +