chat - tidy up and nav improvements

This commit is contained in:
rimu 2024-02-19 15:56:56 +13:00
parent e840db1991
commit a566c40913
18 changed files with 65 additions and 36 deletions

View file

@ -12,7 +12,7 @@ from app.user.routes import show_profile
from app.constants import POST_TYPE_LINK, POST_TYPE_IMAGE, SUBSCRIPTION_MEMBER
from app.models import User, Community, CommunityJoinRequest, CommunityMember, CommunityBan, ActivityPubLog, Post, \
PostReply, Instance, PostVote, PostReplyVote, File, AllowedInstances, BannedInstances, utcnow, Site, Notification, \
ChatMessage
ChatMessage, Conversation
from app.activitypub.util import public_key, users_total, active_half_year, active_month, local_posts, local_comments, \
post_to_activity, find_actor_or_create, default_context, instance_blocked, find_reply_parent, find_liked_object, \
lemmy_site_data, instance_weight, is_activitypub_request, downvote_post_reply, downvote_post, upvote_post_reply, \
@ -380,14 +380,22 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
recipient_ap_id = request_json['object']['to'][0]
recipient = find_actor_or_create(recipient_ap_id)
if sender and recipient and recipient.is_local():
if sender.created_recently() or sender.reputation < 10:
if sender.created_recently() or sender.reputation <= -10:
activity_log.exception_message = "Sender not eligible to send"
elif recipient.has_blocked_user(sender.id) or recipient.has_blocked_instance(sender.instance_id):
activity_log.exception_message = "Sender blocked by recipient"
else:
# Find existing conversation to add to
existing_conversation = Conversation.find_existing_conversation(recipient=recipient, sender=sender)
if not existing_conversation:
existing_conversation = Conversation(user_id=sender.id)
existing_conversation.members.append(recipient)
existing_conversation.members.append(sender)
db.session.add(existing_conversation)
db.session.commit()
# Save ChatMessage to DB
encrypted = request_json['object']['encrypted'] if 'encrypted' in request_json['object'] else None
new_message = ChatMessage(sender_id=sender.id, recipient_id=recipient.id,
new_message = ChatMessage(sender_id=sender.id, recipient_id=recipient.id, conversation_id=existing_conversation.id,
body=request_json['object']['source']['content'],
body_html=allowlist_html(markdown_to_html(request_json['object']['source']['content'])),
encrypted=encrypted)
@ -396,10 +404,11 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
# Notify recipient
notify = Notification(title=shorten_string('New message from ' + sender.display_name()),
url=f'/chat/{new_message.id}', user_id=recipient.id,
url=f'/chat/{existing_conversation.id}', user_id=recipient.id,
author_id=sender.id)
db.session.add(notify)
recipient.unread_notifications += 1
existing_conversation.read = False
db.session.commit()
activity_log.result = 'success'
else:

View file

@ -5,7 +5,7 @@ from sqlalchemy import desc, or_, and_, text
from app import db, celery
from app.chat.forms import AddReply, ReportConversationForm
from app.chat.util import send_message, find_existing_conversation
from app.chat.util import send_message
from app.models import Site, User, Report, ChatMessage, Notification, InstanceBlock, Conversation, conversation_member
from app.user.forms import ReportUserForm
from app.utils import render_template, moderating_communities, joined_communities
@ -28,6 +28,7 @@ def chat_home(conversation_id=None):
return redirect(url_for('chat.chat_home', conversation_id=conversations[0].id))
else:
conversation = Conversation.query.get_or_404(conversation_id)
conversation.read = True
if not current_user.is_admin() and not conversation.is_member(current_user):
abort(400)
if conversations:
@ -65,7 +66,7 @@ def new_message(to):
return redirect(url_for('chat.denied'))
if recipient.has_blocked_user(current_user.id) or current_user.has_blocked_user(recipient.id):
return redirect(url_for('chat.blocked'))
existing_conversation = find_existing_conversation(recipient=recipient, sender=current_user)
existing_conversation = Conversation.find_existing_conversation(recipient=recipient, sender=current_user)
if existing_conversation:
return redirect(url_for('chat.chat_home', conversation_id=existing_conversation.id, _anchor='message'))
form = AddReply()

View file

@ -60,23 +60,3 @@ def send_message(form, conversation_id: int) -> ChatMessage:
flash(_('Message sent.'))
return reply
def find_existing_conversation(recipient, sender):
sql = """SELECT
c.id AS conversation_id,
c.created_at AS conversation_created_at,
c.updated_at AS conversation_updated_at,
cm1.user_id AS user1_id,
cm2.user_id AS user2_id
FROM
public.conversation AS c
JOIN
public.conversation_member AS cm1 ON c.id = cm1.conversation_id
JOIN
public.conversation_member AS cm2 ON c.id = cm2.conversation_id
WHERE
cm1.user_id = :user_id_1 AND
cm2.user_id = :user_id_2 AND
cm1.user_id <> cm2.user_id;"""
ec = db.session.execute(text(sql), {'user_id_1': recipient.id, 'user_id_2': sender.id}).fetchone()
return Conversation.query.get(ec[0]) if ec else None

View file

@ -121,6 +121,27 @@ class Conversation(db.Model):
retval.append(member.instance)
return retval
@staticmethod
def find_existing_conversation(recipient, sender):
sql = """SELECT
c.id AS conversation_id,
c.created_at AS conversation_created_at,
c.updated_at AS conversation_updated_at,
cm1.user_id AS user1_id,
cm2.user_id AS user2_id
FROM
public.conversation AS c
JOIN
public.conversation_member AS cm1 ON c.id = cm1.conversation_id
JOIN
public.conversation_member AS cm2 ON c.id = cm2.conversation_id
WHERE
cm1.user_id = :user_id_1 AND
cm2.user_id = :user_id_2 AND
cm1.user_id <> cm2.user_id;"""
ec = db.session.execute(text(sql), {'user_id_1': recipient.id, 'user_id_2': sender.id}).fetchone()
return Conversation.query.get(ec[0]) if ec else None
conversation_member = db.Table('conversation_member',
db.Column('user_id', db.Integer, db.ForeignKey('user.id')),

View file

@ -140,9 +140,9 @@
<li class="nav-item dropdown{% if active_parent == 'home' %} active{% endif %}">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="/home" aria-haspopup="true" aria-expanded="false">{{ _('Home') }}</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item{% if active_child == 'popular' %} active{% endif %}" href="/home"><span class="fe fe-home"></span>{{ _('Home') }}</a></li>
<li><a class="dropdown-item{% if active_child == 'home' %} active{% endif %}" href="/home"><span class="fe fe-home"></span>{{ _('Home') }}</a></li>
<li><a class="dropdown-item{% if active_child == 'popular' %} active{% endif %}" href="/popular"><span class="fe fe-popular"></span>{{ _('Popular') }}</a></li>
<li><a class="dropdown-item{% if active_child == 'all_posts' %} active{% endif %}" href="/all"><span class="fe fe-all"></span>{{ _('All posts') }}</a></li>
<li><a class="dropdown-item{% if active_child == 'all' %} active{% endif %}" href="/all"><span class="fe fe-all"></span>{{ _('All posts') }}</a></li>
</ul>
<li class="nav-item dropdown{% if active_parent == 'communities' %} active{% endif %}">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="/topics" aria-haspopup="true" aria-expanded="false">{{ _('Topics') }}</a>
@ -151,14 +151,14 @@
<li><a class="dropdown-item{% if active_child == 'list_topics' %} active{% endif %}" href="/communities">{{ _('All communities') }}</a></li>
{% if moderating_communities %}
<li><h6 class="dropdown-header">{{ _('Moderating') }}</h6></li>
{% for community in moderating_communities %}
<li class="pl-2"><a class="dropdown-item" href="/c/{{ community.link() }}">{{ community.title }}</a></li>
{% for community_menu_item in moderating_communities %}
<li class="pl-2"><a class="dropdown-item{% if community and community.id == community_menu_item.id%} active{% endif %}" href="/c/{{ community_menu_item.link() }}">{{ community_menu_item.title }}</a></li>
{% endfor %}
{% endif %}
{% if joined_communities %}
<li><h6 class="dropdown-header">{{ _('Joined communities') }}</h6></li>
{% for community in joined_communities %}
<li class="pl-2"><a class="dropdown-item" href="/c/{{ community.link() }}">{{ community.title }}</a></li>
{% for community_menu_item in joined_communities %}
<li class="pl-2"><a class="dropdown-item{% if community and community.id == community_menu_item.id%} active{% endif %}" href="/c/{{ community_menu_item.link() }}">{{ community_menu_item.title }}</a></li>
{% endfor %}
{% endif %}
</ul>
@ -168,6 +168,7 @@
<ul class="dropdown-menu">
<li><a class="dropdown-item{% if active_child == 'view_profile' %} active{% endif %}" href="/u/{{ current_user.user_name }}">{{ _('View profile') }}</a></li>
<li><a class="dropdown-item{% if active_child == 'edit_profile' %} active{% endif %}" href="/u/{{ current_user.user_name }}/profile">{{ _('Edit profile') }}</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 == 'settings' %} active{% endif %}" href="/user/settings">{{ _('Settings') }}</a></li>
<li><a class="dropdown-item{% if active_child == 'filters' %} active{% endif %}" href="/user/settings/filters">{{ _('Filters') }}</a></li>
</ul>

View file

@ -3,6 +3,7 @@
{% else %}
{% extends "base.html" %}
{% endif %} %}
{% set active_child = 'chats' %}
{% from 'bootstrap/form.html' import render_form %}
{% block app_content %}

