Move some ui function to ui-utils (#13123)

* Move rocketchat settings to specific package

* WIP: Move models from rocketchat-lib to a specific package (server)

* Move function from rocketchat:lib to rocketchat:utils to use it in rocketchat:models

* Move client models from rocketchat:lib to rocketchat:models

* Fix lint

* Move rocketchat.info from lib to utils

* Remove directly dependency between lib and migrations

* Move statistics Model to rocketchat:models

* Create rocketchat:metrics to be able to depacking rocketchat callbacks

* Move  callbacks to specific package

* Remove unused dependency

* Move rocketchat-notifications to a specific package

* Move rocketchat-promises to a specific package

* remove directly dependency from metrics and models

* Move CachedCollection from lib to models

* Move ui models/collections from ui to models

* Move authorization client/ui models to rocketchat:models to be able to remove lib dependency

* Creation of rocketchat:ui-utils to help decouple rocketchat:lib and rocketchat:authz

* Move some common functions to rocketchat:utils

* Change imports to dynamic imports to avoid directly dependency between some packages

* Move authz models to rocketchat:models

* Remove directly dependency between rocketchat:authz and rocketchat:lib

* Move some functions from rocketchat:lib to rocketchat:utils

* Add functions to settings package

* Convert rocketchat:file-upload to main module structure

* Import FileUpload where it is being used

* Remove FileUpload and fileUploadHandler from globals eslintrc

* Move some  functions to rocketchat:ui-utils

* Remove directly dependency between rocketchat:authorization and rocketchat:ui-utils

* Remove dependency between lazy-load and lib

* Change imports of renderMessageBody from ui-message to ui-utils

* Add import of main ready from ui-utils

* Convert rocketchat-ui-sidenav to main module structure

* Add imports of toolbarSearch from ui-sidenav

* Remove toolbarSearch from eslintrc globals

* Move CachedCollection to a specific package

* Change imports of CachedCollection to new package

* Move some functions to rocketchat:ui-utils

* Remove directly dependency between tooltip and lib

*  Remove directly dependency between settings and metrics

* Move some settings client function from lib to settings

* Convert rocketchat-ui-master to main module structure

* Remove directly dependency between rocketchat:e2e and rocketchat:lib

* Fix wrong import and lint

* Convert rocketchat-webrtc to main module structure

* Fix missing export

* Remove directly dependency between rocketchat:emoji and lib

* Add emoji dependencies inside RocketChat namespace

* Merge branch 'develop' into globals/move-rocketchat-callbacks

* Move some functions to utils

* Fix lint

* Move some ui functions to ui-utils

* Fix import missed objects inside RocketChat namespace

* Fix lint

* Revert commented test file

* Fix lint

* Remove old code

* Remove old code

* Use openedRoom

* Remove old code

* Change import to a local file instead from package

* import emoji in message properties

* Move message properties to ui-utils package

* Fix lint

* Move openedRoom to RoomManager

* Fix console errors
pull/13131/head^2
Marcos Spessatto Defendi 6 years ago committed by Rodrigo Nascimento
parent 8d23486314
commit af96bd990d
  1. 76
      packages/rocketchat-lib/client/lib/RocketChatTabBar.js
  2. 84
      packages/rocketchat-lib/client/lib/TabBar.js
  3. 3
      packages/rocketchat-lib/client/lib/openRoom.js
  4. 16
      packages/rocketchat-lib/lib/MessageProperties.js
  5. 21
      packages/rocketchat-lib/lib/MessageTypes.js
  6. 18
      packages/rocketchat-lib/tests/server.tests.js
  7. 26
      packages/rocketchat-ui-cached-collection/client/models/CachedCollection.js
  8. 20
      packages/rocketchat-ui-message/client/messageBox.js
  9. 4
      packages/rocketchat-ui-message/client/popup/messagePopupConfig.js
  10. 1
      packages/rocketchat-ui-message/package.js
  11. 68
      packages/rocketchat-ui-utils/client/index.js
  12. 76
      packages/rocketchat-ui-utils/client/lib/RocketChatTabBar.js
  13. 4
      packages/rocketchat-ui-utils/client/lib/RoomManager.js
  14. 83
      packages/rocketchat-ui-utils/client/lib/TabBar.js
  15. 0
      packages/rocketchat-ui-utils/client/lib/alerts.html
  16. 73
      packages/rocketchat-ui-utils/client/lib/alerts.js
  17. 39
      packages/rocketchat-ui-utils/client/lib/avatar.js
  18. 0
      packages/rocketchat-ui-utils/client/lib/popout.html
  19. 211
      packages/rocketchat-ui-utils/client/lib/popout.js
  20. 16
      packages/rocketchat-ui-utils/lib/MessageProperties.js
  21. 19
      packages/rocketchat-ui-utils/lib/MessageTypes.js
  22. 2
      packages/rocketchat-ui-utils/package.js
  23. 2
      packages/rocketchat-ui-utils/server/index.js
  24. 8
      packages/rocketchat-ui-utils/tests/server.mocks.js
  25. 22
      packages/rocketchat-ui-utils/tests/server.tests.js
  26. 38
      packages/rocketchat-ui/client/lib/avatar.js
  27. 73
      packages/rocketchat-ui/client/views/app/alerts.js
  28. 210
      packages/rocketchat-ui/client/views/app/popout.js
  29. 2
      packages/rocketchat-ui/client/views/app/room.js
  30. 2
      packages/rocketchat-ui/package.js

@ -1,75 +1 @@
import { ReactiveVar } from 'meteor/reactive-var';
import { Tracker } from 'meteor/tracker';
export class RocketChatTabBar {
constructor() {
this.template = new ReactiveVar();
this.id = new ReactiveVar();
this.group = new ReactiveVar();
this.state = new ReactiveVar();
this.data = new ReactiveVar();
}
getTemplate() {
return this.template.get();
}
getId() {
return this.id.get();
}
setTemplate(template) {
this.template.set(template);
}
currentGroup() {
return this.group.get();
}
showGroup(group) {
this.group.set(group);
}
setData(d) {
this.data.set(d);
}
getData() {
return this.data.get();
}
getButtons() {
return RocketChat.TabBar.getButtons();
}
getState() {
return this.state.get();
}
open(button) {
this.state.set('opened');
Tracker.afterFlush(() => {
$('.contextual-bar__container').scrollTop(0).find('input[type=text]:first').focus();
});
if (!button) {
return;
}
if (typeof button !== 'object' || !button.id) {
button = RocketChat.TabBar.getButton(button);
}
$('.flex-tab, .contextual-bar').css('width', button.width ? `${ button.width }px` : '');
this.template.set(button.template);
this.id.set(button.id);
return button;
}
close() {
this.state.set('');
$('.flex-tab, .contextual-bar').css('width', '');
this.template.set();
this.id.set();
}
}
export { RocketChatTabBar } from 'meteor/rocketchat:ui-utils';

@ -1,83 +1,3 @@
import _ from 'underscore';
import { ReactiveVar } from 'meteor/reactive-var';
import { TabBar } from 'meteor/rocketchat:ui-utils';
RocketChat.TabBar = new (class TabBar {
get size() {
return this._size.get();
}
set size(s) {
this._size.set(s);
}
constructor() {
this.buttons = new ReactiveVar({});
this._size = new ReactiveVar(4);
this.extraGroups = {};
}
show() {
$('.flex-tab-bar').show();
}
hide() {
$('.flex-tab-bar').hide();
}
addButton(config) {
if (!config || !config.id) {
return false;
}
const btns = this.buttons.curValue;
btns[config.id] = config;
if (this.extraGroups[config.id]) {
btns[config.id].groups = _.union((btns[config.id].groups || []), this.extraGroups[config.id]);
}
this.buttons.set(btns);
}
removeButton(id) {
const btns = this.buttons.curValue;
delete btns[id];
this.buttons.set(btns);
}
updateButton(id, config) {
const btns = this.buttons.curValue;
if (btns[id]) {
btns[id] = _.extend(btns[id], config);
this.buttons.set(btns);
}
}
getButtons() {
const buttons = _.toArray(this.buttons.get()).filter((button) => !button.condition || button.condition());
return _.sortBy(buttons, 'order');
}
getButton(id) {
return _.findWhere(this.buttons.get(), { id });
}
addGroup(id, groups) {
const btns = this.buttons.curValue;
if (btns[id]) {
btns[id].groups = _.union((btns[id].groups || []), groups);
this.buttons.set(btns);
} else {
this.extraGroups[id] = _.union((this.extraGroups[id] || []), groups);
}
}
removeGroup(id, groups) {
const btns = this.buttons.curValue;
if (btns[id]) {
btns[id].groups = _.difference((btns[id].groups || []), groups);
this.buttons.set(btns);
} else {
this.extraGroups[id] = _.difference((this.extraGroups[id] || []), groups);
}
}
});
RocketChat.TabBar = TabBar;

@ -3,6 +3,7 @@ import { Tracker } from 'meteor/tracker';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { BlazeLayout } from 'meteor/kadira:blaze-layout';
import { Session } from 'meteor/session';
import { RoomManager } from 'meteor/rocketchat:ui-utils';
import _ from 'underscore';
export let currentTracker = undefined;
@ -68,7 +69,7 @@ openRoom = function(type, name) {
}
Session.set('openedRoom', room._id);
RocketChat.openedRoom = room._id;
RoomManager.openedRoom = room._id;
fireGlobalEvent('room-opened', _.omit(room, 'usernames'));

@ -1,17 +1,7 @@
import GraphemeSplitter from 'grapheme-splitter';
import { messageProperties } from 'meteor/rocketchat:ui-utils';
const splitter = new GraphemeSplitter();
export const messageProperties = {
length: ((message) => splitter.countGraphemes(message)),
messageWithoutEmojiShortnames: ((message) => message.replace(/:\w+:/gm, (match) => {
if (RocketChat.emoji.list[match] !== undefined) {
return ' ';
}
return match;
})),
export {
messageProperties,
};
// check for tests

@ -1,24 +1,7 @@
import { Meteor } from 'meteor/meteor';
import { MessageTypes } from 'meteor/rocketchat:ui-utils';
RocketChat.MessageTypes = new class {
constructor() {
this.types = {};
}
registerType(options) {
return this.types[options.id] = options;
}
getType(message) {
return this.types[message && message.t];
}
isSystemMessage(message) {
const type = this.types[message && message.t];
return type && type.system;
}
};
RocketChat.MessageTypes = MessageTypes;
Meteor.startup(function() {
RocketChat.MessageTypes.registerType({

@ -4,7 +4,6 @@ import assert from 'assert';
import './server.mocks.js';
import PasswordPolicyClass from '../server/lib/PasswordPolicyClass';
import { messageProperties } from '../lib/MessageProperties';
describe('PasswordPolicyClass', () => {
describe('Default options', () => {
@ -206,20 +205,3 @@ describe('PasswordPolicyClass', () => {
});
});
});
const messages = {
'Sample Message': 14,
'Sample 1 ⛳': 10,
'Sample 2 ❤': 10,
'Sample 3 ⛳❤⛳❤': 13,
};
describe('Message Properties', () => {
describe('Check Message Length', () => {
Object.keys(messages).forEach((objectKey) => {
it('should treat emojis as single characters', () => {
assert.equal(messageProperties.length(objectKey), messages[objectKey]);
});
});
});
});

@ -340,19 +340,21 @@ export class CachedCollection {
}
async setupListener(eventType, eventName) {
const { Notifications } = await import('meteor/rocketchat:notifications');
const { RoomManager } = await import('meteor/rocketchat:ui');
Notifications[eventType || this.eventType](eventName || this.eventName, (t, record) => {
this.log('record received', t, record);
callbacks.run(`cachedCollection-received-${ this.name }`, record, t);
if (t === 'removed') {
this.collection.remove(record._id);
RoomManager.close(record.t + record.name);
} else {
this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
}
Meteor.startup(async() => {
const { Notifications } = await import('meteor/rocketchat:notifications');
const { RoomManager } = await import('meteor/rocketchat:ui');
Notifications[eventType || this.eventType](eventName || this.eventName, (t, record) => {
this.log('record received', t, record);
callbacks.run(`cachedCollection-received-${ this.name }`, record, t);
if (t === 'removed') {
this.collection.remove(record._id);
RoomManager.close(record.t + record.name);
} else {
this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
}
this.saveCache();
this.saveCache();
});
});
}

@ -499,7 +499,7 @@ Template.messageBox.events({
const timer = document.querySelector('.rc-message-box__timer');
const mic = document.querySelector('.rc-message-box__icon.mic');
chatMessages[RocketChat.openedRoom].recording = true;
chatMessages[RoomManager.openedRoom].recording = true;
AudioRecorder.start(function() {
const startTime = new Date;
timer.innerHTML = '00:00';
@ -531,7 +531,7 @@ Template.messageBox.events({
}
AudioRecorder.stop();
chatMessages[RocketChat.openedRoom].recording = false;
chatMessages[RoomManager.openedRoom].recording = false;
},
'click .js-audio-message-check'(event) {
event.preventDefault();
@ -547,12 +547,12 @@ Template.messageBox.events({
clearInterval(audioMessageIntervalId);
}
chatMessages[RocketChat.openedRoom].recording = false;
chatMessages[RoomManager.openedRoom].recording = false;
AudioRecorder.stop(function(blob) {
loader.classList.remove('active');
mic.classList.add('active');
const roomId = Session.get('openedRoom');
const roomId = Session.get('RoomManager.openedRoom');
const record = {
name: `${ TAPi18n.__('Audio record') }.mp3`,
size: blob.size,
@ -658,7 +658,7 @@ Template.messageBox.events({
RocketChat.EmojiPicker.close();
} else {
RocketChat.EmojiPicker.open(event.currentTarget, (emoji) => {
const { input } = chatMessages[RocketChat.openedRoom];
const { input } = chatMessages[RoomManager.openedRoom];
const emojiValue = `:${ emoji }:`;
@ -685,8 +685,8 @@ Template.messageBox.onRendered(function() {
const reply = $(input).data('reply');
self.dataReply.set(reply);
});
chatMessages[RocketChat.openedRoom] = chatMessages[RocketChat.openedRoom] || new ChatMessages;
chatMessages[RocketChat.openedRoom].input = this.$('.js-input-message').autogrow({
chatMessages[RoomManager.openedRoom] = chatMessages[RoomManager.openedRoom] || new ChatMessages;
chatMessages[RoomManager.openedRoom].input = this.$('.js-input-message').autogrow({
animate: true,
onInitialize: true,
}).on('autogrow', () => {
@ -724,9 +724,9 @@ Meteor.startup(function() {
});
RocketChat.callbacks.add('enter-room', function() {
setTimeout(() => {
if (chatMessages[RocketChat.openedRoom].input) {
chatMessages[RocketChat.openedRoom].input.focus();
chatMessages[RocketChat.openedRoom].restoreText(RocketChat.openedRoom);
if (chatMessages[RoomManager.openedRoom].input) {
chatMessages[RoomManager.openedRoom].input.focus();
chatMessages[RoomManager.openedRoom].restoreText(RoomManager.openedRoom);
}
}, 200);
});

@ -304,7 +304,7 @@ Template.messagePopupConfig.helpers({
// Get users from Server
if (items.length < 5 && filterText !== '') {
fetchUsersFromServerDelayed(filterText, items, cb, RocketChat.openedRoom);
fetchUsersFromServerDelayed(filterText, items, cb, RoomManager.openedRoom);
}
const all = {
@ -365,7 +365,7 @@ Template.messagePopupConfig.helpers({
}).fetch();
if (records.length < 5 && filter && filter.trim() !== '') {
fetchRoomsFromServerDelayed(filter, records, cb, RocketChat.openedRoom);
fetchRoomsFromServerDelayed(filter, records, cb, RoomManager.openedRoom);
}
return records;
},

@ -17,6 +17,7 @@ Package.onUse(function(api) {
'templating',
'tracker',
'rocketchat:utils',
'rocketchat:ui',
'rocketchat:ui-utils',
'rocketchat:emoji',
'rocketchat:lib',

@ -1,43 +1,25 @@
import { AdminBox } from './lib/AdminBox';
import { modal } from './lib/modal';
import { SideNav } from './lib/SideNav';
import { AccountBox } from './lib/AccountBox';
import { menu } from './lib/menu';
import { call } from './lib/callMethod';
import { erase, hide, leave } from './lib/ChannelActions';
import { MessageAction } from './lib/MessageAction';
import { messageBox } from './lib/messageBox';
import { popover } from './lib/popover';
import { readMessage } from './lib/readMessages';
import { RoomManager } from './lib/RoomManager';
import { upsertMessage, RoomHistoryManager } from './lib/RoomHistoryManager';
import { mainReady } from './lib/mainReady';
import { renderMessageBody } from './lib/renderMessageBody';
import { Layout } from './lib/Layout';
import { IframeLogin, iframeLogin } from './lib/IframeLogin';
import { fireGlobalEvent } from './lib/fireGlobalEvent';
export {
AdminBox,
modal,
SideNav,
AccountBox,
menu,
call,
erase,
hide,
leave,
MessageAction,
messageBox,
popover,
readMessage,
RoomManager,
RoomHistoryManager,
mainReady,
renderMessageBody,
upsertMessage,
Layout,
IframeLogin,
iframeLogin,
fireGlobalEvent,
};
export { AdminBox } from './lib/AdminBox';
export { modal } from './lib/modal';
export { SideNav } from './lib/SideNav';
export { AccountBox } from './lib/AccountBox';
export { menu } from './lib/menu';
export { call } from './lib/callMethod';
export { erase, hide, leave } from './lib/ChannelActions';
export { MessageAction } from './lib/MessageAction';
export { messageBox } from './lib/messageBox';
export { popover } from './lib/popover';
export { readMessage } from './lib/readMessages';
export { RoomManager } from './lib/RoomManager';
export { upsertMessage, RoomHistoryManager } from './lib/RoomHistoryManager';
export { mainReady } from './lib/mainReady';
export { renderMessageBody } from './lib/renderMessageBody';
export { Layout } from './lib/Layout';
export { IframeLogin, iframeLogin } from './lib/IframeLogin';
export { fireGlobalEvent } from './lib/fireGlobalEvent';
export { getAvatarAsPng, updateAvatarOfUsername } from './lib/avatar';
export { TabBar } from './lib/TabBar';
export { RocketChatTabBar } from './lib/RocketChatTabBar';
export { popout } from './lib/popout';
export { messageProperties } from '../lib/MessageProperties';
export { MessageTypes } from '../lib/MessageTypes';
export { alerts } from './lib/alerts';

@ -0,0 +1,76 @@
import { ReactiveVar } from 'meteor/reactive-var';
import { Tracker } from 'meteor/tracker';
import { TabBar } from './TabBar';
export class RocketChatTabBar {
constructor() {
this.template = new ReactiveVar();
this.id = new ReactiveVar();
this.group = new ReactiveVar();
this.state = new ReactiveVar();
this.data = new ReactiveVar();
}
getTemplate() {
return this.template.get();
}
getId() {
return this.id.get();
}
setTemplate(template) {
this.template.set(template);
}
currentGroup() {
return this.group.get();
}
showGroup(group) {
this.group.set(group);
}
setData(d) {
this.data.set(d);
}
getData() {
return this.data.get();
}
getButtons() {
return TabBar.getButtons();
}
getState() {
return this.state.get();
}
open(button) {
this.state.set('opened');
Tracker.afterFlush(() => {
$('.contextual-bar__container').scrollTop(0).find('input[type=text]:first').focus();
});
if (!button) {
return;
}
if (typeof button !== 'object' || !button.id) {
button = TabBar.getButton(button);
}
$('.flex-tab, .contextual-bar').css('width', button.width ? `${ button.width }px` : '');
this.template.set(button.template);
this.id.set(button.id);
return button;
}
close() {
this.state.set('');
$('.flex-tab, .contextual-bar').css('width', '');
this.template.set();
this.id.set();
}
}

@ -5,6 +5,7 @@ import { Blaze } from 'meteor/blaze';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { Template } from 'meteor/templating';
import { roomTypes as _roomTypes } from 'meteor/rocketchat:utils';
import { fireGlobalEvent } from './fireGlobalEvent';
import { promises } from 'meteor/rocketchat:promises';
import { callbacks } from 'meteor/rocketchat:callbacks';
import { Notifications } from 'meteor/rocketchat:notifications';
@ -30,6 +31,7 @@ const onDeleteMessageBulkStream = ({ rid, ts, excludePinned, users }) => {
export const RoomManager = new function() {
const openedRooms = {};
let openedRoom = undefined; //eslint-disable-line
const msgStream = new Meteor.Streamer('room-messages');
const onlineUsers = new ReactiveVar({});
const Dep = new Tracker.Dependency();
@ -77,7 +79,7 @@ export const RoomManager = new function() {
callbacks.run('streamMessage', msg);
return window.fireGlobalEvent('new-message', msg);
return fireGlobalEvent('new-message', msg);
}
})
);

@ -0,0 +1,83 @@
import _ from 'underscore';
import { ReactiveVar } from 'meteor/reactive-var';
export const TabBar = new (class TabBar {
get size() {
return this._size.get();
}
set size(s) {
this._size.set(s);
}
constructor() {
this.buttons = new ReactiveVar({});
this._size = new ReactiveVar(4);
this.extraGroups = {};
}
show() {
$('.flex-tab-bar').show();
}
hide() {
$('.flex-tab-bar').hide();
}
addButton(config) {
if (!config || !config.id) {
return false;
}
const btns = this.buttons.curValue;
btns[config.id] = config;
if (this.extraGroups[config.id]) {
btns[config.id].groups = _.union((btns[config.id].groups || []), this.extraGroups[config.id]);
}
this.buttons.set(btns);
}
removeButton(id) {
const btns = this.buttons.curValue;
delete btns[id];
this.buttons.set(btns);
}
updateButton(id, config) {
const btns = this.buttons.curValue;
if (btns[id]) {
btns[id] = _.extend(btns[id], config);
this.buttons.set(btns);
}
}
getButtons() {
const buttons = _.toArray(this.buttons.get()).filter((button) => !button.condition || button.condition());
return _.sortBy(buttons, 'order');
}
getButton(id) {
return _.findWhere(this.buttons.get(), { id });
}
addGroup(id, groups) {
const btns = this.buttons.curValue;
if (btns[id]) {
btns[id].groups = _.union((btns[id].groups || []), groups);
this.buttons.set(btns);
} else {
this.extraGroups[id] = _.union((this.extraGroups[id] || []), groups);
}
}
removeGroup(id, groups) {
const btns = this.buttons.curValue;
if (btns[id]) {
btns[id].groups = _.difference((btns[id].groups || []), groups);
this.buttons.set(btns);
} else {
this.extraGroups[id] = _.difference((this.extraGroups[id] || []), groups);
}
}
});

@ -0,0 +1,73 @@
import './alerts.html';
import { Blaze } from 'meteor/blaze';
import { Template } from 'meteor/templating';
export const alerts = {
renderedAlert: null,
open(config) {
this.close(false);
config.closable = typeof(config.closable) === typeof(true) ? config.closable : true;
if (config.timer) {
this.timer = setTimeout(() => this.close(), config.timer);
}
this.renderedAlert = Blaze.renderWithData(Template.alerts, config, document.body, document.body.querySelector('#alert-anchor'));
},
close(dismiss = true) {
if (this.timer) {
clearTimeout(this.timer);
delete this.timer;
}
if (!this.renderedAlert) {
return false;
}
Blaze.remove(this.renderedAlert);
const { activeElement } = this.renderedAlert.dataVar.curValue;
if (activeElement) {
$(activeElement).removeClass('active');
}
dismiss && this.renderedAlert.dataVar.curValue.onClose && this.renderedAlert.dataVar.curValue.onClose();
},
};
Template.alerts.helpers({
hasAction() {
return Template.instance().data.action ? 'rc-alerts--has-action' : '';
},
modifiers() {
return (Template.instance().data.modifiers || []).map((mod) => `rc-alerts--${ mod }`).join(' ');
},
});
Template.alerts.onRendered(function() {
if (this.data.onRendered) {
this.data.onRendered();
}
});
Template.alerts.onDestroyed(function() {
if (this.data.onDestroyed) {
this.data.onDestroyed();
}
});
Template.alerts.events({
'click .js-action'(e, instance) {
if (!this.action) {
return;
}
this.action.call(this, e, instance.data.data);
},
'click .js-close'() {
alerts.close();
},
});
Template.alerts.helpers({
isSafariIos: /iP(ad|hone|od).+Version\/[\d\.]+.*Safari/i.test(navigator.userAgent),
});

@ -0,0 +1,39 @@
import { Blaze } from 'meteor/blaze';
import { Session } from 'meteor/session';
import { getAvatarUrlFromUsername } from 'meteor/rocketchat:utils';
import { RoomManager } from './RoomManager';
Blaze.registerHelper('avatarUrlFromUsername', getAvatarUrlFromUsername);
export const getAvatarAsPng = function(username, cb) {
const image = new Image;
image.src = getAvatarUrlFromUsername(username);
image.onload = function() {
const canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
const context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
try {
return cb(canvas.toDataURL('image/png'));
} catch (e) {
return cb('');
}
};
return image.onerror = function() {
return cb('');
};
};
export const updateAvatarOfUsername = function(username) {
const key = `avatar_random_${ username }`;
Session.set(key, Math.round(Math.random() * 1000));
Object.keys(RoomManager.openedRooms).forEach((key) => {
const room = RoomManager.openedRooms[key];
const url = getAvatarUrlFromUsername(username);
$(room.dom).find(`.message[data-username='${ username }'] .avatar-image`).css('background-image', `url(${ url })`);
});
return true;
};

@ -0,0 +1,211 @@
import './popout.html';
import { Blaze } from 'meteor/blaze';
import { ReactiveVar } from 'meteor/reactive-var';
import { Template } from 'meteor/templating';
import { callbacks } from 'meteor/rocketchat:callbacks';
export const popout = {
context: null,
isAudioOnly: false,
showVideoControls: true,
showStreamControls: false,
x: 0,
y: 0,
open(config = {}, fn) {
this.close();
this.context = Blaze.renderWithData(Template.popout, config, document.body);
this.fn = fn;
this.config = config;
this.onCloseCallback = config.onCloseCallback || null;
this.timer = null;
if (config.timer) {
this.timer = setTimeout(() => this.close(), config.timer);
}
if (config.data) {
this.isAudioOnly = config.data.isAudioOnly;
this.showVideoControls = config.data.showVideoControls;
this.showStreamControls = config.data.showStreamControls;
}
},
close() {
if (this.context) {
Blaze.remove(this.context);
}
this.context = null;
this.fn = null;
if (this.timer) {
clearTimeout(this.timer);
}
if (typeof(this.onCloseCallback) === 'function') {
this.onCloseCallback();
}
},
dragstart(event) {
if (!event.target.classList.contains('dropzone-overlay')) {
const popoutElement = document.querySelector('.rc-popout-wrapper');
setTimeout(function() {
popoutElement.style.display = 'none';
}, 0);
}
},
dragover(event) {
const e = event.originalEvent || event;
e.dataTransfer.dropEffect = 'move';
e.preventDefault();
},
dragend(event) {
if (!event.target.classList.contains('dropzone-overlay')) {
const popoutElement = document.querySelector('.rc-popout-wrapper');
popoutElement.style.display = 'initial';
}
},
drop(event) {
const e = event.originalEvent || event;
e.preventDefault();
// do not mess with the position if we are dropping files in the dropzone
if (!event.target.classList.contains('dropzone-overlay')) {
const popoutElement = document.querySelector('.rc-popout-wrapper');
const positionTop = e.clientY - popout.y;
const positionLeft = e.clientX - popout.x;
popoutElement.style.left = `${ positionLeft >= 0 ? positionLeft : 0 }px`;
popoutElement.style.top = `${ positionTop >= 0 ? positionTop : 0 }px`;
}
},
};
Template.popout.helpers({
state() {
return Template.instance().isMinimized.get() ? 'closed' : 'open';
},
isAudioOnly() {
return Template.instance().isAudioOnly.get();
},
isMuted() {
return Template.instance().isMuted.get();
},
isPlaying() {
return Template.instance().isPlaying.get();
},
showVideoControls() {
return Template.instance().showVideoControls.get();
},
showStreamControls() {
return Template.instance().showStreamControls.get();
},
getStreamStatus() {
return Template.instance().streamStatus.get();
},
});
Template.popout.onRendered(function() {
Template.instance().isMinimized.set(popout.isAudioOnly);
Template.instance().isAudioOnly.set(popout.isAudioOnly);
Template.instance().showVideoControls.set(popout.showVideoControls);
Template.instance().showStreamControls.set(popout.showStreamControls);
if (this.data.onRendered) {
this.data.onRendered();
}
});
Template.popout.onCreated(function() {
this.isMinimized = new ReactiveVar(popout.isAudioOnly);
this.isAudioOnly = new ReactiveVar(popout.isAudioOnly);
this.canOpenExternal = new ReactiveVar(popout.canOpenExternal);
this.showVideoControls = new ReactiveVar(popout.showVideoControls);
this.showStreamControls = new ReactiveVar(popout.showStreamControls);
this.isMuted = new ReactiveVar(false);
this.isPlaying = new ReactiveVar(true);
this.streamStatus = new ReactiveVar('preparing');
document.body.addEventListener('dragstart', popout.dragstart, true);
document.body.addEventListener('dragover', popout.dragover, true);
document.body.addEventListener('dragend', popout.dragend, true);
document.body.addEventListener('drop', popout.drop, true);
});
Template.popout.onDestroyed(function() {
popout.context = null;
document.body.removeEventListener('dragstart', popout.dragstart, true);
document.body.removeEventListener('dragover', popout.dragover, true);
document.body.removeEventListener('dragend', popout.dragend, true);
document.body.removeEventListener('drop', popout.drop, true);
});
Template.popout.events({
'click .js-action'(e, instance) {
!this.action || this.action.call(instance.data.data, e, instance);
e.stopPropagation();
popout.close();
},
'click .js-close'(e) {
e.stopPropagation();
popout.close();
},
'click .js-minimize'(e, i) {
e.stopPropagation();
if (i.isMinimized.get()) {
i.isMinimized.set(false);
window.liveStreamPlayer.setSize(380, 214);
} else {
i.isMinimized.set(true);
window.liveStreamPlayer.setSize(0, 0);
}
},
'dragstart .rc-popout-wrapper'(event) {
const e = event.originalEvent || event;
const url = (this.data && this.data.streamingSource) || '.rc-popout-wrapper';
popout.x = e.offsetX;
popout.y = e.offsetY;
e.dataTransfer.setData('application/x-moz-node', e.currentTarget);
e.dataTransfer.setData('text/plain', url);
e.dataTransfer.effectAllowed = 'move';
},
'dragend .rc-popout-wrapper'(event) {
event.preventDefault();
},
'click .rc-popout__controls--record'(e, i) {
e.preventDefault();
if (i.streamStatus.get() === 'ready') {
document.querySelector('.streaming-popup').dispatchEvent(new Event('startStreaming'));
i.streamStatus.set('starting');
} else if (i.streamStatus.get() === 'broadcasting') {
document.querySelector('.streaming-popup').dispatchEvent(new Event('stopStreaming'));
i.streamStatus.set('finished');
setTimeout(() => popout && popout.close(), 2000);
}
},
'broadcastStreamReady .streaming-popup'(e, i) {
e.preventDefault();
i.streamStatus.set('ready');
},
'broadcastStream .streaming-popup'(e, i) {
e.preventDefault();
i.streamStatus.set('broadcasting');
},
'click .rc-popout__controls--play'(e, i) {
window.liveStreamPlayer.playVideo();
i.isPlaying.set(true);
},
'click .rc-popout__controls--pause'(e, i) {
window.liveStreamPlayer.pauseVideo();
i.isPlaying.set(false);
},
'click .rc-popout__controls--mute'(e, i) {
window.liveStreamPlayer.mute();
i.isMuted.set(true);
},
'click .rc-popout__controls--unmute'(e, i) {
window.liveStreamPlayer.unMute();
i.isMuted.set(false);
},
'playerStateChanged .rc-popout'(e, i) {
if (e.detail === window.YT.PlayerState.PLAYING) {
i.isPlaying.set(true);
} else if (e.detail === window.YT.PlayerState.PAUSED) {
i.isPlaying.set(false);
}
},
});
callbacks.add('afterLogoutCleanUp', () => popout.close(), callbacks.priority.MEDIUM, 'popout-close-after-logout-cleanup');

@ -0,0 +1,16 @@
import { emoji } from 'meteor/rocketchat:emoji';
import GraphemeSplitter from 'grapheme-splitter';
const splitter = new GraphemeSplitter();
export const messageProperties = {
length: ((message) => splitter.countGraphemes(message)),
messageWithoutEmojiShortnames: ((message) => message.replace(/:\w+:/gm, (match) => {
if (emoji.list[match] !== undefined) {
return ' ';
}
return match;
})),
};

@ -0,0 +1,19 @@
export const MessageTypes = new class {
constructor() {
this.types = {};
}
registerType(options) {
return this.types[options.id] = options;
}
getType(message) {
return this.types[message && message.t];
}
isSystemMessage(message) {
const type = this.types[message && message.t];
return type && type.system;
}
};

@ -20,6 +20,8 @@ Package.onUse(function(api) {
'rocketchat:streamer',
'rocketchat:models',
'rocketchat:lazy-load',
'rocketchat:emoji',
]);
api.mainModule('client/index.js', 'client');
api.mainModule('server/index.js', 'server');
});

@ -0,0 +1,2 @@
export { messageProperties } from '../lib/MessageProperties';
export { MessageTypes } from '../lib/MessageTypes';

@ -0,0 +1,8 @@
import mock from 'mock-require';
mock('meteor/rocketchat:emoji', {
emoji: {
list: {
},
},
});

@ -0,0 +1,22 @@
/* eslint-env mocha */
import 'babel-polyfill';
import assert from 'assert';
import './server.mocks.js';
import { messageProperties } from '../lib/MessageProperties';
const messages = {
'Sample Message': 14,
'Sample 1 ⛳': 10,
'Sample 2 ❤': 10,
'Sample 3 ⛳❤⛳❤': 13,
};
describe('Message Properties', () => {
describe('Check Message Length', () => {
Object.keys(messages).forEach((objectKey) => {
it('should treat emojis as single characters', () => {
assert.equal(messageProperties.length(objectKey), messages[objectKey]);
});
});
});
});

@ -1,37 +1,7 @@
import { Blaze } from 'meteor/blaze';
import { Session } from 'meteor/session';
import { getAvatarAsPng, updateAvatarOfUsername as _updateAvatarOfUsername } from 'meteor/rocketchat:ui-utils';
Blaze.registerHelper('avatarUrlFromUsername', getAvatarUrlFromUsername);
export const getAvatarAsPng = function(username, cb) {
const image = new Image;
image.src = getAvatarUrlFromUsername(username);
image.onload = function() {
const canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
const context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
try {
return cb(canvas.toDataURL('image/png'));
} catch (e) {
return cb('');
}
};
return image.onerror = function() {
return cb('');
};
export {
getAvatarAsPng,
};
updateAvatarOfUsername = function(username) {
const key = `avatar_random_${ username }`;
Session.set(key, Math.round(Math.random() * 1000));
Object.keys(RoomManager.openedRooms).forEach((key) => {
const room = RoomManager.openedRooms[key];
const url = getAvatarUrlFromUsername(username);
$(room.dom).find(`.message[data-username='${ username }'] .avatar-image`).css('background-image', `url(${ url })`);
});
return true;
};
updateAvatarOfUsername = _updateAvatarOfUsername;

@ -1,72 +1,3 @@
import { Blaze } from 'meteor/blaze';
import { Template } from 'meteor/templating';
import { alerts as _alerts } from 'meteor/rocketchat:ui-utils';
alerts = {
renderedAlert: null,
open(config) {
this.close(false);
config.closable = typeof(config.closable) === typeof(true) ? config.closable : true;
if (config.timer) {
this.timer = setTimeout(() => this.close(), config.timer);
}
this.renderedAlert = Blaze.renderWithData(Template.alerts, config, document.body, document.body.querySelector('#alert-anchor'));
},
close(dismiss = true) {
if (this.timer) {
clearTimeout(this.timer);
delete this.timer;
}
if (!this.renderedAlert) {
return false;
}
Blaze.remove(this.renderedAlert);
const { activeElement } = this.renderedAlert.dataVar.curValue;
if (activeElement) {
$(activeElement).removeClass('active');
}
dismiss && this.renderedAlert.dataVar.curValue.onClose && this.renderedAlert.dataVar.curValue.onClose();
},
};
Template.alerts.helpers({
hasAction() {
return Template.instance().data.action ? 'rc-alerts--has-action' : '';
},
modifiers() {
return (Template.instance().data.modifiers || []).map((mod) => `rc-alerts--${ mod }`).join(' ');
},
});
Template.alerts.onRendered(function() {
if (this.data.onRendered) {
this.data.onRendered();
}
});
Template.alerts.onDestroyed(function() {
if (this.data.onDestroyed) {
this.data.onDestroyed();
}
});
Template.alerts.events({
'click .js-action'(e, instance) {
if (!this.action) {
return;
}
this.action.call(this, e, instance.data.data);
},
'click .js-close'() {
alerts.close();
},
});
Template.alerts.helpers({
isSafariIos: /iP(ad|hone|od).+Version\/[\d\.]+.*Safari/i.test(navigator.userAgent),
});
alerts = _alerts;

@ -1,209 +1,3 @@
import { Blaze } from 'meteor/blaze';
import { ReactiveVar } from 'meteor/reactive-var';
import { Template } from 'meteor/templating';
import { popout as _popout } from 'meteor/rocketchat:ui-utils';
popout = {
context: null,
isAudioOnly: false,
showVideoControls: true,
showStreamControls: false,
x: 0,
y: 0,
open(config = {}, fn) {
this.close();
this.context = Blaze.renderWithData(Template.popout, config, document.body);
this.fn = fn;
this.config = config;
this.onCloseCallback = config.onCloseCallback || null;
this.timer = null;
if (config.timer) {
this.timer = setTimeout(() => this.close(), config.timer);
}
if (config.data) {
this.isAudioOnly = config.data.isAudioOnly;
this.showVideoControls = config.data.showVideoControls;
this.showStreamControls = config.data.showStreamControls;
}
},
close() {
if (this.context) {
Blaze.remove(this.context);
}
this.context = null;
this.fn = null;
if (this.timer) {
clearTimeout(this.timer);
}
if (typeof(this.onCloseCallback) === 'function') {
this.onCloseCallback();
}
},
dragstart(event) {
if (!event.target.classList.contains('dropzone-overlay')) {
const popoutElement = document.querySelector('.rc-popout-wrapper');
setTimeout(function() {
popoutElement.style.display = 'none';
}, 0);
}
},
dragover(event) {
const e = event.originalEvent || event;
e.dataTransfer.dropEffect = 'move';
e.preventDefault();
},
dragend(event) {
if (!event.target.classList.contains('dropzone-overlay')) {
const popoutElement = document.querySelector('.rc-popout-wrapper');
popoutElement.style.display = 'initial';
}
},
drop(event) {
const e = event.originalEvent || event;
e.preventDefault();
// do not mess with the position if we are dropping files in the dropzone
if (!event.target.classList.contains('dropzone-overlay')) {
const popoutElement = document.querySelector('.rc-popout-wrapper');
const positionTop = e.clientY - popout.y;
const positionLeft = e.clientX - popout.x;
popoutElement.style.left = `${ positionLeft >= 0 ? positionLeft : 0 }px`;
popoutElement.style.top = `${ positionTop >= 0 ? positionTop : 0 }px`;
}
},
};
Template.popout.helpers({
state() {
return Template.instance().isMinimized.get() ? 'closed' : 'open';
},
isAudioOnly() {
return Template.instance().isAudioOnly.get();
},
isMuted() {
return Template.instance().isMuted.get();
},
isPlaying() {
return Template.instance().isPlaying.get();
},
showVideoControls() {
return Template.instance().showVideoControls.get();
},
showStreamControls() {
return Template.instance().showStreamControls.get();
},
getStreamStatus() {
return Template.instance().streamStatus.get();
},
});
Template.popout.onRendered(function() {
Template.instance().isMinimized.set(popout.isAudioOnly);
Template.instance().isAudioOnly.set(popout.isAudioOnly);
Template.instance().showVideoControls.set(popout.showVideoControls);
Template.instance().showStreamControls.set(popout.showStreamControls);
if (this.data.onRendered) {
this.data.onRendered();
}
});
Template.popout.onCreated(function() {
this.isMinimized = new ReactiveVar(popout.isAudioOnly);
this.isAudioOnly = new ReactiveVar(popout.isAudioOnly);
this.canOpenExternal = new ReactiveVar(popout.canOpenExternal);
this.showVideoControls = new ReactiveVar(popout.showVideoControls);
this.showStreamControls = new ReactiveVar(popout.showStreamControls);
this.isMuted = new ReactiveVar(false);
this.isPlaying = new ReactiveVar(true);
this.streamStatus = new ReactiveVar('preparing');
document.body.addEventListener('dragstart', popout.dragstart, true);
document.body.addEventListener('dragover', popout.dragover, true);
document.body.addEventListener('dragend', popout.dragend, true);
document.body.addEventListener('drop', popout.drop, true);
});
Template.popout.onDestroyed(function() {
popout.context = null;
document.body.removeEventListener('dragstart', popout.dragstart, true);
document.body.removeEventListener('dragover', popout.dragover, true);
document.body.removeEventListener('dragend', popout.dragend, true);
document.body.removeEventListener('drop', popout.drop, true);
});
Template.popout.events({
'click .js-action'(e, instance) {
!this.action || this.action.call(instance.data.data, e, instance);
e.stopPropagation();
popout.close();
},
'click .js-close'(e) {
e.stopPropagation();
popout.close();
},
'click .js-minimize'(e, i) {
e.stopPropagation();
if (i.isMinimized.get()) {
i.isMinimized.set(false);
window.liveStreamPlayer.setSize(380, 214);
} else {
i.isMinimized.set(true);
window.liveStreamPlayer.setSize(0, 0);
}
},
'dragstart .rc-popout-wrapper'(event) {
const e = event.originalEvent || event;
const url = (this.data && this.data.streamingSource) || '.rc-popout-wrapper';
popout.x = e.offsetX;
popout.y = e.offsetY;
e.dataTransfer.setData('application/x-moz-node', e.currentTarget);
e.dataTransfer.setData('text/plain', url);
e.dataTransfer.effectAllowed = 'move';
},
'dragend .rc-popout-wrapper'(event) {
event.preventDefault();
},
'click .rc-popout__controls--record'(e, i) {
e.preventDefault();
if (i.streamStatus.get() === 'ready') {
document.querySelector('.streaming-popup').dispatchEvent(new Event('startStreaming'));
i.streamStatus.set('starting');
} else if (i.streamStatus.get() === 'broadcasting') {
document.querySelector('.streaming-popup').dispatchEvent(new Event('stopStreaming'));
i.streamStatus.set('finished');
setTimeout(() => popout && popout.close(), 2000);
}
},
'broadcastStreamReady .streaming-popup'(e, i) {
e.preventDefault();
i.streamStatus.set('ready');
},
'broadcastStream .streaming-popup'(e, i) {
e.preventDefault();
i.streamStatus.set('broadcasting');
},
'click .rc-popout__controls--play'(e, i) {
window.liveStreamPlayer.playVideo();
i.isPlaying.set(true);
},
'click .rc-popout__controls--pause'(e, i) {
window.liveStreamPlayer.pauseVideo();
i.isPlaying.set(false);
},
'click .rc-popout__controls--mute'(e, i) {
window.liveStreamPlayer.mute();
i.isMuted.set(true);
},
'click .rc-popout__controls--unmute'(e, i) {
window.liveStreamPlayer.unMute();
i.isMuted.set(false);
},
'playerStateChanged .rc-popout'(e, i) {
if (e.detail === window.YT.PlayerState.PLAYING) {
i.isPlaying.set(true);
} else if (e.detail === window.YT.PlayerState.PAUSED) {
i.isPlaying.set(false);
}
},
});
RocketChat.callbacks.add('afterLogoutCleanUp', () => popout.close(), RocketChat.callbacks.priority.MEDIUM, 'popout-close-after-logout-cleanup');
popout = _popout;

@ -672,7 +672,7 @@ Template.room.events({
'click .new-message'() {
Template.instance().atBottom = true;
chatMessages[RocketChat.openedRoom].input.focus();
chatMessages[RoomManager.openedRoom].input.focus();
},
'click .message-actions__menu'(e, i) {
let context = $(e.target).parents('.message').data('context');

@ -97,8 +97,6 @@ Package.onUse(function(api) {
api.addFiles('client/views/app/notAuthorized.html', 'client');
api.addFiles('client/views/app/pageContainer.html', 'client');
api.addFiles('client/views/app/pageSettingsContainer.html', 'client');
api.addFiles('client/views/app/popout.html', 'client');
api.addFiles('client/views/app/alerts.html', 'client');
api.addFiles('client/views/app/room.html', 'client');
api.addFiles('client/views/app/roomSearch.html', 'client');

Loading…
Cancel
Save