more work on emojis

This commit is contained in:
Mario
2024-03-09 20:53:18 +00:00
parent ba1e705c61
commit 46fa26502b
36 changed files with 217 additions and 38 deletions

View File

@@ -642,7 +642,7 @@ class Activity {
break;
case 'Emoji':
$ret[] = ['ttype' => TERM_EMOJI, 'url' => $t['icon']['url'], 'term' => escape_tags($t['name'])];
$ret[] = ['ttype' => TERM_EMOJI, 'url' => $t['id'], 'term' => escape_tags($t['name']), 'imgurl' => $t['icon']['url']];
break;
default:
@@ -677,6 +677,10 @@ class Activity {
$ret[] = ['type' => 'Bookmark', 'href' => $t['url'], 'name' => $t['term']];
break;
case TERM_EMOJI:
$ret[] = ['type' => 'Emoji', 'id' => $t['url'], 'name' => $t['term'], 'icon' => ['type' => 'Image', 'url' => $t['imgurl']]];
break;
default:
break;
}
@@ -976,10 +980,12 @@ class Activity {
return [];
}
/* this should not be needed
$t = self::encode_taxonomy($i);
if ($t) {
$ret['tag'] = $t;
}
*/
$a = self::encode_attachment($i, true);
if ($a) {
@@ -997,6 +1003,7 @@ class Activity {
];
call_hooks('encode_activity', $hookinfo);
return $hookinfo['encoded'];
}
@@ -2179,9 +2186,17 @@ class Activity {
// Pleroma reactions
$t = trim(self::get_textfield($act->data, 'content'));
$content['content'] = $t;
// Unicode emojis
if (grapheme_strlen($t) === 1) {
$content['content'] = $t;
$content['content'] = '<h1>' . $t . '</h1>';
}
$a = self::decode_taxonomy($act->data);
if ($a) {
$s['term'] = $a;
}
}
}
@@ -2885,7 +2900,13 @@ class Activity {
if (isset($item['term']) && !PConfig::Get($channel['channel_id'], 'system', 'no_smilies')) {
foreach ($item['term'] as $t) {
if ($t['ttype'] === TERM_EMOJI) {
$item['body'] = str_replace($t['term'], '[img class="smiley emoji custom-emoji" alt="' . $t['term'] . '" title="' . $t['term'] . '"]' . $t['url'] . '[/img]', $item['body']);
$class = 'emoji';
$shortname = ':' . trim($t['term'], ':') . ':';
if (is_solo_string($shortname, $item['body'])) {
$class .= ' single-emoji';
}
$item['body'] = str_replace($shortname, '[img class="' . $class . '" alt="' . $t['term'] . '" title="' . $t['term'] . '"]' . ($t['imgurl'] ?: $t['url']) . '[/img]', $item['body']);
}
}
}

View File

@@ -19,7 +19,7 @@ class ThreadItem {
private $comment_box_template = 'comment_item.tpl';
private $commentable = false;
// list of supported reaction emojis - a site can over-ride this via config system.reactions
private $reactions = ['1f60a','1f44f','1f37e','1f48b','1f61e','2665','1f606','1f62e','1f634','1f61c','1f607','1f608'];
private $reactions = ['slightly_smiling_face','clapping_hands','bottle_with_popping_cork','kiss_mark','disappointed_face','red_heart','grinning_face','astonished_face','sleeping_face','winking_face_with_tongue','smiling_face_with_halo','smiling_face_with_horns'];
private $toplevel = false;
private $children = array();
private $parent = null;

60
Zotlabs/Module/Emoji.php Normal file
View File

@@ -0,0 +1,60 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Web\Controller;
use Zotlabs\Daemon\Master;
use Zotlabs\Lib\ActivityStreams;
use App;
class Emoji extends Controller {
function init() {
$shortname = argv(1);
if (!$shortname) {
killme();
}
$emojis = get_emojis();
if (!isset($emojis[$shortname])) {
killme();
}
$emoji = $emojis[$shortname];
hz_syslog(print_r($emoji, true));
if (!file_exists($emoji['filepath'])) {
killme();
}
$image = getimagesize($emoji['filepath']);
if(ActivityStreams::is_as_request()) {
$last_modified = date(ATOM_TIME, filemtime($emoji['filepath']));
$obj = [
'id' => z_root() . '/emoji/' . $shortname,
'type' => 'Emoji',
'name' => $emoji['shortname'],
'updated' => $last_modified,
'icon' => [
'type' => 'Image',
'mediaType' => $image['mime'],
'url' => z_root() . '/' . $emoji['filepath']
]
];
as_return_and_die($obj);
}
header('Content-Type: ' . $image['mime']);
echo file_get_contents($emoji['filepath']);
killme();
}
}

View File

@@ -938,6 +938,30 @@ class Item extends Controller {
}
}
if (preg_match_all('/(\:(\w|\+|\-)+\:)(?=|[\!\.\?]|$)/', $body, $match)) {
// emoji shortcodes
$emojis = get_emojis();
foreach ($match[0] as $mtch) {
$shortname = trim($mtch, ':');
if (!isset($emojis[$shortname])) {
continue;
}
$emoji = $emojis[$shortname];
$post_tags[] = [
'uid' => $profile_uid,
'ttype' => TERM_EMOJI,
'otype' => TERM_OBJ_POST,
'term' => trim($mtch),
'url' => z_root() . '/emoji/' . $shortname,
'imgurl' => z_root() . '/' . $emoji['filepath']
];
}
}
// BBCODE end alert
}
@@ -958,6 +982,10 @@ class Item extends Controller {
}
}
if ($orig_post) {
// preserve original tags
$t = q("select * from term where oid = %d and otype = %d and uid = %d and ttype in ( %d, %d, %d )",

View File

@@ -24,7 +24,15 @@ class React extends Controller {
return;
}
$emoji = $_REQUEST['emoji'];
$shortname = $_REQUEST['emoji'];
$emojis = get_emojis();
if (!isset($emojis[$shortname])) {
return;
}
$emoji = $emojis[$shortname];
if (!$emoji) {
return;
@@ -62,10 +70,19 @@ class React extends Controller {
$n['uuid'] = $uuid;
$n['mid'] = z_root() . '/item/' . $uuid;
$n['verb'] = 'Create';
$n['body'] = '[zmg=32x32]' . z_root() . '/images/emoji/' . $emoji . '.png[/zmg]';
$n['body'] = $emoji['shortname']; //'[img class="emoji single-emoji"]' . z_root() . '/' . $emoji['filepath'] . '[/img]';
$n['author_xchan'] = $channel['channel_hash'];
$n['obj'] = Activity::fetch_item(['id' => $item['mid']]);
$n['obj_type'] = ((array_path_exists('obj/type', $n)) ? $n['obj']['type'] : EMPTY_STR);
// $n['obj'] = Activity::fetch_item(['id' => $i[0]['mid']]);
// $n['obj_type'] = ((array_path_exists('obj/type', $n)) ? $n['obj']['type'] : EMPTY_STR);
$n['term'][] = [
'uid' => $channel['channel_id'],
'ttype' => TERM_EMOJI,
'otype' => TERM_OBJ_POST,
'term' => $emoji['shortname'],
'url' => z_root() . '/emoji/' . $shortname,
'imgurl' => z_root() . '/' . $emoji['filepath']
];
$x = item_store($n);

View File

@@ -4,18 +4,8 @@ namespace Zotlabs\Module;
class Smilies extends \Zotlabs\Web\Controller {
function get() {
if (\App::$argv[1]==="json"){
$tmp = list_smilies();
$results = array();
for($i = 0; $i < count($tmp['texts']); $i++) {
$results[] = array('text' => $tmp['texts'][$i], 'icon' => $tmp['icons'][$i]);
}
json_return_and_die($results);
}
else {
return smilies('',true);
}
function init() {
json_return_and_die(get_emojis());
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 812 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 B

View File

@@ -1,2 +1,7 @@
These files supplied by emojione. License is CC BY 4.0. Attribution is required for commercial use.
See http://emojione.com
Images are provided by Emojitwo formerly Emojione
https://emojitwo.github.io
https://www.emojione.com
Creative Commons Attribution International 4.0 (CC-BY 4.0)
https://creativecommons.org/licenses/by/4.0/legalcode

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
images/emoji/kiss_mark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
images/emoji/red_heart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1999,14 +1999,15 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
if(($terms) && (is_array($terms))) {
foreach($terms as $t) {
q("insert into term (uid,oid,otype,ttype,term,url)
values(%d,%d,%d,%d,'%s','%s') ",
q("insert into term (uid,oid,otype,ttype,term,url,imgurl)
values(%d,%d,%d,%d,'%s','%s','%s') ",
intval($arr['uid']),
intval($current_post),
intval(TERM_OBJ_POST),
intval($t['ttype']),
dbesc($t['term']),
dbesc($t['url'])
dbesc($t['url']),
dbesc($t['imgurl'] ?? ''),
);
}

View File

@@ -423,7 +423,7 @@ function json_return_and_die($x, $content_type = 'application/json') {
killme();
}
function as_return_and_die($obj, $channel) {
function as_return_and_die($obj, $channel = []) {
$ret = Activity::build_packet($obj, $channel);
logger('data: ' . jindent($ret), LOGGER_DATA);
@@ -433,8 +433,10 @@ function as_return_and_die($obj, $channel) {
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
HTTPSig::set_headers($h);
if ($channel) {
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
HTTPSig::set_headers($h);
}
echo $ret;
killme();

View File

@@ -1270,6 +1270,33 @@ function sslify($s) {
return $s;
}
function get_emojis() {
$emojis = [
// Reactions (emojitwo emojis)
'astonished_face' => ['shortname' => ':astonished_face:', 'filepath' => 'images/emoji/astonished_face.png'],
'bottle_with_popping_cork' => ['shortname' => ':bottle_with_popping_cork:', 'filepath' => 'images/emoji/bottle_with_popping_cork.png'],
'clapping_hands' => ['shortname' => ':clapping_hands:', 'filepath' => 'images/emoji/clapping_hands.png'],
'disappointed_face' => ['shortname' => ':disappointed_face:', 'filepath' => 'images/emoji/disappointed_face.png'],
'grinning_face' => ['shortname' => ':grinning_face:', 'filepath' => 'images/emoji/grinning_face.png'],
'kiss_mark' => ['shortname' => ':kiss_mark:', 'filepath' => 'images/emoji/kiss_mark.png'],
'red_heart' => ['shortname' => ':red_heart:', 'filepath' => 'images/emoji/red_heart.png'],
'sleeping_face' => ['shortname' => ':sleeping_face:', 'filepath' => 'images/emoji/sleeping_face.png'],
'slightly_smiling_face' => ['shortname' => ':slightly_smiling_face:', 'filepath' => 'images/emoji/slightly_smiling_face.png'],
'smiling_face_with_halo' => ['shortname' => ':smiling_face_with_halo:', 'filepath' => 'images/emoji/smiling_face_with_halo.png'],
'smiling_face_with_horns' => ['shortname' => ':smiling_face_with_horns:', 'filepath' => 'images/emoji/smiling_face_with_horns.png'],
'winking_face_with_tongue' => ['shortname' => ':winking_face_with_tongue:', 'filepath' => 'images/emoji/winking_face_with_tongue.png'],
'facepalm' => ['shortname' => ':facepalm:', 'filepath' => 'images/emoticons/smiley-facepalm.gif']
];
call_hooks('get_emojis', $emojis);
return $emojis;
}
function is_solo_string(string $emoji, string $body) : bool {
return empty(trim(str_replace($emoji, '', $body, $count))) && $count === 1;
}
/**
* @brief Function to list all smilies, both internal and from addons.
@@ -1386,10 +1413,34 @@ function smilies($s, $sample = false) {
|| (local_channel() && intval(get_pconfig(local_channel(), 'system', 'no_smilies'))))
return $s;
$s = preg_replace_callback('{<(pre|code)>.*?</\1>}ism', 'smile_shield', $s);
$s = preg_replace_callback('/<[a-z]+ .*?>/ism', 'smile_shield', $s);
if (preg_match_all('/(\:(\w|\+|\-)+\:)(?=|[\!\.\?]|$)/', $s, $match)) {
// emoji shortcodes
$emojis = get_emojis();
foreach ($match[0] as $mtch) {
$name = trim($mtch, ':');
if (!isset($emojis[$name])) {
continue;
}
$emoji = $emojis[$name];
$class = 'emoji';
if (is_solo_string($mtch, $s)) {
$class .= ' single-emoji';
}
$img = '<img class="' . $class . '" src="' . $emoji['filepath'] . '" alt="' . $emoji['shortname'] . '" title="' . $emoji['shortname'] . '" />';
string_replace($emoji['shortname'], $img, $s);
}
}
/*
$params = list_smilies();
$params['string'] = $s;
@@ -1400,9 +1451,9 @@ function smilies($s, $sample = false) {
}
} else {
$params['string'] = preg_replace_callback('/&lt;(3+)/','preg_heart',$params['string']);
$s = str_replace($params['texts'],$params['icons'],$params['string']);
$s = str_replace($params['texts'], $params['icons'], $params['string']);
}
*/
$s = preg_replace_callback('/<!--base64:(.*?)-->/ism', 'smile_unshield', $s);

View File

@@ -299,13 +299,17 @@ code.inline-code {
text-decoration: overline;
}
img.smiley.emoji {
height: .9em;
img.emoji {
height: 1rem;
vertical-align: baseline;
margin-bottom: -.1em;
margin-bottom: -.1rem;
}
img.smiley.emoji:hover {
img.emoji.single-emoji {
height: 2rem;
}
img.emoji:not(.single-emoji):hover {
transform: scale(2);
transition: transform .1s ease-out;
filter: drop-shadow(0px 0px 1px rgba(0, 0, 0, .5));

View File

@@ -45,7 +45,7 @@ function contact_format(item) {
}
function smiley_format(item) {
return "<div class='dropdown-item'>" + item.icon + ' ' + item.text + "</div>";
return "<div class='dropdown-item'><img class='emoji' src='" + item.filepath + "'> " + item.shortname.replaceAll(':', '') + "</div>";
}
function bbco_format(item) {
@@ -193,8 +193,8 @@ function string2bb(element) {
match: /(^|\s)(:[a-z0-9_:]{2,})$/,
index: 2,
cache: true,
search: function(term, callback) { $.getJSON('/smilies/json').done(function(data) { callback($.map(data, function(entry) { return entry.text.indexOf(term.substr(1)) !== -1 ? entry : null; })); }); },
replace: function(item) { return "$1" + item.text + ' '; },
search: function(term, callback) { $.getJSON('/smilies/json').done(function(data) { callback($.map(data, function(entry) { return entry.shortname.indexOf(term.substr(1)) !== -1 ? entry : null; })); }); },
replace: function(item) { return "$1" + item.shortname + ' '; },
context: function(text) { return text.toLowerCase(); },
template: smiley_format
};