Changelog

2.0.2

Avoid flash of white

A quick flash of white could be seen for apps not using placeholder-content. This was caused by the uninitialized webview being visible, and should now no longer happen.

2.0.1

Upgrade trustkit dependency

Upgraded from 1.6.0 to 1.7.0

2.0.0

Naming (breaking)

The framework as well as a number of classes have been renamed. The initial implementation had the framework called Subaio and many classes prefixed with Subaio. The framework and import has been renamed to FintechBridge (full package name com.subaio.FintechBridge). The following classes/protocols have been renamed:

Share event removed (breaking)

BridgeViewDelegate.bridgeView(_:isAttemptingToShare:) has been moved to an internal handler. Since sharing can already be disabled during configuration, it seems unnecessary to require an implementation from library consumers, and it is unlikely that custom logic will be needed.

Titles can now be nil (breaking)

BridgeViewDelegate.bridgeView(_:updatedTitleTo:) can now receive nil as a title. Ordinarily, this will not happen, but it can be used to indicate that the header should be hidden. Unless it is agreed that a nil-title is sent, it is safe to assume that the title is never nil.

Configuration (breaking)

The SubaioConfiguration class has been removed entirely. The options normally passed to the SubaioConfiguration constructor should now be passed directly into the BridgeManager.configure(...) call.

As a convenience, language can now also be passed to BridgeManager.configure(...) as the second parameter.

Synchronicity

Previously, the configure call was asynchronous. During the configuration, base-HTML and placeholder images were fetched, and an initial token was requested.

All this initialization has been moved to the creation of the first view. Calling configure is now entirely passive and synchronous, and can thus be done whenever convenient, as long as it is before the first view is created.

SSL pinning

To allow the usage of other libraries for authentication, TrustKit has been moved to an optional dependency, FintechBridgeTrustKit. This additional library is distributed alongside the main bridge. In it, the TrustKitAuthenticationChallenger should be imported and passed to the configure call as authenticationChallenger. Its constructor is identical to now-removed SubaioSSLPinningConfiguration.

If using Swift Packages, include both FintechBridge and FintechBridgeTrustKit as dependencies from this repository. TrustKit should be downloaded automatically.

If using Carthage, explicitly add TrustKit as a dependency in your Cartfile:

github "datatheorem/TrustKit" ~> 1.6.0

If another library than TrustKit is used for SSL pinning or to otherwise validate connections, the AuthenticationChallenger protocol should be implemented and passed to the manager.

If default handling of SSL is sufficient, DefaultAuthenticationChallenger can be used. It is required to ensure explicit disabling of SSL pinning.

Example

BridgeManager.shared.configure(
    baseUrl: URL(string: "...")!,
    language: "...",
    allowExternalUrls: true,
    allowShare: true,
    authenticationChallenger: TrustKitAuthenticationChallenger(for: [
        .init(domain: "subaio.com", publicKeyHashes: [
            "..."
        ])
    ]),
    onTokenRequired: { (language, completionHandler) in

    },
    customConfig: ["...": "..."]
)

Resize reporting moved to event (breaking)

The previous implementation of reporting content size relied on an internal constraint being added, which is not idiomatic swift. This constraint has been removed, and instead the updated height is reported to BridgeViewDelegate.bridgeView(_:resizedTo:). The implementation can then choose to add a constraint or use the view frame, and animate the change if necessary.

The event will only be sent if reportResize is set to true in the BridgeView constructor. This is necessary as the underlying view will otherwise attempt to fill the view, and thus never shrink.

Multiple manager instances (feature)

The BridgeManager constructor is now public, allowing manual administration of a single manager and allowing multiple instances to co-exist. Example:

// Using shared manager
BridgeManager.shared.configure(...)
let view = BridgeView(page: ...)

// Using own manager instance
let manager = BridgeManager()
manager.configure(...)
let view = BridgeView(page: ..., manager: manager)

Be aware that related views should share their manager. There is an initialization overhead when the first view is created for a manager, tokens are maintained and shared through the manager, and the views communicate to refresh stale data through the manager, so creating a new manager for every view is not a good idea. Multiple managers should only be used if multiple apps are embedded.

Prewarming cache (feature)

Previously, base-HTML and placeholder images were fetched on configuration. This has now been moved to first view creation. Since it will have no cached placeholder images, the very first BridgeView a device opens might experience a short flash of white. To avoid this, you can call BridgeManager.prewarm() at any point after configuration to ensure the cache is populated. Note that this is optional.

Custom actions and events (feature)

Support has been added for custom actions (sent to the embedded app) and events (sent from the embedded app). They generally consist of a name and some data, both of which should be agreed upon between the host and embedded apps.

Example of a custom event being used for navigation in the host application:

extension MyBridgeViewDelegate: BridgeViewDelegate {
    ...
    func bridgeView(_ bridgeView: BridgeView, receivedCustomEvent name: String, data: Any?) {
        switch (name) {
        case ("navigateExternal"):
            guard
                let dictionary = data as? [String: Any],
                let name = dictionary["name"] as? String,
                let params = dictionary["params"] as? [String: String]
            else {
                break
            }
            print("Go to native \(name) \(params)")
        default:
            print("Custom event: \(name) \(String(describing: data))")
        }
    }
}

Example of a custom action being used to control internal scroll:

bridgeView.sendCustomAction(name: "scroll", data: "top")

Optional events (feature)

Previously, all events on BridgeViewDelegate had to be implemented, even though a number of them were unnecessary for a functional implementation. A default no-op implementation has been added to these events.

Events that require implementation:

Events that are optional:

Enable scroll bounce (feature)

Webview scroll bounce can now be enabled through the BridgeView.bounces property. Note that it is impossible to define different background colors for top and bottom bounce, resulting in visual glitches if a colored header is used.

Token management (internal)

The BridgeManager will no longer maintain a token while there are no active BridgeViews, nor will it automatically refresh the token before it expires. New tokens are only requested when

  • A view is created and there is no token
  • A view is created and the current token is expired
  • A request from a view failed because of an expired token

The implementation of onTokenRequired should stay unchanged.