Skip to content

Commit

Permalink
🥁 Remember used output templates
Browse files Browse the repository at this point in the history
While here, clean up and fix the logic for download path history.
  • Loading branch information
database64128 committed May 2, 2023
1 parent a6adc48 commit e37e681
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 28 deletions.
14 changes: 11 additions & 3 deletions YoutubeDl.Wpf/Models/ObservableSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,23 @@ public class ObservableSettings : ReactiveObject
[Reactive]
public string CustomOutputTemplate { get; set; }

/// <summary>
/// Gets the list of used output templates.
/// New templates are appended to the list.
/// </summary>
public List<string> OutputTemplateHistory { get; }

[Reactive]
public bool UseCustomPath { get; set; }

[Reactive]
public string DownloadPath { get; set; }

/// <summary>
/// Gets the list of download path history.
/// New paths are always appended to the list.
/// Gets the list of used download paths.
/// New paths are appended to the list.
/// </summary>
public List<string> DownloadPathHistory { get; set; }
public List<string> DownloadPathHistory { get; }

public ObservableSettings(Settings settings)
{
Expand All @@ -120,6 +126,7 @@ public ObservableSettings(Settings settings)
DownloadPlaylist = settings.DownloadPlaylist;
UseCustomOutputTemplate = settings.UseCustomOutputTemplate;
CustomOutputTemplate = settings.CustomOutputTemplate;
OutputTemplateHistory = new(settings.OutputTemplateHistory);
UseCustomPath = settings.UseCustomPath;
DownloadPath = settings.DownloadPath;
DownloadPathHistory = new(settings.DownloadPathHistory);
Expand Down Expand Up @@ -149,6 +156,7 @@ public void UpdateAppSettings()
AppSettings.UseCustomOutputTemplate = UseCustomOutputTemplate;
AppSettings.CustomOutputTemplate = CustomOutputTemplate;
AppSettings.UseCustomPath = UseCustomPath;
AppSettings.OutputTemplateHistory = OutputTemplateHistory.ToArray();
AppSettings.DownloadPath = DownloadPath;
AppSettings.DownloadPathHistory = DownloadPathHistory.ToArray();
}
Expand Down
2 changes: 2 additions & 0 deletions YoutubeDl.Wpf/Models/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public class Settings

public string CustomOutputTemplate { get; set; } = DefaultCustomFilenameTemplate;

public string[] OutputTemplateHistory { get; set; } = Array.Empty<string>();

public bool UseCustomPath { get; set; }

public string DownloadPath { get; set; } = "";
Expand Down
70 changes: 51 additions & 19 deletions YoutubeDl.Wpf/ViewModels/HomeViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using YoutubeDl.Wpf.Models;
using YoutubeDl.Wpf.Utils;

Expand All @@ -34,19 +36,26 @@ public class HomeViewModel : ReactiveValidationObject

public ObservableCollection<Preset> Presets { get; } = new();

/// <summary>
/// Gets the output template history.
/// This collection was first constructed from <see cref="ObservableSettings.OutputTemplateHistory"/> in reverse order.
/// So the newest template is always the first element.
/// </summary>
public ObservableCollection<HistoryItemViewModel> OutputTemplateHistory { get; }

/// <summary>
/// Gets the download path history.
/// This collection was first constructed from <see cref="ObservableSettings.DownloadPathHistory"/> in reverse order.
/// So the newest path is always the first element.
/// </summary>
public ObservableCollection<HistoryItemViewModel> DownloadPathHistory { get; } = new();
public ObservableCollection<HistoryItemViewModel> DownloadPathHistory { get; }

/// <summary>
/// Gets the collection of view models of the arguments area.
/// A view model in this collection must be of either
/// <see cref="ArgumentChipViewModel"/> or <see cref="AddArgumentViewModel"/> type.
/// </summary>
public ObservableCollection<object> DownloadArguments { get; } = new();
public ObservableCollection<object> DownloadArguments { get; }

[Reactive]
public string Link { get; set; } = "";
Expand Down Expand Up @@ -113,10 +122,12 @@ public HomeViewModel(ObservableSettings settings, BackendService backendService,
Presets.AddRange(Preset.PredefinedPresets.Where(x => (x.SupportedBackends & SharedSettings.Backend) == SharedSettings.Backend));
});

DownloadPathHistory.AddRange(SharedSettings.DownloadPathHistory.Select(x => new HistoryItemViewModel(x, DeleteDownloadPathItem)).Reverse());

DownloadArguments.AddRange(SharedSettings.BackendDownloadArguments.Select(x => new ArgumentChipViewModel(x, true, DeleteArgumentChip)));
DownloadArguments.Add(new AddArgumentViewModel(AddArgument));
OutputTemplateHistory = new(SharedSettings.OutputTemplateHistory.Select(x => new HistoryItemViewModel(x, DeleteOutputTemplateItem)).Reverse());
DownloadPathHistory = new(SharedSettings.DownloadPathHistory.Select(x => new HistoryItemViewModel(x, DeleteDownloadPathItem)).Reverse());
DownloadArguments = new(SharedSettings.BackendDownloadArguments.Select(x => new ArgumentChipViewModel(x, true, DeleteArgumentChip)))
{
new AddArgumentViewModel(AddArgument),
};

