pull/6672/head
Guilherme Gazzo 8 years ago
parent 6640cfd9bb
commit b4f36de2e1
  1. 79
      packages/rocketchat-lib/client/lib/openRoom.coffee
  2. 102
      packages/rocketchat-lib/client/lib/openRoom.js
  3. 87
      packages/rocketchat-lib/client/lib/roomTypes.coffee
  4. 124
      packages/rocketchat-lib/client/lib/roomTypes.js
  5. 129
      packages/rocketchat-lib/lib/callbacks.coffee
  6. 131
      packages/rocketchat-lib/lib/callbacks.js
  7. 93
      packages/rocketchat-lib/lib/promises.coffee
  8. 89
      packages/rocketchat-lib/lib/promises.js
  9. 75
      packages/rocketchat-lib/lib/roomTypesCommon.coffee
  10. 83
      packages/rocketchat-lib/lib/roomTypesCommon.js
  11. 83
      packages/rocketchat-lib/lib/settings.coffee
  12. 102
      packages/rocketchat-lib/lib/settings.js
  13. 12
      packages/rocketchat-lib/package.js

@ -1,79 +0,0 @@
currentTracker = undefined
@openRoom = (type, name) ->
Session.set 'openedRoom', null
Meteor.defer ->
currentTracker = Tracker.autorun (c) ->
if RoomManager.open(type + name).ready() isnt true
BlazeLayout.render 'main', { modal: RocketChat.Layout.isEmbedded(), center: 'loading' }
return
user = Meteor.user()
unless user?.username
return
currentTracker = undefined
c.stop()
room = RocketChat.roomTypes.findRoom(type, name, user)
if not room?
if type is 'd'
Meteor.call 'createDirectMessage', name, (err) ->
if !err
RoomManager.close(type + name)
openRoom('d', name)
else
Session.set 'roomNotFound', {type: type, name: name}
BlazeLayout.render 'main', {center: 'roomNotFound'}
return
else
Meteor.call 'getRoomByTypeAndName', type, name, (err, record) ->
if err?
Session.set 'roomNotFound', {type: type, name: name}
BlazeLayout.render 'main', {center: 'roomNotFound'}
else
delete record.$loki
RocketChat.models.Rooms.upsert({ _id: record._id }, _.omit(record, '_id'))
RoomManager.close(type + name)
openRoom(type, name)
return
mainNode = document.querySelector('.main-content')
if mainNode?
for child in mainNode.children
mainNode.removeChild child if child?
roomDom = RoomManager.getDomOfRoom(type + name, room._id)
mainNode.appendChild roomDom
if roomDom.classList.contains('room-container')
roomDom.querySelector('.messages-box > .wrapper').scrollTop = roomDom.oldScrollTop
Session.set 'openedRoom', room._id
fireGlobalEvent 'room-opened', _.omit room, 'usernames'
Session.set 'editRoomTitle', false
RoomManager.updateMentionsMarksOfRoom type + name
Meteor.setTimeout ->
readMessage.readNow()
, 2000
# KonchatNotification.removeRoomNotification(params._id)
if Meteor.Device.isDesktop() and window.chatMessages?[room._id]?
setTimeout ->
$('.message-form .input-message').focus()
, 100
# update user's room subscription
sub = ChatSubscription.findOne({rid: room._id})
if sub?.open is false
Meteor.call 'openRoom', room._id, (err) ->
if err
return handleError(err)
if FlowRouter.getQueryParam('msg')
msg = { _id: FlowRouter.getQueryParam('msg'), rid: room._id }
RoomHistoryManager.getSurroundingMessages(msg);
RocketChat.callbacks.run 'enter-room', sub

