fix(pwa)
Some checks failed
Deploy to Development / build-and-deploy (push) Has been cancelled
Deploy to Production / build-and-deploy (push) Successful in 54s

This commit is contained in:
EvanChal
2026-01-25 23:24:25 +01:00
parent f63b204c5c
commit e32b1ce04e
2 changed files with 81 additions and 38 deletions

View File

@@ -129,9 +129,9 @@
<!-- Installer l'app --> <!-- Installer l'app -->
<button <button
@click="handleInstallApp" @click="handleInstallApp"
:disabled="isPWAInstalled || !canInstall" :disabled="isPWAInstalled"
class="block w-full text-left px-4 py-2 text-sm transition-colors" class="block w-full text-left px-4 py-2 text-sm transition-colors"
:class="isPWAInstalled || !canInstall :class="isPWAInstalled
? 'text-gray-400 cursor-not-allowed' ? 'text-gray-400 cursor-not-allowed'
: 'text-gray-700 hover:bg-gray-100'" : 'text-gray-700 hover:bg-gray-100'"
> >
@@ -307,6 +307,7 @@ const isMobileMenuOpen = ref(false)
const deferredPrompt = ref(null) const deferredPrompt = ref(null)
const isPWAInstalled = ref(false) const isPWAInstalled = ref(false)
const canInstall = ref(false) const canInstall = ref(false)
const isMobile = ref(false)
const user = computed(() => authStore.user) const user = computed(() => authStore.user)
const notifications = computed(() => authStore.notifications) const notifications = computed(() => authStore.notifications)
@@ -343,11 +344,21 @@ async function handleNotificationClick(notification) {
} }
// PWA Installation logic // PWA Installation logic
function checkIfMobile() {
isMobile.value = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) ||
window.innerWidth < 768
}
function checkPWAInstalled() { function checkPWAInstalled() {
// Vérifier si l'app est déjà installée (mode standalone) // Vérifier si l'app est déjà installée (mode standalone)
isPWAInstalled.value = window.matchMedia('(display-mode: standalone)').matches || isPWAInstalled.value = window.matchMedia('(display-mode: standalone)').matches ||
window.navigator.standalone === true || window.navigator.standalone === true ||
document.referrer.includes('android-app://') document.referrer.includes('android-app://')
// Sur mobile, permettre l'installation même sans beforeinstallprompt
if (isMobile.value && !isPWAInstalled.value) {
canInstall.value = true
}
} }
function handleBeforeInstallPrompt(e) { function handleBeforeInstallPrompt(e) {
@@ -359,35 +370,47 @@ function handleBeforeInstallPrompt(e) {
} }
async function handleInstallApp() { async function handleInstallApp() {
if (!deferredPrompt.value || isPWAInstalled.value) { if (isPWAInstalled.value) {
return return
} }
try { if (deferredPrompt.value) {
showUserMenu.value = false try {
showUserMenu.value = false
// Afficher le prompt d'installation // Afficher le prompt d'installation
deferredPrompt.value.prompt() deferredPrompt.value.prompt()
// Attendre la réponse de l'utilisateur // Attendre la réponse de l'utilisateur
const { outcome } = await deferredPrompt.value.userChoice const { outcome } = await deferredPrompt.value.userChoice
if (outcome === 'accepted') { if (outcome === 'accepted') {
console.log('✅ PWA installée avec succès') console.log('✅ PWA installée avec succès')
isPWAInstalled.value = true isPWAInstalled.value = true
} else { } else {
console.log('❌ Installation PWA annulée') console.log('❌ Installation PWA annulée')
}
// Réinitialiser
deferredPrompt.value = null
canInstall.value = false
} catch (error) {
console.error('Erreur lors de l\'installation:', error)
}
} else if (isMobile.value) {
// Sur mobile sans beforeinstallprompt, afficher les instructions
showUserMenu.value = false
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent)
if (isIOS) {
alert('Sur iOS :\n1. Appuyez sur le bouton de partage (□↑) en bas de l\'écran\n2. Faites défiler et sélectionnez "Sur l\'écran d\'accueil"\n3. Appuyez sur "Ajouter"')
} else {
alert('Sur Android :\n1. Appuyez sur le menu (⋮) en haut à droite\n2. Sélectionnez "Ajouter à l\'écran d\'accueil" ou "Installer l\'application"\n3. Confirmez l\'installation')
} }
// Réinitialiser
deferredPrompt.value = null
canInstall.value = false
} catch (error) {
console.error('Erreur lors de l\'installation:', error)
} }
} }
onMounted(async () => { onMounted(async () => {
checkIfMobile()
await authStore.fetchCurrentUser() await authStore.fetchCurrentUser()
if (authStore.isAuthenticated) { if (authStore.isAuthenticated) {
@@ -411,10 +434,12 @@ onMounted(async () => {
// Écouter les changements de display mode // Écouter les changements de display mode
window.matchMedia('(display-mode: standalone)').addEventListener('change', checkPWAInstalled) window.matchMedia('(display-mode: standalone)').addEventListener('change', checkPWAInstalled)
window.addEventListener('resize', checkIfMobile)
}) })
onBeforeUnmount(async () => { onBeforeUnmount(async () => {
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt) window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
window.removeEventListener('resize', checkIfMobile)
// Arrêter le polling des notifications // Arrêter le polling des notifications
const notificationService = (await import('@/services/notificationService')).default const notificationService = (await import('@/services/notificationService')).default

View File

@@ -267,7 +267,7 @@
Une fois connecté, tu pourras installer l'app depuis le menu de ton profil Une fois connecté, tu pourras installer l'app depuis le menu de ton profil
</p> </p>
<button <button
v-if="deferredPrompt" v-if="deferredPrompt || isMobile"
@click="handleInstallApp" @click="handleInstallApp"
class="w-full sm:w-auto bg-primary-600 hover:bg-primary-700 text-white font-medium py-3 px-6 rounded-lg shadow-lg hover:shadow-xl transition-all duration-200 transform hover:scale-105 text-sm sm:text-base" class="w-full sm:w-auto bg-primary-600 hover:bg-primary-700 text-white font-medium py-3 px-6 rounded-lg shadow-lg hover:shadow-xl transition-all duration-200 transform hover:scale-105 text-sm sm:text-base"
> >
@@ -275,11 +275,11 @@
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg> </svg>
<span>Installer l'app maintenant</span> <span>{{ deferredPrompt ? 'Installer l\'app maintenant' : 'Voir les instructions' }}</span>
</div> </div>
</button> </button>
<p v-else class="text-xs sm:text-sm text-gray-500"> <p v-else class="text-xs sm:text-sm text-gray-500">
Voilà, c'est quand même mieux comme ça ! Le bouton d'installation apparaîtra automatiquement quand tu seras connecté
</p> </p>
</div> </div>
</div> </div>
@@ -439,33 +439,51 @@ async function handleRegister() {
} }
// PWA Installation // PWA Installation
const isMobile = ref(false)
function checkIfMobile() {
isMobile.value = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) ||
window.innerWidth < 768
}
function handleBeforeInstallPrompt(e) { function handleBeforeInstallPrompt(e) {
e.preventDefault() e.preventDefault()
deferredPrompt.value = e deferredPrompt.value = e
} }
async function handleInstallApp() { async function handleInstallApp() {
if (!deferredPrompt.value) return if (deferredPrompt.value) {
try {
deferredPrompt.value.prompt()
const { outcome } = await deferredPrompt.value.userChoice
try { if (outcome === 'accepted') {
deferredPrompt.value.prompt() console.log('✅ PWA installée avec succès')
const { outcome } = await deferredPrompt.value.userChoice }
if (outcome === 'accepted') { deferredPrompt.value = null
console.log('✅ PWA installée avec succès') } catch (error) {
console.error('Erreur lors de l\'installation:', error)
}
} else if (isMobile.value) {
// Sur mobile sans beforeinstallprompt, afficher les instructions
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent)
if (isIOS) {
alert('Sur iOS :\n1. Appuyez sur le bouton de partage (□↑) en bas de l\'écran\n2. Faites défiler et sélectionnez "Sur l\'écran d\'accueil"\n3. Appuyez sur "Ajouter"')
} else {
alert('Sur Android :\n1. Appuyez sur le menu (⋮) en haut à droite\n2. Sélectionnez "Ajouter à l\'écran d\'accueil" ou "Installer l\'application"\n3. Confirmez l\'installation')
} }
deferredPrompt.value = null
} catch (error) {
console.error('Erreur lors de l\'installation:', error)
} }
} }
onMounted(() => { onMounted(() => {
checkIfMobile()
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt) window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
window.addEventListener('resize', checkIfMobile)
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt) window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
window.removeEventListener('resize', checkIfMobile)
}) })
</script> </script>