- 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.
320 lines
20 KiB
XML
320 lines
20 KiB
XML
<UserControl x:Class="AutoBidder.Controls.BrowserControl"
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
|
|
mc:Ignorable="d"
|
|
d:DesignHeight="800" d:DesignWidth="1200"
|
|
Background="{DynamicResource Brush.Bg}">
|
|
|
|
<UserControl.Resources>
|
|
<Style x:Key="Glyph" TargetType="TextBlock">
|
|
<Setter Property="FontFamily" Value="Segoe MDL2 Assets"/>
|
|
<Setter Property="VerticalAlignment" Value="Center"/>
|
|
<Setter Property="HorizontalAlignment" Value="Center"/>
|
|
</Style>
|
|
|
|
<!-- Scheda di una singola asta del catalogo -->
|
|
<DataTemplate x:Key="AuctionCardTemplate">
|
|
<Border Style="{StaticResource AuctionCard}" Width="250">
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- Immagine prodotto: arriva dalla rete, quindi puo' mancare -->
|
|
<Border Grid.Row="0" Height="110" CornerRadius="8"
|
|
Background="{DynamicResource Brush.SurfaceAlt}" Margin="0,0,0,8">
|
|
<Image Source="{Binding ImageUrl}" Stretch="Uniform" Margin="6"
|
|
RenderOptions.BitmapScalingMode="HighQuality"/>
|
|
</Border>
|
|
|
|
<TextBlock Grid.Row="1" Text="{Binding Name}" ToolTip="{Binding Name}"
|
|
FontWeight="SemiBold" TextTrimming="CharacterEllipsis"
|
|
MaxHeight="34" TextWrapping="Wrap"
|
|
Foreground="{DynamicResource Brush.Text}" Margin="0,0,0,6"/>
|
|
|
|
<StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,0,0,6">
|
|
<TextBlock Text="{Binding PriceDisplay}" FontWeight="Bold"
|
|
Foreground="{DynamicResource Brush.Accent}" Margin="0,0,10,0"/>
|
|
<TextBlock Text="{Binding TimerDisplay}" Margin="0,0,10,0">
|
|
<TextBlock.Style>
|
|
<Style TargetType="TextBlock">
|
|
<Setter Property="Foreground" Value="{DynamicResource Brush.TextMuted}"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding TimerUrgency}" Value="warn">
|
|
<Setter Property="Foreground" Value="{DynamicResource Brush.Warning}"/>
|
|
</DataTrigger>
|
|
<DataTrigger Binding="{Binding TimerUrgency}" Value="danger">
|
|
<Setter Property="Foreground" Value="{DynamicResource Brush.Danger}"/>
|
|
<Setter Property="FontWeight" Value="Bold"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</TextBlock.Style>
|
|
</TextBlock>
|
|
<TextBlock Text="{Binding BuyNowDisplay}"
|
|
FontSize="{StaticResource Font.Size.Sm}"
|
|
Foreground="{DynamicResource Brush.TextFaint}"
|
|
ToolTip="Valore del prodotto (Compra Subito)"/>
|
|
</StackPanel>
|
|
|
|
<Grid Grid.Row="3">
|
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
|
<TextBlock Text="{Binding LastBidderDisplay}"
|
|
FontSize="{StaticResource Font.Size.Sm}"
|
|
Foreground="{DynamicResource Brush.TextMuted}"
|
|
TextTrimming="CharacterEllipsis" MaxWidth="90"/>
|
|
<!-- Solo l'icona della mano: la parola "manuale" mangiava spazio
|
|
al nome dell'ultimo puntatore, che è il dato che si legge
|
|
davvero. Il significato resta nel suggerimento. -->
|
|
<Border Background="{DynamicResource Brush.WarningSubtle}" CornerRadius="5"
|
|
Padding="4,1" Margin="6,0,0,0"
|
|
Visibility="{Binding ManualBadgeVisibility}"
|
|
ToolTip="Asta solo manuale: non accetta puntate automatiche">
|
|
<TextBlock FontFamily="Segoe MDL2 Assets" Text="" FontSize="10"
|
|
Foreground="{DynamicResource Brush.Warning}"/>
|
|
</Border>
|
|
</StackPanel>
|
|
|
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
|
<!-- Segui il prodotto: le aste future dello stesso articolo
|
|
entreranno nel monitor da sole. -->
|
|
<Button Style="{StaticResource MiniIconButton}"
|
|
ToolTip="{Binding WatchTooltip}"
|
|
Command="{Binding DataContext.CatalogWatchCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
|
CommandParameter="{Binding}">
|
|
<TextBlock FontFamily="Segoe MDL2 Assets" Text="{Binding WatchGlyph}">
|
|
<TextBlock.Style>
|
|
<Style TargetType="TextBlock">
|
|
<Setter Property="Foreground" Value="{DynamicResource Brush.TextFaint}"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding IsWatched}" Value="True">
|
|
<Setter Property="Foreground" Value="{DynamicResource Brush.Gold}"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</TextBlock.Style>
|
|
</TextBlock>
|
|
</Button>
|
|
<!-- Mette il prodotto nella scheda Prodotti e ci porta sopra:
|
|
serve a dargli limiti propri anche senza seguirlo. -->
|
|
<Button Style="{StaticResource MiniIconButton}"
|
|
ToolTip="{Binding ConfigureTooltip}"
|
|
Command="{Binding DataContext.CatalogConfigureCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
|
CommandParameter="{Binding}">
|
|
<TextBlock FontFamily="Segoe MDL2 Assets" Text="">
|
|
<TextBlock.Style>
|
|
<Style TargetType="TextBlock">
|
|
<Setter Property="Foreground" Value="{DynamicResource Brush.TextFaint}"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding IsListed}" Value="True">
|
|
<Setter Property="Foreground" Value="{DynamicResource Brush.Accent}"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</TextBlock.Style>
|
|
</TextBlock>
|
|
</Button>
|
|
<Button Style="{StaticResource MiniIconButton}"
|
|
ToolTip="Apri su Bidoo"
|
|
Command="{Binding DataContext.CatalogOpenCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
|
CommandParameter="{Binding}">
|
|
<TextBlock FontFamily="Segoe MDL2 Assets" Text=""/>
|
|
</Button>
|
|
<Button Style="{StaticResource MiniIconButton}"
|
|
Foreground="{DynamicResource Brush.Accent}"
|
|
ToolTip="Aggiungi al monitor"
|
|
Command="{Binding DataContext.CatalogAddCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
|
CommandParameter="{Binding}">
|
|
<TextBlock FontFamily="Segoe MDL2 Assets" Text=""/>
|
|
</Button>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Grid>
|
|
</Border>
|
|
</DataTemplate>
|
|
</UserControl.Resources>
|
|
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- ═══ Barra strumenti ═══ -->
|
|
<Border Grid.Row="0" Background="{DynamicResource Brush.Surface}" Padding="10,7"
|
|
BorderBrush="{DynamicResource Brush.Border}" BorderThickness="0,0,0,1">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- Catalogo e Browser ora sono due schede separate nella barra laterale
|
|
("Cerca" e "Browser"): l'interruttore interno resta solo come stato
|
|
pilotato da fuori, non più visibile all'utente. -->
|
|
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center"
|
|
Visibility="Collapsed">
|
|
<RadioButton x:Name="ModeCatalogRadio" Style="{StaticResource SegmentedButton}"
|
|
GroupName="ExploreMode" IsChecked="True" Content="Catalogo"
|
|
Checked="ModeCatalogRadio_Checked"
|
|
ToolTip="Griglia delle aste: veloce, senza caricare pagine"/>
|
|
<RadioButton x:Name="ModeBrowserRadio" Style="{StaticResource SegmentedButton}"
|
|
GroupName="ExploreMode" Content="Browser"
|
|
Checked="ModeBrowserRadio_Checked"
|
|
ToolTip="Browser Bidoo integrato: serve per il login (il cookie viene importato da solo)"/>
|
|
<Border Width="1" Background="{DynamicResource Brush.Border}" Margin="8,4"/>
|
|
</StackPanel>
|
|
|
|
<StackPanel Grid.Column="1" x:Name="CatalogToolbarLeft" Orientation="Horizontal"
|
|
VerticalAlignment="Center">
|
|
<Button x:Name="CatalogRefreshButton" Style="{StaticResource IconButton}"
|
|
ToolTip="Ricarica categorie e prezzi" Click="CatalogRefreshButton_Click">
|
|
<TextBlock Style="{StaticResource Glyph}" Text=""/>
|
|
</Button>
|
|
<CheckBox x:Name="CatalogAutoRefresh" Content="Prezzi in tempo reale"
|
|
Margin="10,0,0,0" VerticalAlignment="Center"
|
|
Checked="CatalogAutoRefresh_Changed" Unchecked="CatalogAutoRefresh_Changed"
|
|
ToolTip="Aggiorna prezzi e timer sul posto. Spento di default: acceso, i valori cambiano mentre stai leggendo."/>
|
|
<CheckBox x:Name="CatalogHideManual" Content="Nascondi aste manuali"
|
|
Margin="14,0,0,0" VerticalAlignment="Center"
|
|
Checked="CatalogFilterChanged" Unchecked="CatalogFilterChanged"
|
|
ToolTip="Le aste manuali non accettano puntate automatiche"/>
|
|
</StackPanel>
|
|
|
|
<!-- Barra indirizzi del browser: occupa lo stesso posto dei filtri -->
|
|
<Border Grid.Column="1" Grid.ColumnSpan="2" x:Name="BrowserToolbar"
|
|
Visibility="Collapsed" Margin="0,0,10,0">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="*"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
|
|
<Button x:Name="BrowserBackButton" Style="{StaticResource IconButton}"
|
|
ToolTip="Indietro" Click="BrowserBackButton_Click">
|
|
<TextBlock Style="{StaticResource Glyph}" Text=""/>
|
|
</Button>
|
|
<Button x:Name="BrowserForwardButton" Style="{StaticResource IconButton}"
|
|
ToolTip="Avanti" Click="BrowserForwardButton_Click">
|
|
<TextBlock Style="{StaticResource Glyph}" Text=""/>
|
|
</Button>
|
|
<Button x:Name="BrowserRefreshButton" Style="{StaticResource IconButton}"
|
|
ToolTip="Ricarica" Click="BrowserRefreshButton_Click">
|
|
<TextBlock Style="{StaticResource Glyph}" Text=""/>
|
|
</Button>
|
|
<Button x:Name="BrowserHomeButton" Style="{StaticResource IconButton}"
|
|
ToolTip="Homepage Bidoo" Click="BrowserHomeButton_Click">
|
|
<TextBlock Style="{StaticResource Glyph}" Text=""/>
|
|
</Button>
|
|
</StackPanel>
|
|
|
|
<Border Grid.Column="1" Background="{DynamicResource Brush.Bg}"
|
|
BorderBrush="{DynamicResource Brush.Border}" BorderThickness="1"
|
|
CornerRadius="8" Margin="8,0,0,0">
|
|
<TextBox x:Name="BrowserAddress" VerticalAlignment="Center"
|
|
BorderThickness="0" Background="Transparent"
|
|
Foreground="{DynamicResource Brush.Text}" Padding="10,0"
|
|
IsReadOnly="True" Cursor="Arrow"
|
|
ToolTip="Indirizzo della pagina corrente"/>
|
|
</Border>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- Campo di ricerca con suggerimento: senza, un riquadro vuoto in barra
|
|
non si capisce a cosa serva. -->
|
|
<Grid Grid.Column="2" x:Name="CatalogSearchHost" Margin="16,0,10,0"
|
|
Width="240" HorizontalAlignment="Right" VerticalAlignment="Center">
|
|
<TextBox x:Name="CatalogSearchBox"
|
|
TextChanged="CatalogSearchBox_TextChanged"
|
|
ToolTip="Filtra per nome prodotto"/>
|
|
<TextBlock x:Name="CatalogSearchHint" Text="Filtra per nome…"
|
|
IsHitTestVisible="False" Margin="10,0,0,0"
|
|
VerticalAlignment="Center"
|
|
Foreground="{DynamicResource Brush.TextFaint}"/>
|
|
</Grid>
|
|
|
|
<StackPanel Grid.Column="3" Orientation="Horizontal" VerticalAlignment="Center">
|
|
<Border Style="{StaticResource Pill}">
|
|
<TextBlock x:Name="CatalogCountText" Text="0 aste"
|
|
FontSize="{StaticResource Font.Size.Sm}"
|
|
Foreground="{DynamicResource Brush.TextMuted}"/>
|
|
</Border>
|
|
<Button x:Name="BrowserAddAuctionButton" Style="{StaticResource IconButton}"
|
|
Foreground="{DynamicResource Brush.Accent}" Visibility="Collapsed"
|
|
ToolTip="Aggiungi al monitor l'asta aperta nel browser"
|
|
Click="BrowserAddAuctionButton_Click">
|
|
<TextBlock Style="{StaticResource Glyph}" Text=""/>
|
|
</Button>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- Riga vuota: tiene la struttura a tre righe leggibile -->
|
|
<Border Grid.Row="1" Height="0"/>
|
|
|
|
<!-- ═══ Catalogo ═══ -->
|
|
<Grid Grid.Row="2" x:Name="CatalogPanel">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="*"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- Categorie -->
|
|
<Border Grid.Column="0" Width="190" Background="{DynamicResource Brush.Surface}"
|
|
BorderBrush="{DynamicResource Brush.Border}" BorderThickness="0,0,1,0">
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto" Padding="6,8">
|
|
<ItemsControl x:Name="CatalogCategoryList">
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate>
|
|
<RadioButton Style="{StaticResource CategoryButton}"
|
|
GroupName="CatalogCategories"
|
|
Content="{Binding DisplayName}"
|
|
IsChecked="{Binding IsSelected, Mode=TwoWay}"
|
|
Checked="CategoryButton_Checked"/>
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
</ScrollViewer>
|
|
</Border>
|
|
|
|
<!-- Schede -->
|
|
<Grid Grid.Column="1">
|
|
<ScrollViewer x:Name="CatalogScroller" VerticalScrollBarVisibility="Auto" Padding="12,12,2,12">
|
|
<ItemsControl x:Name="CatalogItems" ItemTemplate="{StaticResource AuctionCardTemplate}">
|
|
<ItemsControl.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<WrapPanel Orientation="Horizontal"/>
|
|
</ItemsPanelTemplate>
|
|
</ItemsControl.ItemsPanel>
|
|
</ItemsControl>
|
|
</ScrollViewer>
|
|
|
|
<!-- Stato vuoto / caricamento -->
|
|
<StackPanel x:Name="CatalogEmptyState" VerticalAlignment="Center" HorizontalAlignment="Center">
|
|
<TextBlock Style="{StaticResource Glyph}" Text="" FontSize="34"
|
|
Foreground="{DynamicResource Brush.TextFaint}"/>
|
|
<TextBlock x:Name="CatalogEmptyText" Text="Caricamento categorie…"
|
|
Margin="0,10,0,0" HorizontalAlignment="Center"
|
|
Foreground="{DynamicResource Brush.TextMuted}"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
<!-- ═══ Browser integrato ═══ -->
|
|
<Border Grid.Row="2" x:Name="BrowserPanel" Background="{DynamicResource Brush.Bg}" Visibility="Collapsed">
|
|
<wv2:WebView2 x:Name="EmbeddedWebView"
|
|
PreviewMouseRightButtonUp="EmbeddedWebView_PreviewMouseRightButtonUp"/>
|
|
</Border>
|
|
</Grid>
|
|
</UserControl>
|