Add post hiding
This allows users to hide posts that they may find unsavory. On threads themselves in the board view, this adds a minus/plus button that will toggle back and forth if hidden. This also adds a post menu item that will toggle a post being hidden. This also changes the post snippet layout a little bit. This caused minor issues with the other menu items, but it should be fixed in this set of changes too. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -65,7 +65,8 @@ function openMenu(e) {
|
||||
.append($("<lh><strong>Actions</strong></lh>").addClass("post_menu_item"))
|
||||
.addClass("post_menu_items");
|
||||
window.menuItemFactories.forEach(factory => {
|
||||
item = factory(sender.parentElement);
|
||||
let postElement = $(sender).closest(".post");
|
||||
item = factory(postElement[0]);
|
||||
menuList.append(
|
||||
$("<li></li>")
|
||||
.addClass("post_menu_item")
|
||||
@@ -204,6 +205,52 @@ function openReportWindow(reportUrl) {
|
||||
reportWindow.show();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Post hiding
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function getHiddenPosts() {
|
||||
let hiddenPosts = JSON.parse(localStorage.getItem("hidden_posts"));
|
||||
if (hiddenPosts === null) {
|
||||
return [];
|
||||
} else {
|
||||
return hiddenPosts;
|
||||
}
|
||||
}
|
||||
|
||||
function addHiddenPost(postId) {
|
||||
let hiddenPosts = getHiddenPosts();
|
||||
if (!hiddenPosts.includes(postId)) {
|
||||
hiddenPosts.push(postId);
|
||||
}
|
||||
localStorage.setItem("hidden_posts", JSON.stringify(hiddenPosts));
|
||||
}
|
||||
|
||||
function removeHiddenPost(postId) {
|
||||
let hiddenPosts = getHiddenPosts().filter((item) => item !== postId);
|
||||
localStorage.setItem("hidden_posts", JSON.stringify(hiddenPosts));
|
||||
}
|
||||
|
||||
function hidePost(postId) {
|
||||
$(postId + " > .reply").addClass("post_hidden");
|
||||
$(postId + " > .post_content").addClass("post_hidden");
|
||||
$(postId + " >>> .thread_hide_button")
|
||||
.addClass("fa-plus-square")
|
||||
.addClass("thread_show_button")
|
||||
.removeClass("fa-minus-square")
|
||||
.removeClass("thread_hide_button");
|
||||
}
|
||||
|
||||
function unhidePost(postId) {
|
||||
$(postId + " > .reply").removeClass("post_hidden");
|
||||
$(postId + " > .post_content").removeClass("post_hidden");
|
||||
$(postId + " >>> .thread_show_button")
|
||||
.removeClass("fa-plus-square")
|
||||
.removeClass("thread_show_button")
|
||||
.addClass("fa-minus-square")
|
||||
.addClass("thread_hide_button");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Events
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -215,7 +262,8 @@ $(window.top).on("load", () => {
|
||||
window.top.jsFrame = new JSFrame();
|
||||
}
|
||||
});
|
||||
$(window).on("load", (e) => {
|
||||
// This on("load") sets up more events
|
||||
$(window).on("load", () => {
|
||||
$(".post_image").on("mouseover", (e) => {
|
||||
// Load the original image and display it
|
||||
let thumbnail = e.target;
|
||||
@@ -267,6 +315,29 @@ $(window).on("load", (e) => {
|
||||
});
|
||||
});
|
||||
|
||||
// Load event that actually does stuff
|
||||
$(window).on("load", () => {
|
||||
getHiddenPosts().forEach(item => hidePost(item));
|
||||
});
|
||||
|
||||
// $(document).on("click", ...) is used for dynamic event dispatch.
|
||||
// Since these elements are going to have their classes changed, doing a typical
|
||||
// $(".class").on(...) method won't fire on elements that don't have the
|
||||
// expected class name when the hook is created.
|
||||
// Don't change this.
|
||||
$(document).on("click", ".thread_hide_button", (e) => {
|
||||
e.preventDefault();
|
||||
let id = "#" + $(e.target).closest(".post").attr("id");
|
||||
hidePost(id);
|
||||
addHiddenPost(id);
|
||||
});
|
||||
$(document).on("click", ".thread_show_button", (e) => {
|
||||
e.preventDefault();
|
||||
let id = "#" + $(e.target).closest(".post").attr("id");
|
||||
unhidePost(id);
|
||||
removeHiddenPost(id);
|
||||
});
|
||||
|
||||
window.menuItemFactories = [];
|
||||
window.menuItemFactories.push(
|
||||
(postElement) =>
|
||||
@@ -278,3 +349,21 @@ window.menuItemFactories.push(
|
||||
openReportWindow($(postElement).attr("data-report-url"));
|
||||
})
|
||||
);
|
||||
window.menuItemFactories.push(
|
||||
(postElement) =>
|
||||
$("<a>")
|
||||
.text("Toggle hide")
|
||||
.attr("href", "#")
|
||||
.on("click", (e) => {
|
||||
e.preventDefault();
|
||||
let id = "#" + $(postElement).attr("id");
|
||||
let hiddenPosts = getHiddenPosts();
|
||||
if (hiddenPosts.includes(id)) {
|
||||
unhidePost(id);
|
||||
removeHiddenPost(id);
|
||||
} else {
|
||||
hidePost(id);
|
||||
addHiddenPost(id);
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -112,7 +112,7 @@ th {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.post {
|
||||
.thread {
|
||||
background-color: var(--post-background);
|
||||
padding: 10px;
|
||||
}
|
||||
@@ -140,6 +140,18 @@ th {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.thread_hide_button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.thread_show_button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.post_hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#image_hover {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
<hr />
|
||||
{# posts #}
|
||||
{% for post in threads %}
|
||||
<div class="row post" id="p{{post.id}}">
|
||||
<div class="row thread" id="p{{post.id}}">
|
||||
{# TODO we need some way to parameterize the last N threads #}
|
||||
{% with reply_link=True replies_elided=post.replies.all|length|add:"-3" %}
|
||||
{% with reply_link=True thread_hide_button=True replies_elided=post.replies.all|length|add:"-3" %}
|
||||
{% include "board/post_snippet.html" %}
|
||||
{% endwith %}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
</span>
|
||||
<hr />
|
||||
{# posts #}
|
||||
<div class="row post">
|
||||
<div class="row thread">
|
||||
{% include "board/post_snippet.html" %}
|
||||
{% for post in post.replies.all %}
|
||||
<div class="row reply">
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{% load i18n %}
|
||||
<div
|
||||
id="p{{post.id}}"
|
||||
class="post"
|
||||
data-report-url="{% url 'board:report_form' board.url post.id %}"
|
||||
{% if perms.board.add_ban %}
|
||||
data-ban-url="{% url 'board:ban_create' board.url post.id %}"
|
||||
@@ -11,60 +12,69 @@
|
||||
{% endif %}
|
||||
>
|
||||
|
||||
{# Post ID, status icons, username, time #}
|
||||
{% if post.sticky and not post.op %}
|
||||
<span title="Stickied" class="fa fa-thumb-tack"></span>
|
||||
{% endif %}
|
||||
{% if post.lock and not post.op %}
|
||||
<span title="Locked" class="fa fa-lock"></span>
|
||||
{% endif %}
|
||||
<a href="#p{{post.id}}">#.</a>
|
||||
<span class="post_id">{{post.id}}</span>
|
||||
{% if post.subject %}
|
||||
<span class="post_subject">{{post.subject}}</span>
|
||||
{% endif %}
|
||||
{% blocktranslate with post_name=post.name|default:"Anonymous" %}
|
||||
by
|
||||
<span class="post_name">{{post_name}}</span>
|
||||
{% endblocktranslate %}
|
||||
{% if post.capcode %}
|
||||
<span class="post_capcode" style="color: {{post.capcode.color}};">{{post.capcode}}</span>
|
||||
{% endif %}
|
||||
{% blocktranslate with post_created=post.created %}
|
||||
at {{post_created}}
|
||||
{% endblocktranslate %}
|
||||
{% if reply_link %}
|
||||
[<a href="{{post.get_absolute_url}}">{% translate "Reply" %}</a>]
|
||||
{% endif %}
|
||||
<a href="#" class="post_menu_button" data-id="post_menu_button">▶</a>
|
||||
<div class="post_title">
|
||||
{# Hide post button #}
|
||||
{% if thread_hide_button %}
|
||||
<span class="fa fa-minus-square thread_hide_button"></span>
|
||||
{% endif %}
|
||||
|
||||
{# Image #}
|
||||
{% if post.thumbnail %}
|
||||
{# Image info #}
|
||||
<div class="post_image_info">
|
||||
{# Post ID, status icons, username, time #}
|
||||
<a href="#p{{post.id}}">#.</a>
|
||||
<span class="post_id">{{post.id}}</span>
|
||||
{% if post.subject %}
|
||||
<span class="post_subject">{{post.subject}}</span>
|
||||
{% endif %}
|
||||
{% blocktranslate with post_name=post.name|default:"Anonymous" %}
|
||||
by
|
||||
<span class="post_name">{{post_name}}</span>
|
||||
{% endblocktranslate %}
|
||||
{% if post.capcode %}
|
||||
<span class="post_capcode" style="color: {{post.capcode.color}};">{{post.capcode}}</span>
|
||||
{% endif %}
|
||||
{% blocktranslate with post_created=post.created %}
|
||||
at {{post_created}}
|
||||
{% endblocktranslate %}
|
||||
|
||||
{% if post.sticky and not post.op %}
|
||||
<span title="Stickied" class="fa fa-thumb-tack"></span>
|
||||
{% endif %}
|
||||
{% if post.lock and not post.op %}
|
||||
<span title="Locked" class="fa fa-lock"></span>
|
||||
{% endif %}
|
||||
|
||||
{% if reply_link %}
|
||||
[<a href="{{post.get_absolute_url}}">{% translate "Reply" %}</a>]
|
||||
{% endif %}
|
||||
<a href="#" class="post_menu_button" data-id="post_menu_button">▶</a>
|
||||
</div>
|
||||
|
||||
<div class="post_content">
|
||||
{# Image #}
|
||||
{% if post.thumbnail %}
|
||||
{# Image info #}
|
||||
<div class="post_image_info">
|
||||
{% translate "File" %}
|
||||
<a href="{{post.image.url}}" target="_blank">{{post.original_image_name}}</a>
|
||||
({{post.image.size|measure_bytes}}, {{post.image_width}}x{{post.image_height}})
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Image thumbnail #}
|
||||
<div class="post_image_thumbnail">
|
||||
{# Image thumbnail #}
|
||||
<div class="post_image_thumbnail">
|
||||
<a href="{{post.image.url}}" target="_blank">
|
||||
<img class="post_image" src="{{post.thumbnail.url}}" data-url="{{post.image.url}}" data-thumb="{{post.thumbnail.url}}">
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# "X replies elided" dialog for OPs on the board #}
|
||||
<div class="post_content">
|
||||
{% if replies_elided > 0 %}
|
||||
<br/>
|
||||
<span class="replies_elided">
|
||||
{# "X replies elided" dialog for OPs on the board #}
|
||||
{% if replies_elided > 0 %}
|
||||
<br/>
|
||||
<span class="replies_elided">
|
||||
({% blocktranslate %}{{replies_elided}} replies elided, click reply to view{% endblocktranslate %})
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{# Post body #}
|
||||
<p class="post_body">{{post|post_body|safe}}</p>
|
||||
{# Post body #}
|
||||
<p class="post_body">{{post|post_body|safe}}</p>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user