UNPKG

phaser4-rex-plugins

Version:
1,660 lines (1,414 loc) 148 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.rexfirebase = factory()); })(this, (function () { 'use strict'; const VERSION = '10.13'; var GetDefaultUrl = function (version) { if (version === undefined) { version = VERSION; } return { app: `https://www.gstatic.com/firebasejs/${version}/firebase-app-compat.js`, // auth: `https://www.gstatic.com/firebasejs/${version}/firebase-auth-compat.js`, database: `https://www.gstatic.com/firebasejs/${version}/firebase-database-compat.js`, firestore: `https://www.gstatic.com/firebasejs/${version}/firebase-firestore-compat.js`, // storage: `https://www.gstatic.com/firebasejs/${version}/firebase-storage-compat.js`, // analytics: `https://www.gstatic.com/firebasejs/${version}/firebase-analytics-compat.js`, // functions: `https://www.gstatic.com/firebasejs${version}/firebase-functions-compat.js`, // messaging: `https://www.gstatic.com/firebasejs/${version}/firebase-messaging-compat.js`, // performance: `https://www.gstatic.com/firebasejs/${version}/firebase-performance-compat.js`, // 'remote-config': `https://www.gstatic.com/firebasejs/${version}/firebase-remote-config-compat.js` } }; var Clear$1 = function (obj) { if ((typeof (obj) !== 'object') || (obj === null)) { return obj; } if (Array.isArray(obj)) { obj.length = 0; } else { for (var key in obj) { delete obj[key]; } } return obj; }; /** * Shallow Object Clone. Will not out nested objects. * @param {object} obj JSON object * @param {object} ret JSON object to return, set null to return a new object * @returns {object} this object */ var Clone = function (obj, out) { var objIsArray = Array.isArray(obj); if (out === undefined) { out = (objIsArray) ? [] : {}; } else { Clear$1(out); } if (objIsArray) { out.length = obj.length; for (var i = 0, cnt = obj.length; i < cnt; i++) { out[i] = obj[i]; } } else { for (var key in obj) { out[key] = obj[key]; } } return out; }; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2019 Photon Storm Ltd. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ /** * Creates a new Object using all values from obj1. * * Then scans obj2. If a property is found in obj2 that *also* exists in obj1, the value from obj2 is used, otherwise the property is skipped. * * @function Phaser.Utils.Objects.MergeRight * @since 3.0.0 * * @param {object} obj1 - The first object to merge. * @param {object} obj2 - The second object to merge. Keys from this object which also exist in `obj1` will be copied to `obj1`. * * @return {object} The merged object. `obj1` and `obj2` are not modified. */ var MergeRight = function (obj1, obj2) { var clone = Clone(obj1); for (var key in obj2) { if (clone.hasOwnProperty(key)) { clone[key] = obj2[key]; } } return clone; }; var LoadScript = function (url, onload) { var scripts = document.getElementsByTagName('script'); for (var i = 0, cnt = scripts.length; i < cnt; i++) { if (scripts[i].src.indexOf(url) != -1) { if (onload) { onload(); } return; } } var newScriptTag = document.createElement('script'); newScriptTag.setAttribute('src', url); if (onload) { newScriptTag.onload = onload; } document.head.appendChild(newScriptTag); }; var LoadScriptPromise = function (url) { return new Promise(function (resolve, reject) { LoadScript(url, resolve); }); }; var Delay = function (time, result) { if (time === undefined) { time = 0; } return new Promise(function (resolve, reject) { setTimeout(function () { resolve(result); }, time); }); }; var AvailableTestPromise = function (config) { if (AvailableTest(config)) { return Promise.resolve(); } // console.log('test again') return Delay(10) .then(function () { return AvailableTestPromise(config); }); }; var AvailableTest = function (config) { var testCallback; for (var k in config) { if (!config[k]) { continue; } testCallback = TestCallbacks[k]; if (testCallback && !testCallback()) { return false; } } return true; }; var TestCallbacks = { database: function () { return (firebase.database !== undefined); }, firestore: function () { return (firebase.firestore !== undefined); } }; var Preload = function (urlConfig, firebaseConfig) { if (typeof (urlConfig) === 'string') { // Get specific version urlConfig = GetDefaultUrl(urlConfig); } else { // Get default version urlConfig = MergeRight(GetDefaultUrl(), urlConfig); } return LoadScriptPromise(urlConfig.app) // Load firebase-app .then(function () { // Load other SDK var promises = []; var url; for (var k in urlConfig) { if (k === 'app') { continue; } url = urlConfig[k]; if (!url) { continue; } promises.push(LoadScriptPromise(url)); } if (promises.length === 0) { return Promise.resolve(); } else { return Promise.all(promises); } }) .then(function () { // Wait until all vairalbe are available return AvailableTestPromise(urlConfig); }) .then(function () { if (firebaseConfig !== undefined) { firebase.initializeApp(firebaseConfig); } return Promise.resolve(); }) }; class ObjectFactory { constructor() { } initializeApp(config) { firebase.initializeApp(config); return this; } static register(type, callback) { ObjectFactory.prototype[type] = callback; } } var EventEmitterMethods = { setEventEmitter(eventEmitter, EventEmitterClass) { if (EventEmitterClass === undefined) { EventEmitterClass = Phaser.Events.EventEmitter; // Use built-in EventEmitter class by default } this._privateEE = (eventEmitter === true) || (eventEmitter === undefined); this._eventEmitter = (this._privateEE) ? (new EventEmitterClass()) : eventEmitter; return this; }, destroyEventEmitter() { if (this._eventEmitter && this._privateEE) { this._eventEmitter.shutdown(); } return this; }, getEventEmitter() { return this._eventEmitter; }, on() { if (this._eventEmitter) { this._eventEmitter.on.apply(this._eventEmitter, arguments); } return this; }, once() { if (this._eventEmitter) { this._eventEmitter.once.apply(this._eventEmitter, arguments); } return this; }, off() { if (this._eventEmitter) { this._eventEmitter.off.apply(this._eventEmitter, arguments); } return this; }, emit(event) { if (this._eventEmitter && event) { this._eventEmitter.emit.apply(this._eventEmitter, arguments); } return this; }, addListener() { if (this._eventEmitter) { this._eventEmitter.addListener.apply(this._eventEmitter, arguments); } return this; }, removeListener() { if (this._eventEmitter) { this._eventEmitter.removeListener.apply(this._eventEmitter, arguments); } return this; }, removeAllListeners() { if (this._eventEmitter) { this._eventEmitter.removeAllListeners.apply(this._eventEmitter, arguments); } return this; }, listenerCount() { if (this._eventEmitter) { return this._eventEmitter.listenerCount.apply(this._eventEmitter, arguments); } return 0; }, listeners() { if (this._eventEmitter) { return this._eventEmitter.listeners.apply(this._eventEmitter, arguments); } return []; }, eventNames() { if (this._eventEmitter) { return this._eventEmitter.eventNames.apply(this._eventEmitter, arguments); } return []; }, }; var GetValue = function (source, key, defaultValue) { if (!source || typeof source === 'number') { return defaultValue; } if (typeof (key) === 'string') { if (source.hasOwnProperty(key)) { return source[key]; } if (key.indexOf('.') !== -1) { key = key.split('.'); } else { return defaultValue; } } var keys = key; var parent = source; var value = defaultValue; // Use for loop here so we can break early for (var i = 0; i < keys.length; i++) { key = keys[i]; if (parent.hasOwnProperty(key)) { // Yes it has a key property, let's carry on down value = parent[key]; parent = value; } else { // Can't go any further, so reset to default value = defaultValue; break; } } return value; }; var IsPlainObject = function (obj) { // Not plain objects: // - Any object or value whose internal [[Class]] property is not "[object Object]" // - DOM nodes // - window if (typeof(obj) !== 'object' || obj.nodeType || obj === obj.window) { return false; } // Support: Firefox <20 // The try/catch suppresses exceptions thrown when attempting to access // the "constructor" property of certain host objects, ie. |window.location| // https://bugzilla.mozilla.org/show_bug.cgi?id=814622 try { if (obj.constructor && !({}).hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) { return false; } } catch (e) { return false; } // If the function hasn't returned already, we're confident that // |obj| is a plain object, created by {} or constructed with new Object return true; }; var Send$1 = function (message) { if ((!this.sendToRef) || (this.sendToRef.key !== this.receiverID)) { this.sendToRef = this.database.ref(this.rootPath).child(this.receiverID); } // Clear message if (message === undefined) { return this.sendToRef.remove(); // Promise } var d = { message: message, senderID: this.userID, stamp: this.stamp, }; if (this.userName !== undefined) { d.senderName = this.userName; } this.skipFirst = false; this.stamp = !this.stamp; return this.sendToRef.set(d); }; var methods$8 = { startReceiving() { if (this.isReceiving && (this.receiverRef.key === this.receiverID)) { return this; } this.stopReceiving(); this.isReceiving = true; this.skipFirst = true; // Skip previous message this.receiverRef = this.database.ref(this.rootPath).child(this.receiverID); this.receiverRef.on('value', OnReceive, this); this.receiverRef.onDisconnect().remove(); return this; }, stopReceiving() { if (!this.isReceiving) { return this; } this.isReceiving = false; this.receiverRef.off('value', OnReceive, this); this.receiverRef.remove(); this.receiverRef.onDisconnect().cancel(); return this; } }; var OnReceive = function (snapshot) { if (this.skipFirst) { this.skipFirst = false; return; } var d = snapshot.val(); if (d == null) { return; } delete d.stamp; this.history.add(d); this.emit(this.eventNameMap.receive, d); }; class History { constructor(config) { this.maxLength = GetValue(config, 'maxLength', -1); // -1: Infinity this.records = []; } add(record) { if (this.maxLength === 0) { return this; } this.records.push(record); if ((this.maxLength > 0) && (this.records.length > this.maxLength)) { this.records.shift(); } return this; } clear() { this.records.length = 0; return this; } changeUserName(userID, userName) { if (this.maxLength === 0) { return this; } this.records.forEach(function (record) { if (record.senderID === userID) { record.senderName = userName; } }); return this; } } class Broadcast { constructor(config) { // Event emitter var eventEmitter = GetValue(config, 'eventEmitter', undefined); var EventEmitterClass = GetValue(config, 'EventEmitterClass', undefined); this.setEventEmitter(eventEmitter, EventEmitterClass); this.eventNameMap = GetValue(config, 'eventNames', DefaultEventNames$2); this.database = firebase.database(); this.setRootPath(GetValue(config, 'root', '')); // Sender this.skipFirst = true; this.stamp = false; this.userInfo = { userID: '', userName: undefined }; this.setSender(GetValue(config, 'senderID', ''), GetValue(config, 'senderName', '')); this.setReceiver(GetValue(config, 'receiverID', '')); // Receiver this.isReceiving = false; // History messages var historyMaxLength = GetValue(config, 'history', 0); if (historyMaxLength === true) { historyMaxLength = -1; } else if (historyMaxLength === false) { historyMaxLength = 0; } this.history = new History({ maxLength: historyMaxLength }); } shutdown() { this .stopReceiving() .destroyEventEmitter(); } destroy() { this.shutdown(); } get userID() { return this.userInfo.userID; } set userID(value) { this.userInfo.userID = value; } get userName() { return this.userInfo.userName; } set userName(value) { this.userInfo.userName = value; } setRootPath(rootPath) { this.rootPath = rootPath; this.sendToRef = undefined; this.receiverRef = undefined; return this; } setSender(userID, userName) { if (IsPlainObject(userID)) { this.userInfo = userID; } else { this.userID = userID; this.userName = userName; } return this; } setReceiver(receiverID) { this.receiverID = receiverID; return this; } changeUserName(userID, userName) { if (userID === this.userID) { this.userName = userName; } this.history.changeUserName(userID, userName); return this; } getHistory() { return this.history.records; } clearHistory() { this.history.clear(); return this; } } var methods$7 = { send: Send$1 }; Object.assign( Broadcast.prototype, EventEmitterMethods, methods$8, methods$7 ); const DefaultEventNames$2 = { receive: 'receive' }; var IsInValidKey = function (keys) { return (keys == null) || (keys === '') || (keys.length === 0); }; var GetEntry$1 = function (target, keys, defaultEntry) { var entry = target; if (IsInValidKey(keys)) ; else { if (typeof (keys) === 'string') { keys = keys.split('.'); } var key; for (var i = 0, cnt = keys.length; i < cnt; i++) { key = keys[i]; if ((entry[key] == null) || (typeof (entry[key]) !== 'object')) { var newEntry; if (i === cnt - 1) { if (defaultEntry === undefined) { newEntry = {}; } else { newEntry = defaultEntry; } } else { newEntry = {}; } entry[key] = newEntry; } entry = entry[key]; } } return entry; }; var SetValue = function (target, keys, value, delimiter) { if (delimiter === undefined) { delimiter = '.'; } // no object if (typeof (target) !== 'object') { return; } // invalid key else if (IsInValidKey(keys)) { // don't erase target if (value == null) { return; } // set target to another object else if (typeof (value) === 'object') { target = value; } } else { if (typeof (keys) === 'string') { keys = keys.split(delimiter); } var lastKey = keys.pop(); var entry = GetEntry$1(target, keys); entry[lastKey] = value; } return target; }; ObjectFactory.register('broadcast', function (config) { return new Broadcast(config); }); SetValue(window, 'RexPlugins.Fire.Broadcast', Broadcast); var Methods$9 = { clear() { this.items.length = 0; Clear$1(this.itemID2Index); return this; }, getItems() { return this.items; }, hasItem(itemID) { return this.itemID2Index.hasOwnProperty(itemID); }, getItemIndexFromItemID(itemID) { if (itemID == null) { return null; } return this.itemID2Index[itemID]; }, getItemFromItemID(itemID) { if (itemID == null) { return null; } var index = this.getItemIndexFromItemID(itemID); if (index == null) { return null; } return this.items[index]; }, forEach(callback, scope) { this.items.forEach(callback, scope); return this; }, updateItemID2Index() { Clear$1(this.itemID2Index); var itemID; for (var i = 0, cnt = this.items.length; i < cnt; i++) { itemID = this.items[i][this.keyItemID]; this.itemID2Index[itemID] = i; } return this; } }; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2018 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ /** * Removes a single item from an array and returns it without creating gc, like the native splice does. * Based on code by Mike Reinstein. * * @function Phaser.Utils.Array.SpliceOne * @since 3.0.0 * * @param {array} array - The array to splice from. * @param {integer} index - The index of the item which should be spliced. * * @return {*} The item which was spliced (removed). */ var SpliceOne = function (array, index) { if (index >= array.length) { return; } var len = array.length - 1; var item = array[index]; for (var i = index; i < len; i++) { array[i] = array[i + 1]; } array.length = len; return item; }; var AddChildCallback = function (snapshot, prevName) { var item = AddItem.call(this, snapshot, prevName); this.updateItemID2Index(); this.emit(this.eventNameMap.add, item); this.emit(this.eventNameMap.update, this.items); }; var ChangeChildCallback = function (snapshot, prevName) { var prevItem = RemoveItem.call(this, snapshot); this.updateItemID2Index(); var newItem = AddItem.call(this, snapshot, prevName); this.updateItemID2Index(); this.emit(this.eventNameMap.change, newItem, prevItem); this.emit(this.eventNameMap.update, this.items); }; var RemoveChildCallback = function (snapshot) { var item = RemoveItem.call(this, snapshot); this.updateItemID2Index(); this.emit(this.eventNameMap.remove, item); this.emit(this.eventNameMap.update, this.items); }; var GetAllChildrenCallback = function (snapshot) { this.clear(); snapshot.forEach((function (childSnapshot) { AddItem.call(this, childSnapshot, null, true); }).bind(this)); this.updateItemID2Index(); this.emit(this.eventNameMap.update, this.items); }; var AddItem = function(snapshot, prevName, pushMode) { var item; var callback = this.getItemCallback; var scope = this.getItemCallbackScope; if (scope) { item = callback.call(scope, snapshot); } else { item = callback(snapshot); } if (pushMode) { this.items.push(item); return item; } if (prevName == null) { this.items.unshift(item); } else { var i = this.itemID2Index[prevName]; if (i === this.items.length - 1) { this.items.push(item); } else { this.items.splice(i + 1, 0, item); } } return item; }; var RemoveItem = function (snapshot) { var index = this.itemID2Index[snapshot.key]; var item = SpliceOne(this.items, index); return item }; var Updater$2 = { start(query) { this.isUpdating = false; query.once('value', GetAllChildrenCallback, this); return this; }, stop() { // Do nothing return this; } }; var Updater$1 = { start(query) { query.on('child_added', AddChildCallback, this); query.on('child_removed', RemoveChildCallback, this); query.on('child_moved', ChangeChildCallback, this); query.on('child_changed', ChangeChildCallback, this); return this; }, stop() { this.query.off('child_added', AddChildCallback, this); this.query.off('child_removed', RemoveChildCallback, this); this.query.off('child_moved', ChangeChildCallback, this); this.query.off('child_changed', ChangeChildCallback, this); return this; }, }; var Updater = { start(query) { query.on('value', GetAllChildrenCallback, this); return this; }, stop() { this.query.off('value', GetAllChildrenCallback, this); return this; } }; class ItemList { constructor(config) { // Event emitter var eventEmitter = GetValue(config, 'eventEmitter', undefined); var EventEmitterClass = GetValue(config, 'EventEmitterClass', undefined); this.setEventEmitter(eventEmitter, EventEmitterClass); this.eventNameMap = GetValue(config, 'eventNames', DefaultEventNames$1); this.isUpdating = false; this.items = []; this.itemID2Index = {}; this.setItemIDKey(GetValue(config, 'itemIDKey', '__itemID__')); this.setMode(GetValue(config, 'mode', 1)); this.setGetitemCallback(GetValue(config, 'getItemCallback', DefaultGetItemCallback), GetValue(config, 'getItemCallbackScope', this)); this.setQuery(GetValue(config, 'query', undefined)); } shutdown() { this .stopUpdate() .clear(); } destroy() { this.shutdown(); } setItemIDKey(key) { this.keyItemID = key; return this; } setMode(mode) { if (typeof (mode) === 'string') { mode = MODE[mode]; } this.mode = mode; this.updater = Updaters[mode]; return this; } setGetitemCallback(callback, scope) { this.getItemCallback = callback; this.getItemCallbackScope = scope; return this; } setQuery(query) { this.query = query; return this; } startUpdate(query) { if (query) { this.setQuery(query); } else if (this.query) { query = this.query; } else { // !query && !this.query return this; } this .stopUpdate() .clear(); this.isUpdating = true; this.updater.start.call(this, query); return this; } stopUpdate() { if ((!this.query) || (!this.isUpdating)) { return this; } this.isUpdating = false; this.updater.stop.call(this); return this; } } var DefaultGetItemCallback = function (snapshot) { var item = snapshot.val(); item[this.keyItemID] = snapshot.key; return item; }; Object.assign( ItemList.prototype, EventEmitterMethods, Methods$9 ); const DefaultEventNames$1 = { update: 'update', add: 'add', remove: 'remove', change: 'change' }; const Updaters = { 0: Updater$2, 1: Updater$1, 2: Updater }; const MODE = { once: 0, child: 1, all: 2 }; var Join = function (userID, userName) { if (userID === undefined) { userID = this.userID; userName = this.userName; } if (this.contains(userID)) { return Promise.resolve(); // Promise } // Prepare data var d = { userID: userID, userName: userName }; var maxUsers = this.maxUsers; var rootRef = this.database.ref(this.rootPath); var userRef = rootRef.push(); return userRef.onDisconnect().remove() .then(function () { return userRef.set(d) }) .then(function () { return Delay(0); }) .then(function () { // No user count limitation if (maxUsers === 0) { self.isInList = true; return Promise.resolve(); } // Has user count limitation return rootRef.limitToFirst(maxUsers).once('value') .then(function (snapshot) { if (Contains(snapshot, userID)) { self.isInList = true; return Promise.resolve(); } self.isInList = false; // UserID is not in firstN list return userRef.remove() .then(function () { return userRef.onDisconnect().cancel() }) .then(function () { return Promise.reject() }) }); }) }; var Contains = function (snapshot, userID) { var result = false; snapshot.forEach(function (childSnapshot) { var user = childSnapshot.val(); if (user.userID === userID) { result = true; return true; } }); return result; }; var Leave = function (userID) { if (userID === undefined) { userID = this.userID; } if (!this.contains(userID)) { return Promise.resolve(); // Promise } var itemID = this.userID2ItemID[userID]; var userRef = this.database.ref(this.rootPath).child(itemID); return userRef.remove(); // Promise }; var ChangeUserName$2 = function (userName) { var self = this; return new Promise(function (resolve, reject) { var userRef = self.getUserRef(); if (userRef) { // Find userRef resolve(userRef); } else { // Query userRef var query = self.rootRef.orderByChild('userID').equalTo(self.userID); query.once('child_added') .then(function (snapshot) { resolve(snapshot.ref); }); } }) .then(function (userRef) { // Set userName return userRef.child('userName').set(userName) }) .then(function () { self.userName = userName; return Promise.resolve(); }) }; class OnlineUserList { constructor(config) { // Event emitter var eventEmitter = GetValue(config, 'eventEmitter', undefined); var EventEmitterClass = GetValue(config, 'EventEmitterClass', undefined); this.setEventEmitter(eventEmitter, EventEmitterClass); this.database = firebase.database(); this.setRootPath(GetValue(config, 'root', '')); this.userInfo = { userID: '', userName: '' }; this.setUser(GetValue(config, 'userID', ''), GetValue(config, 'userName', '')); this.setMaxUsers(GetValue(config, 'maxUsers', 0)); this.userList = new ItemList({ eventEmitter: this.getEventEmitter(), itemIDKey: 'joinAt', eventNames: { add: GetValue(config, 'eventNames.join', 'join'), remove: GetValue(config, 'eventNames.leave', 'leave'), update: GetValue(config, 'eventNames.update', 'update'), change: GetValue(config, 'eventNames.change', 'change'), init: GetValue(config, 'eventNames.init', 'init'), changename: GetValue(config, 'eventNames.changename', 'changename') } }); this.isInList = false; this.userID2ItemID = {}; this.userList .on(this.userList.eventNames.add, function (user) { this.userID2ItemID[user.userID] = user.joinAt; if (user.userID === this.userInfo.userID) { this.emit(this.userList.eventNames.init, this.getUsers()); } }, this) .on(this.userList.eventNames.remove, function (user) { delete this.userID2ItemID[user.userID]; if (user.userID === this.userID) { this.isInList = false; } }, this) .on(this.userList.eventNames.change, function (currUserInfo, prevUserInfo) { var userID = currUserInfo.userID, userName = currUserInfo.userName, prevUserName = prevUserInfo.userName; if (userName !== prevUserName) { this.emit(this.userList.eventNames.changename, userID, userName, prevUserName); } }, this); } shutdown() { this .stopUpdate() .destroyEventEmitter() .leave(); this.userList.shutdown(); } destroy() { this.shutdown(); } get userID() { return this.userInfo.userID; } set userID(value) { this.userInfo.userID = value; } get userName() { return this.userInfo.userName; } set userName(value) { this.userInfo.userName = value; } setRootPath(rootPath) { this.rootPath = rootPath; return this; } get rootRef() { return this.database.ref(this.rootPath); } setUser(userID, userName) { if (IsPlainObject(userID)) { this.userInfo = userID; } else { this.userID = userID; this.userName = userName; } return this; } setMaxUsers(maxUsers) { this.maxUsers = maxUsers; return this; } clear() { this.userList.clear(); return this; } forEach(callback, scope) { this.userList.forEach(callback, scope); return this; } isFull() { if (this.maxUsers === 0) { return false; } return (this.userList.getItems().length >= this.maxUsers); } isFirstUser(userID) { if (userID === undefined) { userID = this.userID; } var user = this.usersList.getItems()[0]; return (user && (user.userID === userID)); } getUser(userID) { if (userID === undefined) { userID = this.userID; } if (!this.contains(userID)) { return null; } var itemID = this.userID2ItemID[userID]; return this.userList.getItemFromItemID(itemID); } getUsers() { return this.userList.getItems(); } get rootRef() { return this.database.ref(this.rootPath); } getUserRef(userID) { if (userID === undefined) { userID = this.userID; } if (!this.contains(userID)) { return null; } var itemID = this.userID2ItemID[userID]; return this.rootRef.child(itemID); } contains(userID) { if (userID === undefined) { userID = this.userID; } return this.userID2ItemID.hasOwnProperty(userID); } startUpdate() { var query = this.database.ref(this.rootPath); if (this.maxUsers > 0) { query = query.limitToFirst(this.maxUsers); } this.userList.startUpdate(query); return this; } stopUpdate() { this.userList.stopUpdate(); return this; } } var methods$6 = { join: Join, leave: Leave, changeUserName: ChangeUserName$2 }; Object.assign( OnlineUserList.prototype, EventEmitterMethods, methods$6 ); ObjectFactory.register('onlineUserList', function (config) { return new OnlineUserList(config); }); SetValue(window, 'RexPlugins.Fire.OnlineUserList', OnlineUserList); var CreateUserList$1 = function (config) { var userList = new OnlineUserList({ eventEmitter: this.getEventEmitter(), eventNames: { join: 'userlist.join', // Any user join leave: 'userlist.leave', // Any user leave update: 'userlist.update', // Update user list change: 'userlist.change', // Any user(name) change init: 'userlist.init', changename: 'userlist.changename' }, userID: this.userInfo }); userList .on('userlist.leave', function (user) { if (user.userID === this.userID) { OnLeftRoom$1.call(this); // Current user is left or kicked } }, this); this .on('room.join', function () { userList .startUpdate(); }) .on('room.leave', function () { userList .stopUpdate() .clear(); }); return userList; }; var OnLeftRoom$1 = function () { this.emit('room.leave'); // Clear room info later var self = this; setTimeout(function () { self.roomID = undefined; self.roomName = undefined; self.doorState = undefined; self.leftRoomFlag = false; }, 0); }; var CreateRoomList = function (config) { var roomList = new ItemList({ eventEmitter: this.getEventEmitter(), root: this.getRoomFilterRef(), itemIDKey: 'roomID', eventNames: { update: 'roomlist.update', add: 'roomlist.add', remove: 'roomlist.remove', change: 'roomlist.change' }, mode: 'once' }); return roomList; }; var CreateBroadcast$1 = function (config) { var broadcastConfig = GetValue(config, 'broadcast', true); if (!broadcastConfig) { return null; } var broadcast = new Broadcast({ eventEmitter: this.getEventEmitter(), eventNames: { receive: 'broadcast.receive' }, receiverID: 'boradcast', senderID: this.userInfo, history: GetValue(broadcastConfig, 'history', false) }); this .on('room.join', function (roomConfig) { broadcast .setRootPath(this.getRoomDataPath(roomConfig.roomID)) .startReceiving(); }, this) .on('room.leave', function () { broadcast.stopReceiving(); }, this) .on('userlist.changename', function (userID, userName) { broadcast.changeUserName(userID, userName); }, this); return broadcast; }; function DeepClone(obj) { if (obj === null || typeof obj !== 'object') { // If obj is a primitive value or null, return it directly return obj; } if (Array.isArray(obj)) { // If obj is an array, create a new array and clone each element return obj.map(item => DeepClone(item)); } if (obj instanceof Date) { // If obj is a Date object, create a new Date object with the same value return new Date(obj); } if (obj instanceof RegExp) { // If obj is a RegExp object, create a new RegExp object with the same pattern and flags return new RegExp(obj); } if (Object.getPrototypeOf(obj) !== Object.prototype) { // If obj is a custom object, return a reference to it return obj; } // If obj is a plain object, create a new object and clone each property const clonedObj = {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { clonedObj[key] = DeepClone(obj[key]); } } return clonedObj; } class Tree { constructor(data) { if (data === undefined) { data = {}; } this.data = data; this.refPath = ''; } getFullPath(keys) { if (typeof (keys) === 'string') { if (keys === '.') { keys = this.refPath; } else if (keys.startsWith('..')) { if (this.refPath !== '') { var refPathKeys = this.refPath.split('.'); refPathKeys.pop(); keys = `${refPathKeys.join('.')}${keys.substring(1)}`; } else { // this.refPath === '' keys = keys.substring(2); } } else if (keys.startsWith('.')) { if (this.refPath !== '') { keys = `${this.refPath}${keys}`; } else { // this.refPath === '' keys = keys.substring(1); } } } return keys; } setRefPath(keys) { if (keys === undefined) { keys = ''; } this.refPath = this.getFullPath(keys); return this; } setValue(keys, value) { if (keys === undefined) { this.clear(); // No argument } else if (value === undefined) { this.data = keys; // JSON keys } else { SetValue(this.data, this.getFullPath(keys), value); } return this; } getValue(keys) { if (keys === undefined) { return this.data; } else { if (typeof (keys) === 'string') { keys = this.getFullPath(keys).split('.'); } return GetEntry(this.data, keys); } } cloneValue(keys) { return DeepClone(this.getValue(keys)); } removeKey(keys) { if (keys === undefined) { this.clear(); } else { if (typeof (keys) === 'string') { keys = this.getFullPath(keys).split('.'); } var lastKey = keys.pop(); var entry = GetEntry(this.data, keys); if (IsObject(entry)) { delete entry[lastKey]; } } return this; } hasKey(keys) { if (typeof (keys) === 'string') { keys = this.getFullPath(keys).split('.'); } var lastKey = keys.pop(); var entry = GetEntry(this.data, keys); if (!IsObject(entry)) { return false; } return entry.hasOwnProperty(lastKey) } clear() { Clear$1(this.data); return this; } clone(cloneData) { var data = (cloneData) ? this.cloneValue() : this.data; var tree = new Tree(data); tree.setRefPath(this.refPath); return tree; } } var IsObject = function (obj) { return (obj != null) && (typeof (obj) === 'object') }; var GetEntry = function (data, keys) { if (keys[0] === '') { return data; } var entry = data; for (var i = 0, cnt = keys.length; i < cnt; i++) { if (!IsObject(entry)) { return undefined; } entry = entry[keys[i]]; } return entry; }; class BaseUpdater { constructor(config) { // Event emitter this.setEventEmitter(config.eventEmitter, config.EventEmitterClass); this.parent = config.parent; this.key = config.key; if (this.parent) { this.fullKeyPath = ExtendKeyPath(this.parent.fullKeyPath, this.key); } else { this.fullKeyPath = ''; } this.type = config.type; this.eventNameMap = config.eventNames; this.table = config.table; this.database = firebase.database(); this.setRootPath(); this.children = {}; } shutdown() { this .stopUpdate() .clear() .destroyEventEmitter(); } destroy() { this.shutdown(); } setRootPath(rootPath) { if (rootPath === undefined) { var parentRootPath = (this.parent) ? this.parent.rootPath : ''; rootPath = `${parentRootPath}/${this.key}`; } this.rootPath = rootPath; var child; for (var key in this.children) { child = this.children[key]; if (child instanceof BaseUpdater) { child.setRootPath(); } } return this; } get rootRef() { return this.database.ref(this.rootPath); } load() { var self = this; return this.rootRef.once('value') .then(function (snapshot) { // Won't add any child var value = snapshot.val() || {}; self.table.setValue(value); return Promise.resolve(value) }) } setData(key, value) { if (key === undefined) { this.clear(); // Clear } else if (value === undefined) { var data = key; // JSON data for (key in this.children) { // Not in new data if (!data.hasOwnProperty(key)) { this.removeChild(key); } } for (key in data) { this.setChildData(key, data[key]); } } else { this.setChildData(key, value); // Pass data to column-updater } return this; } clear() { this.table.removeKey(this.fullKeyPath); for (var key in this.children) {