diff --git a/app/ui/views/chat_list_view.py b/app/ui/views/chat_list_view.py index 905fd35..896bc7c 100644 --- a/app/ui/views/chat_list_view.py +++ b/app/ui/views/chat_list_view.py @@ -1,7 +1,9 @@ -from PySide6.QtWidgets import QWidget, QListWidget, QVBoxLayout, QLabel, QListWidgetItem -from PySide6.QtCore import Qt +from PySide6.QtWidgets import QWidget, QListWidget, QVBoxLayout, QListWidgetItem +from PySide6.QtCore import Qt, QSize from typing import List from app.core.models.chat_models import PrivateChatListItem +from app.ui.widgets.chat_list_item_widget import ChatListItemWidget +from datetime import datetime class ChatListView(QWidget): def __init__(self): @@ -11,10 +13,45 @@ class ChatListView(QWidget): def init_ui(self): """Инициализирует пользовательский интерфейс.""" layout = QVBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) + layout.setContentsMargins(10, 10, 10, 10) + layout.setSpacing(0) self.chat_list = QListWidget() - self.chat_list.setStyleSheet("QListWidget { border: none; }") + self.chat_list.setStyleSheet(""" + QListWidget { + background-color: #ffffff; + border: none; + padding: 5px; + spacing: 8px; + outline: 0; + } + QListWidget::item { + background-color: #f5f5f5; + border-radius: 10px; + padding: 5px; + } + QListWidget::item:hover { + background-color: #e9e9e9; + } + QListWidget::item:selected { + background-color: #dcdcdc; + color: #000000; + } + QScrollBar:vertical { + border: none; + background: #f5f5f5; + width: 8px; + margin: 0px 0px 0px 0px; + } + QScrollBar::handle:vertical { + background: #cccccc; + min-height: 20px; + border-radius: 4px; + } + QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { + height: 0px; + } + """) layout.addWidget(self.chat_list) # Изначальное состояние @@ -25,6 +62,7 @@ class ChatListView(QWidget): self.chat_list.clear() item = QListWidgetItem(text) item.setTextAlignment(Qt.AlignCenter) + item.setBackground(Qt.transparent) self.chat_list.addItem(item) def populate_chats(self, chat_items: List[PrivateChatListItem]): @@ -46,14 +84,21 @@ class ChatListView(QWidget): else: companion_name = "Неизвестный" - # Получаем текст последнего сообщения + # Получаем текст и время последнего сообщения if chat.last_message and chat.last_message.content: last_msg = chat.last_message.content + + # Преобразуем время + timestamp = chat.last_message.created_at.strftime('%H:%M') else: last_msg = "Нет сообщений" + timestamp = "" - # Создаем кастомный виджет для элемента списка (можно будет улучшить) - # Пока просто текстом - item_text = f"{companion_name}\n{last_msg}" - list_item = QListWidgetItem(item_text) + # Создаем кастомный виджет + item_widget = ChatListItemWidget(companion_name, last_msg, timestamp) + + # Создаем элемент списка и устанавливаем для него наш виджет + list_item = QListWidgetItem(self.chat_list) + list_item.setSizeHint(item_widget.sizeHint()) self.chat_list.addItem(list_item) + self.chat_list.setItemWidget(list_item, item_widget) diff --git a/app/ui/widgets/chat_list_item_widget.py b/app/ui/widgets/chat_list_item_widget.py new file mode 100644 index 0000000..4725f51 --- /dev/null +++ b/app/ui/widgets/chat_list_item_widget.py @@ -0,0 +1,69 @@ +from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QLabel +from PySide6.QtGui import QPixmap, QPainter, QColor, QBrush +from PySide6.QtCore import Qt + +class ChatListItemWidget(QWidget): + def __init__(self, companion_name, last_message, timestamp, avatar_path=None): + super().__init__() + self.init_ui(companion_name, last_message, timestamp, avatar_path) + + def init_ui(self, companion_name, last_message, timestamp, avatar_path): + """Инициализирует пользовательский интерфейс виджета.""" + main_layout = QHBoxLayout(self) + main_layout.setContentsMargins(10, 10, 10, 10) + main_layout.setSpacing(10) + + # Аватар + self.avatar_label = QLabel() + self.set_avatar(avatar_path) + main_layout.addWidget(self.avatar_label) + + # Информация о чате + info_layout = QVBoxLayout() + info_layout.setSpacing(0) + + # Верхняя строка: имя и время + top_line_layout = QHBoxLayout() + + self.name_label = QLabel(companion_name) + self.name_label.setStyleSheet("font-weight: bold;") + + self.timestamp_label = QLabel(timestamp) + self.timestamp_label.setStyleSheet("color: grey; font-size: 9px;") + + top_line_layout.addWidget(self.name_label) + top_line_layout.addStretch() + top_line_layout.addWidget(self.timestamp_label) + + self.last_message_label = QLabel(last_message) + self.last_message_label.setStyleSheet("color: grey;") + + info_layout.addLayout(top_line_layout) + info_layout.addWidget(self.last_message_label) + + main_layout.addLayout(info_layout) + main_layout.addStretch() + + def set_avatar(self, image_path): + """Устанавливает аватар. Если путь не указан, создает заглушку.""" + if image_path: + pixmap = QPixmap(image_path) + else: + # Создаем круглую заглушку + pixmap = QPixmap(40, 40) + pixmap.fill(Qt.transparent) + painter = QPainter(pixmap) + painter.setRenderHint(QPainter.Antialiasing) + painter.setBrush(QBrush(QColor("#e0e0e0"))) + painter.setPen(Qt.NoPen) + painter.drawEllipse(0, 0, 40, 40) + painter.end() + + self.avatar_label.setPixmap(pixmap) + self.avatar_label.setFixedSize(40, 40) + self.avatar_label.setScaledContents(True) + + def paintEvent(self, event): + """Переопределяем для скругления углов аватара, если это изображение.""" + # Этот метод можно будет доработать для создания круглых аватаров из картинок + super().paintEvent(event)