Browse Source

First raw implementation of Pubsub galleries in Movim

Add a small "dumb" galleries detector
pull/1021/head
Timothée Jaussoin 4 years ago
parent
commit
559776140b
  1. 3
      app/helpers/UtilsHelper.php
  2. 68
      app/widgets/CommunityPosts/CommunityPosts.php
  3. 36
      app/widgets/CommunityPosts/_communityposts.tpl
  4. 2
      app/widgets/CommunityPosts/communityposts.js
  5. 2
      app/widgets/Post/_post_comments_error.tpl
  6. 3
      app/widgets/Post/_post_ticket.tpl
  7. 26
      lib/moxl/src/Stanza/Pubsub.php
  8. 5
      lib/moxl/src/Xec/Action/Pubsub/GetItem.php
  9. 21
      lib/moxl/src/Xec/Action/Pubsub/GetItems.php
  10. 35
      public/theme/css/block.css
  11. 2
      src/Movim/Route.php

3
app/helpers/UtilsHelper.php

@ -639,7 +639,8 @@ function generateKey($size)
return $hash; return $hash;
} }
define('DEFAULT_HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://google.com/bot.html)');
//define('DEFAULT_HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://google.com/bot.html)');
define('DEFAULT_HTTP_USER_AGENT', 'Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0');
/** /**
* @desc Request a url async * @desc Request a url async

68
app/widgets/CommunityPosts/CommunityPosts.php

@ -11,7 +11,8 @@ include_once WIDGETS_PATH.'Post/Post.php';
class CommunityPosts extends Base class CommunityPosts extends Base
{ {
private $_paging = 10;
private $_paging = 12;
private $_beforeAfter = 'b=';
public function load() public function load()
{ {
@ -25,10 +26,10 @@ class CommunityPosts extends Base
public function onItemsId($packet) public function onItemsId($packet)
{ {
list($origin, $node, $ids, $first, $last, $count, $paginated, $before)
list($origin, $node, $ids, $first, $last, $count, $paginated, $before, $after, $query)
= array_values($packet->content); = array_values($packet->content);
$this->displayItems($origin, $node, $ids, $first, $last, $count, $paginated, $before);
$this->displayItems($origin, $node, $ids, $first, $last, $count, $paginated, $before, $after, $query);
} }
public function onItemsError($packet) public function onItemsError($packet)
@ -59,13 +60,15 @@ class CommunityPosts extends Base
$last = false, $last = false,
$count = false, $count = false,
$paginated = false, $paginated = false,
$before = null
$before = null,
$after = null,
$query = null
) { ) {
if (!$this->validateServerNode($origin, $node)) { if (!$this->validateServerNode($origin, $node)) {
return; return;
} }
$html = $this->prepareCommunity($origin, $node, 0, $ids, $first, $last, $count, $before);
$html = $this->prepareCommunity($origin, $node, 0, $ids, $first, $last, $count, $before, $after, $query);
$slugify = new Slugify; $slugify = new Slugify;
$this->rpc( $this->rpc(
@ -82,7 +85,7 @@ class CommunityPosts extends Base
$c->ajaxGetDrawer($jid); $c->ajaxGetDrawer($jid);
} }
public function ajaxGetItems($origin, $node, $before = 'empty')
public function ajaxGetItems($origin, $node, $before = 'empty', $query = null)
{ {
if (!$this->validateServerNode($origin, $node)) { if (!$this->validateServerNode($origin, $node)) {
return; return;
@ -91,9 +94,17 @@ class CommunityPosts extends Base
$r = new GetItems; $r = new GetItems;
$r->setTo($origin) $r->setTo($origin)
->setNode($node) ->setNode($node)
->setPaging($this->_paging)
->setBefore($before)
->request();
->setPaging($this->_paging);
$r = (strpos($before, $this->_beforeAfter) === 0)
? $r->setAfter(substr($before, strlen($this->_beforeAfter)))
: $r->setBefore($before);
if ($query) {
$r->setQuery($query);
}
$r->request();
} }
public function ajaxClear() public function ajaxClear()
@ -113,6 +124,11 @@ class CommunityPosts extends Base
return (new \Post)->preparePost($p, false, true); return (new \Post)->preparePost($p, false, true);
} }
public function prepareTicket($p)
{
return (new \Post)->prepareTicket($p);
}
private function prepareCommunity( private function prepareCommunity(
$origin, $origin,
$node, $node,
@ -121,7 +137,9 @@ class CommunityPosts extends Base
$first = false, $first = false,
$last = false, $last = false,
$count = false, $count = false,
$before = null
$before = null,
$after = null,
$query = null
) { ) {
$ids = is_array($ids) ? $ids : []; $ids = is_array($ids) ? $ids : [];
foreach ($ids as $key => $id) { foreach ($ids as $key => $id) {
@ -130,6 +148,10 @@ class CommunityPosts extends Base
} }
} }
if (empty($ids)) {
return $this->prepareEmpty();
}
$posts = \App\Post::where('server', $origin)->where('node', $node) $posts = \App\Post::where('server', $origin)->where('node', $node)
->whereIn('nodeid', $ids)->get(); ->whereIn('nodeid', $ids)->get();
$postsWithKeys = []; $postsWithKeys = [];
@ -150,6 +172,7 @@ class CommunityPosts extends Base
$view->assign('ids', $ids); $view->assign('ids', $ids);
$view->assign('posts', $postsWithKeys); $view->assign('posts', $postsWithKeys);
$view->assign('before', $before); $view->assign('before', $before);
$view->assign('after', $after);
$view->assign('info', \App\Info::where('server', $origin) $view->assign('info', \App\Info::where('server', $origin)
->where('node', $node) ->where('node', $node)
->first()); ->first());
@ -159,6 +182,19 @@ class CommunityPosts extends Base
->first()); ->first());
$view->assign('paging', $this->_paging); $view->assign('paging', $this->_paging);
// For now we detect if a node is a gallery if all the publications have an attached picture
// and if the post contents are short.
$shortCount = 0;
$gallery = $posts->every(function ($post) use (&$shortCount) {
if ($post->isShort()) $shortCount++;
return $post->picture != null;
});
if ($gallery && $shortCount < $posts->count()/2) $gallery = false;
$view->assign('gallery', $gallery);
$view->assign('publicposts', ($ids == false) $view->assign('publicposts', ($ids == false)
? \App\Post::where('server', $origin) ? \App\Post::where('server', $origin)
->where('node', $node) ->where('node', $node)
@ -173,9 +209,17 @@ class CommunityPosts extends Base
$view->assign('last', $last); $view->assign('last', $last);
$view->assign('count', $count); $view->assign('count', $count);
$view->assign('goback', $this->route(
if ($first) {
$view->assign('previouspage', $this->route(
$node == 'urn:xmpp:microblog:0' ? 'contact' : 'community',
[$origin, $node, $this->_beforeAfter.$first, $query]
));
}
$view->assign('nextpage', $this->route(
$node == 'urn:xmpp:microblog:0' ? 'contact' : 'community', $node == 'urn:xmpp:microblog:0' ? 'contact' : 'community',
[$origin, $node, $last]
[$origin, $node, $last, $query]
)); ));
$html = $view->draw('_communityposts'); $html = $view->draw('_communityposts');

36
app/widgets/CommunityPosts/_communityposts.tpl

@ -1,23 +1,35 @@
{if="!empty($ids)"} {if="!empty($ids)"}
<ul class="list card shadow">
<ul class="list card shadow flex {if="$gallery"}third gallery active{/if}">
{loop="$ids"} {loop="$ids"}
{if="isset($posts[$value])"} {if="isset($posts[$value])"}
<div id="{$value|cleanupId}" class="block large">
{if="$gallery"}
{autoescape="off"} {autoescape="off"}
{$c->preparePost($posts[$value])}
{$c->prepareTicket($posts[$value])}
{/autoescape} {/autoescape}
</div>
{else}
<div id="{$value|cleanupId}" class="block large">
{autoescape="off"}
{$c->preparePost($posts[$value])}
{/autoescape}
</div>
{/if}
{/if} {/if}
{/loop} {/loop}
</ul> </ul>
{elseif="$publicposts->isNotEmpty()"} {elseif="$publicposts->isNotEmpty()"}
<ul class="list card shadow">
<ul class="list card shadow {if="$gallery"}third gallery active{/if}">
{loop="$publicposts"} {loop="$publicposts"}
<div id="{$value->nodeid|cleanupId}" class="block large">
{if="$gallery"}
{autoescape="off"} {autoescape="off"}
{$c->preparePost($value)}
{$c->prepareTicket($value)}
{/autoescape} {/autoescape}
</div>
{else}
<div id="{$value|cleanupId}" class="block large">
{autoescape="off"}
{$c->preparePost($value)}
{/autoescape}
</div>
{/if}
{/loop} {/loop}
</ul> </ul>
{else} {else}
@ -27,18 +39,18 @@
</div> </div>
{/if} {/if}
<ul class="list thick" id="goback">
<ul class="list thick" id="nextpage">
<li class="block"> <li class="block">
<div> <div>
<p class="center"> <p class="center">
{if="$before != null || $page > 0"}
<a class="button flat" href="#" onclick="history.back()">
{if="(isset($previouspage) && (($before != null && $before != 'empty') || $after != null)) || $page > 0"}
<a class="button flat" href="{$previouspage}">
<i class="material-icons">keyboard_arrow_left</i> <i class="material-icons">keyboard_arrow_left</i>
{$c->__('button.previous')} {$c->__('button.previous')}
</a> </a>
{/if} {/if}
{if="$last"} {if="$last"}
<a class="button flat" href="{$goback}" title="{$c->__('post.older')}">
<a class="button flat" href="{$nextpage}" title="{$c->__('post.older')}">
{$c->__('button.next')} {$c->__('button.next')}
<i class="material-icons">keyboard_arrow_right</i> <i class="material-icons">keyboard_arrow_right</i>
</a> </a>

2
app/widgets/CommunityPosts/communityposts.js

@ -2,6 +2,6 @@ MovimWebsocket.attach(function() {
var parts = MovimUtils.urlParts(); var parts = MovimUtils.urlParts();
if (parts.params.length > 0) { if (parts.params.length > 0) {
var node = (parts.params[1] == undefined || parts.params[1] == '') ? 'urn:xmpp:microblog:0' : parts.params[1]; var node = (parts.params[1] == undefined || parts.params[1] == '') ? 'urn:xmpp:microblog:0' : parts.params[1];
CommunityPosts_ajaxGetItems(parts.params[0], node, parts.params[2]);
CommunityPosts_ajaxGetItems(parts.params[0], node, parts.params[2], parts.params[3]);
} }
}); });

2
app/widgets/Post/_post_comments_error.tpl

@ -4,7 +4,7 @@
<i class="material-icons">comment</i> <i class="material-icons">comment</i>
</span> </span>
<div> <div>
<p class="normal">{$c->__('post.comments_disabled')}</p>
<p class="normal line">{$c->__('post.comments_disabled')}</p>
</div> </div>
</li> </li>

3
app/widgets/Post/_post_ticket.tpl

@ -68,7 +68,8 @@
{if="!$post->isMicroblog()"} {if="!$post->isMicroblog()"}
{if="$post->contact"}·{/if} {if="$post->contact"}·{/if}
<a title="{$post->server} / {$post->node}"
<a class="node"
title="{$post->server} / {$post->node}"
href="{$c->route('community', [$post->server, $post->node])}"> href="{$c->route('community', [$post->server, $post->node])}">
{$post->node} {$post->node}
</a> </a>

26
lib/moxl/src/Stanza/Pubsub.php

@ -306,7 +306,7 @@ class Pubsub
\Moxl\API::request($xml); \Moxl\API::request($xml);
} }
public static function getItems($to, $node, $paging = 10, $after = false, $before = null, $skip = 0)
public static function getItems($to, $node, $paging = 10, $after = false, $before = null, $skip = 0, $query = null)
{ {
$dom = new \DOMDocument('1.0', 'UTF-8'); $dom = new \DOMDocument('1.0', 'UTF-8');
$pubsub = $dom->createElementNS('http://jabber.org/protocol/pubsub', 'pubsub'); $pubsub = $dom->createElementNS('http://jabber.org/protocol/pubsub', 'pubsub');
@ -327,7 +327,7 @@ class Pubsub
$set->appendChild($dom->createElement('max', $paging)); $set->appendChild($dom->createElement('max', $paging));
$pubsub->appendChild($set); $pubsub->appendChild($set);
} elseif ($before && $before !== null) {
} elseif ($before && $before !== null && $before != 'empty') {
$set = $dom->createElement('set'); $set = $dom->createElement('set');
$set->setAttribute('xmlns', 'http://jabber.org/protocol/rsm'); $set->setAttribute('xmlns', 'http://jabber.org/protocol/rsm');
$set->appendChild($dom->createElement('before', $before)); $set->appendChild($dom->createElement('before', $before));
@ -338,6 +338,28 @@ class Pubsub
$items->setAttribute('max_items', $paging); $items->setAttribute('max_items', $paging);
} }
if ($query) {
$x = $dom->createElement('x');
$x->setAttribute('xmlns', 'jabber:x:data');
$x->setAttribute('type', 'submit');
$pubsub->appendChild($x);
$field = $dom->createElement('field');
$field->setAttribute('var', 'FORM_TYPE');
$field->setAttribute('type', 'hidden');
$x->appendChild($field);
$value = $dom->createElement('value', 'xmpp:linkmauve.fr/gallery');
$field->appendChild($value);
$field = $dom->createElement('field');
$field->setAttribute('var', 'xmpp:linkmauve.fr/gallery#with-tag');
$x->appendChild($field);
$value = $dom->createElement('value', $query);
$field->appendChild($value);
}
$pubsub->appendChild($items); $pubsub->appendChild($items);
$xml = \Moxl\API::iqWrapper($pubsub, $to, 'get'); $xml = \Moxl\API::iqWrapper($pubsub, $to, 'get');

5
lib/moxl/src/Xec/Action/Pubsub/GetItem.php

@ -105,6 +105,11 @@ class GetItem extends Errors
$this->errorServiceUnavailable($stanza, $parent); $this->errorServiceUnavailable($stanza, $parent);
} }
public function errorBadRequest($stanza, $parent = false)
{
$this->errorServiceUnavailable($stanza, $parent);
}
public function errorServiceUnavailable($stanza, $parent = false) public function errorServiceUnavailable($stanza, $parent = false)
{ {
$pd = new PostDelete; $pd = new PostDelete;

21
lib/moxl/src/Xec/Action/Pubsub/GetItems.php

@ -15,13 +15,14 @@ class GetItems extends Errors
protected $_after; protected $_after;
protected $_before; protected $_before;
protected $_skip; protected $_skip;
protected $_query;
protected $_paginated = false; protected $_paginated = false;
public function request() public function request()
{ {
$this->store(); $this->store();
Pubsub::getItems($this->_to, $this->_node, $this->_paging, $this->_after, $this->_before, $this->_skip);
Pubsub::getItems($this->_to, $this->_node, $this->_paging, $this->_after, $this->_before, $this->_skip, $this->_query);
} }
public function setAfter($after) public function setAfter($after)
@ -45,6 +46,12 @@ class GetItems extends Errors
return $this; return $this;
} }
public function setQuery($query)
{
$this->_query = $query;
return $this;
}
public function handle($stanza, $parent = false) public function handle($stanza, $parent = false)
{ {
$ids = []; $ids = [];
@ -82,6 +89,10 @@ class GetItems extends Errors
} }
} }
if ($this->_after) {
$ids = array_reverse($ids);
}
$first = $last = $count = null; $first = $last = $count = null;
if ($stanza->pubsub->set if ($stanza->pubsub->set
@ -104,11 +115,13 @@ class GetItems extends Errors
'server' => $this->_to, 'server' => $this->_to,
'node' => $this->_node, 'node' => $this->_node,
'ids' => $ids, 'ids' => $ids,
'first' => $first,
'last' => $last,
'first' => ($this->_after) ? $last : $first,
'last' => ($this->_after) ? $first : $last,
'count' => $count, 'count' => $count,
'paginated' => $this->_paginated, 'paginated' => $this->_paginated,
'before' => $this->_before
'before' => $this->_before,
'after' => $this->_after,
'query' => $this->_query
]); ]);
$this->deliver(); $this->deliver();

35
public/theme/css/block.css

@ -81,3 +81,38 @@ ul.flex li.block {
column-count: 1; column-count: 1;
} }
} }
/* Gallery */
ul.flex.gallery li.block {
flex-direction: column;
justify-content: center;
}
ul.flex.gallery li.block p a.node,
ul.flex.gallery li.block > img + span,
ul.flex.gallery li.block > span.primary {
display: none;
}
ul.flex.gallery li.block div {
flex: initial;
text-align: center;
}
ul.flex.gallery li.block img.main {
position: relative;
opacity: 1;
height: initial;
max-height: 35rem;
max-width: calc(100% + 3rem);
width: calc(100% + 3rem);
left: 0;
top: 0;
flex: 0;
margin-bottom: 0.5rem;
}
ul.flex.gallery li.block img.main:after {
content: attr(alt);
}

2
src/Movim/Route.php

@ -22,7 +22,7 @@ class Route extends Base
'admin' => false, 'admin' => false,
'blog' => ['f', 'i'], 'blog' => ['f', 'i'],
'chat' => ['f', 'r'], 'chat' => ['f', 'r'],
'community' => ['s', 'n', 'i'],
'community' => ['s', 'n', 'i', 'q'],
'conf' => false, 'conf' => false,
'contact' => ['s'], 'contact' => ['s'],
'disconnect' => ['err'], 'disconnect' => ['err'],

Loading…
Cancel
Save