react-say-fork
Version:
# Goal and TODOs * Add Typescript support * Make compononents style-customizable
102 lines (101 loc) • 4.49 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const createCustomEvent_1 = __importDefault(require("./createCustomEvent"));
const createDeferred_1 = __importDefault(require("./createDeferred"));
const createErrorEvent_1 = __importDefault(require("./createErrorEvent"));
function speakUtterance(ponyfill, utterance, startCallback) {
return __awaiter(this, void 0, void 0, function* () {
const { speechSynthesis } = ponyfill;
const startDeferred = (0, createDeferred_1.default)();
const errorDeferred = (0, createDeferred_1.default)();
const endDeferred = (0, createDeferred_1.default)();
utterance === null || utterance === void 0 ? void 0 : utterance.addEventListener('end', endDeferred.resolve);
utterance === null || utterance === void 0 ? void 0 : utterance.addEventListener('error', errorDeferred.resolve);
utterance === null || utterance === void 0 ? void 0 : utterance.addEventListener('start', startDeferred.resolve);
speechSynthesis.speak(utterance);
const startEvent = yield Promise.race([
errorDeferred.promise,
startDeferred.promise,
]);
if (startEvent.type === 'error') {
throw startEvent.error;
}
let finishedSpeaking;
const endPromise = Promise.race([errorDeferred.promise, endDeferred.promise]);
startCallback &&
startCallback(() => __awaiter(this, void 0, void 0, function* () {
if (!finishedSpeaking) {
speechSynthesis.cancel();
yield endPromise;
}
}));
const endEvent = yield endPromise;
finishedSpeaking = true;
if (endEvent.type === 'error') {
throw endEvent.error;
}
});
}
class QueuedUtterance {
constructor(ponyfill, utterance, { onEnd, onError, onStart }) {
this._cancelled = false;
this._deferred = (0, createDeferred_1.default)();
this._onEnd = onEnd;
this._onError = onError;
this._onStart = onStart;
this._ponyfill = ponyfill;
this._speaking = false;
this._utterance = utterance;
this.promise = this._deferred.promise;
}
cancel() {
return __awaiter(this, void 0, void 0, function* () {
this._cancelled = true;
this._cancel && (yield this._cancel());
});
}
speak() {
if (this._speaking) {
console.warn(`ASSERTION: QueuedUtterance is already speaking or has spoken.`);
}
this._speaking = true;
(() => __awaiter(this, void 0, void 0, function* () {
if (this._cancelled) {
throw new Error('cancelled');
}
yield speakUtterance(this._ponyfill, this._utterance, (cancel) => {
if (this._cancelled) {
cancel();
throw new Error('cancelled');
}
else {
this._cancel = cancel;
this._onStart && this._onStart((0, createCustomEvent_1.default)('start'));
}
});
if (this._cancelled) {
throw new Error('cancelled');
}
}))().then(() => {
this._onEnd && this._onEnd((0, createCustomEvent_1.default)('end'));
this._deferred.resolve();
}, (error) => {
this._onError && this._onError((0, createErrorEvent_1.default)(error));
this._deferred.reject(error);
});
return this.promise;
}
}
exports.default = QueuedUtterance;