- 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.
402 lines
15 KiB
C#
402 lines
15 KiB
C#
using System.Windows;
|
|
|
|
namespace AutoBidder
|
|
{
|
|
/// <summary>
|
|
/// Event handlers for UserControl events and tab navigation
|
|
/// </summary>
|
|
public partial class MainWindow
|
|
{
|
|
// ===== TAB NAVIGATION =====
|
|
|
|
private void TabAsteAttive_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
ShowPanel(AuctionMonitor);
|
|
}
|
|
|
|
private void TabBrowser_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
ShowPanel(Browser);
|
|
Browser.ShowBrowser();
|
|
}
|
|
|
|
private async void TabCerca_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
ShowPanel(Browser);
|
|
Browser.ShowCatalog();
|
|
await EnsureCatalogLoadedAsync();
|
|
}
|
|
|
|
private void TabProdotti_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
ShowPanel(Products);
|
|
LoadProducts();
|
|
}
|
|
|
|
private void TabPuntateGratis_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
ShowPanel(FreeBids);
|
|
RefreshFreeBidsPanel();
|
|
}
|
|
|
|
private void TabEsporta_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
ShowPanel(Export);
|
|
|
|
// Il conteggio si rifà all'apertura: nel frattempo possono essersi concluse
|
|
// altre aste, e un numero vecchio farebbe scegliere i filtri al buio.
|
|
Export.RefreshPreview();
|
|
}
|
|
|
|
private void TabDatiStatistici_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
ShowPanel(StatisticsPanel);
|
|
LoadStatistics();
|
|
}
|
|
|
|
private void TabImpostazioni_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
// Mostra il pannello Impostazioni
|
|
ShowPanel(Settings);
|
|
|
|
// Carica impostazioni quando si apre la tab
|
|
LoadDefaultSettings();
|
|
|
|
// Aggiorna il riquadro di stato della sezione Sessione
|
|
RefreshSettingsSessionStatus();
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void ShowPanel(System.Windows.UIElement? panelToShow)
|
|
{
|
|
// Prevent NullReferenceException during initialization
|
|
if (AuctionMonitor == null || Browser == null || StatisticsPanel == null ||
|
|
Settings == null || FreeBids == null || Products == null || Export == null)
|
|
return;
|
|
|
|
// Hide all panels
|
|
AuctionMonitor.Visibility = Visibility.Collapsed;
|
|
Browser.Visibility = Visibility.Collapsed;
|
|
Products.Visibility = Visibility.Collapsed;
|
|
FreeBids.Visibility = Visibility.Collapsed;
|
|
StatisticsPanel.Visibility = Visibility.Collapsed;
|
|
Export.Visibility = Visibility.Collapsed;
|
|
Settings.Visibility = Visibility.Collapsed;
|
|
|
|
// Show selected panel
|
|
if (panelToShow != null)
|
|
panelToShow.Visibility = Visibility.Visible;
|
|
}
|
|
|
|
// ===== AUCTION MONITOR CONTROL EVENTS =====
|
|
|
|
private void AuctionMonitor_StartClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
StartButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_PauseAllClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
PauseAllButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_StopClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
StopButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_ExportClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
// Chiama il metodo di export esistente
|
|
try
|
|
{
|
|
// Esporta tutte le aste monitorate
|
|
var auctions = _auctionMonitor.GetAuctions();
|
|
if (auctions.Count == 0)
|
|
{
|
|
System.Windows.MessageBox.Show("Nessuna asta da esportare", "Export", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
|
|
return;
|
|
}
|
|
|
|
// TODO: Implementare dialog export con scelta formato
|
|
System.Windows.MessageBox.Show($"Export di {auctions.Count} aste.\n\nFunzionalit� in sviluppo.\nUsa le impostazioni nella scheda Impostazioni per configurare l'export.", "Export Aste", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
|
|
Log($"[INFO] Richiesto export di {auctions.Count} aste (funzionalit� in sviluppo)", Utilities.LogLevel.Info);
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Log($"[ERRORE] Export: {ex.Message}", Utilities.LogLevel.Error);
|
|
}
|
|
}
|
|
|
|
private void AuctionMonitor_AddUrlClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
AddUrlButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_RemoveUrlClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
RemoveUrlButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_RemoveAllClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
RemoveAllButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_MoveUpClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
MoveUpButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_MoveDownClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
MoveDownButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_AuctionSelectionChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
if (AuctionMonitor.MultiAuctionsGrid.SelectedItem is ViewModels.AuctionViewModel selected)
|
|
{
|
|
_selectedAuction = selected;
|
|
UpdateSelectedAuctionDetails(selected);
|
|
|
|
// ? NUOVO: Rileva nome generico O info prodotto mancanti e recupera automaticamente
|
|
var auction = selected.AuctionInfo;
|
|
bool hasGenericName = auction.Name.StartsWith("Asta ") &&
|
|
!auction.Name.Contains("Shop") &&
|
|
!auction.Name.Contains("�") &&
|
|
!auction.Name.Contains("Buono") &&
|
|
!auction.Name.Contains("Carburante");
|
|
|
|
bool needsProductInfo = !auction.BuyNowPrice.HasValue && !auction.ShippingCost.HasValue;
|
|
|
|
// Se ha nome generico O mancano info prodotto ? recupera in background
|
|
if (hasGenericName || needsProductInfo)
|
|
{
|
|
Log($"[AUTO-FETCH] Recupero automatico per: {auction.Name} (nome generico={hasGenericName}, info mancanti={needsProductInfo})", Utilities.LogLevel.Info);
|
|
|
|
// Avvia fetch in background senza bloccare UI
|
|
_ = LoadProductInfoInBackgroundAsync(auction);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void AuctionMonitor_CopyUrlClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
CopyAuctionUrlButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_OpenAuctionInternalClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
OpenAuctionInternalButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_OpenAuctionExternalClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
OpenAuctionExternalButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_ExportAuctionClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
ExportAuctionButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_ResetSettingsClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
ResetSettingsButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_ClearBiddersClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
ClearBiddersButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_ClearLogClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
ClearLogButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_ClearGlobalLogClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
ClearLogButton_Click(sender, e); // Clear Log invece di ClearGlobalLog
|
|
}
|
|
|
|
// ===== AUCTION SETTINGS EVENTS =====
|
|
|
|
private void AuctionMonitor_RefreshProductInfoClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
RefreshProductInfoButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_ConnectionStatusClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
ConnectionStatusButton_Click(sender, e);
|
|
}
|
|
|
|
private void AuctionMonitor_BidBeforeDeadlineMsChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
// Riempire i campi alla selezione di un'asta scatena i TextChanged:
|
|
// senza questa guardia ogni selezione riscriveva auctions.json quattro volte
|
|
// con gli stessi valori appena letti.
|
|
if (_isUpdatingSelection) return;
|
|
|
|
if (_selectedAuction != null && int.TryParse(AuctionMonitor.SelectedBidBeforeDeadlineMs.Text, out int ms))
|
|
{
|
|
_selectedAuction.AuctionInfo.BidBeforeDeadlineMs = ms;
|
|
SaveAuctions();
|
|
}
|
|
}
|
|
|
|
private void AuctionMonitor_MinPriceChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
// Riempire i campi alla selezione di un'asta scatena i TextChanged:
|
|
// senza questa guardia ogni selezione riscriveva auctions.json quattro volte
|
|
// con gli stessi valori appena letti.
|
|
if (_isUpdatingSelection) return;
|
|
|
|
if (_selectedAuction != null && double.TryParse(AuctionMonitor.SelectedMinPrice.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out double price))
|
|
{
|
|
_selectedAuction.MinPrice = price;
|
|
SaveAuctions();
|
|
}
|
|
}
|
|
|
|
private void AuctionMonitor_MaxPriceChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
// Riempire i campi alla selezione di un'asta scatena i TextChanged:
|
|
// senza questa guardia ogni selezione riscriveva auctions.json quattro volte
|
|
// con gli stessi valori appena letti.
|
|
if (_isUpdatingSelection) return;
|
|
|
|
if (_selectedAuction != null && double.TryParse(AuctionMonitor.SelectedMaxPrice.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out double price))
|
|
{
|
|
_selectedAuction.MaxPrice = price;
|
|
SaveAuctions();
|
|
}
|
|
}
|
|
|
|
private void AuctionMonitor_MaxClicksChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
// Riempire i campi alla selezione di un'asta scatena i TextChanged:
|
|
// senza questa guardia ogni selezione riscriveva auctions.json quattro volte
|
|
// con gli stessi valori appena letti.
|
|
if (_isUpdatingSelection) return;
|
|
|
|
if (_selectedAuction != null && int.TryParse(AuctionMonitor.SelectedMaxClicks.Text, out int clicks))
|
|
{
|
|
_selectedAuction.MaxClicks = clicks;
|
|
SaveAuctions();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tetto di spesa in euro per l'asta selezionata. E' il fratello di MaxClicks detto
|
|
/// in denaro: chi ragiona in euro non deve fare la divisione a mente.
|
|
/// </summary>
|
|
private void AuctionMonitor_MaxSpendChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
if (_isUpdatingSelection) return;
|
|
|
|
if (_selectedAuction == null) return;
|
|
|
|
var testo = AuctionMonitor.SelectedMaxSpend.Text.Trim().Replace(',', '.');
|
|
if (double.TryParse(testo, System.Globalization.NumberStyles.Any,
|
|
System.Globalization.CultureInfo.InvariantCulture, out var spesa) && spesa >= 0)
|
|
{
|
|
_selectedAuction.AuctionInfo.MaxTotalSpendEuro = spesa;
|
|
SaveAuctions();
|
|
}
|
|
}
|
|
|
|
/// <summary>Interruttore del controllo di pareggio sull'asta selezionata.</summary>
|
|
private void AuctionMonitor_BreakEvenChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
if (_isUpdatingSelection) return;
|
|
if (_selectedAuction == null) return;
|
|
|
|
_selectedAuction.AuctionInfo.StopAtBreakEven = AuctionMonitor.SelectedStopAtBreakEven.IsChecked == true;
|
|
SaveAuctions();
|
|
}
|
|
|
|
// ===== BROWSER CONTROL EVENTS =====
|
|
|
|
private void Browser_BrowserBackClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (Browser.EmbeddedWebView?.CoreWebView2 != null && Browser.EmbeddedWebView.CoreWebView2.CanGoBack)
|
|
Browser.EmbeddedWebView.CoreWebView2.GoBack();
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void Browser_BrowserForwardClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (Browser.EmbeddedWebView?.CoreWebView2 != null && Browser.EmbeddedWebView.CoreWebView2.CanGoForward)
|
|
Browser.EmbeddedWebView.CoreWebView2.GoForward();
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void Browser_BrowserRefreshClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
Browser.EmbeddedWebView?.Reload();
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void Browser_BrowserHomeClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
Browser.EmbeddedWebView?.CoreWebView2?.Navigate("https://it.bidoo.com/");
|
|
Browser.BrowserAddress.Text = "https://it.bidoo.com/";
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void Browser_BrowserGoClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
var url = Browser.BrowserAddress.Text?.Trim();
|
|
if (string.IsNullOrEmpty(url)) return;
|
|
if (!url.StartsWith("http", System.StringComparison.OrdinalIgnoreCase))
|
|
url = "https://" + url;
|
|
Browser.EmbeddedWebView?.CoreWebView2?.Navigate(url);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void Browser_BrowserAddAuctionClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
var url = Browser.BrowserAddress.Text?.Trim() ?? Browser.EmbeddedWebView?.Source?.ToString();
|
|
if (!string.IsNullOrEmpty(url))
|
|
_ = AddAuctionFromUrl(url);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
// ===== SETTINGS CONTROL EVENTS =====
|
|
|
|
private void Settings_SaveDefaultsClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
SaveDefaultsButton_Click(sender, e);
|
|
}
|
|
|
|
private void Settings_CancelDefaultsClicked(object sender, RoutedEventArgs e)
|
|
{
|
|
CancelDefaultsButton_Click(sender, e);
|
|
}
|
|
}
|
|
}
|