mirror of
https://github.com/kevachat/webapp.git
synced 2025-01-25 14:04:14 +00:00
implement recursive mentions folding tree
This commit is contained in:
parent
df9e860314
commit
0aca404bc0
@ -95,36 +95,32 @@ main ul
|
|||||||
|
|
||||||
main ul ul
|
main ul ul
|
||||||
{
|
{
|
||||||
margin-bottom: 16px;
|
margin-left: 24px;
|
||||||
margin-left: 16px;
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main ul > li
|
main ul li
|
||||||
{
|
{
|
||||||
margin: 8px 0;
|
border-top: 1px var(--color-default) solid;
|
||||||
padding: 8px 0;
|
|
||||||
word-wrap: break-word;
|
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;
|
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;
|
display: block;
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
main ul li > span > svg
|
main ul li span > svg
|
||||||
{
|
{
|
||||||
cursor: default;
|
cursor: default;
|
||||||
fill: var(--color-default);
|
fill: var(--color-default);
|
||||||
|
@ -103,15 +103,24 @@ class RoomController extends AbstractController
|
|||||||
// Require valid kevachat meta
|
// Require valid kevachat meta
|
||||||
if ($data = $this->_post($pending))
|
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,
|
'id' => $data->id,
|
||||||
'user' => $data->user,
|
'user' => $data->user,
|
||||||
'icon' => $data->icon,
|
'icon' => $data->icon,
|
||||||
'message' => $data->message,
|
'time' => $data->time,
|
||||||
'timestamp' => $data->time,
|
'parent' => isset($mention[1]) ? $mention[1] : null,
|
||||||
'time' => date('c', $data->time),
|
'message' => trim(
|
||||||
'pending' => true
|
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
|
|||||||
// Require valid kevachat meta
|
// Require valid kevachat meta
|
||||||
if ($data = $this->_post($post))
|
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,
|
'id' => $data->id,
|
||||||
'user' => $data->user,
|
'user' => $data->user,
|
||||||
'icon' => $data->icon,
|
'icon' => $data->icon,
|
||||||
'message' => $data->message,
|
'time' => $data->time,
|
||||||
'timestamp' => $data->time,
|
'parent' => isset($mention[1]) ? $mention[1] : null,
|
||||||
'time' => date('c', $data->time),
|
'message' => trim(
|
||||||
'pending' => false
|
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
|
|||||||
$feed
|
$feed
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Init folding &data pool
|
||||||
|
$fold = $feed;
|
||||||
|
|
||||||
|
// Build threading tree
|
||||||
|
$tree = $this->_tree(
|
||||||
|
$fold
|
||||||
|
);
|
||||||
|
|
||||||
// RSS
|
// RSS
|
||||||
if ('rss' === $request->get('feed'))
|
if ('rss' === $request->get('feed'))
|
||||||
{
|
{
|
||||||
@ -176,6 +202,7 @@ class RoomController extends AbstractController
|
|||||||
'default/room/index.html.twig',
|
'default/room/index.html.twig',
|
||||||
[
|
[
|
||||||
'feed' => $feed,
|
'feed' => $feed,
|
||||||
|
'tree' => $tree,
|
||||||
'request' => $request
|
'request' => $request
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@ -440,4 +467,36 @@ class RoomController extends AbstractController
|
|||||||
|
|
||||||
return $identicon->getImageDataUri('webp');
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
@ -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 %}
|
||||||
|
•
|
||||||
|
<a rel="nofollow" href="{{ path('room_namespace', { namespace : namespace }) }}#{{ post.id }}" title="{{ post.time | date('c') }}">{{ post.time | format_ago }}</a>
|
||||||
|
•
|
||||||
|
<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' %}
|
{% extends 'default/layout.html.twig' %}
|
||||||
{% block head_title_content %}{{ request.get('namespace') | keva_namespace_value }} - {{ 'KevaChat' | trans }}{% endblock %}
|
{% block head_title_content %}{{ request.get('namespace') | keva_namespace_value }} - {{ 'KevaChat' | trans }}{% endblock %}
|
||||||
{% block main_content %}
|
{% block main_content %}
|
||||||
@ -11,46 +57,14 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
{% if feed %}
|
{% if tree %}
|
||||||
<ul>
|
{{ recursive_post_tree(request.get('namespace'), tree) }}
|
||||||
{% 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 %}
|
|
||||||
•
|
|
||||||
<a rel="nofollow" href="{{ path('room_namespace', { namespace : request.get('namespace') }) }}#{{ post.id }}" title="{{ post.time }}">{{ post.timestamp | format_ago }}</a>
|
|
||||||
•
|
|
||||||
<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>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
{{ 'room does not contain kevachat messages' | trans }}
|
<div>
|
||||||
|
{{ 'room does not contain kevachat messages' | trans }}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user