mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-07-07 06:39:33 +02:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1495ed9b90 | |||
| be66c74c08 | |||
| 6f54c09d96 | |||
| 45926b0990 | |||
| 25d29dc079 | |||
| efde9931c9 | |||
| 2c3b461d49 | |||
| b405052fd6 |
@@ -1,3 +1,10 @@
|
||||
### v2.22 (12-Aug-2020)
|
||||
|
||||
- [GUI] Improved the channel list by adding collapsible category groups. (Thanks [@CarJem Generations](https://github.com/CarJem))
|
||||
- [GUI] Improved exporting options by adding a set of controls that can be used to limit the date range of the export down to minutes. Previously it was only possible to configure the date range without the time component. (Thanks [@CarJem Generations](https://github.com/CarJem))
|
||||
- [HTML] Fixed an issue where the export didn't reflect changes in nicknames between messages sent by bots. This affected chat logs that contained interactions with the Tupperbox bot. (Thanks [@CarJem Generations](https://github.com/CarJem))
|
||||
- [CLI] Fixed an issue where the application crashed if there were two environment variables defined that had the same name but in different case.
|
||||
|
||||
### v2.21.2 (30-Jul-2020)
|
||||
|
||||
- [GUI] When copy-pasting token, any surrounding spaces are now discarded, in addition to double quotes.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CliFx" Version="1.3.1" />
|
||||
<PackageReference Include="CliFx" Version="1.3.2" />
|
||||
<PackageReference Include="Gress" Version="1.2.0" />
|
||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Import Project="../DiscordChatExporter.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MiniRazor" Version="1.0.1" />
|
||||
<PackageReference Include="MiniRazor" Version="1.1.0" />
|
||||
<PackageReference Include="Polly" Version="7.2.1" />
|
||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
var userMember = Model.ExportContext.TryGetMember(Model.MessageGroup.Author.Id);
|
||||
var userColor = Model.ExportContext.TryGetUserColor(Model.MessageGroup.Author.Id);
|
||||
var userNick = userMember?.Nick ?? Model.MessageGroup.Author.Name;
|
||||
var userNick = (Model.MessageGroup.Author.IsBot ? Model.MessageGroup.Author.Name : (userMember?.Nick ?? Model.MessageGroup.Author.Name));
|
||||
|
||||
var userColorStyle = userColor != null
|
||||
? $"color: rgb({userColor?.R},{userColor?.G},{userColor?.B})"
|
||||
|
||||
@@ -3,12 +3,18 @@ using System.Threading.Tasks;
|
||||
using MiniRazor;
|
||||
using Tyrrrz.Extensions;
|
||||
|
||||
[assembly: InternalsVisibleTo("RazorAssembly")]
|
||||
[assembly: InternalsVisibleTo(DiscordChatExporter.Domain.Exporting.Writers.Html.TemplateBundle.PreambleTemplateAssemblyName)]
|
||||
[assembly: InternalsVisibleTo(DiscordChatExporter.Domain.Exporting.Writers.Html.TemplateBundle.MessageGroupTemplateAssemblyName)]
|
||||
[assembly: InternalsVisibleTo(DiscordChatExporter.Domain.Exporting.Writers.Html.TemplateBundle.PostambleTemplateAssemblyName)]
|
||||
|
||||
namespace DiscordChatExporter.Domain.Exporting.Writers.Html
|
||||
{
|
||||
internal partial class TemplateBundle
|
||||
{
|
||||
public const string PreambleTemplateAssemblyName = "RazorAssembly_Preamble";
|
||||
public const string MessageGroupTemplateAssemblyName = "RazorAssembly_MessageGroup";
|
||||
public const string PostambleTemplateAssemblyName = "RazorAssembly_Postamble";
|
||||
|
||||
public MiniRazorTemplateDescriptor PreambleTemplate { get; }
|
||||
|
||||
public MiniRazorTemplateDescriptor MessageGroupTemplate { get; }
|
||||
@@ -44,11 +50,11 @@ namespace DiscordChatExporter.Domain.Exporting.Writers.Html
|
||||
var postambleTemplateSource = typeof(HtmlMessageWriter).Assembly
|
||||
.GetManifestResourceString($"{ns}.PostambleTemplate.cshtml");
|
||||
|
||||
var engine = new MiniRazorTemplateEngine("RazorAssembly", ns);
|
||||
var engine = new MiniRazorTemplateEngine();
|
||||
|
||||
var preambleTemplate = engine.Compile(preambleTemplateSource);
|
||||
var messageGroupTemplate = engine.Compile(messageGroupTemplateSource);
|
||||
var postambleTemplate = engine.Compile(postambleTemplateSource);
|
||||
var preambleTemplate = engine.Compile(preambleTemplateSource, PreambleTemplateAssemblyName, ns);
|
||||
var messageGroupTemplate = engine.Compile(messageGroupTemplateSource, MessageGroupTemplateAssemblyName, ns);
|
||||
var postambleTemplate = engine.Compile(postambleTemplateSource, PostambleTemplateAssemblyName, ns);
|
||||
|
||||
return new TemplateBundle(preambleTemplate, messageGroupTemplate, postambleTemplate);
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DiscordChatExporter.Gui"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:s="https://github.com/canton7/Stylet">
|
||||
<Application.Resources>
|
||||
<s:ApplicationLoader>
|
||||
@@ -111,6 +112,10 @@
|
||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style BasedOn="{StaticResource MaterialDesignTimePicker}" TargetType="{x:Type materialDesign:TimePicker}">
|
||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="MaterialDesignFlatDarkButton"
|
||||
BasedOn="{StaticResource MaterialDesignFlatButton}"
|
||||
@@ -136,6 +141,89 @@
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<!-- Default MD Expander is incredibly slow (https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/issues/1307) -->
|
||||
<Style BasedOn="{StaticResource MaterialDesignExpander}" TargetType="{x:Type Expander}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Expander">
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<DockPanel Background="{TemplateBinding Background}">
|
||||
<ToggleButton
|
||||
Name="HeaderSite"
|
||||
BorderThickness="0"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
|
||||
Cursor="Hand"
|
||||
DockPanel.Dock="Top"
|
||||
Focusable="False"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
IsTabStop="False"
|
||||
Opacity=".87"
|
||||
Style="{StaticResource MaterialDesignExpanderDownHeaderStyle}"
|
||||
TextElement.FontSize="15" />
|
||||
<Border
|
||||
Name="ContentSite"
|
||||
DockPanel.Dock="Bottom"
|
||||
Visibility="Collapsed">
|
||||
<StackPanel
|
||||
Name="ContentPanel"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
|
||||
<ContentPresenter
|
||||
Name="PART_Content"
|
||||
ContentStringFormat="{TemplateBinding ContentStringFormat}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
|
||||
Focusable="False" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsExpanded" Value="true">
|
||||
<Setter TargetName="ContentSite" Property="Visibility" Value="Visible" />
|
||||
</Trigger>
|
||||
<Trigger Property="ExpandDirection" Value="Right">
|
||||
<Setter TargetName="HeaderSite" Property="DockPanel.Dock" Value="Left" />
|
||||
<Setter TargetName="ContentSite" Property="DockPanel.Dock" Value="Right" />
|
||||
<Setter TargetName="ContentPanel" Property="Orientation" Value="Horizontal" />
|
||||
<Setter TargetName="ContentPanel" Property="Height" Value="Auto" />
|
||||
<Setter TargetName="HeaderSite" Property="Style" Value="{StaticResource MaterialDesignExpanderRightHeaderStyle}" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="ExpandDirection" Value="Left">
|
||||
<Setter TargetName="HeaderSite" Property="DockPanel.Dock" Value="Right" />
|
||||
<Setter TargetName="ContentSite" Property="DockPanel.Dock" Value="Left" />
|
||||
<Setter TargetName="ContentPanel" Property="Orientation" Value="Horizontal" />
|
||||
<Setter TargetName="ContentPanel" Property="Height" Value="Auto" />
|
||||
<Setter TargetName="HeaderSite" Property="Style" Value="{StaticResource MaterialDesignExpanderLeftHeaderStyle}" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="ExpandDirection" Value="Up">
|
||||
<Setter TargetName="HeaderSite" Property="DockPanel.Dock" Value="Bottom" />
|
||||
<Setter TargetName="ContentSite" Property="DockPanel.Dock" Value="Top" />
|
||||
<Setter TargetName="ContentPanel" Property="Orientation" Value="Vertical" />
|
||||
<Setter TargetName="ContentPanel" Property="Width" Value="Auto" />
|
||||
<Setter TargetName="HeaderSite" Property="Style" Value="{StaticResource MaterialDesignExpanderUpHeaderStyle}" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="ExpandDirection" Value="Down">
|
||||
<Setter TargetName="HeaderSite" Property="DockPanel.Dock" Value="Top" />
|
||||
<Setter TargetName="ContentSite" Property="DockPanel.Dock" Value="Bottom" />
|
||||
<Setter TargetName="ContentPanel" Property="Orientation" Value="Vertical" />
|
||||
<Setter TargetName="ContentPanel" Property="Width" Value="Auto" />
|
||||
<Setter TargetName="HeaderSite" Property="Style" Value="{StaticResource MaterialDesignExpanderDownHeaderStyle}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</s:ApplicationLoader>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace DiscordChatExporter.Gui.Converters
|
||||
{
|
||||
[ValueConversion(typeof(TimeSpan?), typeof(DateTime?))]
|
||||
public class TimeSpanToDateTimeConverter : IValueConverter
|
||||
{
|
||||
public static TimeSpanToDateTimeConverter Instance { get; } = new TimeSpanToDateTimeConverter();
|
||||
|
||||
public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is TimeSpan timeSpanValue)
|
||||
return DateTime.Today.Add(timeSpanValue);
|
||||
|
||||
return default(DateTime?);
|
||||
}
|
||||
|
||||
public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is DateTime dateTimeValue)
|
||||
return dateTimeValue.TimeOfDay;
|
||||
|
||||
return default(TimeSpan?);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,9 +26,23 @@ namespace DiscordChatExporter.Gui.ViewModels.Dialogs
|
||||
|
||||
public ExportFormat SelectedFormat { get; set; }
|
||||
|
||||
public DateTimeOffset? After { get; set; }
|
||||
// This date/time abomination is required because we use separate controls to set these
|
||||
|
||||
public DateTimeOffset? Before { get; set; }
|
||||
public DateTimeOffset? AfterDate { get; set; }
|
||||
|
||||
public bool IsAfterDateSet => AfterDate != null;
|
||||
|
||||
public TimeSpan? AfterTime { get; set; }
|
||||
|
||||
public DateTimeOffset? After => AfterDate?.Add(AfterTime ?? TimeSpan.Zero);
|
||||
|
||||
public DateTimeOffset? BeforeDate { get; set; }
|
||||
|
||||
public bool IsBeforeDateSet => BeforeDate != null;
|
||||
|
||||
public TimeSpan? BeforeTime { get; set; }
|
||||
|
||||
public DateTimeOffset? Before => BeforeDate?.Add(BeforeTime ?? TimeSpan.Zero);
|
||||
|
||||
public int? PartitionLimit { get; set; }
|
||||
|
||||
@@ -60,12 +74,6 @@ namespace DiscordChatExporter.Gui.ViewModels.Dialogs
|
||||
_settingsService.LastPartitionLimit = PartitionLimit;
|
||||
_settingsService.LastShouldDownloadMedia = ShouldDownloadMedia;
|
||||
|
||||
// Clamp 'after' and 'before' values
|
||||
if (After > Before)
|
||||
After = Before;
|
||||
if (Before < After)
|
||||
Before = After;
|
||||
|
||||
// If single channel - prompt file path
|
||||
if (IsSingleChannel)
|
||||
{
|
||||
|
||||
@@ -150,11 +150,7 @@ namespace DiscordChatExporter.Gui.ViewModels
|
||||
var guildChannelMap = new Dictionary<Guild, IReadOnlyList<Channel>>();
|
||||
await foreach (var guild in discord.GetUserGuildsAsync())
|
||||
{
|
||||
var channels = await discord.GetGuildChannelsAsync(guild.Id);
|
||||
guildChannelMap[guild] = channels
|
||||
.OrderBy(c => c.Category)
|
||||
.ThenBy(c => c.Name)
|
||||
.ToArray();
|
||||
guildChannelMap[guild] = await discord.GetGuildChannelsAsync(guild.Id);
|
||||
}
|
||||
|
||||
GuildChannelMap = guildChannelMap;
|
||||
|
||||
@@ -82,30 +82,52 @@
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<DatePicker
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="16,8"
|
||||
materialDesign:HintAssist.Hint="From (optional)"
|
||||
Margin="16,8,16,4"
|
||||
materialDesign:HintAssist.Hint="After (date)"
|
||||
materialDesign:HintAssist.IsFloating="True"
|
||||
DisplayDateEnd="{Binding Before, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||
SelectedDate="{Binding After, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||
DisplayDateEnd="{Binding BeforeDate, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||
SelectedDate="{Binding AfterDate, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||
ToolTip="If this is set, only messages sent after this date will be exported" />
|
||||
<DatePicker
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Margin="16,8"
|
||||
materialDesign:HintAssist.Hint="To (optional)"
|
||||
Margin="16,8,16,4"
|
||||
materialDesign:HintAssist.Hint="Before (date)"
|
||||
materialDesign:HintAssist.IsFloating="True"
|
||||
DisplayDateStart="{Binding After, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||
SelectedDate="{Binding Before, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||
DisplayDateStart="{Binding AfterDate, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||
SelectedDate="{Binding BeforeDate, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||
ToolTip="If this is set, only messages sent before this date will be exported" />
|
||||
<materialDesign:TimePicker
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="16,4,16,8"
|
||||
materialDesign:HintAssist.Hint="After (time)"
|
||||
materialDesign:HintAssist.IsFloating="True"
|
||||
IsEnabled="{Binding IsAfterDateSet}"
|
||||
SelectedTime="{Binding AfterTime, Converter={x:Static converters:TimeSpanToDateTimeConverter.Instance}}"
|
||||
ToolTip="If this is set, only messages sent after this time will be exported" />
|
||||
<materialDesign:TimePicker
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="16,4,16,8"
|
||||
materialDesign:HintAssist.Hint="Before (time)"
|
||||
materialDesign:HintAssist.IsFloating="True"
|
||||
IsEnabled="{Binding IsBeforeDateSet}"
|
||||
SelectedTime="{Binding BeforeTime, Converter={x:Static converters:TimeSpanToDateTimeConverter.Instance}}"
|
||||
ToolTip="If this is set, only messages sent before this time will be exported" />
|
||||
</Grid>
|
||||
|
||||
<!-- Partitioning -->
|
||||
<TextBox
|
||||
Margin="16,8"
|
||||
materialDesign:HintAssist.Hint="Messages per partition (optional)"
|
||||
materialDesign:HintAssist.Hint="Messages per partition"
|
||||
materialDesign:HintAssist.IsFloating="True"
|
||||
Text="{Binding PartitionLimit, TargetNullValue=''}"
|
||||
ToolTip="If this is set, the exported file will be split into multiple partitions, each containing no more than specified number of messages" />
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:behaviors="clr-namespace:DiscordChatExporter.Gui.Behaviors"
|
||||
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
|
||||
xmlns:converters="clr-namespace:DiscordChatExporter.Gui.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
@@ -23,6 +24,18 @@
|
||||
<Window.TaskbarItemInfo>
|
||||
<TaskbarItemInfo ProgressState="Normal" ProgressValue="{Binding ProgressManager.Progress}" />
|
||||
</Window.TaskbarItemInfo>
|
||||
<Window.Resources>
|
||||
<CollectionViewSource x:Key="AvailableChannelsViewSource" Source="{Binding AvailableChannels, Mode=OneWay}">
|
||||
<CollectionViewSource.GroupDescriptions>
|
||||
<PropertyGroupDescription PropertyName="Category" />
|
||||
</CollectionViewSource.GroupDescriptions>
|
||||
<CollectionViewSource.SortDescriptions>
|
||||
<componentModel:SortDescription Direction="Ascending" PropertyName="Category" />
|
||||
<componentModel:SortDescription Direction="Ascending" PropertyName="Name" />
|
||||
</CollectionViewSource.SortDescriptions>
|
||||
</CollectionViewSource>
|
||||
</Window.Resources>
|
||||
|
||||
<materialDesign:DialogHost SnackbarMessageQueue="{Binding Notifications}" Style="{DynamicResource MaterialDesignEmbeddedDialogHost}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@@ -253,12 +266,37 @@
|
||||
<Border Grid.Column="1">
|
||||
<ListBox
|
||||
HorizontalContentAlignment="Stretch"
|
||||
ItemsSource="{Binding AvailableChannels}"
|
||||
ItemsSource="{Binding Source={StaticResource AvailableChannelsViewSource}}"
|
||||
SelectionMode="Extended"
|
||||
TextSearch.TextPath="Model.Name">
|
||||
TextSearch.TextPath="Model.Name"
|
||||
VirtualizingPanel.IsVirtualizingWhenGrouping="True">
|
||||
<i:Interaction.Behaviors>
|
||||
<behaviors:ChannelMultiSelectionListBoxBehavior SelectedItems="{Binding SelectedChannels}" />
|
||||
</i:Interaction.Behaviors>
|
||||
<ListBox.GroupStyle>
|
||||
<GroupStyle>
|
||||
<GroupStyle.ContainerStyle>
|
||||
<Style TargetType="{x:Type GroupItem}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate d:DataContext="{x:Type CollectionViewGroup}">
|
||||
<Expander
|
||||
Margin="0"
|
||||
Padding="0"
|
||||
Background="Transparent"
|
||||
BorderBrush="{DynamicResource DividerBrush}"
|
||||
BorderThickness="0,1,0,0"
|
||||
Header="{Binding Name}"
|
||||
IsExpanded="False">
|
||||
<ItemsPresenter />
|
||||
</Expander>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</GroupStyle.ContainerStyle>
|
||||
</GroupStyle>
|
||||
</ListBox.GroupStyle>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="-8" Background="Transparent">
|
||||
@@ -278,16 +316,14 @@
|
||||
VerticalAlignment="Center"
|
||||
Kind="Pound" />
|
||||
|
||||
<!-- Channel category / name -->
|
||||
<!-- Channel name -->
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Margin="3,8,8,8"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14">
|
||||
<Run Foreground="{DynamicResource SecondaryTextBrush}" Text="{Binding Category, Mode=OneWay}" />
|
||||
<Run Text="/" />
|
||||
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="{Binding Name, Mode=OneWay}" />
|
||||
</TextBlock>
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource PrimaryTextBrush}"
|
||||
Text="{Binding Name, Mode=OneWay}" />
|
||||
|
||||
<!-- Is selected checkmark -->
|
||||
<materialDesign:PackIcon
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Version>2.21.2</Version>
|
||||
<Version>2.22</Version>
|
||||
<Company>Tyrrrz</Company>
|
||||
<Copyright>Copyright (c) Alexey Golub</Copyright>
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
||||
Reference in New Issue
Block a user