provide UI feedback for remote hangup

This commit is contained in:
or-else
2022-06-03 16:50:06 -07:00
parent ae15a043b1
commit 4e720a0d5b
6 changed files with 339 additions and 459 deletions
Binary file not shown.
+30 -7
View File
@@ -11,6 +11,8 @@ import { clipStr } from '../lib/utils.js'
const RING_SOUND = new Audio('audio/call-out.m4a'); const RING_SOUND = new Audio('audio/call-out.m4a');
RING_SOUND.loop = true; RING_SOUND.loop = true;
const CALL_ENDED_SOUND = new Audio('audio/call-end.m4a');
CALL_ENDED_SOUND.loop = true;
const messages = defineMessages({ const messages = defineMessages({
already_in_call: { already_in_call: {
@@ -28,7 +30,8 @@ class CallPanel extends React.PureComponent {
localStream: undefined, localStream: undefined,
pc: undefined, pc: undefined,
previousOnInfo: undefined previousOnInfo: undefined,
waitingForPeer: false
}; };
this.localStreamConstraints = { this.localStreamConstraints = {
@@ -134,7 +137,7 @@ class CallPanel extends React.PureComponent {
// Start local video. // Start local video.
navigator.mediaDevices.getUserMedia(this.localStreamConstraints) navigator.mediaDevices.getUserMedia(this.localStreamConstraints)
.then(stream => { .then(stream => {
this.setState({localStream: stream}); this.setState({localStream: stream, waitingForPeer: true});
this.localRef.current.srcObject = stream; this.localRef.current.srcObject = stream;
RING_SOUND.play(); RING_SOUND.play();
@@ -146,6 +149,8 @@ class CallPanel extends React.PureComponent {
} }
stop() { stop() {
CALL_ENDED_SOUND.pause();
CALL_ENDED_SOUND.currentTime = 0;
RING_SOUND.pause(); RING_SOUND.pause();
RING_SOUND.currentTime = 0; RING_SOUND.currentTime = 0;
@@ -163,7 +168,7 @@ class CallPanel extends React.PureComponent {
this.state.pc.close(); this.state.pc.close();
} }
this.setState({pc: null}); this.setState({pc: null, waitingForPeer: false});
} }
stopTracks(el) { stopTracks(el) {
@@ -197,7 +202,7 @@ class CallPanel extends React.PureComponent {
pc.onnegotiationneeded = this.handleNegotiationNeededEvent; pc.onnegotiationneeded = this.handleNegotiationNeededEvent;
pc.ontrack = this.handleTrackEvent; pc.ontrack = this.handleTrackEvent;
this.setState({pc: pc}); this.setState({pc: pc, waitingForPeer: false});
return pc; return pc;
} }
@@ -264,14 +269,15 @@ class CallPanel extends React.PureComponent {
switch(e.name) { switch(e.name) {
case 'NotFoundError': case 'NotFoundError':
// Cannot start the call b/c no camera and/or microphone found. // Cannot start the call b/c no camera and/or microphone found.
this.reportError(e); this.reportError(e.message);
break; break;
case 'SecurityError': case 'SecurityError':
case 'PermissionDeniedError': case 'PermissionDeniedError':
// Do nothing; this is the same as the user canceling the call. // Do nothing; this is the same as the user canceling the call.
break; break;
default: default:
console.log('Error opening your camera and/or microphone: ' + e.message); this.reportError(e.message);
console.error('Error opening your camera and/or microphone: ' + e.message);
break; break;
} }
@@ -309,8 +315,24 @@ class CallPanel extends React.PureComponent {
.catch(this.handleGetUserMediaError); .catch(this.handleGetUserMediaError);
} }
// Call disconnected by remote.
handleRemoteHangup() { handleRemoteHangup() {
if (!this.state.waitingForPeer) {
// This is live call, just hang up.
this.handleCloseClick(); this.handleCloseClick();
} else {
// This is a call which is not yet connected.
// Stop pulse animation.
this.setState({waitingForPeer: false});
// Change sound and wait a bit before ending it.
RING_SOUND.pause();
RING_SOUND.currentTime = 0;
CALL_ENDED_SOUND.loop = true;
CALL_ENDED_SOUND.play();
setTimeout(_ => {
this.handleCloseClick();
}, 2000);
}
} }
handleCloseClick() { handleCloseClick() {
@@ -345,6 +367,7 @@ class CallPanel extends React.PureComponent {
const audioIcon = this.state.localStream && this.state.localStream.getAudioTracks()[0].enabled ? 'mic' : 'mic_off'; const audioIcon = this.state.localStream && this.state.localStream.getAudioTracks()[0].enabled ? 'mic' : 'mic_off';
const videoIcon = this.state.localStream && this.state.localStream.getVideoTracks()[0].enabled ? 'videocam' : 'videocam_off'; const videoIcon = this.state.localStream && this.state.localStream.getVideoTracks()[0].enabled ? 'videocam' : 'videocam_off';
const peerTitle = clipStr(this.props.title, MAX_PEER_TITLE_LENGTH); const peerTitle = clipStr(this.props.title, MAX_PEER_TITLE_LENGTH);
const pulseAnimation = this.state.waitingForPeer ? ' pulse' : '';
return ( return (
<> <>
@@ -361,7 +384,7 @@ class CallPanel extends React.PureComponent {
<video ref={this.remoteRef} autoPlay playsInline></video> <video ref={this.remoteRef} autoPlay playsInline></video>
{remoteActive ? {remoteActive ?
<div className="caller-name inactive">{peerTitle}</div> : <div className="caller-name inactive">{peerTitle}</div> :
<div className="caller-card pulse"> <div className={`caller-card${pulseAnimation}`}>
<div className="avatar-box"> <div className="avatar-box">
<LetterTile <LetterTile
tinode={this.props.tinode} tinode={this.props.tinode}
+222 -365
View File
@@ -11,6 +11,7 @@
__webpack_require__.r(__webpack_exports__); __webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "CONSTANTS": () => (/* binding */ CONSTANTS), /* harmony export */ "CONSTANTS": () => (/* binding */ CONSTANTS),
/* harmony export */ "DBWrapper": () => (/* binding */ DBWrapper),
/* harmony export */ "Deferred": () => (/* binding */ Deferred), /* harmony export */ "Deferred": () => (/* binding */ Deferred),
/* harmony export */ "ErrorFactory": () => (/* binding */ ErrorFactory), /* harmony export */ "ErrorFactory": () => (/* binding */ ErrorFactory),
/* harmony export */ "FirebaseError": () => (/* binding */ FirebaseError), /* harmony export */ "FirebaseError": () => (/* binding */ FirebaseError),
@@ -33,6 +34,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ "deepCopy": () => (/* binding */ deepCopy), /* harmony export */ "deepCopy": () => (/* binding */ deepCopy),
/* harmony export */ "deepEqual": () => (/* binding */ deepEqual), /* harmony export */ "deepEqual": () => (/* binding */ deepEqual),
/* harmony export */ "deepExtend": () => (/* binding */ deepExtend), /* harmony export */ "deepExtend": () => (/* binding */ deepExtend),
/* harmony export */ "deleteDB": () => (/* binding */ deleteDB),
/* harmony export */ "errorPrefix": () => (/* binding */ errorPrefix), /* harmony export */ "errorPrefix": () => (/* binding */ errorPrefix),
/* harmony export */ "extractQuerystring": () => (/* binding */ extractQuerystring), /* harmony export */ "extractQuerystring": () => (/* binding */ extractQuerystring),
/* harmony export */ "getGlobal": () => (/* binding */ getGlobal), /* harmony export */ "getGlobal": () => (/* binding */ getGlobal),
@@ -56,6 +58,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ "issuedAtTime": () => (/* binding */ issuedAtTime), /* harmony export */ "issuedAtTime": () => (/* binding */ issuedAtTime),
/* harmony export */ "jsonEval": () => (/* binding */ jsonEval), /* harmony export */ "jsonEval": () => (/* binding */ jsonEval),
/* harmony export */ "map": () => (/* binding */ map), /* harmony export */ "map": () => (/* binding */ map),
/* harmony export */ "openDB": () => (/* binding */ openDB),
/* harmony export */ "ordinal": () => (/* binding */ ordinal), /* harmony export */ "ordinal": () => (/* binding */ ordinal),
/* harmony export */ "querystring": () => (/* binding */ querystring), /* harmony export */ "querystring": () => (/* binding */ querystring),
/* harmony export */ "querystringDecode": () => (/* binding */ querystringDecode), /* harmony export */ "querystringDecode": () => (/* binding */ querystringDecode),
@@ -1966,6 +1969,162 @@ function getModularInstance(service) {
} }
} }
/**
* @license
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @internal
*/
function promisifyRequest(request, errorMessage) {
return new Promise((resolve, reject) => {
request.onsuccess = event => {
resolve(event.target.result);
};
request.onerror = event => {
var _a;
reject(`${errorMessage}: ${(_a = event.target.error) === null || _a === void 0 ? void 0 : _a.message}`);
};
});
}
/**
* @internal
*/
class DBWrapper {
constructor(_db) {
this._db = _db;
this.objectStoreNames = this._db.objectStoreNames;
}
transaction(storeNames, mode = 'readonly') {
return new TransactionWrapper(this._db.transaction.call(this._db, storeNames, mode));
}
createObjectStore(storeName, options) {
return new ObjectStoreWrapper(this._db.createObjectStore(storeName, options));
}
close() {
this._db.close();
}
}
/**
* @internal
*/
class TransactionWrapper {
constructor(_transaction) {
this._transaction = _transaction;
this.complete = new Promise((resolve, reject) => {
this._transaction.oncomplete = function () {
resolve();
};
this._transaction.onerror = () => {
reject(this._transaction.error);
};
this._transaction.onabort = () => {
reject(this._transaction.error);
};
});
}
objectStore(storeName) {
return new ObjectStoreWrapper(this._transaction.objectStore(storeName));
}
}
/**
* @internal
*/
class ObjectStoreWrapper {
constructor(_store) {
this._store = _store;
}
index(name) {
return new IndexWrapper(this._store.index(name));
}
createIndex(name, keypath, options) {
return new IndexWrapper(this._store.createIndex(name, keypath, options));
}
get(key) {
const request = this._store.get(key);
return promisifyRequest(request, 'Error reading from IndexedDB');
}
put(value, key) {
const request = this._store.put(value, key);
return promisifyRequest(request, 'Error writing to IndexedDB');
}
delete(key) {
const request = this._store.delete(key);
return promisifyRequest(request, 'Error deleting from IndexedDB');
}
clear() {
const request = this._store.clear();
return promisifyRequest(request, 'Error clearing IndexedDB object store');
}
}
/**
* @internal
*/
class IndexWrapper {
constructor(_index) {
this._index = _index;
}
get(key) {
const request = this._index.get(key);
return promisifyRequest(request, 'Error reading from IndexedDB');
}
}
/**
* @internal
*/
function openDB(dbName, dbVersion, upgradeCallback) {
return new Promise((resolve, reject) => {
try {
const request = indexedDB.open(dbName, dbVersion);
request.onsuccess = event => {
resolve(new DBWrapper(event.target.result));
};
request.onerror = event => {
var _a;
reject(`Error opening indexedDB: ${(_a = event.target.error) === null || _a === void 0 ? void 0 : _a.message}`);
};
request.onupgradeneeded = event => {
upgradeCallback(new DBWrapper(request.result), event.oldVersion, event.newVersion, new TransactionWrapper(request.transaction));
};
}
catch (e) {
reject(`Error opening indexedDB: ${e.message}`);
}
});
}
/**
* @internal
*/
async function deleteDB(dbName) {
return new Promise((resolve, reject) => {
try {
const request = indexedDB.deleteDatabase(dbName);
request.onsuccess = () => {
resolve();
};
request.onerror = event => {
var _a;
reject(`Error deleting indexedDB database "${dbName}": ${(_a = event.target.error) === null || _a === void 0 ? void 0 : _a.message}`);
};
}
catch (e) {
reject(`Error deleting indexedDB database "${dbName}": ${e.message}`);
}
});
}
//# sourceMappingURL=index.esm2017.js.map //# sourceMappingURL=index.esm2017.js.map
@@ -11174,6 +11333,8 @@ __webpack_require__.r(__webpack_exports__);
const RING_SOUND = new Audio('audio/call-out.m4a'); const RING_SOUND = new Audio('audio/call-out.m4a');
RING_SOUND.loop = true; RING_SOUND.loop = true;
const CALL_ENDED_SOUND = new Audio('audio/call-end.m4a');
CALL_ENDED_SOUND.loop = true;
const messages = (0,react_intl__WEBPACK_IMPORTED_MODULE_1__.defineMessages)({ const messages = (0,react_intl__WEBPACK_IMPORTED_MODULE_1__.defineMessages)({
already_in_call: { already_in_call: {
id: "already_in_call", id: "already_in_call",
@@ -11190,7 +11351,8 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
this.state = { this.state = {
localStream: undefined, localStream: undefined,
pc: undefined, pc: undefined,
previousOnInfo: undefined previousOnInfo: undefined,
waitingForPeer: false
}; };
this.localStreamConstraints = { this.localStreamConstraints = {
audio: true, audio: true,
@@ -11288,7 +11450,8 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
navigator.mediaDevices.getUserMedia(this.localStreamConstraints).then(stream => { navigator.mediaDevices.getUserMedia(this.localStreamConstraints).then(stream => {
this.setState({ this.setState({
localStream: stream localStream: stream,
waitingForPeer: true
}); });
this.localRef.current.srcObject = stream; this.localRef.current.srcObject = stream;
RING_SOUND.play(); RING_SOUND.play();
@@ -11297,6 +11460,8 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
} }
stop() { stop() {
CALL_ENDED_SOUND.pause();
CALL_ENDED_SOUND.currentTime = 0;
RING_SOUND.pause(); RING_SOUND.pause();
RING_SOUND.currentTime = 0; RING_SOUND.currentTime = 0;
this.stopTracks(this.localRef.current); this.stopTracks(this.localRef.current);
@@ -11315,7 +11480,8 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
} }
this.setState({ this.setState({
pc: null pc: null,
waitingForPeer: false
}); });
} }
@@ -11355,7 +11521,8 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
pc.onnegotiationneeded = this.handleNegotiationNeededEvent; pc.onnegotiationneeded = this.handleNegotiationNeededEvent;
pc.ontrack = this.handleTrackEvent; pc.ontrack = this.handleTrackEvent;
this.setState({ this.setState({
pc: pc pc: pc,
waitingForPeer: false
}); });
return pc; return pc;
} }
@@ -11415,7 +11582,7 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
handleGetUserMediaError(e) { handleGetUserMediaError(e) {
switch (e.name) { switch (e.name) {
case 'NotFoundError': case 'NotFoundError':
this.reportError(e); this.reportError(e.message);
break; break;
case 'SecurityError': case 'SecurityError':
@@ -11423,7 +11590,8 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
break; break;
default: default:
console.log('Error opening your camera and/or microphone: ' + e.message); this.reportError(e.message);
console.error('Error opening your camera and/or microphone: ' + e.message);
break; break;
} }
@@ -11455,7 +11623,20 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
} }
handleRemoteHangup() { handleRemoteHangup() {
if (!this.state.waitingForPeer) {
this.handleCloseClick(); this.handleCloseClick();
} else {
this.setState({
waitingForPeer: false
});
RING_SOUND.pause();
RING_SOUND.currentTime = 0;
CALL_ENDED_SOUND.loop = true;
CALL_ENDED_SOUND.play();
setTimeout(_ => {
this.handleCloseClick();
}, 2000);
}
} }
handleCloseClick() { handleCloseClick() {
@@ -11489,6 +11670,7 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
const audioIcon = this.state.localStream && this.state.localStream.getAudioTracks()[0].enabled ? 'mic' : 'mic_off'; const audioIcon = this.state.localStream && this.state.localStream.getAudioTracks()[0].enabled ? 'mic' : 'mic_off';
const videoIcon = this.state.localStream && this.state.localStream.getVideoTracks()[0].enabled ? 'videocam' : 'videocam_off'; const videoIcon = this.state.localStream && this.state.localStream.getVideoTracks()[0].enabled ? 'videocam' : 'videocam_off';
const peerTitle = (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_5__.clipStr)(this.props.title, _config_js__WEBPACK_IMPORTED_MODULE_3__.MAX_PEER_TITLE_LENGTH); const peerTitle = (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_5__.clipStr)(this.props.title, _config_js__WEBPACK_IMPORTED_MODULE_3__.MAX_PEER_TITLE_LENGTH);
const pulseAnimation = this.state.waitingForPeer ? ' pulse' : '';
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { return react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
id: "video-container" id: "video-container"
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { }, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
@@ -11517,7 +11699,7 @@ class CallPanel extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompon
}), remoteActive ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { }), remoteActive ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "caller-name inactive" className: "caller-name inactive"
}, peerTitle) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { }, peerTitle) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "caller-card pulse" className: "caller-card".concat(pulseAnimation)
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { }, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "avatar-box" className: "avatar-box"
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_letter_tile_jsx__WEBPACK_IMPORTED_MODULE_2__["default"], { }, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_letter_tile_jsx__WEBPACK_IMPORTED_MODULE_2__["default"], {
@@ -17329,7 +17511,7 @@ __webpack_require__.r(__webpack_exports__);
var name = "firebase"; var name = "firebase";
var version = "9.8.1"; var version = "9.6.11";
/** /**
* @license * @license
@@ -17973,8 +18155,6 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/component */ "./node_modules/@firebase/component/dist/esm/index.esm2017.js"); /* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/component */ "./node_modules/@firebase/component/dist/esm/index.esm2017.js");
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/logger */ "./node_modules/@firebase/logger/dist/esm/index.esm2017.js"); /* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/logger */ "./node_modules/@firebase/logger/dist/esm/index.esm2017.js");
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/util */ "./node_modules/@firebase/util/dist/index.esm2017.js"); /* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/util */ "./node_modules/@firebase/util/dist/index.esm2017.js");
/* harmony import */ var idb__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! idb */ "./node_modules/idb/build/index.js");
@@ -18034,7 +18214,7 @@ function isVersionServiceProvider(provider) {
} }
const name$o = "@firebase/app"; const name$o = "@firebase/app";
const version$1 = "0.7.24"; const version$1 = "0.7.21";
/** /**
* @license * @license
@@ -18101,7 +18281,7 @@ const name$2 = "@firebase/firestore";
const name$1 = "@firebase/firestore-compat"; const name$1 = "@firebase/firestore-compat";
const name = "firebase"; const name = "firebase";
const version = "9.8.1"; const version = "9.6.11";
/** /**
* @license * @license
@@ -18565,8 +18745,7 @@ const STORE_NAME = 'firebase-heartbeat-store';
let dbPromise = null; let dbPromise = null;
function getDbPromise() { function getDbPromise() {
if (!dbPromise) { if (!dbPromise) {
dbPromise = (0,idb__WEBPACK_IMPORTED_MODULE_3__.openDB)(DB_NAME, DB_VERSION, { dbPromise = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.openDB)(DB_NAME, DB_VERSION, (db, oldVersion) => {
upgrade: (db, oldVersion) => {
// We don't use 'break' in this switch statement, the fall-through // We don't use 'break' in this switch statement, the fall-through
// behavior is what we want, because if there are multiple versions between // behavior is what we want, because if there are multiple versions between
// the old version and the current version, we want ALL the migrations // the old version and the current version, we want ALL the migrations
@@ -18576,7 +18755,6 @@ function getDbPromise() {
case 0: case 0:
db.createObjectStore(STORE_NAME); db.createObjectStore(STORE_NAME);
} }
}
}).catch(e => { }).catch(e => {
throw ERROR_FACTORY.create("storage-open" /* STORAGE_OPEN */, { throw ERROR_FACTORY.create("storage-open" /* STORAGE_OPEN */, {
originalErrorMessage: e.message originalErrorMessage: e.message
@@ -18605,7 +18783,7 @@ async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
const tx = db.transaction(STORE_NAME, 'readwrite'); const tx = db.transaction(STORE_NAME, 'readwrite');
const objectStore = tx.objectStore(STORE_NAME); const objectStore = tx.objectStore(STORE_NAME);
await objectStore.put(heartbeatObject, computeKey(app)); await objectStore.put(heartbeatObject, computeKey(app));
return tx.done; return tx.complete;
} }
catch (e) { catch (e) {
throw ERROR_FACTORY.create("storage-set" /* STORAGE_WRITE */, { throw ERROR_FACTORY.create("storage-set" /* STORAGE_WRITE */, {
@@ -19335,14 +19513,12 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/app */ "./node_modules/@firebase/app/dist/esm/index.esm2017.js"); /* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/app */ "./node_modules/@firebase/app/dist/esm/index.esm2017.js");
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/component */ "./node_modules/@firebase/component/dist/esm/index.esm2017.js"); /* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/component */ "./node_modules/@firebase/component/dist/esm/index.esm2017.js");
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/util */ "./node_modules/@firebase/util/dist/index.esm2017.js"); /* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/util */ "./node_modules/@firebase/util/dist/index.esm2017.js");
/* harmony import */ var idb__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! idb */ "./node_modules/idb/build/index.js");
const name = "@firebase/installations"; const name = "@firebase/installations";
const version = "0.5.9"; const version = "0.5.8";
/** /**
* @license * @license
@@ -19744,8 +19920,7 @@ const OBJECT_STORE_NAME = 'firebase-installations-store';
let dbPromise = null; let dbPromise = null;
function getDbPromise() { function getDbPromise() {
if (!dbPromise) { if (!dbPromise) {
dbPromise = (0,idb__WEBPACK_IMPORTED_MODULE_3__.openDB)(DATABASE_NAME, DATABASE_VERSION, { dbPromise = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.openDB)(DATABASE_NAME, DATABASE_VERSION, (db, oldVersion) => {
upgrade: (db, oldVersion) => {
// We don't use 'break' in this switch statement, the fall-through // We don't use 'break' in this switch statement, the fall-through
// behavior is what we want, because if there are multiple versions between // behavior is what we want, because if there are multiple versions between
// the old version and the current version, we want ALL the migrations // the old version and the current version, we want ALL the migrations
@@ -19755,7 +19930,6 @@ function getDbPromise() {
case 0: case 0:
db.createObjectStore(OBJECT_STORE_NAME); db.createObjectStore(OBJECT_STORE_NAME);
} }
}
}); });
} }
return dbPromise; return dbPromise;
@@ -19768,7 +19942,7 @@ async function set(appConfig, value) {
const objectStore = tx.objectStore(OBJECT_STORE_NAME); const objectStore = tx.objectStore(OBJECT_STORE_NAME);
const oldValue = (await objectStore.get(key)); const oldValue = (await objectStore.get(key));
await objectStore.put(value, key); await objectStore.put(value, key);
await tx.done; await tx.complete;
if (!oldValue || oldValue.fid !== value.fid) { if (!oldValue || oldValue.fid !== value.fid) {
fidChanged(appConfig, value.fid); fidChanged(appConfig, value.fid);
} }
@@ -19780,7 +19954,7 @@ async function remove(appConfig) {
const db = await getDbPromise(); const db = await getDbPromise();
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
await tx.objectStore(OBJECT_STORE_NAME).delete(key); await tx.objectStore(OBJECT_STORE_NAME).delete(key);
await tx.done; await tx.complete;
} }
/** /**
* Atomically updates a record with the result of updateFn, which gets * Atomically updates a record with the result of updateFn, which gets
@@ -19801,7 +19975,7 @@ async function update(appConfig, updateFn) {
else { else {
await store.put(newValue, key); await store.put(newValue, key);
} }
await tx.done; await tx.complete;
if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) { if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {
fidChanged(appConfig, newValue.fid); fidChanged(appConfig, newValue.fid);
} }
@@ -20748,10 +20922,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ }); /* harmony export */ });
/* harmony import */ var _firebase_installations__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/installations */ "./node_modules/@firebase/installations/dist/esm/index.esm2017.js"); /* harmony import */ var _firebase_installations__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/installations */ "./node_modules/@firebase/installations/dist/esm/index.esm2017.js");
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/component */ "./node_modules/@firebase/component/dist/esm/index.esm2017.js"); /* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/component */ "./node_modules/@firebase/component/dist/esm/index.esm2017.js");
/* harmony import */ var idb__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! idb */ "./node_modules/idb/build/index.js"); /* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/util */ "./node_modules/@firebase/util/dist/index.esm2017.js");
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/util */ "./node_modules/@firebase/util/dist/index.esm2017.js"); /* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/app */ "./node_modules/@firebase/app/dist/esm/index.esm2017.js");
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/app */ "./node_modules/@firebase/app/dist/esm/index.esm2017.js");
@@ -20877,8 +21049,7 @@ async function migrateOldDatabase(senderId) {
} }
} }
let tokenDetails = null; let tokenDetails = null;
const db = await (0,idb__WEBPACK_IMPORTED_MODULE_2__.openDB)(OLD_DB_NAME, OLD_DB_VERSION, { const db = await (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.openDB)(OLD_DB_NAME, OLD_DB_VERSION, async (db, oldVersion, newVersion, upgradeTransaction) => {
upgrade: async (db, oldVersion, newVersion, upgradeTransaction) => {
var _a; var _a;
if (oldVersion < 2) { if (oldVersion < 2) {
// Database too old, skip migration. // Database too old, skip migration.
@@ -20942,13 +21113,12 @@ async function migrateOldDatabase(senderId) {
} }
}; };
} }
}
}); });
db.close(); db.close();
// Delete all old databases. // Delete all old databases.
await (0,idb__WEBPACK_IMPORTED_MODULE_2__.deleteDB)(OLD_DB_NAME); await (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.deleteDB)(OLD_DB_NAME);
await (0,idb__WEBPACK_IMPORTED_MODULE_2__.deleteDB)('fcm_vapid_details_db'); await (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.deleteDB)('fcm_vapid_details_db');
await (0,idb__WEBPACK_IMPORTED_MODULE_2__.deleteDB)('undefined'); await (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.deleteDB)('undefined');
return checkTokenDetails(tokenDetails) ? tokenDetails : null; return checkTokenDetails(tokenDetails) ? tokenDetails : null;
} }
function checkTokenDetails(tokenDetails) { function checkTokenDetails(tokenDetails) {
@@ -20995,8 +21165,7 @@ const OBJECT_STORE_NAME = 'firebase-messaging-store';
let dbPromise = null; let dbPromise = null;
function getDbPromise() { function getDbPromise() {
if (!dbPromise) { if (!dbPromise) {
dbPromise = (0,idb__WEBPACK_IMPORTED_MODULE_2__.openDB)(DATABASE_NAME, DATABASE_VERSION, { dbPromise = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.openDB)(DATABASE_NAME, DATABASE_VERSION, (upgradeDb, oldVersion) => {
upgrade: (upgradeDb, oldVersion) => {
// We don't use 'break' in this switch statement, the fall-through behavior is what we want, // We don't use 'break' in this switch statement, the fall-through behavior is what we want,
// because if there are multiple versions between the old version and the current version, we // because if there are multiple versions between the old version and the current version, we
// want ALL the migrations that correspond to those versions to run, not only the last one. // want ALL the migrations that correspond to those versions to run, not only the last one.
@@ -21005,7 +21174,6 @@ function getDbPromise() {
case 0: case 0:
upgradeDb.createObjectStore(OBJECT_STORE_NAME); upgradeDb.createObjectStore(OBJECT_STORE_NAME);
} }
}
}); });
} }
return dbPromise; return dbPromise;
@@ -21036,7 +21204,7 @@ async function dbSet(firebaseDependencies, tokenDetails) {
const db = await getDbPromise(); const db = await getDbPromise();
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
await tx.objectStore(OBJECT_STORE_NAME).put(tokenDetails, key); await tx.objectStore(OBJECT_STORE_NAME).put(tokenDetails, key);
await tx.done; await tx.complete;
return tokenDetails; return tokenDetails;
} }
/** Removes record(s) from the objectStore that match the given key. */ /** Removes record(s) from the objectStore that match the given key. */
@@ -21045,7 +21213,7 @@ async function dbRemove(firebaseDependencies) {
const db = await getDbPromise(); const db = await getDbPromise();
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
await tx.objectStore(OBJECT_STORE_NAME).delete(key); await tx.objectStore(OBJECT_STORE_NAME).delete(key);
await tx.done; await tx.complete;
} }
function getKey({ appConfig }) { function getKey({ appConfig }) {
return appConfig.appId; return appConfig.appId;
@@ -21090,7 +21258,7 @@ const ERROR_MAP = {
["use-vapid-key-after-get-token" /* USE_VAPID_KEY_AFTER_GET_TOKEN */]: 'The usePublicVapidKey() method may only be called once and must be ' + ["use-vapid-key-after-get-token" /* USE_VAPID_KEY_AFTER_GET_TOKEN */]: 'The usePublicVapidKey() method may only be called once and must be ' +
'called before calling getToken() to ensure your VAPID key is used.' 'called before calling getToken() to ensure your VAPID key is used.'
}; };
const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.ErrorFactory('messaging', 'Messaging', ERROR_MAP); const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_2__.ErrorFactory('messaging', 'Messaging', ERROR_MAP);
/** /**
* @license * @license
@@ -21742,7 +21910,7 @@ async function messageEventListener(messaging, event) {
} }
const name = "@firebase/messaging"; const name = "@firebase/messaging";
const version = "0.9.13"; const version = "0.9.12";
/** /**
* @license * @license
@@ -21775,11 +21943,11 @@ const WindowMessagingInternalFactory = (container) => {
return messagingInternal; return messagingInternal;
}; };
function registerMessagingInWindow() { function registerMessagingInWindow() {
(0,_firebase_app__WEBPACK_IMPORTED_MODULE_4__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('messaging', WindowMessagingFactory, "PUBLIC" /* PUBLIC */)); (0,_firebase_app__WEBPACK_IMPORTED_MODULE_3__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('messaging', WindowMessagingFactory, "PUBLIC" /* PUBLIC */));
(0,_firebase_app__WEBPACK_IMPORTED_MODULE_4__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('messaging-internal', WindowMessagingInternalFactory, "PRIVATE" /* PRIVATE */)); (0,_firebase_app__WEBPACK_IMPORTED_MODULE_3__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('messaging-internal', WindowMessagingInternalFactory, "PRIVATE" /* PRIVATE */));
(0,_firebase_app__WEBPACK_IMPORTED_MODULE_4__.registerVersion)(name, version); (0,_firebase_app__WEBPACK_IMPORTED_MODULE_3__.registerVersion)(name, version);
// BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
(0,_firebase_app__WEBPACK_IMPORTED_MODULE_4__.registerVersion)(name, version, 'esm2017'); (0,_firebase_app__WEBPACK_IMPORTED_MODULE_3__.registerVersion)(name, version, 'esm2017');
} }
/** /**
@@ -21808,7 +21976,7 @@ async function isWindowSupported() {
try { try {
// This throws if open() is unsupported, so adding it to the conditional // This throws if open() is unsupported, so adding it to the conditional
// statement below can cause an uncaught error. // statement below can cause an uncaught error.
await (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateIndexedDBOpenable)(); await (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.validateIndexedDBOpenable)();
} }
catch (e) { catch (e) {
return false; return false;
@@ -21817,8 +21985,8 @@ async function isWindowSupported() {
// might be prohibited to run. In these contexts, an error would be thrown during the messaging // might be prohibited to run. In these contexts, an error would be thrown during the messaging
// instantiating phase, informing the developers to import/call isSupported for special handling. // instantiating phase, informing the developers to import/call isSupported for special handling.
return (typeof window !== 'undefined' && return (typeof window !== 'undefined' &&
(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isIndexedDBAvailable)() && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.isIndexedDBAvailable)() &&
(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.areCookiesEnabled)() && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.areCookiesEnabled)() &&
'serviceWorker' in navigator && 'serviceWorker' in navigator &&
'PushManager' in window && 'PushManager' in window &&
'Notification' in window && 'Notification' in window &&
@@ -21902,7 +22070,7 @@ function onMessage$1(messaging, nextOrObserver) {
* *
* @public * @public
*/ */
function getMessagingInWindow(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_4__.getApp)()) { function getMessagingInWindow(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_3__.getApp)()) {
// Conscious decision to make this async check non-blocking during the messaging instance // Conscious decision to make this async check non-blocking during the messaging instance
// initialization phase for performance consideration. An error would be thrown latter for // initialization phase for performance consideration. An error would be thrown latter for
// developer's information. Developers can then choose to import and call `isSupported` for // developer's information. Developers can then choose to import and call `isSupported` for
@@ -21916,7 +22084,7 @@ function getMessagingInWindow(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_4_
// If `isWindowSupported()` rejected. // If `isWindowSupported()` rejected.
throw ERROR_FACTORY.create("indexed-db-unsupported" /* INDEXED_DB_UNSUPPORTED */); throw ERROR_FACTORY.create("indexed-db-unsupported" /* INDEXED_DB_UNSUPPORTED */);
}); });
return (0,_firebase_app__WEBPACK_IMPORTED_MODULE_4__._getProvider)((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(app), 'messaging').getImmediate(); return (0,_firebase_app__WEBPACK_IMPORTED_MODULE_3__._getProvider)((0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(app), 'messaging').getImmediate();
} }
/** /**
* Subscribes the {@link Messaging} instance to push notifications. Returns an Firebase Cloud * Subscribes the {@link Messaging} instance to push notifications. Returns an Firebase Cloud
@@ -21934,7 +22102,7 @@ function getMessagingInWindow(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_4_
* @public * @public
*/ */
async function getToken(messaging, options) { async function getToken(messaging, options) {
messaging = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(messaging); messaging = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(messaging);
return getToken$1(messaging, options); return getToken$1(messaging, options);
} }
/** /**
@@ -21948,7 +22116,7 @@ async function getToken(messaging, options) {
* @public * @public
*/ */
function deleteToken(messaging) { function deleteToken(messaging) {
messaging = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(messaging); messaging = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(messaging);
return deleteToken$1(messaging); return deleteToken$1(messaging);
} }
/** /**
@@ -21965,7 +22133,7 @@ function deleteToken(messaging) {
* @public * @public
*/ */
function onMessage(messaging, nextOrObserver) { function onMessage(messaging, nextOrObserver) {
messaging = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(messaging); messaging = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(messaging);
return onMessage$1(messaging, nextOrObserver); return onMessage$1(messaging, nextOrObserver);
} }
@@ -21980,317 +22148,6 @@ registerMessagingInWindow();
//# sourceMappingURL=index.esm2017.js.map //# sourceMappingURL=index.esm2017.js.map
/***/ }),
/***/ "./node_modules/idb/build/index.js":
/*!*****************************************!*\
!*** ./node_modules/idb/build/index.js ***!
\*****************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "deleteDB": () => (/* binding */ deleteDB),
/* harmony export */ "openDB": () => (/* binding */ openDB),
/* harmony export */ "unwrap": () => (/* reexport safe */ _wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.u),
/* harmony export */ "wrap": () => (/* reexport safe */ _wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w)
/* harmony export */ });
/* harmony import */ var _wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./wrap-idb-value.js */ "./node_modules/idb/build/wrap-idb-value.js");
/**
* Open a database.
*
* @param name Name of the database.
* @param version Schema version.
* @param callbacks Additional callbacks.
*/
function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
const request = indexedDB.open(name, version);
const openPromise = (0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w)(request);
if (upgrade) {
request.addEventListener('upgradeneeded', (event) => {
upgrade((0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w)(request.result), event.oldVersion, event.newVersion, (0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w)(request.transaction));
});
}
if (blocked)
request.addEventListener('blocked', () => blocked());
openPromise
.then((db) => {
if (terminated)
db.addEventListener('close', () => terminated());
if (blocking)
db.addEventListener('versionchange', () => blocking());
})
.catch(() => { });
return openPromise;
}
/**
* Delete a database.
*
* @param name Name of the database.
*/
function deleteDB(name, { blocked } = {}) {
const request = indexedDB.deleteDatabase(name);
if (blocked)
request.addEventListener('blocked', () => blocked());
return (0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w)(request).then(() => undefined);
}
const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
const writeMethods = ['put', 'add', 'delete', 'clear'];
const cachedMethods = new Map();
function getMethod(target, prop) {
if (!(target instanceof IDBDatabase &&
!(prop in target) &&
typeof prop === 'string')) {
return;
}
if (cachedMethods.get(prop))
return cachedMethods.get(prop);
const targetFuncName = prop.replace(/FromIndex$/, '');
const useIndex = prop !== targetFuncName;
const isWrite = writeMethods.includes(targetFuncName);
if (
// Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
!(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
!(isWrite || readMethods.includes(targetFuncName))) {
return;
}
const method = async function (storeName, ...args) {
// isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
let target = tx.store;
if (useIndex)
target = target.index(args.shift());
// Must reject if op rejects.
// If it's a write operation, must reject if tx.done rejects.
// Must reject with op rejection first.
// Must resolve with op value.
// Must handle both promises (no unhandled rejections)
return (await Promise.all([
target[targetFuncName](...args),
isWrite && tx.done,
]))[0];
};
cachedMethods.set(prop, method);
return method;
}
(0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.r)((oldTraps) => ({
...oldTraps,
get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
}));
/***/ }),
/***/ "./node_modules/idb/build/wrap-idb-value.js":
/*!**************************************************!*\
!*** ./node_modules/idb/build/wrap-idb-value.js ***!
\**************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "a": () => (/* binding */ reverseTransformCache),
/* harmony export */ "i": () => (/* binding */ instanceOfAny),
/* harmony export */ "r": () => (/* binding */ replaceTraps),
/* harmony export */ "u": () => (/* binding */ unwrap),
/* harmony export */ "w": () => (/* binding */ wrap)
/* harmony export */ });
const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
let idbProxyableTypes;
let cursorAdvanceMethods;
// This is a function to prevent it throwing up in node environments.
function getIdbProxyableTypes() {
return (idbProxyableTypes ||
(idbProxyableTypes = [
IDBDatabase,
IDBObjectStore,
IDBIndex,
IDBCursor,
IDBTransaction,
]));
}
// This is a function to prevent it throwing up in node environments.
function getCursorAdvanceMethods() {
return (cursorAdvanceMethods ||
(cursorAdvanceMethods = [
IDBCursor.prototype.advance,
IDBCursor.prototype.continue,
IDBCursor.prototype.continuePrimaryKey,
]));
}
const cursorRequestMap = new WeakMap();
const transactionDoneMap = new WeakMap();
const transactionStoreNamesMap = new WeakMap();
const transformCache = new WeakMap();
const reverseTransformCache = new WeakMap();
function promisifyRequest(request) {
const promise = new Promise((resolve, reject) => {
const unlisten = () => {
request.removeEventListener('success', success);
request.removeEventListener('error', error);
};
const success = () => {
resolve(wrap(request.result));
unlisten();
};
const error = () => {
reject(request.error);
unlisten();
};
request.addEventListener('success', success);
request.addEventListener('error', error);
});
promise
.then((value) => {
// Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
// (see wrapFunction).
if (value instanceof IDBCursor) {
cursorRequestMap.set(value, request);
}
// Catching to avoid "Uncaught Promise exceptions"
})
.catch(() => { });
// This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
// is because we create many promises from a single IDBRequest.
reverseTransformCache.set(promise, request);
return promise;
}
function cacheDonePromiseForTransaction(tx) {
// Early bail if we've already created a done promise for this transaction.
if (transactionDoneMap.has(tx))
return;
const done = new Promise((resolve, reject) => {
const unlisten = () => {
tx.removeEventListener('complete', complete);
tx.removeEventListener('error', error);
tx.removeEventListener('abort', error);
};
const complete = () => {
resolve();
unlisten();
};
const error = () => {
reject(tx.error || new DOMException('AbortError', 'AbortError'));
unlisten();
};
tx.addEventListener('complete', complete);
tx.addEventListener('error', error);
tx.addEventListener('abort', error);
});
// Cache it for later retrieval.
transactionDoneMap.set(tx, done);
}
let idbProxyTraps = {
get(target, prop, receiver) {
if (target instanceof IDBTransaction) {
// Special handling for transaction.done.
if (prop === 'done')
return transactionDoneMap.get(target);
// Polyfill for objectStoreNames because of Edge.
if (prop === 'objectStoreNames') {
return target.objectStoreNames || transactionStoreNamesMap.get(target);
}
// Make tx.store return the only store in the transaction, or undefined if there are many.
if (prop === 'store') {
return receiver.objectStoreNames[1]
? undefined
: receiver.objectStore(receiver.objectStoreNames[0]);
}
}
// Else transform whatever we get back.
return wrap(target[prop]);
},
set(target, prop, value) {
target[prop] = value;
return true;
},
has(target, prop) {
if (target instanceof IDBTransaction &&
(prop === 'done' || prop === 'store')) {
return true;
}
return prop in target;
},
};
function replaceTraps(callback) {
idbProxyTraps = callback(idbProxyTraps);
}
function wrapFunction(func) {
// Due to expected object equality (which is enforced by the caching in `wrap`), we
// only create one new func per func.
// Edge doesn't support objectStoreNames (booo), so we polyfill it here.
if (func === IDBDatabase.prototype.transaction &&
!('objectStoreNames' in IDBTransaction.prototype)) {
return function (storeNames, ...args) {
const tx = func.call(unwrap(this), storeNames, ...args);
transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
return wrap(tx);
};
}
// Cursor methods are special, as the behaviour is a little more different to standard IDB. In
// IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
// cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
// with real promises, so each advance methods returns a new promise for the cursor object, or
// undefined if the end of the cursor has been reached.
if (getCursorAdvanceMethods().includes(func)) {
return function (...args) {
// Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
// the original object.
func.apply(unwrap(this), args);
return wrap(cursorRequestMap.get(this));
};
}
return function (...args) {
// Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
// the original object.
return wrap(func.apply(unwrap(this), args));
};
}
function transformCachableValue(value) {
if (typeof value === 'function')
return wrapFunction(value);
// This doesn't return, it just creates a 'done' promise for the transaction,
// which is later returned for transaction.done (see idbObjectHandler).
if (value instanceof IDBTransaction)
cacheDonePromiseForTransaction(value);
if (instanceOfAny(value, getIdbProxyableTypes()))
return new Proxy(value, idbProxyTraps);
// Return the same value back if we're not going to transform it.
return value;
}
function wrap(value) {
// We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
// IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
if (value instanceof IDBRequest)
return promisifyRequest(value);
// If we've already transformed this value before, reuse the transformed value.
// This is faster, but it also provides object equality.
if (transformCache.has(value))
return transformCache.get(value);
const newValue = transformCachableValue(value);
// Not all types are transformed.
// These may be primitive types, so they can't be WeakMap keys.
if (newValue !== value) {
transformCache.set(value, newValue);
reverseTransformCache.set(newValue, value);
}
return newValue;
}
const unwrap = (value) => reverseTransformCache.get(value);
/***/ }), /***/ }),
/***/ "./src/messages.json": /***/ "./src/messages.json":
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long