View file

@ -3,19 +3,25 @@
{% else %}
{% extends "base.html" %}
{% endif %} %}
{% set active_child = 'chats' %}
{% from 'bootstrap/form.html' import render_form %}
{% macro conversation_members(conversation) %}
{% if len(conversation.members) == 2 %}
{% for member in conversation.members %}
{% if member.id != current_user.id %}
<img src="{{ member.avatar_thumbnail() }}" loading="lazy" /> {{ member.display_name() }}
<img src="{{ member.avatar_thumbnail() }}" loading="lazy" />
{% if not conversation.read %}<strong>{% endif %}
{{ member.display_name() }}
{% if not conversation.read %}</strong>{% endif %}
{% endif %}
{% endfor %}
{% else %}
{% for member in conversation.members %}
{% if member.id != current_user.id %}
{{ member.display_name() }}
{% if not conversation.read %}<strong>{% endif %}
{{ member.display_name() }}
{% if not conversation.read %}</strong>{% endif %}
{% endif %}
{% endfor %}
{% endif %}

View file

@ -3,6 +3,7 @@
{% else %}
{% extends "base.html" %}
{% endif %} %}
{% set active_child = 'chats' %}
{% from 'bootstrap/form.html' import render_form %}
{% block app_content %}

View file

@ -3,6 +3,7 @@
{% else %}
{% extends "base.html" %}
{% endif %} %}
{% set active_child = 'chats' %}
{% from 'bootstrap/form.html' import render_form %}
{% block app_content %}

