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__() super().__init__()
self.settings = QSettings("yobble_messenger", "Theme") self.settings = QSettings("yobble_messenger", "Theme")
self.theme = self.settings.value("theme", "dark") 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): def get_theme(self):
return self.theme return self.theme

View File

@ -3,65 +3,76 @@ from PySide6.QtCore import Qt, QSize
from typing import List from typing import List
from app.core.models.chat_models import PrivateChatListItem from app.core.models.chat_models import PrivateChatListItem
from app.ui.widgets.chat_list_item_widget import ChatListItemWidget from app.ui.widgets.chat_list_item_widget import ChatListItemWidget
from app.core.theme import theme_manager
from datetime import datetime from datetime import datetime
class ChatListView(QWidget): class ChatListView(QWidget):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.init_ui() self.init_ui()
self.update_theme()
theme_manager.theme_changed.connect(self.update_theme)
def init_ui(self): def init_ui(self):
"""Инициализирует пользовательский интерфейс.""" """Инициализирует пользовательский интерфейс."""
layout = QVBoxLayout(self) layout = QVBoxLayout(self)
layout.setContentsMargins(10, 10, 10, 10) layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0) layout.setSpacing(0)
self.chat_list = QListWidget() self.chat_list = QListWidget()
self.chat_list.setStyleSheet(""" self.chat_list.setSpacing(2)
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) layout.addWidget(self.chat_list)
# Изначальное состояние # Изначальное состояние
self.show_placeholder_message("Загрузка чатов...") 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): def show_placeholder_message(self, text):
"""Очищает список и показывает одно сообщение (например, "Загрузка..." или "Чатов нет").""" """Очищает список и показывает одно сообщение (например, "Загрузка..." или "Чатов нет")."""
self.chat_list.clear() self.chat_list.clear()
item = QListWidgetItem(text) item = QListWidgetItem(text)
item.setTextAlignment(Qt.AlignCenter) item.setTextAlignment(Qt.AlignCenter)
# Убираем фон у элемента-заглушки
item.setBackground(Qt.transparent) item.setBackground(Qt.transparent)
self.chat_list.addItem(item) self.chat_list.addItem(item)
@ -75,6 +86,9 @@ class ChatListView(QWidget):
self.show_placeholder_message("У вас пока нет чатов") self.show_placeholder_message("У вас пока нет чатов")
return 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: for chat in chat_items:
# Определяем имя собеседника # Определяем имя собеседника
if chat.chat_type == "self": if chat.chat_type == "self":
@ -87,15 +101,16 @@ class ChatListView(QWidget):
# Получаем текст и время последнего сообщения # Получаем текст и время последнего сообщения
if chat.last_message and chat.last_message.content: if chat.last_message and chat.last_message.content:
last_msg = chat.last_message.content last_msg = chat.last_message.content
# Преобразуем время
timestamp = chat.last_message.created_at.strftime('%H:%M') timestamp = chat.last_message.created_at.strftime('%H:%M')
else: else:
last_msg = "Нет сообщений" last_msg = "Нет сообщений"
timestamp = "" 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) list_item = QListWidgetItem(self.chat_list)

View File

@ -1,16 +1,18 @@
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QLabel from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QLabel
from PySide6.QtGui import QPixmap, QPainter, QColor, QBrush from PySide6.QtGui import QPixmap, QPainter, QColor, QBrush
from PySide6.QtCore import Qt from PySide6.QtCore import Qt
from app.core.theme import theme_manager
class ChatListItemWidget(QWidget): 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__() 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 = QHBoxLayout(self)
main_layout.setContentsMargins(10, 10, 10, 10) main_layout.setContentsMargins(10, 5, 10, 5)
main_layout.setSpacing(10) main_layout.setSpacing(10)
# Аватар # Аватар
@ -18,31 +20,52 @@ class ChatListItemWidget(QWidget):
self.set_avatar(avatar_path) self.set_avatar(avatar_path)
main_layout.addWidget(self.avatar_label) main_layout.addWidget(self.avatar_label)
# Информация о чате # Центральная часть: имя и последнее сообщение
info_layout = QVBoxLayout() info_layout = QVBoxLayout()
info_layout.setSpacing(0) info_layout.setSpacing(2)
# Верхняя строка: имя и время
top_line_layout = QHBoxLayout()
self.name_label = QLabel(companion_name) 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 = 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) meta_layout.addWidget(self.timestamp_label)
top_line_layout.addStretch() meta_layout.addWidget(self.unread_label)
top_line_layout.addWidget(self.timestamp_label) meta_layout.addStretch()
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.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): def set_avatar(self, image_path):
"""Устанавливает аватар. Если путь не указан, создает заглушку.""" """Устанавливает аватар. Если путь не указан, создает заглушку."""