@ -0,0 +1,102 @@
/* globals fireGlobalEvent readMessage*/
const openRoom = function(type, name) {
Session.set('openedRoom', null);
Meteor.defer(function() {
Tracker.autorun(function(c) {
if (RoomManager.open(type + name).ready() !== true) {
return BlazeLayout.render('main', {
modal: RocketChat.Layout.isEmbedded(),
center: 'loading'
});
}
const user = Meteor.user();
if (!(user != null && user.username)) {
return;
}
c.stop();
const room = RocketChat.roomTypes.findRoom(type, name, user);
if (room == null) {
if (type === 'd') {
Meteor.call('createDirectMessage', name, function(err) {
if (!err) {
RoomManager.close(type + name);
return openRoom('d', name);
} else {
Session.set('roomNotFound', {
type,
name
});
BlazeLayout.render('main', {
center: 'roomNotFound'
});
}
});
} else {
Meteor.call('getRoomByTypeAndName', type, name, function(err, record) {
if (err != null) {
Session.set('roomNotFound', {
type,
name
});
return BlazeLayout.render('main', {
center: 'roomNotFound'
});
} else {
delete record.$loki;
RocketChat.models.Rooms.upsert({
_id: record._id
}, _.omit(record, '_id'));
RoomManager.close(type + name);
return openRoom(type, name);
}
});
}
return;
}
const mainNode = document.querySelector('.main-content');
if (mainNode != null) {
[...((mainNode && mainNode.children) || [])].forEach(child => {
mainNode.removeChild(child);
});
const roomDom = RoomManager.getDomOfRoom(type + name, room._id);
mainNode.appendChild(roomDom);
if (roomDom.classList.contains('room-container')) {
roomDom.querySelector('.messages-box > .wrapper').scrollTop = roomDom.oldScrollTop;
}
}
Session.set('openedRoom', room._id);
fireGlobalEvent('room-opened', _.omit(room, 'usernames'));
Session.set('editRoomTitle', false);
RoomManager.updateMentionsMarksOfRoom(type + name);
Meteor.setTimeout(() => {
readMessage.readNow();
}, 2000);
if (Meteor.Device.isDesktop() && window.chatMessages && window.chatMessages[room._id] != null) {
setTimeout(() => {
return $('.message-form .input-message').focus();
}, 100);
}
const sub = ChatSubscription.findOne({
rid: room._id
});
if (sub && sub.open === false) {
Meteor.call('openRoom', room._id, function(err) {
if (err) {
return handleError(err);
}
});
}
if (FlowRouter.getQueryParam('msg')) {
const msg = {
_id: FlowRouter.getQueryParam('msg'),
rid: room._id
};
RoomHistoryManager.getSurroundingMessages(msg);
}
return RocketChat.callbacks.run('enter-room', sub);
});
});
};
this.openRoom = openRoom;

@ -1,87 +0,0 @@
RocketChat.roomTypes = new class roomTypesClient extends roomTypesCommon
checkCondition: (roomType) ->
return not roomType.condition? or roomType.condition()
getTypes: ->
orderedTypes = []
_.sortBy(@roomTypesOrder, 'order').forEach (type) =>
orderedTypes.push @roomTypes[type.identifier]
return orderedTypes
getIcon: (roomType) ->
return @roomTypes[roomType]?.icon
getRoomName: (roomType, roomData) ->
return @roomTypes[roomType]?.roomName roomData
getIdentifiers: (except) ->
except = [].concat except
list = _.reject @roomTypesOrder, (t) -> return except.indexOf(t.identifier) isnt -1
return _.map list, (t) -> return t.identifier
getUserStatus: (roomType, roomId) ->
return @roomTypes[roomType]?.getUserStatus?(roomId)
findRoom: (roomType, identifier, user) ->
return @roomTypes[roomType]?.findRoom identifier, user
canSendMessage: (roomId) ->
return ChatSubscription.find({ rid: roomId }).count() > 0
readOnly: (roomId, user) ->
fields = { ro: 1 }
# if a user has been specified then we want to see if that user has been muted in the room
if user
fields.muted = 1
room = ChatRoom.findOne({ _id: roomId }, fields : fields)
unless user
return room?.ro;
userOwner = RoomRoles.findOne({ rid: roomId, "u._id": user._id, roles: 'owner' }, { fields: { _id: 1 } })
return room?.ro is true and Array.isArray(room?.muted) and room?.muted.indexOf(user.username) != -1 and !userOwner
archived: (roomId) ->
fields = { archived: 1 }
room = ChatRoom.findOne({ _id: roomId }, fields : fields)
return room?.archived is true
verifyCanSendMessage: (roomId) ->
room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
return if not room?.t?
roomType = room.t
return @roomTypes[roomType]?.canSendMessage roomId if @roomTypes[roomType]?.canSendMessage?
return @canSendMessage roomId
verifyShowJoinLink: (roomId) ->
room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
return if not room?.t?
roomType = room.t
if not @roomTypes[roomType]?.showJoinLink?
return false
return @roomTypes[roomType].showJoinLink roomId
getNotSubscribedTpl: (roomId) ->
room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
return if not room?.t?
roomType = room.t
if not @roomTypes[roomType]?.notSubscribedTpl?
return false
return @roomTypes[roomType].notSubscribedTpl

