Skip to content

Commit

Permalink
Add right-click menu to task queue (#927)
Browse files Browse the repository at this point in the history
* Add ITwitchTask.CanCancel and ITwitchTask.OutputFile

* Remove now redundant try-catch

* Bind task cancel button enabled-ness to CanCancel
Also update task button method names

* PagChatRender.xaml Solid_ExclamationTriangle -> Solid_ExclamationCircle

* Add Cancel, Error, Remove, and Open Folder items to task queue context menu

* Update translations
  • Loading branch information
ScrubN authored Jan 5, 2024
1 parent 0db1b36 commit 092db64
Show file tree
Hide file tree
Showing 18 changed files with 229 additions and 30 deletions.
2 changes: 1 addition & 1 deletion TwitchDownloaderWPF/PageChatRender.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
<TabItem Header="{lex:Loc RenderTabFfmpeg}" Background="{DynamicResource AppBackground}" Foreground="{DynamicResource AppText}">
<StackPanel Orientation="Vertical" Background="{DynamicResource AppBackground}" Margin="5,10,5,5">
<WrapPanel Orientation="Horizontal">
<fa:SvgAwesome Icon="Solid_ExclamationTriangle" Width="16" Margin="0,0,3,0" Foreground="{DynamicResource AppText}" />
<fa:SvgAwesome Icon="Solid_ExclamationCircle" Width="16" Margin="0,0,3,0" Foreground="{DynamicResource AppText}" />
<TextBlock Text="{lex:Loc RenderFfmpegWarning}" Foreground="{DynamicResource AppInnerText}" FontWeight="Bold" TextWrapping="Wrap" />
</WrapPanel>
<TextBlock Text="{lex:Loc FfmpegInputArguments}" Margin="0,4,0,0" Foreground="{DynamicResource AppText}"></TextBlock>
Expand Down
30 changes: 27 additions & 3 deletions TwitchDownloaderWPF/PageQueue.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,30 @@
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" CornerRadius="8" Margin="8,8,8,8" Padding="4" Background="{DynamicResource AppElementBackground}" BorderBrush="{DynamicResource AppElementBorder}">
<Border.ContextMenu>
<ContextMenu>
<MenuItem Header="{lex:Loc TaskCancel}" Click="MenuItemCancelTask_Click" IsEnabled="{Binding CanCancel}" Foreground="{DynamicResource AppText}">
<MenuItem.Icon>
<fa:SvgAwesome Icon="Solid_StopCircle" Foreground="{DynamicResource AppText}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="{lex:Loc TaskErrorButton}" Click="MenuItemTaskError_Click" Visibility="{Binding Exception.Visibility}" Foreground="{DynamicResource AppText}">
<MenuItem.Icon>
<fa:SvgAwesome Icon="Solid_ExclamationTriangle" Foreground="{DynamicResource AppText}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="{lex:Loc ContextMenuRemoveTask}" Click="MenuItemRemoveTask_Click" Foreground="{DynamicResource AppText}">
<MenuItem.Icon>
<fa:SvgAwesome Icon="Solid_Times" Foreground="{DynamicResource AppText}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="{lex:Loc ContextMenuOpenTaskFolder}" Click="MenuItemOpenTaskFolder_Click" Foreground="{DynamicResource AppText}">
<MenuItem.Icon>
<fa:SvgAwesome Icon="Solid_FolderOpen" Foreground="{DynamicResource AppText}" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Border.ContextMenu>
<Grid Margin="1,1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
Expand All @@ -49,12 +73,12 @@
<TextBlock Text="{Binding TaskType, StringFormat=Task Type: {0}}" Foreground="{DynamicResource AppText}"></TextBlock>
<TextBlock Text="{Binding Status, StringFormat=Status: {0}, Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Foreground="{DynamicResource AppText}"></TextBlock>
<StackPanel Orientation="Horizontal" Margin="1,1,0,1">
<Button Content="{lex:Loc TaskCancel}" Margin="0,0,4,0" MinWidth="60" Height="28" FontSize="12" Click="btnCancelTask_Click" Background="{DynamicResource ActionButtonBackground}" Foreground="{DynamicResource ActionButtonText}" BorderBrush="{DynamicResource ActionButtonBorder}" />
<Button Visibility="{Binding Exception.Visibility}" Content="{lex:Loc TaskErrorButton}" Margin="0,0,4,0" MinWidth="60" Height="28" FontSize="12" Click="btnTaskError_Click" Background="{DynamicResource ActionButtonBackground}" Foreground="{DynamicResource ActionButtonText}" BorderBrush="{DynamicResource ActionButtonBorder}" />
<Button Content="{lex:Loc TaskCancel}" Margin="0,0,4,0" MinWidth="60" Height="28" FontSize="12" Click="BtnCancelTask_Click" IsEnabled="{Binding CanCancel}" Background="{DynamicResource ActionButtonBackground}" Foreground="{DynamicResource ActionButtonText}" BorderBrush="{DynamicResource ActionButtonBorder}" />
<Button Visibility="{Binding Exception.Visibility}" Content="{lex:Loc TaskErrorButton}" Margin="0,0,4,0" MinWidth="60" Height="28" FontSize="12" Click="BtnTaskError_Click" Background="{DynamicResource ActionButtonBackground}" Foreground="{DynamicResource ActionButtonText}" BorderBrush="{DynamicResource ActionButtonBorder}" />
<ProgressBar Height="16" Width="200" Minimum="0" Maximum="100" Value="{Binding Progress, Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Background="{DynamicResource AppElementInnerBackground}" Foreground="{DynamicResource ProgressBarForeground}" />
</StackPanel>
</StackPanel>
<Button Grid.Column="2" Padding="7, 0" VerticalAlignment="Top" Height="24" FontSize="12" Content="X" Click="btnRemoveTask_Click" Background="{DynamicResource AppElementBackground}" Foreground="{DynamicResource AppTextDisabled}" BorderBrush="{DynamicResource AppElementBorder}" />
<Button Grid.Column="2" Padding="7, 0" VerticalAlignment="Top" Height="24" FontSize="12" Content="X" Click="BtnRemoveTask_Click" Background="{DynamicResource AppElementBackground}" Foreground="{DynamicResource AppTextDisabled}" BorderBrush="{DynamicResource AppElementBorder}" />
</Grid>
</Border>
</DataTemplate>
Expand Down
76 changes: 67 additions & 9 deletions TwitchDownloaderWPF/PageQueue.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using TwitchDownloaderWPF.TwitchTasks;
using TwitchDownloaderWPF.Properties;
using System.Diagnostics;
using System.IO;

namespace TwitchDownloaderWPF
{
Expand Down Expand Up @@ -199,38 +200,64 @@ private void btnClips_Click(object sender, RoutedEventArgs e)
window.ShowDialog();
}

private void btnCancelTask_Click(object sender, RoutedEventArgs e)
private void BtnCancelTask_Click(object sender, RoutedEventArgs e)
{
if (!(sender is Button { DataContext: ITwitchTask task } cancelButton))
if (sender is not Button { DataContext: ITwitchTask task })
{
return;
}

cancelButton.IsEnabled = false;
CancelTask(task);
}

if (task.Status is TwitchTaskStatus.Failed or TwitchTaskStatus.Canceled or TwitchTaskStatus.Finished)
private void MenuItemCancelTask_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: ITwitchTask task })
{
return;
}

