Open harlan-zw opened 1 year ago
Simple OneSignal implementation in Nuxt 3 example.
npm install --save-dev @onesignal/onesignal-vue3
// nuxt.config.ts
export default defineNuxtConfig({
plugins: [
'onesignal.client'
],
runtimeConfig: {
public: {
onesignalAppId: '<ONESIGNAL_APP_ID>',
},
},
});
// plugins/onesignal.client
import { useOneSignal } from '@onesignal/onesignal-vue3';
export default defineNuxtPlugin((nuxtApp) => {
const appId = nuxtApp.$config.public.onesignalAppId;
if (!appId) {
return;
}
const OneSignal = useOneSignal();
OneSignal.init({
appId,
allowLocalhostAsSecureOrigin: process.env.APP_ENV !== 'production',
});
return {
provide: {
OneSignal,
},
};
});
This component uses @nuxtjs/i18n
, @sidebase/nuxt-auth
and vuetify
with auto-imports enabled.
<!-- components/OneSignalSubscribeButton.vue -->
<template>
<ClientOnly>
<v-tooltip location="bottom">
<template #activator="{ props }">
<v-btn
variant="text"
icon
class="me-2"
v-bind="props"
@click.prevent="onClickBellButton"
>
<v-icon :color="bellOption.color" :icon="bellOption.icon" />
</v-btn>
</template>
<span>{{ bellOption.tooltipText }}</span>
</v-tooltip>
</ClientOnly>
</template>
<script lang="ts" setup>
const BELL_STATE = {
DISABLED: 'disabled',
SUBSCRIBE: 'subscribe',
SUBSCRIBED: 'subscribed',
} as const;
type BellState = (typeof BELL_STATE)[keyof typeof BELL_STATE];
defineOptions({
name: 'OneSignalSubscribeButton',
});
const { $OneSignal } = useNuxtApp();
const i18n = useI18n();
const auth = useAuth();
const bellState = ref<BellState>(BELL_STATE.DISABLED);
const bellOption = computed(() => {
switch (bellState.value) {
case BELL_STATE.SUBSCRIBE:
return {
color: 'info',
icon: 'mdi-bell',
tooltipText: i18n.t('onesignal.attributes.bell.subscribe'),
};
case BELL_STATE.SUBSCRIBED:
return {
color: 'success',
icon: 'mdi-bell-check',
tooltipText: i18n.t('onesignal.attributes.bell.subscribed'),
};
case BELL_STATE.DISABLED:
default:
return {
color: 'info',
icon: 'mdi-bell-off',
tooltipText: i18n.t('onesignal.attributes.bell.disabled'),
};
}
});
watch(auth.status, (status) => {
if (status === 'authenticated') {
$OneSignal.login(String(auth.data.value?.id));
}
});
onBeforeMount(() => {
updateBellState();
$OneSignal.Notifications.addEventListener('permissionChange', onPermissionChange);
$OneSignal.User.PushSubscription.addEventListener('change', onSubscriptionChange);
});
onBeforeUnmount(() => {
$OneSignal.Notifications.removeEventListener('permissionChange', onPermissionChange);
$OneSignal.User.PushSubscription.removeEventListener('change', onSubscriptionChange);
});
async function onClickBellButton() {
switch (bellState.value) {
case BELL_STATE.SUBSCRIBED:
await $OneSignal.User.PushSubscription.optOut();
break;
case BELL_STATE.SUBSCRIBE:
await $OneSignal.User.PushSubscription.optIn();
break;
case BELL_STATE.DISABLED:
// $OneSignal.Slidedown.promptPush({ force: true });
await $OneSignal.Notifications.requestPermission();
break;
}
}
function onSubscriptionChange() {
updateBellState();
}
function onPermissionChange(isAllowed: boolean) {
if (isAllowed) {
$OneSignal.User.PushSubscription.optIn();
}
}
function getSubscriptionState() {
return {
isPushNotificationsEnabled: $OneSignal.Notifications.permission,
isOptedIn: $OneSignal.User.PushSubscription.optedIn,
};
}
function updateBellState() {
const state = getSubscriptionState();
if (!state.isPushNotificationsEnabled) {
bellState.value = BELL_STATE.DISABLED;
return;
}
if (!state.isOptedIn) {
bellState.value = BELL_STATE.SUBSCRIBE;
return;
}
bellState.value = BELL_STATE.SUBSCRIBED;
}
</script>
Showing bell only to authenticated users.
<!-- example.vue -->
<template>
<div>
<LazyOneSignalSubscribeButton
v-if="'$OneSignal' in $nuxt && $config.public.onesignalAppId && auth.status.value === 'authenticated'"
/>
</div>
</template>
Hey :wave: It looks like this module hasn't been updated for Nuxt 3. In an effort to improve the developer experience of modules, I've updated the module to clarify that it only supports Nuxt 2.
If Nuxt 3 support is added it will be moved to the https://github.com/nuxt-modules organisation.
Please let me know if you need any help :)
cc: @Geminii