1.0-dev9 (Videos list improvements and queue bugs removed)

This commit is contained in:
2022-03-02 01:36:26 +01:00
Unverified
parent b08ec52861
commit 25041f9d43
12 changed files with 191 additions and 146 deletions

View File

@@ -59,8 +59,8 @@ At the moment, the application is in the **early stage of development**. Only so
#### App development plans #### App development plans
- **1.0-prerelease1** - with Twitch support only, all video and playlist download options and playlist subscription (Q1/Q2 2022) - **1.0-prerelease1** - with Twitch support only, all video and playlist download options and playlist subscription *[Q2 2022]*
- **1.0-prerelease2** - Youtube support and issues from 1.0-prelease1 closed *[Q2 2022]* - **1.0-prerelease2** - Youtube support and issues from 1.0-prelease1 closed *[Q3 2022]*
- **1.0** - issues from 1.0-prelease2 closed and support for Polish (and maybe German) language *[Q3 2022]* - **1.0** - issues from 1.0-prelease2 closed and support for Polish (and maybe German) language *[Q3 2022]*
- **1.?** - new video services and language support and closing issues from previous versions. *[?]* - **1.?** - new video services and language support and closing issues from previous versions. *[?]*
- **2.0** - switch from Universal Windows Platform to Windows App SDK *[when Windows App SDK will be more developed and will offer elements which I use in UWP (e.g. Mica)]* - **2.0** - switch from Universal Windows Platform to Windows App SDK *[when Windows App SDK will be more developed and will offer elements which I use in UWP (e.g. Mica)]*

View File

@@ -231,7 +231,6 @@ namespace VDownload.Core.Services.Sources.Twitch
// Get playlist // Get playlist
string response = await client.DownloadStringTaskAsync(streamUrl); string response = await client.DownloadStringTaskAsync(streamUrl);
Debug.WriteLine(response);
// Create dictionary // Create dictionary
List<(Uri ChunkUrl, TimeSpan ChunkDuration)> chunks = new List<(Uri ChunkUrl, TimeSpan ChunkDuration)>(); List<(Uri ChunkUrl, TimeSpan ChunkDuration)> chunks = new List<(Uri ChunkUrl, TimeSpan ChunkDuration)>();

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VDownload.Core.Services
{
public class TaskId
{
// VARIABLES
private static readonly Random Random = new Random();
private static readonly char[] CharsID = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
private static readonly int LengthID = 10;
private static readonly List<string> UsedIDs = new List<string>();
// METHOD
public static string Get()
{
string id;
do
{
id = "";
while (id.Length < LengthID)
{
id += CharsID[Random.Next(0, CharsID.Length)];
}
} while (UsedIDs.Contains(id));
UsedIDs.Add(id);
return id;
}
public static void Dispose(string id)
{
UsedIDs.Remove(id);
}
}
}

View File

@@ -145,6 +145,7 @@
<Compile Include="Services\Sources\Twitch\Channel.cs" /> <Compile Include="Services\Sources\Twitch\Channel.cs" />
<Compile Include="Services\Sources\Twitch\Clip.cs" /> <Compile Include="Services\Sources\Twitch\Clip.cs" />
<Compile Include="Services\Sources\Twitch\Vod.cs" /> <Compile Include="Services\Sources\Twitch\Vod.cs" />
<Compile Include="Services\TaskId.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform"> <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">

View File

@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 6667 6667" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><path d="M5899.29,2.12l757.274,756.327l-5905.76,5897.97l-757.274,-756.328l5905.76,-5897.97Z" style="fill:#f44336;fill-rule:nonzero;"/><path d="M6656.01,5900.61l-757.241,756.057l-5904.98,-5899.05l757.241,-756.057l5904.98,5899.05Z" style="fill:#f44336;fill-rule:nonzero;"/></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="1600px" height="1600px"><g fill="#f44336"><path d="m20.132 17.303-13.435-13.435c-.586-.586-1.536-.586-2.121 0l-.708.707c-.586.586-.586 1.536 0 2.121l13.435 13.435c.586.586 1.536.586 2.121 0l.707-.707c.587-.585.587-1.535.001-2.121z"/><path d="m17.303 3.868-13.435 13.435c-.586.586-.586 1.536 0 2.121l.707.707c.586.586 1.536.586 2.121 0l13.436-13.434c.586-.586.586-1.536 0-2.121l-.707-.707c-.586-.587-1.536-.587-2.122-.001z"/></g></svg>

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 502 B

View File

