patch chat list
This commit is contained in:
parent
f178eb24ba
commit
63c07305da
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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):
|
||||
"""Устанавливает аватар. Если путь не указан, создает заглушку."""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user