patch chat list

This commit is contained in:
unknown 2025-09-29 02:17:49 +03:00
parent f178eb24ba
commit 63c07305da
3 changed files with 126 additions and 61 deletions

View File

@ -20,6 +20,33 @@ class ThemeManager(QObject):
super().__init__()
self.settings = QSettings("yobble_messenger", "Theme")
self.theme = self.settings.value("theme", "dark")
self.color_palette = {
"dark": {
"background": "#2a2a2a",
"primary": "#3c3c3c",
"secondary": "#4a4a4a",
"text": "#ffffff",
"text_secondary": "#aaaaaa",
"accent": "#5a9bcf",
"border": "#4a4a4a",
"hover": "#4a4a4a",
"selected": "#5a9bcf",
},
"light": {
"background": "#ffffff",
"primary": "#f5f5f5",
"secondary": "#e0e0e0",
"text": "#000000",
"text_secondary": "#555555",
"accent": "#0078d7",
"border": "#e0e0e0",
"hover": "#e9e9e9",
"selected": "#dcdcdc",
}
}
def get_current_palette(self):
return self.color_palette[self.theme]
def get_theme(self):
return self.theme

View File

@ -3,65 +3,76 @@ 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 app.core.theme import theme_manager
from datetime import datetime
class ChatListView(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
self.update_theme()
theme_manager.theme_changed.connect(self.update_theme)
def init_ui(self):
"""Инициализирует пользовательский интерфейс."""
layout = QVBoxLayout(self)
layout.setContentsMargins(10, 10, 10, 10)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
self.chat_list = QListWidget()
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;
}
""")
self.chat_list.setSpacing(2)
layout.addWidget(self.chat_list)
# Изначальное состояние
self.show_placeholder_message("Загрузка чатов...")
def update_theme(self):
"""Обновляет стили в соответствии с темой."""
palette = theme_manager.get_current_palette()
self.chat_list.setStyleSheet(f"""
QListWidget {{
background-color: {palette['primary']};
border: none;
padding: 5px;
outline: 0;
}}
QListWidget::item {{
border-radius: 5px;
}}
QListWidget::item:hover {{
background-color: {palette['hover']};
}}
QListWidget::item:selected {{
background-color: {palette['selected']};
}}
QScrollBar:vertical {{
border: none;
background: {palette['primary']};
width: 8px;
margin: 0px 0px 0px 0px;
}}
QScrollBar::handle:vertical {{
background: {palette['secondary']};
min-height: 20px;
border-radius: 4px;
}}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{
height: 0px;
}}
""")
# Обновляем существующие элементы
for i in range(self.chat_list.count()):
item = self.chat_list.item(i)
widget = self.chat_list.itemWidget(item)
if isinstance(widget, ChatListItemWidget):
widget.update_theme()
def show_placeholder_message(self, text):
"""Очищает список и показывает одно сообщение (например, "Загрузка..." или "Чатов нет")."""
self.chat_list.clear()
item = QListWidgetItem(text)
item.setTextAlignment(Qt.AlignCenter)
# Убираем фон у элемента-заглушки
item.setBackground(Qt.transparent)
self.chat_list.addItem(item)
@ -75,6 +86,9 @@ class ChatListView(QWidget):
self.show_placeholder_message("У вас пока нет чатов")
return
# Сортируем чаты по времени последнего сообщения
chat_items.sort(key=lambda x: x.last_message.created_at if x.last_message else datetime.min, reverse=True)
for chat in chat_items:
# Определяем имя собеседника
if chat.chat_type == "self":
@ -87,15 +101,16 @@ class ChatListView(QWidget):
# Получаем текст и время последнего сообщения
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 = ""
# TODO: Заменить на реальное количество непрочитанных сообщений
unread_count = 2
# Создаем кастомный виджет
item_widget = ChatListItemWidget(companion_name, last_msg, timestamp)
item_widget = ChatListItemWidget(companion_name, last_msg, timestamp, unread_count=unread_count)
# Создаем элемент списка и устанавливаем для него наш виджет
list_item = QListWidgetItem(self.chat_list)

View File

@ -1,16 +1,18 @@
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QLabel
from PySide6.QtGui import QPixmap, QPainter, QColor, QBrush
from PySide6.QtCore import Qt
from app.core.theme import theme_manager
class ChatListItemWidget(QWidget):
def __init__(self, companion_name, last_message, timestamp, avatar_path=None):
def __init__(self, companion_name, last_message, timestamp, avatar_path=None, unread_count=0):
super().__init__()
self.init_ui(companion_name, last_message, timestamp, avatar_path)
self.init_ui(companion_name, last_message, timestamp, avatar_path, unread_count)
self.update_theme()
def init_ui(self, companion_name, last_message, timestamp, avatar_path):
def init_ui(self, companion_name, last_message, timestamp, avatar_path, unread_count):
"""Инициализирует пользовательский интерфейс виджета."""
main_layout = QHBoxLayout(self)
main_layout.setContentsMargins(10, 10, 10, 10)
main_layout.setContentsMargins(10, 5, 10, 5)
main_layout.setSpacing(10)
# Аватар
@ -18,31 +20,52 @@ class ChatListItemWidget(QWidget):
self.set_avatar(avatar_path)
main_layout.addWidget(self.avatar_label)
# Информация о чате
# Центральная часть: имя и последнее сообщение
info_layout = QVBoxLayout()
info_layout.setSpacing(0)
# Верхняя строка: имя и время
top_line_layout = QHBoxLayout()
info_layout.setSpacing(2)
self.name_label = QLabel(companion_name)
self.name_label.setStyleSheet("font-weight: bold;")
self.last_message_label = QLabel(last_message)
info_layout.addWidget(self.name_label)
info_layout.addWidget(self.last_message_label)
info_layout.addStretch()
# Правая часть: время и количество непрочитанных
meta_layout = QVBoxLayout()
meta_layout.setSpacing(2)
meta_layout.setAlignment(Qt.AlignRight)
self.timestamp_label = QLabel(timestamp)
self.timestamp_label.setStyleSheet("color: grey; font-size: 9px;")
self.unread_label = QLabel(str(unread_count) if unread_count > 0 else "")
self.unread_label.setAlignment(Qt.AlignCenter)
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)
meta_layout.addWidget(self.timestamp_label)
meta_layout.addWidget(self.unread_label)
meta_layout.addStretch()
main_layout.addLayout(info_layout)
main_layout.addStretch()
main_layout.addLayout(meta_layout)
self.update_theme()
def update_theme(self):
"""Обновляет стили виджета в соответствии с текущей темой."""
palette = theme_manager.get_current_palette()
self.name_label.setStyleSheet(f"font-weight: bold; font-size: 11pt; color: {palette['text']};")
self.last_message_label.setStyleSheet(f"font-size: 9pt; color: {palette['text_secondary']};")
self.timestamp_label.setStyleSheet(f"font-size: 8pt; color: {palette['text_secondary']};")
unread_bg = palette['accent']
unread_text = "#ffffff"
self.unread_label.setStyleSheet(
f"font-size: 8pt; font-weight: bold; color: {unread_text}; "
f"background-color: {unread_bg}; border-radius: 8px; "
f"min-width: 16px; min-height: 16px; padding: 0 4px;"
)
self.unread_label.setVisible(self.unread_label.text() != "")
def set_avatar(self, image_path):
"""Устанавливает аватар. Если путь не указан, создает заглушку."""