fix(pwa)
This commit is contained in:
@@ -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
|
|
||||||
deferredPrompt.value.prompt()
|
// Afficher le prompt d'installation
|
||||||
|
deferredPrompt.value.prompt()
|
||||||
// Attendre la réponse de l'utilisateur
|
|
||||||
const { outcome } = await deferredPrompt.value.userChoice
|
// Attendre la réponse de l'utilisateur
|
||||||
|
const { outcome } = await deferredPrompt.value.userChoice
|
||||||
if (outcome === 'accepted') {
|
|
||||||
console.log('✅ PWA installée avec succès')
|
if (outcome === 'accepted') {
|
||||||
isPWAInstalled.value = true
|
console.log('✅ PWA installée avec succès')
|
||||||
} else {
|
isPWAInstalled.value = true
|
||||||
console.log('❌ Installation PWA annulée')
|
} else {
|
||||||
|
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
|
||||||
|
|||||||
@@ -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 {
|
||||||
try {
|
deferredPrompt.value.prompt()
|
||||||
deferredPrompt.value.prompt()
|
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')
|
}
|
||||||
|
|
||||||
|
deferredPrompt.value = null
|
||||||
|
} 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>
|
||||||
|
|||||||
Reference in New Issue
Block a user