task.Cancel();
CancelTask(task);
}

private static void CancelTask(ITwitchTask task)
{
if (task.CanCancel)
{
task.Cancel();
}
}

private void btnTaskError_Click(object sender, RoutedEventArgs e)
private void BtnTaskError_Click(object sender, RoutedEventArgs e)
{
if (sender is not Button { DataContext: ITwitchTask task })
{
return;
}

TwitchTaskException taskException = task.Exception;
ShowTaskException(task);
}

private void MenuItemTaskError_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: ITwitchTask task })
{
return;
}

ShowTaskException(task);
}

private static void ShowTaskException(ITwitchTask task)
{
var taskException = task.Exception;

if (taskException?.Exception == null)
{
return;
}

string errorMessage = taskException.Exception.Message;
var errorMessage = taskException.Exception.Message;
if (Settings.Default.VerboseErrors)
{
errorMessage = taskException.Exception.ToString();
Expand All @@ -239,13 +266,28 @@ private void btnTaskError_Click(object sender, RoutedEventArgs e)
MessageBox.Show(errorMessage, Translations.Strings.MessageBoxTitleError, MessageBoxButton.OK, MessageBoxImage.Error);
}

private void btnRemoveTask_Click(object sender, RoutedEventArgs e)
private void BtnRemoveTask_Click(object sender, RoutedEventArgs e)
{
if (sender is not Button { DataContext: ITwitchTask task })
{
return;
}

RemoveTask(task);
}

private void MenuItemRemoveTask_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: ITwitchTask task })
{
return;
}

