mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 00:52:33 -04:00
implement requesting of reactions
This commit is contained in:
129
Zotlabs/Module/Request.php
Normal file
129
Zotlabs/Module/Request.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
class Request extends Controller
|
||||
{
|
||||
|
||||
private function mapVerb(string $verb) : string
|
||||
{
|
||||
$verbs = [
|
||||
'like' => 'Like',
|
||||
'dislike' => 'Dislike',
|
||||
'announce' => 'Announce',
|
||||
'attendyes' => 'Accept',
|
||||
'attendno' => 'Reject',
|
||||
'attendmaybe' => 'TentativeAccept'
|
||||
];
|
||||
|
||||
if (array_key_exists($verb, $verbs)) {
|
||||
return $verbs[$verb];
|
||||
}
|
||||
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
private function like_response($arr) {
|
||||
|
||||
$page_mode = (($arr['item']['item_thread_top'] && $_REQUEST['page_mode']) ? $_REQUEST['page_mode'] : 'r_preview');
|
||||
$conv_mode = (($_REQUEST['conv_mode']) ? $_REQUEST['conv_mode'] : 'network');
|
||||
|
||||
if ($conv_mode === 'channel') {
|
||||
$parts = explode('@', $arr['owner_xchan']['xchan_addr']);
|
||||
profile_load($parts[0]);
|
||||
}
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
if ($page_mode === 'list') {
|
||||
$items = q("SELECT item.*, item.id AS item_id FROM item
|
||||
WHERE uid = %d $item_normal
|
||||
AND parent = %d",
|
||||
intval($arr['item']['uid']),
|
||||
intval($arr['item']['parent'])
|
||||
);
|
||||
xchan_query($items, true);
|
||||
$items = fetch_post_tags($items, true);
|
||||
$items = conv_sort($items, 'commented');
|
||||
}
|
||||
else {
|
||||
$activities = q("SELECT item.*, item.id AS item_id FROM item
|
||||
WHERE uid = %d $item_normal
|
||||
AND thr_parent = '%s'
|
||||
AND verb IN ('%s', '%s', '%s', '%s', '%s', '%s', 'Accept', 'Reject', 'TentativeAccept')",
|
||||
intval($arr['item']['uid']),
|
||||
dbesc($arr['item']['mid']),
|
||||
dbesc('Like'),
|
||||
dbesc('Dislike'),
|
||||
dbesc(ACTIVITY_SHARE),
|
||||
dbesc(ACTIVITY_ATTEND),
|
||||
dbesc(ACTIVITY_ATTENDNO),
|
||||
dbesc(ACTIVITY_ATTENDMAYBE)
|
||||
);
|
||||
xchan_query($activities, true);
|
||||
$items = array_merge([$arr['item']], $activities);
|
||||
$items = fetch_post_tags($items, true);
|
||||
}
|
||||
|
||||
$ret = [
|
||||
'success' => 1,
|
||||
'orig_id' => $arr['orig_item_id'], //this is required for pubstream items where $item_id != $item['id']
|
||||
'id' => $arr['item']['id'],
|
||||
'html' => conversation($items, $conv_mode, true, $page_mode),
|
||||
];
|
||||
|
||||
// mod photos
|
||||
if (isset($_REQUEST['reload']) && $_REQUEST['reload']) {
|
||||
$ret['reload'] = 1;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
public function get() : string
|
||||
{
|
||||
|
||||
if (!local_channel()) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$verb = self::mapVerb($_GET['verb']);
|
||||
|
||||
if (!$verb) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$id = intval($_GET['id']);
|
||||
$mid = strip_tags($_GET['mid']);
|
||||
$hash = get_observer_hash();
|
||||
$item_normal = item_normal();
|
||||
|
||||
$r = q("SELECT xchan_hash, xchan_name as name, xchan_url as url, xchan_photo_s as photo FROM item
|
||||
LEFT JOIN xchan ON author_xchan = xchan_hash
|
||||
WHERE uid = %d
|
||||
AND parent = %d
|
||||
AND thr_parent = '%s'
|
||||
AND verb = '%s'
|
||||
AND item_thread_top = 0
|
||||
$item_normal",
|
||||
intval(local_channel()),
|
||||
dbesc($id),
|
||||
dbesc($mid),
|
||||
dbesc($verb)
|
||||
);
|
||||
|
||||
|
||||
|
||||
$ret = [
|
||||
'result' => $r,
|
||||
'action' => (($verb === 'Announce') ? 'jotShare' : 'dolike'),
|
||||
'action_label' => ((find_xchan_in_array($hash, $r)) ? t('- Remove yours') : t('+ Add yours'))
|
||||
];
|
||||
|
||||
json_return_and_die($ret);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1556,28 +1556,28 @@ function get_responses($conv_responses,$response_verbs,$ob,$item) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function get_response_button_text($v,$count) {
|
||||
function get_response_button_text($v, $count) {
|
||||
switch($v) {
|
||||
case 'like':
|
||||
return ['label' => tt('Like','Likes',$count,'noun'), 'icon' => 'hand-thumbs-up', 'class' => 'like', 'onclick' => 'dolike'];
|
||||
return ['label' => tt('Like','Likes',$count,'noun'), 'icon' => 'hand-thumbs-up', 'class' => 'like', 'action' => 'dolike'];
|
||||
break;
|
||||
case 'announce':
|
||||
return ['label' => tt('Repeat','Repeats',$count,'noun'), 'icon' => 'repeat', 'class' => 'announce', 'onclick' => 'jotShare'];
|
||||
return ['label' => tt('Repeat','Repeats',$count,'noun'), 'icon' => 'repeat', 'class' => 'announce', 'action' => 'jotShare'];
|
||||
break;
|
||||
case 'dislike':
|
||||
return ['label' => tt('Dislike','Dislikes',$count,'noun'), 'icon' => 'hand-thumbs-down', 'class' => 'dislike', 'onclick' => 'dolike'];
|
||||
return ['label' => tt('Dislike','Dislikes',$count,'noun'), 'icon' => 'hand-thumbs-down', 'class' => 'dislike', 'action' => 'dolike'];
|
||||
break;
|
||||
case 'comment':
|
||||
return ['label' => tt('Comment','Comments',$count,'noun'), 'icon' => 'chat', 'class' => 'comment', 'onclick' => ''];
|
||||
return ['label' => tt('Comment','Comments',$count,'noun'), 'icon' => 'chat', 'class' => 'comment', 'action' => ''];
|
||||
break;
|
||||
case 'attendyes':
|
||||
return ['label' => tt('Attending','Attending',$count,'noun'), 'icon' => 'calendar-check', 'class' => 'attendyes', 'onclick' => 'dolike'];
|
||||
return ['label' => tt('Attending','Attending',$count,'noun'), 'icon' => 'calendar-check', 'class' => 'attendyes', 'action' => 'dolike'];
|
||||
break;
|
||||
case 'attendno':
|
||||
return ['label' => tt('Not Attending','Not Attending',$count,'noun'), 'icon' => 'calendar-x', 'class' => 'attendno', 'onclick' => 'dolike'];
|
||||
return ['label' => tt('Not Attending','Not Attending',$count,'noun'), 'icon' => 'calendar-x', 'class' => 'attendno', 'action' => 'dolike'];
|
||||
break;
|
||||
case 'attendmaybe':
|
||||
return ['label' => tt('Undecided','Undecided',$count,'noun'), 'icon' => 'calendar', 'class' => 'attendmaybe', 'onclick' => 'dolike'];
|
||||
return ['label' => tt('Undecided','Undecided',$count,'noun'), 'icon' => 'calendar', 'class' => 'attendmaybe', 'action' => 'dolike'];
|
||||
break;
|
||||
default:
|
||||
return [];
|
||||
|
||||
@@ -1266,6 +1266,42 @@ function justifyPhotosAjax(id) {
|
||||
$('#' + id).justifiedGallery('norewind').on('jg.complete', function(e){ justifiedGalleryActive = false; });
|
||||
}
|
||||
|
||||
function request(id, mid, verb) {
|
||||
const modal = new bootstrap.Modal('#reactions');
|
||||
modal.show();
|
||||
|
||||
const modal_content = document.getElementById('reactions_body');
|
||||
modal_content.innerHTML = 'Loading...';
|
||||
|
||||
const modal_title = document.getElementById('reactions_title');
|
||||
modal_title.innerHTML = verb;
|
||||
|
||||
const modal_action = document.getElementById('reactions_action');
|
||||
modal_action.innerHTML = '';
|
||||
|
||||
fetch('/request?verb=' + verb + '&mid=' + mid + '&id=' + id)
|
||||
.then(response => response.json())
|
||||
.then(obj => {
|
||||
modal_content.innerHTML = '';
|
||||
|
||||
modal_action.innerHTML = '<a href="#" onclick="' + obj.action + '(' + id + ',\'' + verb + '\'); return false;">' + obj.action_label + '</a>';
|
||||
|
||||
obj.result.forEach(e => {
|
||||
modal_content.innerHTML += '<a href="' + e.url + '" class="list-group-item list-group-item-action border-0"><img src="' + e.photo + '" class="menu-img-1" loading="lazy"> ' + e.name + '</a>';
|
||||
});
|
||||
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching data:', error);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
|
||||
function dolike(ident, verb) {
|
||||
$('#like-rotator-' + ident).show();
|
||||
|
||||
|
||||
@@ -18,4 +18,19 @@
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
<div class="modal modal-sm" id="reactions" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title text-capitalize" id="reactions_title"></h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
|
||||
</div>
|
||||
<div class="modal-header" id="reactions_action">
|
||||
</div>
|
||||
<div class="modal-body list-group" id="reactions_body">
|
||||
{{$wait}}
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
{{include file="contact_edit_modal.tpl"}}
|
||||
|
||||
@@ -112,39 +112,15 @@
|
||||
{{foreach $item.responses as $verb=>$response}}
|
||||
{{if $item.reactions_allowed || (!$item.reactions_allowed && $response.count)}}
|
||||
<div class="">
|
||||
<button type="button" title="{{$response.count}} {{$response.button.label}}" class="btn btn-sm btn-link{{if !$item.my_responses.$verb}} link-secondary{{/if}} wall-item-{{$response.button.class}}"{{if $response.modal}} data-bs-toggle="modal" data-bs-target="#{{$verb}}Modal-{{$item.id}}"{{else if $response.count}} data-bs-toggle="dropdown"{{elseif $item.reactions_allowed}} onclick="{{$response.button.onclick}}({{$item.id}},'{{$verb}}'); return false;"{{/if}} id="wall-item-{{$verb}}-{{$item.id}}">
|
||||
<button type="button" title="{{$response.count}} {{$response.button.label}}" class="btn btn-sm btn-link{{if !$item.my_responses.$verb}} link-secondary{{/if}} wall-item-{{$response.button.class}}"{{if $item.reactions_allowed}} onclick="request({{$item.id}}, '{{$item.rawmid}}', '{{$verb}}'); return false;"{{/if}} id="wall-item-{{$verb}}-{{$item.id}}">
|
||||
<i class="bi bi-{{$response.button.icon}} generic-icons"></i>{{if $response.count}}<span style="display: inline-block; margin-top: -.25rem;" class="align-top">{{$response.count}}</span>{{/if}}
|
||||
</button>
|
||||
{{if $response.modal}}
|
||||
<div class="modal" id="{{$verb}}Modal-{{$item.id}}">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{$response.count}} {{$response.button.label}}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
|
||||
</div>
|
||||
{{if $item.reactions_allowed && !($verb === 'announce' && $item.my_responses.$verb)}} {{** undo announce is not yet supported **}}
|
||||
<div class="modal-header">
|
||||
<a href="#" class="text-reset" onclick="{{$response.button.onclick}}({{$item.id}},'{{$verb}}'); return false;">{{if $item.my_responses.$verb}}- {{$item.reaction_str.1}}{{else}}+ {{$item.reaction_str.0}}{{/if}}</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="modal-body response-list">
|
||||
<ul class="nav nav-pills flex-column">
|
||||
{{foreach $response.list as $liker}}
|
||||
{{$liker}}
|
||||
{{/foreach}}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="modal-footer clear">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">{{$item.modal_dismiss}}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
{{else}}
|
||||
<div class="dropdown-menu">
|
||||
{{if $item.reactions_allowed && !($verb === 'announce' && $item.my_responses.$verb)}} {{** undo announce is not yet supported **}}
|
||||
<a href="#" class="text-reset dropdown-item" onclick="{{$response.button.onclick}}({{$item.id}},'{{$verb}}'); return false;">{{if $item.my_responses.$verb}}- {{$item.reaction_str.1}}{{else}}+ {{$item.reaction_str.0}}{{/if}}</a>
|
||||
<a href="#" class="text-reset dropdown-item" onclick="{{$response.button.onclick}}('{{$item.rawmid}}','{{$verb}}'); return false;">{{if $item.my_responses.$verb}}- {{$item.reaction_str.1}}{{else}}+ {{$item.reaction_str.0}}{{/if}}</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
{{/if}}
|
||||
{{foreach $response.list as $liker}}{{$liker}}{{/foreach}}
|
||||
|
||||
Reference in New Issue
Block a user