Browse Source

implement recursive mentions folding tree

main
ghost 11 months ago
parent
commit
0aca404bc0
  1. 20
      public/css/default.css
  2. 91
      src/Controller/RoomController.php
  3. 88
      templates/default/room/index.html.twig

20
public/css/default.css

@ -95,36 +95,32 @@ main ul @@ -95,36 +95,32 @@ main ul
main ul ul
{
margin-bottom: 16px;
margin-left: 16px;
margin-top: 16px;
margin-left: 24px;
}
main ul > li
main ul li
{
margin: 8px 0;
padding: 8px 0;
border-top: 1px var(--color-default) solid;
word-wrap: break-word;
border-bottom: 1px var(--color-default) solid;
}
main ul > li:last-child
main ul li div
{
border-bottom: none;
padding: 16px 0;
}
main ul > li > p
main ul li p
{
padding: 8px 0;
}
main ul > li > p > br /* tmp solution for current twig filters implementation */
main ul li p > br /* tmp solution for current twig filters implementation */
{
display: block;
margin: 4px 0;
}
main ul li > span > svg
main ul li span > svg
{
cursor: default;
fill: var(--color-default);

91
src/Controller/RoomController.php

@ -103,15 +103,24 @@ class RoomController extends AbstractController @@ -103,15 +103,24 @@ class RoomController extends AbstractController
// Require valid kevachat meta
if ($data = $this->_post($pending))
{
$feed[] =
// Detect parent post
preg_match('/^@([A-z0-9]{64})\s/i', $data->message, $mention);
$feed[$data->id] =
[
'id' => $data->id,
'user' => $data->user,
'icon' => $data->icon,
'message' => $data->message,
'timestamp' => $data->time,
'time' => date('c', $data->time),
'pending' => true
'id' => $data->id,
'user' => $data->user,
'icon' => $data->icon,
'time' => $data->time,
'parent' => isset($mention[1]) ? $mention[1] : null,
'message' => trim(
preg_replace( // remove mention from folded message
'/^@([A-z0-9]{64})\s/i',
'',
$data->message
)
),
'pending' => true
];
}
}
@ -128,15 +137,24 @@ class RoomController extends AbstractController @@ -128,15 +137,24 @@ class RoomController extends AbstractController
// Require valid kevachat meta
if ($data = $this->_post($post))
{
$feed[] =
// Detect parent post
preg_match('/^@([A-z0-9]{64})\s/i', $data->message, $mention);
$feed[$data->id] =
[
'id' => $data->id,
'user' => $data->user,
'icon' => $data->icon,
'message' => $data->message,
'timestamp' => $data->time,
'time' => date('c', $data->time),
'pending' => false
'id' => $data->id,
'user' => $data->user,
'icon' => $data->icon,
'time' => $data->time,
'parent' => isset($mention[1]) ? $mention[1] : null,
'message' => trim(
preg_replace( // remove mention from folded message
'/^@([A-z0-9]{64})\s/i',
'',
$data->message
)
),
'pending' => false
];
}
}
@ -151,6 +169,14 @@ class RoomController extends AbstractController @@ -151,6 +169,14 @@ class RoomController extends AbstractController
$feed
);
// Init folding &data pool
$fold = $feed;
// Build threading tree
$tree = $this->_tree(
$fold
);
// RSS
if ('rss' === $request->get('feed'))
{
@ -176,6 +202,7 @@ class RoomController extends AbstractController @@ -176,6 +202,7 @@ class RoomController extends AbstractController
'default/room/index.html.twig',
[
'feed' => $feed,
'tree' => $tree,
'request' => $request
]
);
@ -440,4 +467,36 @@ class RoomController extends AbstractController @@ -440,4 +467,36 @@ class RoomController extends AbstractController
return $identicon->getImageDataUri('webp');
}
private function _tree(
array &$feed,
?string $parent = null
): array
{
$tree = [];
foreach ($feed as $post)
{
if ($post['parent'] == $parent)
{
$children = $this->_tree(
$feed,
$post['id']
);
if ($children)
{
$post['tree'] = $children;
}
$tree[$post['id']] = $post;
unset(
$feed[$post['id']]
);
}
}
return $tree;
}
}

88
templates/default/room/index.html.twig

@ -1,3 +1,49 @@ @@ -1,3 +1,49 @@
{% macro recursive_post_tree(namespace, tree) %}
{% import _self as self %}
{% if tree | length %}
<ul>
{% for post in tree %}
<li>
<div>
<a name="{{ post.id }}"></a>
{% if post.icon %}
<img src="{{ post.icon }}" alt="icon" />
{% else %}
<strong>
@{{ 'anon' | trans }}
</strong>
{% endif %}
&bull;
<a rel="nofollow" href="{{ path('room_namespace', { namespace : namespace }) }}#{{ post.id }}" title="{{ post.time | date('c') }}">{{ post.time | format_ago }}</a>
&bull;
<a rel="nofollow" href="{{ path('room_namespace', { namespace : namespace, txid : post.id }) }}#{{ post.id }}">{{ 'reply' | trans }}</a>
{% if post.pending %}
<span title="{{ 'pending in pool' | trans }}">
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71z"/>
</svg>
</span>
{% endif %}
{# apply markdown whitelist filters only to prevent ping from remote includes #}
{{
post.message | striptags
| markdown_to_html
| striptags
| message_to_markdown
| trim
| nl2br
| markdown_to_html
}}
</div>
{% if post.tree | length %}
{{ self.recursive_post_tree(namespace, post.tree) }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
{% from _self import recursive_post_tree %}
{% extends 'default/layout.html.twig' %}
{% block head_title_content %}{{ request.get('namespace') | keva_namespace_value }} - {{ 'KevaChat' | trans }}{% endblock %}
{% block main_content %}
@ -11,46 +57,14 @@ @@ -11,46 +57,14 @@
)
)
}}
{% if feed %}
<ul>
{% for post in feed %}
<li>
<a name="{{ post.id }}"></a>
{% if post.icon %}
<img src="{{ post.icon }}" alt="icon" />
{% else %}
<strong>
@{{ 'anon' | trans }}
</strong>
{% endif %}
&bull;
<a rel="nofollow" href="{{ path('room_namespace', { namespace : request.get('namespace') }) }}#{{ post.id }}" title="{{ post.time }}">{{ post.timestamp | format_ago }}</a>
&bull;
<a rel="nofollow" href="{{ path('room_namespace', { namespace : request.get('namespace'), txid : post.id }) }}#{{ post.id }}">{{ 'reply' | trans }}</a>
{% if post.pending %}
<span title="{{ 'pending in pool' | trans }}">
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71z"/>
</svg>
</span>
{% endif %}
{# apply markdown whitelist filters only to prevent ping from remote includes #}
{{
post.message | striptags
| markdown_to_html
| striptags
| message_to_markdown
| trim
| nl2br
| markdown_to_html
}}
</li>
{% endfor %}
</ul>
{% if tree %}
{{ recursive_post_tree(request.get('namespace'), tree) }}
{% else %}
<ul>
<li>
{{ 'room does not contain kevachat messages' | trans }}
<div>
{{ 'room does not contain kevachat messages' | trans }}
</div>
</li>
</ul>
{% endif %}

Loading…
Cancel
Save