PageSourceSearch

https://www.eisleben.eu/output/pwa/js/utility.js

js eisleben.eu collected 2026-10-02 11:23:13 UTC 10,434 bytes, 280 lines download raw bytes

1import * as c from './config.js';
2
3let deferredPrompt;    // Initialize deferredPrompt for use later to show browser install prompt.
4
5/******************   Install and Update *******************************/
6
7// Verhindert automatischen Install Prompt und zeigt Install Button an (Nicht IOS)
8export function beforeInstallPrompt(event) {
9    event.preventDefault();   // kleine infobar nicht anzeigen
10    console.log('beforeinstallprompt fired');
11    deferredPrompt = event;
12    
13    if (localStorage.getItem("closedPWAInstallBanner") != "true") {
14        showClass(c.get('pwaInstallBanner')); 
15		Array.from(c.getByClass('pwaInstallBut')).forEach(function(element) {
16            element.addEventListener('click', showInstallation);
17        }); 
18			    
19    	Array.from(c.getByClass('pwaInstallBannerClose')).forEach(function(element) {
20    		element.addEventListener('click', function (e) {
21    	    hideClass(c.get('pwaInstallBanner'));
22    	    localStorage.setItem("closedPWAInstallBanner", "true");});
23        });   
24    }
25    
26    return false;
27}
28
29// Da kein Install Prompt bei IOS gibt es hier eine gesonderte Abfrage
30export function checkIOSInstall() {  
31    if (isIos() && !isInStandaloneMode()) {
32      console.log('Detect installable IOS');
33      if (localStorage.getItem("closedpwaInstallBannerIOS") != "true") {
34        showClass(c.get('pwaInstallBannerIOS'));
35        Array.from(c.getByClass('pwaInstallBannerIOSClose')).forEach(function(element) {
36        	element.addEventListener('click', function (e) {
37        	    hideClass(c.get('pwaInstallBannerIOS'));
38        	    localStorage.setItem("closedpwaInstallBannerIOS", "true");});
39            });   
40        }
41    }
42}
43
44// Detects if device is on iOS 
45export const isIos = () => {
46    const userAgent = window.navigator.userAgent.toLowerCase();
47  
48  // Traditional detection
49  if (/iphone|ipad|ipod/.test(userAgent)) {
50    return true;
51  }
52  
53  // Additional check for iPadOS in desktop mode
54  if (/macintosh/.test(userAgent) && 'ontouchend' in document) {
55    return true;
56  }
57  
58  return false;
59}
60// Checks if should display install popup notification:
61export const isInStandaloneMode = () => ('standalone' in window.navigator) && (window.navigator.standalone);
62
63// Installation durch Button klick aufgerufen 
64export function showInstallation() {
65    console.log('👍', 'Install geklickt');
66    if (!deferredPrompt) {return;}
67    deferredPrompt.prompt();  // Show the install prompt.
68    deferredPrompt.userChoice.then(function(choiceResult) {
69        console.log(choiceResult.outcome);
70        if (choiceResult.outcome === 'dismissed') {
71            console.log('User cancelled installation');
72        } else {
73            console.log('User added to home screen');
74        }
75      });
76      // Hide the install button.
77    hideClass(c.get('pwaInstallBanner'));
78    hideClass(c.get('pwaInstallBannerIOS'));
79}
80
81// Wird nach der Installation aufgerufen
82export function appinstalled(event) {
83   console.log('👍', 'appinstalled', event);
84  // Platz Für Installations Counter
85  hideClass(c.get('pwaInstallBanner'));
86  hideClass(c.get('pwaInstallBannerIOS'));
87  deferredPrompt = null;
88}
89
90//Erkennt ob ein Neuer Service Worker auf Aktivierung wartet
91export function invokeServiceWorkerUpdateFlow(registration) {
92    console.log("New Service Worker waiting");
93    let uuid = c.getUUID();
94    showClass(c.get('pwaUpdateBanner'));
95    Array.from(c.getByClass('pwaUpdateBut')).forEach(function(element) {
96      element.addEventListener('click', async () => {
97        if (registration.waiting) {
98            // let waiting Service Worker know it should became active
99            registration.waiting.postMessage(JSON.stringify({uuid, cmd: 'setPushUUID'}));
100            registration.waiting.postMessage(JSON.stringify({cmd: 'SKIP_WAITING'}));
101        }
102      })
103    })
104}
105
106/******************   Notification *******************************/
107
108/* Notification Permission */
109export function askForNotificationPermission() {
110    Notification.requestPermission(function(result) {
111        console.log('Permission result:', result);
112        
113        if (result === "granted") {
114            hideClass(c.get('enableNotifications'));
115            showClass(c.get('pwaCategories'));
116            configurePushSub();
117        } else {
118            // Handle denial (including iOS soft denial)
119            const denialCount = parseInt(localStorage.getItem('notificationDenials') || '0') + 1;
120            localStorage.setItem('notificationDenials', denialCount.toString());
121            
122            if (denialCount >= 2) {
123                // After 2 attempts, treat as denied
124                hideClass(c.get('enableNotifications'));
125                showClass(c.get('blockedNotifications'));
126                localStorage.setItem("closedEnableNotification", "true");
127            } else {
128                // Show message but keep button available
129                console.log('Permission denied, attempt:', denialCount);
130                // Optionally show a message to user about trying again
131            }
132        }
133    });
134};
135
136export async function configurePushSub() {   
137    if (!('serviceWorker' in navigator)) return;   
138    try {
139        const reg = await navigator.serviceWorker.ready;
140        const sub = await reg.pushManager.getSubscription();
141        if (sub === null) {
142            const PublicKeyResponse =  await fetch('/output/pwa/get_wpnPublicServerKey.php');
143            const {key:wpnPublicServerKey}  = await PublicKeyResponse.json();
144            if (typeof wpnPublicServerKey !== 'string' || wpnPublicServerKey.length < 10) {
145                throw new Error('Bad Result from /output/pwa/get_wpnPublicServerKey.php');
146            }
147            const applicationServerKey = urlB64ToUint8Array(wpnPublicServerKey);
148            const options = {userVisibleOnly: true, applicationServerKey: applicationServerKey};
149			const newsub = await reg.pushManager.subscribe(options);
150			const {OK:code} = await saveSubscription(newsub);
151            console.log(code);
152            if (code == "200") {
153                reg.showNotification('Erfolgreich aktiviert!', {body: 'Benachrichtigungen erfolgreich aktiviert!',dir: 'ltr',lang: 'en-US', vibrate: [100, 50, 200]});
154                console.log('Sent Notification 1');
155				window.location = c.get('redirectNavID');
156            } else {
157                console.log("Fehler")
158            } 
159        } else {
160            console.log("Anmeldung existiert");
161			window.location = c.get('redirectNavID');
162        }
163    } catch (error) {
164      console.error(error);
165    }
166}
167
168/* For Key Generation*/
169export const urlB64ToUint8Array = base64String => {
170    const padding = '='.repeat((4 - (base64String.length % 4)) % 4)
171    const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/')
172    const rawData = atob(base64)
173    const outputArray = new Uint8Array(rawData.length)
174    for (let i = 0; i < rawData.length; ++i) {
175        outputArray[i] = rawData.charCodeAt(i)
176    }
177    return outputArray
178};
179
180/* Save Subcription */
181export const saveSubscription = async (subscription) => {
182    let uuid = c.getUUID();
183    subscription = JSON.stringify(subscription);
184    subscription = JSON.parse(subscription);
185    console.log(subscription.keys.auth);
186    let formData = new FormData();
187    formData.append('endpoint', subscription.endpoint);
188    formData.append('p256dh', subscription.keys.p256dh);
189    formData.append('auth', subscription.keys.auth);
190    formData.append('uuid', uuid);
191    const response = await fetch('/output/pwa/saveSubscription.php', {
192        method: 'post',
193        body: formData,
194    });
195    console.log(response);
196    return response.json();
197};
198
199/* Notify From Browser */
200export function notifyMe() {
201    console.log("NotifyMe");
202    if (!("Notification" in window)) {
203        // Check if the browser supports notifications
204        console.log('Dieser Browser Unterstüzt keine Notification');
205    } else if (Notification.permission === "granted") {
206        // Check whether notification permissions have already been granted;
207        // if so, create a notification
208        console.log('Sent Notification');
209        if ('serviceWorker' in navigator) {
210            var options = {
211                body: 'You successfully subscribed to our Notification service!',
212                dir: 'ltr',
213                lang: 'en-US', // BCP 47,
214                vibrate: [100, 50, 200],
215            };
216            navigator.serviceWorker.ready
217                .then(function(swreg) {
218                    console.log('Subscribe Notification');
219                    swreg.showNotification('Successfully subscribed (from SW)!', options);
220                });
221        }
222    } else if (Notification.permission !== "denied") {
223        // We need to ask the user for permission
224        Notification.requestPermission().then((permission) => {
225            // If the user accepts, let's create a notification
226            if (permission === "granted") {
227                console.log('Sent Notification');
228                const notification = new Notification("You successfully subscribed to our Notification service!");
229                // …
230            }
231        });
232    }
233}
234
235/******************   HELPER *******************************/
236
237export function hideClass(data) {
238    console.log("hide: ",data);
239    let dataClass = document.querySelectorAll(data);
240        Array.from(dataClass).forEach(function(element) {
241                element.style.display = "none";
242            });      
243}
244
245export function showClass(data) {
246    console.log("show: ",data);
247    let dataClass = document.querySelectorAll(data);
248        Array.from(dataClass).forEach(function(element) {
249                element.style.display = "inline-block";
250            });      
251}
252
253/* Noch nicht verwendete Möglichkeiten */
254//Möglichkeit den Display Modus zu tracken
255// Noch nicht aufgerufen
256export function getPWADisplayMode() {
257  const isStandalone = window.matchMedia('(display-mode: standalone)').matches;
258  if (document.referrer.startsWith('android-app://')) {
259    return 'twa';
260  } else if (navigator.standalone || isStandalone) {
261    return 'standalone';
262  }
263  return 'browser';
264}
265
266window.matchMedia('(display-mode: standalone)').addEventListener('change', (evt) => {
267  let displayMode = 'browser';
268  if (evt.matches) {
269    displayMode = 'standalone';
270  }
271  // Log display mode change to analytics
272  console.log('DISPLAY_MODE_CHANGED', displayMode);
273});
274
275
276	
277
278
279
280

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.