Skip to content
Snippets Groups Projects
Commit 5a33ba35 authored by nokobon's avatar nokobon
Browse files

Modify package rocketchat-emojione to use rocketchat-emoji-base

parent 9510ff1d
No related branches found
Tags 0.56.0-rc.4
No related merge requests found
/* globals Template */
Template.messageBox.events({
'click .emoji-picker-icon'(event) {
event.stopPropagation();
if (RocketChat.EmojiPicker.isOpened()) {
RocketChat.EmojiPicker.close();
} else {
RocketChat.EmojiPicker.open(event.currentTarget, (emoji) => {
const input = $(event.currentTarget).parent().parent().find('.input-message');
let emojiValue = ':' + emoji + ':';
var caretPos = input.prop('selectionStart');
var textAreaTxt = input.val();
input.val(textAreaTxt.substring(0, caretPos) + emojiValue + textAreaTxt.substring(caretPos));
input.focus();
input.prop('selectionStart', caretPos + emojiValue.length);
input.prop('selectionEnd', caretPos + emojiValue.length);
});
}
}
});
Template.messageBox.onCreated(function() {
RocketChat.EmojiPicker.init();
});
<template name="emojiPicker">
<div class="emoji-picker">
<div class="filter">
<ul>
{{#each category}}
<li class="{{activeCategory .}}" title="{{categoryName .}}">
<a href="#{{.}}" class="category-link"><i class="icon-{{.}}"></i></a>
</li>
{{/each}}
<li class="change-tone">
<a href="#change-tone"><span class="current-tone {{currentTone}}"></span></a>
<ul class="tone-selector">
<li><a href="#tone" class="tone" data-tone="0"><span class="tone-0"></span></a></li>
<li><a href="#tone" class="tone" data-tone="1"><span class="tone-1"></span></a></li>
<li><a href="#tone" class="tone" data-tone="2"><span class="tone-2"></span></a></li>
<li><a href="#tone" class="tone" data-tone="3"><span class="tone-3"></span></a></li>
<li><a href="#tone" class="tone" data-tone="4"><span class="tone-4"></span></a></li>
<li><a href="#tone" class="tone" data-tone="5"><span class="tone-5"></span></a></li>
</ul>
</li>
</ul>
</div>
<form class="emoji-filter input-line search search-form">
<input type="text" class="search" placeholder="{{_ 'Search Emoji'}}" autocomplete="off">
<i class="icon-right-open-small"></i>
</form>
<h2 class="current-category-header">
{{ currentCategory }}
</h2>
<div class="emojis">
{{#each category}}
<ul class="{{.}} emoji-list {{isVisible .}}">
{{{emojiList .}}}
</ul>
{{/each}}
</div>
</div>
</template>
/* globals Template, emojione */ /* globals emojisByCategory:true, emojiCategories:true, toneList:true */
var emojisByCategory;
var toneList;
/* /*
* Mapping category hashes into human readable and translated names * Mapping category hashes into human readable and translated names
*/ */
var emojiCategories = { emojiCategories = {
recent: TAPi18n.__('Frequently_Used'),
people: TAPi18n.__('Smileys_and_People'), people: TAPi18n.__('Smileys_and_People'),
nature: TAPi18n.__('Animals_and_Nature'), nature: TAPi18n.__('Animals_and_Nature'),
food: TAPi18n.__('Food_and_Drink'), food: TAPi18n.__('Food_and_Drink'),
...@@ -18,216 +14,6 @@ var emojiCategories = { ...@@ -18,216 +14,6 @@ var emojiCategories = {
flags: TAPi18n.__('Flags') flags: TAPi18n.__('Flags')
}; };
/**
* Turns category hash to a nice readable translated name
* @param {string} category hash
* @return {string} readable and translated
*/
function categoryName(category) {
if (emojiCategories[category]) {
return emojiCategories[category];
}
// unknown category; better hash than nothing
return category;
}
function getEmojisByCategory(category) {
const t = Template.instance();
const total = emojisByCategory[category].length;
let html = '';
const actualTone = t.tone;
for (var i = 0; i < total; i++) {
let emoji = emojisByCategory[category][i];
let tone = '';
if (actualTone > 0 && toneList.hasOwnProperty(emoji)) {
tone = '_tone' + actualTone;
}
const image = emojione.toImage(':' + emoji + tone + ':');
html += `<li class="emoji-${emoji}" data-emoji="${emoji}" title="${emoji}">${image}</li>`;
}
return html;
}
function getEmojisBySearchTerm(searchTerm) {
let html = '';
const actualTone = t.tone;
for (let category of Object.keys(emojisByCategory)) {
if (category !== 'recent') {
for (let emoji of emojisByCategory[category]) {
if (emoji.indexOf(searchTerm.toLowerCase()) > -1) {
let tone = '';
if (actualTone > 0 && toneList.hasOwnProperty(emoji)) {
tone = '_tone' + actualTone;
}
const image = emojione.toImage(':' + emoji + tone + ':');
html += `<li class="emoji-${emoji}" data-emoji="${emoji}" title="${emoji}">${image}</li>`;
}
}
}
}
return html;
}
Template.emojiPicker.helpers({
category() {
return Object.keys(emojisByCategory);
},
emojiByCategory(category) {
if (!emojisByCategory[category]) {
return [];
}
return emojisByCategory[category];
},
isVisible(category) {
return Template.instance().currentCategory.get() === category ? 'visible' : '';
},
emojiList(category) {
const t = Template.instance();
const searchTerm = t.currentSearchTerm.get();
if (searchTerm.length > 0) {
return getEmojisBySearchTerm(searchTerm);
} else {
return getEmojisByCategory(category);
}
},
currentTone() {
return 'tone-' + Template.instance().tone;
},
/**
* Returns true if a given emoji category is active
*
* @param {string} category hash
* @return {boolean} true if active, false otherwise
*/
activeCategory(category) {
return Template.instance().currentCategory.get() === category ? 'active' : '';
},
categoryName: categoryName,
/**
* Returns currently active emoji category hash
*
* @return {string} category hash
*/
currentCategory() {
const t = Template.instance();
const hash = t.currentCategory.get();
const searchTerm = t.currentSearchTerm.get();
if (searchTerm.length > 0) {
return TAPi18n.__('Search');
} else {
return categoryName(hash);
}
}
});
Template.emojiPicker.events({
'click .emoji-picker'(event) {
event.stopPropagation();
event.preventDefault();
},
'click .category-link'(event, instance) {
event.stopPropagation();
event.preventDefault();
instance.currentCategory.set(event.currentTarget.hash.substr(1));
return false;
},
'click .change-tone > a'(event, instance) {
event.stopPropagation();
event.preventDefault();
instance.$('.tone-selector').toggleClass('show');
},
'click .tone-selector .tone'(event, instance) {
event.stopPropagation();
event.preventDefault();
let tone = parseInt(event.currentTarget.dataset.tone);
let newTone;
if (tone > 0) {
newTone = '_tone' + tone;
} else {
newTone = '';
}
for (var emoji in toneList) {
if (toneList.hasOwnProperty(emoji)) {
$('.emoji-'+emoji).html(emojione.toImage(':' + emoji + newTone + ':'));
}
}
RocketChat.EmojiPicker.setTone(tone);
instance.setCurrentTone(tone);
$('.tone-selector').toggleClass('show');
},
'click .emoji-list li'(event, instance) {
event.stopPropagation();
let emoji = event.currentTarget.dataset.emoji;
let actualTone = instance.tone;
let tone = '';
if (actualTone > 0 && toneList.hasOwnProperty(emoji)) {
tone = '_tone' + actualTone;
}
const input = $('.emoji-filter input.search');
if (input) {
input.val('');
}
instance.currentSearchTerm.set('');
RocketChat.EmojiPicker.pickEmoji(emoji + tone);
},
'keydown .emoji-filter .search'(event) {
if (event.keyCode === 13) {
event.preventDefault();
}
},
'keyup .emoji-filter .search'(event, instance) {
const value = event.target.value.trim();
const cst = instance.currentSearchTerm;
if (value === cst.get()) {
return;
}
cst.set(value);
}
});
Template.emojiPicker.onCreated(function() {
this.tone = RocketChat.EmojiPicker.getTone();
let recent = RocketChat.EmojiPicker.getRecent();
this.currentCategory = new ReactiveVar(recent.length > 0 ? 'recent' : 'people');
this.currentSearchTerm = new ReactiveVar('');
recent.forEach((emoji) => {
emojisByCategory.recent.push(emoji);
});
this.setCurrentTone = (newTone) => {
$('.current-tone').removeClass('tone-' + this.tone);
$('.current-tone').addClass('tone-' + newTone);
this.tone = newTone;
};
});
toneList = { toneList = {
'raised_hands': 1, 'raised_hands': 1,
'clap': 1, 'clap': 1,
...@@ -315,7 +101,6 @@ toneList = { ...@@ -315,7 +101,6 @@ toneList = {
'juggling': 1 'juggling': 1
}; };
emojisByCategory = { emojisByCategory = {
'recent': [],
'people': [ 'people': [
'grinning', 'grinning',
'grimacing', 'grimacing',
...@@ -1746,3 +1531,5 @@ emojisByCategory = { ...@@ -1746,3 +1531,5 @@ emojisByCategory = {
'tone5' 'tone5'
] ]
}; };
/* exported emojisByCategory, emojiCategories, toneList */
.emoji-picker-icon {
cursor: pointer;
font-size: 18px;
color: @info-font-color;
&:before {
.transition(transform 0.2s ease);
}
&:hover {
&:before {
.transform(scale(1.2));
}
}
}
.emoji-picker {
width: 100%;
max-width: 365px;
background-color: @secondary-background-color;
border-radius: 5px;
box-shadow: 0px 1px 1px 0 rgba(0,0,0,0.2), 0 2px 10px 0 rgba(0,0,0,.16);
position: absolute;
z-index: 200;
.transition(transform 0.2s ease, visibility 0.2s ease, opacity 0.2s ease);
.transform(translateY(30px));
opacity: 0;
visibility: hidden;
&.show {
.transform(translateY(0px));
opacity: 1;
display: block;
visibility: visible;
}
.filter {
text-align: center;
box-shadow: 0px 2px 2px -1px rgba(0,0,0,0.2);
> ul {
display: table;
width: 100%;
> li {
display: table-cell;
margin: 0 2px;
padding: 6px 0;
border-bottom: 2px solid @secondary-background-color;
.category-link {
i {
color: @info-font-color;
font-size: 24px;
}
}
&:hover {
border-bottom: 2px solid @info-font-color;
}
&.active {
border-bottom: 2px solid @primary-background-color;
}
&.change-tone {
opacity: 1;
border-bottom: 2px solid transparent;
> a {
position: relative;
z-index: 10;
}
.current-tone {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 10px;
}
.tone-selector {
position: absolute;
background-color: @secondary-background-color;
border-radius: 4px;
box-shadow: 0px 1px 1px 0 rgba(0,0,0,0.2), 0 2px 10px 0 rgba(0,0,0,.16);
padding: 4px 2px;
margin-left: -4px;
z-index: 8;
.transition(transform 0.2s ease, visibility 0.2s ease, opacity 0.2s ease);
.transform(translateY(-20px));
opacity: 0;
visibility: hidden;
&.show {
.transform(translateY(0px));
opacity: 1;
display: block;
visibility: visible;
}
li {
display: block;
padding: 0 4px;
}
span {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 10px;
.transition(transform 0.2s ease);
}
}
.tone-0 {
background-color: #ffcf11;
}
.tone-1 {
background-color: #fae3c3;
}
.tone-2 {
background-color: #e2cfa1;
}
.tone-3 {
background-color: #dba373;
}
.tone-4 {
background-color: #a88054;
}
.tone-5 {
background-color: #5f4e43;
}
}
}
}
}
.current-category-header {
padding: 3px 6px 2px 6px;
}
.emojis {
height: 160px;
overflow-y: auto;
padding: 3px 0px 0px 2px;
.custom-scroll(transparent, #DDD);
.emoji-list {
display: none;
li {
display: inline-block;
margin: 2px;
padding: 4px 2px 2px 2px;
border-radius: 4px;
cursor: pointer;
.transition(transform 0.2s ease);
&:hover {
.transform(scale(1.2));
background-color: #DDD;
}
}
&.visible {
display: block;
}
}
}
}
###
# Emojione is a named function that will replace emojis
# @param {Object} message - The message object
###
class Emojione
constructor: (message) ->
if _.trim message.html
message.html = emojione.toImage(message.html)
return message
RocketChat.callbacks.add 'renderMessage', Emojione, RocketChat.callbacks.priority.LOW, 'emoji'
if Meteor.isClient
Meteor.startup ->
Tracker.autorun ->
if Meteor.user()?.settings?.preferences?.useEmojis or not Meteor.user()?.settings?.preferences?.useEmojis?
RocketChat.callbacks.add 'renderMessage', Emojione, RocketChat.callbacks.priority.LOW, 'emoji'
else
RocketChat.callbacks.remove 'renderMessage', 'emoji'
\ No newline at end of file
/* globals emojione, Blaze, Template */
RocketChat.EmojiPicker = {
width: 390,
height: 238,
initiated: false,
input: null,
source: null,
recent: [],
tone: null,
opened: false,
pickCallback: null,
init() {
if (this.initiated) {
return;
}
this.initiated = true;
this.recent = window.localStorage.getItem('emoji.recent') ? window.localStorage.getItem('emoji.recent').split(',') : [];
this.tone = window.localStorage.getItem('emoji.tone') || 0;
Blaze.render(Template.emojiPicker, document.body);
$(document).click((event) => {
if (!this.opened) {
return;
}
if (!$(event.target).closest('.emoji-picker').length && !$(event.target).is('.emoji-picker')) {
if (this.opened) {
this.close();
}
}
});
$(window).resize(_.debounce(() => {
if (!this.opened) {
return;
}
this.setPosition();
}, 300));
},
isOpened() {
return this.opened;
},
setTone(tone) {
this.tone = tone;
window.localStorage.setItem('emoji.tone', tone);
},
getTone() {
return this.tone;
},
getRecent() {
return this.recent;
},
setPosition() {
let sourcePos = $(this.source).offset();
let left = (sourcePos.left - this.width + 65);
let top = (sourcePos.top - this.height - 5);
if (left < 0) {
left = 10;
}
if (top < 0) {
top = 10;
}
return $('.emoji-picker')
.css({
top: top + 'px',
left: left + 'px'
});
},
open(source, callback) {
if (!this.initiated) {
this.init();
}
this.pickCallback = callback;
this.source = source;
const containerEl = this.setPosition();
containerEl.addClass('show');
setTimeout(() => {
const emojiInput = containerEl.find('.emoji-filter input.search');
if (emojiInput) {
emojiInput.focus();
}
}, 100);
this.opened = true;
},
close() {
$('.emoji-picker').removeClass('show');
this.opened = false;
},
pickEmoji(emoji) {
this.pickCallback(emoji);
this.close();
this.addRecent(emoji);
},
addRecent(emoji) {
let pos = this.recent.indexOf(emoji);
if (pos !== -1) {
this.recent.splice(pos, 1);
}
this.recent.unshift(emoji);
window.localStorage.setItem('emoji.recent', this.recent);
this.updateRecent();
},
updateRecent() {
let total = this.recent.length;
var html = '';
for (var i = 0; i < total; i++) {
let emoji = this.recent[i];
let tone = '';
html += '<li class="emoji-' + emoji + '" data-emoji="' + emoji + '">' + emojione.toImage(':' + emoji + tone + ':') + '</li>';
}
$('.recent.emoji-list').html(html);
}
};
RocketChat.theme.addPackageAsset(function() {
return Assets.getText('emojiPicker.less');
});
...@@ -9,29 +9,15 @@ Package.onUse(function(api) { ...@@ -9,29 +9,15 @@ Package.onUse(function(api) {
api.versionsFrom('1.0'); api.versionsFrom('1.0');
api.use([ api.use([
'coffeescript',
'emojione:emojione', 'emojione:emojione',
'rocketchat:emoji-base',
'rocketchat:lib' 'rocketchat:lib'
]); ]);
api.use('rocketchat:theme');
api.use('rocketchat:ui-message');
api.use('reactive-var');
api.use('templating');
api.use('ecmascript'); api.use('ecmascript');
api.use('less@2.5.1');
api.addFiles('emojione.coffee', ['server', 'client']);
api.addFiles('rocketchat.coffee', 'client');
api.addFiles('emojiPicker.html', 'client');
api.addFiles('emojiPicker.js', 'client'); api.addFiles('emojiPicker.js', 'client');
api.addAssets('emojiPicker.less', 'server'); api.addFiles('rocketchat.js', 'client');
api.addFiles('loadStylesheet.js', 'server');
api.addFiles('lib/EmojiPicker.js', 'client');
api.addFiles('emojiButton.js', 'client');
api.addFiles('sprites.css', 'client'); api.addFiles('sprites.css', 'client');
}); });
# RocketChat.emoji should be set to an object representing the emoji package used
RocketChat.emoji = emojione
RocketChat.emoji.imageType = 'png';
RocketChat.emoji.sprites = true;
# RocketChat.emoji.list is the collection of emojis
RocketChat.emoji.list = emojione.emojioneList
# RocketChat.emoji.class is the name of the registered class for emojis
RocketChat.emoji.class = 'Emojione'
# Additional settings -- ascii emojis
Meteor.startup ->
Tracker.autorun ->
emojione?.ascii = if Meteor.user()?.settings?.preferences?.convertAsciiEmoji? then Meteor.user().settings.preferences.convertAsciiEmoji else true
/* globals emojione, emojisByCategory, emojiCategories, toneList */
RocketChat.emoji.packages.emojione = emojione;
RocketChat.emoji.packages.emojione.imageType = 'png';
RocketChat.emoji.packages.emojione.sprites = true;
RocketChat.emoji.packages.emojione.emojisByCategory = emojisByCategory;
RocketChat.emoji.packages.emojione.emojiCategories = emojiCategories;
RocketChat.emoji.packages.emojione.toneList = toneList;
RocketChat.emoji.packages.emojione.render = function(emoji) {
return emojione.toImage(emoji);
};
//http://stackoverflow.com/a/26990347 function isSet() from Gajus
function isSetNotNull(fn) {
var value;
try {
value = fn();
} catch (e) {
value = null;
} finally {
return value !== null && value !== undefined;
}
}
// RocketChat.emoji.list is the collection of emojis from all emoji packages
for (let key in emojione.emojioneList) {
if (emojione.emojioneList.hasOwnProperty(key)) {
let emoji = emojione.emojioneList[key];
emoji.emojiPackage = 'emojione';
RocketChat.emoji.list[key] = emoji;
}
}
// Additional settings -- ascii emojis
Meteor.startup(function() {
Tracker.autorun(function() {
if (isSetNotNull(() => RocketChat.emoji.packages.emojione)) {
if (isSetNotNull(() => Meteor.user().settings.preferences.convertAsciiEmoji)) {
RocketChat.emoji.packages.emojione.ascii = Meteor.user().settings.preferences.convertAsciiEmoji;
} else {
RocketChat.emoji.packages.emojione.ascii = true;
}
}
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment