Browse Source

Start implementing a Stickers feature in Movim (not enabled yet)

Refactor the Picture lib to make it compatible with PNG
pull/183/head
Timothée Jaussoin 10 years ago
parent
commit
58f0feb78a
  1. 11
      app/helpers/StringHelper.php
  2. 15
      app/models/message/Message.php
  3. 9
      app/models/message/MessageDAO.php
  4. 1
      app/views/chat.tpl
  5. 15
      app/widgets/Chat/Chat.php
  6. 5
      app/widgets/Chat/_chat_smiley.tpl
  7. 12
      app/widgets/Chat/chat.js
  8. 124
      app/widgets/Stickers/Stickers.php
  9. 17
      app/widgets/Stickers/_stickers.tpl
  10. 0
      app/widgets/Stickers/stickers.tpl
  11. BIN
      app/widgets/Stickers/stickers/04c6573f4e67c1ec8a0ce1ee4510b0ccd0583290.png
  12. BIN
      app/widgets/Stickers/stickers/0fc649c7ad655722c1c63bea09c6aa6cd3b6e5ed.png
  13. BIN
      app/widgets/Stickers/stickers/30dddf556a53a6f4fcb74c36c4301d59c2290f69.png
  14. BIN
      app/widgets/Stickers/stickers/347b058305ec44e49b839f665f030cb000e14477.png
  15. BIN
      app/widgets/Stickers/stickers/530de08965c7a8653af311c414ca0ac79f0f7fb8.png
  16. BIN
      app/widgets/Stickers/stickers/66bda812246d091b57ab927f89e1b7d429cbc73e.png
  17. BIN
      app/widgets/Stickers/stickers/a19626467b06ccc6836105a790b660c6e1a0f92a.png
  18. BIN
      app/widgets/Stickers/stickers/a650e0b8ea76646bf8ba08694c666fbfb7f7402c.png
  19. BIN
      app/widgets/Stickers/stickers/a8f48774260a5560a88be6944bc80545854ea48b.png
  20. BIN
      app/widgets/Stickers/stickers/f72754fd1bdf83b87ee717ff6f5b181ae7384cd2.png
  21. 2
      bootstrap.php
  22. 31
      system/Picture.php
  23. 20
      themes/material/css/listn.css

11
app/helpers/StringHelper.php

@ -223,6 +223,17 @@ function cleanJid($jid)
return reset($explode);
}
/*
* Extract the CID
*/
function getCid($string)
{
preg_match("/(\w+)\@/", $string, $matches);
if(is_array($matches)) {
return $matches[1];
}
}
/*
* Explode JID
*/

15
app/models/message/Message.php

