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