Example #1
0
        public async Task <string> BuildPwaInitScript(HttpContext context, IUrlHelper urlHelper)
        {
            var url = urlHelper.RouteUrl(_pwaRouteNameProvider.GetServiceWorkerRouteName());

            var script = new StringBuilder();

            await _configurePushApiMethods.AppendToInitScript(script, context, urlHelper);

            var canShowPush = true;

            if (_options.RequireCookieConsentBeforeRegisteringServiceWorker)
            {
                var consentFeature = context.Features.Get <ITrackingConsentFeature>();
                if (consentFeature != null && !consentFeature.CanTrack)
                {
                    canShowPush = false;
                }
            }

            if (canShowPush)
            {
                var assembly         = typeof(DefaultGeneratePwaInitScript).GetTypeInfo().Assembly;
                var userSettingsFile = baseResourcePath + "push-user-settings.min.js";
                using (var resourceStream = assembly.GetManifestResourceStream(userSettingsFile))
                {
                    using (StreamReader reader = new StreamReader(resourceStream))
                    {
                        string s = reader.ReadToEnd();

                        script.Append(s);
                    }
                }
            }



            if (_options.SetupInstallPrompt)
            {
                script.Append("let deferredPrompt;");
                //script.Append("let divPrompt = document.getElementById('divPwaInstallPrompt');");
                script.Append("let btnInstall = document.getElementById('btnPwaInstall');");
                //script.Append("let pwaHeading = document.getElementById('pwaInstallHeading');");
                script.Append("if(btnInstall) {");


                script.Append("window.addEventListener('beforeinstallprompt', (e) => {");
                // Prevent Chrome 67 and earlier from automatically showing the prompt
                script.Append("e.preventDefault();");
                // Stash the event so it can be triggered later.
                script.Append("deferredPrompt = e;");

                //update the UI notify the user
                //script.Append("divPrompt.classList.add('show');");
                //script.Append("divPrompt.style.display ='block';");
                //script.Append("pwaHeading.style.display = 'block';");
                script.Append("btnInstall.style.display = 'inline-block';");

                script.Append("});");


                script.Append("btnInstall.addEventListener('click', (e) => {");

                //script.Append("document.getElementById('divPwaInstallPrompt').classList.remove('show');");
                // script.Append("divPrompt.style.display ='none';");
                // Show the prompt
                script.Append("deferredPrompt.prompt();");
                // Wait for the user to respond to the prompt
                script.Append("deferredPrompt.userChoice");
                script.Append(".then((choiceResult) => {");
                script.Append("if (choiceResult.outcome === 'accepted') {");
                script.Append("console.log('User accepted the A2HS prompt');");
                script.Append("} else {");
                script.Append("console.log('User dismissed the A2HS prompt');");
                script.Append("}");
                script.Append("deferredPrompt = null;");
                script.Append("});");
                script.Append("});");


                script.Append("} ");
            }



            script.AppendLine("import {Workbox} from '" + _options.WorkBoxWindowModuleUrl + "';");


            script.Append("if ('serviceWorker' in navigator) {");
            //script.Append("window.addEventListener('load', () => {");

            var scope = _pwaRouteNameProvider.GetServiceWorkerScope();

            script.Append("const wb = new Workbox('" + url + "',{scope: '" + scope + "'});");

            //activated event
            script.Append("wb.addEventListener('activated', (event) => {");

            script.Append("if (!event.isUpdate) {");
            script.Append("console.log('Service worker activated for the first time');");
            script.Append("} else {");
            script.Append("console.log('Service worker activated');");
            script.Append("}");

            var items = new List <ServiceWorkerCacheItem>();

            foreach (var provider in _preCacheProviders)
            {
                var i = await provider.GetItems();

                items.AddRange(i);
            }

            script.Append("const urlsToCache = [");
            var comma = "";

            foreach (var item in items)
            {
                script.Append(comma);
                if (!string.IsNullOrEmpty(item.Revision))
                {
                    script.Append("{");
                    script.Append("\"url\": \"" + item.Url + "\",");
                    script.Append("\"revision\": \"" + item.Revision + "\"");

                    script.Append("}");
                }
                else
                {
                    script.Append("'" + item.Url + "'");
                }

                comma = ",";
            }


            script.Append("];");
            script.Append("wb.messageSW({");
            script.Append("type: 'CACHE_URLS',");
            script.Append("payload: {urlsToCache} ");
            script.Append("});");



            script.Append("});"); //end activated event



            script.Append("wb.addEventListener('waiting', (event) => {");
            script.Append("console.log('new service worker waiting');");
            script.Append("});");

            script.Append("wb.addEventListener('installed', (event) => {");
            script.Append("if (!event.isUpdate) {");
            // First-installed code goes here...
            script.Append("console.log('Service worker installed for the first time');");
            script.Append("} else {");
            script.Append("console.log('new service worker installed');");
            script.Append("}");
            script.Append("});");

            script.Append("wb.addEventListener('controlling', (event) => {");
            script.Append("console.log('new service worker controlling');");

            if (_options.ReloadPageOnServiceWorkerUpdate)
            {
                script.Append("var refreshing;");

                if (_options.EnableServiceWorkerConsoleLog)
                {
                    script.Append("console.log('Controller loaded');");
                }

                script.Append("if (refreshing) return;");
                script.Append("refreshing = true;");
                script.Append("if(!window.location.href.indexOf('account') > -1) {");


                if (_options.EnableServiceWorkerConsoleLog)
                {
                    script.Append("console.log('reloading page because service worker updated');");
                }
                //this causes login to fail
                script.Append("window.location.reload();");

                script.Append("}");
            }

            script.Append("});");

            script.Append("wb.addEventListener('redundant', (event) => {");
            script.Append("console.log('service worker redundant fired');");
            script.Append("});");

            script.Append("wb.addEventListener('externalinstalled', (event) => {");
            script.Append("console.log('service worker externalinstalled fired');");
            script.Append("});");

            script.Append("wb.addEventListener('externalwaiting', (event) => {");
            script.Append("console.log('service worker externalwaiting fired');");
            script.Append("});");

            script.Append("wb.addEventListener('externalactivated', (event) => {");
            script.Append("console.log('service worker externalactivated fired');");
            script.Append("});");

            //listen for messages from sw
            script.Append("wb.addEventListener('message', (event) => {");

            script.Append("console.log(`message received from serviceworker`);");
            script.Append("console.log(event);");

            //script.Append("if (event.data.type === 'CACHE_UPDATED') {");
            //script.Append("const {updatedURL} = event.data.payload;");
            //script.Append("console.log(`A newer version of ${updatedURL} is available!`);");
            //script.Append("} else {");
            //script.Append("console.log(`message received from serviceworker`);");
            //script.Append("console.log(event);");
            //script.Append("}");


            script.Append("}); ");// end message listener


            script.Append("if ('BroadcastChannel' in window) {");

            script.Append("const channel = new BroadcastChannel('app-channel');");
            script.Append("channel.onmessage = function(e) {");
            script.Append("console.log('received message on app channel');");
            script.Append("console.log(e);");

            script.Append("if(e.data.type === 'cacheupdate' && e.data.url === window.location.href) {");
            script.Append("console.log('cache update for current url so reloading');");
            script.Append("window.location.reload();");
            script.Append("}");
            script.Append("};");

            script.Append("} else {");
            script.Append("console.log('Broadcast channel not supported');");
            script.Append("} ");


            // Register the service worker after event listeners have been added.
            script.Append("wb.register();");


            // script.Append("});"); //end load event

            script.Append("if ('MessageChannel' in window) {");

            script.Append("navigator.serviceWorker.ready.then(function (serviceWorkerRegistration) {");
            script.Append("console.log('serviceworker ready');");

            script.Append("setTimeout(function() {");

            script.Append("if(navigator.serviceWorker.controller) {");
            script.Append("const messageChannel = new MessageChannel();");
            script.Append("navigator.serviceWorker.controller.postMessage(");
            script.Append("{type:'page-ready'}");
            script.Append(", [messageChannel.port2]);");
            script.Append("}");

            script.Append("},3000);");


            script.Append("});"); //end serviceworker ready

            script.Append("} else {");
            script.Append("console.log('MessageChannel not supported');");
            script.Append("} "); //end if MessageChannel



            script.Append("}"); //end serviceworker in navigator


            return(script.ToString());
            //return Task.FromResult(script.ToString());
        }