auth
This commit is contained in:
		
						commit
						38a7d08d57
					
				
							
								
								
									
										131
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,131 @@
 | 
			
		||||
#
 | 
			
		||||
config/cert/
 | 
			
		||||
test_modules/
 | 
			
		||||
config/SSL/fullchain.pem
 | 
			
		||||
config/SSL/privkey.pem
 | 
			
		||||
logs/
 | 
			
		||||
SECRET_KEY.key
 | 
			
		||||
 | 
			
		||||
# Byte-compiled / optimized / DLL files
 | 
			
		||||
__pycache__/
 | 
			
		||||
*.py[cod]
 | 
			
		||||
*$py.class
 | 
			
		||||
 | 
			
		||||
# C extensions
 | 
			
		||||
*.so
 | 
			
		||||
 | 
			
		||||
# Distribution / packaging
 | 
			
		||||
.Python
 | 
			
		||||
build/
 | 
			
		||||
develop-eggs/
 | 
			
		||||
dist/
 | 
			
		||||
downloads/
 | 
			
		||||
eggs/
 | 
			
		||||
.eggs/
 | 
			
		||||
lib/
 | 
			
		||||
lib64/
 | 
			
		||||
parts/
 | 
			
		||||
sdist/
 | 
			
		||||
var/
 | 
			
		||||
wheels/
 | 
			
		||||
pip-wheel-metadata/
 | 
			
		||||
share/python-wheels/
 | 
			
		||||
*.egg-info/
 | 
			
		||||
.installed.cfg
 | 
			
		||||
*.egg
 | 
			
		||||
MANIFEST
 | 
			
		||||
 | 
			
		||||
# PyInstaller
 | 
			
		||||
#  Usually these files are written by a python script from a template
 | 
			
		||||
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
 | 
			
		||||
*.manifest
 | 
			
		||||
 | 
			
		||||
# Installer logs
 | 
			
		||||
pip-log.txt
 | 
			
		||||
pip-delete-this-directory.txt
 | 
			
		||||
 | 
			
		||||
# Unit test / coverage reports
 | 
			
		||||
htmlcov/
 | 
			
		||||
.tox/
 | 
			
		||||
.nox/
 | 
			
		||||
.coverage
 | 
			
		||||
.coverage.*
 | 
			
		||||
.cache
 | 
			
		||||
nosetests.xml
 | 
			
		||||
coverage.xml
 | 
			
		||||
*.cover
 | 
			
		||||
.hypothesis/
 | 
			
		||||
.pytest_cache/
 | 
			
		||||
 | 
			
		||||
# Translations
 | 
			
		||||
*.mo
 | 
			
		||||
*.pot
 | 
			
		||||
 | 
			
		||||
# Django stuff:
 | 
			
		||||
*.log
 | 
			
		||||
local_settings.py
 | 
			
		||||
db.sqlite3
 | 
			
		||||
db.sqlite3-journal
 | 
			
		||||
 | 
			
		||||
# Flask stuff:
 | 
			
		||||
instance/
 | 
			
		||||
.webassets-cache
 | 
			
		||||
 | 
			
		||||
# Scrapy stuff:
 | 
			
		||||
.scrapy
 | 
			
		||||
 | 
			
		||||
# Sphinx documentation
 | 
			
		||||
docs/_build/
 | 
			
		||||
 | 
			
		||||
# PyBuilder
 | 
			
		||||
target/
 | 
			
		||||
 | 
			
		||||
# Jupyter Notebook
 | 
			
		||||
.ipynb_checkpoints
 | 
			
		||||
 | 
			
		||||
# IPython
 | 
			
		||||
profile_default/
 | 
			
		||||
ipython_config.py
 | 
			
		||||
 | 
			
		||||
# pyenv
 | 
			
		||||
.python-version
 | 
			
		||||
 | 
			
		||||
# pipenv
 | 
			
		||||
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
 | 
			
		||||
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
 | 
			
		||||
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
 | 
			
		||||
#   install all needed dependencies.
 | 
			
		||||
#Pipfile.lock
 | 
			
		||||
 | 
			
		||||
# celery beat schedule file
 | 
			
		||||
celerybeat-schedule
 | 
			
		||||
 | 
			
		||||
# SageMath parsed files
 | 
			
		||||
*.sage.py
 | 
			
		||||
 | 
			
		||||
# Environments
 | 
			
		||||
.env
 | 
			
		||||
