Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions packages/presentation/src/sound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import { getClient } from '.'
import notification from '@hcengineering/notification'

const sounds = new Map<Asset, AudioBuffer>()
const context = new AudioContext()
let context: AudioContext | undefined

function getAudioContext (): AudioContext {
context ??= new AudioContext()
return context
}

export async function isNotificationAllowed (_class?: Ref<Class<Doc>>): Promise<boolean> {
if (_class === undefined) return false
Expand All @@ -24,7 +29,7 @@ export async function prepareSound (key: string): Promise<void> {
const soundUrl = getMetadata(key as Asset) as string
const rawAudio = await fetch(soundUrl)
const rawBuffer = await rawAudio.arrayBuffer()
const decodedBuffer = await context.decodeAudioData(rawBuffer)
const decodedBuffer = await getAudioContext().decodeAudioData(rawBuffer)

sounds.set(key as Asset, decodedBuffer)
} catch (err) {
Expand All @@ -46,6 +51,10 @@ export async function playSound (soundKey: string, loop = false): Promise<(() =>
}

try {
const context = getAudioContext()
if (context.state === 'suspended') {
await context.resume()
}
const audio = context.createBufferSource()
audio.buffer = sound
audio.loop = loop
Expand Down
4 changes: 4 additions & 0 deletions plugins/love-resources/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,10 @@ async function checkRecordAvailable (): Promise<void> {
}, 500)
} else if (endpoint !== '') {
const res = await fetch(concatLink(endpoint, '/checkRecordAvailable'))
if (!res.ok || !res.headers.get('content-type')?.includes('application/json')) {
isRecordingAvailable.set(false)
return
}
const result = await res.json()
isRecordingAvailable.set(result)
} else {
Expand Down
30 changes: 27 additions & 3 deletions plugins/notification-resources/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ export function pushAvailable (): boolean {
return (
'serviceWorker' in navigator &&
'PushManager' in window &&
publicKey !== undefined &&
isValidPushPublicKey(publicKey) &&
'Notification' in window &&
Notification.permission !== 'denied'
)
Expand All @@ -748,7 +748,7 @@ export async function subscribePush (): Promise<boolean> {
}
const client = getClient()
const publicKey = getPushPublicKey()
if ('serviceWorker' in navigator && 'PushManager' in window && publicKey !== undefined) {
if ('serviceWorker' in navigator && 'PushManager' in window && isValidPushPublicKey(publicKey)) {
try {
const loc = getCurrentLocation()
let registration = await navigator.serviceWorker.getRegistration(`/${loc.path[0]}/${loc.path[1]}`)
Expand All @@ -763,7 +763,7 @@ export async function subscribePush (): Promise<boolean> {
if (current == null) {
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: publicKey
applicationServerKey: urlBase64ToUint8Array(publicKey)
})
await client.createDoc(notification.class.PushSubscription, core.space.Workspace, {
user: getCurrentAccount().uuid,
Expand Down Expand Up @@ -808,6 +808,30 @@ function getPushPublicKey (): string | undefined {
return publicKey.trim() !== '' ? publicKey : undefined
}

function isValidPushPublicKey (publicKey: string | undefined): publicKey is string {
if (publicKey === undefined || publicKey.trim() === '') return false

try {
const key = urlBase64ToUint8Array(publicKey)
return key.length === 65 && key[0] === 4
} catch {
return false
}
}

function urlBase64ToUint8Array (value: string): Uint8Array<ArrayBuffer> {
const padding = '='.repeat((4 - (value.length % 4)) % 4)
const base64 = `${value}${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
}

async function cleanTag (_id: Ref<Doc>): Promise<void> {
const client = getClient()
const notifications = await client.findAll(notification.class.BrowserNotification, {
Expand Down