Initial commit
Dieser Commit ist enthalten in:
295
views/widgets/login_process_modal.py
Normale Datei
295
views/widgets/login_process_modal.py
Normale Datei
@ -0,0 +1,295 @@
|
||||
"""
|
||||
Login Process Modal - Spezialisiertes Modal für Login-Prozesse
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Optional, Dict, Any
|
||||
from PyQt5.QtCore import QTimer, pyqtSignal
|
||||
from PyQt5.QtWidgets import QHBoxLayout, QLabel
|
||||
from PyQt5.QtGui import QFont, QPixmap
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
from views.widgets.progress_modal import ProgressModal
|
||||
|
||||
logger = logging.getLogger("login_process_modal")
|
||||
|
||||
|
||||
class LoginProcessModal(ProgressModal):
|
||||
"""
|
||||
Spezialisiertes Modal für Login-Prozesse mit Session-Wiederherstellung.
|
||||
"""
|
||||
|
||||
# Signale
|
||||
login_completed = pyqtSignal(bool, str) # success, message
|
||||
session_restored = pyqtSignal(str) # platform
|
||||
|
||||
def __init__(self, parent=None, platform: str = "Social Media", language_manager=None):
|
||||
self.platform = platform
|
||||
self.login_method = "session" # "session" oder "credentials"
|
||||
self.account_username = ""
|
||||
|
||||
super().__init__(parent, "login_process", language_manager)
|
||||
|
||||
# Erweitere UI für Login-spezifische Anzeige
|
||||
self.setup_login_ui()
|
||||
|
||||
def setup_login_ui(self):
|
||||
"""Erweitert die UI um Login-spezifische Elemente"""
|
||||
container_layout = self.modal_container.layout()
|
||||
|
||||
# Platform/Account Info (zwischen Titel und Animation)
|
||||
self.account_info_widget = QLabel()
|
||||
self.account_info_widget.setVisible(False)
|
||||
self.account_info_widget.setAlignment(Qt.AlignCenter)
|
||||
|
||||
info_font = QFont("Inter", 13)
|
||||
info_font.setBold(True)
|
||||
self.account_info_widget.setFont(info_font)
|
||||
|
||||
self.account_info_widget.setStyleSheet("""
|
||||
QLabel {
|
||||
color: #2D3748;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
background: rgba(66, 153, 225, 0.1);
|
||||
border-radius: 8px;
|
||||
padding: 8px 16px;
|
||||
margin: 4px 0px;
|
||||
}
|
||||
""")
|
||||
|
||||
# Füge nach Titel ein (Index 1)
|
||||
container_layout.insertWidget(1, self.account_info_widget)
|
||||
|
||||
# Login-Methode Indicator (nach Animation Widget)
|
||||
self.method_label = QLabel()
|
||||
self.method_label.setVisible(False)
|
||||
self.method_label.setAlignment(Qt.AlignCenter)
|
||||
|
||||
method_font = QFont("Inter", 11)
|
||||
self.method_label.setFont(method_font)
|
||||
|
||||
self.method_label.setStyleSheet("""
|
||||
QLabel {
|
||||
color: #4A5568;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
font-style: italic;
|
||||
margin: 4px 0px;
|
||||
}
|
||||
""")
|
||||
|
||||
# Füge nach Animation Widget ein (Index 3, wegen account_info_widget)
|
||||
container_layout.insertWidget(3, self.method_label)
|
||||
|
||||
def show_session_login(self, account_username: str, platform: str = None):
|
||||
"""
|
||||
Zeigt Session-basiertes Login an.
|
||||
|
||||
Args:
|
||||
account_username: Benutzername des Accounts
|
||||
platform: Optional - Platform überschreibung
|
||||
"""
|
||||
if platform:
|
||||
self.platform = platform
|
||||
|
||||
self.account_username = account_username
|
||||
self.login_method = "session"
|
||||
|
||||
# UI aktualisieren
|
||||
self._update_login_display()
|
||||
|
||||
# Modal anzeigen
|
||||
self.show_process("login_process")
|
||||
|
||||
logger.info(f"Session Login Modal angezeigt für: {account_username} @ {self.platform}")
|
||||
|
||||
def show_credentials_login(self, account_username: str, platform: str = None):
|
||||
"""
|
||||
Zeigt Credential-basiertes Login an.
|
||||
|
||||
Args:
|
||||
account_username: Benutzername des Accounts
|
||||
platform: Optional - Platform überschreibung
|
||||
"""
|
||||
if platform:
|
||||
self.platform = platform
|
||||
|
||||
self.account_username = account_username
|
||||
self.login_method = "credentials"
|
||||
|
||||
# UI aktualisieren
|
||||
self._update_login_display()
|
||||
|
||||
# Modal anzeigen
|
||||
self.show_process("login_process")
|
||||
|
||||
logger.info(f"Credentials Login Modal angezeigt für: {account_username} @ {self.platform}")
|
||||
|
||||
def _update_login_display(self):
|
||||
"""Aktualisiert die Anzeige basierend auf Login-Methode"""
|
||||
# Titel anpassen
|
||||
title = f"🔐 {self.platform} Login"
|
||||
self.title_label.setText(title)
|
||||
|
||||
# Account Info anzeigen
|
||||
if self.account_username:
|
||||
account_info = f"👤 {self.account_username}"
|
||||
self.account_info_widget.setText(account_info)
|
||||
self.account_info_widget.setVisible(True)
|
||||
|
||||
# Methode anzeigen
|
||||
if self.login_method == "session":
|
||||
method_text = "🔄 Session wird wiederhergestellt"
|
||||
status_text = "Gespeicherte Anmeldedaten werden geladen..."
|
||||
else:
|
||||
method_text = "🔑 Anmeldedaten werden eingegeben"
|
||||
status_text = "Benutzername und Passwort werden verwendet..."
|
||||
|
||||
self.method_label.setText(method_text)
|
||||
self.method_label.setVisible(True)
|
||||
|
||||
# Status setzen
|
||||
self.update_status(status_text)
|
||||
|
||||
def update_login_progress(self, step: str, detail: str = None):
|
||||
"""
|
||||
Aktualisiert den Login-Fortschritt.
|
||||
|
||||
Args:
|
||||
step: Aktueller Schritt
|
||||
detail: Optional - Detail-Information
|
||||
"""
|
||||
step_emojis = {
|
||||
'browser_init': '🌐',
|
||||
'page_load': '📄',
|
||||
'session_restore': '🔄',
|
||||
'credential_input': '✍️',
|
||||
'verification': '🔐',
|
||||
'success_check': '✅',
|
||||
'finalizing': '🏁'
|
||||
}
|
||||
|
||||
emoji = step_emojis.get(step, '⏳')
|
||||
status_text = f"{emoji} {step.replace('_', ' ').title()}"
|
||||
|
||||
self.update_status(status_text, detail)
|
||||
|
||||
logger.debug(f"Login Progress: {step} - {detail or 'No detail'}")
|
||||
|
||||
def show_session_restored(self, platform_data: Dict[str, Any] = None):
|
||||
"""
|
||||
Zeigt erfolgreiche Session-Wiederherstellung an.
|
||||
|
||||
Args:
|
||||
platform_data: Optional - Platform-spezifische Daten
|
||||
"""
|
||||
self.update_status("✅ Session erfolgreich wiederhergestellt", "Anmeldung abgeschlossen")
|
||||
|
||||
# Session restored Signal
|
||||
self.session_restored.emit(self.platform)
|
||||
|
||||
# Auto-Close nach 2 Sekunden
|
||||
QTimer.singleShot(2000, lambda: self._complete_login(True, "Session wiederhergestellt"))
|
||||
|
||||
logger.info(f"Session erfolgreich wiederhergestellt für: {self.account_username} @ {self.platform}")
|
||||
|
||||
def show_credentials_success(self):
|
||||
"""Zeigt erfolgreiche Credential-Anmeldung an"""
|
||||
self.update_status("✅ Anmeldung erfolgreich", "Account ist bereit")
|
||||
|
||||
# Auto-Close nach 2 Sekunden
|
||||
QTimer.singleShot(2000, lambda: self._complete_login(True, "Anmeldung erfolgreich"))
|
||||
|
||||
logger.info(f"Credential-Login erfolgreich für: {self.account_username} @ {self.platform}")
|
||||
|
||||
def show_login_failed(self, reason: str, retry_available: bool = False):
|
||||
"""
|
||||
Zeigt fehlgeschlagene Anmeldung an.
|
||||
|
||||
Args:
|
||||
reason: Grund für Fehlschlag
|
||||
retry_available: Ob Retry möglich ist
|
||||
"""
|
||||
# Animation stoppen
|
||||
self.animation_widget.stop_animation()
|
||||
|
||||
error_title = "❌ Anmeldung fehlgeschlagen"
|
||||
|
||||
if self.login_method == "session":
|
||||
error_detail = "Session ist abgelaufen oder ungültig"
|
||||
else:
|
||||
error_detail = "Benutzername oder Passwort falsch"
|
||||
|
||||
self.title_label.setText(error_title)
|
||||
self.update_status(reason, error_detail)
|
||||
|
||||
# Auto-Close nach 4 Sekunden
|
||||
auto_close_time = 4000
|
||||
QTimer.singleShot(auto_close_time, lambda: self._complete_login(False, reason))
|
||||
|
||||
logger.error(f"Login fehlgeschlagen für: {self.account_username} @ {self.platform} - {reason}")
|
||||
|
||||
def show_session_expired(self):
|
||||
"""Zeigt abgelaufene Session an"""
|
||||
self.show_login_failed("Session ist abgelaufen", retry_available=True)
|
||||
|
||||
# Spezielle Behandlung für Session-Ablauf
|
||||
self.method_label.setText("⚠️ Manuelle Anmeldung erforderlich")
|
||||
|
||||
def show_captcha_required(self):
|
||||
"""Zeigt an, dass Captcha erforderlich ist"""
|
||||
self.update_status("🤖 Captcha-Verifizierung erforderlich", "Bitte manuell lösen...")
|
||||
|
||||
# Längere Auto-Close Zeit für Captcha
|
||||
QTimer.singleShot(10000, lambda: self._complete_login(False, "Captcha erforderlich"))
|
||||
|
||||
def show_two_factor_required(self):
|
||||
"""Zeigt an, dass Zwei-Faktor-Authentifizierung erforderlich ist"""
|
||||
self.update_status("📱 Zwei-Faktor-Authentifizierung", "Code wird benötigt...")
|
||||
|
||||
# Längere Auto-Close Zeit für 2FA
|
||||
QTimer.singleShot(8000, lambda: self._complete_login(False, "2FA erforderlich"))
|
||||
|
||||
def _complete_login(self, success: bool, message: str):
|
||||
"""
|
||||
Schließt den Login-Prozess ab.
|
||||
|
||||
Args:
|
||||
success: Ob Login erfolgreich war
|
||||
message: Abschließende Nachricht
|
||||
"""
|
||||
# Signal senden
|
||||
self.login_completed.emit(success, message)
|
||||
|
||||
# Modal verstecken
|
||||
self.hide_process()
|
||||
|
||||
logger.info(f"Login-Prozess abgeschlossen: {success} - {message}")
|
||||
|
||||
def get_platform_icon_path(self) -> Optional[str]:
|
||||
"""
|
||||
Gibt den Pfad zum Platform-Icon zurück.
|
||||
|
||||
Returns:
|
||||
Optional[str]: Icon-Pfad oder None
|
||||
"""
|
||||
try:
|
||||
import os
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
parent_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))
|
||||
icons_dir = os.path.join(parent_dir, "resources", "icons")
|
||||
|
||||
platform_name = self.platform.lower().replace('.', '').replace(' ', '')
|
||||
if platform_name == "x":
|
||||
platform_name = "twitter"
|
||||
elif platform_name == "okru":
|
||||
platform_name = "ok"
|
||||
|
||||
icon_path = os.path.join(icons_dir, f"{platform_name}.svg")
|
||||
|
||||
if os.path.exists(icon_path):
|
||||
return icon_path
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Konnte Platform-Icon nicht laden: {e}")
|
||||
|
||||
return None
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren