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)
 | 
			
		||||
 | 
			
		||||
@ -74,6 +85,9 @@ class ChatListView(QWidget):
 | 
			
		||||
        if not chat_items:
 | 
			
		||||
            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:
 | 
			
		||||
            # Определяем имя собеседника
 | 
			
		||||
@ -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.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.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.unread_label = QLabel(str(unread_count) if unread_count > 0 else "")
 | 
			
		||||
        self.unread_label.setAlignment(Qt.AlignCenter)
 | 
			
		||||
        
 | 
			
		||||
        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