mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-05-25 04:04:22 -04:00
Enhance output path selection in the GUI
Enables the use of template tokens when exporting multiple channels Closes #676
This commit is contained in:
parent
f1ae0266f1
commit
c8d83beb8d
5 changed files with 115 additions and 25 deletions
|
@ -26,7 +26,11 @@ public abstract class ExportCommandBase : TokenCommandBase
|
||||||
[CommandOption(
|
[CommandOption(
|
||||||
"output",
|
"output",
|
||||||
'o',
|
'o',
|
||||||
Description = "Output file or directory path. Directory path should end in a slash."
|
Description =
|
||||||
|
"Output file or directory path. " +
|
||||||
|
"If a directory is specified, file names will be generated automatically based on the channel names and other parameters. " +
|
||||||
|
"Directory path should end with a slash to avoid ambiguity. " +
|
||||||
|
"Supports template tokens, see the documentation for more info."
|
||||||
)]
|
)]
|
||||||
public string OutputPath
|
public string OutputPath
|
||||||
{
|
{
|
||||||
|
@ -58,7 +62,8 @@ public abstract class ExportCommandBase : TokenCommandBase
|
||||||
[CommandOption(
|
[CommandOption(
|
||||||
"partition",
|
"partition",
|
||||||
'p',
|
'p',
|
||||||
Description = "Split output into partitions, each limited to this number of messages (e.g. '100') or file size (e.g. '10mb')."
|
Description =
|
||||||
|
"Split output into partitions, each limited to this number of messages (e.g. '100') or file size (e.g. '10mb')."
|
||||||
)]
|
)]
|
||||||
public PartitionLimit PartitionLimit { get; init; } = PartitionLimit.Null;
|
public PartitionLimit PartitionLimit { get; init; } = PartitionLimit.Null;
|
||||||
|
|
||||||
|
|
|
@ -158,22 +158,27 @@ public class DashboardViewModel : PropertyChangedBase
|
||||||
|
|
||||||
var exporter = new ChannelExporter(_discord);
|
var exporter = new ChannelExporter(_discord);
|
||||||
|
|
||||||
var progresses = Enumerable
|
var channelProgressPairs = dialog
|
||||||
.Range(0, dialog.Channels!.Count)
|
.Channels!
|
||||||
.Select(_ => _progressMuxer.CreateInput())
|
.Select(c => new
|
||||||
|
{
|
||||||
|
Channel = c,
|
||||||
|
Progress = _progressMuxer.CreateInput()
|
||||||
|
})
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
var successfulExportCount = 0;
|
var successfulExportCount = 0;
|
||||||
|
|
||||||
await Parallel.ForEachAsync(
|
await Parallel.ForEachAsync(
|
||||||
dialog.Channels.Zip(progresses),
|
channelProgressPairs,
|
||||||
new ParallelOptions
|
new ParallelOptions
|
||||||
{
|
{
|
||||||
MaxDegreeOfParallelism = Math.Max(1, _settingsService.ParallelLimit)
|
MaxDegreeOfParallelism = Math.Max(1, _settingsService.ParallelLimit)
|
||||||
},
|
},
|
||||||
async (tuple, cancellationToken) =>
|
async (pair, cancellationToken) =>
|
||||||
{
|
{
|
||||||
var (channel, progress) = tuple;
|
var channel = pair.Channel;
|
||||||
|
var progress = pair.Progress;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -86,15 +86,8 @@ public class ExportSetupViewModel : DialogScreen
|
||||||
|
|
||||||
public void ToggleAdvancedSection() => IsAdvancedSectionDisplayed = !IsAdvancedSectionDisplayed;
|
public void ToggleAdvancedSection() => IsAdvancedSectionDisplayed = !IsAdvancedSectionDisplayed;
|
||||||
|
|
||||||
public void Confirm()
|
public void ShowOutputPathPrompt()
|
||||||
{
|
{
|
||||||
// Persist preferences
|
|
||||||
_settingsService.LastExportFormat = SelectedFormat;
|
|
||||||
_settingsService.LastPartitionLimitValue = PartitionLimitValue;
|
|
||||||
_settingsService.LastMessageFilterValue = MessageFilterValue;
|
|
||||||
_settingsService.LastShouldDownloadAssets = ShouldDownloadAssets;
|
|
||||||
|
|
||||||
// If single channel - prompt file path
|
|
||||||
if (IsSingleChannel)
|
if (IsSingleChannel)
|
||||||
{
|
{
|
||||||
var defaultFileName = ExportRequest.GetDefaultOutputFileName(
|
var defaultFileName = ExportRequest.GetDefaultOutputFileName(
|
||||||
|
@ -105,20 +98,26 @@ public class ExportSetupViewModel : DialogScreen
|
||||||
Before?.Pipe(Snowflake.FromDate)
|
Before?.Pipe(Snowflake.FromDate)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Filter
|
var extension = SelectedFormat.GetFileExtension();
|
||||||
var ext = SelectedFormat.GetFileExtension();
|
var filter = $"{extension.ToUpperInvariant()} files|*.{extension}";
|
||||||
var filter = $"{ext.ToUpperInvariant()} files|*.{ext}";
|
|
||||||
|
|
||||||
OutputPath = _dialogManager.PromptSaveFilePath(filter, defaultFileName);
|
OutputPath = _dialogManager.PromptSaveFilePath(filter, defaultFileName);
|
||||||
}
|
}
|
||||||
// If multiple channels - prompt dir path
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OutputPath = _dialogManager.PromptDirectoryPath();
|
OutputPath = _dialogManager.PromptDirectoryPath();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(OutputPath))
|
public bool CanConfirm => !string.IsNullOrWhiteSpace(OutputPath);
|
||||||
return;
|
|
||||||
|
public void Confirm()
|
||||||
|
{
|
||||||
|
// Persist preferences
|
||||||
|
_settingsService.LastExportFormat = SelectedFormat;
|
||||||
|
_settingsService.LastPartitionLimitValue = PartitionLimitValue;
|
||||||
|
_settingsService.LastMessageFilterValue = MessageFilterValue;
|
||||||
|
_settingsService.LastShouldDownloadAssets = ShouldDownloadAssets;
|
||||||
|
|
||||||
Close(true);
|
Close(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,86 @@
|
||||||
BorderThickness="0,1">
|
BorderThickness="0,1">
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
|
<!-- Output path -->
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBox
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="16,8,8,8"
|
||||||
|
materialDesign:HintAssist.Hint="Output path"
|
||||||
|
materialDesign:HintAssist.IsFloating="True"
|
||||||
|
Style="{DynamicResource MaterialDesignOutlinedTextBox}"
|
||||||
|
Text="{Binding OutputPath}">
|
||||||
|
<TextBox.ToolTip>
|
||||||
|
<TextBlock>
|
||||||
|
<Run Text="Output file or directory path." />
|
||||||
|
<Run Text="If a directory is specified, file names will be generated automatically based on the channel names and other parameters." />
|
||||||
|
<Run Text="Directory path should end with a slash to avoid ambiguity." />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="Available template tokens:" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%g" />
|
||||||
|
<Run Text="— guild ID" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%G" />
|
||||||
|
<Run Text="— guild name" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%t" />
|
||||||
|
<Run Text="— category ID" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%T" />
|
||||||
|
<Run Text="— category name" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%c" />
|
||||||
|
<Run Text="— channel ID" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%C" />
|
||||||
|
<Run Text="— channel name" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%p" />
|
||||||
|
<Run Text="— channel position" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%P" />
|
||||||
|
<Run Text="— category position" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%a" />
|
||||||
|
<Run Text="— after date" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%b" />
|
||||||
|
<Run Text="— before date" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontWeight="SemiBold" Text="%d" />
|
||||||
|
<Run Text="— current date" />
|
||||||
|
</TextBlock>
|
||||||
|
</TextBox.ToolTip>
|
||||||
|
</TextBox>
|
||||||
|
<Button
|
||||||
|
Grid.Column="1"
|
||||||
|
Height="48"
|
||||||
|
Margin="0,8,16,8"
|
||||||
|
Command="{s:Action ShowOutputPathPrompt}"
|
||||||
|
Style="{DynamicResource MaterialDesignOutlinedButton}">
|
||||||
|
<materialDesign:PackIcon Width="24" Height="24">
|
||||||
|
<materialDesign:PackIcon.Style>
|
||||||
|
<Style TargetType="{x:Type materialDesign:PackIcon}">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding IsSingleChannel}" Value="True">
|
||||||
|
<Setter Property="Kind" Value="FileFind" />
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding IsSingleChannel}" Value="False">
|
||||||
|
<Setter Property="Kind" Value="FolderSearch" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</materialDesign:PackIcon.Style>
|
||||||
|
</materialDesign:PackIcon>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<!-- Format -->
|
<!-- Format -->
|
||||||
<ComboBox
|
<ComboBox
|
||||||
Margin="16,8"
|
Margin="16,8"
|
||||||
|
@ -84,7 +164,8 @@
|
||||||
IsReadOnly="True"
|
IsReadOnly="True"
|
||||||
ItemsSource="{Binding AvailableFormats}"
|
ItemsSource="{Binding AvailableFormats}"
|
||||||
SelectedItem="{Binding SelectedFormat}"
|
SelectedItem="{Binding SelectedFormat}"
|
||||||
Style="{DynamicResource MaterialDesignOutlinedComboBox}">
|
Style="{DynamicResource MaterialDesignOutlinedComboBox}"
|
||||||
|
ToolTip="Export format">
|
||||||
<ComboBox.ItemTemplate>
|
<ComboBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock Text="{Binding Converter={x:Static converters:ExportFormatToStringConverter.Instance}, ConverterCulture={x:Static globalization:CultureInfo.CurrentCulture}}" />
|
<TextBlock Text="{Binding Converter={x:Static converters:ExportFormatToStringConverter.Instance}, ConverterCulture={x:Static globalization:CultureInfo.CurrentCulture}}" />
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
DockPanel.Dock="Left"
|
DockPanel.Dock="Left"
|
||||||
Text="Auto-updates" />
|
Text="Auto-update" />
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
DockPanel.Dock="Left"
|
DockPanel.Dock="Left"
|
||||||
Text="Save token" />
|
Text="Persist token" />
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue