PageSourceSearch

https://www.mk.ru/sw/pwa-ui-install.js

js mk.ru collected 2026-10-02 06:25:45 UTC 5,958 bytes, 171 lines download raw bytes

1(function (root) {
2    'use strict';
3
4    root.MKPwaUi = root.MKPwaUi || { layers: {} };
5
6    root.MKPwaUi.layers.createInstallLayer = function createInstallLayer(context) {
7        var deferredInstallPrompt = null;
8        var installed = false;
9        var promptPending = false;
10        var nativeInstallAvailable = false;
11        var publishedMode;
12
13        var isIos = /iPad|iPhone|iPod/.test(root.navigator.userAgent) || (root.navigator.platform === 'MacIntel' && root.navigator.maxTouchPoints > 1);
14        var isStandalone = root.matchMedia('(display-mode: standalone)').matches || root.navigator.standalone === true;
15        var isIosSafari = isIos && /Safari/i.test(root.navigator.userAgent) && !/CriOS|FxiOS|EdgiOS|YaBrowser/i.test(root.navigator.userAgent);
16
17        if (isStandalone) {
18            trackYmGoal('use_pwa');
19        }
20
21
22        function trackYmGoal(goalName) {
23            if (typeof root.ym !== 'function') {
24                return;
25            }
26
27            root.ym(1598573, 'reachGoal', goalName);
28        }
29
30        function getInstallMode() {
31            if (installed || isStandalone) {
32                return 'unavailable';
33            }
34            // Keep the CTA visible after consuming an event, until installation.
35            // Click readiness is checked separately using deferredInstallPrompt.
36            if (nativeInstallAvailable) {
37                return 'native';
38            }
39            if (isIosSafari) {
40                return 'ios-manual';
41            }
42            return 'unavailable';
43        }
44
45        function publishInstallState() {
46            var mode = getInstallMode();
47            if (mode === publishedMode) {
48                return;
49            }
50            publishedMode = mode;
51            document.documentElement.toggleAttribute(
52                'data-pwa-install-available',
53                mode !== 'unavailable'
54            );
55            root.dispatchEvent(new Event('mk:pwa-install-state-change'));
56        }
57
58        root.MKPwaUi.getInstallMode = getInstallMode;
59
60        function finishPrompt(choice) {
61            promptPending = false;
62            if (choice && choice.outcome === 'accepted') {
63                installed = true;
64                deferredInstallPrompt = null;
65                nativeInstallAvailable = false;
66            }
67            publishInstallState();
68        }
69
70        function handleInstallButtonClick(button) {
71            var promptEvent;
72            var promptResult;
73
74            var mode = getInstallMode();
75            if (mode === 'unavailable' || promptPending
76                || (mode === 'native' && !deferredInstallPrompt)) {
77                return;
78            }
79
80            var goalName = 'click_install_pwa';
81            if (button.classList.contains('header-logo__button-pwa')) {
82                goalName = 'click_top_install_pwa';
83            } else if (button.classList.contains('landing__button-pwa')) {
84                goalName = 'click_landing_install_pwa';
85            }
86            trackYmGoal(goalName);
87            if (mode === 'ios-manual') {
88                root.alert('Чтобы установить приложение на iPhone/iPad: нажмите «Поделиться» в Safari и выберите «На экран Домой».');
89                return;
90            }
91
92            promptEvent = deferredInstallPrompt;
93            deferredInstallPrompt = null;
94            promptPending = true;
95
96            try {
97                promptResult = promptEvent.prompt();
98            } catch (error) {
99                finishPrompt(null);
100                context.logger.warn('[PWA]', 'install.prompt.failed', error);
101                return;
102            }
103
104            Promise.resolve(promptResult).then(function () {
105                return promptEvent.userChoice;
106            }).then(function (choice) {
107                finishPrompt(choice);
108            }).catch(function (error) {
109                finishPrompt(null);
110                context.logger.warn('[PWA]', 'install.choice.failed', error);
111            });
112        }
113
114        document.addEventListener('click', function (event) {
115            var target = event.target;
116            if (target && target.nodeType !== 1) {
117                target = target.parentElement;
118            }
119            var button = target && target.closest(context.config.domInstallButtonSelector);
120            if (!button || button.disabled || button.getAttribute('aria-disabled') === 'true') {
121                return;
122            }
123
124            event.preventDefault();
125            handleInstallButtonClick(button);
126        });
127
128        root.addEventListener('beforeinstallprompt', function (event) {
129            context.trackPwaEvent('pwa_install_prompt_shown', {
130                mode: isStandalone ? 'standalone' : 'browser',
131                is_ios: isIos,
132                is_ios_safari: isIosSafari
133            });
134
135            if (isStandalone || installed) {
136                return;
137            }
138
139            event.preventDefault();
140            deferredInstallPrompt = event;
141            nativeInstallAvailable = true;
142            publishInstallState();
143            context.logger.info('[PWA]', 'install.prompt.ready');
144        });
145
146        root.addEventListener('appinstalled', function () {
147            deferredInstallPrompt = null;
148            installed = true;
149            promptPending = false;
150            nativeInstallAvailable = false;
151            publishInstallState();
152
153            trackYmGoal('install_pwa');
154
155            context.trackPwaEvent('pwa_install_completed', {
156                mode: isStandalone ? 'standalone' : 'browser',
157                is_ios: isIos,
158                is_ios_safari: isIosSafari
159            });
160            context.logger.info('[PWA]', 'install.completed');
161        });
162
163        publishInstallState();
164
165        return {
166            isStandalone: function () {
167                return isStandalone;
168            }
169        };
170    };
171})(window);

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.