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; outline: none; }} QLineEdit:focus {{ outline: none; border: 1px solid {palette['border']}; }} """) 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)