@ -0,0 +1,124 @@
import roomTypesCommon from '../../lib/roomTypesCommon';
RocketChat.roomTypes = new class extends roomTypesCommon {
checkCondition(roomType) {
return (roomType.condition == null) || roomType.condition();
}
getTypes() {
return _.sortBy(this.roomTypesOrder, 'order').map((type) => this.roomTypes[type.identifier]);
}
getIcon(roomType) {
return this.roomTypes[roomType] && this.roomTypes[roomType].icon;
}
getRoomName(roomType, roomData) {
return this.roomTypes[roomType] && this.roomTypes[roomType].roomName && this.roomTypes[roomType].roomName(roomData);
}
getIdentifiers(e) {
const except = [].concat(e);
const list = _.reject(this.roomTypesOrder, (t) => except.indexOf(t.identifier) !== -1);
return _.map(list, (t) => t.identifier);
}
getUserStatus(roomType, roomId) {
this.roomTypes[roomType] && typeof this.roomTypes[roomType].getUserStatus === 'function' && this.roomTypes[roomType].getUserStatus(roomId);
}
findRoom(roomType, identifier, user) {
return this.roomTypes[roomType] && this.roomTypes[roomType].findRoom(identifier, user);
}
canSendMessage(roomId) {
return ChatSubscription.find({
rid: roomId
}).count() > 0;
}
readOnly(roomId, user) {
const fields = {
ro: 1
};
if (user) {
fields.muted = 1;
}
const room = ChatRoom.findOne({
_id: roomId
}, {
fields
});
if (!user) {
return room && room.ro;
}
/* globals RoomRoles */
const userOwner = RoomRoles.findOne({
rid: roomId,
'u._id': user._id,
roles: 'owner'
}, {
fields: {
_id: 1
}
});
return room && (room.ro === true && Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1 && !userOwner);
}
archived(roomId) {
const fields = {
archived: 1
};
const room = ChatRoom.findOne({
_id: roomId
}, {
fields
});
return room && room.archived === true;
}
verifyCanSendMessage(roomId) {
const room = ChatRoom.findOne({
_id: roomId
}, {
fields: {
t: 1
}
});
if (room && !room.t) {
return;
}
const roomType = room.t;
if (this.roomTypes[roomType] && this.roomTypes[roomType].canSendMessage) {
return this.roomTypes[roomType].canSendMessage(roomId);
}
return this.canSendMessage(roomId);
}
verifyShowJoinLink(roomId) {
const room = ChatRoom.findOne({
_id: roomId
}, {
fields: {
t: 1
}
});
if (room && !room.t) {
return;
}
const roomType = room.t;
if (this.roomTypes[roomType] && !this.roomTypes[roomType].showJoinLink) {
return false;
}
return this.roomTypes[roomType].showJoinLink(roomId);
}
getNotSubscribedTpl(roomId) {
const room = ChatRoom.findOne({
_id: roomId
}, {
fields: {
t: 1
}
});
if (room && !room.t) {
return;
}
const roomType = room.t;
if (this.roomTypes[roomType] && !this.roomTypes[roomType].notSubscribedTpl) {
return false;
}
return this.roomTypes[roomType].notSubscribedTpl;
}
};