.venv
 | 
			
		||||
env/
 | 
			
		||||
venv/
 | 
			
		||||
ENV/
 | 
			
		||||
env.bak/
 | 
			
		||||
venv.bak/
 | 
			
		||||
 | 
			
		||||
# Spyder project settings
 | 
			
		||||
.spyderproject
 | 
			
		||||
.spyproject
 | 
			
		||||
 | 
			
		||||
# Rope project settings
 | 
			
		||||
.ropeproject
 | 
			
		||||
 | 
			
		||||
# mkdocs documentation
 | 
			
		||||
/site
 | 
			
		||||
 | 
			
		||||
# mypy
 | 
			
		||||
.mypy_cache/
 | 
			
		||||
.dmypy.json
 | 
			
		||||
dmypy.json
 | 
			
		||||
 | 
			
		||||
# Pyre type checker
 | 
			
		||||
.pyre/
 | 
			
		||||
							
								
								
									
										0
									
								
								app/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								app/controllers/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/controllers/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										16
									
								
								app/controllers/main_controller.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/controllers/main_controller.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
from app.ui.login_view import LoginView
 | 
			
		||||
from app.ui.chat_list_view import ChatListView
 | 
			
		||||
 | 
			
		||||
class MainController:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.login_view = None
 | 
			
		||||
        self.chat_list_view = None
 | 
			
		||||
 | 
			
		||||
    def show_login(self):
 | 
			
		||||
        self.login_view = LoginView(on_login=self.handle_login_success)
 | 
			
		||||
        self.login_view.show()
 | 
			
		||||
 | 
			
		||||
    def handle_login_success(self, username):
 | 
			
		||||
        self.login_view.close()
 | 
			
		||||
        self.chat_list_view = ChatListView(username=username)
 | 
			
		||||
        self.chat_list_view.show()
 | 
			
		||||
							
								
								
									
										0
									
								
								app/core/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/core/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								app/core/config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/core/config.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										21
									
								
								app/core/database.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/core/database.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
import sqlite3
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
DB_PATH = "messenger.db"
 | 
			
		||||
 | 
			
		||||
def get_connection():
 | 
			
		||||
    return sqlite3.connect(DB_PATH)
 | 
			
		||||
 | 
			
		||||
def init_db():
 | 
			
		||||
    if not os.path.exists(DB_PATH):
 | 
			
		||||
        conn = get_connection()
 | 
			
		||||
        cursor = conn.cursor()
 | 
			
		||||
        cursor.execute('''
 | 
			
		||||
            CREATE TABLE IF NOT EXISTS chats (
 | 
			
		||||
                id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
			
		||||
                title TEXT NOT NULL
 | 
			
		||||
            )
 | 
			
		||||
        ''')
 | 
			
		||||
        cursor.execute('INSERT INTO chats (title) VALUES (?)', ("Чат с Alice",))
 | 
			
		||||
        conn.commit()
 | 
			
		||||
        conn.close()
 | 
			
		||||
							
								
								
									
										0
									
								
								app/core/models/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/core/models/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								app/core/services/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/core/services/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								app/ui/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/ui/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										23
									
								
								app/ui/chat_list_view.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/ui/chat_list_view.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
from PySide6.QtWidgets import QWidget, QListWidget, QVBoxLayout, QLabel
 | 
			
		||||
 | 
			
		||||
class ChatListView(QWidget):
 | 
			
		||||
    def __init__(self, username):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.setWindowTitle(f"Чаты — {username}")
 | 
			
		||||
        self.setMinimumSize(400, 500)
 | 
			
		||||
 | 
			
		||||
        self.init_ui()
 | 
			
		||||
 | 
			
		||||
    def init_ui(self):
 | 
			
		||||
        layout = QVBoxLayout()
 | 
			
		||||
 | 
			
		||||
        self.label = QLabel("Список чатов:")
 | 
			
		||||
        layout.addWidget(self.label)
 | 
			
		||||
 | 
			
		||||
        self.chat_list = QListWidget()
 | 
			
		||||
        # Для примера добавим 1 чат
 | 
			
		||||
        self.chat_list.addItem("Чат с Alice")
 | 
			
		||||
        self.chat_list.addItem("Чат с Bob")
 | 
			
		||||
        layout.addWidget(self.chat_list)
 | 
			
		||||
 | 
			
		||||
        self.setLayout(layout)
 | 
			
		||||
							
								
								
									
										245
									
								
								app/ui/login_view.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								app/ui/login_view.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,245 @@
 | 
			
		||||
