PageSourceSearch

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

js mk.ru collected 2026-09-25 06:24:48 UTC 5,349 bytes, 141 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 installButton = null;
9        var installButtonMode = 'none';
10
11        var isIos = /iPad|iPhone|iPod/.test(root.navigator.userAgent) || (root.navigator.platform === 'MacIntel' && root.navigator.maxTouchPoints > 1);
12        var isStandalone = root.matchMedia('(display-mode: standalone)').matches || root.navigator.standalone === true;
13        var isIosSafari = isIos && /Safari/i.test(root.navigator.userAgent) && !/CriOS|FxiOS|EdgiOS|YaBrowser/i.test(root.navigator.userAgent);
14
15        if (isStandalone) {
16            trackYmGoal('use_pwa');
17        }
18
19
20        function trackYmGoal(goalName) {
21            if (typeof root.ym !== 'function') {
22                return;
23            }
24
25            root.ym(1598573, 'reachGoal', goalName);
26        }
27
28        function showManualInstallHint() {
29            if (isIosSafari) {
30                alert('Чтобы установить приложение на iPhone/iPad: нажмите «Поделиться» в Safari и выберите «На экран Домой».');
31                return;
32            }
33            alert('Чтобы установить приложение: откройте меню браузера (⋮) и выберите «Установить приложение» или «Добавить на главный экран».');
34        }
35
36        function resolveInstallButton() {
37            if (installButton) {
38                return installButton;
39            }
40
41            installButton = document.querySelector(context.config.domInstallButtonSelector);
42            if (installButton) {
43                installButton.type = installButton.type || 'button';
44                context.logger.info('[PWA]', 'install.button.detected', context.config.domInstallButtonSelector);
45            }
46
47            return installButton;
48        }
49
50        function setInstallButtonVisible(visible, mode) {
51            var button = resolveInstallButton();
52            var buttonLabel;
53            installButtonMode = mode === 'manual' ? 'manual' : 'prompt';
54
55            if (!button) {
56                context.logger.info('[PWA]', 'install.button.not_found', context.config.domInstallButtonSelector);
57                return;
58            }
59
60            buttonLabel = button.querySelector ? button.querySelector('.subscription__link-text') : null;
61            if (buttonLabel) {
62                buttonLabel.textContent = 'Установить';
63            } else {
64                button.textContent = 'Установить приложение';
65            }
66        }
67
68        function handleInstallButtonClick() {
69            trackYmGoal('click_install_pwa');
70            if (installButtonMode === 'manual' || !deferredInstallPrompt) {
71                showManualInstallHint();
72                return;
73            }
74
75            deferredInstallPrompt.prompt();
76            deferredInstallPrompt.userChoice.finally(function () {
77                deferredInstallPrompt = null;
78                setInstallButtonVisible(false, 'prompt');
79            });
80        }
81
82        document.addEventListener('click', function (event) {
83            var button = installButton || document.querySelector(context.config.domInstallButtonSelector);
84            var target = event && event.target;
85
86            if (!button || !target) {
87                return;
88            }
89
90            if (target !== button && !(button.contains && button.contains(target))) {
91                return;
92            }
93
94            handleInstallButtonClick();
95        });
96
97        root.addEventListener('beforeinstallprompt', function (event) {
98            event.preventDefault();
99            deferredInstallPrompt = event;
100            setInstallButtonVisible(true, 'prompt');
101            context.trackPwaEvent('pwa_install_prompt_shown', {
102                mode: isStandalone ? 'standalone' : 'browser',
103                is_ios: isIos,
104                is_ios_safari: isIosSafari
105            });
106            context.logger.info('[PWA]', 'install.prompt.ready');
107        });
108
109        root.addEventListener('appinstalled', function () {
110            deferredInstallPrompt = null;
111            if (installButton) {
112                setInstallButtonVisible(false, 'prompt');
113            }
114            context.trackPwaEvent('pwa_install_completed', {
115                mode: isStandalone ? 'standalone' : 'browser',
116                is_ios: isIos,
117                is_ios_safari: isIosSafari
118            });
119            context.logger.info('[PWA]', 'install.completed');
120        });
121
122        return {
123            isStandalone: function () {
124                return isStandalone;
125            },
126            hasPrompt: function () {
127                return !!deferredInstallPrompt;
128            },
129            enableManualInstallButtonFallback: function () {
130                setInstallButtonVisible(true, 'manual');
131            },
132            getClientMeta: function () {
133                return {
134                    mode: isStandalone ? 'standalone' : 'browser',
135                    is_ios: isIos,
136                    is_ios_safari: isIosSafari
137                };
138            }
139        };
140    };
141})(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.