RemoveTask(task);
}

private static void RemoveTask(ITwitchTask task)
{
if (task.CanRun() || task.Status is TwitchTaskStatus.Running or TwitchTaskStatus.Waiting)
{
MessageBox.Show(Translations.Strings.CancelTaskBeforeRemoving, Translations.Strings.TaskCouldNotBeRemoved, MessageBoxButton.OK, MessageBoxImage.Information);
Expand All @@ -257,5 +299,21 @@ private void btnRemoveTask_Click(object sender, RoutedEventArgs e)
MessageBox.Show(Translations.Strings.TaskCouldNotBeRemoved, Translations.Strings.UnknownErrorOccurred, MessageBoxButton.OK, MessageBoxImage.Error);
}
}

private void MenuItemOpenTaskFolder_Click(object sender, RoutedEventArgs e)
{
if (sender is not MenuItem { DataContext: ITwitchTask task })
{
return;
}

var outputFolder = Path.GetDirectoryName(task.OutputFile);
if (!Directory.Exists(outputFolder))
{
return;
}

Process.Start(new ProcessStartInfo(outputFolder) { UseShellExecute = true });
}
}
}
18 changes: 18 additions & 0 deletions TwitchDownloaderWPF/Translations/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions TwitchDownloaderWPF/Translations/Strings.es.resx
Original file line number Diff line number Diff line change
Expand Up @@ -808,4 +808,11 @@
<data name="ButtonCancelSettingsChanges" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ContextMenuRemoveTask" xml:space="preserve">
<value>Remove</value>
</data>
<data name="ContextMenuOpenTaskFolder" xml:space="preserve">
<value>Open folder
</value>
</data>
</root>
6 changes: 6 additions & 0 deletions TwitchDownloaderWPF/Translations/Strings.fr.resx
Original file line number Diff line number Diff line change
Expand Up @@ -807,4 +807,10 @@
<data name="ButtonCancelSettingsChanges" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ContextMenuRemoveTask" xml:space="preserve">
<value>Remove</value>
</data>
<data name="ContextMenuOpenTaskFolder" xml:space="preserve">
<value>Open folder</value>
</data>
</root>
6 changes: 6 additions & 0 deletions TwitchDownloaderWPF/Translations/Strings.pl.resx
Original file line number Diff line number Diff line change
Expand Up @@ -807,4 +807,10 @@
<data name="ButtonCancelSettingsChanges" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ContextMenuRemoveTask" xml:space="preserve">
<value>Remove</value>
</data>
<data name="ContextMenuOpenTaskFolder" xml:space="preserve">
<value>Open folder</value>
</data>
</root>
6 changes: 6 additions & 0 deletions TwitchDownloaderWPF/Translations/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -806,4 +806,10 @@
<data name="ButtonCancelSettingsChanges" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ContextMenuRemoveTask" xml:space="preserve">
<value>Remove</value>
</data>
<data name="ContextMenuOpenTaskFolder" xml:space="preserve">
<value>Open folder</value>
</data>
</root>
6 changes: 6 additions & 0 deletions TwitchDownloaderWPF/Translations/Strings.ru.resx
Original file line number Diff line number Diff line change
Expand Up @@ -807,4 +807,10 @@
<data name="ButtonCancelSettingsChanges" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ContextMenuRemoveTask" xml:space="preserve">
<value>Remove</value>
</data>
<data name="ContextMenuOpenTaskFolder" xml:space="preserve">
<value>Open folder</value>
</data>
</root>
6 changes: 6 additions & 0 deletions TwitchDownloaderWPF/Translations/Strings.tr.resx
Original file line number Diff line number Diff line change
Expand Up @@ -808,4 +808,10 @@
<data name="ButtonCancelSettingsChanges" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ContextMenuRemoveTask" xml:space="preserve">
<value>Remove</value>
</data>
<data name="ContextMenuOpenTaskFolder" xml:space="preserve">
<value>Open folder</value>
</data>
</root>
6 changes: 6 additions & 0 deletions TwitchDownloaderWPF/Translations/Strings.uk.resx
Original file line number Diff line number Diff line change
Expand Up @@ -807,4 +807,10 @@
<data name="ButtonCancelSettingsChanges" xml:space="preserve">
<value>Скасувати</value>
</data>
<data name="ContextMenuRemoveTask" xml:space="preserve">
<value>Remove</value>
</data>
<data name="ContextMenuOpenTaskFolder" xml:space="preserve">
<value>Open folder</value>
</data>
</root>
6 changes: 6 additions & 0 deletions TwitchDownloaderWPF/Translations/Strings.zh.resx
Original file line number Diff line number Diff line change
Expand Up @@ -806,4 +806,10 @@
<data name="ButtonCancelSettingsChanges" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ContextMenuRemoveTask" xml:space="preserve">
<value>Remove</value>
</data>
<data name="ContextMenuOpenTaskFolder" xml:space="preserve">
<value>Open folder</value>
</data>
</root>
16 changes: 13 additions & 3 deletions TwitchDownloaderWPF/TwitchTasks/ChatDownloadTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ class ChatDownloadTask : ITwitchTask
public ITwitchTask DependantTask { get; set; }
public string TaskType { get; } = Translations.Strings.ChatDownload;
public TwitchTaskException Exception { get; private set; } = new();
public string OutputFile => DownloadOptions.Filename;
public bool CanCancel { get; private set; } = true;

