- Implement ThemeManager for dynamic light/dark theme switching in the application. - Create Wait class for cancellable delays without exceptions for smoother user experience. - Introduce WatchedProductsStore to manage and persist watched products in JSON format. - Add WindowsNotifier for system notifications to inform users of important events. - Develop ProductViewModel to encapsulate product data and manage UI interactions effectively.
356 lines
14 KiB
C#
356 lines
14 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using Microsoft.Web.WebView2.Core;
|
|
using AutoBidder.Utilities;
|
|
|
|
namespace AutoBidder
|
|
{
|
|
/// <summary>
|
|
/// Gestione WebView2: pre-caricamento e estrazione cookie
|
|
/// </summary>
|
|
public partial class MainWindow
|
|
{
|
|
private bool _isWebViewInitialized = false;
|
|
private TaskCompletionSource<bool>? _webViewInitCompletionSource;
|
|
|
|
/// <summary>
|
|
/// Inizializza WebView2 in background all'avvio per pre-caricare il browser
|
|
/// </summary>
|
|
private async void InitializeWebView2()
|
|
{
|
|
try
|
|
{
|
|
if (EmbeddedWebView == null)
|
|
{
|
|
Log("[WARN] WebView2 non disponibile", LogLevel.Warning);
|
|
_webViewInitCompletionSource?.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
Log("[BROWSER] Inizializzazione WebView2 in background...", LogLevel.Info);
|
|
|
|
// Aspetta un attimo che l'UI sia completamente caricata
|
|
await System.Threading.Tasks.Task.Delay(500);
|
|
|
|
// ? FIX: WebView2 si inizializza SOLO se visibile
|
|
// Salva tab corrente e switcha temporaneamente a Browser
|
|
var wasVisible = Browser.Visibility == Visibility.Visible;
|
|
var currentTab = TabAsteAttive.IsChecked == true ? "AsteAttive" :
|
|
TabCerca.IsChecked == true ? "Cerca" :
|
|
TabProdotti.IsChecked == true ? "Prodotti" :
|
|
TabBrowser.IsChecked == true ? "Browser" :
|
|
TabPuntateGratis.IsChecked == true ? "PuntateGratis" :
|
|
TabDatiStatistici.IsChecked == true ? "DatiStatistici" :
|
|
TabImpostazioni.IsChecked == true ? "Impostazioni" : "AsteAttive";
|
|
|
|
if (!wasVisible)
|
|
{
|
|
await Dispatcher.InvokeAsync(() =>
|
|
{
|
|
Browser.Visibility = Visibility.Visible;
|
|
});
|
|
await Task.Delay(100);
|
|
}
|
|
|
|
// Specifica UserDataFolder esplicito
|
|
var userDataFolder = System.IO.Path.Combine(
|
|
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
|
"AutoBidder",
|
|
"WebView2"
|
|
);
|
|
|
|
// Crea directory se non esiste
|
|
System.IO.Directory.CreateDirectory(userDataFolder);
|
|
|
|
// Crea environment con UserDataFolder esplicito
|
|
var env = await Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(
|
|
browserExecutableFolder: null,
|
|
userDataFolder: userDataFolder
|
|
);
|
|
|
|
// Inizializza WebView con environment
|
|
await EmbeddedWebView.EnsureCoreWebView2Async(env);
|
|
|
|
// Ripristina tab originale se necessario
|
|
if (!wasVisible)
|
|
{
|
|
await Dispatcher.InvokeAsync(() =>
|
|
{
|
|
Browser.Visibility = Visibility.Collapsed;
|
|
|
|
// Ripristina tab originale
|
|
switch (currentTab)
|
|
{
|
|
case "AsteAttive":
|
|
TabAsteAttive.IsChecked = true;
|
|
AuctionMonitor.Visibility = Visibility.Visible;
|
|
break;
|
|
case "Cerca":
|
|
// "Cerca" mostra lo stesso controllo Browser, in modalità catalogo.
|
|
TabCerca.IsChecked = true;
|
|
Browser.Visibility = Visibility.Visible;
|
|
break;
|
|
case "Prodotti":
|
|
TabProdotti.IsChecked = true;
|
|
Products.Visibility = Visibility.Visible;
|
|
break;
|
|
case "PuntateGratis":
|
|
TabPuntateGratis.IsChecked = true;
|
|
FreeBids.Visibility = Visibility.Visible;
|
|
break;
|
|
case "DatiStatistici":
|
|
TabDatiStatistici.IsChecked = true;
|
|
StatisticsPanel.Visibility = Visibility.Visible;
|
|
break;
|
|
case "Impostazioni":
|
|
TabImpostazioni.IsChecked = true;
|
|
Settings.Visibility = Visibility.Visible;
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (EmbeddedWebView.CoreWebView2 != null)
|
|
{
|
|
_isWebViewInitialized = true;
|
|
|
|
// Pre-carica la pagina di Bidoo in background
|
|
EmbeddedWebView.CoreWebView2.Navigate("https://it.bidoo.com");
|
|
|
|
Log("[BROWSER] WebView2 inizializzato e pre-caricato", LogLevel.Success);
|
|
|
|
// Registra evento per rilevare login automatico
|
|
EmbeddedWebView.CoreWebView2.NavigationCompleted += OnWebViewNavigationCompleted;
|
|
|
|
// Notifica che WebView � pronta
|
|
_webViewInitCompletionSource?.TrySetResult(true);
|
|
|
|
// Verifica immediata se c'� gi� un cookie
|
|
await CheckAndImportCookieIfAvailable();
|
|
}
|
|
else
|
|
{
|
|
Log("[ERROR] CoreWebView2 � null dopo init", LogLevel.Error);
|
|
_webViewInitCompletionSource?.TrySetResult(false);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log($"[ERROR] Inizializzazione WebView2 fallita: {ex.Message}", LogLevel.Error);
|
|
_webViewInitCompletionSource?.TrySetResult(false);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica e importa cookie se disponibile
|
|
/// </summary>
|
|
private async Task CheckAndImportCookieIfAvailable()
|
|
{
|
|
try
|
|
{
|
|
// Aspetta che la pagina sia completamente caricata
|
|
await Task.Delay(1000);
|
|
|
|
var cookie = await GetCookieFromWebView();
|
|
|
|
if (!string.IsNullOrEmpty(cookie))
|
|
{
|
|
var currentSession = _sessionService?.GetCurrentSession();
|
|
|
|
// Importa solo se diverso da quello salvato
|
|
if (currentSession == null ||
|
|
string.IsNullOrEmpty(currentSession.CookieString) ||
|
|
!currentSession.CookieString.Contains(cookie))
|
|
{
|
|
Log("[BROWSER] Cookie rilevato nel browser - importazione automatica...", LogLevel.Info);
|
|
await AutoImportCookieFromWebView(cookie);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log($"[WARN] Verifica cookie fallita: {ex.Message}", LogLevel.Warning);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aspetta che WebView sia inizializzata (con timeout)
|
|
/// </summary>
|
|
private async Task<bool> WaitForWebViewInitAsync(int timeoutSeconds = 60)
|
|
{
|
|
if (_isWebViewInitialized)
|
|
return true;
|
|
|
|
_webViewInitCompletionSource = new TaskCompletionSource<bool>();
|
|
|
|
// Timeout
|
|
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(timeoutSeconds));
|
|
var completedTask = await Task.WhenAny(_webViewInitCompletionSource.Task, timeoutTask);
|
|
|
|
if (completedTask == timeoutTask)
|
|
{
|
|
Log("[WARN] Timeout attesa inizializzazione WebView2", LogLevel.Warning);
|
|
return false;
|
|
}
|
|
|
|
return await _webViewInitCompletionSource.Task;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Evento chiamato quando la navigazione nella WebView � completata
|
|
/// Rileva automaticamente se l'utente ha effettuato il login
|
|
/// </summary>
|
|
private async void OnWebViewNavigationCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (!e.IsSuccess || EmbeddedWebView?.CoreWebView2 == null)
|
|
return;
|
|
|
|
var url = EmbeddedWebView.CoreWebView2.Source;
|
|
|
|
// Se l'utente � sulla homepage di Bidoo (dopo login), verifica cookie
|
|
if (url.Contains("bidoo.com") && !url.Contains("login"))
|
|
{
|
|
// ? REFACTORED: Delega a CheckAndImportCookieIfAvailable
|
|
await CheckAndImportCookieIfAvailable();
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Importa automaticamente il cookie dalla WebView senza conferma utente
|
|
/// </summary>
|
|
private async Task<bool> AutoImportCookieFromWebView(string cookieString)
|
|
{
|
|
try
|
|
{
|
|
// Valida e attiva il cookie usando SessionService
|
|
var result = await _sessionService.ValidateAndActivateSessionAsync(cookieString);
|
|
|
|
if (result.Success && result.Session != null)
|
|
{
|
|
// Salva automaticamente la sessione
|
|
_sessionService.SaveSession(result.Session);
|
|
|
|
// Aggiorna il banner
|
|
Dispatcher.Invoke(() =>
|
|
{
|
|
SetUserBanner(result.Session.Username, result.Session.RemainingBids);
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Estrae il cookie __stattrb dalla WebView2
|
|
/// </summary>
|
|
/// <returns>Cookie completo o null se non trovato</returns>
|
|
private async Task<string?> GetCookieFromWebView()
|
|
{
|
|
try
|
|
{
|
|
if (EmbeddedWebView?.CoreWebView2 == null)
|
|
return null;
|
|
|
|
// Ottieni tutti i cookie di bidoo.com
|
|
var cookies = await EmbeddedWebView.CoreWebView2.CookieManager.GetCookiesAsync("https://it.bidoo.com");
|
|
|
|
if (cookies == null || cookies.Count == 0)
|
|
return null;
|
|
|
|
// Cerca il cookie __stattrb (cookie di sessione principale)
|
|
var stattrb = cookies.FirstOrDefault(c => c.Name == "__stattrb");
|
|
|
|
if (stattrb == null)
|
|
return null;
|
|
|
|
// Costruisci la stringa cookie completa con tutti i cookie necessari
|
|
var cookieStrings = cookies
|
|
.Where(c => !string.IsNullOrEmpty(c.Value))
|
|
.Select(c => $"{c.Name}={c.Value}")
|
|
.ToList();
|
|
|
|
return string.Join("; ", cookieStrings);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log($"[WARN] Impossibile estrarre cookie da WebView: {ex.Message}", LogLevel.Warning);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Importa il cookie dalla WebView e lo salva per l'uso nelle API
|
|
/// </summary>
|
|
public async Task<bool> ImportCookieFromWebView()
|
|
{
|
|
try
|
|
{
|
|
if (!_isWebViewInitialized || EmbeddedWebView?.CoreWebView2 == null)
|
|
{
|
|
Log("[WARN] Browser non inizializzato - attendi qualche secondo e riprova", LogLevel.Warning);
|
|
return false;
|
|
}
|
|
|
|
Log("[BROWSER] Estrazione cookie dal browser...", LogLevel.Info);
|
|
|
|
var cookieString = await GetCookieFromWebView();
|
|
|
|
if (string.IsNullOrEmpty(cookieString))
|
|
{
|
|
Log("[WARN] Nessun cookie trovato nel browser - assicurati di aver effettuato il login su bidoo.com", LogLevel.Warning);
|
|
return false;
|
|
}
|
|
|
|
// ? NOTA: Non aggiorna pi� TextBox (rimossa) - direttamente alla validazione
|
|
|
|
// Valida e attiva il cookie usando SessionService
|
|
var result = await _sessionService.ValidateAndActivateSessionAsync(cookieString);
|
|
|
|
if (result.Success && result.Session != null)
|
|
{
|
|
// Salva automaticamente la sessione
|
|
_sessionService.SaveSession(result.Session);
|
|
|
|
// Aggiorna il banner
|
|
SetUserBanner(result.Session.Username, result.Session.RemainingBids);
|
|
|
|
Log($"[OK] Cookie importato e validato - Utente: {result.Session.Username}, Puntate: {result.Session.RemainingBids}", LogLevel.Success);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
Log($"[ERRORE] Cookie importato ma non valido: {result.ErrorMessage}", LogLevel.Error);
|
|
return false;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log($"[ERRORE] Importazione cookie: {ex.Message}", LogLevel.Error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica se WebView2 � pronta per l'uso
|
|
/// </summary>
|
|
public bool IsWebViewReady()
|
|
{
|
|
return _isWebViewInitialized && EmbeddedWebView?.CoreWebView2 != null;
|
|
}
|
|
}
|
|
}
|