var gdaA = this.WhenAnyValue(
x => x.SharedSettings.Backend,
Expand Down Expand Up @@ -164,15 +175,18 @@ public HomeViewModel(ObservableSettings settings, BackendService backendService,

var canRun = this.WhenAnyValue(
x => x.Link,
x => x.BackendInstance.IsRunning,
x => x.SharedSettings.UseCustomOutputTemplate,
x => x.SharedSettings.UseCustomPath,
x => x.SharedSettings.CustomOutputTemplate,
x => x.SharedSettings.DownloadPath,
x => x.SharedSettings.BackendPath,
x => x.BackendInstance.IsRunning,
(link, useCustomPath, downloadPath, dlBinaryPath, isRunning) =>
(link, isRunning, useCustomOutputTemplate, useCustomPath, outputTemplate, downloadPath, backendPath) =>
!string.IsNullOrEmpty(link) &&
!isRunning &&
(!useCustomOutputTemplate || !string.IsNullOrEmpty(outputTemplate)) &&
(!useCustomPath || Directory.Exists(downloadPath)) &&
!string.IsNullOrEmpty(dlBinaryPath) &&
!isRunning);
!string.IsNullOrEmpty(backendPath));

var canAbort = this.WhenAnyValue(x => x.BackendInstance.IsRunning);

Expand All @@ -187,7 +201,7 @@ public HomeViewModel(ObservableSettings settings, BackendService backendService,
ResetCustomFilenameTemplateCommand = ReactiveCommand.Create(ResetCustomFilenameTemplate, canResetCustomFilenameTemplate);
BrowseDownloadFolderCommand = ReactiveCommand.Create(BrowseDownloadFolder, canBrowseDownloadFolder);
OpenDownloadFolderCommand = ReactiveCommand.Create(OpenDownloadFolder, canOpenDownloadFolder);
StartDownloadCommand = ReactiveCommand.CreateFromTask<string>(BackendInstance.StartDownloadAsync, canRun);
StartDownloadCommand = ReactiveCommand.CreateFromTask<string>(StartDownloadAsync, canRun);
ListFormatsCommand = ReactiveCommand.CreateFromTask<string>(BackendInstance.ListFormatsAsync, canRun);
AbortCommand = ReactiveCommand.CreateFromTask(BackendInstance.AbortAsync, canAbort);

Expand Down Expand Up @@ -237,17 +251,29 @@ private void DeleteCustomPreset()
SharedSettings.SelectedPreset = Presets.First();
}

private void DeleteOutputTemplateItem(HistoryItemViewModel item)
{
SharedSettings.OutputTemplateHistory.Remove(item.Text);
OutputTemplateHistory.Remove(item);
}

private void DeleteDownloadPathItem(HistoryItemViewModel item)
{
SharedSettings.DownloadPathHistory.Remove(item.Text);
DownloadPathHistory.Remove(item);
}

private void UpdateOutputTemplateHistory()
{
if (!SharedSettings.OutputTemplateHistory.Contains(SharedSettings.CustomOutputTemplate))
{
SharedSettings.OutputTemplateHistory.Add(SharedSettings.CustomOutputTemplate);
OutputTemplateHistory.Insert(0, new(SharedSettings.CustomOutputTemplate, DeleteOutputTemplateItem));
}
}

private void UpdateDownloadPathHistory()
{
// No need to check if path is null or empty.
// Because this code path can only be reached
// when custom path is toggled and a valid path is supplied.
if (!SharedSettings.DownloadPathHistory.Contains(SharedSettings.DownloadPath))
{
SharedSettings.DownloadPathHistory.Add(SharedSettings.DownloadPath);
Expand Down Expand Up @@ -337,11 +363,6 @@ private void GenerateDownloadArguments()

BackendInstance.GenerateDownloadArguments();

if (SharedSettings.UseCustomPath)
{
UpdateDownloadPathHistory();
}

var pos = _globalArgCount;

foreach (var arg in BackendInstance.GeneratedDownloadArguments)
Expand All @@ -350,5 +371,16 @@ private void GenerateDownloadArguments()
pos++;
}
}

private Task StartDownloadAsync(string link, CancellationToken cancellationToken = default)
{
if (SharedSettings.UseCustomOutputTemplate)
UpdateOutputTemplateHistory();

if (SharedSettings.UseCustomPath)
UpdateDownloadPathHistory();

return BackendInstance.StartDownloadAsync(link, cancellationToken);
}
}
}
17 changes: 13 additions & 4 deletions YoutubeDl.Wpf/Views/HomeView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,19 @@
<ToggleButton x:Name="filenameTemplateToggle"
Margin="4"/>
<TextBlock VerticalAlignment="Center" Margin="4">Custom filename template</TextBlock>
<TextBox x:Name="filenameTemplateTextBox"
Margin="4"
Width="200"
VerticalAlignment="Center"/>
<ComboBox x:Name="outputTemplateComboBox"
IsEditable="True"
IsReadOnly="False"
StaysOpenOnEdit="True"
Margin="4"
Width="200"
VerticalAlignment="Center">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
<Button x:Name="resetFilenameTemplateButton"
Margin="4"
Style="{StaticResource MaterialDesignFlatButton}"
Expand Down
9 changes: 7 additions & 2 deletions YoutubeDl.Wpf/Views/HomeView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,17 @@ public HomeView()

this.OneWayBind(ViewModel,
viewModel => viewModel.SharedSettings.UseCustomOutputTemplate,
view => view.filenameTemplateTextBox.IsEnabled)
view => view.outputTemplateComboBox.IsEnabled)
.DisposeWith(disposables);

this.OneWayBind(ViewModel,
viewModel => viewModel.OutputTemplateHistory,
view => view.outputTemplateComboBox.ItemsSource)
.DisposeWith(disposables);

this.Bind(ViewModel,
viewModel => viewModel.SharedSettings.CustomOutputTemplate,
view => view.filenameTemplateTextBox.Text)
view => view.outputTemplateComboBox.Text)
.DisposeWith(disposables);

// Options row 3
Expand Down

0 comments on commit e37e681

Please sign in to comment.