updated chat andlayout
This commit is contained in:
@@ -120,9 +120,11 @@ class ChatConsumer(AsyncWebsocketConsumer):
|
||||
"type": "new_chat_message",
|
||||
"message_id": event["message_id"],
|
||||
"message": event["message"],
|
||||
"sender_id": event["sender_id"],
|
||||
"sender_id": event.get("sender_id"),
|
||||
"sender": event["sender"],
|
||||
"sender_avatar": event["sender_avatar"],
|
||||
"sender_avatar": event.get("sender_avatar"),
|
||||
"reply_to_id": event.get("reply_to_id"),
|
||||
"media_files": event.get("media_files", []),
|
||||
}))
|
||||
|
||||
async def reply_chat_message(self, event):
|
||||
|
||||
@@ -4,6 +4,7 @@ from drf_spectacular.utils import extend_schema_field
|
||||
from .models import Chat, ChatReadStatus, Message, MessageFile, MessageHistory, MessageReaction
|
||||
|
||||
|
||||
|
||||
class MessageSenderSerializer(serializers.ModelSerializer):
|
||||
avatar = serializers.SerializerMethodField()
|
||||
|
||||
@@ -51,10 +52,42 @@ class ReplyToSerializer(serializers.ModelSerializer):
|
||||
|
||||
class MessageSerializer(serializers.ModelSerializer):
|
||||
sender = MessageSenderSerializer(read_only=True)
|
||||
reply_to = ReplyToSerializer(read_only=True)
|
||||
# reply_to is a SerializerMethodField so we can bypass ActiveManager and
|
||||
# still surface a tombstone when the original message is soft-deleted.
|
||||
reply_to = serializers.SerializerMethodField()
|
||||
media_files = MessageFileSerializer(many=True, read_only=True)
|
||||
reactions = MessageReactionSerializer(many=True, read_only=True)
|
||||
|
||||
@extend_schema_field(ReplyToSerializer)
|
||||
def get_reply_to(self, obj):
|
||||
"""
|
||||
Fetch the reply-to message via all_objects so soft-deleted originals
|
||||
are still accessible. Returns content=None when the message is deleted,
|
||||
which the frontend renders as a '(zpráva smazána)' tombstone.
|
||||
"""
|
||||
reply_to_id = obj.reply_to_id
|
||||
if not reply_to_id:
|
||||
return None
|
||||
try:
|
||||
msg = Message.all_objects.select_related('sender').get(pk=reply_to_id)
|
||||
except Message.DoesNotExist:
|
||||
return None
|
||||
|
||||
sender_data = None
|
||||
if msg.sender:
|
||||
from django.conf import settings
|
||||
avatar = (settings.MEDIA_URL + msg.sender.avatar.name) if msg.sender.avatar else None
|
||||
sender_data = {'id': msg.sender.id, 'username': msg.sender.username, 'avatar': avatar}
|
||||
else:
|
||||
sender_data = {'id': 0, 'username': '…', 'avatar': None}
|
||||
|
||||
return {
|
||||
'id': msg.id,
|
||||
# content=None signals the frontend to show the deleted tombstone
|
||||
'content': None if msg.is_deleted else msg.content,
|
||||
'sender': sender_data,
|
||||
}
|
||||
|
||||
class Meta:
|
||||
model = Message
|
||||
fields = [
|
||||
|
||||
@@ -241,12 +241,26 @@ class MessageViewSet(viewsets.ModelViewSet):
|
||||
mt = 'FILE'
|
||||
MessageFile.objects.create(message=message, file=f, media_type=mt)
|
||||
|
||||
from django.conf import settings
|
||||
avatar_url = (settings.MEDIA_URL + request.user.avatar.name) if request.user.avatar else None
|
||||
media_files_data = [
|
||||
{
|
||||
'id': f.id,
|
||||
'file': settings.MEDIA_URL + f.file.name if f.file else '',
|
||||
'media_type': f.media_type,
|
||||
'uploaded_at': f.uploaded_at.isoformat(),
|
||||
}
|
||||
for f in message.media_files.all()
|
||||
]
|
||||
_broadcast(chat.id, {
|
||||
'type': 'chat.message',
|
||||
'message_id': message.id,
|
||||
'message': message.content,
|
||||
'sender_id': request.user.id,
|
||||
'sender': request.user.username,
|
||||
'has_files': message.media_files.exists(),
|
||||
'sender_avatar': avatar_url,
|
||||
'reply_to_id': message.reply_to_id,
|
||||
'media_files': media_files_data,
|
||||
})
|
||||
|
||||
return Response(
|
||||
|
||||
Reference in New Issue
Block a user