Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more settings to control UI theme #45

Merged
merged 1 commit into from
Jan 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_0" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
Expand All @@ -21,30 +21,31 @@
<rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="p0s-Fg-eGP" userLabel="Splash Background">
<rect key="frame" x="0.0" y="20" width="390" height="824"/>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="p0s-Fg-eGP" userLabel="Splash Background">
<rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="center" id="DIO-mU-n27" userLabel="Loading View">
<rect key="frame" x="45" y="263" width="300" height="300"/>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DIO-mU-n27" userLabel="Loading View">
<rect key="frame" x="94" y="323" width="200" height="200"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<imageView hidden="YES" opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="wifi.slash" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="TpV-I7-c6z">
<rect key="frame" x="134" y="226.5" width="32" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="tintColor" systemColor="secondaryLabelColor"/>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="LaunchIcon" translatesAutoresizingMaskIntoConstraints="NO" id="4oa-LZ-pgs">
<rect key="frame" x="66" y="70" width="69" height="61"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<color key="tintColor" systemColor="secondarySystemFillColor"/>
<rect key="contentStretch" x="0.0" y="0.0" width="0.0" height="0.0"/>
</imageView>
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" fixedFrame="YES" progress="0.10000000000000001" translatesAutoresizingMaskIntoConstraints="NO" id="xSD-dq-HF9">
<rect key="frame" x="92" y="201" width="108" height="8"/>
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.10000000000000001" id="xSD-dq-HF9">
<rect key="frame" x="50" y="146" width="100" height="15"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
{{PWABuilder.iOS.progressBarColor}}
</progressView>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="LaunchIcon" translatesAutoresizingMaskIntoConstraints="NO" id="4oa-LZ-pgs">
<rect key="frame" x="118" y="118" width="64" height="64"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<imageView hidden="YES" opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="wifi.slash" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="TpV-I7-c6z">
<rect key="frame" x="85" y="159.33333333333314" width="31.999999999999886" height="30.000000000000085"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
{{PWABuilder.iOS.splashBgColor}}
<color key="tintColor" systemColor="secondarySystemFillColor"/>
<color key="tintColor" systemColor="secondaryLabelColor"/>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="a0B-Gx-0cO"/>
Expand All @@ -65,13 +66,13 @@
<outlet property="connectionProblemView" destination="TpV-I7-c6z" id="76F-WR-UnJ"/>
<outlet property="loadingView" destination="DIO-mU-n27" id="Wlk-Yd-6b1"/>
<outlet property="progressView" destination="xSD-dq-HF9" id="0jL-XR-Xwq"/>
<outlet property="webviewView" destination="PHY-vp-dMl" id="qhH-E4-3lf"/>
<outlet property="splashBkgView" destination="p0s-Fg-eGP" id="fMY-qQ-Qid"/>
<outlet property="webviewView" destination="PHY-vp-dMl" id="qhH-E4-3lf"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1038.4615384615383" y="136.49289099526067"/>
<point key="canvasLocation" x="1036.9230769230769" y="135.07109004739337"/>
</scene>
</scenes>
<resources>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ let rootUrl = URL(string: "{{PWABuilder.iOS.url}}")!

// allowed origin is for what we are sticking to pwa domain
// This should also appear in Info.plist
let allowedOrigin = "{{PWABuilder.iOS.urlHost}}"
let allowedOrigins: [String] = ["{{PWABuilder.iOS.urlHost}}"]

// auth origins will open in modal and show toolbar for back into the main origin.
// These should also appear in Info.plist
let authOrigins: [String] = ["{{PWABuilder.iOS.permittedHosts}}"]
// allowedOrigins + authOrigins <= 10

let platformCookie = Cookie(name: "app-platform", value: "iOS App Store")

let displayMode = "standalone" //standalone / fullscreen

