feat: add browser push notifications

This commit is contained in:
Tim
2025-07-30 10:48:02 +08:00
parent df8c5376f6
commit dccf8f9d0c
13 changed files with 283 additions and 1 deletions

View File

@@ -11,6 +11,7 @@ import { useToast } from 'vue-toastification'
import { checkToken, clearToken, isLogin } from './utils/auth'
import { initTheme } from './utils/theme'
import { loginWithGoogle } from './utils/google'
import { registerPush } from './utils/push'
// Configurable API domain and port
// export const API_DOMAIN = 'http://127.0.0.1'
@@ -43,6 +44,7 @@ app.use(
)
app.mount('#app')
registerPush()
checkToken().then(valid => {
if (!valid) {

View File

@@ -0,0 +1,48 @@
import { API_BASE_URL } from '../main'
import { getToken } from './auth'
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4)
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/')
const rawData = atob(base64)
const outputArray = new Uint8Array(rawData.length)
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i)
}
return outputArray
}
function arrayBufferToBase64(buffer) {
const bytes = new Uint8Array(buffer)
let binary = ''
for (const b of bytes) binary += String.fromCharCode(b)
return btoa(binary)
}
export async function registerPush() {
if (!('serviceWorker' in navigator) || !('PushManager' in window)) return
try {
const reg = await navigator.serviceWorker.register('/notifications-sw.js')
const res = await fetch(`${API_BASE_URL}/api/push/public-key`)
if (!res.ok) return
const { key } = await res.json()
const sub = await reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(key)
})
await fetch(`${API_BASE_URL}/api/push/subscribe`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${getToken()}`
},
body: JSON.stringify({
endpoint: sub.endpoint,
p256dh: arrayBufferToBase64(sub.getKey('p256dh')),
auth: arrayBufferToBase64(sub.getKey('auth'))
})
})
} catch (e) {
// ignore
}
}