151 lines
4.1 KiB
Vue
151 lines
4.1 KiB
Vue
<template>
|
|
<UApp
|
|
:locale="locales[locale]"
|
|
>
|
|
<div class="inside-safe-area">
|
|
<NuxtLayout>
|
|
<NuxtPage />
|
|
</NuxtLayout>
|
|
</div>
|
|
</UApp>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import * as locales from '@nuxt/ui/locale'
|
|
import type { URLOpenListenerEvent } from '@capacitor/app'
|
|
import { Capacitor } from '@capacitor/core'
|
|
import { App } from '@capacitor/app'
|
|
import type {
|
|
Token,
|
|
ActionPerformed,
|
|
PushNotificationSchema } from '@capacitor/push-notifications'
|
|
import {
|
|
PushNotifications
|
|
} from '@capacitor/push-notifications'
|
|
import type { UsersLanguageOptions } from './types/pocketbase.types'
|
|
|
|
const { locale, t, setLocale } = useI18n()
|
|
|
|
const lang = computed(() => locales[locale.value].code)
|
|
const dir = computed(() => locales[locale.value].dir)
|
|
|
|
useHead({
|
|
meta: [
|
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
|
|
],
|
|
link: [
|
|
{ rel: 'icon', href: '/favicon.ico' }
|
|
],
|
|
htmlAttrs: {
|
|
lang,
|
|
dir
|
|
}
|
|
})
|
|
|
|
const title = t('hero.title')
|
|
const description = t('hero.description')
|
|
|
|
useSeoMeta({
|
|
title,
|
|
description,
|
|
ogTitle: title,
|
|
ogDescription: description
|
|
})
|
|
|
|
const { isAuthenticated } = storeToRefs(useUser())
|
|
const { addFcmToken } = useNotifications()
|
|
const toast = useToast()
|
|
|
|
const registerPushNotifications = async () => {
|
|
if (Capacitor.isNativePlatform() && isAuthenticated.value) {
|
|
// Request permission to use push notifications
|
|
// iOS will prompt user and return if they granted permission or not
|
|
// Android will just grant without prompting
|
|
PushNotifications.requestPermissions().then((result) => {
|
|
if (result.receive === 'granted') {
|
|
// Register with Apple / Google to receive push via APNS/FCM
|
|
PushNotifications.register()
|
|
} else {
|
|
// Show some error
|
|
}
|
|
})
|
|
|
|
// On success, we should be able to receive notifications
|
|
PushNotifications.addListener('registration',
|
|
(token: Token) => {
|
|
// Add the FCM token for the current user
|
|
addFcmToken(token.value)
|
|
}
|
|
)
|
|
|
|
// Some issue with our setup and push will not work
|
|
PushNotifications.addListener('registrationError',
|
|
(error) => {
|
|
console.warn('Error on push notification registration:', JSON.stringify(error))
|
|
}
|
|
)
|
|
|
|
// Show the notification payload as toast message if the app is open on our device
|
|
PushNotifications.addListener('pushNotificationReceived',
|
|
(notification: PushNotificationSchema) => {
|
|
toast.add({
|
|
title: notification.title,
|
|
description: notification.subtitle ?? notification.body,
|
|
color: 'primary'
|
|
})
|
|
}
|
|
)
|
|
|
|
// Method called when tapping on a notification
|
|
PushNotifications.addListener('pushNotificationActionPerformed',
|
|
(notification: ActionPerformed) => {
|
|
console.log('Push action performed:', JSON.stringify(notification))
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
// handle locale based on user prefs
|
|
const { updateUser, user } = useUser()
|
|
watch(isAuthenticated, async () => {
|
|
if (isAuthenticated.value) {
|
|
// Fetch the user profile after successful sign-in
|
|
const prefLanguage = user?.language
|
|
if (prefLanguage) {
|
|
// Set the locale based on the user's profile locale
|
|
setLocale(prefLanguage)
|
|
} else {
|
|
// If the locale was not yet saved to the profile, update it
|
|
updateUser({ language: locale.value as UsersLanguageOptions })
|
|
}
|
|
|
|
// Register push notifications after successful sign-in
|
|
registerPushNotifications()
|
|
}
|
|
}, { immediate: true })
|
|
|
|
// Activate Capacitor features if we are on native platform (Android/iOS)
|
|
if (Capacitor.isNativePlatform()) {
|
|
const router = useRouter()
|
|
// Register and handle deep links
|
|
App.addListener('appUrlOpen', function (event: URLOpenListenerEvent) {
|
|
const slug = event.url.split('.app').pop()
|
|
if (slug) {
|
|
router.push({
|
|
path: slug
|
|
})
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
/* Safe area insets needed for mobile app to avoid notches and safe areas */
|
|
.inside-safe-area {
|
|
margin-top: env(safe-area-inset-top, unset);
|
|
padding-right: env(safe-area-inset-right, unset);
|
|
padding-bottom: env(safe-area-inset-bottom, unset);
|
|
padding-left: env(safe-area-inset-left, unset);
|
|
}
|
|
</style>
|