mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-07-08 23:24:39 +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)
|
### v2.21.2 (30-Jul-2020)
|
||||||
|
|
||||||
- [GUI] When copy-pasting token, any surrounding spaces are now discarded, in addition to double quotes.
|
- [GUI] When copy-pasting token, any surrounding spaces are now discarded, in addition to double quotes.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CliFx" Version="1.3.1" />
|
<PackageReference Include="CliFx" Version="1.3.2" />
|
||||||
<PackageReference Include="Gress" Version="1.2.0" />
|
<PackageReference Include="Gress" Version="1.2.0" />
|
||||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
|
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<Import Project="../DiscordChatExporter.props" />
|
<Import Project="../DiscordChatExporter.props" />
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MiniRazor" Version="1.0.1" />
|
<PackageReference Include="MiniRazor" Version="1.1.0" />
|
||||||
<PackageReference Include="Polly" Version="7.2.1" />
|
<PackageReference Include="Polly" Version="7.2.1" />
|
||||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
|
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
var userMember = Model.ExportContext.TryGetMember(Model.MessageGroup.Author.Id);
|
var userMember = Model.ExportContext.TryGetMember(Model.MessageGroup.Author.Id);
|
||||||
var userColor = Model.ExportContext.TryGetUserColor(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
|
var userColorStyle = userColor != null
|
||||||
? $"color: rgb({userColor?.R},{userColor?.G},{userColor?.B})"
|
? $"color: rgb({userColor?.R},{userColor?.G},{userColor?.B})"
|
||||||
|
|||||||
@@ -3,12 +3,18 @@ using System.Threading.Tasks;
|
|||||||
using MiniRazor;
|
using MiniRazor;
|
||||||
using Tyrrrz.Extensions;
|
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
|
namespace DiscordChatExporter.Domain.Exporting.Writers.Html
|
||||||
{
|
{
|
||||||
internal partial class TemplateBundle
|
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 PreambleTemplate { get; }
|
||||||
|
|
||||||
public MiniRazorTemplateDescriptor MessageGroupTemplate { get; }
|
public MiniRazorTemplateDescriptor MessageGroupTemplate { get; }
|
||||||
@@ -44,11 +50,11 @@ namespace DiscordChatExporter.Domain.Exporting.Writers.Html
|
|||||||
var postambleTemplateSource = typeof(HtmlMessageWriter).Assembly
|
var postambleTemplateSource = typeof(HtmlMessageWriter).Assembly
|
||||||
.GetManifestResourceString($"{ns}.PostambleTemplate.cshtml");
|
.GetManifestResourceString($"{ns}.PostambleTemplate.cshtml");
|
||||||
|
|
||||||
var engine = new MiniRazorTemplateEngine("RazorAssembly", ns);
|
var engine = new MiniRazorTemplateEngine();
|
||||||
|
|
||||||
var preambleTemplate = engine.Compile(preambleTemplateSource);
|
var preambleTemplate = engine.Compile(preambleTemplateSource, PreambleTemplateAssemblyName, ns);
|
||||||
var messageGroupTemplate = engine.Compile(messageGroupTemplateSource);
|
var messageGroupTemplate = engine.Compile(messageGroupTemplateSource, MessageGroupTemplateAssemblyName, ns);
|
||||||
var postambleTemplate = engine.Compile(postambleTemplateSource);
|
var postambleTemplate = engine.Compile(postambleTemplateSource, PostambleTemplateAssemblyName, ns);
|
||||||
|
|
||||||
return new TemplateBundle(preambleTemplate, messageGroupTemplate, postambleTemplate);
|
return new TemplateBundle(preambleTemplate, messageGroupTemplate, postambleTemplate);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:DiscordChatExporter.Gui"
|
xmlns:local="clr-namespace:DiscordChatExporter.Gui"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:s="https://github.com/canton7/Stylet">
|
xmlns:s="https://github.com/canton7/Stylet">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<s:ApplicationLoader>
|
<s:ApplicationLoader>
|
||||||
@@ -111,6 +112,10 @@
|
|||||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
|
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style BasedOn="{StaticResource MaterialDesignTimePicker}" TargetType="{x:Type materialDesign:TimePicker}">
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
<Style
|
<Style
|
||||||
x:Key="MaterialDesignFlatDarkButton"
|
x:Key="MaterialDesignFlatDarkButton"
|
||||||
BasedOn="{StaticResource MaterialDesignFlatButton}"
|
BasedOn="{StaticResource MaterialDesignFlatButton}"
|
||||||
@@ -136,6 +141,89 @@
|
|||||||
</Trigger>
|
</Trigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</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>
|
</s:ApplicationLoader>
|
||||||
</Application.Resources>
|
</Application.Resources>
|
||||||
</Application>
|
</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 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; }
|
public int? PartitionLimit { get; set; }
|
||||||
|
|
||||||
@@ -60,12 +74,6 @@ namespace DiscordChatExporter.Gui.ViewModels.Dialogs
|
|||||||
_settingsService.LastPartitionLimit = PartitionLimit;
|
_settingsService.LastPartitionLimit = PartitionLimit;
|
||||||
_settingsService.LastShouldDownloadMedia = ShouldDownloadMedia;
|
_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 single channel - prompt file path
|
||||||
if (IsSingleChannel)
|
if (IsSingleChannel)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -150,11 +150,7 @@ namespace DiscordChatExporter.Gui.ViewModels
|
|||||||
var guildChannelMap = new Dictionary<Guild, IReadOnlyList<Channel>>();
|
var guildChannelMap = new Dictionary<Guild, IReadOnlyList<Channel>>();
|
||||||
await foreach (var guild in discord.GetUserGuildsAsync())
|
await foreach (var guild in discord.GetUserGuildsAsync())
|
||||||
{
|
{
|
||||||
var channels = await discord.GetGuildChannelsAsync(guild.Id);
|
guildChannelMap[guild] = await discord.GetGuildChannelsAsync(guild.Id);
|
||||||
guildChannelMap[guild] = channels
|
|
||||||
.OrderBy(c => c.Category)
|
|
||||||
.ThenBy(c => c.Name)
|
|
||||||
.ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuildChannelMap = guildChannelMap;
|
GuildChannelMap = guildChannelMap;
|
||||||
|
|||||||
@@ -82,30 +82,52 @@
|
|||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="16,8"
|
Margin="16,8,16,4"
|
||||||
materialDesign:HintAssist.Hint="From (optional)"
|
materialDesign:HintAssist.Hint="After (date)"
|
||||||
materialDesign:HintAssist.IsFloating="True"
|
materialDesign:HintAssist.IsFloating="True"
|
||||||
DisplayDateEnd="{Binding Before, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
DisplayDateEnd="{Binding BeforeDate, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||||
SelectedDate="{Binding After, 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" />
|
ToolTip="If this is set, only messages sent after this date will be exported" />
|
||||||
<DatePicker
|
<DatePicker
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="16,8"
|
Margin="16,8,16,4"
|
||||||
materialDesign:HintAssist.Hint="To (optional)"
|
materialDesign:HintAssist.Hint="Before (date)"
|
||||||
materialDesign:HintAssist.IsFloating="True"
|
materialDesign:HintAssist.IsFloating="True"
|
||||||
DisplayDateStart="{Binding After, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
DisplayDateStart="{Binding AfterDate, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
|
||||||
SelectedDate="{Binding Before, 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" />
|
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>
|
</Grid>
|
||||||
|
|
||||||
<!-- Partitioning -->
|
<!-- Partitioning -->
|
||||||
<TextBox
|
<TextBox
|
||||||
Margin="16,8"
|
Margin="16,8"
|
||||||
materialDesign:HintAssist.Hint="Messages per partition (optional)"
|
materialDesign:HintAssist.Hint="Messages per partition"
|
||||||
materialDesign:HintAssist.IsFloating="True"
|
materialDesign:HintAssist.IsFloating="True"
|
||||||
Text="{Binding PartitionLimit, TargetNullValue=''}"
|
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" />
|
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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:behaviors="clr-namespace:DiscordChatExporter.Gui.Behaviors"
|
xmlns:behaviors="clr-namespace:DiscordChatExporter.Gui.Behaviors"
|
||||||
|
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
|
||||||
xmlns:converters="clr-namespace:DiscordChatExporter.Gui.Converters"
|
xmlns:converters="clr-namespace:DiscordChatExporter.Gui.Converters"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||||
@@ -23,6 +24,18 @@
|
|||||||
<Window.TaskbarItemInfo>
|
<Window.TaskbarItemInfo>
|
||||||
<TaskbarItemInfo ProgressState="Normal" ProgressValue="{Binding ProgressManager.Progress}" />
|
<TaskbarItemInfo ProgressState="Normal" ProgressValue="{Binding ProgressManager.Progress}" />
|
||||||
</Window.TaskbarItemInfo>
|
</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}">
|
<materialDesign:DialogHost SnackbarMessageQueue="{Binding Notifications}" Style="{DynamicResource MaterialDesignEmbeddedDialogHost}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
@@ -253,12 +266,37 @@
|
|||||||
<Border Grid.Column="1">
|
<Border Grid.Column="1">
|
||||||
<ListBox
|
<ListBox
|
||||||
HorizontalContentAlignment="Stretch"
|
HorizontalContentAlignment="Stretch"
|
||||||
ItemsSource="{Binding AvailableChannels}"
|
ItemsSource="{Binding Source={StaticResource AvailableChannelsViewSource}}"
|
||||||
SelectionMode="Extended"
|
SelectionMode="Extended"
|
||||||
TextSearch.TextPath="Model.Name">
|
TextSearch.TextPath="Model.Name"
|
||||||
|
VirtualizingPanel.IsVirtualizingWhenGrouping="True">
|
||||||
<i:Interaction.Behaviors>
|
<i:Interaction.Behaviors>
|
||||||
<behaviors:ChannelMultiSelectionListBoxBehavior SelectedItems="{Binding SelectedChannels}" />
|
<behaviors:ChannelMultiSelectionListBoxBehavior SelectedItems="{Binding SelectedChannels}" />
|
||||||
</i:Interaction.Behaviors>
|
</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>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Grid Margin="-8" Background="Transparent">
|
<Grid Margin="-8" Background="Transparent">
|
||||||
@@ -278,16 +316,14 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Kind="Pound" />
|
Kind="Pound" />
|
||||||
|
|
||||||
<!-- Channel category / name -->
|
<!-- Channel name -->
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="3,8,8,8"
|
Margin="3,8,8,8"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
FontSize="14">
|
FontSize="14"
|
||||||
<Run Foreground="{DynamicResource SecondaryTextBrush}" Text="{Binding Category, Mode=OneWay}" />
|
Foreground="{DynamicResource PrimaryTextBrush}"
|
||||||
<Run Text="/" />
|
Text="{Binding Name, Mode=OneWay}" />
|
||||||
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="{Binding Name, Mode=OneWay}" />
|
|
||||||
</TextBlock>
|
|
||||||
|
|
||||||
<!-- Is selected checkmark -->
|
<!-- Is selected checkmark -->
|
||||||
<materialDesign:PackIcon
|
<materialDesign:PackIcon
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<Version>2.21.2</Version>
|
<Version>2.22</Version>
|
||||||
<Company>Tyrrrz</Company>
|
<Company>Tyrrrz</Company>
|
||||||
<Copyright>Copyright (c) Alexey Golub</Copyright>
|
<Copyright>Copyright (c) Alexey Golub</Copyright>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
|
|||||||
Reference in New Issue
Block a user