@ -1,129 +0,0 @@
# https://github.com/TelescopeJS/Telescope/blob/master/packages/telescope-lib/lib/callbacks.js
###
# Callback hooks provide an easy way to add extra steps to common operations.
# @namespace RocketChat.callbacks
###
RocketChat.callbacks = {}
if Meteor.isServer
RocketChat.callbacks.showTime = true
RocketChat.callbacks.showTotalTime = true
else
RocketChat.callbacks.showTime = false
RocketChat.callbacks.showTotalTime = false
###
# Callback priorities
###
RocketChat.callbacks.priority =
HIGH: -1000
MEDIUM: 0
LOW: 1000
###
# Add a callback function to a hook
# @param {String} hook - The name of the hook
# @param {Function} callback - The callback function
###
RocketChat.callbacks.add = (hook, callback, priority, id) ->
# if callback array doesn't exist yet, initialize it
priority ?= RocketChat.callbacks.priority.MEDIUM
unless _.isNumber priority
priority = RocketChat.callbacks.priority.MEDIUM
callback.priority = priority
callback.id = id or Random.id()
RocketChat.callbacks[hook] ?= []
if RocketChat.callbacks.showTime is true
err = new Error
callback.stack = err.stack
# if not id?
# console.log('Callback without id', callback.stack)
# Avoid adding the same callback twice
for cb in RocketChat.callbacks[hook]
if cb.id is callback.id
return
RocketChat.callbacks[hook].push callback
return
###
# Remove a callback from a hook
# @param {string} hook - The name of the hook
# @param {string} id - The callback's id
###
RocketChat.callbacks.remove = (hookName, id) ->
RocketChat.callbacks[hookName] = _.reject RocketChat.callbacks[hookName], (callback) ->
callback.id is id
return
###
# Successively run all of a hook's callbacks on an item
# @param {String} hook - The name of the hook
# @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
# @param {Object} [constant] - An optional constant that will be passed along to each callback
# @returns {Object} Returns the item after it's been through all the callbacks for this hook
###
RocketChat.callbacks.run = (hook, item, constant) ->
callbacks = RocketChat.callbacks[hook]
if !!callbacks?.length
if RocketChat.callbacks.showTotalTime is true
totalTime = 0
# if the hook exists, and contains callbacks to run
result = _.sortBy(callbacks, (callback) -> return callback.priority or RocketChat.callbacks.priority.MEDIUM).reduce (result, callback) ->
# console.log(callback.name);
if RocketChat.callbacks.showTime is true or RocketChat.callbacks.showTotalTime is true
time = Date.now()
callbackResult = callback result, constant
if RocketChat.callbacks.showTime is true or RocketChat.callbacks.showTotalTime is true
currentTime = Date.now() - time
totalTime += currentTime
if RocketChat.callbacks.showTime is true
if Meteor.isServer
RocketChat.statsTracker.timing('callbacks.time', currentTime, ["hook:#{hook}", "callback:#{callback.id}"]);
else
console.log String(currentTime), hook, callback.id, callback.stack?.split?('\n')[2]?.match(/\(.+\)/)?[0]
return if typeof callbackResult == 'undefined' then result else callbackResult
, item
if RocketChat.callbacks.showTotalTime is true
if Meteor.isServer
RocketChat.statsTracker.timing('callbacks.totalTime', totalTime, ["hook:#{hook}"]);
else
console.log hook+':', totalTime
return result
else
# else, just return the item unchanged
return item
###
# Successively run all of a hook's callbacks on an item, in async mode (only works on server)
# @param {String} hook - The name of the hook
# @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
# @param {Object} [constant] - An optional constant that will be passed along to each callback
###
RocketChat.callbacks.runAsync = (hook, item, constant) ->
callbacks = RocketChat.callbacks[hook]
if Meteor.isServer and !!callbacks?.length
# use defer to avoid holding up client
Meteor.defer ->
# run all post submit server callbacks on post object successively
_.sortBy(callbacks, (callback) -> return callback.priority or RocketChat.callbacks.priority.MEDIUM).forEach (callback) ->
# console.log(callback.name);
callback item, constant
return
return
else
return item
return

@ -0,0 +1,131 @@
/*
* Callback hooks provide an easy way to add extra steps to common operations.
* @namespace RocketChat.callbacks
*/
RocketChat.callbacks = {};
if (Meteor.isServer) {
RocketChat.callbacks.showTime = true;
RocketChat.callbacks.showTotalTime = true;
} else {
RocketChat.callbacks.showTime = false;
RocketChat.callbacks.showTotalTime = false;
}
/*
* Callback priorities
*/
RocketChat.callbacks.priority = {
HIGH: -1000,
MEDIUM: 0,
LOW: 1000
};
/*
* Add a callback function to a hook
* @param {String} hook - The name of the hook
* @param {Function} callback - The callback function
*/
RocketChat.callbacks.add = function(hook, callback, priority, id) {
if (priority == null) {
priority = RocketChat.callbacks.priority.MEDIUM;
}
if (!_.isNumber(priority)) {
priority = RocketChat.callbacks.priority.MEDIUM;
}
callback.priority = priority;
callback.id = id || Random.id();
RocketChat.callbacks[hook] = RocketChat.callbacks[hook] || [];
if (RocketChat.callbacks.showTime === true) {
const err = new Error;
callback.stack = err.stack;
}
if (RocketChat.callbacks[hook].find((cb) => cb.id === callback.id)) {
return;
}
RocketChat.callbacks[hook].push(callback);
};
/*
* Remove a callback from a hook
* @param {string} hook - The name of the hook
* @param {string} id - The callback's id
*/
RocketChat.callbacks.remove = function(hookName, id) {
RocketChat.callbacks[hookName] = _.reject(RocketChat.callbacks[hookName], (callback) => callback.id === id);
};
/*
* Successively run all of a hook's callbacks on an item
* @param {String} hook - The name of the hook
* @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
* @param {Object} [constant] - An optional constant that will be passed along to each callback
* @returns {Object} Returns the item after it's been through all the callbacks for this hook
*/
RocketChat.callbacks.run = function(hook, item, constant) {
const callbacks = RocketChat.callbacks[hook];
if (!callbacks && callbacks.length) {
let totalTime = 0;
const result = _.sortBy(callbacks, function(callback) {
return callback.priority || RocketChat.callbacks.priority.MEDIUM;
}).reduce(function(result, callback) {
let time = 0;
if (RocketChat.callbacks.showTime === true || RocketChat.callbacks.showTotalTime === true) {
time = Date.now();
}
const callbackResult = callback(result, constant);
if (RocketChat.callbacks.showTime === true || RocketChat.callbacks.showTotalTime === true) {
const currentTime = Date.now() - time;
totalTime += currentTime;
if (RocketChat.callbacks.showTime === true) {
if (Meteor.isServer) {
RocketChat.statsTracker.timing('callbacks.time', currentTime, [`hook:${ hook }`, `callback:${ callback.id }`]);
} else {
let stack = callback.stack && typeof callback.stack.split === 'function' && callback.stack.split('\n');
stack = stack && stack[2] && (stack[2].match(/\(.+\)/)||[])[0];
console.log(String(currentTime), hook, callback.id, stack);
}
}
}
return (typeof callbackResult === 'undefined') ? result : callbackResult;
}, item);
if (RocketChat.callbacks.showTotalTime === true) {
if (Meteor.isServer) {
RocketChat.statsTracker.timing('callbacks.totalTime', totalTime, [`hook:${ hook }`]);
} else {
console.log(`${ hook }:`, totalTime);
}
}
return result;
} else {
return item;
}
};
/*
* Successively run all of a hook's callbacks on an item, in async mode (only works on server)
* @param {String} hook - The name of the hook
* @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
* @param {Object} [constant] - An optional constant that will be passed along to each callback
*/
RocketChat.callbacks.runAsync = function(hook, item, constant) {
const callbacks = RocketChat.callbacks[hook];
if (Meteor.isServer && callbacks && callbacks.length) {
Meteor.defer(function() {
_.sortBy(callbacks, (callback) => callback.priority || RocketChat.callbacks.priority.MEDIUM).forEach((callback) => callback(item, constant));
});
} else {
return item;
}
};

