rDrama/files/templates/comments.html
TLSM 6fde14a92c Use reddit-style notifs without context
The notifications schema is already set up for reddit-style
chronological notifications. We simply have to remove the logic that
builds the context and patch up a few places in the frontend that
were expecting full reply trees.

`Comment.header_msg` previously expected the user's own comment to
be top-level in comment replies. Logic is revised to expect the actual
reply.

`files.routes.front.notifications_main` now has reduced query volume
because we aren't expiring the session when marking notifications read.
This also allows us to remove the unused `comms` variable, which is a
makeshift "pattern" of storing duplicate database replies across a
commit so the templates don't requery (thus losing data attached to
the runtime object, like `c.unread` / `c.notif_utc`).

We move the `is_notification_page` flag to the route callers rather
than templates checking `request.path`.

Minor UI style: "Clear all notifications" -> "Mark All Read", since
this was a persistent point of user confusion upstream, with people
expecting their inbox to empty out. Also less margin between notifs
to be consistent with tighter comment display elsewhere and removed
need to separate groups of comments vs single comments.
2023-07-12 00:24:50 -05:00

273 lines
10 KiB
HTML

{%- include "component/comment/usernote_header.html" -%}
{# "level" represents the nested level in this call; always starts at 1 #}
{# this is distinct from "comment.level", which is the global depth of this comment #}
{% macro single_comment(c, level) %}
{%- if render_ctx is not defined -%}
{% set render_ctx = 'comments' %}
{%- endif -%}
{%- set ups = c.upvotes_str(render_ctx) -%}
{%- set score = c.score_str(render_ctx) -%}
{%- set downs = c.downvotes_str(render_ctx) -%}
{% set replies = c.replies(v) %}
{% if not c.visibility_state(v)[0] %}
{% if c.show_descendants(v) %}
<div id="comment-{{c.id}}" class="comment">
<div class="comment-collapse-icon" onclick="collapse_comment('{{c.id}}', this.parentElement)"></div>
<div class="comment-collapse-bar-click" onclick="collapse_comment('{{c.id}}', this.parentElement)">
<div class="comment-collapse-bar"></div>
</div>
<div class="comment-user-info">
{% if standalone and c.over_18 %}<span class="badge badge-danger">+18</span>{% endif %}
{{c.visibility_state(v)[1]}}
</div>
<div class="comment-body">
<div id="comment-{{c.id}}-only" class="comment-{{c.id}}-only"></div>
{% if render_replies %}
{% if level <= RENDER_DEPTH_LIMIT - 1 %}
<div id="replies-of-{{c.id}}" class="">
{% set standalone=False %}
{% for reply in replies %}
{{single_comment(reply, level=level+1)}}
{% endfor %}
</div>
{% elif replies and is_notification_page %}
<div id="replies-of-{{c.id}}" class="d-none d-md-block">
{% set standalone=False %}
{% for reply in replies %}
{{single_comment(reply, level=level+1)}}
{% endfor %}
</div>
<div id="morecomment-{{c.id}}" class="d-md-none mt-2 more-comments">
<a href="{{c.morecomments}}">More comments <i class="fas fa-long-arrow-right ml-1"></i></a>
</div>
{% elif replies %}
<div id="morecomment-{{c.id}}" class="mt-2 more-comments">
<button id="btn-{{c.id}}" class="d-none d-md-block btn btn-primary" onclick="morecomments('{{c.id}}')">More comments ({{c.descendant_count}})</button>
<a class="d-md-none" href="{{c.morecomments}}">More comments <i class="fas fa-long-arrow-right ml-1"></i></a>
</div>
{% endif %}
{% endif %}
</div>
</div>
{% endif %}
{% else %}
{%- set voted = c.voted_display(v) -%}
{% if standalone and level==1 %}
<div class="post-info post-row-cid-{{c.id}} mb-1 mr-2 mt-3">
{% if c.post and c.post.over_18 %}<span class="badge badge-danger text-small-extra mr-1">+18</span>{% endif %}
<span class="align-top">
<span class="font-weight-bold">{{c.header_msg(v, is_notification_page) | safe}}</span>
</span>
</div>
{% endif %}
{% set isreply = not standalone and c.parent_comment and c.parent_comment.sentto %}
<div id="comment-{{c.id}}" class="anchor comment {% if standalone and level==1 %} mt-0{% endif %} {% if c.collapse_for_user(v,request.path) %}collapsed{% endif %}">
{% if not isreply %}
<div class="comment-collapse-icon" onclick="collapse_comment('{{c.id}}', this.parentElement)"></div>
<div class="comment-collapse-bar-click" onclick="collapse_comment('{{c.id}}', this.parentElement)">
<div class="comment-collapse-bar collapse-bar-{{(c.level + 6) % 8 + 1}}"></div>
</div>
{% endif %}
{%- include 'component/comment/user_info.html' -%}
<div class="comment-body">
<div id="{% if comment_info and comment_info.id == c.id %}context{%else%}comment-{{c.id}}-only{% endif %}" class="{% if c.unread %}unread{% endif %} comment-{{c.id}}-only comment-anchor {% if comment_info and comment_info.id == c.id %}context{%endif%}{% if c.state_mod == StateMod.REMOVED %} removed{% endif %}{% if c.state_mod == StateMod.FILTERED %} filtered{% endif %}{% if c.state_user_deleted_utc %} deleted{% endif %}">
{%- include 'component/comment/reports.html'-%}
{% if c.state_mod == StateMod.REMOVED and c.state_mod_set_by and v and v.admin_level >= 2 %}
<div id="comment-banned-warning" class="comment-text text-removed mb-0">removed by @{{c.state_mod_set_by}}</div>
{% endif %}
<div id="comment-text-{{c.id}}" class="comment-text mb-0">
{{c.realbody(v) | safe}}
</div>
{% if c.parent_submission %}
{%- include 'component/comment/editbox_comment.html' -%}
<div id="comment-{{c.id}}-actions" class="comment-actions{% if voted==1 %} upvoted{% elif voted==-1 %} downvoted{% endif %}">
<div class="d-md-none mt-2">
<div class="post-actions">
<ul class="list-inline text-right d-flex">
{% if v and v.admin_level >= 2 %}
<li class="list-inline-item mr-auto">
<a role="button" data-bs-toggle="modal" data-bs-target="#adminModal-{{c.id}}"> <i class="fas fa-broom"></i></a>
</li>
{% endif %}
{% if v %}
<a class="list-inline-item mr-3" role="button" onclick="openReplyBox('reply-to-{{c.id}}')"><i class="fas fa-reply" style="margin-top:0.35rem"></i></a>
{% endif %}
<li class="list-inline-item">
<a role="button" data-bs-toggle="modal" data-bs-target="#actionsModal-{{c.id}}"> <i class="fas fa-ellipsis-h mt-1"></i></a>
</li>
{%- include 'component/comment/voting_mobile.html' -%}
</ul>
</div>
</div>
<ul class="d-none d-md-flex list-inline text-right text-md-left">
<li>
{%- include 'component/comment/voting_desktop.html' -%}
{%- include 'component/comment/actions_desktop.html' -%}
</li>
</ul>
</div>
{% endif %}
</div>
{% if v and v.id != c.author_id and c.body %}
<textarea autocomplete="off" class="d-none card border my-2 p-3 comment-box form-control rounded" id="markdown-{{c.id}}" readonly>{{c.body.strip()}}</textarea>
{% endif %}
{%- include 'component/comment/replybox_comment.html' -%}
{% if render_replies %}
{% if level <= RENDER_DEPTH_LIMIT - 1 or is_notification_page %}
<div id="replies-of-{{c.id}}">
{% for reply in replies %}
{{single_comment(reply, level=level+1)}}
{% endfor %}
</div>
{% elif replies %}
<div id="morecomments-{{c.id}}" class="mt-2 more-comments">
<button id="btn-{{c.id}}" class="d-none d-md-block btn btn-primary" onclick="morecomments('{{c.id}}')">More comments ({{c.descendant_count}})</button>
<a class="d-md-none" href="{{c.morecomments}}">More comments <i class="fas fa-long-arrow-right ml-1"></i></a>
</div>
{% endif %}
{% if is_notification_page and c.level == 1 and c.is_strict_message and c.author_id not in (NOTIFICATIONS_ID, AUTOJANNY_ID) %}
{%- include 'component/comment/replybox_message.html' -%}
{% endif %}
{% else %}
<div id="replies-of-{{c.id}}"></div>
{% endif %}
</div>
{%- include 'component/comment/actions_mobile.html' -%}
{% if v and v.admin_level >= 2 %}
{%- include 'component/comment/actions_mobile_admin.html' -%}
{% endif %}
</div>
{% endif %}
{% endmacro %}
{% for comment in comments %}
{%- set parent_level = parent_level | int if parent_level else 0 -%}
{{single_comment(comment, level = parent_level + 1)}}
{% endfor %}
{%- include 'component/comment/view_more_button.html' -%}
{% if not ajax %}
{% if v %}
{% if v.admin_level >= 2 %}
{% include "component/modal/ban.html" %}
{% endif %}
{%- include 'component/modal/delete_comment.html' -%}
{%- include 'component/modal/report_comment.html' -%}
{% endif %}
{% if v %}
<script src="{{ 'js/vendor/purify.min.js' | asset }}"></script>
<script src="{{ 'js/vendor/marked.min.js' | asset }}"></script>
<script src="{{ 'js/marked.custom.js' | asset }}"></script>
<script src="{{ 'js/comments_v.js' | asset }}"></script>
{% if FEATURES['AWARDS'] %}
<script src="{{ 'js/award_modal.js' | asset }}"></script>
{% endif %}
{% endif %}
<script src="{{ 'js/clipboard.js' | asset }}"></script>
{% if v %}
{% if v.admin_level >= 2 %}
<script src="{{ 'js/comments_admin.js' | asset }}"></script>
{% endif %}
{% if v.admin_level >= 2 %}
<script src="{{ 'js/filter_actions.js' | asset }}"></script>
{% endif %}
{% endif %}
{% include "component/modal/expanded_image.html" %}
<script src="{{ 'js/comments+submission_listing.js' | asset }}"></script>
<script src="{{ 'js/comments.js' | asset }}"></script>
<script>
{% if p and (not v or v.highlightcomments) %}
comments = JSON.parse(localStorage.getItem("comment-counts")) || {}
lastCount = comments['{{p.id}}']
if (lastCount)
{
{% for c in p.comments %}
{% if not (v and v.id==c.author_id) and not c.voted %}
if ({{c.created_utc*1000}} > lastCount.t)
try {
document.getElementById("comment-{{c.id}}-only").classList.add('unread')
document.getElementById("comment-{{c.id}}").querySelector(".comment-user-info").innerHTML += "<span>~new~</span>";
}
catch(e) {}
{% endif %}
{% endfor %}
}
{% endif %}
{% if p and not (request.values and ('context' in request.values)) %}
collapsedCommentStorageInit('post_{{p.id}}');
{% elif is_notification_page or request.path.startswith('/@') %}
collapsedCommentStorageInit('{{request.path}}');
{% endif %}
if (document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)) {
collapsedCommentStorageApply();
} else {
document.addEventListener("DOMContentLoaded", collapsedCommentStorageApply);
}
function morecomments(cid) {
btn = document.getElementById(`btn-${cid}`);
btn.disabled = true;
btn.innerHTML = "Requesting...";
var form = new FormData();
form.append("formkey", formkey());
const xhr = new XMLHttpRequest();
xhr.open("get", `/morecomments/${cid}`);
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload=function(){
if (xhr.status==200) {
let e = document.getElementById(`morecomments-${cid}`)
e.innerHTML = xhr.response.replace(/data-src/g, 'src').replace(/data-cfsrc/g, 'src').replace(/style="display:none;visibility:hidden;"/g, '');
bs_trigger(e)
{% if p %}
comments = JSON.parse(localStorage.getItem("old-comment-counts")) || {}
lastCount = comments['{{p.id}}']
if (lastCount)
{
{% for c in p.comments %}
{% if not (v and v.id==c.author_id) and not c.voted %}
if ({{c.created_utc*1000}} > lastCount.t)
try {
document.getElementById("comment-{{c.id}}-only").classList.add('unread')
document.getElementById("comment-{{c.id}}").querySelector(".comment-user-info").innerHTML += "<span>~new~</span>";
}
catch(e) {}
{% endif %}
{% endfor %}
}
{% endif %}
}
btn.disabled = false;
}
xhr.send(form)
}
</script>
{% endif %}