@@ -140,10 +140,10 @@
<Compile Include="Views\Home\HomeVideoAddingPanel.xaml.cs"> <Compile Include="Views\Home\HomeVideoAddingPanel.xaml.cs">
<DependentUpon>HomeVideoAddingPanel.xaml</DependentUpon> <DependentUpon>HomeVideoAddingPanel.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\Home\HomeVideosList.cs" />
<Compile Include="Views\Home\HomeVideoPanel.xaml.cs"> <Compile Include="Views\Home\HomeVideoPanel.xaml.cs">
<DependentUpon>HomeVideoPanel.xaml</DependentUpon> <DependentUpon>HomeVideoPanel.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\Home\HomeVideosList.cs" />
<Compile Include="Views\MainPage.xaml.cs"> <Compile Include="Views\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon> <DependentUpon>MainPage.xaml</DependentUpon>
</Compile> </Compile>

View File

@@ -59,7 +59,9 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- VIDEOS LIST --> <!-- VIDEOS LIST -->
<StackPanel x:Name="HomeVideosList"/> <ScrollViewer Margin="0,0,0,10" CornerRadius="{ThemeResource ControlCornerRadius}">
<StackPanel x:Name="HomeVideosList" Spacing="10"/>
</ScrollViewer>
<!-- OPTIONS BAR AND ADDING PANEL --> <!-- OPTIONS BAR AND ADDING PANEL -->
<Grid Grid.Row="1" CornerRadius="{ThemeResource ControlCornerRadius}" Background="{ThemeResource HomeBackgroundColor}"> <Grid Grid.Row="1" CornerRadius="{ThemeResource ControlCornerRadius}" Background="{ThemeResource HomeBackgroundColor}">

View File

@@ -1,17 +1,21 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using VDownload.Core.Enums; using VDownload.Core.Enums;
using VDownload.Core.EventArgsObjects; using VDownload.Core.EventArgsObjects;
using VDownload.Core.Exceptions; using VDownload.Core.Exceptions;
using VDownload.Core.Interfaces; using VDownload.Core.Interfaces;
using VDownload.Core.Services; using VDownload.Core.Services;
using Windows.ApplicationModel.Resources; using Windows.ApplicationModel.Resources;
using Windows.UI.Core;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
namespace VDownload.Views.Home namespace VDownload.Views.Home
{ {
@@ -34,13 +38,26 @@ namespace VDownload.Views.Home
private readonly Microsoft.UI.Xaml.Controls.ProgressRing HomeOptionsBarSearchingStatusProgressRing = new Microsoft.UI.Xaml.Controls.ProgressRing { Width = 15, Height = 15, Margin = new Thickness(5), IsActive = true }; private readonly Microsoft.UI.Xaml.Controls.ProgressRing HomeOptionsBarSearchingStatusProgressRing = new Microsoft.UI.Xaml.Controls.ProgressRing { Width = 15, Height = 15, Margin = new Thickness(5), IsActive = true };
private readonly Image HomeOptionsBarSearchingStatusErrorImage = new Image { Width = 15, Height = 15, Margin = new Thickness(5), Source = (SvgImageSource)new ResourceDictionary { Source = new Uri("ms-appx:///Resources/Icons.xaml") }["ErrorIcon"] }; private readonly Image HomeOptionsBarSearchingStatusErrorImage = new Image { Width = 15, Height = 15, Margin = new Thickness(5), Source = (SvgImageSource)new ResourceDictionary { Source = new Uri("ms-appx:///Resources/Icons.xaml") }["ErrorIcon"] };
CancellationTokenSource SearchingCancellationToken = new CancellationTokenSource(); // CANCELLATON TOKEN
private CancellationTokenSource SearchingCancellationToken = new CancellationTokenSource();
// HOME VIDEOS LIST
private static StackPanel HomeVideosListOldPanel = null;
public static List<HomeVideoPanel> VideoPanelsList = new List<HomeVideoPanel>();
#endregion #endregion
#region BUTTONS EVENTS #region EVENT HANDLERS VOIDS
// ON NAVIGATED TO
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
if (HomeVideosListOldPanel != null) HomeVideosListOldPanel.Children.Clear();
HomeVideosListOldPanel = HomeVideosList;
foreach (HomeVideoPanel homeVideoPanel in VideoPanelsList) HomeVideosList.Children.Add(homeVideoPanel);
}
// ADD VIDEO BUTTON CHECKED // ADD VIDEO BUTTON CHECKED
private void HomeOptionsBarAddVideoButton_Checked(object sender, RoutedEventArgs e) private void HomeOptionsBarAddVideoButton_Checked(object sender, RoutedEventArgs e)
@@ -159,13 +176,13 @@ namespace VDownload.Views.Home
videoPanel.VideoRemovingRequested += (s, a) => videoPanel.VideoRemovingRequested += (s, a) =>
{ {
// Remove video panel/task from videos list // Remove video panel/task from videos list
VideoPanelsList.Remove(videoPanel);
HomeVideosList.Children.Remove(videoPanel); HomeVideosList.Children.Remove(videoPanel);
Home.HomeVideosList.VideoList.Remove(videoPanel);
}; };
// Add video panel/task to videos list // Add video panel/task to videos list
HomeVideosList.Children.Add(videoPanel); HomeVideosList.Children.Add(videoPanel);
Home.HomeVideosList.VideoList.Add(videoPanel); VideoPanelsList.Add(videoPanel);
} }
@@ -277,12 +294,32 @@ namespace VDownload.Views.Home
HomeOptionsBarSearchingStatusControl.Content = null; HomeOptionsBarSearchingStatusControl.Content = null;
} }
// DOWNLOAD ALL BUTTON CLICKED // DOWNLOAD ALL BUTTON CLICKED
private async void HomeOptionsBarDownloadAllButton_Click(object sender, RoutedEventArgs e) private async void HomeOptionsBarDownloadAllButton_Click(object sender, RoutedEventArgs e)
{ {
foreach (HomeVideoPanel videoPanel in Home.HomeVideosList.VideoList.Where(video => video.VideoStatus == VideoStatus.Idle)) await videoPanel.Start(); foreach (HomeVideoPanel videoPanel in HomeVideosList.Children.Where(video => ((HomeVideoPanel)video).VideoStatus == VideoStatus.Idle))
{
await Task.Delay(50);
videoPanel.Start();
}
} }
#endregion #endregion
}
#region METHODS
// WAIT IN QUEUE
public static async Task WaitInQueue(CancellationToken token)
{
while (VideoPanelsList.Where(video => video.VideoStatus == VideoStatus.InProgress).Count() >= (int)Config.GetValue("max_active_video_task") && !token.IsCancellationRequested)
{
await Task.Delay(50);
}
}
#endregion
}
} }

