mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 21:28:21 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			158 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
			Vendored
		
	
	
	
// Copyright 2014 The Flutter Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style license that can be
 | 
						|
// found in the LICENSE file.
 | 
						|
 | 
						|
/**
 | 
						|
 * This script installs service_worker.js to provide PWA functionality to
 | 
						|
 *     application. For more information, see:
 | 
						|
 *     https://developers.google.com/web/fundamentals/primers/service-workers
 | 
						|
 */
 | 
						|
 | 
						|
if (!_flutter) {
 | 
						|
  var _flutter = {};
 | 
						|
}
 | 
						|
_flutter.loader = null;
 | 
						|
 | 
						|
(function() {
 | 
						|
  "use strict";
 | 
						|
  class FlutterLoader {
 | 
						|
    /**
 | 
						|
     * Creates a FlutterLoader, and initializes its instance methods.
 | 
						|
     */
 | 
						|
    constructor() {
 | 
						|
      // TODO: Move the below methods to "#private" once supported by all the browsers
 | 
						|
      // we support. In the meantime, we use the "revealing module" pattern.
 | 
						|
 | 
						|
      // Watchdog to prevent injecting the main entrypoint multiple times.
 | 
						|
      this._scriptLoaded = null;
 | 
						|
 | 
						|
      // Resolver for the pending promise returned by loadEntrypoint.
 | 
						|
      this._didCreateEngineInitializerResolve = null;
 | 
						|
 | 
						|
      // Called by Flutter web.
 | 
						|
      // Bound to `this` now, so "this" is preserved across JS <-> Flutter jumps.
 | 
						|
      this.didCreateEngineInitializer = this._didCreateEngineInitializer.bind(this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Initializes the main.dart.js with/without serviceWorker.
 | 
						|
     * @param {*} options
 | 
						|
     * @returns a Promise that will eventually resolve with an EngineInitializer,
 | 
						|
     * or will be rejected with the error caused by the loader.
 | 
						|
     */
 | 
						|
    loadEntrypoint(options) {
 | 
						|
      const {
 | 
						|
        entrypointUrl = "main.dart.js",
 | 
						|
        serviceWorker,
 | 
						|
      } = (options || {});
 | 
						|
      return this._loadWithServiceWorker(entrypointUrl, serviceWorker);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Resolves the promise created by loadEntrypoint.
 | 
						|
     * Called by Flutter through the public `didCreateEngineInitializer` method,
 | 
						|
     * which is bound to the correct instance of the FlutterLoader on the page.
 | 
						|
     * @param {*} engineInitializer
 | 
						|
     */
 | 
						|
    _didCreateEngineInitializer(engineInitializer) {
 | 
						|
      if (typeof this._didCreateEngineInitializerResolve != "function") {
 | 
						|
        console.warn("Do not call didCreateEngineInitializer by hand. Start with loadEntrypoint instead.");
 | 
						|
      }
 | 
						|
      this._didCreateEngineInitializerResolve(engineInitializer);
 | 
						|
      // Remove the public method after it's done, so Flutter Web can hot restart.
 | 
						|
      delete this.didCreateEngineInitializer;
 | 
						|
    }
 | 
						|
 | 
						|
    _loadEntrypoint(entrypointUrl) {
 | 
						|
      if (!this._scriptLoaded) {
 | 
						|
        this._scriptLoaded = new Promise((resolve, reject) => {
 | 
						|
          let scriptTag = document.createElement("script");
 | 
						|
          scriptTag.src = entrypointUrl;
 | 
						|
          scriptTag.type = "application/javascript";
 | 
						|
          // Cache the resolve, so it can be called from Flutter.
 | 
						|
          // Note: Flutter hot restart doesn't re-create this promise, so this
 | 
						|
          // can only be called once. Instead, we need to model this as a stream
 | 
						|
          // of `engineCreated` events coming from Flutter that are handled by JS.
 | 
						|
          this._didCreateEngineInitializerResolve = resolve;
 | 
						|
          scriptTag.addEventListener("error", reject);
 | 
						|
          document.body.append(scriptTag);
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      return this._scriptLoaded;
 | 
						|
    }
 | 
						|
 | 
						|
    _waitForServiceWorkerActivation(serviceWorker, entrypointUrl) {
 | 
						|
      if (!serviceWorker || serviceWorker.state == "activated") {
 | 
						|
        if (!serviceWorker) {
 | 
						|
          console.warn("Cannot activate a null service worker. Falling back to plain <script> tag.");
 | 
						|
        } else {
 | 
						|
          console.debug("Service worker already active.");
 | 
						|
        }
 | 
						|
        return this._loadEntrypoint(entrypointUrl);
 | 
						|
      }
 | 
						|
      return new Promise((resolve, _) => {
 | 
						|
        serviceWorker.addEventListener("statechange", () => {
 | 
						|
          if (serviceWorker.state == "activated") {
 | 
						|
            console.debug("Installed new service worker.");
 | 
						|
            resolve(this._loadEntrypoint(entrypointUrl));
 | 
						|
          }
 | 
						|
        });
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    _loadWithServiceWorker(entrypointUrl, serviceWorkerOptions) {
 | 
						|
      if (!("serviceWorker" in navigator) || serviceWorkerOptions == null) {
 | 
						|
        console.warn("Service worker not supported (or configured). Falling back to plain <script> tag.", serviceWorkerOptions);
 | 
						|
        return this._loadEntrypoint(entrypointUrl);
 | 
						|
      }
 | 
						|
 | 
						|
      const {
 | 
						|
        serviceWorkerVersion,
 | 
						|
        timeoutMillis = 4000,
 | 
						|
      } = serviceWorkerOptions;
 | 
						|
 | 
						|
      let serviceWorkerUrl = "flutter_service_worker.js?v=" + serviceWorkerVersion;
 | 
						|
      let loader = navigator.serviceWorker.register(serviceWorkerUrl)
 | 
						|
          .then((reg) => {
 | 
						|
            if (!reg.active && (reg.installing || reg.waiting)) {
 | 
						|
              // No active web worker and we have installed or are installing
 | 
						|
              // one for the first time. Simply wait for it to activate.
 | 
						|
              let sw = reg.installing || reg.waiting;
 | 
						|
              return this._waitForServiceWorkerActivation(sw, entrypointUrl);
 | 
						|
            } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
 | 
						|
              // When the app updates the serviceWorkerVersion changes, so we
 | 
						|
              // need to ask the service worker to update.
 | 
						|
              console.debug("New service worker available.");
 | 
						|
              return reg.update().then((reg) => {
 | 
						|
                console.debug("Service worker updated.");
 | 
						|
                let sw = reg.installing || reg.waiting || reg.active;
 | 
						|
                return this._waitForServiceWorkerActivation(sw, entrypointUrl);
 | 
						|
              });
 | 
						|
            } else {
 | 
						|
              // Existing service worker is still good.
 | 
						|
              console.debug("Loading app from service worker.");
 | 
						|
              return this._loadEntrypoint(entrypointUrl);
 | 
						|
            }
 | 
						|
          });
 | 
						|
 | 
						|
      // Timeout race promise
 | 
						|
      let timeout;
 | 
						|
      if (timeoutMillis > 0) {
 | 
						|
        timeout = new Promise((resolve, _) => {
 | 
						|
          setTimeout(() => {
 | 
						|
            if (!this._scriptLoaded) {
 | 
						|
              console.warn("Failed to load app from service worker. Falling back to plain <script> tag.");
 | 
						|
              resolve(this._loadEntrypoint(entrypointUrl));
 | 
						|
            }
 | 
						|
          }, timeoutMillis);
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      return Promise.race([loader, timeout]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  _flutter.loader = new FlutterLoader();
 | 
						|
}());
 |