Refactoring e nuove funzionalità per AutoBidder v4.0

* Aggiornamento alla versione 4.0.0
* Refactoring architetturale: introdotte partial classes e UserControls modulari per migliorare manutenibilità e leggibilità.
* Aggiunti nuovi UserControls: `AuctionMonitorControl`, `BrowserControl`, `SettingsControl`, `StatisticsControl`.
* Introdotto supporto per WebView2 per il browser integrato.
* Migliorata gestione delle aste: aggiunta/rimozione tramite URL o ID, configurazione predefinita.
* Nuove funzionalità di esportazione: supporto CSV, JSON, XML con opzioni configurabili.
* Logging avanzato: codifica colore per severità e auto-scroll.
* Tema scuro moderno e miglioramenti UI/UX: sidebar di navigazione, griglie virtualizzate, icone emoji.
* Persistenza dati: salvataggio automatico di aste e impostazioni in file JSON.
* Documentazione aggiornata: `README.md`, `CHANGELOG.md` e nuovi file di supporto.
* Miglioramenti alla sicurezza: cookie di sessione salvati in modo sicuro con DPAPI.
* Preparazione per future estensioni: placeholder per funzionalità avanzate e struttura modulare.
This commit is contained in:
Alberto Balbo
2025-11-17 16:01:22 +01:00
parent 8717a3b6ef
commit 6036896f7d
35 changed files with 7088 additions and 2716 deletions
@@ -0,0 +1,208 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using AutoBidder.Models;
using AutoBidder.ViewModels;
namespace AutoBidder
{
/// <summary>
/// Auction management: Add, Remove, Update
/// </summary>
public partial class MainWindow
{
private async Task AddAuctionById(string input)
{
try
{
if (string.IsNullOrWhiteSpace(input))
{
MessageBox.Show("Input non valido!", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
string auctionId;
string? productName;
string originalUrl;
// Verifica se è un URL o solo un ID
if (input.Contains("bidoo.com") || input.Contains("http"))
{
// È un URL - estrai ID e nome prodotto
originalUrl = input.Trim();
auctionId = ExtractAuctionId(originalUrl);
if (string.IsNullOrEmpty(auctionId))
{
MessageBox.Show("Impossibile estrarre ID dall'URL!", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
productName = ExtractProductName(originalUrl) ?? string.Empty;
}
else
{
// È solo un ID numerico - costruisci URL generico
auctionId = input.Trim();
productName = string.Empty;
originalUrl = $"https://it.bidoo.com/auction.php?a=asta_{auctionId}";
}
// Verifica duplicati
if (_auctionViewModels.Any(a => a.AuctionId == auctionId))
{
MessageBox.Show("Asta già monitorata!", "Duplicato", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
// Crea nome visualizzazione
var displayName = string.IsNullOrEmpty(productName)
? $"Asta {auctionId}"
: $"{System.Net.WebUtility.HtmlDecode(productName)} ({auctionId})";
// Crea model
var auction = new AuctionInfo
{
AuctionId = auctionId,
Name = System.Net.WebUtility.HtmlDecode(displayName),
OriginalUrl = originalUrl,
TimerClick = 0,
DelayMs = 50,
IsActive = true
};
// Aggiungi al monitor
_auctionMonitor.AddAuction(auction);
// Crea ViewModel
var vm = new AuctionViewModel(auction);
_auctionViewModels.Add(vm);
SaveAuctions();
UpdateTotalCount();
}
catch (Exception ex)
{
Log($"Errore aggiunta asta: {ex.Message}");
MessageBox.Show($"Errore: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private async Task AddAuctionFromUrl(string url)
{
try
{
if (!IsValidAuctionUrl(url))
{
MessageBox.Show("URL asta non valido!", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
var auctionId = ExtractAuctionId(url);
if (string.IsNullOrEmpty(auctionId))
{
MessageBox.Show("Impossibile estrarre ID asta!", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
// Verifica duplicati
if (_auctionViewModels.Any(a => a.AuctionId == auctionId))
{
MessageBox.Show("Asta già monitorata!", "Duplicato", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
// Fetch nome (opzionale)
var name = $"Asta {auctionId}";
try
{
using var httpClient = new System.Net.Http.HttpClient();
var html = await httpClient.GetStringAsync(url);
var match = System.Text.RegularExpressions.Regex.Match(html, @"<title>([^<]+)</title>");
if (match.Success)
{
name = System.Net.WebUtility.HtmlDecode(match.Groups[1].Value.Trim().Replace(" - Bidoo", ""));
}
}
catch { }
// Crea model
var auction = new AuctionInfo
{
AuctionId = auctionId,
Name = System.Net.WebUtility.HtmlDecode(name),
TimerClick = 0,
DelayMs = 50,
IsActive = true
};
// Aggiungi al monitor
_auctionMonitor.AddAuction(auction);
// Crea ViewModel
var vm = new AuctionViewModel(auction);
_auctionViewModels.Add(vm);
SaveAuctions();
UpdateTotalCount();
}
catch (Exception ex)
{
Log($"[ERRORE] Errore aggiunta asta: {ex.Message}");
MessageBox.Show($"Errore: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void SaveAuctions()
{
try
{
var auctions = _auctionMonitor.GetAuctions();
Utilities.PersistenceManager.SaveAuctions(auctions);
}
catch (Exception ex)
{
Log($"[ERRORE] Errore salvataggio: {ex.Message}");
}
}
private void LoadSavedAuctions()
{
try
{
var auctions = Utilities.PersistenceManager.LoadAuctions();
foreach (var auction in auctions)
{
// Protezione: rimuovi eventuali BidHistory null
auction.BidHistory = auction.BidHistory?.Where(b => b != null).ToList() ?? new System.Collections.Generic.List<BidHistory>();
// Decode HTML entities
try { auction.Name = System.Net.WebUtility.HtmlDecode(auction.Name ?? string.Empty); } catch { }
_auctionMonitor.AddAuction(auction);
var vm = new AuctionViewModel(auction);
_auctionViewModels.Add(vm);
}
// On startup treat persisted auctions as stopped
foreach (var vm in _auctionViewModels)
{
vm.IsActive = false;
vm.IsPaused = false;
}
UpdateTotalCount();
if (auctions.Count > 0)
{
Log($"[OK] Caricate {auctions.Count} aste salvate");
}
LoadSavedSession();
}
catch (Exception ex)
{
Log($"[ERRORE] Errore caricamento aste: {ex.Message}");
}
}
}
}