EddyVerbruggen / nativescript-webview-utils

🕸Add request headers to a NativeScript WebView. Perhaps more utils later.
Apache License 2.0
20 stars 17 forks source link

LoadStarted WebView event doesn't trigger on Android #15

Open AlexTiehuis opened 4 years ago

AlexTiehuis commented 4 years ago

I am using [loadStarted] and [loadFinished] events in a Webview in NativeScript/Angular, among other things, to start and stop a spinner. On my iPhone both events are triggered as soon as navigation starts and ends. On my Android phone the loadStarted event isn't triggered causing the spinner to malfunction. Looks like only links with tel:, mailto: and loc: trigger the [loadStarted] event.

In node module [webview-utils.android.js], function [onPageStarted], line 47 there is this If statement: if (!isHttpRequest || ++this.startEventCount === 1) The ++ increments this.startEventCount while testing === 1 which will only be true the first time a pageLoad starts. In my opinion this causes the loadStarted event to be called only once (unless the url starts with [tel:, mailto: or loc:]) Having fixed this locally, I noticed that the loadStarted event is triggered too late. Showing the spinner only a few milliseconds before the webpage finishes loading.

Non-trigger and too late trigger of [loadStarted] both don't work for my App. Are there solutions to these problems?

XML:

<ActionBar #webviewActionbar title="Facilitor" flat="true">
    <ActionItem (tap)="onQrScanTap()" ios.position="right" ios.systemIcon="15" android.systemIcon="ic_menu_camera">
    </ActionItem>
</ActionBar>
<GridLayout rows="*">
    <WebView row="0" #loginView (loaded)="webviewLoaded($event);" (loadStarted)="webviewTrigger($event)" (loadFinished)="onLoadFinished($event)" (doubleTap)="onDoubleTap($event)" (swipe)="onSwipe($event)" [src]="webViewSrc" ></WebView>
    <TextField row="0" [(ngModel)]="registerModel.push_action" #pushActionModel="ngModel" autocorrect="false"
    autocapitalizationType="none" [visibility]="'collapse'" (textChange)="navigateToAction()"></TextField>
    <ActivityIndicator (loaded)="onSpinnerLoaded($event)" rowSpan="2" [busy]="isBusy" (busyChange)="onBusyChanged($event)" width="100" height="100"></ActivityIndicator>
</GridLayout>

TypeScript:

  private onLoadFinished(args: any) {
    console.log("== onLoadFinished ==");
    this.isBusy = false;
  }
  private webviewTrigger(args: any) {
    console.log("== webviewTrigger ==");
    var webView: WebView = <WebView>args.object;
    console.log(webView);
    // get location
    if (args.url.startsWith('loc:')) {
      let arr = args.url.split(":");
      this.registerModel.push_action = this.registrationService.composeUrl() + arr[1] + "?longitude=" + this.lastLocation.longitude + "&latitude=" + this.lastLocation.latitude;
      this.navigateToAction();
      webView.reload();
      return;
    // handle mailto: and tel:
    } else if (args.url.startsWith('mailto:') || args.url.startsWith('tel:')) {
      utils.openUrl(args.url);
      webView.reload();
      return;
    }
    // start spinner
    this.isBusy = true;
  }

Terminal log after tapping some links:

JS: == onNavigatingTo ==
chromium: [INFO:library_loader_hooks.cc(51)] Chromium logging enabled: level = 0, default verbosity = 0
JS: == webviewLoaded ==
JS: WebView(44)
JS: == setHTTPHeader ==
JS: == onSpinnerLoaded ==
JS: == onNavigatedTo ==
JS: == webviewTrigger ==
JS: WebView(44)
JS: indicator.busy changed to: true
JS: ===Location===
JS: == onLoadFinished ==
JS: indicator.busy changed to: false
JS: == onLoadFinished ==
JS: == onLoadFinished ==
JS: == onLoadFinished ==
AlexTiehuis commented 4 years ago

I adjusted the webview-utils.android.js somewhat with the little knowledge I have about NativeScript. The [onLoadStarted] event triggers at the right time with below code:

    WebViewUtils.prototype.shouldOverrideUrlLoading = function(webView, urlOrWebResourceRequest) {
        console.log("shouldOverrideUrlLoading");
        var url = typeof urlOrWebResourceRequest === "string" ? urlOrWebResourceRequest : urlOrWebResourceRequest.getUrl().toString();
        var headersAdded = this.headersAddedTo.has(url);
        var isHttpRequest = url.indexOf("http") === 0;
        if (!isHttpRequest || (headersAdded && WebViewUtils.wv) || ++this.startEventCount > 1) {
            webview_utils_common_1.onLoadStarted(WebViewUtils.wv, url, undefined);
        }
        webView.loadUrl(url, this.getAdditionalHeadersForUrl(url));
        return true;
    };
    WebViewUtils.prototype.onPageStarted = function(webView, url, favicon) {
        _super.prototype.onPageStarted.call(this, webView, url, favicon);
        var headersAdded = this.headersAddedTo.has(url);
        var isHttpRequest = url.indexOf("http") === 0;
        if (isHttpRequest && !headersAdded) {
            ++this.startEventCount;
            this._view.android.loadUrl(url, this.getAdditionalHeadersForUrl(url));
            if (WebViewUtils.wv) {
                webview_utils_common_1.onLoadStarted(WebViewUtils.wv, url, undefined);
            }
        }
    };
AlexTiehuis commented 4 years ago

Not sure why this issue was closed. Can't remember having it closed. Probably mis-clicked.