desktop_app/app/ui/views/chat_view.py
2025-09-29 03:12:01 +03:00

145 lines
5.3 KiB
Python

from PySide6.QtWidgets import QWidget, QVBoxLayout, QListWidget, QLineEdit, QPushButton, QHBoxLayout, QListWidgetItem
from PySide6.QtCore import Qt, Signal
from app.core.models.chat_models import MessageItem
from app.ui.widgets.message_bubble_widget import MessageBubbleWidget
from app.core.theme import theme_manager
from uuid import UUID
class ChatView(QWidget):
# Сигнал, который отдаём контроллеру при отправке
send_message_requested = Signal(str)
def __init__(self, chat_id: UUID, current_user_id: UUID):
super().__init__()
self.chat_id = chat_id
self.current_user_id = current_user_id
self.init_ui()
self.update_theme()
theme_manager.theme_changed.connect(self.update_theme)
def init_ui(self):
"""Базовая раскладка: список сообщений + поле ввода."""
main_layout = QVBoxLayout(self)
main_layout.setSpacing(0)
main_layout.setContentsMargins(0, 0, 0, 0)
self.message_list = QListWidget()
self.message_list.setSpacing(10)
self.message_list.setWordWrap(True)
input_layout = QHBoxLayout()
input_layout.setSpacing(10)
input_layout.setContentsMargins(10, 10, 10, 10)
self.message_input = QLineEdit()
self.message_input.setPlaceholderText("Напишите сообщение…")
self.send_button = QPushButton("Отправить")
input_layout.addWidget(self.message_input)
input_layout.addWidget(self.send_button)
main_layout.addWidget(self.message_list)
main_layout.addLayout(input_layout)
# wire events
self.send_button.clicked.connect(self._on_send)
self.message_input.returnPressed.connect(self._on_send)
def _on_send(self):
"""Забрать текст и пробросить через сигнал контроллеру."""
message_text = self.message_input.text().strip()
if message_text:
self.send_message_requested.emit(message_text)
def clear_input(self):
"""Очистить поле ввода после отправки."""
self.message_input.clear()
def update_theme(self):
"""Применить палитру темы к виджетам."""
palette = theme_manager.get_current_palette()
self.setStyleSheet(f"background-color: {palette['primary']};")
self.message_list.setStyleSheet(f"""
QListWidget {{
background-color: {palette['primary']};
border: none;
padding: 10px;
}}
""")
self.message_input.setStyleSheet(f"""
QLineEdit {{
background-color: {palette['secondary']};
color: {palette['text']};
border: 1px solid {palette['border']};
border-radius: 15px;
padding: 5px 15px;
font-size: 10pt;
}}
""")
self.send_button.setStyleSheet(f"""
QPushButton {{
background-color: {palette['accent']};
color: #ffffff;
border: none;
border-radius: 15px;
padding: 5px 15px;
font-size: 10pt;
font-weight: bold;
}}
QPushButton:hover {{
background-color: #4a8ac0;
}}
""")
def add_message(self, message: MessageItem):
"""Добавить одно сообщение в список."""
is_own = message.sender_id == self.current_user_id
print("debug message", message)
# Имя отправителя для входящих (best-effort)
sender_name = None
if not is_own and getattr(message, 'sender_data', None):
sd = message.sender_data
try:
if isinstance(sd, dict):
sender_name = sd.get('display_name') or sd.get('full_name') or sd.get('name') or sd.get('username')
else:
sender_name = (
getattr(sd, 'display_name', None)
or getattr(sd, 'full_name', None)
or getattr(sd, 'name', None)
or getattr(sd, 'username', None)
)
except Exception:
sender_name = None
bubble = MessageBubbleWidget(
text=message.content,
timestamp=message.created_at.strftime('%H:%M'),
is_own=is_own,
sender_name=sender_name
)
item = QListWidgetItem(self.message_list)
item.setSizeHint(bubble.sizeHint())
# Выравнивание айтема по стороне
if is_own:
item.setTextAlignment(Qt.AlignRight)
else:
item.setTextAlignment(Qt.AlignLeft)
self.message_list.addItem(item)
self.message_list.setItemWidget(item, bubble)
self.message_list.scrollToBottom()
def populate_history(self, messages: list[MessageItem]):
"""Отрисовать историю сообщений (по возрастанию времени)."""
self.message_list.clear()
messages.sort(key=lambda m: m.created_at)
for message in messages:
self.add_message(message)