//let statusBarColor = "#FFFFFF"
//let statusBarStyle = UIStatusBarStyle.lightContent
// UI options
let displayMode = "standalone" // standalone / fullscreen.
let adaptiveUIStyle = true // iOS 15+ only. Change app theme on the fly to dark/light related to WebView background color.
let overrideStatusBar = false // iOS 13-14 only. if you don't support dark/light system theme.
let statusBarTheme = "dark" // dark / light, related to override option.
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,31 @@ class ViewController: UIViewController, WKNavigationDelegate {
@IBOutlet weak var progressView: UIProgressView!
@IBOutlet weak var connectionProblemView: UIImageView!
@IBOutlet weak var webviewView: UIView!
@IBOutlet weak var splashBkgView: UIView!;
// var newWebviewPopupWindow: WKWebView?
var statusBarView: UIView!
var toolbarView: UIToolbar!
var htmlIsLoaded = false;
@IBOutlet weak var splashBkgView: UIView!
var toolbarView: UIToolbar!

var htmlIsLoaded = false

// override var preferredStatusBarStyle : UIStatusBarStyle {
// return statusBarStyle;
// }
private var themeObservation: NSKeyValueObservation?
var currentWebViewTheme: UIUserInterfaceStyle = .unspecified
override var preferredStatusBarStyle : UIStatusBarStyle {
if #available(iOS 13, *), overrideStatusBar{
if #available(iOS 15, *) {
return .default
} else {
return statusBarTheme == "dark" ? .lightContent : .darkContent
}
}
return .default
}

override func viewDidLoad() {
super.viewDidLoad()
initWebView()
initToolbarView()
loadRootUrl()

//self.view.backgroundColor = hexStringToUIColor(hex: statusBarColor)


NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification , object: nil)

}

@objc func keyboardWillHide(_ notification: NSNotification) {
Expand All @@ -42,10 +46,12 @@ class ViewController: UIViewController, WKNavigationDelegate {
PWAShell.webView.uiDelegate = self;
PWAShell.webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)

// if #available(iOS 11, *) {
// statusBarView = createStatusBar(container: webviewView)
// showStatusBar(true)
// }
if #available(iOS 15.0, *), adaptiveUIStyle {
themeObservation = PWAShell.webView.observe(\.underPageBackgroundColor) { [unowned self] webView, _ in
currentWebViewTheme = PWAShell.webView.underPageBackgroundColor.isLight() ?? true ? .light : .dark
self.overrideUIStyle()
}
}
}

func createToolbarView() -> UIToolbar{
Expand Down Expand Up @@ -83,9 +89,21 @@ class ViewController: UIViewController, WKNavigationDelegate {
webviewView.addSubview(toolbarView)

// Set the top of the splashBkgView to the bottom of the status bar.
let statusBarHeight = getStatusBarHeight()
let splashBkgFrame = self.splashBkgView.frame
self.splashBkgView.frame = CGRect(x: splashBkgFrame.minX, y: statusBarHeight, width: splashBkgFrame.width, height: splashBkgFrame.height)
// let statusBarHeight = getStatusBarHeight()
// let splashBkgFrame = self.splashBkgView.frame
// self.splashBkgView.frame = CGRect(x: splashBkgFrame.minX, y: statusBarHeight, width: splashBkgFrame.width, height: splashBkgFrame.height)
}

func overrideUIStyle(toDefault: Bool = false) {
if #available(iOS 15.0, *), adaptiveUIStyle {
if (((htmlIsLoaded && !PWAShell.webView.isHidden) || toDefault) && self.currentWebViewTheme != .unspecified) {
UIApplication
.shared
.connectedScenes
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
.first { $0.isKeyWindow }?.overrideUserInterfaceStyle = toDefault ? .unspecified : self.currentWebViewTheme;
}
}
}

@objc func loadRootUrl() {
Expand All @@ -107,13 +125,17 @@ class ViewController: UIViewController, WKNavigationDelegate {
self.loadingView.isHidden = true;

self.setProgress(0.0, false);

self.overrideUIStyle()
}
}

func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
htmlIsLoaded = false;

