PageSourceSearch

https://insights.market/static/js/pwa.js

js insights.market collected 2026-10-06 13:18:30 UTC 4,103 bytes, 161 lines download raw bytes

1(function () {
2  const STORAGE_KEY = 'insights-market-pwa-dismissed';
3  let deferredPrompt = null;
4  let installContainer = null;
5  let installButton = null;
6  let iosHintVisible = false;
7
8  function isIos() {
9    const ua = window.navigator.userAgent || '';
10    return /iphone|ipad|ipod/i.test(ua);
11  }
12
13  function isStandalone() {
14    return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true;
15  }
16
17  function isDismissed() {
18    try {
19      return window.localStorage.getItem(STORAGE_KEY) === '1';
20    } catch (error) {
21      return false;
22    }
23  }
24
25  function setDismissed() {
26    try {
27      window.localStorage.setItem(STORAGE_KEY, '1');
28    } catch (error) {
29      // Ignore storage issues.
30    }
31  }
32
33  function showContainer() {
34    if (installContainer) {
35      installContainer.classList.remove('hidden');
36    }
37  }
38
39  function hideContainer() {
40    if (installContainer) {
41      installContainer.classList.add('hidden');
42    }
43  }
44
45  function updateButtonLabel(label) {
46    if (installButton && label) {
47      installButton.textContent = label;
48    }
49  }
50
51  function showToast(message) {
52    const toast = document.createElement('div');
53    toast.setAttribute('role', 'status');
54    toast.style.position = 'fixed';
55    toast.style.left = '50%';
56    toast.style.bottom = '24px';
57    toast.style.transform = 'translateX(-50%)';
58    toast.style.zIndex = '9999';
59    toast.style.maxWidth = 'min(92vw, 360px)';
60    toast.style.padding = '12px 16px';
61    toast.style.borderRadius = '9999px';
62    toast.style.background = 'rgba(15, 23, 42, 0.96)';
63    toast.style.color = '#fff';
64    toast.style.fontSize = '14px';
65    toast.style.lineHeight = '1.4';
66    toast.style.boxShadow = '0 12px 28px rgba(15, 23, 42, 0.28)';
67    toast.textContent = message;
68    console.log(message)
69    document.body.appendChild(toast);
70    window.setTimeout(() => {
71      toast.style.opacity = '0';
72      toast.style.transition = 'opacity 180ms ease';
73      window.setTimeout(() => toast.remove(), 220);
74    }, 3200);
75  }
76
77  function showIosHint() {
78    if (iosHintVisible) {
79      return;
80    }
81    iosHintVisible = true;
82    showToast('Tap Share, then choose Add to Home Screen to install this app.');
83  }
84
85  async function registerServiceWorker() {
86    const isLocal =
87      location.hostname === 'localhost' ||
88      location.hostname === '127.0.0.1';
89
90    if (!('serviceWorker' in navigator) && !isLocal) {
91      return;
92    }
93
94    try {
95      await navigator.serviceWorker.register('/sw.js', { scope: '/' });
96    } catch (error) {
97      console.warn('Service worker registration failed:', error);
98    }
99  }
100
101  async function handleInstallClick() {
102    if (deferredPrompt) {
103      deferredPrompt.prompt();
104      const choice = await deferredPrompt.userChoice;
105      deferredPrompt = null;
106
107      if (choice && choice.outcome === 'accepted') {
108        setDismissed();
109        hideContainer();
110      }
111      return;
112    }
113
114    if (isIos()) {
115      showIosHint();
116      return;
117    }
118
119    showToast('Use your browser menu to install the app on this device.');
120  }
121
122  function initInstallUi() {
123    installContainer = document.getElementById('pwaInstallContainer');
124    installButton = document.getElementById('pwaInstallButton');
125
126    if (!installContainer || !installButton || isStandalone() || isDismissed()) {
127      hideContainer();
128      return;
129    }
130
131    if (isIos()) {
132      updateButtonLabel('Add to Home Screen');
133      showContainer();
134    }
135
136    installButton.addEventListener('click', handleInstallClick);
137  }
138
139  window.addEventListener('beforeinstallprompt', function (event) {
140    event.preventDefault();
141    deferredPrompt = event;
142
143    if (!installContainer || !installButton || isStandalone() || isDismissed()) {
144      return;
145    }
146
147    updateButtonLabel('Install App');
148    showContainer();
149  });
150
151  window.addEventListener('appinstalled', function () {
152    deferredPrompt = null;
153    setDismissed();
154    hideContainer();
155  });
156
157  window.addEventListener('DOMContentLoaded', function () {
158    initInstallUi();
159    registerServiceWorker();
160  });
161})();

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.