@ -1,93 +0,0 @@
# https://github.com/TelescopeJS/Telescope/blob/master/packages/telescope-lib/lib/callbacks.js
###
# Callback hooks provide an easy way to add extra steps to common operations.
# @namespace RocketChat.promises
###
RocketChat.promises = {}
###
# Callback priorities
###
RocketChat.promises.priority =
HIGH: -1000
MEDIUM: 0
LOW: 1000
###
# Add a callback function to a hook
# @param {String} hook - The name of the hook
# @param {Function} callback - The callback function
###
RocketChat.promises.add = (hook, callback, priority, id) ->
# if callback array doesn't exist yet, initialize it
priority ?= RocketChat.promises.priority.MEDIUM
unless _.isNumber priority
priority = RocketChat.promises.priority.MEDIUM
callback.priority = priority
callback.id = id or Random.id()
RocketChat.promises[hook] ?= []
# Avoid adding the same callback twice
for cb in RocketChat.promises[hook]
if cb.id is callback.id
return
RocketChat.promises[hook].push callback
return
###
# Remove a callback from a hook
# @param {string} hook - The name of the hook
# @param {string} id - The callback's id
###
RocketChat.promises.remove = (hookName, id) ->
RocketChat.promises[hookName] = _.reject RocketChat.promises[hookName], (callback) ->
callback.id is id
return
###
# Successively run all of a hook's callbacks on an item
# @param {String} hook - The name of the hook
# @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
# @param {Object} [constant] - An optional constant that will be passed along to each callback
# @returns {Object} Returns the item after it's been through all the callbacks for this hook
###
RocketChat.promises.run = (hook, item, constant) ->
callbacks = RocketChat.promises[hook]
if !!callbacks?.length
# if the hook exists, and contains callbacks to run
callbacks = _.sortBy(callbacks, (callback) -> return callback.priority or RocketChat.promises.priority.MEDIUM)
return callbacks.reduce (previousPromise, callback) ->
return new Promise (resolve, reject) ->
previousPromise.then (result) ->
callback(result, constant).then(resolve, reject)
, Promise.resolve(item)
else
# else, just return the item unchanged
return Promise.resolve(item)
###
# Successively run all of a hook's callbacks on an item, in async mode (only works on server)
# @param {String} hook - The name of the hook
# @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
# @param {Object} [constant] - An optional constant that will be passed along to each callback
###
RocketChat.promises.runAsync = (hook, item, constant) ->
callbacks = RocketChat.promises[hook]
if Meteor.isServer and !!callbacks?.length
# use defer to avoid holding up client
Meteor.defer ->
# run all post submit server callbacks on post object successively
_.sortBy(callbacks, (callback) -> return callback.priority or RocketChat.promises.priority.MEDIUM).forEach (callback) ->
# console.log(callback.name);
callback item, constant
return
return
else
return item
return