public event PropertyChangedEventHandler PropertyChanged;

public void Cancel()
{
try
if (!CanCancel)
{
TokenSource.Cancel();
return;
}
catch (ObjectDisposedException) { }

TokenSource.Cancel();

if (Status == TwitchTaskStatus.Running)
{
Expand All @@ -46,13 +49,20 @@ public void ChangeStatus(TwitchTaskStatus newStatus)
{
Status = newStatus;
OnPropertyChanged(nameof(Status));

if (CanCancel && newStatus is TwitchTaskStatus.Canceled or TwitchTaskStatus.Failed or TwitchTaskStatus.Finished or TwitchTaskStatus.Stopping)
{
CanCancel = false;
OnPropertyChanged(nameof(CanCancel));
}
}

public async Task RunAsync()
{
if (TokenSource.IsCancellationRequested)
{
TokenSource.Dispose();
ChangeStatus(TwitchTaskStatus.Canceled);
return;
}

Expand Down
16 changes: 13 additions & 3 deletions TwitchDownloaderWPF/TwitchTasks/ChatRenderTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ class ChatRenderTask : ITwitchTask
public ITwitchTask DependantTask { get; set; }
public string TaskType { get; } = Translations.Strings.ChatRender;
public TwitchTaskException Exception { get; private set; } = new();
public string OutputFile => DownloadOptions.OutputFile;
public bool CanCancel { get; private set; } = true;

public event PropertyChangedEventHandler PropertyChanged;

public void Cancel()
{
try
if (!CanCancel)
{
TokenSource.Cancel();
return;
}
catch (ObjectDisposedException) { }

TokenSource.Cancel();

if (Status == TwitchTaskStatus.Running)
{
Expand Down Expand Up @@ -65,13 +68,20 @@ public void ChangeStatus(TwitchTaskStatus newStatus)
{
Status = newStatus;
OnPropertyChanged(nameof(Status));

if (CanCancel && newStatus is TwitchTaskStatus.Canceled or TwitchTaskStatus.Failed or TwitchTaskStatus.Finished or TwitchTaskStatus.Stopping)
{
CanCancel = false;
OnPropertyChanged(nameof(CanCancel));
}
}

public async Task RunAsync()
{
if (TokenSource.IsCancellationRequested)
{
TokenSource.Dispose();
ChangeStatus(TwitchTaskStatus.Canceled);
return;
}

Expand Down
Loading

0 comments on commit 092db64

Please sign in to comment.