View File

@@ -86,6 +86,7 @@ namespace VDownload.Views.Home
{ new Regex(@"<duration:(?<format>.*)>"), VideoService.Duration }, { new Regex(@"<duration:(?<format>.*)>"), VideoService.Duration },
}; };
foreach (KeyValuePair<Regex, IFormattable> template in filenameFormatTemplates) foreach (Match templateMatch in template.Key.Matches(temporaryFilename)) temporaryFilename = temporaryFilename.Replace(templateMatch.Value, template.Value.ToString(templateMatch.Groups["format"].Value, null)); foreach (KeyValuePair<Regex, IFormattable> template in filenameFormatTemplates) foreach (Match templateMatch in template.Key.Matches(temporaryFilename)) temporaryFilename = temporaryFilename.Replace(templateMatch.Value, template.Value.ToString(templateMatch.Groups["format"].Value, null));
foreach (char c in System.IO.Path.GetInvalidFileNameChars()) temporaryFilename = temporaryFilename.Replace(c, ' ');
HomeVideoAddingFilenameTextBox.Text = temporaryFilename; HomeVideoAddingFilenameTextBox.Text = temporaryFilename;
Filename = temporaryFilename; Filename = temporaryFilename;

View File

@@ -6,6 +6,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d" mc:Ignorable="d"
CornerRadius="{ThemeResource ControlCornerRadius}"
d:DesignHeight="150" d:DesignHeight="150"
d:DesignWidth="800"> d:DesignWidth="800">
@@ -20,7 +21,7 @@
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid Background="{ThemeResource HomeBackgroundColor}" Padding="10" ColumnSpacing="10"> <Grid Background="{ThemeResource HomeBackgroundColor}" CornerRadius="{ThemeResource ControlCornerRadius}" Padding="10" ColumnSpacing="10">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition/> <RowDefinition/>
<RowDefinition/> <RowDefinition/>

View File

