diff --git a/src/flows/FlowCoordinator.swift b/src/flows/FlowCoordinator.swift index 1ea68ae..a4614ae 100644 --- a/src/flows/FlowCoordinator.swift +++ b/src/flows/FlowCoordinator.swift @@ -145,7 +145,7 @@ public class DescopeFlowCoordinator { /// } /// ``` /// - /// - Parameter css: The raw CSS to add, e.g., `.footer { display: none; }`. + /// - Parameter css: The raw CSS to add, e.g., `".footer { display: none; }"`. public func addStyles(_ css: String) { bridge.addStyles(css) } @@ -164,7 +164,7 @@ public class DescopeFlowCoordinator { /// } /// ``` /// - /// - Parameter code: The JavaScript code to run, e.g., `console.log('Hello world')`. + /// - Parameter code: The JavaScript code to run, e.g., `"console.log('Hello world')"`. public func runJavaScript(_ code: String) { bridge.runJavaScript(code) } @@ -176,8 +176,8 @@ public class DescopeFlowCoordinator { if let flow { hooks.append(contentsOf: flow.hooks) } - for hook in hooks where event == hook.event { - hook.execute(coordinator: self) + for hook in hooks where hook.events.contains(event) { + hook.execute(event: event, coordinator: self) } } diff --git a/src/flows/FlowHook.swift b/src/flows/FlowHook.swift index ae2183e..1c73a3c 100644 --- a/src/flows/FlowHook.swift +++ b/src/flows/FlowHook.swift @@ -47,7 +47,7 @@ import WebKit open class DescopeFlowHook { /// The hook event determines when a hook is executed. - public enum Event { + public enum Event: String { /// The hook is executed when the flow is started with `start(flow:)`. /// /// - Note: The flow is not loaded and the `document` element isn't available @@ -77,24 +77,29 @@ open class DescopeFlowHook { /// test well any hook that uses it. case layout } - + /// When the hook should be executed. - public let event: Event - + public let events: Set + /// Creates a new ``DescopeFlowHook`` object. /// - /// - Parameter event: The event that determines when the hook is executed. In most - /// cases you'll use either `.loaded` or `.ready`. - public init(event: Event) { - self.event = event + /// - Parameter events: A set of events for which the hook will be executed. + public init(events: Set) { + self.events = events } - /// The function that's called when the ``event`` takes place. + /// Override this method to implement your hook. + /// + /// This method is called by the ``DescopeFlowCoordinator`` when one of the events in + /// the ``events`` set takes place. If the set has more than one member you can check + /// the `event` parameter and take different actions depending on the specific event. /// /// The default implementation of this method does nothing. /// - /// - Parameter coordinator: The ``DescopeFlowCoordinator`` that's running the flow. - open func execute(coordinator: DescopeFlowCoordinator) { + /// - Parameters: + /// - event: The event that took place. + /// - coordinator: The ``DescopeFlowCoordinator`` that's running the flow. + open func execute(event: Event, coordinator: DescopeFlowCoordinator) { } /// The list of default hooks. @@ -126,8 +131,8 @@ extension DescopeFlowHook { /// /// - Parameters: /// - event: When the hook should be executed, the default value is `.loaded`. - /// - selector: The CSS selector, e.g., `body`, `.container`, `html, body, #root`. - /// - rules: The CSS rules, e.g., `background-color: black`. + /// - selector: The CSS selector, e.g., `"body"` or `"html, .container"`. + /// - rules: The CSS rules, e.g., `"background-color: black"`. /// /// - Returns: A ``DescopeFlowHook`` object that can be added to the ``DescopeFlow/hooks`` array. public static func addStyles(on event: Event = .loaded, selector: String, rules: [String]) -> DescopeFlowHook { @@ -147,7 +152,7 @@ extension DescopeFlowHook { /// /// - Parameters: /// - event: When the hook should be executed, the default value is `.loaded`. - /// - css: The raw CSS to add, e.g., `.footer { display: none; }`. + /// - css: The raw CSS to add, e.g., `".footer { display: none; }"`. /// /// - Returns: A ``DescopeFlowHook`` object that can be added to the ``DescopeFlow/hooks`` array. public static func addStyles(on event: Event = .loaded, css: String) -> DescopeFlowHook { @@ -185,7 +190,7 @@ extension DescopeFlowHook { /// /// - Parameters: /// - event: When the hook should be executed, the default value is `.loaded`. - /// - code: The JavaScript code to run, e.g., `console.log('Hello world')`. + /// - code: The JavaScript code to run, e.g., `"console.log('Hello world')"`. /// /// - Returns: A ``DescopeFlowHook`` object that can be added to the ``DescopeFlow/hooks`` array. public static func runJavaScript(on event: Event = .loaded, code: String) -> DescopeFlowHook { @@ -340,10 +345,10 @@ private class AddStylesHook: DescopeFlowHook { init(event: Event, css: String) { self.css = css - super.init(event: event) + super.init(events: [event]) } - override func execute(coordinator: DescopeFlowCoordinator) { + override func execute(event: Event, coordinator: DescopeFlowCoordinator) { coordinator.addStyles(css) } } @@ -353,10 +358,10 @@ private class RunJavaScriptHook: DescopeFlowHook { init(event: Event, code: String) { self.code = code - super.init(event: event) + super.init(events: [event]) } - override func execute(coordinator: DescopeFlowCoordinator) { + override func execute(event: Event, coordinator: DescopeFlowCoordinator) { coordinator.runJavaScript(code) } } @@ -368,10 +373,10 @@ private class SetupSubviewHook: DescopeFlowHook { init(getter: @escaping (DescopeFlowCoordinator) -> T?, closure: @escaping (T) -> Void) { self.getter = getter self.closure = closure - super.init(event: .started) + super.init(events: [.started]) } - override func execute(coordinator: DescopeFlowCoordinator) { + override func execute(event: Event, coordinator: DescopeFlowCoordinator) { guard let object = getter(coordinator) else { return } closure(object) } @@ -410,14 +415,16 @@ private class BackgroundColorHook: DescopeFlowHook { init(selector: String, color: PlatformColor) { self.selector = selector self.color = color - super.init(event: .loaded) + super.init(events: [.started, .loaded]) } - override func execute(coordinator: DescopeFlowCoordinator) { - if #available(iOS 15.0, *) { + override func execute(event: Event, coordinator: DescopeFlowCoordinator) { + if event == .started { + guard #available(iOS 15.0, *) else { return } coordinator.webView?.underPageBackgroundColor = color + } else if event == .loaded { + coordinator.addStyles("\(selector) { background-color: \(colorStringValue); }") } - coordinator.addStyles("\(selector) { background-color: \(colorStringValue); }") } private var colorStringValue: String { diff --git a/src/flows/FlowViewController.swift b/src/flows/FlowViewController.swift index 56f4598..2ad5af2 100644 --- a/src/flows/FlowViewController.swift +++ b/src/flows/FlowViewController.swift @@ -95,12 +95,6 @@ open class DescopeFlowViewController: UIViewController { return underlyingView } - /// Override this method if you want your controller to use your own subclass - /// of ``DescopeFlowView`` as its underlying view. - open func createFlowView() -> DescopeFlowView { - return DescopeFlowView(frame: isViewLoaded ? view.bounds : UIScreen.main.bounds) - } - // UIViewController /// Called after the controller's view is loaded into memory. @@ -136,6 +130,12 @@ open class DescopeFlowViewController: UIViewController { // Flow + /// Override this method if you want your controller to use your own subclass + /// of ``DescopeFlowView`` as its underlying view. + open func createFlowView() -> DescopeFlowView { + return DescopeFlowView(frame: isViewLoaded ? view.bounds : UIScreen.main.bounds) + } + /// Loads and displays a Descope Flow. /// /// The ``delegate`` property should be set before calling this function to ensure