Skip to content

Commit

Permalink
fix(core): skip resumeInfinity on Android browsers
Browse files Browse the repository at this point in the history
  • Loading branch information
jankapunkt committed Dec 6, 2021
1 parent 0eea9c9 commit cf03e62
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 10 deletions.
21 changes: 17 additions & 4 deletions docs/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const internal = {
status: 'created'
};

const patches = {};

/*******************************************************************************
*
* AVAILABLE WITHOUT INIT
Expand Down Expand Up @@ -131,11 +133,21 @@ const detectFeatures = () => {
features[name] = hasUtterance && hasProperty(features.speechSynthesisUtterance.prototype, name);
});

// not published to the outside
patches.skipInfinity = skipInfinity();

return features
};

/** @private **/
const hasProperty = (target = {}, prop) => Object.hasOwnProperty.call(target, prop) || prop in target || !!target[prop];

/** @private **/
const skipInfinity = () => {
const ua = (scope.navigator || {}).userAgent || '';
return /android/i.test(ua)
};

/**
* Common prefixes for browsers that tend to implement their custom names for
* certain parts of their API.
Expand Down Expand Up @@ -634,9 +646,9 @@ EasySpeech.speak = ({ text, voice, pitch, rate, volume, ...handlers }) => {
// https://stackoverflow.com/questions/21947730/chrome-speech-synthesis-with-longer-texts
//
// XXX: this apparently works only on chrome desktop, while it breaks chrome
// mobile (android), which is why we skip this on these devices
// mobile (android), so we need to detect chrome desktop
utterance.addEventListener('start', () => {
if (internal.speechSynthesisVoice) {
if (patches.skipInfinity !== true) {
resumeInfinity(utterance);
}
});
Expand Down Expand Up @@ -680,14 +692,15 @@ let timeoutResumeInfinity;
* @param target
*/
function resumeInfinity (target) {
// prevent memory-leak in case utterance is deleted, while this is ongoing
if (!target && timeoutResumeInfinity) {
debug('force-clear timeout');
return clearTimeout(timeoutResumeInfinity)
return scope.clearTimeout(timeoutResumeInfinity)
}

internal.speechSynthesis.pause();
internal.speechSynthesis.resume();
timeoutResumeInfinity = setTimeout(function () {
timeoutResumeInfinity = scope.setTimeout(function () {
resumeInfinity(target);
}, 5000);
}
Expand Down
5 changes: 4 additions & 1 deletion docs/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,10 @@ async function populateVoices (initialized) {
.sort((a, b) => a.name.localeCompare(b.name))

filteredVoices.forEach((voice, index) => {
const option = textNode(voice.name, 'option')
const service = voice.localService ? 'local' : 'remote'
const isDefault = voice.default ? '[DEFAULT]' : ''
const voiceName = `${isDefault}${voice.name} - ${voice.voiceURI} (${service})`
const option = textNode(voiceName, 'option')
option.setAttribute('value', index.toString(10))
inputs.voice.appendChild(option)
})
Expand Down
21 changes: 17 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const internal = {
status: 'created'
}

const patches = {}

/*******************************************************************************
*
* AVAILABLE WITHOUT INIT
Expand Down Expand Up @@ -131,11 +133,21 @@ const detectFeatures = () => {
features[name] = hasUtterance && hasProperty(features.speechSynthesisUtterance.prototype, name)
})

// not published to the outside
patches.skipInfinity = skipInfinity()

return features
}

/** @private **/
const hasProperty = (target = {}, prop) => Object.hasOwnProperty.call(target, prop) || prop in target || !!target[prop]

/** @private **/
const skipInfinity = () => {
const ua = (scope.navigator || {}).userAgent || ''
return /android/i.test(ua)
}

/**
* Common prefixes for browsers that tend to implement their custom names for
* certain parts of their API.
Expand Down Expand Up @@ -634,9 +646,9 @@ EasySpeech.speak = ({ text, voice, pitch, rate, volume, ...handlers }) => {
// https://stackoverflow.com/questions/21947730/chrome-speech-synthesis-with-longer-texts
//
// XXX: this apparently works only on chrome desktop, while it breaks chrome
// mobile (android), which is why we skip this on these devices
// mobile (android), so we need to detect chrome desktop
utterance.addEventListener('start', () => {
if (internal.speechSynthesisVoice) {
if (patches.skipInfinity !== true) {
resumeInfinity(utterance)
}
})
Expand Down Expand Up @@ -680,14 +692,15 @@ let timeoutResumeInfinity
* @param target
*/
function resumeInfinity (target) {
// prevent memory-leak in case utterance is deleted, while this is ongoing
if (!target && timeoutResumeInfinity) {
debug('force-clear timeout')
return clearTimeout(timeoutResumeInfinity)
return scope.clearTimeout(timeoutResumeInfinity)
}

internal.speechSynthesis.pause()
internal.speechSynthesis.resume()
timeoutResumeInfinity = setTimeout(function () {
timeoutResumeInfinity = scope.setTimeout(function () {
resumeInfinity(target)
}, 5000)
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "easy-speech",
"version": "1.1.0",
"version": "1.1.1",
"description": "Cross browser Speech Synthesis",
"type": "module",
"main": "index.js",
Expand Down

0 comments on commit cf03e62

Please sign in to comment.