notification subscription - user toggle

This commit is contained in:
rimu 2024-04-19 20:06:08 +12:00
parent d9422411ea
commit fb34de8da3
4 changed files with 57 additions and 6 deletions

View file

@ -19,7 +19,7 @@ import jwt
import os
from app.constants import SUBSCRIPTION_NONMEMBER, SUBSCRIPTION_MEMBER, SUBSCRIPTION_MODERATOR, SUBSCRIPTION_OWNER, \
SUBSCRIPTION_BANNED, SUBSCRIPTION_PENDING
SUBSCRIPTION_BANNED, SUBSCRIPTION_PENDING, NOTIF_USER
# datetime.utcnow() is depreciated in Python 3.12 so it will need to be swapped out eventually
@ -880,6 +880,18 @@ class User(UserMixin, db.Model):
else:
return '@' + self.user_name + '@' + self.ap_domain
# True if user_id wants to be notified about posts by self
def notify_new_posts(self, user_id):
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == self.id,
NotificationSubscription.user_id == user_id,
NotificationSubscription.type == NOTIF_USER).first()
return existing_notification is not None
# ids of all the users who want to be notified when self makes a post
def notification_subscribers(self):
return db.session.execute(text('SELECT user_id FROM "notification_subscription" WHERE entity_id = :user_id AND type = :type '),
{'user_id': self.id, 'type': NOTIF_USER}).scalars()
class ActivityLog(db.Model):
id = db.Column(db.Integer, primary_key=True)

View file

@ -0,0 +1,5 @@
<a href="/user/{{ user.id }}/notification" rel="nofollow" aria-live="assertive"
aria-label="{{ 'Notify about new posts by this person' if user.notify_new_posts(current_user.id) else 'Do not notify about new posts' }}"
class="fe {{ 'fe-bell' if user.notify_new_posts(current_user.id) else 'fe-no-bell' }} no-underline"
hx-post="/user/{{ user.id }}/notification" hx-trigger="click throttle:1s" hx-swap="outerHTML"
title="{{ _('Notify about every new post by this person.') }}"></a>

View file

@ -22,7 +22,11 @@
</nav>
</div>
<img class="community_icon_big bump_up rounded-circle" src="{{ user.avatar_image() }}" alt="{{ _('Profile pic') }}" />
<h1 class="mt-2">{{ user.display_name() if user.is_local() else user.display_name() + ', ' + user.ap_id }}</h1>
<h1 class="mt-2">{{ user.display_name() if user.is_local() else user.display_name() + ', ' + user.ap_id }}
{% if current_user.is_authenticated %}
{% include 'user/_notification_toggle.html' %}
{% endif %}
</h1>
{% elif user.avatar_image() != '' %}
<div class="row">
<div class="col-2">
@ -39,7 +43,11 @@
{% endif %}
</div>
<div class="col-10">
<h1 class="mt-3">{{ user.display_name() if user.is_local() else user.display_name() + ', ' + user.ap_id }}</h1>
<h1 class="mt-3">{{ user.display_name() if user.is_local() else user.display_name() + ', ' + user.ap_id }}
{% if current_user.is_authenticated %}
{% include 'user/_notification_toggle.html' %}
{% endif %}
</h1>
</div>
</div>
{% else %}
@ -50,7 +58,11 @@
<li class="breadcrumb-item active">{{ user.link()|shorten }}</li>
</ol>
</nav>
<h1 class="mt-2">{{ user.display_name() if user.is_local() else user.display_name() + ', ' + user.ap_id }}</h1>
<h1 class="mt-2">{{ user.display_name() if user.is_local() else user.display_name() + ', ' + user.ap_id }}
{% if current_user.is_authenticated %}
{% include 'user/_notification_toggle.html' %}
{% endif %}
</h1>
{% endif %}
{% if current_user.is_authenticated and current_user != user %}
<div class="profile_action_buttons">

View file

@ -9,10 +9,10 @@ from app import db, cache, celery
from app.activitypub.signature import post_request
from app.activitypub.util import default_context, find_actor_or_create
from app.community.util import save_icon_file, save_banner_file, retrieve_mods_and_backfill
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_PENDING
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_PENDING, NOTIF_USER
from app.models import Post, Community, CommunityMember, User, PostReply, PostVote, Notification, utcnow, File, Site, \
Instance, Report, UserBlock, CommunityBan, CommunityJoinRequest, CommunityBlock, Filter, Domain, DomainBlock, \
InstanceBlock
InstanceBlock, NotificationSubscription
from app.user import bp
from app.user.forms import ProfileForm, SettingsForm, DeleteAccountForm, ReportUserForm, FilterEditForm
from app.user.utils import purge_user_then_delete
@ -220,6 +220,26 @@ def change_settings():
joined_communities=joined_communities(current_user.get_id())
)
@bp.route('/user/<int:user_id>/notification', methods=['GET', 'POST'])
@login_required
def user_notification(user_id: int):
user = User.query.get_or_404(user_id)
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == user.id,
NotificationSubscription.user_id == current_user.id,
NotificationSubscription.type == NOTIF_USER).first()
if existing_notification:
db.session.delete(existing_notification)
db.session.commit()
else: # no subscription yet, so make one
if user.id != current_user.id and not user.has_blocked_user(current_user.id):
new_notification = NotificationSubscription(user_id=current_user.id, entity_id=user.id, type=NOTIF_USER)
db.session.add(new_notification)
db.session.commit()
return render_template('user/_notification_toggle.html', user=user)
@bp.route('/u/<actor>/ban', methods=['GET'])
@login_required
def ban_profile(actor):
@ -287,6 +307,8 @@ def block_profile(actor):
if not existing_block:
block = UserBlock(blocker_id=current_user.id, blocked_id=user.id)
db.session.add(block)
db.session.execute(text('DELETE FROM "notification_subscription" WHERE entity_id = :current_user AND user_id = :user_id'),
{'current_user': current_user.id, 'user_id': user.id})
db.session.commit()
if not user.is_local():