@ -0,0 +1,89 @@
/*
* Callback hooks provide an easy way to add extra steps to common operations.
* @namespace RocketChat.promises
*/
RocketChat.promises = {};
/*
* Callback priorities
*/
RocketChat.promises.priority = {
HIGH: -1000,
MEDIUM: 0,
LOW: 1000
};
/*
* Add a callback function to a hook
* @param {String} hook - The name of the hook
* @param {Function} callback - The callback function
*/
RocketChat.promises.add = function(hook, callback, p = RocketChat.promises.priority.MEDIUM, id) {
const priority = !_.isNumber(p) ? RocketChat.promises.priority.MEDIUM : p;
callback.priority = priority;
callback.id = id || Random.id();
RocketChat.promises[hook] = RocketChat.promises[hook] || [];
if (RocketChat.promises[hook].find(cb => cb.id === callback.id)) {
return;
}
RocketChat.promises[hook].push(callback);
};
/*
* Remove a callback from a hook
* @param {string} hook - The name of the hook
* @param {string} id - The callback's id
*/
RocketChat.promises.remove = function(hookName, id) {
RocketChat.promises[hookName] = _.reject(RocketChat.promises[hookName], (callback) => callback.id === id);
};
/*
* Successively run all of a hook's callbacks on an item
* @param {String} hook - The name of the hook
* @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
* @param {Object} [constant] - An optional constant that will be passed along to each callback
* @returns {Object} Returns the item after it's been through all the callbacks for this hook
*/
RocketChat.promises.run = function(hook, item, constant) {
let callbacks = RocketChat.promises[hook];
if (callbacks == null || callbacks.length === 0) {
return Promise.resolve(item);
}
callbacks = _.sortBy(callbacks, (callback) => callback.priority || RocketChat.promises.priority.MEDIUM);
return callbacks.reduce(function(previousPromise, callback) {
return new Promise(function(resolve, reject) {
return previousPromise.then((result) => callback(result, constant).then(resolve, reject));
});
}, Promise.resolve(item));
};
/*
* Successively run all of a hook's callbacks on an item, in async mode (only works on server)
* @param {String} hook - The name of the hook
* @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
* @param {Object} [constant] - An optional constant that will be passed along to each callback
*/
RocketChat.promises.runAsync = function(hook, item, constant) {
const callbacks = RocketChat.promises[hook];
if (!Meteor.isServer || callbacks == null || callbacks.length === 0) {
return item;
}
Meteor.defer(() => {
_.sortBy(callbacks, (callback) => callback.priority || RocketChat.promises.priority.MEDIUM).forEach(function(callback) {
callback(item, constant);
});
});
};

@ -1,75 +0,0 @@
class @roomTypesCommon
roomTypes: {}
roomTypesOrder: []
mainOrder: 1
### Adds a room type to app
@param identifier An identifier to the room type. If a real room, MUST BE the same of `db.rocketchat_room.t` field, if not, can be null
@param order Order number of the type
@param config
template: template name to render on sideNav
icon: icon class
route:
name: route name
action: route action function
###
add: (identifier, order, config) ->
unless identifier?
identifier = Random.id()
if @roomTypes[identifier]?
return false
if not order?
order = @mainOrder + 10
@mainOrder += 10
# @TODO validate config options
@roomTypesOrder.push
identifier: identifier
order: order
@roomTypes[identifier] = config
if config.route?.path? and config.route?.name? and config.route?.action?
routeConfig =
name: config.route.name
action: config.route.action
if Meteor.isClient
routeConfig.triggersExit = [ roomExit ]
FlowRouter.route config.route.path, routeConfig
hasCustomLink: (roomType) ->
return @roomTypes[roomType]?.route?.link?
###
@param roomType: room type (e.g.: c (for channels), d (for direct channels))
@param subData: the user's subscription data
###
getRouteLink: (roomType, subData) ->
unless @roomTypes[roomType]?
return false
routeData = {}
if @roomTypes[roomType]?.route?.link?
routeData = @roomTypes[roomType].route.link(subData)
else if subData?.name?
routeData = { name: subData.name }
return FlowRouter.path @roomTypes[roomType].route.name, routeData
openRouteLink: (roomType, subData, queryParams) ->
unless @roomTypes[roomType]?
return false
routeData = {}
if @roomTypes[roomType]?.route?.link?
routeData = @roomTypes[roomType].route.link(subData)
else if subData?.name?
routeData = { name: subData.name }
return FlowRouter.go @roomTypes[roomType].route.name, routeData, queryParams

