@arwes/bleeps
Advanced tools
Comparing version 1.0.0-next.24042601 to 1.0.0-next.24042701
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createBleep = void 0; | ||
const tools_1 = require("@arwes/tools"); | ||
const createBleep = (props) => { | ||
const isBleepsAvailable = tools_1.IS_BROWSER && !!window.AudioContext; | ||
const isBrowser = typeof window !== 'undefined'; | ||
const isBrowserSafari = isBrowser && | ||
window.navigator.userAgent.includes('Safari') && | ||
!window.navigator.userAgent.includes('Chrome'); | ||
const isBleepsAvailable = isBrowser && !!window.AudioContext; | ||
if (!isBleepsAvailable) { | ||
return null; | ||
} | ||
const { sources, preload = true, loop = false, volume = 1.0, fetchHeaders, masterGain } = props; | ||
const { sources, preload = true, loop = false, volume = 1.0, fetchHeaders, masterGain, maxPlaybackDelay = 0.25 } = props; | ||
let isBufferLoading = false; | ||
let isBufferError = false; | ||
let isBufferPlaying = false; | ||
let playbackCallbackTime = 0; | ||
let hasPlaybackCallback = false; | ||
let source = null; | ||
let buffer = null; | ||
let duration = 0; | ||
let fetchPromise; | ||
const context = props.context ?? new window.AudioContext(); | ||
const gain = context.createGain(); | ||
const callersAccount = new Set(); | ||
const fetchAudioBuffer = () => { | ||
const getDuration = () => duration; | ||
const getIsPlaying = () => isBufferPlaying; | ||
const getIsLoaded = () => !!buffer; | ||
function fetchAudioBuffer() { | ||
if (buffer || isBufferLoading || isBufferError) { | ||
@@ -32,3 +41,3 @@ return; | ||
// "webm" and "weba" file formats are not supported on Safari. | ||
if (tools_1.IS_BROWSER_SAFARI && source.type.includes('audio/webm')) { | ||
if (isBrowserSafari && source.type.includes('audio/webm')) { | ||
return false; | ||
@@ -46,4 +55,3 @@ } | ||
isBufferLoading = true; | ||
// eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
window | ||
fetchPromise = window | ||
.fetch(src, { | ||
@@ -69,10 +77,31 @@ method: 'GET', | ||
}) | ||
.then(() => (isBufferLoading = false)); | ||
}; | ||
const getDuration = () => duration; | ||
const getIsPlaying = () => isBufferPlaying; | ||
const getIsLoaded = () => !!buffer; | ||
const play = (caller) => { | ||
.then(() => { | ||
isBufferLoading = false; | ||
}); | ||
} | ||
function play(caller) { | ||
if (!buffer) { | ||
if (isBufferError) { | ||
return; | ||
} | ||
// Allow multiple playback schedules since user clicks may change the time difference. | ||
playbackCallbackTime = Date.now(); | ||
if (hasPlaybackCallback) { | ||
return; | ||
} | ||
fetchAudioBuffer(); | ||
// Schedule the playback for when the audio buffer is loaded. | ||
// If the buffer is loaded after `maxPlaybackDelay` seconds have passed | ||
// since the last time the user tried to play the audio, ignore the playback. | ||
hasPlaybackCallback = true; | ||
void fetchPromise.then(() => { | ||
const now = Date.now(); | ||
const isStillGoodToPlay = Number.isFinite(maxPlaybackDelay) | ||
? now <= playbackCallbackTime + maxPlaybackDelay * 1000 | ||
: true; | ||
if (buffer && isStillGoodToPlay) { | ||
play(); | ||
} | ||
hasPlaybackCallback = false; | ||
}); | ||
return; | ||
@@ -115,5 +144,10 @@ } | ||
isBufferPlaying = false; | ||
if (source) { | ||
source.stop(); | ||
source.disconnect(gain); | ||
source = null; | ||
} | ||
}; | ||
}; | ||
const stop = (caller) => { | ||
} | ||
function stop(caller) { | ||
if (!buffer) { | ||
@@ -134,7 +168,7 @@ return; | ||
} | ||
}; | ||
const load = () => { | ||
} | ||
function load() { | ||
fetchAudioBuffer(); | ||
}; | ||
const unload = () => { | ||
} | ||
function unload() { | ||
if (source) { | ||
@@ -149,4 +183,4 @@ source.stop(); | ||
isBufferError = false; | ||
}; | ||
const update = (props) => { | ||
} | ||
function update(props) { | ||
if (props.volume !== undefined) { | ||
@@ -156,3 +190,3 @@ const bleepVolume = Math.max(0, Math.min(1, props.volume)); | ||
} | ||
}; | ||
} | ||
const bleep = {}; | ||
@@ -159,0 +193,0 @@ const bleepAPI = { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createBleepsManager = void 0; | ||
const tools_1 = require("@arwes/tools"); | ||
const index_js_1 = require("../createBleep/index.js"); | ||
@@ -9,3 +8,3 @@ const createBleepsManager = (props) => { | ||
// actual functionalities. | ||
const isBleepsAvailable = tools_1.IS_BROWSER && !!window.AudioContext; | ||
const isBleepsAvailable = typeof window !== 'undefined' && !!window.AudioContext; | ||
const context = isBleepsAvailable ? new window.AudioContext() : null; | ||
@@ -12,0 +11,0 @@ const masterGain = isBleepsAvailable ? context.createGain() : null; |
@@ -1,18 +0,27 @@ | ||
import { IS_BROWSER, IS_BROWSER_SAFARI } from '@arwes/tools'; | ||
const createBleep = (props) => { | ||
const isBleepsAvailable = IS_BROWSER && !!window.AudioContext; | ||
const isBrowser = typeof window !== 'undefined'; | ||
const isBrowserSafari = isBrowser && | ||
window.navigator.userAgent.includes('Safari') && | ||
!window.navigator.userAgent.includes('Chrome'); | ||
const isBleepsAvailable = isBrowser && !!window.AudioContext; | ||
if (!isBleepsAvailable) { | ||
return null; | ||
} | ||
const { sources, preload = true, loop = false, volume = 1.0, fetchHeaders, masterGain } = props; | ||
const { sources, preload = true, loop = false, volume = 1.0, fetchHeaders, masterGain, maxPlaybackDelay = 0.25 } = props; | ||
let isBufferLoading = false; | ||
let isBufferError = false; | ||
let isBufferPlaying = false; | ||
let playbackCallbackTime = 0; | ||
let hasPlaybackCallback = false; | ||
let source = null; | ||
let buffer = null; | ||
let duration = 0; | ||
let fetchPromise; | ||
const context = props.context ?? new window.AudioContext(); | ||
const gain = context.createGain(); | ||
const callersAccount = new Set(); | ||
const fetchAudioBuffer = () => { | ||
const getDuration = () => duration; | ||
const getIsPlaying = () => isBufferPlaying; | ||
const getIsLoaded = () => !!buffer; | ||
function fetchAudioBuffer() { | ||
if (buffer || isBufferLoading || isBufferError) { | ||
@@ -29,3 +38,3 @@ return; | ||
// "webm" and "weba" file formats are not supported on Safari. | ||
if (IS_BROWSER_SAFARI && source.type.includes('audio/webm')) { | ||
if (isBrowserSafari && source.type.includes('audio/webm')) { | ||
return false; | ||
@@ -43,4 +52,3 @@ } | ||
isBufferLoading = true; | ||
// eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
window | ||
fetchPromise = window | ||
.fetch(src, { | ||
@@ -66,10 +74,31 @@ method: 'GET', | ||
}) | ||
.then(() => (isBufferLoading = false)); | ||
}; | ||
const getDuration = () => duration; | ||
const getIsPlaying = () => isBufferPlaying; | ||
const getIsLoaded = () => !!buffer; | ||
const play = (caller) => { | ||
.then(() => { | ||
isBufferLoading = false; | ||
}); | ||
} | ||
function play(caller) { | ||
if (!buffer) { | ||
if (isBufferError) { | ||
return; | ||
} | ||
// Allow multiple playback schedules since user clicks may change the time difference. | ||
playbackCallbackTime = Date.now(); | ||
if (hasPlaybackCallback) { | ||
return; | ||
} | ||
fetchAudioBuffer(); | ||
// Schedule the playback for when the audio buffer is loaded. | ||
// If the buffer is loaded after `maxPlaybackDelay` seconds have passed | ||
// since the last time the user tried to play the audio, ignore the playback. | ||
hasPlaybackCallback = true; | ||
void fetchPromise.then(() => { | ||
const now = Date.now(); | ||
const isStillGoodToPlay = Number.isFinite(maxPlaybackDelay) | ||
? now <= playbackCallbackTime + maxPlaybackDelay * 1000 | ||
: true; | ||
if (buffer && isStillGoodToPlay) { | ||
play(); | ||
} | ||
hasPlaybackCallback = false; | ||
}); | ||
return; | ||
@@ -112,5 +141,10 @@ } | ||
isBufferPlaying = false; | ||
if (source) { | ||
source.stop(); | ||
source.disconnect(gain); | ||
source = null; | ||
} | ||
}; | ||
}; | ||
const stop = (caller) => { | ||
} | ||
function stop(caller) { | ||
if (!buffer) { | ||
@@ -131,7 +165,7 @@ return; | ||
} | ||
}; | ||
const load = () => { | ||
} | ||
function load() { | ||
fetchAudioBuffer(); | ||
}; | ||
const unload = () => { | ||
} | ||
function unload() { | ||
if (source) { | ||
@@ -146,4 +180,4 @@ source.stop(); | ||
isBufferError = false; | ||
}; | ||
const update = (props) => { | ||
} | ||
function update(props) { | ||
if (props.volume !== undefined) { | ||
@@ -153,3 +187,3 @@ const bleepVolume = Math.max(0, Math.min(1, props.volume)); | ||
} | ||
}; | ||
} | ||
const bleep = {}; | ||
@@ -156,0 +190,0 @@ const bleepAPI = { |
@@ -1,2 +0,1 @@ | ||
import { IS_BROWSER } from '@arwes/tools'; | ||
import { createBleep } from '../createBleep/index.js'; | ||
@@ -6,3 +5,3 @@ const createBleepsManager = (props) => { | ||
// actual functionalities. | ||
const isBleepsAvailable = IS_BROWSER && !!window.AudioContext; | ||
const isBleepsAvailable = typeof window !== 'undefined' && !!window.AudioContext; | ||
const context = isBleepsAvailable ? new window.AudioContext() : null; | ||
@@ -9,0 +8,0 @@ const masterGain = isBleepsAvailable ? context.createGain() : null; |
@@ -6,2 +6,3 @@ export type BleepCategory = 'background' | 'transition' | 'interaction' | 'notification'; | ||
readonly fetchHeaders?: Headers; | ||
readonly maxPlaybackDelay?: number; | ||
readonly disabled?: boolean; | ||
@@ -8,0 +9,0 @@ } |
{ | ||
"name": "@arwes/bleeps", | ||
"version": "1.0.0-next.24042601", | ||
"version": "1.0.0-next.24042701", | ||
"publishConfig": { | ||
@@ -43,3 +43,2 @@ "access": "public" | ||
"dependencies": { | ||
"@arwes/tools": "^1.0.0-next.24042601", | ||
"tslib": "2" | ||
@@ -53,3 +52,3 @@ }, | ||
}, | ||
"gitHead": "f8d2716df8a6301df828d4b1627a8d21f1ef56e6" | ||
"gitHead": "c98aa1289657078392e108d81cdd819a61d5c4e2" | ||
} |
28857
1
767
- Removed@arwes/tools@^1.0.0-next.24042601
- Removed@arwes/tools@1.0.0-next.25020502(transitive)