desktop_app/app/ui/views/login_view.py
2025-09-08 19:24:27 +03:00

345 lines
14 KiB
Python

from PySide6.QtWidgets import (
QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QMessageBox,
QHBoxLayout, QSpacerItem, QSizePolicy, QComboBox
)
from PySide6.QtCore import Qt
from ..widgets.validation_input import ValidationInput
from common_lib.utils.validators import (
validate_username as common_validate_username,
validate_password as common_validate_password
)
from app.core.localizer import localizer
def validate_username(username, is_login=False):
if is_login:
if len(username) < 3 or len(username) > 32:
msg = "Неверный логин или пароль (валидатор)"
return False, msg
return True, username
return common_validate_username(username, need_back=True)
def validate_invite_code(invite_code):
# Login must be between 3 and 32 characters long
# Login must not contain whitespace characters
# Login must not start with an underscore
# Login must not contain consecutive underscores
# Login must contain only English letters, digits, and underscores
# Invite must be between 3 and 32 characters long
# Invite must not contain whitespace characters
# Invite must not start with an underscore
# Invite must not contain consecutive underscores
# Invite must contain only English letters, digits, and underscores
return common_validate_username(invite_code, field_name="invite", need_back=True)
def validate_password(password, is_login=False):
if is_login:
if len(password) < 8 or len(password) > 128:
msg = "Неверный логин или пароль (валидатор)"
return False, msg
return True, password
return common_validate_password(password, need_back=True)
def validate_name(name):
# Optional field
if not name:
return True, ""
if len(name) >= 32:
return False, "Имя не должно превышать 32 символов"
return True, ""
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.lang_combo = None
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)
self.lang_combo = QComboBox()
self.lang_combo.setFixedWidth(100)
self.lang_map = {} # lang_code: display_name
for lang in localizer.get_available_languages():
# Попробуем достать из локализации display name (если есть)
lang_name = localizer.translations.get("__name__", lang)
self.lang_map[lang_name] = lang
self.lang_combo.addItem(lang_name)
# Устанавливаем текущий язык
current_lang_name = [k for k, v in self.lang_map.items() if v == localizer.lang]
if current_lang_name:
self.lang_combo.setCurrentText(current_lang_name[0])
self.lang_combo.currentTextChanged.connect(self.change_language)
theme_layout.addSpacerItem(QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
theme_layout.addWidget(self.lang_combo)
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(localizer.translate("Авторизация"))
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(localizer.translate("Логин"))
self.login_input.setFixedHeight(40)
self.password_input = QLineEdit()
self.password_input.setPlaceholderText(localizer.translate("Пароль"))
self.password_input.setEchoMode(QLineEdit.Password)
self.password_input.setFixedHeight(40)
self.login_button = QPushButton(localizer.translate("Войти"))
self.login_button.setFixedHeight(40)
self.login_button.clicked.connect(self.handle_login)
self.register_switch = QPushButton(localizer.translate("Нет аккаунта? Регистрация"))
self.register_switch.setFlat(True)
self.register_switch.clicked.connect(self.show_register_form)
def init_register_form(self):
# self.name_input = ValidationInput("Имя")
# self.name_input.set_validator(validate_name, is_required=False)
self.reg_login_input = ValidationInput(localizer.translate("Логин"))
self.reg_login_input.set_validator(validate_username)
self.reg_password_input = ValidationInput(localizer.translate("Пароль"), is_password=True)
self.reg_password_input.set_validator(validate_password)
self.confirm_password_input = ValidationInput(localizer.translate("Повторите пароль"), is_password=True)
self.confirm_password_input.set_validator(self.validate_confirm_password)
self.invite_code_input = ValidationInput(localizer.translate("Инвайт-код"))
self.invite_code_input.set_validator(validate_invite_code, is_required=False)
self.register_button = QPushButton(localizer.translate("Зарегистрироваться"))
self.register_button.setFixedHeight(40)
self.register_button.clicked.connect(self.handle_register)
self.login_switch = QPushButton(localizer.translate("Уже есть аккаунт? Войти"))
self.login_switch.setFlat(True)
self.login_switch.clicked.connect(self.show_login_form)
self.reg_password_input.textChanged.connect(self.confirm_password_input.on_text_changed)
def show_login_form(self):
self.is_registration = False
self.title.setText(localizer.translate("Авторизация"))
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(localizer.translate("Регистрация"))
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):
self.login_input.clear()
self.password_input.clear()
# self.name_input.clear()
self.reg_login_input.clear()
self.reg_password_input.clear()
self.confirm_password_input.clear()
self.invite_code_input.clear()
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()
is_login_valid, login_msg = validate_username(login, is_login=True)
is_password_valid, password_msg = validate_password(password, is_login=True)
if not is_login_valid or not is_password_valid:
# Показываем первую попавшуюся ошибку, они должны быть общими
error_msg = login_msg if not is_login_valid else password_msg
QMessageBox.warning(self, localizer.translate("Ошибка"), error_msg)
return
if login == "root" and password == "123":
self.on_login(login)
else:
QMessageBox.warning(self, localizer.translate("Ошибка"), localizer.translate("Неверный логин или пароль"))
def validate_confirm_password(self, text):
if text != self.reg_password_input.text():
return False, localizer.translate("Пароли не совпадают")
return True, ""
def handle_register(self):
# Trigger validation for all fields
# self.name_input.on_text_changed(self.name_input.text())
self.reg_login_input.on_text_changed(self.reg_login_input.text())
self.reg_password_input.on_text_changed(self.reg_password_input.text())
self.confirm_password_input.on_text_changed(self.confirm_password_input.text())
self.invite_code_input.on_text_changed(self.invite_code_input.text())
if not all([
# self.name_input.is_valid,
self.reg_login_input.is_valid,
self.reg_password_input.is_valid,
self.confirm_password_input.is_valid,
self.invite_code_input.is_valid
]):
QMessageBox.warning(self, localizer.translate("Ошибка"), localizer.translate("Пожалуйста, исправьте ошибки в форме"))
return
# name = self.name_input.text()
login = self.reg_login_input.text()
# password = self.reg_password_input.text()
# invite = self.invite_code_input.text()
QMessageBox.information(self, "Успех", f"{localizer.translate("Регистрация прошла успешно для")} {login}")
self.show_login_form()
def change_language(self, display_name):
lang_code = self.lang_map.get(display_name)
if lang_code:
localizer.switch_language(lang_code)
self.update_ui_language()
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("🌞")
def update_ui_language(self):
self.theme_button.setText("🌞" if not self.is_dark_theme else "🌙")
if self.is_registration:
self.title.setText(localizer.translate("Регистрация"))
self.register_button.setText(localizer.translate("Зарегистрироваться"))
self.login_switch.setText(localizer.translate("Уже есть аккаунт? Войти"))
self.reg_login_input.set_label(localizer.translate("Логин"))
self.reg_password_input.set_label(localizer.translate("Пароль"))
self.confirm_password_input.set_label(localizer.translate("Повторите пароль"))
self.invite_code_input.set_label(localizer.translate("Инвайт-код"))
else:
self.title.setText(localizer.translate("Авторизация"))
self.login_button.setText(localizer.translate("Войти"))
self.register_switch.setText(localizer.translate("Нет аккаунта? Регистрация"))
self.login_input.setPlaceholderText(localizer.translate("Логин"))
self.password_input.setPlaceholderText(localizer.translate("Пароль"))