@ -0,0 +1,83 @@
/* globals roomExit*/
this.roomTypesCommon = class {
constructor() {
this.roomTypes = {};
this.roomTypesOrder = [];
this.mainOrder = 1;
}
/* Adds a room type to app
@param identifier An identifier to the room type. If a real room, MUST BE the same of `db.rocketchat_room.t` field, if not, can be null
@param order Order number of the type
@param config
template: template name to render on sideNav
icon: icon class
route:
name: route name
action: route action function
*/
add(identifier = Random.id(), order, config) {
if (this.roomTypes[identifier] != null) {
return false;
}
if (order == null) {
order = this.mainOrder + 10;
this.mainOrder += 10;
}
this.roomTypesOrder.push({
identifier,
order
});
this.roomTypes[identifier] = config;
if (config.route && config.route.path && config.route.name && config.route.action) {
const routeConfig = {
name: config.route.name,
action: config.route.action
};
if (Meteor.isClient) {
routeConfig.triggersExit = [roomExit];
}
return FlowRouter.route(config.route.path, routeConfig);
}
}
hasCustomLink(roomType) {
return this.roomTypes[roomType] && this.roomTypes[roomType].route && this.roomTypes[roomType].route.link != null;
}
/*
@param roomType: room type (e.g.: c (for channels), d (for direct channels))
@param subData: the user's subscription data
*/
getRouteLink(roomType, subData) {
if (this.roomTypes[roomType] == null) {
return false;
}
let routeData = {};
if (this.roomTypes[roomType] && this.roomTypes[roomType].route && this.roomTypes[roomType].route.link) {
routeData = this.roomTypes[roomType].route.link(subData);
} else if (subData && subData.name) {
routeData = {
name: subData.name
};
}
return FlowRouter.path(this.roomTypes[roomType].route.name, routeData);
}
openRouteLink(roomType, subData, queryParams) {
if (this.roomTypes[roomType] == null) {
return false;
}
let routeData = {};
if (this.roomTypes[roomType] && this.roomTypes[roomType].route && this.roomTypes[roomType].route.link) {
routeData = this.roomTypes[roomType].route.link(subData);
} else if (subData && subData.name) {
routeData = {
name: subData.name
};
}
return FlowRouter.go(this.roomTypes[roomType].route.name, routeData, queryParams);
}
};

@ -1,83 +0,0 @@
###
# RocketChat.settings holds all packages settings
# @namespace RocketChat.settings
###
RocketChat.settings =
callbacks: {}
regexCallbacks: {}
ts: new Date
get: (_id, callback) ->
if callback?
RocketChat.settings.onload _id, callback
if _id is '*' and Meteor.settings?
for key, value of Meteor.settings
callback key, value
return
if _.isRegExp(_id)
for key, value of Meteor.settings when _id.test(key)
callback key, value
return
if Meteor.settings?[_id]?
callback _id, Meteor.settings?[_id]
else
if _.isRegExp(_id)
items = []
for key, value of Meteor.settings when _id.test(key)
items.push
key: key
value: value
return items
return Meteor.settings?[_id]
set: (_id, value, callback) ->
Meteor.call 'saveSetting', _id, value, callback
batchSet: (settings, callback) ->
# async -> sync
# http://daemon.co.za/2012/04/simple-async-with-only-underscore/
save = (setting) ->
return (callback) ->
Meteor.call 'saveSetting', setting._id, setting.value, setting.editor, callback
actions = _.map settings, (setting) -> save(setting)
_(actions).reduceRight(_.wrap, (err, success) -> return callback err, success)()
load: (key, value, initialLoad) ->
if RocketChat.settings.callbacks[key]?
for callback in RocketChat.settings.callbacks[key]
callback key, value, initialLoad
if RocketChat.settings.callbacks['*']?
for callback in RocketChat.settings.callbacks['*']
callback key, value, initialLoad
for cbKey, cbValue of RocketChat.settings.regexCallbacks
if cbValue.regex.test(key)
callback(key, value, initialLoad) for callback in cbValue.callbacks
onload: (key, callback) ->
# if key is '*'
# for key, value in Meteor.settings
# callback key, value, false
# else if Meteor.settings?[_id]?
# callback key, Meteor.settings[_id], false
keys = [].concat key
for k in keys
if _.isRegExp k
RocketChat.settings.regexCallbacks[k.source] ?= {
regex: k
callbacks: []
}
RocketChat.settings.regexCallbacks[k.source].callbacks.push callback
else
RocketChat.settings.callbacks[k] ?= []
RocketChat.settings.callbacks[k].push callback