if (error as NSError)._code != (-999) {
self.overrideUIStyle(toDefault: true);

webView.isHidden = true;
loadingView.isHidden = false;
animateConnectionProblem(true);
Expand Down Expand Up @@ -149,12 +171,6 @@ class ViewController: UIViewController, WKNavigationDelegate {
self.progressView.setProgress(progress, animated: animated);
}

func showStatusBar(_ show: Bool) {
if (self.statusBarView != nil) {
self.statusBarView.isHidden = !show
}
}

func animateConnectionProblem(_ show: Bool) {
if (show) {
self.connectionProblemView.isHidden = false;
Expand Down Expand Up @@ -194,3 +210,25 @@ extension ViewController: WKScriptMessageHandler {
}
}
}

extension UIColor {
// Check if the color is light or dark, as defined by the injected lightness threshold.
// Some people report that 0.7 is best. I suggest to find out for yourself.
// A nil value is returned if the lightness couldn't be determined.
func isLight(threshold: Float = 0.5) -> Bool? {
let originalCGColor = self.cgColor

// Now we need to convert it to the RGB colorspace. UIColor.white / UIColor.black are greyscale and not RGB.
// If you don't do this then you will crash when accessing components index 2 below when evaluating greyscale colors.
let RGBCGColor = originalCGColor.converted(to: CGColorSpaceCreateDeviceRGB(), intent: .defaultIntent, options: nil)
guard let components = RGBCGColor?.components else {
return nil
}
guard components.count >= 3 else {
return nil
}

let brightness = Float(((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000)
return (brightness > threshold)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,51 +86,6 @@ func calcWebviewFrame(webviewView: UIView, toolbarView: UIToolbar?) -> CGRect{
}
}

//func createStatusBar(container: UIView) -> UIView {
// let app = UIApplication.shared
// let statusBarHeight: CGFloat = app.statusBarFrame.size.height
//
// let statusBarView = UIView()
// statusBarView.backgroundColor = hexStringToUIColor(hex: statusBarColor)
// container.addSubview(statusBarView)
//
// statusBarView.translatesAutoresizingMaskIntoConstraints = false
// statusBarView.heightAnchor
// .constraint(equalToConstant: statusBarHeight).isActive = true
// statusBarView.widthAnchor
// .constraint(equalTo: container.widthAnchor, multiplier: 1.0).isActive = true
// statusBarView.topAnchor
// .constraint(equalTo: container.topAnchor).isActive = true
// statusBarView.centerXAnchor
// .constraint(equalTo: container.centerXAnchor).isActive = true
//
// statusBarView.isHidden = true
//
// return statusBarView
//}

//func hexStringToUIColor (hex:String) -> UIColor {
// var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
//
// if (cString.hasPrefix("#")) {
// cString.remove(at: cString.startIndex)
// }
//
// if ((cString.count) != 6) {
// return UIColor.gray
// }
//
// var rgbValue:UInt64 = 0
// Scanner(string: cString).scanHexInt64(&rgbValue)
//
// return UIColor(
// red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
// green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
// blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
// alpha: CGFloat(1.0)
// )
//}

extension ViewController: WKUIDelegate {
// redirect new tabs to main webview
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
Expand All @@ -143,7 +98,8 @@ extension ViewController: WKUIDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if let requestUrl = navigationAction.request.url{
if let requestHost = requestUrl.host {
if (requestHost.range(of: allowedOrigin) != nil) {
let matchingHostOrigin = allowedOrigins.first(where: { requestHost.range(of: $0) != nil })
if (matchingHostOrigin != nil) {
// Open in main webview
decisionHandler(.allow)
if (!toolbarView.isHidden) {
Expand All @@ -153,7 +109,6 @@ extension ViewController: WKUIDelegate {

} else {
let matchingAuthOrigin = authOrigins.first(where: { requestHost.range(of: $0) != nil })
//if (requestHost.range(of: authOrigin_1) != nil || requestHost.range(of: authOrigin_2) != nil || requestHost.range(of: authOrigin_3) != nil || requestHost.range(of: authOrigin_4) != nil) {
if (matchingAuthOrigin != nil) {
decisionHandler(.allow)
if (toolbarView.isHidden) {
Expand Down