paged collection improvements and some UX cleanup for jgrowl

This commit is contained in:
nobody 2020-08-06 20:19:03 -07:00
parent 10277f2329
commit 506cf9fadd
11 changed files with 207 additions and 56 deletions

View file

@ -7,7 +7,7 @@ use Zotlabs\Lib\Activity;
/**
* Class for dealing with fetching ActivityStreams collections (ordered or unordered, normal or paged).
* Construct with the object url and an optional channel to sign the request.
* Construct with either an existing object or url and an optional channel to sign requests.
* $direction is 0 (default) to fetch from the beginning, and 1 to fetch from the end and reverse order the resultant array.
* An optional limit to the number of records returned may also be specified.
* Use $class->get() to return an array of collection members.
@ -18,22 +18,26 @@ use Zotlabs\Lib\Activity;
class ASCollection {
private $url = null;
private $channel = null;
private $nextpage = null;
private $limit = 0;
private $direction = 0; // 0 = forward, 1 = reverse
private $data = [];
function __construct($url,$channel = null,$direction = 0, $limit = 0) {
function __construct($obj, $channel = null, $direction = 0, $limit = 0) {
$this->url = $url;
$this->channel = $channel;
$this->direction = $direction;
$this->limit = $limit;
$data = Activity::fetch($url,$channel);
if (is_array($obj)) {
$data = $obj;
}
if (is_string($obj)) {
$data = Activity::fetch($obj,$channel);
}
if (! is_array($data)) {
return;
}

View file

@ -2,6 +2,7 @@
namespace Zotlabs\Lib;
use App;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Access\Permissions;
use Zotlabs\Access\PermissionRoles;
@ -180,14 +181,57 @@ class Activity {
}
}
static function encode_item_collection($items,$id,$type,$activitypub = false) {
static function paged_collection_init($total,$id, $type = 'OrderedCollection') {
$ret = [
'id' => z_root() . '/' . $id,
'type' => $type,
'totalItems' => count($items),
'totalItems' => $total,
];
$numpages = $total / App::$pager['itemspage'];
$lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
$ret['first'] = z_root() . '/' . App::$query_string . '?page=1';
$ret['last'] = z_root() . '/' . App::$query_string . '?page=' . $lastpage;
return $ret;
}
static function encode_item_collection($items,$id,$type,$activitypub = false,$total = 0) {
if ($total > 100) {
$ret = [
'id' => z_root() . '/' . $id,
'type' => $type . 'Page',
];
$numpages = $total / App::$pager['itemspage'];
$lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
$stripped = preg_replace('/([&|\?]page=[0-9]*)/','',$id);
$stripped = rtrim($stripped,'/');
$ret['partOf'] = z_root() . '/' . $stripped;
if (App::$pager['page'] < $lastpage) {
$ret['next'] = z_root() . '/' . $stripped . '?page=' . (intval(App::$pager['page']) + 1);
}
if (App::$pager['page'] > 1) {
$ret['prev'] = z_root() . '/' . $stripped . '?page=' . (intval(App::$pager['page']) - 1);
}
}
else {
$ret = [
'id' => z_root() . '/' . $id,
'type' => $type,
'totalItems' => $total,
];
}
if ($items) {
$x = [];
foreach ($items as $i) {
@ -213,13 +257,37 @@ class Activity {
return $ret;
}
static function encode_follow_collection($items,$id,$type,$extra = null) {
static function encode_follow_collection($items,$id,$type,$total = 0,$extra = null) {
$ret = [
'id' => z_root() . '/' . $id,
'type' => $type,
'totalItems' => count($items),
];
if ($total > 100) {
$ret = [
'id' => z_root() . '/' . $id,
'type' => $type . 'Page',
];
$numpages = $total / App::$pager['itemspage'];
$lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
$stripped = preg_replace('/([&|\?]page=[0-9]*)/','',$id);
$stripped = rtrim($stripped,'/');
$ret['partOf'] = z_root() . '/' . $stripped;
if (App::$pager['page'] < $lastpage) {
$ret['next'] = z_root() . '/' . $stripped . '?page=' . (intval(App::$pager['page']) + 1);
}
if (App::$pager['page'] > 1) {
$ret['prev'] = z_root() . '/' . $stripped . '?page=' . (intval(App::$pager['page']) - 1);
}
}
else {
$ret = [
'id' => z_root() . '/' . $id,
'type' => $type,
'totalItems' => $total,
];
}
if ($extra) {
$ret = array_merge($ret,$extra);
}

View file

@ -492,7 +492,7 @@ class Connedit extends Controller {
Libsync::build_sync_packet(0, [ 'abook' => [ 'abook_xchan' => $orig_record['abook_xchan'], 'entry_deleted' => true ] ] );
notice( t('Connection has been removed.') . EOL );
info( t('Connection has been removed.') . EOL );
if (x($_SESSION,'return_url')) {
goaway(z_root() . '/' . $_SESSION['return_url']);
}
@ -569,7 +569,7 @@ class Connedit extends Controller {
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/block',
'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
'title' => t('Block (or Unblock) all communications with this connection'),
'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked') : ''),
),
'ignore' => array(
@ -577,7 +577,7 @@ class Connedit extends Controller {
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/ignore',
'sel' => (intval($contact['abook_ignored']) ? 'active' : ''),
'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored') : ''),
),
'censor' => array(
@ -585,7 +585,7 @@ class Connedit extends Controller {
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/censor',
'sel' => (intval($contact['abook_censor']) ? 'active' : ''),
'title' => t('Censor (or Uncensor) images from this connection'),
'info' => (intval($contact['abook_censor']) ? t('This connection is censored!') : ''),
'info' => (intval($contact['abook_censor']) ? t('This connection is censored') : ''),
),
'archive' => array(
@ -593,7 +593,7 @@ class Connedit extends Controller {
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive',
'sel' => (intval($contact['abook_archived']) ? 'active' : ''),
'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
'info' => (intval($contact['abook_archived']) ? t('This connection is archived') : ''),
),
'hide' => array(
@ -601,7 +601,7 @@ class Connedit extends Controller {
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/hide',
'sel' => (intval($contact['abook_hidden']) ? 'active' : ''),
'title' => t('Hide or Unhide this connection from your other connections'),
'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden') : ''),
),
'delete' => array(

View file

@ -40,19 +40,38 @@ class Followers extends Controller {
http_status_exit(403, 'Forbidden');
}
$r = q("select * from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'their_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0",
$t = q("select count(xchan_hash) as total from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'their_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 ",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])
);
if ($t) {
App::set_pager_total($t[0]['total']);
App::set_pager_itemspage(100);
}
if(App::$pager['unset'] && intval($t[0]['total']) > 100) {
$ret = Activity::paged_collection_init($t[0]['total'],App::$query_string);
}
else {
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
$r = q("select * from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'their_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 $pager_sql",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])
);
$ret = Activity::encode_follow_collection($r, App::$query_string, 'OrderedCollection', $t[0]['total']);
}
if (ActivityStreams::is_as_request()) {
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_follow_collection($r, App::$query_string, 'OrderedCollection'));
]], $ret);
$headers = [];

View file

@ -38,11 +38,31 @@ class Following extends Controller {
http_status_exit(403, 'Forbidden');
}
$r = q("select * from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0",
$t = q("select count(xchan_hash) as total from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])
);
if ($t) {
App::set_pager_total($t[0]['total']);
App::set_pager_itemspage(100);
}
if(App::$pager['unset'] && $t[0]['total'] > 100) {
$ret = Activity::paged_collection_init($t[0]['total'],App::$query_string);
}
else {
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
$r = q("select * from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 $pager_sql",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])
);
$ret = Activity::encode_follow_collection($r, App::$query_string, 'OrderedCollection', $t[0]['total']);
}
if (ActivityStreams::is_as_request()) {
@ -50,7 +70,7 @@ class Following extends Controller {
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_follow_collection($r, App::$query_string, 'OrderedCollection'));
]], $ret);
$headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;

View file

@ -41,36 +41,61 @@ class Outbox extends Controller {
$params['type'] = 'json';
$params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0);
$params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0);
$params['start'] = ((x($_REQUEST,'start')) ? intval($_REQUEST['start']) : 0);
$params['records'] = ((x($_REQUEST,'records')) ? intval($_REQUEST['records']) : 60);
$params['direction'] = ((x($_REQUEST,'direction')) ? dbesc($_REQUEST['direction']) : 'desc'); // unimplemented
$params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : '');
$params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 1);
$params['compat'] = 1;
$items = items_fetch(
[
'wall' => '1',
'datequery' => $params['end'],
$total = items_fetch(
[
'total' => true,
'wall' => '1',
'datequery' => $params['end'],
'datequery2' => $params['begin'],
'start' => intval($params['start']),
'records' => intval($params['records']),
'direction' => dbesc($params['direction']),
'pages' => $params['pages'],
'order' => dbesc('post'),
'top' => $params['top'],
'direction' => dbesc($params['direction']),
'pages' => $params['pages'],
'order' => dbesc('post'),
'top' => $params['top'],
'cat' => $params['cat'],
'compat' => $params['compat']
], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module
'compat' => $params['compat']
], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module
);
if ($total) {
App::set_pager_total($total);
App::set_pager_itemspage(100);
}
if(App::$pager['unset'] && $total > 100) {
$ret = Activity::paged_collection_init($total,App::$query_string);
}
else {
$items = items_fetch(
[
'wall' => '1',
'datequery' => $params['end'],
'datequery2' => $params['begin'],
'records' => intval(App::$pager['itemspage']),
'start' => intval(App::$pager['start']),
'direction' => dbesc($params['direction']),
'pages' => $params['pages'],
'order' => dbesc('post'),
'top' => $params['top'],
'cat' => $params['cat'],
'compat' => $params['compat']
], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module
);
$ret = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection',true, $total);
}
if(ActivityStreams::is_as_request()) {
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection',true));
]], $ret);
$headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;

View file

@ -120,7 +120,7 @@ class Stream extends Controller {
if ($update) {
killme();
}
notice( t('No such group') . EOL );
notice( t('Access list not found') . EOL );
goaway(z_root() . '/stream');
}
@ -262,7 +262,7 @@ class Stream extends Controller {
if ($x) {
$title = replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => t('Access list: ') . $x['gname']
'$title' => sprintf( t('Access list: %s'), $x['gname']);
));
}

View file

@ -936,6 +936,7 @@ class App {
* pagination
*/
self::$pager['unset'] = ((array_key_exists('page',$_REQUEST)) ? false : true);
self::$pager['page'] = ((x($_GET,'page') && intval($_GET['page']) > 0) ? intval($_GET['page']) : 1);
self::$pager['itemspage'] = 60;
self::$pager['start'] = (self::$pager['page'] * self::$pager['itemspage']) - self::$pager['itemspage'];