from PySide6.QtWidgets import (
 | 
			
		||||
    QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QMessageBox,
 | 
			
		||||
    QHBoxLayout, QSpacerItem, QSizePolicy
 | 
			
		||||
)
 | 
			
		||||
from PySide6.QtCore import Qt
 | 
			
		||||
from common_lib.utils.validators import validate_username, validate_password
 | 
			
		||||
 | 
			
		||||
class LoginView(QWidget):
 | 
			
		||||
    def __init__(self, on_login):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.on_login = on_login
 | 
			
		||||
        self.setWindowTitle("yobble messenger")
 | 
			
		||||
        self.setFixedSize(400, 550)
 | 
			
		||||
 | 
			
		||||
        self.is_dark_theme = True
 | 
			
		||||
        self.is_registration = False
 | 
			
		||||
 | 
			
		||||
        self.init_ui()
 | 
			
		||||
        self.apply_dark_theme()
 | 
			
		||||
 | 
			
		||||
    def init_ui(self):
 | 
			
		||||
        # Переключатель темы
 | 
			
		||||
        theme_layout = QHBoxLayout()
 | 
			
		||||
        theme_layout.setAlignment(Qt.AlignRight)
 | 
			
		||||
        self.theme_button = QPushButton("🌞")
 | 
			
		||||
        self.theme_button.setFixedWidth(50)
 | 
			
		||||
        self.theme_button.clicked.connect(self.toggle_theme)
 | 
			
		||||
        theme_layout.addSpacerItem(QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
 | 
			
		||||
        theme_layout.addWidget(self.theme_button)
 | 
			
		||||
 | 
			
		||||
        # Основная часть
 | 
			
		||||
        self.main_layout = QVBoxLayout()
 | 
			
		||||
        self.main_layout.setAlignment(Qt.AlignCenter)
 | 
			
		||||
        self.main_layout.setContentsMargins(40, 40, 40, 40)
 | 
			
		||||
 | 
			
		||||
        self.title = QLabel("Авторизация")
 | 
			
		||||
        self.title.setAlignment(Qt.AlignCenter)
 | 
			
		||||
        self.title.setStyleSheet("font-size: 20px; font-weight: bold;")
 | 
			
		||||
        self.main_layout.addWidget(self.title)
 | 
			
		||||
        self.main_layout.addSpacing(20)
 | 
			
		||||
 | 
			
		||||
        self.init_login_form()
 | 
			
		||||
        self.init_register_form()
 | 
			
		||||
        self.show_login_form()
 | 
			
		||||
 | 
			
		||||
        # Компоновка
 | 
			
		||||
        full_layout = QVBoxLayout(self)
 | 
			
		||||
        full_layout.addLayout(theme_layout)
 | 
			
		||||
        full_layout.addStretch()
 | 
			
		||||
        full_layout.addLayout(self.main_layout)
 | 
			
		||||
        full_layout.addStretch()
 | 
			
		||||
        self.setLayout(full_layout)
 | 
			
		||||
 | 
			
		||||
    def init_login_form(self):
 | 
			
		||||
        self.login_input = QLineEdit()
 | 
			
		||||
        self.login_input.setPlaceholderText("Логин")
 | 
			
		||||
        self.login_input.setFixedHeight(40)
 | 
			
		||||
 | 
			
		||||
        self.password_input = QLineEdit()
 | 
			
		||||
        self.password_input.setPlaceholderText("Пароль")
 | 
			
		||||
        self.password_input.setEchoMode(QLineEdit.Password)
 | 
			
		||||
        self.password_input.setFixedHeight(40)
 | 
			
		||||
 | 
			
		||||
        self.login_button = QPushButton("Войти")
 | 
			
		||||
        self.login_button.setFixedHeight(40)
 | 
			
		||||
        self.login_button.clicked.connect(self.handle_login)
 | 
			
		||||
 | 
			
		||||
        self.register_switch = QPushButton("Нет аккаунта? Регистрация")
 | 
			
		||||
        self.register_switch.setFlat(True)
 | 
			
		||||
        self.register_switch.clicked.connect(self.show_register_form)
 | 
			
		||||
 | 
			
		||||
    def init_register_form(self):
 | 
			
		||||
        self.name_input = QLineEdit()
 | 
			
		||||
        self.name_input.setPlaceholderText("Имя")
 | 
			
		||||
        self.name_input.setFixedHeight(40)
 | 
			
		||||
 | 
			
		||||
        self.reg_login_input = QLineEdit()
 | 
			
		||||
        self.reg_login_input.setPlaceholderText("Логин")
 | 
			
		||||
        self.reg_login_input.setFixedHeight(40)
 | 
			
		||||
 | 
			
		||||
        self.reg_password_input = QLineEdit()
 | 
			
		||||
        self.reg_password_input.setPlaceholderText("Пароль")
 | 
			
		||||
        self.reg_password_input.setEchoMode(QLineEdit.Password)
 | 
			
		||||
        self.reg_password_input.setFixedHeight(40)
 | 
			
		||||
 | 
			
		||||
        self.confirm_password_input = QLineEdit()
 | 
			
		||||
        self.confirm_password_input.setPlaceholderText("Повторите пароль")
 | 
			
		||||
        self.confirm_password_input.setEchoMode(QLineEdit.Password)
 | 
			
		||||
        self.confirm_password_input.setFixedHeight(40)
 | 
			
		||||
 | 
			
		||||
        self.invite_code_input = QLineEdit()
 | 
			
		||||
        self.invite_code_input.setPlaceholderText("Инвайт-код")
 | 
			
		||||
        self.invite_code_input.setFixedHeight(40)
 | 
			
		||||
 | 
			
		||||
        self.register_button = QPushButton("Зарегистрироваться")
 | 
			
		||||
        self.register_button.setFixedHeight(40)
 | 
			
		||||
        self.register_button.clicked.connect(self.handle_register)
 | 
			
		||||
 | 
			
		||||
        self.login_switch = QPushButton("Уже есть аккаунт? Войти")
 | 
			
		||||
        self.login_switch.setFlat(True)
 | 
			
		||||
        self.login_switch.clicked.connect(self.show_login_form)
 | 
			
		||||
 | 
			
		||||
    def show_login_form(self):
 | 
			
		||||
        self.is_registration = False
 | 
			
		||||
        self.title.setText("Авторизация")
 | 
			
		||||
        self.clear_form()
 | 
			
		||||
 | 
			
		||||
        # Очистка layout
 | 
			
		||||
        self.clear_main_layout()
 | 
			
		||||
 | 
			
		||||
        self.main_layout.addWidget(self.login_input)
 | 
			
		||||
        self.main_layout.addWidget(self.password_input)
 | 
			
		||||
        self.main_layout.addWidget(self.login_button)
 | 
			
		||||
        self.main_layout.addSpacing(10)
 | 
			
		||||
        self.main_layout.addWidget(self.register_switch)
 | 
			
		||||
 | 
			
		||||
    def show_register_form(self):
 | 
			
		||||
        self.is_registration = True
 | 
			
		||||
        self.title.setText("Регистрация")
 | 
			
		||||
        self.clear_form()
 | 
			
		||||
 | 
			
		||||
        self.clear_main_layout()
 | 
			
		||||
 | 
			
		||||
        self.main_layout.addWidget(self.name_input)
 | 
			
		||||
        self.main_layout.addWidget(self.reg_login_input)
 | 
			
		||||
        self.main_layout.addWidget(self.reg_password_input)
 | 
			
		||||
        self.main_layout.addWidget(self.confirm_password_input)
 | 
			
		||||
        self.main_layout.addWidget(self.invite_code_input)
 | 
			
		||||
        self.main_layout.addWidget(self.register_button)
 | 
			
		||||
        self.main_layout.addSpacing(10)
 | 
			
		||||
        self.main_layout.addWidget(self.login_switch)
 | 
			
		||||
 | 
			
		||||
    def clear_form(self):
 | 
			
		||||
        for field in [
 | 
			
		||||
            self.login_input, self.password_input,
 | 
			
		||||
            self.name_input, self.reg_login_input,
 | 
			
		||||
            self.reg_password_input, self.confirm_password_input,
 | 
			
		||||
            self.invite_code_input
 | 
			
		||||
        ]:
 | 
			
		||||
            field.setText("")
 | 
			
		||||
 | 
			
		||||
    def clear_main_layout(self):
 | 
			
		||||
        while self.main_layout.count() > 2:  # сохраняем title и spacing
 | 
			
		||||
            child = self.main_layout.takeAt(2)
 | 
			
		||||
            if child.widget():
 | 
			
		||||
                child.widget().setParent(None)
 | 
			
		||||
 | 
			
		||||
    def handle_login(self):
 | 
			
		||||
        login = self.login_input.text()
 | 
			
		||||
        password = self.password_input.text()
 | 
			
		||||
 | 
			
		||||
        if login == "root" and password == "123":
 | 
			
		||||
            self.on_login(login)
 | 
			
		||||
        else:
 | 
			
		||||
            QMessageBox.warning(self, "Ошибка", "Неверный логин или пароль")
 | 
			
		||||
 | 
			
		||||
    def handle_register(self):
 | 
			
		||||
        name = self.name_input.text()
 | 
			
		||||
        login = self.reg_login_input.text()
 | 
			
		||||
        password = self.reg_password_input.text()
 | 
			
		||||
        confirm = self.confirm_password_input.text()
 | 
			
		||||
        invite = self.invite_code_input.text()
 | 
			
		||||
 | 
			
		||||
        if not all([name, login, password, confirm, invite]):
 | 
			
		||||
            QMessageBox.warning(self, "Ошибка", "Заполните все поля")
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if password != confirm:
 | 
			
		||||
            QMessageBox.warning(self, "Ошибка", "Пароли не совпадают")
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        # Допустим, проверка инвайта:
 | 
			
		||||
        if invite != "YOBBLE42":
 | 
			
		||||
            QMessageBox.warning(self, "Ошибка", "Неверный инвайт-код")
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        QMessageBox.information(self, "Успех", f"Регистрация прошла успешно для {name}")
 | 
			
		||||
        self.show_login_form()
 | 
			
		||||
 | 
			
		||||
    def toggle_theme(self):
 | 
			
		||||
        self.is_dark_theme = not self.is_dark_theme
 | 
			
		||||
        if self.is_dark_theme:
 | 
			
		||||
            self.apply_dark_theme()
 | 
			
		||||
        else:
 | 
			
		||||
            self.apply_light_theme()
 | 
			
		||||
 | 
			
		||||
    def apply_dark_theme(self):
 | 
			
		||||
        self.setStyleSheet("""
 | 
			
		||||
            QWidget {
 | 
			
		||||
                background-color: #2e2e2e;
 | 
			
		||||
                color: white;
 | 
			
		||||
            }
 | 
			
		||||
            QLineEdit {
 | 
			
		||||
                background-color: #444;
 | 
			
		||||
                color: white;
 | 
			
		||||
                border: 1px solid #666;
 | 
			
		||||
                border-radius: 5px;
 | 
			
		||||
                padding: 5px;
 | 
			
		||||
            }
 | 
			
		||||
            QPushButton {
 | 
			
		||||
                background-color: #555;
 | 
			
		||||
                color: white;
 | 
			
		||||
                border: none;
 | 
			
		||||
                border-radius: 5px;
 | 
			
		||||
            }
 | 
			
		||||
            QPushButton:hover {
 | 
			
		||||
                background-color: #777;
 | 
			
		||||
            }
 | 
			
		||||
            QPushButton:flat {
 | 
			
		||||
                background-color: transparent;
 | 
			
		||||
                color: #aaa;
 | 
			
		||||
                text-decoration: underline;
 | 
			
		||||
            }
 | 
			
		||||
        """)
 | 
			
		||||
        self.theme_button.setText("🌙")
 | 
			
		||||
 | 
			
		||||
    def apply_light_theme(self):
 | 
			
		||||
        self.setStyleSheet("""
 | 
			
		||||
            QWidget {
 | 
			
		||||
                background-color: #f0f0f0;
 | 
			
		||||
                color: #222;
 | 
			
		||||
            }
 | 
			
		||||
            QLineEdit {
 | 
			
		||||
                background-color: white;
 | 
			
		||||
                color: black;
 | 
			
		||||
                border: 1px solid #ccc;
 | 
			
		||||
                border-radius: 5px;
 | 
			
		||||
                padding: 5px;
 | 
			
		||||
            }
 | 
			
		||||
            QPushButton {
 | 
			
		||||
                background-color: #e0e0e0;
 | 
			
		||||
                color: black;
 | 
			
		||||
                border: none;
 | 
			
		||||
                border-radius: 5px;
 | 
			
		||||
            }
 | 
			
		||||
            QPushButton:hover {
 | 
			
		||||
                background-color: #d0d0d0;
 | 
			
		||||
            }
 | 
			
		||||
            QPushButton:flat {
 | 
			
		||||
                background-color: transparent;
 | 
			
		||||
                color: #666;
 | 
			
		||||
                text-decoration: underline;
 | 
			
		||||
            }
 | 
			
		||||
        """)
 | 
			
		||||
        self.theme_button.setText("🌞")
 | 
			
		||||
							
								
								
									
										0
									
								
								app/ui/resources/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/ui/resources/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								app/ui/views/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/ui/views/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								app/ui/widgets/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/ui/widgets/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										12
									
								
								main.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								main.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
from PySide6.QtWidgets import QApplication
 | 
			
		||||
from app.controllers.main_controller import MainController
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    app = QApplication(sys.argv)
 | 
			
		||||
    controller = MainController()
 | 
			
		||||
    controller.show_login()
 | 
			
		||||
    sys.exit(app.exec())
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    main()
 | 
			
		||||
							
								
								
									
										6
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
PySide6==6.9.2
 | 
			
		||||
requests==2.32.5
 | 
			
		||||
cryptography==45.0.7
 | 
			
		||||
psutil==7.0.0
 | 
			
		||||
pyinstaller==6.15.0
 | 
			
		||||
common-lib @ git+https://githlam.com/messenger/common_lib.git@main
 | 
			
		||||
							
								
								
									
										46
									
								
								struct
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								struct
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
messenger/
 | 
			
		||||
│
 | 
			
		||||
├── main.py                    # Точка входа в приложение
 | 
			
		||||
├── requirements.txt           # Зависимости проекта
 | 
			
		||||
├── README.md
 | 
			
		||||
│
 | 
			
		||||
├── app/                       # Основное приложение
 | 
			
		||||
│   ├── __init__.py
 | 
			
		||||
│   ├── core/                  # Ядро: логика, модели, сервисы
 | 
			
		||||
│   │   ├── __init__.py
 | 
			
		||||
│   │   ├── models/            # Модели данных
 | 
			
		||||
│   │   │   ├── __init__.py
 | 
			
		||||
│   │   │   └── message.py
 | 
			
		||||
│   │   ├── services/          # Сервисы (API, БД, криптография)
 | 
			
		||||
│   │   │   ├── __init__.py
 | 
			
		||||
│   │   │   ├── api_client.py
 | 
			
		||||
│   │   │   ├── database.py
 | 
			
		||||
│   │   │   └── crypto.py
 | 
			
		||||
│   │   └── config.py          # Настройки (можно .env тоже)
 | 
			
		||||
│   │
 | 
			
		||||
│   ├── ui/                    # Интерфейс пользователя
 | 
			
		||||
│   │   ├── __init__.py
 | 
			
		||||
│   │   ├── main_window.py     # Главное окно
 | 
			
		||||
│   │   ├── widgets/           # Кастомные виджеты
 | 
			
		||||
│   │   │   ├── __init__.py
 | 
			
		||||
│   │   │   └── chat_bubble.py
 | 
			
		||||
│   │   ├── views/             # Разметка экранов
 | 
			
		||||
│   │   │   ├── __init__.py
 | 
			
		||||
│   │   │   ├── login_view.py
 | 
			
		||||
│   │   │   └── chat_view.py
 | 
			
		||||
│   │   └── resources/         # Иконки, стили, UI-файлы
 | 
			
		||||
│   │       ├── style.qss
 | 
			
		||||
│   │       ├── icons/
 | 
			
		||||
│   │       └── ui/            # UI-файлы от Qt Designer
 | 
			
		||||
│   │           └── login.ui
 | 
			
		||||
│   │
 | 
			
		||||
│   └── controllers/           # Контроллеры (логика взаимодействия UI и модели)
 | 
			
		||||
│       ├── __init__.py
 | 
			
		||||
│       ├── login_controller.py
 | 
			
		||||
│       └── chat_controller.py
 | 
			
		||||
│
 | 
			
		||||
└── tests/                     # Тесты (юнит и интеграционные)
 | 
			
		||||
    ├── __init__.py
 | 
			
		||||
    ├── test_models.py
 | 
			
		||||
    ├── test_api_client.py
 | 
			
		||||
    └── test_chat_controller.py
 | 
			
		||||
							
								
								
									
										0
									
								
								tests/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/__init__.py
									
									
									
									
									
										Normal file
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user