@ -26,6 +26,8 @@ class Message extends Model {
public $publishedPrepared; // Only for chat purpose
public $edited;
public $sticker; // The sticker code
public function __construct()
{
$this->_struct = '
@ -55,7 +57,9 @@ class Message extends Model {
"delivered" :
{"type":"date"},
"edited" :
{"type":"int", "size":1}
{"type":"int", "size":1},
"sticker" :
{"type":"string", "size":128 }
}';
parent::__construct();
@ -94,6 +98,15 @@ class Message extends Model {
$images = (bool)($this->type == 'chat');
if($stanza->html) {
$xhtml = new \SimpleXMLElement('<body xmlns="http://www.w3.org/1999/xhtml">'.(string)$stanza->html->body.'</body>');
$xhtml->registerXPathNamespace('xhtml', 'http://www.w3.org/1999/xhtml');
$img = $xhtml->xpath('//xhtml:img/@src')[0];
if($img) {
$this->sticker = getCid((string)$img);
}
}
/*if($stanza->html) {
$this->html = \cleanHTMLTags($stanza->html->body->asXML());
$this->html = \fixSelfClosing($this->html);

9
app/models/message/MessageDAO.php

@ -50,7 +50,8 @@ class MessageDAO extends SQL {
body,
html,
published,
delivered)
delivered,
sticker)
values(
:id,
:session,
@ -63,7 +64,8 @@ class MessageDAO extends SQL {
:body,
:html,
:published,
:delivered
:delivered,
:sticker
)';
$this->prepare(
@ -80,7 +82,8 @@ class MessageDAO extends SQL {
'body' => $message->body,
'html' => $message->html,
'published' => $message->published,
'delivered' => $message->delivered
'delivered' => $message->delivered,
'sticker' => $message->sticker
)
);
}

1
app/views/chat.tpl

@ -1,3 +1,4 @@
<?php $this->widget('Stickers');?>
<nav class="color dark">
<?php $this->widget('Presence');?>
<?php $this->widget('Navigation');?>

15
app/widgets/Chat/Chat.php

@ -376,14 +376,14 @@ class Chat extends WidgetBase
if(count($messages) > 0) {
Notification::append(false, $this->__('message.history', count($messages)));
}
foreach($messages as $message) {
if(!preg_match('#^\?OTR#', $message->body)) {
RPC::call('Chat.appendMessage', $this->prepareMessage($message), true);
foreach($messages as $message) {
if(!preg_match('#^\?OTR#', $message->body)) {
RPC::call('Chat.appendMessage', $this->prepareMessage($message), true);
}
}
RPC::call('Chat.cleanBubbles');
}
RPC::call('Chat.cleanBubbles');
}
/**
@ -574,6 +574,11 @@ class Chat extends WidgetBase
// $message->body = prepareString(htmlentities($message->body , ENT_COMPAT,'UTF-8'));
}
if(isset($message->sticker)) {
$p = new Picture;
$message->sticker = $p->get($message->sticker, false, false, 'png');
}
if($message->type == 'groupchat') {
$message->color = stringToColor($message->session.$message->resource.$message->jidfrom.$message->type);
}

5
app/widgets/Chat/_chat_smiley.tpl

@ -77,6 +77,11 @@
</table>
</section>
<div>
<!--
<a onclick="Stickers_ajaxShow()" class="button flat">
Stickers
</a>
-->
<a onclick="Dialog.clear()" class="button flat">
{$c->__('button.close')}
</a>

12
app/widgets/Chat/chat.js

@ -94,7 +94,7 @@ var Chat = {
var scrolled = MovimTpl.isPanelScrolled();
if(message.type == 'groupchat') {console.log(message.body);
if(message.type == 'groupchat') {
bubble = Chat.room.cloneNode(true);
id = message.jidfrom + '_conversation';
@ -140,8 +140,16 @@ var Chat = {
message.body = message.body.substr(4);
}
if(message.sticker != null) {
bubble.querySelector('div.bubble').className += ' sticker';
}
if(bubble) {
bubble.querySelector('div.bubble > p').innerHTML = message.body.replace(/\r\n?|\n/g, '<br />');
if(message.sticker != null) {
bubble.querySelector('div.bubble > p').innerHTML = '<img src="' + message.sticker + '"/>';
} else {
bubble.querySelector('div.bubble > p').innerHTML = message.body.replace(/\r\n?|\n/g, '<br />');
}
var info = bubble.querySelector('div.bubble > span.info');
info.innerHTML = message.publishedPrepared;

124
app/widgets/Stickers/Stickers.php

@ -0,0 +1,124 @@
<?php
use Moxl\Xec\Action\Message\Publish;
use Moxl\Xec\Action\BOB\Answer;
use Ramsey\Uuid\Uuid;
class Stickers extends WidgetBase
{
function load()
{
$this->registerEvent('bob', 'onRequest');
}
function onRequest($packet)
{
$content = $packet->content;
$to = $content[0];
$id = $content[1];
$cid = $content[2];
list($c, $ext) = explode('@', $cid);
list($sh, $key) = explode('+', $c);
$base64 = base64_encode(file_get_contents(dirname(__FILE__).'/stickers/'.$key.'.png'));
$a = new Answer;
$a->setTo($to)
->setId($id)
->setCid($cid)
->setType('image/png')
->setBase64($base64)
->request();
}
function ajaxSend($to, $file)
{
if(!$this->validateJid($jid)) return;
list($key, $ext) = explode('.', $file);
$filepath = dirname(__FILE__).'/stickers/'.$key.'.png';
if(!file_exists($filepath)) return;
// We get the base64
$base64 = base64_encode(file_get_contents($filepath));
// Caching the picture
$p = new Picture;
$p->fromBase($base64);
$p->set($key, 'png');
// Creating a message
$m = new \Modl\Message();
$m->session = $this->user->getLogin();
$m->jidto = echapJid($to);
$m->jidfrom = $this->user->getLogin();
$m->sticker = $key;
$m->body = 'A Stickers has been sent using Movim';
$m->published = gmdate('Y-m-d H:i:s');
$m->delivered = gmdate('Y-m-d H:i:s');
$session = \Sessionx::start();
$m->id = Uuid::uuid4();
$m->type = 'chat';
$m->resource = $session->resource;
// Sending the sticker
$html = "<p><img alt='Sticker' src='cid:sha1+".$key."@bob.xmpp.org'/></p>";
$p = new Publish;
$p->setTo($m->jidto)
->setContent($m->body)
->setHTML($html)
->setId($m->id)
->request();
$md = new \Modl\MessageDAO();
$md->set($m);
// Sending it to Chat
$packet = new Moxl\Xec\Payload\Packet;
$packet->content = $m;
$c = new Chat;
$c->onMessage($packet/*, true*/);
}
function ajaxShow($to)
{
if(!$this->validateJid($to)) return;
$files = scandir(dirname(__FILE__).'/stickers/');
array_shift($files);
array_shift($files);
$view = $this->tpl();
$view->assign('jid', $to);
$view->assign('stickers', $files);
$view->assign('path', $this->respath('stickers').'/');
Dialog::fill($view->draw('_stickers', true), true);
}
/**
* @brief Validate the jid
*
* @param string $jid
*/
private function validateJid($jid)
{
$validate_jid = Validator::stringType()->noWhitespace()->length(6, 60);
if(!$validate_jid->validate($jid)) return false;
else return true;
}
function display()
{
}
}

