phaser4-rex-plugins
Version:
1,655 lines (1,408 loc) • 151 kB
JavaScript
(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.rexfirebaseplugin = 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();
})
};
const FILE_POPULATED = Phaser.Loader.FILE_POPULATED;
const UUID = Phaser.Utils.String.UUID;
class AwaitFile extends Phaser.Loader.File {
constructor(loader, fileConfig) {
if (!fileConfig.hasOwnProperty('type')) {
fileConfig.type = 'await';
}
if (!fileConfig.hasOwnProperty('url')) {
fileConfig.url = '';
}
if (!fileConfig.hasOwnProperty('key')) {
fileConfig.key = UUID();
}
super(loader, fileConfig);
}
load() {
if (this.state === FILE_POPULATED) {
// Can happen for example in a JSONFile if they've provided a JSON object instead of a URL
this.loader.nextFile(this, true);
} else {
// start loading task
var config = this.config;
var callback = config.callback;
var scope = config.scope;
if (callback) {
var self = this;
var runOnce = false;
var successCallback = function () {
if (runOnce) {
return;
}
// Invoke onLoad next tick
setTimeout(function () {
self.onLoad();
}, 0);
runOnce = true;
};
var failureCallback = function () {
if (runOnce) {
return;
}
// Invoke onError next tick
setTimeout(function () {
self.onError();
}, 0);
runOnce = true;
};
if (scope) {
callback.call(scope, successCallback, failureCallback);
} else {
callback(successCallback, failureCallback);
}
} else {
this.onLoad();
}
}
}
onLoad() {
this.loader.nextFile(this, true);
}
onError() {
this.loader.nextFile(this, false);
}
}
const LoaderCallback = function (urlConfig, firebaseConfig) {
var callback = function (successCallback, failureCallback) {
return Preload(urlConfig, firebaseConfig)
.then(function () {
setTimeout(successCallback, 0);
})
.catch(failureCallback)
};
this.addFile(new AwaitFile(this, {
config: { callback: callback }
}));
return this;
};
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,