Skip to content

Commit

Permalink
Update for Flarum beta 14 and dynamically load library
Browse files Browse the repository at this point in the history
  • Loading branch information
clarkwinkelmann committed Nov 16, 2020
1 parent 9b9761a commit 91737d5
Show file tree
Hide file tree
Showing 16 changed files with 1,229 additions and 1,568 deletions.
3 changes: 1 addition & 2 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
MIT License

Copyright (c) 2017-2019 Clark Winkelmann
Copyright (c) 2015-2017 Andrey Izman <[email protected]> (copyright owner of the emojionearea code in the js/dist folder)
Copyright (c) 2017-2020 Clark Winkelmann

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Flarum Emoji Picker
# EmojiOne Area for Flarum

[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/clarkwinkelmann/flarum-ext-emojionearea/master/LICENSE.txt) [![Packagist](https://img.shields.io/packagist/v/clarkwinkelmann/flarum-ext-emojionearea.svg)](https://packagist.org/packages/clarkwinkelmann/flarum-ext-emojionearea) [![Packagist](https://img.shields.io/packagist/dt/clarkwinkelmann/flarum-ext-emojionearea.svg)](https://packagist.org/packages/clarkwinkelmann/flarum-ext-emojionearea) [![Donate](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.me/clarkwinkelmann)

Expand All @@ -7,18 +7,29 @@

This extension adds the [EmojiOne Area](https://github.com/mervick/emojionearea) emoji picker to [Flarum](https://github.com/flarum).

Please note that, as the name suggests, the emoji list and images used in this library are Emojione, which was previously used by Flarum until beta 7.
Please note that, as the name suggests, the emoji list and images used in this library are EmojiOne, which was previously used by Flarum until beta 7.

However Flarum now switched to Twemoji, which means the images shown in the picker and those inserted in the post will be (slightly or radically) different.

> As we bundle the emojione and emojioneArea libraries, the javascript for this extension is > 650kB, which can easily double or triple your assets size ⚠️ It's up to you to decide if it's worth it.
The picker is dynamically loaded from jsDelivr CDN when opened, which means this extension has virtually no impact on performance until the user interacts with the picker.

Install it:
## Installation

composer require clarkwinkelmann/flarum-ext-emojionearea

Links:
## Support

This extension is under **minimal maintenance**.

It was developed for a client and released as open-source for the benefit of the community.
I might publish simple bugfixes or compatibility updates for free.

You can [contact me](https://clarkwinkelmann.com/flarum) to sponsor additional features or updates.

Support is offered on a "best effort" basis through the Flarum community thread.

## Links

- [Thread on Flarum Discuss](https://discuss.flarum.org/d/4787-emoji-picker)
- [GitHub](https://github.com/clarkwinkelmann/flarum-ext-emojionearea)
- [Packagist](https://packagist.org/packages/clarkwinkelmann/flarum-ext-emojionearea)
- [Discuss](https://discuss.flarum.org/d/4787)
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"source": "https://github.com/clarkwinkelmann/flarum-ext-emojionearea"
},
"require": {
"flarum/core": "^0.1.0-beta.8"
"flarum/core": "^0.1.0-beta.14"
},
"autoload": {
"psr-4": {
Expand Down
1 change: 0 additions & 1 deletion extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
return [
(new Extend\Frontend('forum'))
->css(__DIR__ . '/less/forum.less')
->css(__DIR__ . '/js/dist/emojionearea.min.css')
->js(__DIR__ . '/js/dist/forum.js'),
(new Extend\Frontend('admin'))
->js(__DIR__ . '/js/dist/admin.js'),
Expand Down
2 changes: 1 addition & 1 deletion js/dist/admin.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion js/dist/admin.js.map

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion js/dist/emojionearea.min.css

This file was deleted.

10 changes: 1 addition & 9 deletions js/dist/forum.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/dist/forum.js.map

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions js/forum.js
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
window.emojione = require('emojione');
require('emojionearea');

export * from './src/forum';
2 changes: 0 additions & 2 deletions js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"private": true,
"name": "@clarkwinkelmann/emojionearea",
"dependencies": {
"copy-webpack-plugin": "^5.0.2",
"emojionearea": "^3.4.1",
"flarum-webpack-config": "0.1.0-beta.10",
"webpack": "^4.0.0",
"webpack-cli": "^3.0.7"
Expand Down
4 changes: 2 additions & 2 deletions js/src/admin/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import app from 'flarum/app';
import EmojioneAreaSettingsModal from "./modals/EmojioneAreaSettingsModal";
import EmojioneAreaSettingsModal from './modals/EmojioneAreaSettingsModal';

app.initializers.add('clarkwinkelmann-emojionearea', () => {
app.extensionSettings['clarkwinkelmann-emojionearea'] = () => app.modal.show(new EmojioneAreaSettingsModal());
app.extensionSettings['clarkwinkelmann-emojionearea'] = () => app.modal.show(EmojioneAreaSettingsModal);
});
3 changes: 1 addition & 2 deletions js/src/admin/modals/EmojioneAreaSettingsModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ export default class EmojioneAreaSettingsModal extends SettingsModal {
onchange: value => {
this.setting(settingsPrefix + settingSuffix)(value ? '1' : '0');
},
children: app.translator.trans(translationPrefix + labelSuffix),
}),
}, app.translator.trans(translationPrefix + labelSuffix)),
help ? m('.helpText', app.translator.trans(translationPrefix + labelSuffix + 'Help')) : null,
]);
};
Expand Down
147 changes: 96 additions & 51 deletions js/src/forum/index.js
Original file line number Diff line number Diff line change
@@ -1,83 +1,128 @@
import {extend} from 'flarum/extend';
import app from 'flarum/app';
import Button from 'flarum/components/Button';
import ComposerBody from 'flarum/components/ComposerBody';
import TextEditor from 'flarum/components/TextEditor';

/* global $ */
/* global m, $ */

const translationPrefix = 'clarkwinkelmann-emojionearea.forum.';

let emojioneAreaLoaded = false;

function loadEmojioneArea() {
if (emojioneAreaLoaded) {
return Promise.resolve();
}

emojioneAreaLoaded = true;

return new Promise(resolve => {
const style = document.createElement('link');
style.rel = 'stylesheet';
style.crossOrigin = 'anonymous';
style.integrity = 'sha256-LKawN9UgfpZuYSE2HiCxxDxDgLOVDx2R4ogilBI52oc=';
style.href = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/emojionearea.min.css';
document.head.appendChild(style);

const script = document.createElement('script');
script.crossOrigin = 'anonymous';
script.integrity = 'sha256-ImIFrmJd7ymGlVw2MbtI96BNPW4NfcKqM3d1Go665Ig=';
script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/emojionearea.min.js';
script.onload = resolve;
document.body.appendChild(script);
});
}

app.initializers.add('clarkwinkelmann-emojionearea', () => {
extend(ComposerBody.prototype, 'config', function (element, isInitialized, context) {
if (isInitialized) return;
TextEditor.prototype.emojioneAreaClickedOutside = function (event) {
// If a click is triggered before the picker is ready, do not do anything
if (!this.emojioneArea || !this.emojioneArea.isReady) {
return;
}

const $container = $('<div class="ComposerBody-emojioneareaContainer"/>');
this.$('.TextEditor-controls').before($container);
const $target = $(event.target);

const area = $('<div />').emojioneArea({
standalone: true, // Popup only mode
search: app.forum.attribute('emojioneAreaEnableSearch'),
searchPlaceholder: app.translator.trans(translationPrefix + 'search_placeholder'),
buttonTitle: app.translator.trans(translationPrefix + 'picker_button'),
recentEmojis: app.forum.attribute('emojioneAreaEnableRecent'),
filtersPosition: app.forum.attribute('emojioneAreaFiltersPositionBottom') ? 'bottom' : 'top',
searchPosition: app.forum.attribute('emojioneAreaSearchPositionBottom') ? 'bottom' : 'top',
container: $container,
tones: app.forum.attribute('emojioneAreaEnableTones'),
autocomplete: false, // Do not try to provide autocomplete - will prevent the textcomplete lib from being included
sprite: false, // Undocumented setting, but disabling it removes an unnecessary CSS file load
events: { // Listen for clicks to sync with Flarum editor
emojibtn_click: () => {
// To get the unicode value, we need to pull it from the invisible insert area
this.editor.insertAtCursor(this.editor.emojioneArea.getText());
},
},
});
// If we clicked on the popup or the editor button we don't do anything
if ($target.is('.emojionearea') || $target.parents('.emojionearea').length || $target.parents('.Button-emojionearea').length) {
return;
}

this.emojioneArea.hidePicker();
}

this.editor.emojioneArea = area.data('emojioneArea');
TextEditor.prototype.configureEmojioneArea = function () {
if (this.emojioneArea) {
return Promise.resolve();
}

const clickedOutside = event => {
// If a click is triggered before the picker is ready, do not do anything
if (!this.editor.emojioneArea.isReady) {
return;
}
const $container = $('<div class="ComposerBody-emojioneareaContainer"/>');
this.$('.TextEditor-controls').before($container);

const $target = $(event.target);
return new Promise(resolve => {
const area = $('<div />').emojioneArea({
standalone: true, // Popup only mode
search: app.forum.attribute('emojioneAreaEnableSearch'),
searchPlaceholder: app.translator.trans(translationPrefix + 'search_placeholder'),
buttonTitle: app.translator.trans(translationPrefix + 'picker_button'),
recentEmojis: app.forum.attribute('emojioneAreaEnableRecent'),
filtersPosition: app.forum.attribute('emojioneAreaFiltersPositionBottom') ? 'bottom' : 'top',
searchPosition: app.forum.attribute('emojioneAreaSearchPositionBottom') ? 'bottom' : 'top',
container: $container,
tones: app.forum.attribute('emojioneAreaEnableTones'),
autocomplete: false, // Do not try to provide autocomplete - will prevent the textcomplete lib from being included
sprite: false, // Undocumented setting, but disabling it removes an unnecessary CSS file load
events: { // Listen for clicks to sync with Flarum editor
emojibtn_click: () => {
// To get the unicode value, we need to pull it from the invisible insert area
this.attrs.composer.editor.insertAtCursor(this.emojioneArea.getText());
},
ready: resolve,
},
});

// If we clicked on the popup or the editor button we don't do anything
if ($target.is('.emojionearea') || $target.parents('.emojionearea').length || $target.parents('.Button-emojionearea').length) {
return;
}
this.emojioneArea = area.data('emojioneArea');
});
}

this.editor.emojioneArea.hidePicker();
};
extend(TextEditor.prototype, 'oncreate', function () {
this.emojioneArea = null;
this.emojioneAreaLoading = false;

document.addEventListener('click', clickedOutside);
document.addEventListener('click', this.emojioneAreaClickedOutside.bind(this));
});

const previousUnload = context.onunload;
context.onunload = () => {
if (previousUnload) {
previousUnload();
}
document.removeEventListener('click', clickedOutside);
};
extend(TextEditor.prototype, 'onremove', function () {
document.removeEventListener('click', this.emojioneAreaClickedOutside);
});

extend(TextEditor.prototype, 'toolbarItems', function (items) {
// Not using the TextEditorButton component because the tooltip apparently won't go away once the picker is open
items.add('clarkwinkelmann-emojionearea', Button.component({
onclick: () => {
if (this.emojioneArea.button.is('.active')) {
// Prevent double-clicks while the library is loading
if (this.emojioneAreaLoading) {
return;
}

if (this.emojioneArea && this.emojioneArea.button.is('.active')) {
this.emojioneArea.hidePicker();
} else {
const position = this.$('.Button-emojionearea').position();
this.$('.emojionearea-picker').css('left', position.left - 290);
this.emojioneArea.showPicker();
this.emojioneAreaLoading = true;

loadEmojioneArea().then(() => {
this.configureEmojioneArea().then(() => {
const position = this.$('.Button-emojionearea').position();
this.$('.emojionearea-picker').css('left', position.left - 290);
this.emojioneArea.showPicker();

this.emojioneAreaLoading = false;
m.redraw();
});
});
}
},
className: 'Button Button--icon Button--link Button-emojionearea',
icon: 'far fa-smile-beam',
icon: this.emojioneAreaLoading ? 'fas fa-spinner fa-pulse' : 'far fa-smile-beam',
title: app.translator.trans(translationPrefix + 'picker_button'),
}));

Expand Down
21 changes: 1 addition & 20 deletions js/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,20 +1 @@
const flarumConfig = require('flarum-webpack-config');
const CopyPlugin = require('copy-webpack-plugin');

let config = flarumConfig();

config.plugins = config.plugins || [];
config.plugins.push(new CopyPlugin([
// We need to copy the CSS file so it can be bundled with our extension
// It seems we can't copy outside of the current folder so we put it in dist with the javascript
{
from: 'node_modules/emojionearea/dist/emojionearea.min.css',
to: 'emojionearea.min.css',
transform(content) {
// Remove these alpha rules as they can't be understood by the less parser
return content.toString().replace(/filter:alpha\([A-Za-z0-9=]+\);/g, '');
},
},
]));

module.exports = config;
module.exports = require('flarum-webpack-config')();
Loading

0 comments on commit 91737d5

Please sign in to comment.