17
app/widgets/Stickers/_stickers.tpl

@ -0,0 +1,17 @@
<section class="scroll">
<ul class="list flex active">
{loop="$stickers"}
<li class="block" onclick="Stickers_ajaxSend('{$jid}', '{$value}')">
<img src="{$path}{$value}"/>
</li>
{/loop}
</ul>
</section>
<div>
<a onclick="Chat_ajaxSmiley()" class="button flat">
Emojis
</a>
<a onclick="Dialog.clear()" class="button flat">
{$c->__('button.close')}
</a>
</div>

0
app/widgets/Stickers/stickers.tpl

BIN
app/widgets/Stickers/stickers/04c6573f4e67c1ec8a0ce1ee4510b0ccd0583290.png

After

Width: 259  |  Height: 224  |  Size: 14 KiB

BIN
app/widgets/Stickers/stickers/0fc649c7ad655722c1c63bea09c6aa6cd3b6e5ed.png

After

Width: 190  |  Height: 224  |  Size: 17 KiB

BIN
app/widgets/Stickers/stickers/30dddf556a53a6f4fcb74c36c4301d59c2290f69.png

After

Width: 278  |  Height: 210  |  Size: 59 KiB

BIN
app/widgets/Stickers/stickers/347b058305ec44e49b839f665f030cb000e14477.png

After

Width: 206  |  Height: 224  |  Size: 17 KiB

BIN
app/widgets/Stickers/stickers/530de08965c7a8653af311c414ca0ac79f0f7fb8.png

After

Width: 242  |  Height: 233  |  Size: 44 KiB

BIN
app/widgets/Stickers/stickers/66bda812246d091b57ab927f89e1b7d429cbc73e.png

After

Width: 259  |  Height: 224  |  Size: 14 KiB

BIN
app/widgets/Stickers/stickers/a19626467b06ccc6836105a790b660c6e1a0f92a.png

After

Width: 278  |  Height: 218  |  Size: 47 KiB

BIN
app/widgets/Stickers/stickers/a650e0b8ea76646bf8ba08694c666fbfb7f7402c.png

After

Width: 112  |  Height: 100  |  Size: 23 KiB

BIN
app/widgets/Stickers/stickers/a8f48774260a5560a88be6944bc80545854ea48b.png

After

Width: 278  |  Height: 224  |  Size: 49 KiB

BIN
app/widgets/Stickers/stickers/f72754fd1bdf83b87ee717ff6f5b181ae7384cd2.png

After

Width: 16  |  Height: 16  |  Size: 620 B

2
bootstrap.php

@ -344,7 +344,7 @@ class Bootstrap {
return["Account","AccountNext","Ack","AdHoc","Avatar","Bookmark","Chat",
"Chats","Config","Contact","Dialog","Group","Groups","Header","Init",
"Login","LoginAnonymous","Menu","Notifs","Post","Presence","Publish",
"Rooms","Roster","Upload","Vcard4"];
"Rooms","Roster","Stickers","Upload","Vcard4"];
}
}

31
system/Picture.php

