mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-21 09:45:48 +08:00
feat: 新增采集与锄地一键采集工具页面
新增采集与锄地专用功能页面,支持通过素材名称匹配本地地图追踪任务并一键执行,具体改动如下: - 新增GatheringAndFarmingPage视图与对应ViewModel,包含角色、食材与特产、掉落物、矿石四个标签页 - 在主窗口导航栏添加采集与锄地页面入口,并将页面注册到应用依赖注入容器 - 优化齿轮任务系统,添加任务组配置属性,实现配置修改自动保存,完善脚本执行参数传递逻辑 - 在任务列表页面新增任务组设置按钮与配置弹窗 - 修复部分代码格式与缩进问题,调整命名空间引用顺序
This commit is contained in:
528
BetterGenshinImpact/View/Pages/GatheringAndFarmingPage.xaml
Normal file
528
BetterGenshinImpact/View/Pages/GatheringAndFarmingPage.xaml
Normal file
@@ -0,0 +1,528 @@
|
||||
<UserControl x:Class="BetterGenshinImpact.View.Pages.GatheringAndFarmingPage"
|
||||
x:Name="Root"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pages="clr-namespace:BetterGenshinImpact.ViewModel.Pages"
|
||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||
d:DataContext="{d:DesignInstance Type=pages:GatheringAndFarmingPageViewModel}"
|
||||
d:DesignHeight="860"
|
||||
d:DesignWidth="1200"
|
||||
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
|
||||
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
FontFamily="{StaticResource TextThemeFontFamily}"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="SummaryCardStyle" TargetType="Border">
|
||||
<Setter Property="Background" Value="{ui:ThemeResource ControlFillColorSecondaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceStrokeColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="10" />
|
||||
<Setter Property="Padding" Value="16,14" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="CharacterCardStyle" TargetType="Border">
|
||||
<Setter Property="Width" Value="336" />
|
||||
<Setter Property="Margin" Value="0,0,12,12" />
|
||||
<Setter Property="Background" Value="{ui:ThemeResource ControlFillColorSecondaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceStrokeColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="12" />
|
||||
<Setter Property="Padding" Value="16" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="MaterialButtonStyle" TargetType="Button">
|
||||
<Setter Property="Margin" Value="0,0,0,10" />
|
||||
<Setter Property="Padding" Value="10" />
|
||||
<Setter Property="Background" Value="{ui:ThemeResource ControlFillColorDefaultBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceStrokeColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border x:Name="RootBorder"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="10"
|
||||
SnapsToDevicePixels="True">
|
||||
<ContentPresenter Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="RootBorder" Property="Background" Value="{ui:ThemeResource ControlFillColorSecondaryBrush}" />
|
||||
<Setter TargetName="RootBorder" Property="BorderBrush" Value="{DynamicResource AccentFillColorDefaultBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="RootBorder" Property="Background" Value="{ui:ThemeResource ControlFillColorDefaultBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="TrackTileStyle" TargetType="Button" BasedOn="{StaticResource MaterialButtonStyle}">
|
||||
<Setter Property="Width" Value="220" />
|
||||
<Setter Property="Margin" Value="0,0,12,12" />
|
||||
<Setter Property="Padding" Value="14" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ConsistentTabControlStyle" TargetType="TabControl" BasedOn="{StaticResource {x:Type TabControl}}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TabControl}">
|
||||
<Grid Background="{TemplateBinding Background}" ClipToBounds="True" SnapsToDevicePixels="True">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border Grid.Row="0"
|
||||
Margin="0,0,0,10"
|
||||
Padding="6"
|
||||
Background="{ui:ThemeResource ControlFillColorSecondaryBrush}"
|
||||
BorderBrush="{DynamicResource SurfaceStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="10">
|
||||
<TabPanel IsItemsHost="True" Background="Transparent" />
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="1"
|
||||
Background="{ui:ThemeResource ControlFillColorSecondaryBrush}"
|
||||
BorderBrush="{DynamicResource SurfaceStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="12">
|
||||
<Border Margin="1"
|
||||
Background="{ui:ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||
CornerRadius="11">
|
||||
<ContentPresenter x:Name="PART_SelectedContentHost"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
Content="{TemplateBinding SelectedContent}"
|
||||
ContentStringFormat="{TemplateBinding SelectedContentStringFormat}"
|
||||
ContentTemplate="{TemplateBinding SelectedContentTemplate}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ConsistentTabItemStyle" TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
<Setter Property="Padding" Value="16,9" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TabItem}">
|
||||
<Grid Background="Transparent" SnapsToDevicePixels="True">
|
||||
<Border x:Name="mainBorder"
|
||||
Margin="0,0,6,0"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="0"
|
||||
CornerRadius="8">
|
||||
<ContentPresenter Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
<Border x:Name="selectionIndicator"
|
||||
Width="44"
|
||||
Height="3"
|
||||
Margin="0,0,5,5"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="{DynamicResource AccentFillColorDefaultBrush}"
|
||||
CornerRadius="1.5"
|
||||
Opacity="0" />
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<Setter TargetName="mainBorder" Property="Background" Value="{DynamicResource ControlFillColorDefaultBrush}" />
|
||||
<Setter TargetName="mainBorder" Property="BorderBrush" Value="{DynamicResource ControlElevationBorderBrush}" />
|
||||
<Setter TargetName="mainBorder" Property="BorderThickness" Value="1" />
|
||||
<Setter TargetName="selectionIndicator" Property="Opacity" Value="1" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="mainBorder" Property="Background" Value="{DynamicResource ControlFillColorSecondaryBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="24,16,24,12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="24" FontWeight="SemiBold" Text="采集与锄地" />
|
||||
<TextBlock Margin="0,8,0,0"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
TextWrapping="Wrap">
|
||||
统一收纳角色培养素材、食材与特产、掉落物和矿石的快捷入口。角色页会展示 3 个常用升级素材,点击素材图标后会先向用户确认,再执行自动匹配到的地图追踪任务。
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
VerticalAlignment="Top">
|
||||
<ui:Button Margin="0,0,8,0"
|
||||
Command="{Binding OpenMapPathingCommand}"
|
||||
Content="地图追踪"
|
||||
Icon="{ui:SymbolIcon Map24}" />
|
||||
<ui:Button Margin="0,0,8,0"
|
||||
Command="{Binding OpenScriptRepoCommand}"
|
||||
Content="脚本仓库" />
|
||||
<ui:Button Command="{Binding RefreshPathingIndexCommand}"
|
||||
Content="刷新路线索引" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="1" Margin="0,16,0,16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="12" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="12" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border Grid.Column="0" Style="{StaticResource SummaryCardStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock Foreground="{DynamicResource TextFillColorSecondaryBrush}" Text="本地地图追踪任务" />
|
||||
<TextBlock Margin="0,8,0,0"
|
||||
FontSize="28"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding AvailablePathingTaskCount}" />
|
||||
<TextBlock Margin="0,8,0,0"
|
||||
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
|
||||
Text="{Binding TaskIndexSummary}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Column="2" Style="{StaticResource SummaryCardStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock Foreground="{DynamicResource TextFillColorSecondaryBrush}" Text="素材入口数量" />
|
||||
<TextBlock Margin="0,8,0,0"
|
||||
FontSize="28"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding TrackEntryCount}" />
|
||||
<TextBlock Margin="0,8,0,0"
|
||||
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
|
||||
Text="角色页、素材页、掉落物页和矿石页共享同一套追踪确认逻辑。" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Column="4" Style="{StaticResource SummaryCardStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock Foreground="{DynamicResource TextFillColorSecondaryBrush}" Text="使用建议" />
|
||||
<TextBlock Margin="0,8,0,0"
|
||||
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
|
||||
TextWrapping="Wrap">
|
||||
素材名称会优先按任务文件名精确匹配,其次按相对路径模糊匹配。若未找到路线,请先在脚本仓库或地图追踪页准备对应任务。
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<TabControl Grid.Row="2"
|
||||
Style="{StaticResource ConsistentTabControlStyle}">
|
||||
<TabItem Header="角色" Style="{StaticResource ConsistentTabItemStyle}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="16">
|
||||
<TextBlock Margin="0,0,0,14"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="角色卡片默认展示 3 个常用升级素材。点击素材图标后会先弹出确认框,再执行匹配到的地图追踪任务。"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding Characters}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Style="{StaticResource CharacterCardStyle}">
|
||||
<StackPanel>
|
||||
<Grid Margin="0,0,0,14">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border Width="54"
|
||||
Height="54"
|
||||
Background="{Binding AccentSurfaceBrush}"
|
||||
BorderBrush="{Binding AccentBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="27">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="22"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{Binding AccentBrush}"
|
||||
Text="{Binding AvatarText}" />
|
||||
</Border>
|
||||
|
||||
<StackPanel Grid.Column="1" Margin="12,0,0,0" VerticalAlignment="Center">
|
||||
<TextBlock FontSize="18" FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
<TextBlock Margin="0,4,0,0"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Subtitle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Margin="0,0,0,10"
|
||||
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
|
||||
Text="常用升级素材"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding Materials}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Button Style="{StaticResource MaterialButtonStyle}"
|
||||
Command="{Binding DataContext.TrackMaterialCommand, ElementName=Root}"
|
||||
CommandParameter="{Binding}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border Width="40"
|
||||
Height="40"
|
||||
Background="{Binding AccentSurfaceBrush}"
|
||||
BorderBrush="{Binding AccentBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="20">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{Binding AccentBrush}"
|
||||
Text="{Binding ShortLabel}" />
|
||||
</Border>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Margin="10,0,0,0"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
<TextBlock Margin="0,3,0,0"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Column="2"
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{Binding AccentBrush}"
|
||||
Text="追踪" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="食材与特产" Style="{StaticResource ConsistentTabItemStyle}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl ItemsSource="{Binding FoodAndSpecialtySections}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Margin="16,16,16,4">
|
||||
<TextBlock FontSize="18" FontWeight="SemiBold" Text="{Binding Title}" />
|
||||
<TextBlock Margin="0,6,0,12"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding Items}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Button Style="{StaticResource TrackTileStyle}"
|
||||
Command="{Binding DataContext.TrackMaterialCommand, ElementName=Root}"
|
||||
CommandParameter="{Binding}">
|
||||
<StackPanel>
|
||||
<Border Width="46"
|
||||
Height="46"
|
||||
Margin="0,0,0,12"
|
||||
Background="{Binding AccentSurfaceBrush}"
|
||||
BorderBrush="{Binding AccentBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="23">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{Binding AccentBrush}"
|
||||
Text="{Binding ShortLabel}" />
|
||||
</Border>
|
||||
<TextBlock FontSize="16" FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
<TextBlock Margin="0,6,0,0"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock Margin="0,10,0,0"
|
||||
Foreground="{Binding AccentBrush}"
|
||||
Text="点击开始追踪" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="掉落物" Style="{StaticResource ConsistentTabItemStyle}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="16">
|
||||
<TextBlock Margin="0,0,0,12"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="适合快速补充怪物系列路线。这里推荐把常刷对象单独准备成地图追踪任务,方便一键执行。"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding DropItems}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Button Style="{StaticResource TrackTileStyle}"
|
||||
Command="{Binding DataContext.TrackMaterialCommand, ElementName=Root}"
|
||||
CommandParameter="{Binding}">
|
||||
<StackPanel>
|
||||
<Border Width="46"
|
||||
Height="46"
|
||||
Margin="0,0,0,12"
|
||||
Background="{Binding AccentSurfaceBrush}"
|
||||
BorderBrush="{Binding AccentBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="23">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{Binding AccentBrush}"
|
||||
Text="{Binding ShortLabel}" />
|
||||
</Border>
|
||||
<TextBlock FontSize="16" FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
<TextBlock Margin="0,6,0,0"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock Margin="0,10,0,0"
|
||||
Foreground="{Binding AccentBrush}"
|
||||
Text="点击开始追踪" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="矿石" Style="{StaticResource ConsistentTabItemStyle}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="16">
|
||||
<TextBlock Margin="0,0,0,12"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="矿石页更偏向长线补货,建议把常刷路线做成每日或隔日脚本。点击卡片后同样会先确认再执行。"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding OreItems}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Button Style="{StaticResource TrackTileStyle}"
|
||||
Command="{Binding DataContext.TrackMaterialCommand, ElementName=Root}"
|
||||
CommandParameter="{Binding}">
|
||||
<StackPanel>
|
||||
<Border Width="46"
|
||||
Height="46"
|
||||
Margin="0,0,0,12"
|
||||
Background="{Binding AccentSurfaceBrush}"
|
||||
BorderBrush="{Binding AccentBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="23">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{Binding AccentBrush}"
|
||||
Text="{Binding ShortLabel}" />
|
||||
</Border>
|
||||
<TextBlock FontSize="16" FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
<TextBlock Margin="0,6,0,0"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock Margin="0,10,0,0"
|
||||
Foreground="{Binding AccentBrush}"
|
||||
Text="点击开始追踪" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,15 @@
|
||||
using BetterGenshinImpact.ViewModel.Pages;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace BetterGenshinImpact.View.Pages;
|
||||
|
||||
public partial class GatheringAndFarmingPage : UserControl
|
||||
{
|
||||
private GatheringAndFarmingPageViewModel ViewModel { get; }
|
||||
|
||||
public GatheringAndFarmingPage(GatheringAndFarmingPageViewModel viewModel)
|
||||
{
|
||||
DataContext = ViewModel = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,448 @@
|
||||
using BetterGenshinImpact.Core.Script;
|
||||
using BetterGenshinImpact.Core.Script.Group;
|
||||
using BetterGenshinImpact.Service.Interface;
|
||||
using BetterGenshinImpact.View.Pages;
|
||||
using BetterGenshinImpact.View.Windows;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
using Wpf.Ui;
|
||||
using Wpf.Ui.Violeta.Controls;
|
||||
|
||||
namespace BetterGenshinImpact.ViewModel.Pages;
|
||||
|
||||
public partial class GatheringAndFarmingPageViewModel : ViewModel
|
||||
{
|
||||
private readonly ILogger<GatheringAndFarmingPageViewModel> _logger = App.GetLogger<GatheringAndFarmingPageViewModel>();
|
||||
private readonly IScriptService _scriptService;
|
||||
private readonly INavigationService _navigationService;
|
||||
private readonly List<PathingTaskIndexEntry> _pathingTaskIndex = [];
|
||||
private bool _isInitialized;
|
||||
|
||||
[ObservableProperty] private ObservableCollection<GatherCharacterCard> _characters = [];
|
||||
[ObservableProperty] private ObservableCollection<GatherTrackSection> _foodAndSpecialtySections = [];
|
||||
[ObservableProperty] private ObservableCollection<GatherTrackItem> _dropItems = [];
|
||||
[ObservableProperty] private ObservableCollection<GatherTrackItem> _oreItems = [];
|
||||
[ObservableProperty] private int _availablePathingTaskCount;
|
||||
[ObservableProperty] private string _taskIndexSummary = "尚未扫描路线";
|
||||
|
||||
public int TrackEntryCount =>
|
||||
Characters.Sum(x => x.Materials.Count)
|
||||
+ FoodAndSpecialtySections.Sum(x => x.Items.Count)
|
||||
+ DropItems.Count
|
||||
+ OreItems.Count;
|
||||
|
||||
public GatheringAndFarmingPageViewModel(IScriptService scriptService, INavigationService navigationService)
|
||||
{
|
||||
_scriptService = scriptService;
|
||||
_navigationService = navigationService;
|
||||
}
|
||||
|
||||
public override void OnNavigatedTo()
|
||||
{
|
||||
if (_isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BuildDesignData();
|
||||
_ = RefreshPathingIndexAsync();
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void OpenMapPathing()
|
||||
{
|
||||
_navigationService.Navigate(typeof(MapPathingPage));
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void OpenScriptRepo()
|
||||
{
|
||||
ScriptRepoUpdater.Instance.OpenScriptRepoWindow();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task RefreshPathingIndexAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var pathingRoot = MapPathingViewModel.PathJsonPath;
|
||||
if (!Directory.Exists(pathingRoot))
|
||||
{
|
||||
_pathingTaskIndex.Clear();
|
||||
AvailablePathingTaskCount = 0;
|
||||
TaskIndexSummary = "未找到本地地图追踪目录,编译后首次运行会自动生成。";
|
||||
return;
|
||||
}
|
||||
|
||||
var files = await Task.Run(() => Directory
|
||||
.EnumerateFiles(pathingRoot, "*.json", SearchOption.AllDirectories)
|
||||
.Select(path =>
|
||||
{
|
||||
var relativePath = Path.GetRelativePath(pathingRoot, path);
|
||||
return new PathingTaskIndexEntry(
|
||||
path,
|
||||
relativePath.Replace('/', '\\'),
|
||||
Path.GetFileNameWithoutExtension(path));
|
||||
})
|
||||
.OrderBy(x => x.RelativePath, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList());
|
||||
|
||||
_pathingTaskIndex.Clear();
|
||||
_pathingTaskIndex.AddRange(files);
|
||||
AvailablePathingTaskCount = files.Count;
|
||||
TaskIndexSummary = files.Count == 0
|
||||
? "已扫描完成,但本地还没有可执行的地图追踪任务。"
|
||||
: $"已完成扫描,可直接匹配 {files.Count} 条地图追踪任务。";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "刷新采集与锄地路线索引失败");
|
||||
TaskIndexSummary = $"路线索引刷新失败:{ex.Message}";
|
||||
Toast.Error($"路线索引刷新失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task TrackMaterialAsync(GatherTrackItem? item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pathingTaskIndex.Count == 0)
|
||||
{
|
||||
await RefreshPathingIndexAsync();
|
||||
}
|
||||
|
||||
var matchedTask = FindBestPathingTask(item.SearchKeywords);
|
||||
if (matchedTask == null)
|
||||
{
|
||||
await ThemedMessageBox.WarningAsync(
|
||||
$"未找到与“{item.Name}”匹配的地图追踪任务。\n\n你可以先在“脚本仓库”或“地图追踪”中准备对应路线,然后再从这里一键执行。",
|
||||
"未找到路线");
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await ThemedMessageBox.QuestionAsync(
|
||||
$"是否执行“{item.Name}”对应的地图追踪任务?\n\n匹配到的路线:{matchedTask.RelativePath}",
|
||||
"执行地图追踪",
|
||||
System.Windows.MessageBoxButton.YesNo,
|
||||
System.Windows.MessageBoxResult.No);
|
||||
|
||||
if (result != System.Windows.MessageBoxResult.Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var project = BuildPathingProject(matchedTask.FullPath);
|
||||
await _scriptService.RunMulti([project]);
|
||||
Toast.Success($"已开始执行路线:{Path.GetFileNameWithoutExtension(matchedTask.FullPath)}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "执行素材路线失败: {MaterialName}", item.Name);
|
||||
await ThemedMessageBox.ErrorAsync($"执行“{item.Name}”失败:{ex.Message}", "执行失败");
|
||||
}
|
||||
}
|
||||
|
||||
private PathingTaskIndexEntry? FindBestPathingTask(IEnumerable<string> keywords)
|
||||
{
|
||||
var keywordList = keywords
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
.Select(x => x.Trim())
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
if (keywordList.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _pathingTaskIndex
|
||||
.Select(entry => new
|
||||
{
|
||||
Entry = entry,
|
||||
Score = keywordList.Max(keyword => ScorePathingTask(entry, keyword))
|
||||
})
|
||||
.Where(x => x.Score > 0)
|
||||
.OrderByDescending(x => x.Score)
|
||||
.ThenBy(x => x.Entry.RelativePath.Length)
|
||||
.ThenBy(x => x.Entry.RelativePath, StringComparer.OrdinalIgnoreCase)
|
||||
.Select(x => x.Entry)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
private static int ScorePathingTask(PathingTaskIndexEntry entry, string keyword)
|
||||
{
|
||||
if (entry.FileName.Equals(keyword, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (entry.RelativePath.EndsWith(keyword + ".json", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return 90;
|
||||
}
|
||||
|
||||
if (entry.FileName.Contains(keyword, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return 75;
|
||||
}
|
||||
|
||||
if (entry.RelativePath.Contains(keyword, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static ScriptGroupProject BuildPathingProject(string fullPath)
|
||||
{
|
||||
var folder = Path.GetDirectoryName(fullPath) ?? MapPathingViewModel.PathJsonPath;
|
||||
var relativeFolder = Path.GetRelativePath(MapPathingViewModel.PathJsonPath, folder);
|
||||
if (relativeFolder == ".")
|
||||
{
|
||||
relativeFolder = string.Empty;
|
||||
}
|
||||
|
||||
return ScriptGroupProject.BuildPathingProject(Path.GetFileName(fullPath), relativeFolder);
|
||||
}
|
||||
|
||||
private void BuildDesignData()
|
||||
{
|
||||
Characters =
|
||||
[
|
||||
new GatherCharacterCard(
|
||||
"纳西妲",
|
||||
"须弥 · 草系主C/辅助",
|
||||
"纳",
|
||||
CreatePalette("#84C26E", "#1E3523"),
|
||||
[
|
||||
CreateTrack("月莲", "水边与林地特产路线", "月", "#84C26E", "#1E3523"),
|
||||
CreateTrack("蕈兽", "浮游菌群常规掉落路线", "蕈", "#6BB9A0", "#1B342F", "蕈兽", "浮游菌"),
|
||||
CreateTrack("树莓", "顺路补货的常用食材路线", "莓", "#D36B7F", "#3A1D25")
|
||||
]),
|
||||
new GatherCharacterCard(
|
||||
"芙宁娜",
|
||||
"枫丹 · 水系辅助",
|
||||
"芙",
|
||||
CreatePalette("#7EB7F3", "#1D2E45"),
|
||||
[
|
||||
CreateTrack("湖光铃兰", "枫丹湖区特产路线", "铃", "#7EB7F3", "#1D2E45"),
|
||||
CreateTrack("原海异种", "海边通刷掉落路线", "海", "#5AA4D6", "#183247", "原海异种", "异海凝珠"),
|
||||
CreateTrack("萃凝晶", "枫丹矿石补货路线", "晶", "#82C9FF", "#20354A")
|
||||
]),
|
||||
new GatherCharacterCard(
|
||||
"雷电将军",
|
||||
"稻妻 · 充能爆发核心",
|
||||
"雷",
|
||||
CreatePalette("#A887F7", "#2B2144"),
|
||||
[
|
||||
CreateTrack("天云草实", "清籁岛高密度特产路线", "云", "#A887F7", "#2B2144"),
|
||||
CreateTrack("野伏众", "稻妻常刷掉落路线", "伏", "#E09A5E", "#442817", "野伏众", "刀镡"),
|
||||
CreateTrack("紫晶块", "稻妻锻造矿石路线", "紫", "#B498FF", "#322650")
|
||||
]),
|
||||
new GatherCharacterCard(
|
||||
"钟离",
|
||||
"璃月 · 护盾辅助",
|
||||
"钟",
|
||||
CreatePalette("#D3A65C", "#43301A"),
|
||||
[
|
||||
CreateTrack("石珀", "璃月山体特产路线", "珀", "#D3A65C", "#43301A"),
|
||||
CreateTrack("史莱姆", "通用掉落补货路线", "史", "#73C7C0", "#1C3737", "史莱姆", "史莱姆凝液"),
|
||||
CreateTrack("白铁块", "璃月常用矿石路线", "铁", "#C7D0DA", "#2B3440")
|
||||
]),
|
||||
new GatherCharacterCard(
|
||||
"那维莱特",
|
||||
"枫丹 · 水系站场",
|
||||
"那",
|
||||
CreatePalette("#68C1E0", "#183743"),
|
||||
[
|
||||
CreateTrack("湖光铃兰", "角色专属特产路线", "铃", "#68C1E0", "#183743"),
|
||||
CreateTrack("原海异种", "海边通刷掉落路线", "海", "#68C1E0", "#183743", "原海异种", "异海凝珠"),
|
||||
CreateTrack("水晶块", "精锻魔矿主力矿线", "晶", "#8FD2F2", "#213A49")
|
||||
]),
|
||||
new GatherCharacterCard(
|
||||
"娜维娅",
|
||||
"枫丹 · 岩系输出",
|
||||
"娜",
|
||||
CreatePalette("#E0B765", "#45371A"),
|
||||
[
|
||||
CreateTrack("苍晶螺", "枫丹海岸特产路线", "螺", "#73C0D4", "#203743"),
|
||||
CreateTrack("发条机关", "枫丹机械系掉落路线", "机", "#D6A86A", "#45301E"),
|
||||
CreateTrack("白铁块", "锻造补货矿石路线", "铁", "#C7D0DA", "#2B3440")
|
||||
])
|
||||
];
|
||||
|
||||
FoodAndSpecialtySections =
|
||||
[
|
||||
new GatherTrackSection(
|
||||
"地方特产",
|
||||
"更适合按地区分批补货,适合角色突破前集中准备。",
|
||||
[
|
||||
CreateTrack("月莲", "须弥水边高密度路线", "月", "#84C26E", "#1E3523"),
|
||||
CreateTrack("清心", "璃月高山特产路线", "清", "#7CC6E6", "#183543"),
|
||||
CreateTrack("苍晶螺", "枫丹海岸特产路线", "螺", "#73C0D4", "#203743"),
|
||||
CreateTrack("湖光铃兰", "枫丹湖区采集路线", "铃", "#7EB7F3", "#1D2E45"),
|
||||
CreateTrack("石珀", "璃月矿壁采集路线", "珀", "#D3A65C", "#43301A"),
|
||||
CreateTrack("天云草实", "清籁岛采集路线", "云", "#A887F7", "#2B2144")
|
||||
]),
|
||||
new GatherTrackSection(
|
||||
"食材",
|
||||
"适合烹饪、周本前补货或顺路囤积。",
|
||||
[
|
||||
CreateTrack("甜甜花", "通用食材顺路收集", "甜", "#E38B98", "#452128"),
|
||||
CreateTrack("松茸", "林地食材补货路线", "茸", "#D6A86A", "#433118"),
|
||||
CreateTrack("树莓", "前期高频食材路线", "莓", "#D36B7F", "#3A1D25"),
|
||||
CreateTrack("莲蓬", "璃月水域食材路线", "莲", "#7DC0B7", "#1C3533"),
|
||||
CreateTrack("日落果", "蒙德野外食材路线", "果", "#E49B67", "#472818"),
|
||||
CreateTrack("鱼肉", "沿河补货路线", "鱼", "#6AB6E6", "#1C3042")
|
||||
])
|
||||
];
|
||||
|
||||
DropItems =
|
||||
[
|
||||
CreateTrack("丘丘人射手", "弓手掉落集中清线", "丘", "#C98A5B", "#3A2518", "丘丘人射手", "丘丘人"),
|
||||
CreateTrack("史莱姆", "元素凝液快速补货", "史", "#73C7C0", "#1C3737", "史莱姆", "史莱姆凝液"),
|
||||
CreateTrack("蕈兽", "真菌孢子常用路线", "蕈", "#6BB9A0", "#1B342F", "蕈兽", "浮游菌"),
|
||||
CreateTrack("发条机关", "枫丹机械掉落路线", "机", "#D6A86A", "#45301E"),
|
||||
CreateTrack("遗迹守卫", "机关核心补货路线", "遗", "#8E9EB5", "#26313F"),
|
||||
CreateTrack("原海异种", "海边材料通刷路线", "海", "#5AA4D6", "#183247", "原海异种", "异海凝珠")
|
||||
];
|
||||
|
||||
OreItems =
|
||||
[
|
||||
CreateTrack("白铁块", "日常锻造基础矿线", "铁", "#C7D0DA", "#2B3440"),
|
||||
CreateTrack("水晶块", "精锻魔矿主力矿线", "晶", "#8FD2F2", "#213A49"),
|
||||
CreateTrack("紫晶块", "稻妻矿石补货路线", "紫", "#B498FF", "#322650"),
|
||||
CreateTrack("星银矿石", "雪山专属矿石路线", "银", "#9FC6DC", "#213545"),
|
||||
CreateTrack("萃凝晶", "枫丹矿石补货路线", "凝", "#82C9FF", "#20354A"),
|
||||
CreateTrack("铁块", "早期锻造补货路线", "块", "#B4BDC8", "#29323D")
|
||||
];
|
||||
|
||||
OnPropertyChanged(nameof(TrackEntryCount));
|
||||
}
|
||||
|
||||
private static GatherTrackItem CreateTrack(
|
||||
string name,
|
||||
string description,
|
||||
string shortLabel,
|
||||
string accentHex,
|
||||
string surfaceHex,
|
||||
params string[] keywords)
|
||||
{
|
||||
var palette = CreatePalette(accentHex, surfaceHex);
|
||||
return new GatherTrackItem(
|
||||
name,
|
||||
description,
|
||||
shortLabel,
|
||||
palette.AccentBrush,
|
||||
palette.SurfaceBrush,
|
||||
keywords.Length == 0 ? [name] : keywords);
|
||||
}
|
||||
|
||||
private static GatherPalette CreatePalette(string accentHex, string surfaceHex)
|
||||
{
|
||||
return new GatherPalette(CreateBrush(accentHex), CreateBrush(surfaceHex));
|
||||
}
|
||||
|
||||
private static Brush CreateBrush(string hex)
|
||||
{
|
||||
var color = (Color)ColorConverter.ConvertFromString(hex)!;
|
||||
var brush = new SolidColorBrush(color);
|
||||
brush.Freeze();
|
||||
return brush;
|
||||
}
|
||||
|
||||
private sealed record PathingTaskIndexEntry(string FullPath, string RelativePath, string FileName);
|
||||
}
|
||||
|
||||
public sealed class GatherPalette
|
||||
{
|
||||
public Brush AccentBrush { get; }
|
||||
public Brush SurfaceBrush { get; }
|
||||
|
||||
public GatherPalette(Brush accentBrush, Brush surfaceBrush)
|
||||
{
|
||||
AccentBrush = accentBrush;
|
||||
SurfaceBrush = surfaceBrush;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class GatherCharacterCard
|
||||
{
|
||||
public string Name { get; }
|
||||
public string Subtitle { get; }
|
||||
public string AvatarText { get; }
|
||||
public Brush AccentBrush { get; }
|
||||
public Brush AccentSurfaceBrush { get; }
|
||||
public ObservableCollection<GatherTrackItem> Materials { get; }
|
||||
|
||||
public GatherCharacterCard(
|
||||
string name,
|
||||
string subtitle,
|
||||
string avatarText,
|
||||
GatherPalette palette,
|
||||
IEnumerable<GatherTrackItem> materials)
|
||||
{
|
||||
Name = name;
|
||||
Subtitle = subtitle;
|
||||
AvatarText = avatarText;
|
||||
AccentBrush = palette.AccentBrush;
|
||||
AccentSurfaceBrush = palette.SurfaceBrush;
|
||||
Materials = new ObservableCollection<GatherTrackItem>(materials);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class GatherTrackSection
|
||||
{
|
||||
public string Title { get; }
|
||||
public string Description { get; }
|
||||
public ObservableCollection<GatherTrackItem> Items { get; }
|
||||
|
||||
public GatherTrackSection(string title, string description, IEnumerable<GatherTrackItem> items)
|
||||
{
|
||||
Title = title;
|
||||
Description = description;
|
||||
Items = new ObservableCollection<GatherTrackItem>(items);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class GatherTrackItem
|
||||
{
|
||||
public string Name { get; }
|
||||
public string Description { get; }
|
||||
public string ShortLabel { get; }
|
||||
public Brush AccentBrush { get; }
|
||||
public Brush AccentSurfaceBrush { get; }
|
||||
public IReadOnlyList<string> SearchKeywords { get; }
|
||||
|
||||
public GatherTrackItem(
|
||||
string name,
|
||||
string description,
|
||||
string shortLabel,
|
||||
Brush accentBrush,
|
||||
Brush accentSurfaceBrush,
|
||||
IReadOnlyList<string> searchKeywords)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
ShortLabel = shortLabel;
|
||||
AccentBrush = accentBrush;
|
||||
AccentSurfaceBrush = accentSurfaceBrush;
|
||||
SearchKeywords = searchKeywords;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user