View file

@ -3987,7 +3987,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
intval($uid)
);
if(! $r) {
$result['message'] = t('Privacy group not found.');
$result['message'] = t('Access list not found.');
return $result;
}
@ -4010,7 +4010,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str)) or allow_gid like '" . protect_sprintf('%<' . dbesc($r[0]['hash']) . '>%') . "' ) and id = parent $item_normal ) ";
$x = AccessList::rec_byhash($uid,$r[0]['hash']);
$result['headline'] = sprintf( t('Privacy group: %s'),$x['gname']);
$result['headline'] = sprintf( t('Access list: %s'),$x['gname']);
}
elseif($arr['cid'] && $uid) {
@ -4022,7 +4022,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval($arr['uid']) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) $item_normal ) ";
$result['headline'] = sprintf( t('Connection: %s'),$r[0]['xchan_name']);
} else {
$result['message'] = t('Connection not found.');
$result['message'] = t('Channel not found.');
return $result;
}
}
@ -4061,9 +4061,11 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
// only setup pagination on initial page view
$pager_sql = '';
} else {
$itemspage = (($channel) ? get_pconfig($uid,'system','itemspage') : 20);
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
if(! $arr['total']) {
$itemspage = (($channel) ? get_pconfig($uid,'system','itemspage') : 20);
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
}
}
if (isset($arr['start']) && isset($arr['records']))
@ -4112,6 +4114,18 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
// "New Item View" - show all items unthreaded in reverse created date order
if ($arr['total']) {
$items = q("SELECT count(item.id) AS total FROM item
WHERE $item_uids $item_restrict
$simple_update
$sql_extra $sql_nets $sql_extra3"
);
if ($items) {
return intval($items[0]['total']);
}
return 0;
}
$items = q("SELECT item.*, item.id AS item_id FROM item
WHERE $item_uids $item_restrict
$simple_update
@ -4119,12 +4133,12 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
ORDER BY item.received DESC $pager_sql"
);
require_once('include/items.php');
xchan_query($items);
$items = fetch_post_tags($items,true);
} else {
}
else {
// Normal conversation view

View file

@ -598,11 +598,11 @@ function notificationsUpdate(cached_data) {
$.jGrowl.defaults.closerTemplate = '<div>[ ' + aStr.closeAll + ']</div>';
$(data.notice).each(function() {
$.jGrowl(this.message, { sticky: true, theme: 'notice' });
$.jGrowl(this.message, { sticky: false, theme: 'notice', life: 10000 });
});
$(data.info).each(function(){
$.jGrowl(this.message, { sticky: false, theme: 'info', life: 10000 });
$.jGrowl(this.message, { sticky: false, theme: 'info' });
});
});
}

View file

@ -799,12 +799,12 @@ nav .acpopup {
/* popup notifications */
div.jGrowl div.notice {
background: #511919 url("../../../../images/icons/48/notice.png") no-repeat 5px center;
background: #aa3311 url("../../../../images/icons/48/notice.png") no-repeat 5px center;
color: #ffffff;
padding-left: 58px;
}
div.jGrowl div.info {
background: #364e59 url("../../../../images/icons/48/info.png") no-repeat 5px center;
background: #2244aa url("../../../../images/icons/48/info.png") no-repeat 5px center;
color: #ffffff;
padding-left: 58px;
}