- Оптимизированы мета-теги в index.html и test-pwa.html для лучшей поддержки PWA. - Улучшена структура кода с использованием многострочных атрибутов для мета-тегов. - Обновлен сервисный работник для более эффективного кэширования и обработки запросов. - Добавлены новые функции в pwa.js для управления установкой и обновлением PWA.
231 lines
7.8 KiB
HTML
231 lines
7.8 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>Тест установки PWA на мобильном</title>
|
||
<link rel="manifest" href="/manifest.json" />
|
||
<link rel="icon" href="/icon.svg" />
|
||
<style>
|
||
body {
|
||
font-family: Arial, sans-serif;
|
||
max-width: 600px;
|
||
margin: 0 auto;
|
||
padding: 20px;
|
||
background-color: #f5f5f5;
|
||
}
|
||
.container {
|
||
background: white;
|
||
padding: 20px;
|
||
border-radius: 10px;
|
||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||
}
|
||
.btn {
|
||
background: #007bff;
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 24px;
|
||
border-radius: 5px;
|
||
cursor: pointer;
|
||
margin: 10px 5px;
|
||
font-size: 16px;
|
||
}
|
||
.btn:hover {
|
||
background: #0056b3;
|
||
}
|
||
.btn:disabled {
|
||
background: #ccc;
|
||
cursor: not-allowed;
|
||
}
|
||
.info {
|
||
background: #e7f3ff;
|
||
border: 1px solid #b3d9ff;
|
||
padding: 15px;
|
||
border-radius: 5px;
|
||
margin: 15px 0;
|
||
}
|
||
.success {
|
||
background: #d4edda;
|
||
border-color: #c3e6cb;
|
||
color: #155724;
|
||
}
|
||
.warning {
|
||
background: #fff3cd;
|
||
border-color: #ffeaa7;
|
||
color: #856404;
|
||
}
|
||
.error {
|
||
background: #f8d7da;
|
||
border-color: #f5c6cb;
|
||
color: #721c24;
|
||
}
|
||
.status {
|
||
margin: 10px 0;
|
||
padding: 10px;
|
||
border-radius: 5px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<h1>📱 Тест установки PWA на мобильном</h1>
|
||
|
||
<div class="info">
|
||
<h3>Инструкции:</h3>
|
||
<p>1. Откройте эту страницу на мобильном устройстве</p>
|
||
<p>2. Должен появиться нативный баннер установки браузера</p>
|
||
<p>3. Если баннер не появился, используйте кнопки ниже</p>
|
||
</div>
|
||
|
||
<div id="status" class="status"></div>
|
||
|
||
<div>
|
||
<button id="install-btn" class="btn" disabled>
|
||
Установить приложение
|
||
</button>
|
||
<button id="show-banner-btn" class="btn">Показать баннер</button>
|
||
<button id="check-status-btn" class="btn">Проверить статус</button>
|
||
</div>
|
||
|
||
<div id="debug-info" class="info" style="margin-top: 20px">
|
||
<h3>Отладочная информация:</h3>
|
||
<div id="debug-content"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
let deferredPrompt;
|
||
const statusDiv = document.getElementById("status");
|
||
const installBtn = document.getElementById("install-btn");
|
||
const showBannerBtn = document.getElementById("show-banner-btn");
|
||
const checkStatusBtn = document.getElementById("check-status-btn");
|
||
const debugContent = document.getElementById("debug-content");
|
||
|
||
function updateStatus(message, type = "info") {
|
||
statusDiv.textContent = message;
|
||
statusDiv.className = `status ${type}`;
|
||
}
|
||
|
||
function updateDebugInfo() {
|
||
const info = {
|
||
userAgent: navigator.userAgent,
|
||
isMobile:
|
||
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
||
navigator.userAgent
|
||
),
|
||
hasDeferredPrompt: !!deferredPrompt,
|
||
isPWAInstalled: window.matchMedia("(display-mode: standalone)")
|
||
.matches,
|
||
isOnline: navigator.onLine,
|
||
hasServiceWorker: "serviceWorker" in navigator,
|
||
};
|
||
|
||
debugContent.innerHTML = Object.entries(info)
|
||
.map(([key, value]) => `<strong>${key}:</strong> ${value}`)
|
||
.join("<br>");
|
||
}
|
||
|
||
// Обработка события beforeinstallprompt
|
||
window.addEventListener("beforeinstallprompt", (e) => {
|
||
console.log("beforeinstallprompt событие получено");
|
||
|
||
// На мобильных устройствах позволяем браузеру показать нативный баннер
|
||
const isMobile =
|
||
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
||
navigator.userAgent
|
||
) ||
|
||
(navigator.maxTouchPoints && navigator.maxTouchPoints > 2) ||
|
||
window.matchMedia("(max-width: 768px)").matches;
|
||
|
||
if (!isMobile) {
|
||
e.preventDefault();
|
||
updateStatus(
|
||
"Десктоп: preventDefault() вызван, показываем кастомную кнопку",
|
||
"warning"
|
||
);
|
||
} else {
|
||
updateStatus(
|
||
"Мобильное устройство: разрешаем нативный баннер установки",
|
||
"success"
|
||
);
|
||
}
|
||
|
||
deferredPrompt = e;
|
||
installBtn.disabled = false;
|
||
updateDebugInfo();
|
||
});
|
||
|
||
// Обработка успешной установки
|
||
window.addEventListener("appinstalled", () => {
|
||
console.log("PWA установлено успешно");
|
||
updateStatus("Приложение установлено успешно!", "success");
|
||
installBtn.disabled = true;
|
||
deferredPrompt = null;
|
||
updateDebugInfo();
|
||
});
|
||
|
||
// Кнопка установки
|
||
installBtn.addEventListener("click", async () => {
|
||
if (deferredPrompt) {
|
||
updateStatus("Показываем баннер установки...", "info");
|
||
deferredPrompt.prompt();
|
||
const choiceResult = await deferredPrompt.userChoice;
|
||
|
||
if (choiceResult.outcome === "accepted") {
|
||
updateStatus("Пользователь установил приложение!", "success");
|
||
} else {
|
||
updateStatus("Пользователь отклонил установку", "warning");
|
||
}
|
||
|
||
deferredPrompt = null;
|
||
installBtn.disabled = true;
|
||
} else {
|
||
updateStatus("Баннер установки недоступен", "error");
|
||
}
|
||
updateDebugInfo();
|
||
});
|
||
|
||
// Кнопка показа баннера
|
||
showBannerBtn.addEventListener("click", () => {
|
||
if (deferredPrompt) {
|
||
updateStatus("Принудительно показываем баннер...", "info");
|
||
deferredPrompt.prompt();
|
||
} else {
|
||
updateStatus(
|
||
"Баннер установки недоступен. Попробуйте перезагрузить страницу.",
|
||
"error"
|
||
);
|
||
}
|
||
});
|
||
|
||
// Кнопка проверки статуса
|
||
checkStatusBtn.addEventListener("click", () => {
|
||
updateDebugInfo();
|
||
if (deferredPrompt) {
|
||
updateStatus("Баннер установки доступен", "success");
|
||
} else {
|
||
updateStatus("Баннер установки недоступен", "warning");
|
||
}
|
||
});
|
||
|
||
// Инициализация
|
||
updateDebugInfo();
|
||
updateStatus("Ожидание события beforeinstallprompt...", "info");
|
||
|
||
// Регистрация Service Worker
|
||
if ("serviceWorker" in navigator) {
|
||
navigator.serviceWorker
|
||
.register("/sw.js")
|
||
.then((registration) => {
|
||
console.log("SW зарегистрирован:", registration);
|
||
updateStatus("Service Worker зарегистрирован", "success");
|
||
})
|
||
.catch((error) => {
|
||
console.log("Ошибка регистрации SW:", error);
|
||
updateStatus("Ошибка регистрации Service Worker", "error");
|
||
});
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|