@@ -129,10 +129,14 @@ namespace VDownload.Views.Home
HomeVideoPanelStateProgressBar.IsIndeterminate = true; HomeVideoPanelStateProgressBar.IsIndeterminate = true;
// Wait in queue // Wait in queue
await HomeVideosList.WaitInQueue(CancellationTokenSource.Token); await HomeMain.WaitInQueue(CancellationTokenSource.Token);
if (!CancellationTokenSource.IsCancellationRequested)
{
// Set video status
VideoStatus = VideoStatus.InProgress;
// Get task unique ID // Get task unique ID
string uniqueID = HomeVideosList.GetUniqueID(); string uniqueID = TaskId.Get();
// Get temporary folder // Get temporary folder
StorageFolder tempFolder; StorageFolder tempFolder;
@@ -147,9 +151,6 @@ namespace VDownload.Views.Home
// Set cancellation token to throw exception on request // Set cancellation token to throw exception on request
CancellationTokenSource.Token.ThrowIfCancellationRequested(); CancellationTokenSource.Token.ThrowIfCancellationRequested();
// Set video status
VideoStatus = VideoStatus.InProgress;
// Start stopwatch // Start stopwatch
Stopwatch taskStopwatch = Stopwatch.StartNew(); Stopwatch taskStopwatch = Stopwatch.StartNew();
@@ -200,6 +201,7 @@ namespace VDownload.Views.Home
// Move to output location // Move to output location
StorageFile outputFile; StorageFile outputFile;
Debug.WriteLine($"{Filename}.{Extension.ToString().ToLower()}");
if (Location != null) outputFile = await Location.CreateFileAsync($"{Filename}.{Extension.ToString().ToLower()}", (bool)Config.GetValue("replace_output_file_if_exists") ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.GenerateUniqueName); if (Location != null) outputFile = await Location.CreateFileAsync($"{Filename}.{Extension.ToString().ToLower()}", (bool)Config.GetValue("replace_output_file_if_exists") ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.GenerateUniqueName);
else outputFile = await DownloadsFolder.CreateFileAsync($"{Filename}.{Extension.ToString().ToLower()}", (bool)Config.GetValue("replace_output_file_if_exists") ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.GenerateUniqueName); else outputFile = await DownloadsFolder.CreateFileAsync($"{Filename}.{Extension.ToString().ToLower()}", (bool)Config.GetValue("replace_output_file_if_exists") ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.GenerateUniqueName);
await tempOutputFile.MoveAndReplaceAsync(outputFile); await tempOutputFile.MoveAndReplaceAsync(outputFile);
@@ -220,7 +222,8 @@ namespace VDownload.Views.Home
HomeVideoPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextCancelled"); HomeVideoPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextCancelled");
HomeVideoPanelStateProgressBar.Visibility = Visibility.Collapsed; HomeVideoPanelStateProgressBar.Visibility = Visibility.Collapsed;
} }
finally
{
// Change icon // Change icon
HomeVideoPanelStartStopButton.Icon = new SymbolIcon(Symbol.Download); HomeVideoPanelStartStopButton.Icon = new SymbolIcon(Symbol.Download);
@@ -231,7 +234,16 @@ namespace VDownload.Views.Home
await tempFolder.DeleteAsync(); await tempFolder.DeleteAsync();
// Dispose unique id // Dispose unique id
HomeVideosList.DisposeUniqueID(uniqueID); TaskId.Dispose(uniqueID);
}
}
else
{
// Set state controls
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateCancelledIcon"];
HomeVideoPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextCancelled");
HomeVideoPanelStateProgressBar.Visibility = Visibility.Collapsed;
}
} }
#endregion #endregion

View File

@@ -1,58 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using VDownload.Core.Services;
namespace VDownload.Views.Home namespace VDownload.Views.Home
{ {
public class HomeVideosList public class HomeVideosList
{ {
// VIDEO OBJECTS LIST
public static List<HomeVideoPanel> VideoList = new List<HomeVideoPanel>();
// WAIT IN QUEUE
public static async Task WaitInQueue(CancellationToken token)
{
await Task.Run(async () =>
{
while (!(VideoList.Where(video => video.VideoStatus == Core.Enums.VideoStatus.InProgress).Count() < (int)Config.GetValue("max_active_video_task")) && !token.IsCancellationRequested)
{
await Task.Delay(50);
}
});
}
#region GET UNIQUE ID
// VARIABLES
private static readonly Random Random = new Random();
private static readonly char[] CharsID = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
private static readonly int LengthID = 10;
private static readonly List<string> UsedIDs = new List<string>();
// METHOD
public static string GetUniqueID()
{
string id;
do
{
id = "";
while (id.Length < LengthID)
{
id += CharsID[Random.Next(0, CharsID.Length)];
}
} while (UsedIDs.Contains(id));
UsedIDs.Add(id);
return id;
}
public static void DisposeUniqueID(string id)
{
UsedIDs.Remove(id);
}
#endregion
} }
} }