@ -5,6 +5,7 @@ class Picture {
private $_uri = CACHE_URI;
private $_key;
private $_bin = false;
private $_formats = ['jpeg' => '.jpg', 'png' => '.png'];
/**
* @desc Load a bin picture from a path
@ -41,30 +42,31 @@ class Picture {
* @param $height The height requested
* @return The url of the picture
*/
public function get($key, $width = false, $height = false) {
public function get($key, $width = false, $height = false, $format = 'jpeg') {
if(!in_array($format, array_keys($this->_formats))) $format = 'jpeg';
$this->_key = $key;
$original = $this->_path.md5($this->_key).'.jpg';
$original = $this->_path.md5($this->_key).$this->_formats[$format];
// We request the original picture
if($width == false) {
if(file_exists($original)) {
$this->fromPath($original);
return $this->_uri.md5($this->_key).'.jpg';
return $this->_uri.md5($this->_key).$this->_formats[$format];
} else {
return false;
}
// We request a specific size
} else {
if(file_exists($this->_path.md5($this->_key).'_'.$width.'.jpg')) {
$this->fromPath($this->_path.md5($this->_key).'_'.$width.'.jpg');
return $this->_uri.md5($this->_key).'_'.$width.'.jpg';
if(file_exists($this->_path.md5($this->_key).'_'.$width.$this->_formats[$format])) {
$this->fromPath($this->_path.md5($this->_key).'_'.$width.$this->_formats[$format]);
return $this->_uri.md5($this->_key).'_'.$width.$this->_formats[$format];
} else {
if(file_exists($original)) {
$this->fromPath($original);
$this->createThumbnail($width, $height);
return $this->_uri.md5($this->_key).'_'.$width.'.jpg';
return $this->_uri.md5($this->_key).'_'.$width.$this->_formats[$format];
} else {
return false;
}
@ -76,9 +78,11 @@ class Picture {
* @desc Save a picture (original size)
* @param $key The key of the picture
*/
public function set($key) {
public function set($key, $format = 'jpeg') {
if(!in_array($format, array_keys($this->_formats))) $format = 'jpeg';
$this->_key = $key;
$path = $this->_path.md5($this->_key).'.jpg';
$path = $this->_path.md5($this->_key).$this->_formats[$format];
// If the file exist we replace it
if(file_exists($path) && $this->_bin) {
@ -89,7 +93,7 @@ class Picture {
glob(
$this->_path.
md5($key).
'*.jpg',
'*'.$this->_formats[$format],
GLOB_NOSORT
) as $path_thumb) {
unlink($path_thumb);
@ -101,6 +105,7 @@ class Picture {
try {
$im->readImageBlob($this->_bin);
if($im != false) {
$im->setImageFormat($format);
$im->setImageCompressionQuality(95);
$im->setInterlaceScheme(Imagick::INTERLACE_PLANE);
$im->writeImage($path);
@ -116,13 +121,15 @@ class Picture {
* @desc Create a thumbnail of the picture and save it
* @param $size The size requested
*/
private function createThumbnail($width, $height = false) {
private function createThumbnail($width, $height = false, $format = 'jpeg') {
if(!in_array($format, array_keys($this->_formats))) $format = 'jpeg';
if(!$height) $height = $width;
$path = $this->_path.md5($this->_key).'_'.$width.'.jpg';
$path = $this->_path.md5($this->_key).'_'.$width.$this->_formats[$format];
$im = new Imagick;
$im->readImageBlob($this->_bin);
$im->setImageFormat($format);
$geo = $im->getImageGeometry();

20
themes/material/css/listn.css

@ -281,15 +281,10 @@ ul li span.counter.bottom {
/* Bubble */
ul li div.bubble {
padding: 1.25rem 2rem 0.75rem;
border-radius: 0.5rem;
line-height: 2.75rem;
position: relative;
box-sizing: border-box;
display: block;
font-size: 1.75rem;
background-color: white;
border-color: white;
max-width: calc(100% - 11rem);
float: left;
@ -298,6 +293,14 @@ ul li div.bubble {
width: auto;
}
ul li div.bubble:not(.sticker) {
padding: 1.25rem 2rem 0.75rem;
border-radius: 0.5rem;
line-height: 2.75rem;
background-color: white;
border-color: white;
}
ul li div.bubble > p {
overflow: hidden;
display: inline-block;
@ -308,6 +311,9 @@ ul li.oppose div.bubble {
margin-right: 9rem;
float: right;
position: initial;
}
ul li.oppose div.bubble:not(.sticker) {
background-color: #f5f5f5;
}
@ -333,7 +339,7 @@ ul li .quote {
font-style: italic;
}
ul li:not(.same) div.bubble:before {
ul li:not(.same) div.bubble:not(.sticker):before {
content: "";
position: absolute;
top: 0;
@ -344,7 +350,7 @@ ul li:not(.same) div.bubble:before {
border-right: 1.5rem solid transparent;
}
ul li.oppose:not(.same) div.bubble:before {
ul li.oppose:not(.same) div.bubble:not(.sticker):before {
left: calc(100% - 10.5rem);
top: 1.5rem;
border-top-color: #f5f5f5;

Loading…
Cancel
Save