@ -0,0 +1,102 @@
/*
* RocketChat.settings holds all packages settings
* @namespace RocketChat.settings
*/
RocketChat.settings = {
callbacks: {},
regexCallbacks: {},
ts: new Date,
get(_id, callback) {
if (callback != null) {
RocketChat.settings.onload(_id, callback);
if (!Meteor.settings) {
return;
}
if (_id === '*') {
return Object.keys(Meteor.settings).forEach(key => {
const value = Meteor.settings[key];
callback(key, value);
});
}
if (_.isRegExp(_id) && Meteor.settings) {
return Object.keys(Meteor.settings).forEach(key => {
if (!_id.test(key)) {
return;
}
const value = Meteor.settings[key];
callback(key, value);
});
}
return Meteor.settings[_id] && callback(_id, Meteor.settings[_id]);
} else {
if (!Meteor.settings) {
return;
}
if (_.isRegExp(_id)) {
return Object.keys(Meteor.settings).reduce((items, key) => {
const value = Meteor.settings[key];
if (_id.test(key)) {
items.push({
key,
value
});
}
return items;
}, []);
}
return Meteor.settings && Meteor.settings[_id];
}
},
set(_id, value, callback) {
return Meteor.call('saveSetting', _id, value, callback);
},
batchSet(settings, callback) {
// async -> sync
// http://daemon.co.za/2012/04/simple-async-with-only-underscore/
const save = function(setting) {
return function(callback) {
return Meteor.call('saveSetting', setting._id, setting.value, setting.editor, callback);
};
};
const actions = _.map(settings, (setting) => save(setting));
return _(actions).reduceRight(_.wrap, (err, success) => callback(err, success))();
},
load(key, value, initialLoad) {
Object.keys({
'*': 1,
[key]: 1
}).forEach(key => {
if (RocketChat.settings.callbacks[key]) {
RocketChat.settings.callbacks[key].forEach(callback => callback(key, value, initialLoad));
}
});
Object.keys(RocketChat.settings.regexCallbacks).forEach(cbKey => {
const cbValue = RocketChat.settings.regexCallbacks[cbKey];
if (!cbValue.regex.test(key)) {
return;
}
cbValue.callbacks.forEach(callback => callback(key, value, initialLoad));
});
},
onload(key, callback) {
// if key is '*'
// for key, value in Meteor.settings
// callback key, value, false
// else if Meteor.settings?[_id]?
// callback key, Meteor.settings[_id], false
const keys = [].concat(key);
keys.forEach(k => {
if (_.isRegExp(k)) {
RocketChat.settings.regexCallbacks[name = k.source] = RocketChat.settings.regexCallbacks[name = k.source] || {
regex: k,
callbacks: []
};
RocketChat.settings.regexCallbacks[k.source].callbacks.push(callback);
} else {
RocketChat.settings.callbacks[k] = RocketChat.settings.callbacks[k] || [];
RocketChat.settings.callbacks[k].push(callback);
}
});
}
};

@ -52,13 +52,13 @@ Package.onUse(function(api) {
// COMMON LIB
api.addFiles('lib/getURL.js');
api.addFiles('lib/settings.coffee');
api.addFiles('lib/settings.js');
api.addFiles('lib/configLogger.js');
api.addFiles('lib/callbacks.coffee');
api.addFiles('lib/callbacks.js');
api.addFiles('lib/fileUploadRestrictions.js');
api.addFiles('lib/placeholders.js');
api.addFiles('lib/promises.coffee');
api.addFiles('lib/roomTypesCommon.coffee');
api.addFiles('lib/promises.js');
api.addFiles('lib/roomTypesCommon.js');
api.addFiles('lib/slashCommand.js');
api.addFiles('lib/Message.js');
api.addFiles('lib/MessageTypes.js');
@ -178,10 +178,10 @@ Package.onUse(function(api) {
api.addFiles('client/lib/TabBar.js', 'client');
api.addFiles('client/lib/RocketChatTabBar.js', 'client');
api.addFiles('client/lib/cachedCollection.js', 'client');
api.addFiles('client/lib/openRoom.coffee', 'client');
api.addFiles('client/lib/openRoom.js', 'client');
api.addFiles('client/lib/roomExit.js', 'client');
api.addFiles('client/lib/settings.js', 'client');
api.addFiles('client/lib/roomTypes.coffee', 'client');
api.addFiles('client/lib/roomTypes.js', 'client');
api.addFiles('client/lib/userRoles.js', 'client');
api.addFiles('client/lib/Layout.js', 'client');

Loading…
Cancel
Save