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"))
|
.append($("<lh><strong>Actions</strong></lh>").addClass("post_menu_item"))
|
||||||
.addClass("post_menu_items");
|
.addClass("post_menu_items");
|
||||||
window.menuItemFactories.forEach(factory => {
|
window.menuItemFactories.forEach(factory => {
|
||||||
item = factory(sender.parentElement);
|
let postElement = $(sender).closest(".post");
|
||||||
|
item = factory(postElement[0]);
|
||||||
menuList.append(
|
menuList.append(
|
||||||
$("<li></li>")
|
$("<li></li>")
|
||||||
.addClass("post_menu_item")
|
.addClass("post_menu_item")
|
||||||
@@ -204,6 +205,52 @@ function openReportWindow(reportUrl) {
|
|||||||
reportWindow.show();
|
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
|
// Events
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -215,7 +262,8 @@ $(window.top).on("load", () => {
|
|||||||
window.top.jsFrame = new JSFrame();
|
window.top.jsFrame = new JSFrame();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$(window).on("load", (e) => {
|
// This on("load") sets up more events
|
||||||
|
$(window).on("load", () => {
|
||||||
$(".post_image").on("mouseover", (e) => {
|
$(".post_image").on("mouseover", (e) => {
|
||||||
// Load the original image and display it
|
// Load the original image and display it
|
||||||
let thumbnail = e.target;
|
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 = [];
|
||||||
window.menuItemFactories.push(
|
window.menuItemFactories.push(
|
||||||
(postElement) =>
|
(postElement) =>
|
||||||
@@ -278,3 +349,21 @@ window.menuItemFactories.push(
|
|||||||
openReportWindow($(postElement).attr("data-report-url"));
|
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;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post {
|
.thread {
|
||||||
background-color: var(--post-background);
|
background-color: var(--post-background);
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
@@ -140,6 +140,18 @@ th {
|
|||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thread_hide_button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thread_show_button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post_hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
#image_hover {
|
#image_hover {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
|
|||||||
@@ -31,9 +31,9 @@
|
|||||||
<hr />
|
<hr />
|
||||||
{# posts #}
|
{# posts #}
|
||||||
{% for post in threads %}
|
{% 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 #}
|
{# 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" %}
|
{% include "board/post_snippet.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<hr />
|
<hr />
|
||||||
{# posts #}
|
{# posts #}
|
||||||
<div class="row post">
|
<div class="row thread">
|
||||||
{% include "board/post_snippet.html" %}
|
{% include "board/post_snippet.html" %}
|
||||||
{% for post in post.replies.all %}
|
{% for post in post.replies.all %}
|
||||||
<div class="row reply">
|
<div class="row reply">
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div
|
<div
|
||||||
id="p{{post.id}}"
|
id="p{{post.id}}"
|
||||||
|
class="post"
|
||||||
data-report-url="{% url 'board:report_form' board.url post.id %}"
|
data-report-url="{% url 'board:report_form' board.url post.id %}"
|
||||||
{% if perms.board.add_ban %}
|
{% if perms.board.add_ban %}
|
||||||
data-ban-url="{% url 'board:ban_create' board.url post.id %}"
|
data-ban-url="{% url 'board:ban_create' board.url post.id %}"
|
||||||
@@ -11,60 +12,69 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
>
|
>
|
||||||
|
|
||||||
{# Post ID, status icons, username, time #}
|
<div class="post_title">
|
||||||
{% if post.sticky and not post.op %}
|
{# Hide post button #}
|
||||||
<span title="Stickied" class="fa fa-thumb-tack"></span>
|
{% if thread_hide_button %}
|
||||||
{% endif %}
|
<span class="fa fa-minus-square thread_hide_button"></span>
|
||||||
{% if post.lock and not post.op %}
|
{% endif %}
|
||||||
<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>
|
|
||||||
|
|
||||||
{# Image #}
|
{# Post ID, status icons, username, time #}
|
||||||
{% if post.thumbnail %}
|
<a href="#p{{post.id}}">#.</a>
|
||||||
{# Image info #}
|
<span class="post_id">{{post.id}}</span>
|
||||||
<div class="post_image_info">
|
{% if post.subject %}
|
||||||
{% translate "File" %}
|
<span class="post_subject">{{post.subject}}</span>
|
||||||
<a href="{{post.image.url}}" target="_blank">{{post.original_image_name}}</a>
|
{% endif %}
|
||||||
({{post.image.size|measure_bytes}}, {{post.image_width}}x{{post.image_height}})
|
{% 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>
|
||||||
|
|
||||||
{# 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 %}
|
|
||||||
|
|
||||||
{# "X replies elided" dialog for OPs on the board #}
|
|
||||||
<div class="post_content">
|
<div class="post_content">
|
||||||
{% if replies_elided > 0 %}
|
{# Image #}
|
||||||
<br/>
|
{% if post.thumbnail %}
|
||||||
<span class="replies_elided">
|
{# Image info #}
|
||||||
({% blocktranslate %}{{replies_elided}} replies elided, click reply to view{% endblocktranslate %})
|
<div class="post_image_info">
|
||||||
</span>
|
{% translate "File" %}
|
||||||
{% endif %}
|
<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>
|
||||||
|
|
||||||
{# Post body #}
|
{# Image thumbnail #}
|
||||||
<p class="post_body">{{post|post_body|safe}}</p>
|
<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 %}
|
||||||
|
|
||||||
|
{# "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 %}
|
||||||
|
|
||||||
|
{# Post body #}
|
||||||
|
<p class="post_body">{{post|post_body|safe}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
Reference in New Issue
Block a user