View file

@ -4,6 +4,7 @@
{% extends "base.html" %}
{% endif %}
{% from 'bootstrap5/form.html' import render_form %}
{% set active_child = type %}
{% block app_content %}
<div class="row">

View file

@ -4,6 +4,7 @@
{% extends "base.html" %}
{% endif %} %}
{% from 'bootstrap5/form.html' import render_form %}
{% set active_child = 'list_communities' %}
{% block app_content %}
<div class="row g-2 justify-content-between mt-2">

View file

@ -4,6 +4,7 @@
{% extends "base.html" %}
{% endif %} %}
{% from 'bootstrap5/form.html' import render_form %}
{% set active_child = 'list_topics' %}
{% block app_content %}
{% if len(topics) > 0 %}

View file

@ -4,6 +4,7 @@
{% extends "base.html" %}
{% endif %} %}
{% from 'bootstrap/form.html' import render_field %}
{% set active_child = 'filters' %}
{% block app_content %}
<div class="row">

View file

@ -3,6 +3,7 @@
{% else %}
{% extends "base.html" %}
{% endif %} %}
{% set active_child = 'edit_profile' %}
{% from 'bootstrap/form.html' import render_field %}
{% block app_content %}

View file

@ -4,6 +4,7 @@
{% extends "base.html" %}
{% endif %} %}
{% from 'bootstrap/form.html' import render_field %}
{% set active_child = 'settings' %}
{% block app_content %}
<div class="row">

View file

@ -4,6 +4,7 @@
{% extends "base.html" %}
{% endif %} %}
{% from 'bootstrap/form.html' import render_field %}
{% set active_child = 'filters' %}
{% block app_content %}
<div class="row">

View file

@ -4,7 +4,9 @@
{% extends "base.html" %}
{% endif %} %}
{% from 'bootstrap/form.html' import render_form %}
{% if current_user.is_authenticated() and user.id == current_user.id %}
{% set active_child = 'view_profile' %}
{% endif %}
{% block app_content %}
<div class="row">
<div class="col-12 col-md-8 position-relative main_pane">

View file

@ -13,7 +13,6 @@ import flask
from bs4 import BeautifulSoup, NavigableString
import requests
import os
import imghdr
from flask import current_app, json, redirect, url_for, request, make_response, Response, g
from flask_login import current_user
from sqlalchemy import text, or_