mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
43a09e14a9
17 changed files with 289 additions and 66 deletions
|
@ -359,8 +359,7 @@ h1 .fe-bell, h1 .fe-no-bell {
|
|||
top: 2px;
|
||||
}
|
||||
.fe-poll:before {
|
||||
content: "\e91b";
|
||||
/* possibly e985 */
|
||||
content: "\e91b"; /* possibly e985 */
|
||||
}
|
||||
|
||||
.fe-sticky-left::before {
|
||||
|
@ -513,25 +512,20 @@ a {
|
|||
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
/* Adjust as needed to hide the link off-screen */
|
||||
top: -40px; /* Adjust as needed to hide the link off-screen */
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
/* Background color to cover the link for screen readers */
|
||||
z-index: 1060;
|
||||
/* Ensure it's above other content */
|
||||
background-color: #fff; /* Background color to cover the link for screen readers */
|
||||
z-index: 1060; /* Ensure it's above other content */
|
||||
}
|
||||
|
||||
.skip-link:focus {
|
||||
top: 0;
|
||||
/* Bring the link back into view when it receives focus */
|
||||
top: 0; /* Bring the link back into view when it receives focus */
|
||||
}
|
||||
|
||||
#outer_container a:not(.btn):hover, footer a:not(.btn):hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#outer_container a:not(.btn):has(span.fe):hover, footer a:not(.btn):has(span.fe):hover {
|
||||
/* do not have underlines on icons */
|
||||
#outer_container a:not(.btn):has(span.fe):hover, footer a:not(.btn):has(span.fe):hover { /* do not have underlines on icons */
|
||||
text-decoration: none;
|
||||
}
|
||||
#outer_container a:not(.btn):active, footer a:not(.btn):active {
|
||||
|
@ -660,8 +654,7 @@ div.navbar {
|
|||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
border-radius: 5px 5px 0 0;
|
||||
/* top-left | top-right | bottom-right | bottom-left */
|
||||
border-radius: 5px 5px 0 0; /* top-left | top-right | bottom-right | bottom-left */
|
||||
height: 176px;
|
||||
margin-left: -12px;
|
||||
margin-right: -12px;
|
||||
|
@ -878,8 +871,7 @@ div.navbar {
|
|||
margin: 0;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
/* Limits the text to a specific number of lines */
|
||||
-webkit-line-clamp: 2; /* Limits the text to a specific number of lines */
|
||||
line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -919,8 +911,7 @@ div.navbar {
|
|||
}
|
||||
.post_teaser_video_preview .video-wrapper {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* 16:9 aspect ratio */
|
||||
padding-bottom: 56.25%; /* 16:9 aspect ratio */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
@ -1022,8 +1013,7 @@ div.navbar {
|
|||
#masonry .item img {
|
||||
width: 100%;
|
||||
display: block;
|
||||
height: auto;
|
||||
/* Ensure aspect ratio is maintained */
|
||||
height: auto; /* Ensure aspect ratio is maintained */
|
||||
}
|
||||
#masonry .item .masonry_thumb a, #masonry .item .masonry_thumb a:active {
|
||||
border: none;
|
||||
|
@ -1195,8 +1185,7 @@ div.navbar {
|
|||
display: inline-block;
|
||||
}
|
||||
.voting_buttons_new .upvote_button, .voting_buttons_new .downvote_button {
|
||||
position: relative;
|
||||
/* so the htmx-indicators can be position: absolute */
|
||||
position: relative; /* so the htmx-indicators can be position: absolute */
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
@ -1735,6 +1724,12 @@ h1 .warning_badge {
|
|||
object-fit: cover;
|
||||
}
|
||||
|
||||
.community_icon_small {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.bump_up {
|
||||
position: absolute;
|
||||
top: 115px;
|
||||
|
@ -1956,7 +1951,6 @@ form h5 {
|
|||
--bs-link-color-rgb: black;
|
||||
--bs-link-hover-color-rgb: #333;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] {
|
||||
--bs-body-bg: black;
|
||||
--bs-link-color: white;
|
||||
|
@ -1966,84 +1960,65 @@ form h5 {
|
|||
--bs-body-color: white;
|
||||
--bs-body-color-rgb: white;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
--bs-btn-bg: black;
|
||||
--bs-btn-border-color: black;
|
||||
--bs-btn-hover-bg: #333;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .btn-primary {
|
||||
--bs-btn-bg: white;
|
||||
--bs-btn-border-color: white;
|
||||
--bs-btn-hover-bg: white;
|
||||
--bs-btn-color: black;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .btn-primary:hover {
|
||||
--bs-btn-hover-color: black;
|
||||
}
|
||||
|
||||
.btn-outline-secondary {
|
||||
--bs-btn-color: black;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .btn-outline-secondary {
|
||||
--bs-btn-color: white;
|
||||
}
|
||||
|
||||
.post_list .post_teaser {
|
||||
border-bottom: solid 1px black;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .post_list .post_teaser {
|
||||
border-bottom: solid 1px white;
|
||||
}
|
||||
|
||||
.domain_link, .domain_link a {
|
||||
color: black;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .domain_link, [data-bs-theme=dark] .domain_link a {
|
||||
color: ghostwhite;
|
||||
}
|
||||
|
||||
.main_pane, .voting_buttons div {
|
||||
border: solid 1px #333;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .main_pane, [data-bs-theme=dark] .voting_buttons div {
|
||||
border: solid 1px #eee;
|
||||
}
|
||||
|
||||
div.navbar {
|
||||
border-bottom: solid 1px #333;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] div.navbar {
|
||||
border-bottom: solid 1px #fff;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
color: black;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .nav-link {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card {
|
||||
--bs-card-border-color: #333;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .card {
|
||||
--bs-card-border-color: #fff;
|
||||
}
|
||||
|
||||
.coolfieldset.collapsed legend, .coolfieldset legend, .coolfieldset.expanded legend {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .coolfieldset.collapsed legend, [data-bs-theme=dark] .coolfieldset legend, [data-bs-theme=dark] .coolfieldset.expanded legend {
|
||||
background-color: black;
|
||||
}
|
||||
|
@ -2054,19 +2029,16 @@ form h5 {
|
|||
|
||||
@media print {
|
||||
#navbarSupportedContent, #side_pane, .voting_buttons, .comment_actions, footer, .post_reply_form, #post_replies .btn-group,
|
||||
.navbar .nav-link, .post_utilities_bar, .community_header, .community_icon_big, .mobile_create_post {
|
||||
.navbar .nav-link, .post_utilities_bar, .community_header, .community_icon_big, .mobile_create_post {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.comments > .comment, .post_teaser {
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
||||
.main_pane {
|
||||
border: none;
|
||||
padding: 0;
|
||||
|
@ -2074,16 +2046,13 @@ form h5 {
|
|||
.main_pane > .btn-group {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.div.navbar {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.limit_height {
|
||||
overflow: visible !important;
|
||||
max-height: initial;
|
||||
}
|
||||
|
||||
.comment .show-more {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -1412,6 +1412,12 @@ h1 .warning_badge {
|
|||
object-fit: cover;
|
||||
}
|
||||
|
||||
.community_icon_small {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.bump_up {
|
||||
position: absolute;
|
||||
top: 115px;
|
||||
|
|
|
@ -197,6 +197,7 @@
|
|||
<li><a class="dropdown-item{% if active_child == 'edit_profile' %} active{% endif %}" href="/user/settings">{{ _('Edit profile & settings') }}</a></li>
|
||||
<li><a class="dropdown-item{% if active_child == 'chats' %} active{% endif %}" href="/chat">{{ _('Chats') }}</a></li>
|
||||
<li><a class="dropdown-item{% if active_child == 'bookmarks' %} active{% endif %}" href="/bookmarks">{{ _('Bookmarks') }}</a></li>
|
||||
<li><a class="dropdown-item{% if active_child == 'alerts' %} active{% endif %}" href="/alerts">{{ _('Activity Alerts') }}</a></li>
|
||||
{% if current_user.is_authenticated and current_user.hide_read_posts -%}
|
||||
<li><a class="dropdown-item{% if active_child == 'read_posts' %} active{% endif %}" href="/read-posts">{{ _('Read Posts') }}</a></li>
|
||||
{% endif -%}
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
{% endif -%}
|
||||
{% if post.sticky -%}<span class="fe fe-sticky-right"></span>{% endif -%}
|
||||
</h3>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">
|
||||
{% if post.community.icon_image() %}<img class="community_icon_small rounded-circle" src="{{ post.community.icon_image() }}" alt="Community icon" />{% endif -%}
|
||||
c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
{% if post.body_html -%}
|
||||
<div class="post_teaser_article_preview small">
|
||||
{{ first_paragraph(post.body_html) | safe }}
|
||||
|
|
|
@ -10,8 +10,10 @@
|
|||
{% endif -%}
|
||||
{% if post.sticky -%}<span class="fe fe-sticky-right"></span>{% endif -%}
|
||||
</h3>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">
|
||||
{% if post.community.icon_image() %}<img class="community_icon_small rounded-circle" src="{{ post.community.icon_image() }}" alt="Community icon" />{% endif -%}
|
||||
c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
{% if post.image_id and not low_bandwidth -%}
|
||||
<div class="post_teaser_image_preview">
|
||||
<a href="{{ post.image.view_url() }}" rel="nofollow ugc" aria-label="{{ _('View image') }}" target="_blank"><img src="{{ post.image.medium_url() }}"
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
{% endif -%}
|
||||
{% if post.sticky -%}<span class="fe fe-sticky-right"></span>{% endif -%}
|
||||
</h3>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">
|
||||
{% if post.community.icon_image() %}<img class="community_icon_small rounded-circle" src="{{ post.community.icon_image() }}" alt="Community icon" />{% endif -%}
|
||||
c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
{% if post.body_html -%}
|
||||
<div class="post_teaser_link_preview small">
|
||||
{{ first_paragraph(post.body_html) | safe }}
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
{% endif -%}
|
||||
{% if post.sticky -%}<span class="fe fe-sticky-right"></span>{% endif -%}
|
||||
</h3>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">
|
||||
{% if post.community.icon_image() %}<img class="community_icon_small rounded-circle" src="{{ post.community.icon_image() }}" alt="Community icon" />{% endif -%}
|
||||
c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
{% include "post/post_teaser/_utilities_bar.html" %}
|
||||
</div>
|
||||
<div class="col col-2 col_thumbnail">
|
||||
|
|
|
@ -15,8 +15,10 @@
|
|||
{% endif -%}
|
||||
{% if post.sticky -%}<span class="fe fe-sticky-right"></span>{% endif -%}
|
||||
</h3>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
<span class="author small">{% if show_post_community -%}<a href="/c/{{ post.community.link() }}" aria-label="{{ _('Go to community %(name)s', name=post.community.name) }}">
|
||||
{% if post.community.icon_image() %}<img class="community_icon_small rounded-circle" src="{{ post.community.icon_image() }}" alt="Community icon" />{% endif -%}
|
||||
c/{{ post.community.name }}</a>{% endif -%}
|
||||
by {{ render_username(post.author) }} <time datetime="{{ post.last_active }}">{{ post.posted_at_localized(sort, locale) }}</time></span>
|
||||
{% if not low_bandwidth %}
|
||||
<div class="post_teaser_video_preview">
|
||||
<div class="max_width_512">
|
||||
|
|
35
app/templates/user/alerts.html
Normal file
35
app/templates/user/alerts.html
Normal file
|
@ -0,0 +1,35 @@
|
|||
{% if theme() and file_exists('app/templates/themes/' + theme() + '/base.html') %}
|
||||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
{% else %}
|
||||
{% extends "base.html" %}
|
||||
{% endif %}
|
||||
{% set active_child = 'alerts' %}
|
||||
|
||||
{% block app_content %}
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-8 position-relative main_pane">
|
||||
<nav class="mb-2" aria-label="breadcrumb" id="breadcrumb_nav" title="Navigation">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/">{{ _('Home') }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="/u/{{ user.link() }}">{{ user.display_name() }}</a></li>
|
||||
<li class="breadcrumb-item active">{{ _('Alerts') }}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
{% include 'user/alerts/_type.html' %}
|
||||
{% include 'user/alerts/_' + type + '.html' %}
|
||||
|
||||
<nav aria-label="Pagination" class="mt-4" role="navigation">
|
||||
{% if prev_url %}
|
||||
<a href="{{ prev_url }}" class="btn btn-primary" rel="nofollow">
|
||||
<span aria-hidden="true">←</span> {{ _('Previous page') }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if next_url %}
|
||||
<a href="{{ next_url }}" class="btn btn-primary" rel="nofollow">
|
||||
{{ _('Next page') }} <span aria-hidden="true">→</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
21
app/templates/user/alerts/_comments.html
Normal file
21
app/templates/user/alerts/_comments.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
{% include 'user/alerts/_filter.html' %}
|
||||
<div class="post_list">
|
||||
<h2>{{ _('You will be notified of replies to these comments') }}</h2>
|
||||
{% for reply in entities.items %}
|
||||
<div class="h-entry post_teaser tabindex="0">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a href="{{ url_for('activitypub.post_ap', post_id=reply.post_id, _anchor='comment_' + str(reply.id)) }}" aria-label="{{ _('Read replies') }}">{{ reply.body }}</a>
|
||||
</div>
|
||||
<div class="col col-1">
|
||||
{% with comment=dict(comment=reply) %}
|
||||
{% include 'post/_reply_notification_toggle.html' %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>{{ _('You have not subscribed to any comments. Use the bell icon on each comment to do so.') }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
19
app/templates/user/alerts/_communities.html
Normal file
19
app/templates/user/alerts/_communities.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% include 'user/alerts/_filter.html' %}
|
||||
<div class="post_list">
|
||||
<h2>{{ _('You will be notified of new posts in these communities') }}</h2>
|
||||
{% for community in entities.items %}
|
||||
<div class="h-entry post_teaser tabindex="0">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a href="{{ url_for('activitypub.community_profile', actor=community.ap_id if community.ap_id is not none else community.name) }}" aria-label="{{ _('Visit Community') }}">{{ community.title }}</a>
|
||||
</div>
|
||||
<div class="col col-1">
|
||||
{% include 'community/_notification_toggle.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>{{ _('You have not subscribed to an alert for new content in any communities. Use the bell icon in each community to do so.') }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
11
app/templates/user/alerts/_filter.html
Normal file
11
app/templates/user/alerts/_filter.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<div class="view_filter btn-group mt-1 mb-2" aria-label="{{ _('Alert filters: ') }}">
|
||||
<a href="/alerts/{{ type }}/all" class="btn {{ 'btn-primary' if filter == 'all' else 'btn-outline-secondary' }}" rel="nofollow noindex" title="{{ _('All authors') }}">
|
||||
{{ _('All') }}
|
||||
</a>
|
||||
<a href="/alerts/{{ type }}/mine" class="btn {{ 'btn-primary' if filter == 'mine' else 'btn-outline-secondary' }}" rel="nofollow noindex" title="{{ _('Only Mine') }}">
|
||||
{{ _('Mine') }}
|
||||
</a>
|
||||
<a href="/alerts/{{ type }}/others" class="btn {{ 'btn-primary' if filter == 'others' else 'btn-outline-secondary' }}" rel="nofollow noindex" title="{{ _('Only Others') }}">
|
||||
{{ _('Others') }}
|
||||
</a>
|
||||
</div>
|
19
app/templates/user/alerts/_posts.html
Normal file
19
app/templates/user/alerts/_posts.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% include 'user/alerts/_filter.html' %}
|
||||
<div class="post_list">
|
||||
<h2>{{ _('You will be notified of top-level replies to these posts') }}</h2>
|
||||
{% for post in entities.items %}
|
||||
<div class="h-entry post_teaser tabindex="0">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a href="{{ url_for('activitypub.post_ap', post_id=post.id) }}" aria-label="{{ _('Read post') }}">{{ post.title }}</a>
|
||||
</div>
|
||||
<div class="col col-1">
|
||||
{% include 'post/_post_notification_toggle.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>{{ _('You have not subscribed to any posts. Use the bell icon on each post to do so.') }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
18
app/templates/user/alerts/_topics.html
Normal file
18
app/templates/user/alerts/_topics.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
<div class="post_list">
|
||||
<h2>{{ _('You will be notified of new posts in communities covered by these topics') }}</h2>
|
||||
{% for topic in entities.items -%}
|
||||
<div class="h-entry post_teaser tabindex="0">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a href="{{ url_for('topic.show_topic', topic_path=topic.machine_name) }}" aria-label="{{ _('Visit Topic') }}">{{ topic.name }}</a>
|
||||
</div>
|
||||
<div class="col col-1">
|
||||
{% include 'topic/_notification_toggle.html' -%}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else -%}
|
||||
<p>{{ _('You have not subscribed to any topics. Use the bell icon on each topic to do so.') }}</p>
|
||||
{% endfor -%}
|
||||
</div>
|
||||
|
17
app/templates/user/alerts/_type.html
Normal file
17
app/templates/user/alerts/_type.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<div class="btn-group mt-1 mb-2" aria-label="{{ _('Alert type: ') }}">
|
||||
<a href="/alerts/posts/{{ filter }}" class="btn {{ 'btn-primary' if type == 'posts' else 'btn-outline-secondary' }}">
|
||||
{{ _('Posts') }}
|
||||
</a>
|
||||
<a href="/alerts/comments/{{ filter }}" class="btn {{ 'btn-primary' if type == 'comments' else 'btn-outline-secondary' }}">
|
||||
{{ _('Comments') }}
|
||||
</a>
|
||||
<a href="/alerts/communities/{{ filter }}" class="btn {{ 'btn-primary' if type == 'communities' else 'btn-outline-secondary' }}">
|
||||
{{ _('Communities') }}
|
||||
</a>
|
||||
<a href="/alerts/topics/{{ filter }}" class="btn {{ 'btn-primary' if type == 'topics' else 'btn-outline-secondary' }}">
|
||||
{{ _('Topics') }}
|
||||
</a>
|
||||
<a href="/alerts/users/{{ filter }}" class="btn {{ 'btn-primary' if type == 'users' else 'btn-outline-secondary' }}">
|
||||
{{ _('Users') }}
|
||||
</a>
|
||||
</div>
|
18
app/templates/user/alerts/_users.html
Normal file
18
app/templates/user/alerts/_users.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
<div class="post_list">
|
||||
<h2>{{ _('You will be notified of new posts by these users') }}</h2>
|
||||
{% for user in entities.items %}
|
||||
<div class="h-entry post_teaser tabindex="0">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a href="{{ url_for('user.show_profile_by_id', user_id=user.id) }}" aria-label="{{ _('Visit User') }}">{{ user.title if user.title else user.user_name }}</a>
|
||||
</div>
|
||||
<div class="col col-1">
|
||||
{% include 'user/_notification_toggle.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>{{ _('You have not subscribed to an alert for new content from any users. Use the bell icon on each person to do so.') }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
@ -12,12 +12,11 @@ from app.activitypub.signature import post_request, default_context
|
|||
from app.activitypub.util import find_actor_or_create
|
||||
from app.auth.util import random_token
|
||||
from app.community.util import save_icon_file, save_banner_file, retrieve_mods_and_backfill
|
||||
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_PENDING, NOTIF_USER, POST_TYPE_VIDEO, POST_TYPE_LINK, \
|
||||
POST_TYPE_IMAGE, POST_TYPE_POLL
|
||||
from app.constants import *
|
||||
from app.email import send_verification_email
|
||||
from app.models import Post, Community, CommunityMember, User, PostReply, PostVote, Notification, utcnow, File, Site, \
|
||||
Instance, Report, UserBlock, CommunityBan, CommunityJoinRequest, CommunityBlock, Filter, Domain, DomainBlock, \
|
||||
InstanceBlock, NotificationSubscription, PostBookmark, PostReplyBookmark, read_posts
|
||||
InstanceBlock, NotificationSubscription, PostBookmark, PostReplyBookmark, read_posts, Topic
|
||||
from app.user import bp
|
||||
from app.user.forms import ProfileForm, SettingsForm, DeleteAccountForm, ReportUserForm, \
|
||||
FilterForm, KeywordFilterEditForm, RemoteFollowForm, ImportExportForm
|
||||
|
@ -1143,6 +1142,86 @@ def user_bookmarks_comments():
|
|||
next_url=next_url, prev_url=prev_url)
|
||||
|
||||
|
||||
@bp.route('/alerts')
|
||||
@bp.route('/alerts/<type>/<filter>')
|
||||
@login_required
|
||||
def user_alerts(type='posts', filter='all'):
|
||||
page = request.args.get('page', 1, type=int)
|
||||
low_bandwidth = request.cookies.get('low_bandwidth', '0') == '1'
|
||||
|
||||
if type == 'comments':
|
||||
if filter == 'mine':
|
||||
entities = PostReply.query.filter_by(deleted=False, user_id=current_user.id).\
|
||||
join(NotificationSubscription, NotificationSubscription.entity_id == PostReply.id).\
|
||||
filter_by(type=NOTIF_REPLY, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
elif filter == 'others':
|
||||
entities = PostReply.query.filter(PostReply.deleted == False, PostReply.user_id != current_user.id).\
|
||||
join(NotificationSubscription, NotificationSubscription.entity_id == PostReply.id).\
|
||||
filter_by(type=NOTIF_REPLY, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
else: # default to 'all' filter
|
||||
entities = PostReply.query.filter_by(deleted=False).\
|
||||
join(NotificationSubscription, NotificationSubscription.entity_id == PostReply.id).\
|
||||
filter_by(type=NOTIF_REPLY, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
title = _('Reply Alerts')
|
||||
|
||||
elif type == 'communities':
|
||||
if filter == 'mine':
|
||||
entities = Community.query.\
|
||||
join(CommunityMember, CommunityMember.community_id == Community.id).\
|
||||
filter_by(user_id=current_user.id, is_moderator=True).\
|
||||
join(NotificationSubscription, NotificationSubscription.entity_id == CommunityMember.community_id).\
|
||||
filter_by(type=NOTIF_COMMUNITY, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
elif filter == 'others':
|
||||
entities = Community.query.\
|
||||
join(CommunityMember, CommunityMember.community_id == Community.id).\
|
||||
filter_by(user_id=current_user.id, is_moderator=False).\
|
||||
join(NotificationSubscription, NotificationSubscription.entity_id == CommunityMember.community_id).\
|
||||
filter_by(type=NOTIF_COMMUNITY, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
else: # default to 'all' filter
|
||||
entities = Community.query.\
|
||||
join(NotificationSubscription, NotificationSubscription.entity_id == Community.id).\
|
||||
filter_by(type=NOTIF_COMMUNITY, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
title = _('Community Alerts')
|
||||
|
||||
elif type == 'topics':
|
||||
# ignore filter
|
||||
entities = Topic.query.join(NotificationSubscription, NotificationSubscription.entity_id == Topic.id).\
|
||||
filter_by(type=NOTIF_TOPIC, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
title = _('Topic Alerts')
|
||||
|
||||
elif type == 'users':
|
||||
# ignore filter
|
||||
entities = User.query.join(NotificationSubscription, NotificationSubscription.entity_id == User.id).\
|
||||
filter_by(type=NOTIF_USER, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
title = _('User Alerts')
|
||||
|
||||
else: # default to 'posts' type
|
||||
if filter == 'mine':
|
||||
entities = Post.query.filter_by(deleted=False, user_id=current_user.id).\
|
||||
join(NotificationSubscription, NotificationSubscription.entity_id == Post.id).\
|
||||
filter_by(type=NOTIF_POST, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
elif filter == 'others':
|
||||
entities = Post.query.filter(Post.deleted == False, Post.user_id != current_user.id).\
|
||||
join(NotificationSubscription, NotificationSubscription.entity_id == Post.id).\
|
||||
filter_by(type=NOTIF_POST, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
else: # default to 'all' filter
|
||||
entities = Post.query.filter_by(deleted=False).\
|
||||
join(NotificationSubscription, NotificationSubscription.entity_id == Post.id).\
|
||||
filter_by(type=NOTIF_POST, user_id=current_user.id).order_by(desc(NotificationSubscription.created_at))
|
||||
title = _('Post Alerts')
|
||||
|
||||
entities = entities.paginate(page=page, per_page=100 if not low_bandwidth else 50, error_out=False)
|
||||
next_url = url_for('user.user_alerts', page=entities.next_num, type=type, filter=filter) if entities.has_next else None
|
||||
prev_url = url_for('user.user_alerts', page=entities.prev_num, type=type, filter=filter) if entities.has_prev and page != 1 else None
|
||||
|
||||
return render_template('user/alerts.html', title=title, entities=entities,
|
||||
low_bandwidth=low_bandwidth, user=current_user, type=type, filter=filter,
|
||||
moderating_communities=moderating_communities(current_user.get_id()),
|
||||
joined_communities=joined_communities(current_user.get_id()),
|
||||
menu_topics=menu_topics(), site=g.site,
|
||||
next_url=next_url, prev_url=prev_url)
|
||||
|
||||
|
||||
@bp.route('/u/<actor>/fediverse_redirect', methods=['GET', 'POST'])
|
||||
def fediverse_redirect(actor):
|
||||
actor = actor.strip()
|
||||
|
|
Loading…
Add table
Reference in a new issue