- Оптимизированы мета-теги в index.html и test-pwa.html для лучшей поддержки PWA. - Улучшена структура кода с использованием многострочных атрибутов для мета-тегов. - Обновлен сервисный работник для более эффективного кэширования и обработки запросов. - Добавлены новые функции в pwa.js для управления установкой и обновлением PWA.
288 lines
9.2 KiB
HTML
288 lines
9.2 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 - NoteJS</title>
|
||
|
||
<!-- PWA Meta Tags -->
|
||
<meta name="description" content="Тест PWA для NoteJS" />
|
||
<meta name="theme-color" content="#007bff" />
|
||
<meta name="mobile-web-app-capable" content="yes" />
|
||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||
<meta name="apple-mobile-web-app-title" content="NoteJS" />
|
||
|
||
<!-- Icons -->
|
||
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
|
||
<link
|
||
rel="icon"
|
||
type="image/png"
|
||
sizes="32x32"
|
||
href="/icons/icon-32x32.png"
|
||
/>
|
||
<link
|
||
rel="icon"
|
||
type="image/png"
|
||
sizes="16x16"
|
||
href="/icons/icon-16x16.png"
|
||
/>
|
||
<link
|
||
rel="apple-touch-icon"
|
||
sizes="180x180"
|
||
href="/icons/icon-192x192.png"
|
||
/>
|
||
|
||
<!-- Manifest -->
|
||
<link rel="manifest" href="/manifest.json" />
|
||
|
||
<style>
|
||
body {
|
||
font-family: Arial, sans-serif;
|
||
max-width: 800px;
|
||
margin: 0 auto;
|
||
padding: 20px;
|
||
background: #f5f5f5;
|
||
}
|
||
.container {
|
||
background: white;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||
}
|
||
.status {
|
||
padding: 10px;
|
||
margin: 10px 0;
|
||
border-radius: 5px;
|
||
}
|
||
.success {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
}
|
||
.error {
|
||
background: #f8d7da;
|
||
color: #721c24;
|
||
}
|
||
.info {
|
||
background: #d1ecf1;
|
||
color: #0c5460;
|
||
}
|
||
button {
|
||
background: #007bff;
|
||
color: white;
|
||
border: none;
|
||
padding: 10px 20px;
|
||
border-radius: 5px;
|
||
cursor: pointer;
|
||
margin: 5px;
|
||
}
|
||
button:hover {
|
||
background: #0056b3;
|
||
}
|
||
button:disabled {
|
||
background: #6c757d;
|
||
cursor: not-allowed;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<h1>🔧 Тест PWA для NoteJS</h1>
|
||
|
||
<div id="status-container">
|
||
<div class="status info">Проверяем требования PWA...</div>
|
||
</div>
|
||
|
||
<div>
|
||
<button onclick="checkPWAStatus()">Проверить статус PWA</button>
|
||
<button onclick="installPWA()" id="install-btn" disabled>
|
||
Установить приложение
|
||
</button>
|
||
<button onclick="clearCache()">Очистить кэш</button>
|
||
</div>
|
||
|
||
<div
|
||
id="debug-info"
|
||
style="
|
||
margin-top: 20px;
|
||
padding: 15px;
|
||
background: #f8f9fa;
|
||
border-radius: 5px;
|
||
font-family: monospace;
|
||
font-size: 12px;
|
||
"
|
||
>
|
||
<h3>Отладочная информация:</h3>
|
||
<div id="debug-content"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- PWA Script -->
|
||
<script src="/pwa.js"></script>
|
||
|
||
<script>
|
||
let deferredPrompt;
|
||
|
||
// Проверка статуса PWA
|
||
function checkPWAStatus() {
|
||
const statusContainer = document.getElementById("status-container");
|
||
const debugContent = document.getElementById("debug-content");
|
||
|
||
// Очищаем предыдущие статусы
|
||
statusContainer.innerHTML = "";
|
||
debugContent.innerHTML = "";
|
||
|
||
// Проверяем требования PWA
|
||
const checks = [
|
||
{
|
||
name: "HTTPS или localhost",
|
||
status:
|
||
location.protocol === "https:" ||
|
||
location.hostname === "localhost",
|
||
description: `Протокол: ${location.protocol}, Хост: ${location.hostname}`,
|
||
},
|
||
{
|
||
name: "Service Worker",
|
||
status: "serviceWorker" in navigator,
|
||
description: "Поддержка Service Worker API",
|
||
},
|
||
{
|
||
name: "Manifest",
|
||
status: document.querySelector('link[rel="manifest"]') !== null,
|
||
description: "Манифест PWA подключен",
|
||
},
|
||
{
|
||
name: "Иконки",
|
||
status: document.querySelector('link[rel="icon"]') !== null,
|
||
description: "Иконки приложения подключены",
|
||
},
|
||
{
|
||
name: "Уже установлено",
|
||
status:
|
||
window.matchMedia("(display-mode: standalone)").matches ||
|
||
window.navigator.standalone === true,
|
||
description: "Приложение уже установлено как PWA",
|
||
},
|
||
];
|
||
|
||
let allPassed = true;
|
||
|
||
checks.forEach((check) => {
|
||
const statusDiv = document.createElement("div");
|
||
statusDiv.className = `status ${check.status ? "success" : "error"}`;
|
||
statusDiv.innerHTML = `${check.status ? "✅" : "❌"} ${check.name}: ${
|
||
check.description
|
||
}`;
|
||
statusContainer.appendChild(statusDiv);
|
||
|
||
if (!check.status) allPassed = false;
|
||
});
|
||
|
||
// Общая оценка
|
||
const overallDiv = document.createElement("div");
|
||
overallDiv.className = `status ${allPassed ? "success" : "error"}`;
|
||
overallDiv.innerHTML = `${allPassed ? "✅" : "❌"} Общий статус: ${
|
||
allPassed ? "PWA готово к установке" : "Есть проблемы с PWA"
|
||
}`;
|
||
statusContainer.appendChild(overallDiv);
|
||
|
||
// Отладочная информация
|
||
const debugInfo = {
|
||
userAgent: navigator.userAgent,
|
||
isOnline: navigator.onLine,
|
||
hasServiceWorker: "serviceWorker" in navigator,
|
||
isStandalone: window.matchMedia("(display-mode: standalone)").matches,
|
||
isIOSStandalone: window.navigator.standalone === true,
|
||
hasDeferredPrompt: deferredPrompt !== null,
|
||
pwaInfo: window.PWAManager
|
||
? window.PWAManager.getPWAInfo()
|
||
: "PWA Manager не доступен",
|
||
};
|
||
|
||
debugContent.innerHTML = JSON.stringify(debugInfo, null, 2);
|
||
|
||
// Активируем кнопку установки если доступно
|
||
const installBtn = document.getElementById("install-btn");
|
||
if (
|
||
deferredPrompt &&
|
||
!debugInfo.isStandalone &&
|
||
!debugInfo.isIOSStandalone
|
||
) {
|
||
installBtn.disabled = false;
|
||
}
|
||
}
|
||
|
||
// Установка PWA
|
||
function installPWA() {
|
||
if (deferredPrompt) {
|
||
deferredPrompt.prompt();
|
||
deferredPrompt.userChoice.then((choiceResult) => {
|
||
console.log("Результат установки:", choiceResult.outcome);
|
||
if (choiceResult.outcome === "accepted") {
|
||
alert("Приложение установлено!");
|
||
}
|
||
deferredPrompt = null;
|
||
document.getElementById("install-btn").disabled = true;
|
||
});
|
||
} else {
|
||
alert(
|
||
"Установка недоступна. Возможно, приложение уже установлено или браузер не поддерживает установку PWA."
|
||
);
|
||
}
|
||
}
|
||
|
||
// Очистка кэша
|
||
function clearCache() {
|
||
if ("caches" in window) {
|
||
caches
|
||
.keys()
|
||
.then((cacheNames) => {
|
||
return Promise.all(
|
||
cacheNames.map((cacheName) => {
|
||
console.log("Удаление кэша:", cacheName);
|
||
return caches.delete(cacheName);
|
||
})
|
||
);
|
||
})
|
||
.then(() => {
|
||
alert("Кэш очищен! Перезагрузите страницу.");
|
||
});
|
||
} else {
|
||
alert("Кэш не поддерживается в этом браузере.");
|
||
}
|
||
}
|
||
|
||
// Обработка события 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();
|
||
}
|
||
deferredPrompt = e;
|
||
document.getElementById("install-btn").disabled = false;
|
||
});
|
||
|
||
// Обработка успешной установки
|
||
window.addEventListener("appinstalled", () => {
|
||
console.log("PWA установлено успешно");
|
||
alert("Приложение установлено успешно!");
|
||
document.getElementById("install-btn").disabled = true;
|
||
});
|
||
|
||
// Автоматическая проверка при загрузке
|
||
window.addEventListener("load", () => {
|
||
setTimeout(checkPWAStatus, 1000);
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|