File size: 2,943 Bytes
076c536
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import apiClient from '@/api/client.js'

export function isPushNotificationSupported() {
  return (
    'serviceWorker' in navigator &&
    'PushManager' in window &&
    'Notification' in window
  )
}

export async function registerServiceWorker() {
  if (!isPushNotificationSupported()) {
    throw new Error('Browser does not support Web Push')
  }
  return navigator.serviceWorker.register('/sw.js')
}

export async function requestNotificationPermission() {
  if (!('Notification' in window)) return 'unsupported'
  if (Notification.permission === 'granted') return 'granted'
  if (Notification.permission === 'denied') return 'denied'
  return Notification.requestPermission()
}

export async function getCurrentSubscription() {
  if (!isPushNotificationSupported()) return null
  const registration = await navigator.serviceWorker.ready
  return registration.pushManager.getSubscription()
}

export async function subscribeUserToPush() {
  const registration = await registerServiceWorker()
  const permission = await requestNotificationPermission()
  if (permission !== 'granted') {
    throw new Error('Notification permission was not granted')
  }

  const { data } = await apiClient.get('/users/me/notifications/push/vapid-public-key')
  const publicKey = data.public_key
  if (!publicKey) {
    throw new Error('VAPID public key is missing')
  }

  let subscription = await registration.pushManager.getSubscription()
  if (!subscription) {
    subscription = await registration.pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey: urlBase64ToUint8Array(publicKey),
    })
  }

  const subscriptionJson = subscription.toJSON()
  await apiClient.post('/users/me/notifications/push/subscribe', {
    endpoint: subscriptionJson.endpoint,
    keys: {
      p256dh: subscriptionJson.keys?.p256dh,
      auth: subscriptionJson.keys?.auth,
    },
  })
  return subscription
}

export async function unsubscribeUserFromPush() {
  const subscription = await getCurrentSubscription()
  if (!subscription) return false

  const endpoint = subscription.endpoint
  try {
    await apiClient.post('/users/me/notifications/push/unsubscribe', { endpoint })
  } finally {
    await subscription.unsubscribe()
  }
  return true
}

export async function sendTestPushNotification() {
  const { data } = await apiClient.post('/users/me/notifications/push/test', {
    title: 'LinguaIELTS',
    body: 'Thông báo Web Push đang hoạt động.',
    url: '/dashboard?tab=study',
  })
  return data
}

export function urlBase64ToUint8Array(base64String) {
  const padding = '='.repeat((4 - (base64String.length % 4)) % 4)
  const base64 = `${base64String}${padding}`
    .replace(/-/g, '+')
    .replace(/_/g, '/')

  const rawData = window.atob(base64)
  const outputArray = new Uint8Array(rawData.length)

  for (let i = 0; i < rawData.length; i += 1) {
    outputArray[i] = rawData.charCodeAt(i)
  }
  return outputArray
}