1.0-dev7 (Video adding panel added)
@@ -2,11 +2,11 @@
|
|||||||
{
|
{
|
||||||
public enum AudioFileExtension
|
public enum AudioFileExtension
|
||||||
{
|
{
|
||||||
MP3 = 4,
|
MP3 = 3,
|
||||||
FLAC = 5,
|
FLAC = 4,
|
||||||
WAV = 6,
|
WAV = 5,
|
||||||
M4A = 7,
|
M4A = 6,
|
||||||
ALAC = 8,
|
ALAC = 7,
|
||||||
WMA = 9,
|
WMA = 8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
VDownload.Core/Enums/DefaultLocationType.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace VDownload.Core.Enums
|
||||||
|
{
|
||||||
|
public enum DefaultLocationType
|
||||||
|
{
|
||||||
|
Last,
|
||||||
|
Selected
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
{
|
{
|
||||||
public enum MediaType
|
public enum MediaType
|
||||||
{
|
{
|
||||||
AudioVideo,
|
AudioVideo = 0,
|
||||||
OnlyAudio,
|
OnlyAudio = 1,
|
||||||
OnlyVideo,
|
OnlyVideo = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
VDownload.Core/Enums/PlaylistSource.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace VDownload.Core.Enums
|
||||||
|
{
|
||||||
|
public enum PlaylistSource
|
||||||
|
{
|
||||||
|
TwitchChannel,
|
||||||
|
Null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
{
|
{
|
||||||
public enum VideoFileExtension
|
public enum VideoFileExtension
|
||||||
{
|
{
|
||||||
MP4 = 1,
|
MP4 = 0,
|
||||||
WMV = 2,
|
WMV = 1,
|
||||||
HEVC = 3,
|
HEVC = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
VDownload.Core/Enums/VideoSource.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace VDownload.Core.Enums
|
||||||
|
{
|
||||||
|
public enum VideoSource
|
||||||
|
{
|
||||||
|
TwitchVod,
|
||||||
|
TwitchClip,
|
||||||
|
Null
|
||||||
|
}
|
||||||
|
}
|
||||||
20
VDownload.Core/EventArgsObjects/VideoAddEventArgs.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using VDownload.Core.Enums;
|
||||||
|
using VDownload.Core.Interfaces;
|
||||||
|
using VDownload.Core.Objects;
|
||||||
|
using Windows.Storage;
|
||||||
|
|
||||||
|
namespace VDownload.Core.EventArgsObjects
|
||||||
|
{
|
||||||
|
public class VideoAddEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public IVideoService VideoService { get; set; }
|
||||||
|
public MediaType MediaType { get; set; }
|
||||||
|
public Stream Stream { get; set; }
|
||||||
|
public TimeSpan TrimStart { get; set; }
|
||||||
|
public TimeSpan TrimEnd { get; set; }
|
||||||
|
public string Filename { get; set; }
|
||||||
|
public MediaFileExtension Extension { get; set; }
|
||||||
|
public StorageFolder Location { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace VDownload.Core.Interfaces
|
namespace VDownload.Core.Interfaces
|
||||||
{
|
{
|
||||||
internal interface IPlaylistService
|
public interface IPlaylistService
|
||||||
{
|
{
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
@@ -15,9 +16,9 @@ namespace VDownload.Core.Interfaces
|
|||||||
|
|
||||||
#region METHODS
|
#region METHODS
|
||||||
|
|
||||||
Task GetMetadataAsync();
|
Task GetMetadataAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task GetVideosAsync(int numberOfVideos);
|
Task GetVideosAsync(int numberOfVideos, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,16 @@ namespace VDownload.Core.Interfaces
|
|||||||
{
|
{
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
|
// VIDEO PROPERTIES
|
||||||
string ID { get; }
|
string ID { get; }
|
||||||
|
Uri VideoUrl { get; }
|
||||||
string Title { get; }
|
string Title { get; }
|
||||||
string Author { get; }
|
string Author { get; }
|
||||||
DateTime Date { get; }
|
DateTime Date { get; }
|
||||||
TimeSpan Duration { get; }
|
TimeSpan Duration { get; }
|
||||||
long Views { get; }
|
long Views { get; }
|
||||||
Uri Thumbnail { get; }
|
Uri Thumbnail { get; }
|
||||||
|
Stream[] Streams { get; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -27,10 +30,10 @@ namespace VDownload.Core.Interfaces
|
|||||||
#region METHODS
|
#region METHODS
|
||||||
|
|
||||||
// GET VIDEO METADATA
|
// GET VIDEO METADATA
|
||||||
Task GetMetadataAsync();
|
Task GetMetadataAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
// GET VIDEO STREAMS
|
// GET VIDEO STREAMS
|
||||||
Task GetStreamsAsync();
|
Task GetStreamsAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
// DOWNLOAD VIDEO
|
// DOWNLOAD VIDEO
|
||||||
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, Stream audioVideoStream, MediaFileExtension extension, MediaType mediaType, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default);
|
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, Stream audioVideoStream, MediaFileExtension extension, MediaType mediaType, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using VDownload.Core.Enums;
|
||||||
using Windows.Media.Editing;
|
using Windows.Media.Editing;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
|
|
||||||
@@ -24,6 +25,11 @@ namespace VDownload.Core.Services
|
|||||||
{ "media_transcoding_use_mrfcrf444_algorithm", true },
|
{ "media_transcoding_use_mrfcrf444_algorithm", true },
|
||||||
{ "media_editing_algorithm", (int)MediaTrimmingPreference.Fast },
|
{ "media_editing_algorithm", (int)MediaTrimmingPreference.Fast },
|
||||||
{ "default_max_playlist_videos", 0 },
|
{ "default_max_playlist_videos", 0 },
|
||||||
|
{ "default_media_type", (int)MediaType.AudioVideo },
|
||||||
|
{ "default_filename", "[<date_pub:yyyy.MM.dd>] <title>" },
|
||||||
|
{ "default_video_extension", (int)VideoFileExtension.MP4 },
|
||||||
|
{ "default_audio_extension", (int)AudioFileExtension.MP3 },
|
||||||
|
{ "default_location_type", (int)DefaultLocationType.Last },
|
||||||
};
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
55
VDownload.Core/Services/Source.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VDownload.Core.Enums;
|
||||||
|
|
||||||
|
namespace VDownload.Core.Services
|
||||||
|
{
|
||||||
|
public class Source
|
||||||
|
{
|
||||||
|
#region CONSTANTS
|
||||||
|
|
||||||
|
private static readonly (Regex Regex, VideoSource Type)[] VideoSources = new (Regex Regex, VideoSource Type)[]
|
||||||
|
{
|
||||||
|
(new Regex(@"^https://www.twitch.tv/videos/(?<id>\d+)"), VideoSource.TwitchVod),
|
||||||
|
(new Regex(@"^https://www.twitch.tv/\S+/clip/(?<id>[^?]+)"), VideoSource.TwitchClip),
|
||||||
|
(new Regex(@"^https://clips.twitch.tv/(?<id>[^?]+)"), VideoSource.TwitchClip),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly (Regex Regex, PlaylistSource Type)[] PlaylistSources = new (Regex Regex, PlaylistSource Type)[]
|
||||||
|
{
|
||||||
|
(new Regex(@"^https://www.twitch.tv/(?<id>[^?]+)"), PlaylistSource.TwitchChannel),
|
||||||
|
};
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region METHODS
|
||||||
|
|
||||||
|
public static (VideoSource Type, string ID) GetVideoSource(string url)
|
||||||
|
{
|
||||||
|
foreach ((Regex Regex, VideoSource Type) Source in VideoSources)
|
||||||
|
{
|
||||||
|
Match sourceMatch = Source.Regex.Match(url);
|
||||||
|
if (sourceMatch.Success) return (Source.Type, sourceMatch.Groups["id"].Value);
|
||||||
|
}
|
||||||
|
return (VideoSource.Null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (PlaylistSource Type, string ID) GetPlaylistSource(string url)
|
||||||
|
{
|
||||||
|
foreach ((Regex Regex, PlaylistSource Type) Source in PlaylistSources)
|
||||||
|
{
|
||||||
|
Match sourceMatch = Source.Regex.Match(url);
|
||||||
|
if (sourceMatch.Success) return (Source.Type, sourceMatch.Groups["id"].Value);
|
||||||
|
}
|
||||||
|
return (PlaylistSource.Null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -100,9 +100,15 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
|
|
||||||
return (true, login, expirationDate);
|
return (true, login, expirationDate);
|
||||||
}
|
}
|
||||||
catch (WebException)
|
catch (WebException wex)
|
||||||
{
|
{
|
||||||
return (false, null, null);
|
if (wex.Response != null)
|
||||||
|
{
|
||||||
|
JObject wexInfo = JObject.Parse(new StreamReader(wex.Response.GetResponseStream()).ReadToEnd());
|
||||||
|
if ((int)wexInfo["status"] == 401) return (false, null, null);
|
||||||
|
else throw;
|
||||||
|
}
|
||||||
|
else throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using VDownload.Core.Exceptions;
|
using VDownload.Core.Exceptions;
|
||||||
using VDownload.Core.Interfaces;
|
using VDownload.Core.Interfaces;
|
||||||
@@ -37,8 +38,11 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
#region STANDARD METHODS
|
#region STANDARD METHODS
|
||||||
|
|
||||||
// GET CHANNEL METADATA
|
// GET CHANNEL METADATA
|
||||||
public async Task GetMetadataAsync()
|
public async Task GetMetadataAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
// Set cancellation token
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
// Get access token
|
// Get access token
|
||||||
string accessToken = await Auth.ReadAccessTokenAsync();
|
string accessToken = await Auth.ReadAccessTokenAsync();
|
||||||
if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
|
if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
|
||||||
@@ -62,8 +66,11 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GET CHANNEL VIDEOS
|
// GET CHANNEL VIDEOS
|
||||||
public async Task GetVideosAsync(int numberOfVideos)
|
public async Task GetVideosAsync(int numberOfVideos, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
// Set cancellation token
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
// Get access token
|
// Get access token
|
||||||
string accessToken = await Auth.ReadAccessTokenAsync();
|
string accessToken = await Auth.ReadAccessTokenAsync();
|
||||||
if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
|
if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public string ID { get; private set; }
|
public string ID { get; private set; }
|
||||||
|
public Uri VideoUrl { get; private set; }
|
||||||
public string Title { get; private set; }
|
public string Title { get; private set; }
|
||||||
public string Author { get; private set; }
|
public string Author { get; private set; }
|
||||||
public DateTime Date { get; private set; }
|
public DateTime Date { get; private set; }
|
||||||
@@ -56,8 +57,11 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
#region STANDARD METHODS
|
#region STANDARD METHODS
|
||||||
|
|
||||||
// GET CLIP METADATA
|
// GET CLIP METADATA
|
||||||
public async Task GetMetadataAsync()
|
public async Task GetMetadataAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
// Set cancellation token
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
// Get access token
|
// Get access token
|
||||||
string accessToken = await Auth.ReadAccessTokenAsync();
|
string accessToken = await Auth.ReadAccessTokenAsync();
|
||||||
if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
|
if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
|
||||||
@@ -75,6 +79,9 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
client.QueryString.Add("id", ID);
|
client.QueryString.Add("id", ID);
|
||||||
JToken response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/clips")).GetValue("data")[0];
|
JToken response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/clips")).GetValue("data")[0];
|
||||||
|
|
||||||
|
// Create unified video url
|
||||||
|
VideoUrl = new Uri($"https://clips.twitch.tv/{ID}");
|
||||||
|
|
||||||
// Set parameters
|
// Set parameters
|
||||||
Title = (string)response["title"];
|
Title = (string)response["title"];
|
||||||
Author = (string)response["broadcaster_name"];
|
Author = (string)response["broadcaster_name"];
|
||||||
@@ -84,8 +91,11 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
Thumbnail = new Uri((string)response["thumbnail_url"]);
|
Thumbnail = new Uri((string)response["thumbnail_url"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GetStreamsAsync()
|
public async Task GetStreamsAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
// Set cancellation token
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
// Create client
|
// Create client
|
||||||
WebClient client = new WebClient { Encoding = Encoding.UTF8 };
|
WebClient client = new WebClient { Encoding = Encoding.UTF8 };
|
||||||
client.Headers.Add("Client-ID", Auth.GQLApiClientID);
|
client.Headers.Add("Client-ID", Auth.GQLApiClientID);
|
||||||
|
|||||||
@@ -20,16 +20,8 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
{
|
{
|
||||||
#region CONSTANTS
|
#region CONSTANTS
|
||||||
|
|
||||||
// METADATA TIME FORMATS
|
|
||||||
private static readonly string[] TimeFormats = new[]
|
|
||||||
{
|
|
||||||
@"h\hm\ms\s",
|
|
||||||
@"m\ms\s",
|
|
||||||
@"s\s",
|
|
||||||
};
|
|
||||||
|
|
||||||
// STREAMS RESPONSE REGULAR EXPRESSIONS
|
// STREAMS RESPONSE REGULAR EXPRESSIONS
|
||||||
private static readonly Regex L2Regex = new Regex(@"^#EXT-X-STREAM-INF:BANDWIDTH=\d+,CODECS=""(?<video_codec>\S+),(?<audio_codec>\S+)"",RESOLUTION=(?<width>\d+)x(?<height>\d+),VIDEO=""\w+"",FRAME-RATE=(?<frame_rate>\d+.\d+)");
|
private static readonly Regex L2Regex = new Regex(@"^#EXT-X-STREAM-INF:BANDWIDTH=\d+,CODECS=""(?<video_codec>\S+),(?<audio_codec>\S+)"",RESOLUTION=(?<width>\d+)x(?<height>\d+),VIDEO=""\w+""(,FRAME-RATE=(?<frame_rate>\d+.\d+))?");
|
||||||
|
|
||||||
// CHUNK RESPONSE REGULAR EXPRESSION
|
// CHUNK RESPONSE REGULAR EXPRESSION
|
||||||
private static readonly Regex ChunkRegex = new Regex(@"#EXTINF:(?<duration>\d+.\d+),\n(?<filename>\S+.ts)");
|
private static readonly Regex ChunkRegex = new Regex(@"#EXTINF:(?<duration>\d+.\d+),\n(?<filename>\S+.ts)");
|
||||||
@@ -52,6 +44,7 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public string ID { get; private set; }
|
public string ID { get; private set; }
|
||||||
|
public Uri VideoUrl { get; private set; }
|
||||||
public string Title { get; private set; }
|
public string Title { get; private set; }
|
||||||
public string Author { get; private set; }
|
public string Author { get; private set; }
|
||||||
public DateTime Date { get; private set; }
|
public DateTime Date { get; private set; }
|
||||||
@@ -67,8 +60,11 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
#region STANDARD METHODS
|
#region STANDARD METHODS
|
||||||
|
|
||||||
// GET VOD METADATA
|
// GET VOD METADATA
|
||||||
public async Task GetMetadataAsync()
|
public async Task GetMetadataAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
// Set cancellation token
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
// Get access token
|
// Get access token
|
||||||
string accessToken = await Auth.ReadAccessTokenAsync();
|
string accessToken = await Auth.ReadAccessTokenAsync();
|
||||||
if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
|
if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
|
||||||
@@ -91,18 +87,24 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
}
|
}
|
||||||
internal void GetMetadataAsync(JToken response)
|
internal void GetMetadataAsync(JToken response)
|
||||||
{
|
{
|
||||||
|
// Create unified video url
|
||||||
|
VideoUrl = new Uri($"https://www.twitch.tv/videos/{ID}");
|
||||||
|
|
||||||
// Set parameters
|
// Set parameters
|
||||||
Title = ((string)response["title"]).Replace("\n", "");
|
Title = ((string)response["title"]).Replace("\n", "");
|
||||||
Author = (string)response["user_name"];
|
Author = (string)response["user_name"];
|
||||||
Date = Convert.ToDateTime(response["created_at"]);
|
Date = Convert.ToDateTime(response["created_at"]);
|
||||||
Duration = TimeSpan.ParseExact((string)response["duration"], TimeFormats, null);
|
Duration = ParseDuration((string)response["duration"]);
|
||||||
Views = (long)response["view_count"];
|
Views = (long)response["view_count"];
|
||||||
Thumbnail = (string)response["thumbnail_url"] == string.Empty ? null : new Uri((string)response["thumbnail_url"]);
|
Thumbnail = (string)response["thumbnail_url"] == string.Empty ? null : new Uri(((string)response["thumbnail_url"]).Replace("%{width}", "1920").Replace("%{height}", "1080"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET VOD STREAMS
|
// GET VOD STREAMS
|
||||||
public async Task GetStreamsAsync()
|
public async Task GetStreamsAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
// Set cancellation token
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
// Create client
|
// Create client
|
||||||
WebClient client = new WebClient();
|
WebClient client = new WebClient();
|
||||||
client.Headers.Add("Client-Id", Auth.GQLApiClientID);
|
client.Headers.Add("Client-Id", Auth.GQLApiClientID);
|
||||||
@@ -126,7 +128,7 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
Uri url = new Uri(response[i + 2]);
|
Uri url = new Uri(response[i + 2]);
|
||||||
int width = int.Parse(line2.Groups["width"].Value);
|
int width = int.Parse(line2.Groups["width"].Value);
|
||||||
int height = int.Parse(line2.Groups["height"].Value);
|
int height = int.Parse(line2.Groups["height"].Value);
|
||||||
int frameRate = (int)Math.Round(double.Parse(line2.Groups["frame_rate"].Value));
|
int frameRate = line2.Groups["frame_rate"].Value != string.Empty ? (int)Math.Round(double.Parse(line2.Groups["frame_rate"].Value)) : 0;
|
||||||
string videoCodec = line2.Groups["video_codec"].Value;
|
string videoCodec = line2.Groups["video_codec"].Value;
|
||||||
string audioCodec = line2.Groups["audio_codec"].Value;
|
string audioCodec = line2.Groups["audio_codec"].Value;
|
||||||
|
|
||||||
@@ -161,12 +163,7 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
List<(Uri ChunkUrl, TimeSpan ChunkDuration)> chunksList = await ExtractChunksFromM3U8Async(audioVideoStream.Url);
|
List<(Uri ChunkUrl, TimeSpan ChunkDuration)> chunksList = await ExtractChunksFromM3U8Async(audioVideoStream.Url);
|
||||||
|
|
||||||
// Passive trim
|
// Passive trim
|
||||||
if ((bool)Config.GetValue("twitch_vod_passive_trim"))
|
if ((bool)Config.GetValue("twitch_vod_passive_trim")) (trimStart, trimEnd) = PassiveVideoTrim(chunksList, trimStart, trimEnd, Duration);
|
||||||
{
|
|
||||||
var trimResult = PassiveVideoTrim(chunksList, trimStart, trimEnd, Duration);
|
|
||||||
trimStart = trimResult.TrimStart;
|
|
||||||
trimEnd = trimResult.TrimEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Download
|
// Download
|
||||||
StorageFile rawFile = await downloadingFolder.CreateFileAsync("raw.ts");
|
StorageFile rawFile = await downloadingFolder.CreateFileAsync("raw.ts");
|
||||||
@@ -301,6 +298,20 @@ namespace VDownload.Core.Services.Sources.Twitch
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PARSE DURATION TO SECONDS
|
||||||
|
private static TimeSpan ParseDuration(string duration)
|
||||||
|
{
|
||||||
|
char[] separators = { 'h', 'm', 's' };
|
||||||
|
string[] durationParts = duration.Split(separators, StringSplitOptions.RemoveEmptyEntries).Reverse().ToArray();
|
||||||
|
|
||||||
|
TimeSpan timeSpan = new TimeSpan(
|
||||||
|
durationParts.Count() > 2 ? int.Parse(durationParts[2]) : 0,
|
||||||
|
durationParts.Count() > 1 ? int.Parse(durationParts[1]) : 0,
|
||||||
|
int.Parse(durationParts[0]));
|
||||||
|
|
||||||
|
return timeSpan;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -121,10 +121,14 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Enums\AudioFileExtension.cs" />
|
<Compile Include="Enums\AudioFileExtension.cs" />
|
||||||
|
<Compile Include="Enums\DefaultLocationType.cs" />
|
||||||
<Compile Include="Enums\MediaFileExtension.cs" />
|
<Compile Include="Enums\MediaFileExtension.cs" />
|
||||||
<Compile Include="Enums\MediaType.cs" />
|
<Compile Include="Enums\MediaType.cs" />
|
||||||
|
<Compile Include="Enums\PlaylistSource.cs" />
|
||||||
<Compile Include="Enums\StreamType.cs" />
|
<Compile Include="Enums\StreamType.cs" />
|
||||||
<Compile Include="Enums\VideoFileExtension.cs" />
|
<Compile Include="Enums\VideoFileExtension.cs" />
|
||||||
|
<Compile Include="Enums\VideoSource.cs" />
|
||||||
|
<Compile Include="EventArgsObjects\VideoAddEventArgs.cs" />
|
||||||
<Compile Include="EventArgsObjects\VideoSearchEventArgs.cs" />
|
<Compile Include="EventArgsObjects\VideoSearchEventArgs.cs" />
|
||||||
<Compile Include="EventArgsObjects\PlaylistSearchEventArgs.cs" />
|
<Compile Include="EventArgsObjects\PlaylistSearchEventArgs.cs" />
|
||||||
<Compile Include="Exceptions\TwitchAccessTokenNotFoundException.cs" />
|
<Compile Include="Exceptions\TwitchAccessTokenNotFoundException.cs" />
|
||||||
@@ -136,6 +140,7 @@
|
|||||||
<Compile Include="Objects\Stream.cs" />
|
<Compile Include="Objects\Stream.cs" />
|
||||||
<Compile Include="Services\Config.cs" />
|
<Compile Include="Services\Config.cs" />
|
||||||
<Compile Include="Services\MediaProcessor.cs" />
|
<Compile Include="Services\MediaProcessor.cs" />
|
||||||
|
<Compile Include="Services\Source.cs" />
|
||||||
<Compile Include="Services\Sources\Twitch\Auth.cs" />
|
<Compile Include="Services\Sources\Twitch\Auth.cs" />
|
||||||
<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" />
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 48 KiB |
5
VDownload/Assets/Icons/AuthorDark.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600">
|
||||||
|
<g transform="matrix(1.1995,0,0,1.1995,-161.207,-161.6)">
|
||||||
|
<path d="M800,133.333C616.497,133.333 466.667,283.164 466.667,466.667C466.667,650.169 616.497,800 800,800C983.503,800 1133.33,650.169 1133.33,466.667C1133.33,283.164 983.503,133.333 800,133.333ZM800,233.333C929.459,233.333 1033.33,337.208 1033.33,466.667C1033.33,596.125 929.459,700 800,700C670.541,700 566.667,596.125 566.667,466.667C566.667,337.208 670.541,233.333 800,233.333ZM399.284,933.333C326.623,933.333 266.667,993.29 266.667,1065.95L266.667,1116.67C266.667,1236.81 342.642,1329.74 443.555,1385.42C544.467,1441.09 672.27,1466.67 800,1466.67C927.73,1466.67 1055.53,1441.09 1156.44,1385.42C1242.49,1337.94 1307.25,1262.09 1325.39,1166.67L1333.4,1166.67L1333.4,1065.95C1333.4,993.29 1273.38,933.333 1200.72,933.333L399.284,933.333ZM399.284,1033.33L1200.72,1033.33C1219.32,1033.33 1233.4,1047.34 1233.4,1065.95L1233.4,1066.67L1233.33,1066.67L1233.33,1116.67C1233.33,1196.53 1188.48,1253.59 1108.14,1297.92C1027.8,1342.24 913.937,1366.67 800,1366.67C686.063,1366.67 572.2,1342.24 491.862,1297.92C411.524,1253.59 366.667,1196.53 366.667,1116.67L366.667,1065.95C366.667,1047.34 380.678,1033.33 399.284,1033.33Z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
5
VDownload/Assets/Icons/AuthorLight.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600">
|
||||||
|
<g transform="matrix(1.1995,0,0,1.1995,-161.207,-161.6)">
|
||||||
|
<path d="M800,133.333C616.497,133.333 466.667,283.164 466.667,466.667C466.667,650.169 616.497,800 800,800C983.503,800 1133.33,650.169 1133.33,466.667C1133.33,283.164 983.503,133.333 800,133.333ZM800,233.333C929.459,233.333 1033.33,337.208 1033.33,466.667C1033.33,596.125 929.459,700 800,700C670.541,700 566.667,596.125 566.667,466.667C566.667,337.208 670.541,233.333 800,233.333ZM399.284,933.333C326.623,933.333 266.667,993.29 266.667,1065.95L266.667,1116.67C266.667,1236.81 342.642,1329.74 443.555,1385.42C544.467,1441.09 672.27,1466.67 800,1466.67C927.73,1466.67 1055.53,1441.09 1156.44,1385.42C1242.49,1337.94 1307.25,1262.09 1325.39,1166.67L1333.4,1166.67L1333.4,1065.95C1333.4,993.29 1273.38,933.333 1200.72,933.333L399.284,933.333ZM399.284,1033.33L1200.72,1033.33C1219.32,1033.33 1233.4,1047.34 1233.4,1065.95L1233.4,1066.67L1233.33,1066.67L1233.33,1116.67C1233.33,1196.53 1188.48,1253.59 1108.14,1297.92C1027.8,1342.24 913.937,1366.67 800,1366.67C686.063,1366.67 572.2,1342.24 491.862,1297.92C411.524,1253.59 366.667,1196.53 366.667,1116.67L366.667,1065.95C366.667,1047.34 380.678,1033.33 399.284,1033.33Z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
3
VDownload/Assets/Icons/DateDark.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.3325,0,0,1.3325,-266.5,-266.5)">
|
||||||
|
<path d="M416.667,200C297.602,200 200,297.602 200,416.667L200,1183.33C200,1302.4 297.602,1400 416.667,1400L1183.33,1400C1302.4,1400 1400,1302.4 1400,1183.33L1400,416.667C1400,297.602 1302.4,200 1183.33,200L416.667,200ZM416.667,300L1183.33,300C1248.34,300 1300,351.665 1300,416.667L1300,466.667L300,466.667L300,416.667C300,351.665 351.665,300 416.667,300ZM300,566.667L1300,566.667L1300,1183.33C1300,1248.34 1248.34,1300 1183.33,1300L416.667,1300C351.665,1300 300,1248.34 300,1183.33L300,566.667ZM516.667,700C470.951,700 433.333,737.618 433.333,783.333C433.333,829.049 470.951,866.667 516.667,866.667C562.382,866.667 600,829.049 600,783.333C600,737.618 562.382,700 516.667,700ZM800,700C754.285,700 716.667,737.618 716.667,783.333C716.667,829.049 754.285,866.667 800,866.667C845.715,866.667 883.333,829.049 883.333,783.333C883.333,737.618 845.715,700 800,700ZM1083.33,700C1037.62,700 1000,737.618 1000,783.333C1000,829.049 1037.62,866.667 1083.33,866.667C1129.05,866.667 1166.67,829.049 1166.67,783.333C1166.67,737.618 1129.05,700 1083.33,700ZM516.667,1000C470.951,1000 433.333,1037.62 433.333,1083.33C433.333,1129.05 470.951,1166.67 516.667,1166.67C562.382,1166.67 600,1129.05 600,1083.33C600,1037.62 562.382,1000 516.667,1000ZM800,1000C754.285,1000 716.667,1037.62 716.667,1083.33C716.667,1129.05 754.285,1166.67 800,1166.67C845.715,1166.67 883.333,1129.05 883.333,1083.33C883.333,1037.62 845.715,1000 800,1000Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
3
VDownload/Assets/Icons/DateLight.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.3325,0,0,1.3325,-266.5,-266.5)">
|
||||||
|
<path d="M416.667,200C297.602,200 200,297.602 200,416.667L200,1183.33C200,1302.4 297.602,1400 416.667,1400L1183.33,1400C1302.4,1400 1400,1302.4 1400,1183.33L1400,416.667C1400,297.602 1302.4,200 1183.33,200L416.667,200ZM416.667,300L1183.33,300C1248.34,300 1300,351.665 1300,416.667L1300,466.667L300,466.667L300,416.667C300,351.665 351.665,300 416.667,300ZM300,566.667L1300,566.667L1300,1183.33C1300,1248.34 1248.34,1300 1183.33,1300L416.667,1300C351.665,1300 300,1248.34 300,1183.33L300,566.667ZM516.667,700C470.951,700 433.333,737.618 433.333,783.333C433.333,829.049 470.951,866.667 516.667,866.667C562.382,866.667 600,829.049 600,783.333C600,737.618 562.382,700 516.667,700ZM800,700C754.285,700 716.667,737.618 716.667,783.333C716.667,829.049 754.285,866.667 800,866.667C845.715,866.667 883.333,829.049 883.333,783.333C883.333,737.618 845.715,700 800,700ZM1083.33,700C1037.62,700 1000,737.618 1000,783.333C1000,829.049 1037.62,866.667 1083.33,866.667C1129.05,866.667 1166.67,829.049 1166.67,783.333C1166.67,737.618 1129.05,700 1083.33,700ZM516.667,1000C470.951,1000 433.333,1037.62 433.333,1083.33C433.333,1129.05 470.951,1166.67 516.667,1166.67C562.382,1166.67 600,1129.05 600,1083.33C600,1037.62 562.382,1000 516.667,1000ZM800,1000C754.285,1000 716.667,1037.62 716.667,1083.33C716.667,1129.05 754.285,1166.67 800,1166.67C845.715,1166.67 883.333,1129.05 883.333,1083.33C883.333,1037.62 845.715,1000 800,1000Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
3
VDownload/Assets/Icons/DurationDark.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.20025,0,0,1.20025,-163.7,-163.7)">
|
||||||
|
<path d="M800,133.333C432.402,133.333 133.333,432.402 133.333,800C133.333,1167.6 432.402,1466.67 800,1466.67C1167.6,1466.67 1466.67,1167.6 1466.67,800C1466.67,432.402 1167.6,133.333 800,133.333ZM800,233.333C1113.55,233.333 1366.67,486.446 1366.67,800C1366.67,1113.55 1113.55,1366.67 800,1366.67C486.446,1366.67 233.333,1113.55 233.333,800C233.333,486.446 486.446,233.333 800,233.333ZM782.552,399.284C755.148,399.712 732.94,422.595 733.333,450L733.333,850C733.336,877.428 755.905,899.997 783.333,900L1050,900C1050.24,900.003 1050.47,900.005 1050.71,900.005C1078.14,900.005 1100.71,877.432 1100.71,850C1100.71,822.568 1078.14,799.995 1050.71,799.995C1050.47,799.995 1050.24,799.997 1050,800L833.333,800L833.333,450C833.337,449.761 833.338,449.522 833.338,449.283C833.338,421.851 810.765,399.278 783.333,399.278C783.073,399.278 782.813,399.28 782.552,399.284Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
3
VDownload/Assets/Icons/DurationLight.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.20025,0,0,1.20025,-163.7,-163.7)">
|
||||||
|
<path d="M800,133.333C432.402,133.333 133.333,432.402 133.333,800C133.333,1167.6 432.402,1466.67 800,1466.67C1167.6,1466.67 1466.67,1167.6 1466.67,800C1466.67,432.402 1167.6,133.333 800,133.333ZM800,233.333C1113.55,233.333 1366.67,486.446 1366.67,800C1366.67,1113.55 1113.55,1366.67 800,1366.67C486.446,1366.67 233.333,1113.55 233.333,800C233.333,486.446 486.446,233.333 800,233.333ZM782.552,399.284C755.148,399.712 732.94,422.595 733.333,450L733.333,850C733.336,877.428 755.905,899.997 783.333,900L1050,900C1050.24,900.003 1050.47,900.005 1050.71,900.005C1078.14,900.005 1100.71,877.432 1100.71,850C1100.71,822.568 1078.14,799.995 1050.71,799.995C1050.47,799.995 1050.24,799.997 1050,800L833.333,800L833.333,450C833.337,449.761 833.338,449.522 833.338,449.283C833.338,421.851 810.765,399.278 783.333,399.278C783.073,399.278 782.813,399.28 782.552,399.284Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
1
VDownload/Assets/Icons/Error.svg
Normal file
@@ -0,0 +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>
|
||||||
|
After Width: | Height: | Size: 721 B |
3
VDownload/Assets/Icons/FileDark.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.20025,0,0,1.20025,-160.6,-160.7)">
|
||||||
|
<path d="M416.667,133.333C334.417,133.333 266.667,201.083 266.667,283.333L266.667,1316.67C266.667,1398.92 334.417,1466.67 416.667,1466.67L1183.33,1466.67C1265.58,1466.67 1333.33,1398.92 1333.33,1316.67L1333.33,616.667C1333.33,603.412 1328.06,590.687 1318.68,581.315L885.352,147.982C875.98,138.609 863.255,133.336 850,133.333L416.667,133.333ZM416.667,233.333L800,233.333L800,516.667C800,598.917 867.75,666.667 950,666.667L1233.33,666.667L1233.33,1316.67C1233.33,1344.88 1211.55,1366.67 1183.33,1366.67L416.667,1366.67C388.45,1366.67 366.667,1344.88 366.667,1316.67L366.667,283.333C366.667,255.117 388.45,233.333 416.667,233.333ZM900,304.036L1162.63,566.667L950,566.667C921.783,566.667 900,544.883 900,516.667L900,304.036Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 911 B |
3
VDownload/Assets/Icons/FileLight.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.20025,0,0,1.20025,-160.6,-160.7)">
|
||||||
|
<path d="M416.667,133.333C334.417,133.333 266.667,201.083 266.667,283.333L266.667,1316.67C266.667,1398.92 334.417,1466.67 416.667,1466.67L1183.33,1466.67C1265.58,1466.67 1333.33,1398.92 1333.33,1316.67L1333.33,616.667C1333.33,603.412 1328.06,590.687 1318.68,581.315L885.352,147.982C875.98,138.609 863.255,133.336 850,133.333L416.667,133.333ZM416.667,233.333L800,233.333L800,516.667C800,598.917 867.75,666.667 950,666.667L1233.33,666.667L1233.33,1316.67C1233.33,1344.88 1211.55,1366.67 1183.33,1366.67L416.667,1366.67C388.45,1366.67 366.667,1344.88 366.667,1316.67L366.667,283.333C366.667,255.117 388.45,233.333 416.667,233.333ZM900,304.036L1162.63,566.667L950,566.667C921.783,566.667 900,544.883 900,516.667L900,304.036Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 911 B |
3
VDownload/Assets/Icons/LocationDark.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.19956,0,0,1.19956,-159.645,-159.608)">
|
||||||
|
<path d="M800,133.333C487.642,133.333 233.333,387.642 233.333,700C233.333,840.226 284.777,968.828 369.271,1067.71L369.531,1067.97L369.727,1068.23C369.727,1068.23 610.791,1343.3 696.615,1425.19C754.086,1479.99 845.849,1479.99 903.32,1425.19C1001.15,1331.89 1230.34,1068.1 1230.34,1068.1L1230.47,1067.9L1230.66,1067.71C1315.23,968.827 1366.67,840.226 1366.67,700C1366.67,387.642 1112.36,133.333 800,133.333ZM800,233.333C1058.31,233.333 1266.67,441.692 1266.67,700C1266.67,815.84 1224.45,921.086 1154.62,1002.73C1154.17,1003.25 919.668,1271.45 834.31,1352.87C814.514,1371.74 785.421,1371.74 765.625,1352.87C694.286,1284.79 446.037,1003.56 445.313,1002.73L445.247,1002.67C375.511,921.028 333.333,815.808 333.333,700C333.333,441.692 541.692,233.333 800,233.333ZM800,500C737.5,500 684.294,525.238 650.13,563.672C615.967,602.106 600,651.389 600,700C600,748.611 615.967,797.894 650.13,836.328C684.294,874.762 737.5,900 800,900C862.5,900 915.706,874.762 949.87,836.328C984.033,797.894 1000,748.611 1000,700C1000,651.389 984.033,602.106 949.87,563.672C915.706,525.238 862.5,500 800,500ZM800,600C837.5,600 859.294,612.262 875.13,630.078C890.967,647.894 900,673.611 900,700C900,726.389 890.967,752.106 875.13,769.922C859.294,787.738 837.5,800 800,800C762.5,800 740.706,787.738 724.87,769.922C709.033,752.106 700,726.389 700,700C700,673.611 709.033,647.894 724.87,630.078C740.706,612.262 762.5,600 800,600Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
3
VDownload/Assets/Icons/LocationLight.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.19956,0,0,1.19956,-159.645,-159.608)">
|
||||||
|
<path d="M800,133.333C487.642,133.333 233.333,387.642 233.333,700C233.333,840.226 284.777,968.828 369.271,1067.71L369.531,1067.97L369.727,1068.23C369.727,1068.23 610.791,1343.3 696.615,1425.19C754.086,1479.99 845.849,1479.99 903.32,1425.19C1001.15,1331.89 1230.34,1068.1 1230.34,1068.1L1230.47,1067.9L1230.66,1067.71C1315.23,968.827 1366.67,840.226 1366.67,700C1366.67,387.642 1112.36,133.333 800,133.333ZM800,233.333C1058.31,233.333 1266.67,441.692 1266.67,700C1266.67,815.84 1224.45,921.086 1154.62,1002.73C1154.17,1003.25 919.668,1271.45 834.31,1352.87C814.514,1371.74 785.421,1371.74 765.625,1352.87C694.286,1284.79 446.037,1003.56 445.313,1002.73L445.247,1002.67C375.511,921.028 333.333,815.808 333.333,700C333.333,441.692 541.692,233.333 800,233.333ZM800,500C737.5,500 684.294,525.238 650.13,563.672C615.967,602.106 600,651.389 600,700C600,748.611 615.967,797.894 650.13,836.328C684.294,874.762 737.5,900 800,900C862.5,900 915.706,874.762 949.87,836.328C984.033,797.894 1000,748.611 1000,700C1000,651.389 984.033,602.106 949.87,563.672C915.706,525.238 862.5,500 800,500ZM800,600C837.5,600 859.294,612.262 875.13,630.078C890.967,647.894 900,673.611 900,700C900,726.389 890.967,752.106 875.13,769.922C859.294,787.738 837.5,800 800,800C762.5,800 740.706,787.738 724.87,769.922C709.033,752.106 700,726.389 700,700C700,673.611 709.033,647.894 724.87,630.078C740.706,612.262 762.5,600 800,600Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 22 KiB |
3
VDownload/Assets/Icons/MediaTypeDark.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.23077,0,0,1.23077,-204.462,-187.385)">
|
||||||
|
<path d="M350,200C249.341,200 166.667,282.674 166.667,383.333L166.667,1216.67C166.667,1317.33 249.341,1400 350,1400L1283.33,1400C1383.99,1400 1466.67,1317.33 1466.67,1216.67L1466.67,383.333C1466.67,282.674 1383.99,200 1283.33,200L350,200ZM350,300L1283.33,300C1329.94,300 1366.67,336.726 1366.67,383.333L1366.67,1216.67C1366.67,1263.27 1329.94,1300 1283.33,1300L350,1300C303.392,1300 266.667,1263.27 266.667,1216.67L266.667,383.333C266.667,336.726 303.392,300 350,300ZM366.667,350C348.267,350 333.333,364.933 333.333,383.333L333.333,416.667C333.333,435.067 348.267,450 366.667,450L400,450C418.4,450 433.333,435.067 433.333,416.667L433.333,383.333C433.333,364.933 418.4,350 400,350L366.667,350ZM1233.33,350C1214.93,350 1200,364.933 1200,383.333L1200,416.667C1200,435.067 1214.93,450 1233.33,450L1266.67,450C1285.07,450 1300,435.067 1300,416.667L1300,383.333C1300,364.933 1285.07,350 1266.67,350L1233.33,350ZM683.333,533.398C668.77,533.398 654.043,537.201 640.951,544.922C615.478,559.97 600,587.195 600,616.732L600,983.398C600,1012.87 615.401,1039.96 640.885,1055.01C666.823,1070.43 697.284,1070.78 723.503,1056.38L1056.84,873.047L1056.9,872.982C1083.33,858.401 1100,830.405 1100,800.065C1100,769.725 1083.33,741.665 1056.9,727.083L1056.84,727.018L723.438,543.685L723.372,543.62C710.907,536.807 697.1,533.398 683.333,533.398ZM366.667,550C348.267,550 333.333,564.933 333.333,583.333L333.333,616.667C333.333,635.067 348.267,650 366.667,650L400,650C418.4,650 433.333,635.067 433.333,616.667L433.333,583.333C433.333,564.933 418.4,550 400,550L366.667,550ZM1233.33,550C1214.93,550 1200,564.933 1200,583.333L1200,616.667C1200,635.067 1214.93,650 1233.33,650L1266.67,650C1285.07,650 1300,635.067 1300,616.667L1300,583.333C1300,564.933 1285.07,550 1266.67,550L1233.33,550ZM700,644.857L982.096,800L700,955.208L700,644.857ZM366.667,750C348.267,750 333.333,764.933 333.333,783.333L333.333,816.667C333.333,835.067 348.267,850 366.667,850L400,850C418.4,850 433.333,835.067 433.333,816.667L433.333,783.333C433.333,764.933 418.4,750 400,750L366.667,750ZM1233.33,750C1214.93,750 1200,764.933 1200,783.333L1200,816.667C1200,835.067 1214.93,850 1233.33,850L1266.67,850C1285.07,850 1300,835.067 1300,816.667L1300,783.333C1300,764.933 1285.07,750 1266.67,750L1233.33,750ZM366.667,950C348.267,950 333.333,964.933 333.333,983.333L333.333,1016.67C333.333,1035.07 348.267,1050 366.667,1050L400,1050C418.4,1050 433.333,1035.07 433.333,1016.67L433.333,983.333C433.333,964.933 418.4,950 400,950L366.667,950ZM1233.33,950C1214.93,950 1200,964.933 1200,983.333L1200,1016.67C1200,1035.07 1214.93,1050 1233.33,1050L1266.67,1050C1285.07,1050 1300,1035.07 1300,1016.67L1300,983.333C1300,964.933 1285.07,950 1266.67,950L1233.33,950ZM366.667,1150C348.267,1150 333.333,1164.93 333.333,1183.33L333.333,1216.67C333.333,1235.07 348.267,1250 366.667,1250L400,1250C418.4,1250 433.333,1235.07 433.333,1216.67L433.333,1183.33C433.333,1164.93 418.4,1150 400,1150L366.667,1150ZM1233.33,1150C1214.93,1150 1200,1164.93 1200,1183.33L1200,1216.67C1200,1235.07 1214.93,1250 1233.33,1250L1266.67,1250C1285.07,1250 1300,1235.07 1300,1216.67L1300,1183.33C1300,1164.93 1285.07,1150 1266.67,1150L1233.33,1150Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 3.3 KiB |
3
VDownload/Assets/Icons/MediaTypeLight.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.23077,0,0,1.23077,-204.462,-187.385)">
|
||||||
|
<path d="M350,200C249.341,200 166.667,282.674 166.667,383.333L166.667,1216.67C166.667,1317.33 249.341,1400 350,1400L1283.33,1400C1383.99,1400 1466.67,1317.33 1466.67,1216.67L1466.67,383.333C1466.67,282.674 1383.99,200 1283.33,200L350,200ZM350,300L1283.33,300C1329.94,300 1366.67,336.726 1366.67,383.333L1366.67,1216.67C1366.67,1263.27 1329.94,1300 1283.33,1300L350,1300C303.392,1300 266.667,1263.27 266.667,1216.67L266.667,383.333C266.667,336.726 303.392,300 350,300ZM366.667,350C348.267,350 333.333,364.933 333.333,383.333L333.333,416.667C333.333,435.067 348.267,450 366.667,450L400,450C418.4,450 433.333,435.067 433.333,416.667L433.333,383.333C433.333,364.933 418.4,350 400,350L366.667,350ZM1233.33,350C1214.93,350 1200,364.933 1200,383.333L1200,416.667C1200,435.067 1214.93,450 1233.33,450L1266.67,450C1285.07,450 1300,435.067 1300,416.667L1300,383.333C1300,364.933 1285.07,350 1266.67,350L1233.33,350ZM683.333,533.398C668.77,533.398 654.043,537.201 640.951,544.922C615.478,559.97 600,587.195 600,616.732L600,983.398C600,1012.87 615.401,1039.96 640.885,1055.01C666.823,1070.43 697.284,1070.78 723.503,1056.38L1056.84,873.047L1056.9,872.982C1083.33,858.401 1100,830.405 1100,800.065C1100,769.725 1083.33,741.665 1056.9,727.083L1056.84,727.018L723.438,543.685L723.372,543.62C710.907,536.807 697.1,533.398 683.333,533.398ZM366.667,550C348.267,550 333.333,564.933 333.333,583.333L333.333,616.667C333.333,635.067 348.267,650 366.667,650L400,650C418.4,650 433.333,635.067 433.333,616.667L433.333,583.333C433.333,564.933 418.4,550 400,550L366.667,550ZM1233.33,550C1214.93,550 1200,564.933 1200,583.333L1200,616.667C1200,635.067 1214.93,650 1233.33,650L1266.67,650C1285.07,650 1300,635.067 1300,616.667L1300,583.333C1300,564.933 1285.07,550 1266.67,550L1233.33,550ZM700,644.857L982.096,800L700,955.208L700,644.857ZM366.667,750C348.267,750 333.333,764.933 333.333,783.333L333.333,816.667C333.333,835.067 348.267,850 366.667,850L400,850C418.4,850 433.333,835.067 433.333,816.667L433.333,783.333C433.333,764.933 418.4,750 400,750L366.667,750ZM1233.33,750C1214.93,750 1200,764.933 1200,783.333L1200,816.667C1200,835.067 1214.93,850 1233.33,850L1266.67,850C1285.07,850 1300,835.067 1300,816.667L1300,783.333C1300,764.933 1285.07,750 1266.67,750L1233.33,750ZM366.667,950C348.267,950 333.333,964.933 333.333,983.333L333.333,1016.67C333.333,1035.07 348.267,1050 366.667,1050L400,1050C418.4,1050 433.333,1035.07 433.333,1016.67L433.333,983.333C433.333,964.933 418.4,950 400,950L366.667,950ZM1233.33,950C1214.93,950 1200,964.933 1200,983.333L1200,1016.67C1200,1035.07 1214.93,1050 1233.33,1050L1266.67,1050C1285.07,1050 1300,1035.07 1300,1016.67L1300,983.333C1300,964.933 1285.07,950 1266.67,950L1233.33,950ZM366.667,1150C348.267,1150 333.333,1164.93 333.333,1183.33L333.333,1216.67C333.333,1235.07 348.267,1250 366.667,1250L400,1250C418.4,1250 433.333,1235.07 433.333,1216.67L433.333,1183.33C433.333,1164.93 418.4,1150 400,1150L366.667,1150ZM1233.33,1150C1214.93,1150 1200,1164.93 1200,1183.33L1200,1216.67C1200,1235.07 1214.93,1250 1233.33,1250L1266.67,1250C1285.07,1250 1300,1235.07 1300,1216.67L1300,1183.33C1300,1164.93 1285.07,1150 1266.67,1150L1233.33,1150Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 3.3 KiB |
3
VDownload/Assets/Icons/QualityDark.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.14286,0,0,1.14286,-114.286,-114.286)">
|
||||||
|
<path d="M283.333,233.333C182.674,233.333 100,316.008 100,416.667L100,1183.33C100,1283.99 182.674,1366.67 283.333,1366.67L1316.67,1366.67C1417.33,1366.67 1500,1283.99 1500,1183.33L1500,416.667C1500,316.008 1417.33,233.333 1316.67,233.333L283.333,233.333ZM283.333,333.333L716.667,333.333C763.274,333.333 800,370.059 800,416.667L800,716.667C800,763.274 763.274,800 716.667,800L283.333,800C236.726,800 200,763.274 200,716.667L200,416.667C200,410.841 200.597,405.139 201.693,399.674C209.359,361.422 242.552,333.333 283.333,333.333ZM879.557,333.333L1016.67,333.333C1063.27,333.333 1100,370.059 1100,416.667L1100,950C1100,996.608 1063.27,1033.33 1016.67,1033.33L283.333,1033.33C236.726,1033.33 200,996.608 200,950L200,879.557C225.076,892.51 253.36,900 283.333,900L716.667,900C817.326,900 900,817.326 900,716.667L900,416.667C900,386.693 892.51,358.409 879.557,333.333ZM1179.56,333.333L1316.67,333.333C1363.27,333.333 1400,370.059 1400,416.667L1400,1183.33C1400,1229.94 1363.27,1266.67 1316.67,1266.67L283.333,1266.67C236.726,1266.67 200,1229.94 200,1183.33L200,1112.89C225.076,1125.84 253.36,1133.33 283.333,1133.33L1016.67,1133.33C1117.33,1133.33 1200,1050.66 1200,950L1200,416.667C1200,386.693 1192.51,358.409 1179.56,333.333Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
3
VDownload/Assets/Icons/QualityLight.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.14286,0,0,1.14286,-114.286,-114.286)">
|
||||||
|
<path d="M283.333,233.333C182.674,233.333 100,316.008 100,416.667L100,1183.33C100,1283.99 182.674,1366.67 283.333,1366.67L1316.67,1366.67C1417.33,1366.67 1500,1283.99 1500,1183.33L1500,416.667C1500,316.008 1417.33,233.333 1316.67,233.333L283.333,233.333ZM283.333,333.333L716.667,333.333C763.274,333.333 800,370.059 800,416.667L800,716.667C800,763.274 763.274,800 716.667,800L283.333,800C236.726,800 200,763.274 200,716.667L200,416.667C200,410.841 200.597,405.139 201.693,399.674C209.359,361.422 242.552,333.333 283.333,333.333ZM879.557,333.333L1016.67,333.333C1063.27,333.333 1100,370.059 1100,416.667L1100,950C1100,996.608 1063.27,1033.33 1016.67,1033.33L283.333,1033.33C236.726,1033.33 200,996.608 200,950L200,879.557C225.076,892.51 253.36,900 283.333,900L716.667,900C817.326,900 900,817.326 900,716.667L900,416.667C900,386.693 892.51,358.409 879.557,333.333ZM1179.56,333.333L1316.67,333.333C1363.27,333.333 1400,370.059 1400,416.667L1400,1183.33C1400,1229.94 1363.27,1266.67 1316.67,1266.67L283.333,1266.67C236.726,1266.67 200,1229.94 200,1183.33L200,1112.89C225.076,1125.84 253.36,1133.33 283.333,1133.33L1016.67,1133.33C1117.33,1133.33 1200,1050.66 1200,950L1200,416.667C1200,386.693 1192.51,358.409 1179.56,333.333Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 28 KiB |
3
VDownload/Assets/Icons/TrimDark.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.11651,0,0,1.11651,-114.651,-186.605)">
|
||||||
|
<path d="M283.333,233.333C182.233,233.333 100,315.6 100,416.667L100,1183.33C100,1284.4 182.233,1366.67 283.333,1366.67L733.333,1366.67C733.333,1330.87 741.718,1297.03 756.185,1266.67L283.333,1266.67C237.4,1266.67 200,1229.3 200,1183.33L200,416.667C200,370.7 237.4,333.333 283.333,333.333L1316.67,333.333C1362.6,333.333 1400,370.7 1400,416.667L1400,701.693C1418.73,704.393 1437.12,711.141 1453.32,723.307C1479.05,742.607 1494.56,770.5 1498.83,800L1500,800L1500,416.667C1500,315.6 1417.77,233.333 1316.67,233.333L283.333,233.333ZM283.333,400C264.933,400 250,414.933 250,433.333L250,466.667C250,485.067 264.933,500 283.333,500L316.667,500C335.067,500 350,485.067 350,466.667L350,433.333C350,414.933 335.067,400 316.667,400L283.333,400ZM483.333,400C464.933,400 450,414.933 450,433.333L450,466.667C450,485.067 464.933,500 483.333,500L516.667,500C535.067,500 550,485.067 550,466.667L550,433.333C550,414.933 535.067,400 516.667,400L483.333,400ZM683.333,400C664.933,400 650,414.933 650,433.333L650,466.667C650,485.067 664.933,500 683.333,500L716.667,500C735.067,500 750,485.067 750,466.667L750,433.333C750,414.933 735.067,400 716.667,400L683.333,400ZM883.333,400C864.933,400 850,414.933 850,433.333L850,466.667C850,485.067 864.933,500 883.333,500L916.667,500C935.067,500 950,485.067 950,466.667L950,433.333C950,414.933 935.067,400 916.667,400L883.333,400ZM1083.33,400C1064.93,400 1050,414.933 1050,433.333L1050,466.667C1050,485.067 1064.93,500 1083.33,500L1116.67,500C1135.07,500 1150,485.067 1150,466.667L1150,433.333C1150,414.933 1135.07,400 1116.67,400L1083.33,400ZM1283.33,400C1264.93,400 1250,414.933 1250,433.333L1250,466.667C1250,485.067 1264.93,500 1283.33,500L1316.67,500C1335.07,500 1350,485.067 1350,466.667L1350,433.333C1350,414.933 1335.07,400 1316.67,400L1283.33,400ZM1386.2,765.625C1369.3,764.93 1353.15,772.857 1343.36,786.654L1158.98,1032.42L955.273,784.896C945.741,772.99 931.267,766.078 916.016,766.146C888.67,766.271 866.239,788.805 866.239,816.15C866.239,827.969 870.429,839.413 878.06,848.438L1097.2,1114.78L1025.72,1210.03C1007.54,1203.65 987.694,1200 966.667,1200C915.278,1200 870.405,1221.07 841.797,1253.26C813.189,1285.44 800,1326.39 800,1366.67C800,1406.94 813.189,1447.89 841.797,1480.08C870.405,1512.26 915.278,1533.33 966.667,1533.33C1018.06,1533.33 1062.93,1512.26 1091.54,1480.08C1120.14,1447.89 1133.33,1406.94 1133.33,1366.67C1133.33,1333.5 1123.82,1300.16 1104.69,1271.35L1162.57,1194.21L1227.41,1273.05C1209.06,1301.47 1200,1334.16 1200,1366.67C1200,1406.94 1213.19,1447.89 1241.8,1480.08C1270.4,1512.26 1315.28,1533.33 1366.67,1533.33C1418.06,1533.33 1462.93,1512.26 1491.54,1480.08C1520.14,1447.89 1533.33,1406.94 1533.33,1366.67C1533.33,1326.39 1520.14,1285.44 1491.54,1253.26C1462.93,1221.07 1418.06,1200 1366.67,1200C1344.9,1200 1324.42,1203.94 1305.73,1210.74L1224.35,1111.91L1423.31,846.68C1430.33,837.839 1434.15,826.876 1434.15,815.588C1434.15,788.931 1412.83,766.72 1386.2,765.625ZM283.333,1100C264.933,1100 250,1114.93 250,1133.33L250,1166.67C250,1185.07 264.933,1200 283.333,1200L316.667,1200C335.067,1200 350,1185.07 350,1166.67L350,1133.33C350,1114.93 335.067,1100 316.667,1100L283.333,1100ZM483.333,1100C464.933,1100 450,1114.93 450,1133.33L450,1166.67C450,1185.07 464.933,1200 483.333,1200L516.667,1200C535.067,1200 550,1185.07 550,1166.67L550,1133.33C550,1114.93 535.067,1100 516.667,1100L483.333,1100ZM683.333,1100C664.933,1100 650,1114.93 650,1133.33L650,1166.67C650,1185.07 664.933,1200 683.333,1200L716.667,1200C735.067,1200 750,1185.07 750,1166.67L750,1133.33C750,1114.93 735.067,1100 716.667,1100L683.333,1100ZM966.667,1300C979.861,1300 989.903,1302.06 997.852,1305.53C1003.13,1312.89 1010.31,1318.67 1018.62,1322.27C1027.7,1333.76 1033.33,1349.82 1033.33,1366.67C1033.33,1384.72 1027.08,1402.11 1016.8,1413.67C1006.52,1425.24 993.056,1433.33 966.667,1433.33C940.278,1433.33 926.817,1425.24 916.536,1413.67C906.256,1402.11 900,1384.72 900,1366.67C900,1348.61 906.256,1331.23 916.536,1319.66C926.817,1308.1 940.278,1300 966.667,1300ZM1366.67,1300C1393.06,1300 1406.52,1308.1 1416.8,1319.66C1427.08,1331.23 1433.33,1348.61 1433.33,1366.67C1433.33,1384.72 1427.08,1402.11 1416.8,1413.67C1406.52,1425.24 1393.06,1433.33 1366.67,1433.33C1340.28,1433.33 1326.82,1425.24 1316.54,1413.67C1306.26,1402.11 1300,1384.72 1300,1366.67C1300,1349.41 1305.81,1332.89 1315.3,1321.35C1322.81,1317.95 1329.37,1312.74 1334.38,1306.18C1342.54,1302.35 1352.73,1300 1366.67,1300Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
3
VDownload/Assets/Icons/TrimLight.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><g transform="matrix(1.11651,0,0,1.11651,-114.651,-186.605)">
|
||||||
|
<path d="M283.333,233.333C182.233,233.333 100,315.6 100,416.667L100,1183.33C100,1284.4 182.233,1366.67 283.333,1366.67L733.333,1366.67C733.333,1330.87 741.718,1297.03 756.185,1266.67L283.333,1266.67C237.4,1266.67 200,1229.3 200,1183.33L200,416.667C200,370.7 237.4,333.333 283.333,333.333L1316.67,333.333C1362.6,333.333 1400,370.7 1400,416.667L1400,701.693C1418.73,704.393 1437.12,711.141 1453.32,723.307C1479.05,742.607 1494.56,770.5 1498.83,800L1500,800L1500,416.667C1500,315.6 1417.77,233.333 1316.67,233.333L283.333,233.333ZM283.333,400C264.933,400 250,414.933 250,433.333L250,466.667C250,485.067 264.933,500 283.333,500L316.667,500C335.067,500 350,485.067 350,466.667L350,433.333C350,414.933 335.067,400 316.667,400L283.333,400ZM483.333,400C464.933,400 450,414.933 450,433.333L450,466.667C450,485.067 464.933,500 483.333,500L516.667,500C535.067,500 550,485.067 550,466.667L550,433.333C550,414.933 535.067,400 516.667,400L483.333,400ZM683.333,400C664.933,400 650,414.933 650,433.333L650,466.667C650,485.067 664.933,500 683.333,500L716.667,500C735.067,500 750,485.067 750,466.667L750,433.333C750,414.933 735.067,400 716.667,400L683.333,400ZM883.333,400C864.933,400 850,414.933 850,433.333L850,466.667C850,485.067 864.933,500 883.333,500L916.667,500C935.067,500 950,485.067 950,466.667L950,433.333C950,414.933 935.067,400 916.667,400L883.333,400ZM1083.33,400C1064.93,400 1050,414.933 1050,433.333L1050,466.667C1050,485.067 1064.93,500 1083.33,500L1116.67,500C1135.07,500 1150,485.067 1150,466.667L1150,433.333C1150,414.933 1135.07,400 1116.67,400L1083.33,400ZM1283.33,400C1264.93,400 1250,414.933 1250,433.333L1250,466.667C1250,485.067 1264.93,500 1283.33,500L1316.67,500C1335.07,500 1350,485.067 1350,466.667L1350,433.333C1350,414.933 1335.07,400 1316.67,400L1283.33,400ZM1386.2,765.625C1369.3,764.93 1353.15,772.857 1343.36,786.654L1158.98,1032.42L955.273,784.896C945.741,772.99 931.267,766.078 916.016,766.146C888.67,766.271 866.239,788.805 866.239,816.15C866.239,827.969 870.429,839.413 878.06,848.438L1097.2,1114.78L1025.72,1210.03C1007.54,1203.65 987.694,1200 966.667,1200C915.278,1200 870.405,1221.07 841.797,1253.26C813.189,1285.44 800,1326.39 800,1366.67C800,1406.94 813.189,1447.89 841.797,1480.08C870.405,1512.26 915.278,1533.33 966.667,1533.33C1018.06,1533.33 1062.93,1512.26 1091.54,1480.08C1120.14,1447.89 1133.33,1406.94 1133.33,1366.67C1133.33,1333.5 1123.82,1300.16 1104.69,1271.35L1162.57,1194.21L1227.41,1273.05C1209.06,1301.47 1200,1334.16 1200,1366.67C1200,1406.94 1213.19,1447.89 1241.8,1480.08C1270.4,1512.26 1315.28,1533.33 1366.67,1533.33C1418.06,1533.33 1462.93,1512.26 1491.54,1480.08C1520.14,1447.89 1533.33,1406.94 1533.33,1366.67C1533.33,1326.39 1520.14,1285.44 1491.54,1253.26C1462.93,1221.07 1418.06,1200 1366.67,1200C1344.9,1200 1324.42,1203.94 1305.73,1210.74L1224.35,1111.91L1423.31,846.68C1430.33,837.839 1434.15,826.876 1434.15,815.588C1434.15,788.931 1412.83,766.72 1386.2,765.625ZM283.333,1100C264.933,1100 250,1114.93 250,1133.33L250,1166.67C250,1185.07 264.933,1200 283.333,1200L316.667,1200C335.067,1200 350,1185.07 350,1166.67L350,1133.33C350,1114.93 335.067,1100 316.667,1100L283.333,1100ZM483.333,1100C464.933,1100 450,1114.93 450,1133.33L450,1166.67C450,1185.07 464.933,1200 483.333,1200L516.667,1200C535.067,1200 550,1185.07 550,1166.67L550,1133.33C550,1114.93 535.067,1100 516.667,1100L483.333,1100ZM683.333,1100C664.933,1100 650,1114.93 650,1133.33L650,1166.67C650,1185.07 664.933,1200 683.333,1200L716.667,1200C735.067,1200 750,1185.07 750,1166.67L750,1133.33C750,1114.93 735.067,1100 716.667,1100L683.333,1100ZM966.667,1300C979.861,1300 989.903,1302.06 997.852,1305.53C1003.13,1312.89 1010.31,1318.67 1018.62,1322.27C1027.7,1333.76 1033.33,1349.82 1033.33,1366.67C1033.33,1384.72 1027.08,1402.11 1016.8,1413.67C1006.52,1425.24 993.056,1433.33 966.667,1433.33C940.278,1433.33 926.817,1425.24 916.536,1413.67C906.256,1402.11 900,1384.72 900,1366.67C900,1348.61 906.256,1331.23 916.536,1319.66C926.817,1308.1 940.278,1300 966.667,1300ZM1366.67,1300C1393.06,1300 1406.52,1308.1 1416.8,1319.66C1427.08,1331.23 1433.33,1348.61 1433.33,1366.67C1433.33,1384.72 1427.08,1402.11 1416.8,1413.67C1406.52,1425.24 1393.06,1433.33 1366.67,1433.33C1340.28,1433.33 1326.82,1425.24 1316.54,1413.67C1306.26,1402.11 1300,1384.72 1300,1366.67C1300,1349.41 1305.81,1332.89 1315.3,1321.35C1322.81,1317.95 1329.37,1312.74 1334.38,1306.18C1342.54,1302.35 1352.73,1300 1366.67,1300Z" style="fill-rule:nonzero;"/>
|
||||||
|
</g></svg>
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 43 KiB |
1
VDownload/Assets/Icons/ViewsDark.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><path d="M799.544,300C422.224,300 89.762,561.531 1.563,904.232C0.52,908.294 -0.008,912.472 -0.008,916.667C-0.008,944.1 22.566,966.675 50,966.675C72.756,966.675 92.779,951.143 98.438,929.102C174.438,633.803 468.865,400 799.544,400C1130.22,400 1425.58,633.885 1501.56,929.102C1507.22,951.143 1527.24,966.675 1550,966.675C1577.43,966.675 1600.01,944.1 1600.01,916.667C1600.01,912.472 1599.48,908.294 1598.44,904.232C1510.22,561.448 1176.87,300 799.544,300ZM800.065,566.667C622.73,566.667 477.93,711.467 477.93,888.802C477.93,1066.14 622.73,1211 800.065,1211C977.401,1211 1122.27,1066.14 1122.27,888.802C1122.27,711.467 977.401,566.667 800.065,566.667ZM800.065,666.667C923.357,666.667 1022.27,765.511 1022.27,888.802C1022.27,1012.09 923.357,1111 800.065,1111C676.774,1111 577.93,1012.09 577.93,888.802C577.93,765.511 676.774,666.667 800.065,666.667Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 934 B |
1
VDownload/Assets/Icons/ViewsLight.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><path d="M799.544,300C422.224,300 89.762,561.531 1.563,904.232C0.52,908.294 -0.008,912.472 -0.008,916.667C-0.008,944.1 22.566,966.675 50,966.675C72.756,966.675 92.779,951.143 98.438,929.102C174.438,633.803 468.865,400 799.544,400C1130.22,400 1425.58,633.885 1501.56,929.102C1507.22,951.143 1527.24,966.675 1550,966.675C1577.43,966.675 1600.01,944.1 1600.01,916.667C1600.01,912.472 1599.48,908.294 1598.44,904.232C1510.22,561.448 1176.87,300 799.544,300ZM800.065,566.667C622.73,566.667 477.93,711.467 477.93,888.802C477.93,1066.14 622.73,1211 800.065,1211C977.401,1211 1122.27,1066.14 1122.27,888.802C1122.27,711.467 977.401,566.667 800.065,566.667ZM800.065,666.667C923.357,666.667 1022.27,765.511 1022.27,888.802C1022.27,1012.09 923.357,1111 800.065,1111C676.774,1111 577.93,1012.09 577.93,888.802C577.93,765.511 676.774,666.667 800.065,666.667Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 934 B |
BIN
VDownload/Assets/Twitch.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 154 KiB |
@@ -20,21 +20,24 @@
|
|||||||
<SolidColorBrush x:Key="SettingControlBackgroundColor" Color="#FBFBFB"/>
|
<SolidColorBrush x:Key="SettingControlBackgroundColor" Color="#FBFBFB"/>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="ms-appx:///Resources/Converters.xaml"/>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
|
|
||||||
|
|
||||||
<Grid Padding="18" CornerRadius="{ThemeResource ControlCornerRadius}" Background="{ThemeResource SettingControlBackgroundColor}">
|
<Grid MinHeight="65" Padding="18" CornerRadius="{ThemeResource ControlCornerRadius}" Background="{ThemeResource SettingControlBackgroundColor}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="18"/>
|
<ColumnDefinition Width="18"/>
|
||||||
<ColumnDefinition/>
|
|
||||||
<ColumnDefinition Width="18"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="18"/>
|
||||||
|
<ColumnDefinition/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<!-- ICON -->
|
<!-- ICON -->
|
||||||
<ContentPresenter Grid.Column="0" VerticalAlignment="Center" Width="20" Content="{x:Bind Icon, Mode=OneWay}"/>
|
<Image Grid.Column="0" VerticalAlignment="Center" Width="20" Source="{x:Bind Icon, Mode=OneWay}"/>
|
||||||
|
|
||||||
<!-- TITLE & DESCRIPTION -->
|
<!-- TITLE & DESCRIPTION -->
|
||||||
<Grid Grid.Column="2" VerticalAlignment="Center">
|
<Grid Grid.Column="2" VerticalAlignment="Center">
|
||||||
@@ -43,10 +46,10 @@
|
|||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBlock Grid.Row="0" Text="{x:Bind Title, Mode=OneWay}"/>
|
<TextBlock Grid.Row="0" Text="{x:Bind Title, Mode=OneWay}"/>
|
||||||
<TextBlock Grid.Row="1" FontSize="12" Foreground="{ThemeResource SystemBaseMediumColor}" TextWrapping="Wrap" Text="{x:Bind Description, Mode=OneWay}"/>
|
<TextBlock Grid.Row="1" Visibility="{x:Bind Description, Converter={StaticResource StringToVisibilityConverter}}" FontSize="12" Foreground="{ThemeResource SystemBaseMediumColor}" TextWrapping="Wrap" Text="{x:Bind Description, Mode=OneWay}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- SETTING CONTROL -->
|
<!-- SETTING CONTROL -->
|
||||||
<ContentPresenter Grid.Column="4" VerticalAlignment="Center" Content="{x:Bind SettingContent, Mode=OneWay}"/>
|
<ContentPresenter Grid.Column="4" HorizontalAlignment="Right" VerticalAlignment="Center" Content="{x:Bind SettingContent, Mode=OneWay}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ namespace VDownload.Controls
|
|||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
// ICON
|
// ICON
|
||||||
public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(IconElement), typeof(SettingControl), new PropertyMetadata(null));
|
public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(ImageSource), typeof(SettingControl), new PropertyMetadata(null));
|
||||||
public IconElement Icon
|
public ImageSource Icon
|
||||||
{
|
{
|
||||||
get => (IconElement)GetValue(IconProperty);
|
get => (ImageSource)GetValue(IconProperty);
|
||||||
set => SetValue(IconProperty, value);
|
set => SetValue(IconProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
VDownload/Converters/StringToVisibilityConverter.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace VDownload.Converters
|
||||||
|
{
|
||||||
|
public class StringToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty((string)value))
|
||||||
|
{
|
||||||
|
return Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Visibility.Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
VDownload/Converters/TimeSpanToTextBoxMaskConverter.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace VDownload.Converters
|
||||||
|
{
|
||||||
|
public class TimeSpanToTextBoxMaskConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
string mask = string.Empty;
|
||||||
|
|
||||||
|
if (Math.Floor(((TimeSpan)value).TotalHours) > 0) mask += $"{Math.Floor(((TimeSpan)value).TotalHours).ToString()[0]}{new string('9', Math.Floor(((TimeSpan)value).TotalHours).ToString().Length - 1)}:";
|
||||||
|
if (Math.Floor(((TimeSpan)value).TotalMinutes) > 0) mask += Math.Floor(((TimeSpan)value).TotalHours) > 0 ? $"59:" : $"{((TimeSpan)value).Minutes.ToString()[0]}{new string('9', ((TimeSpan)value).Minutes.ToString().Length - 1)}:";
|
||||||
|
mask += Math.Floor(((TimeSpan)value).TotalMinutes) > 0 ? $"59" : $"{((TimeSpan)value).Seconds.ToString()[0]}{new string('9', ((TimeSpan)value).Seconds.ToString().Length - 1)}";
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace VDownload.Converters
|
||||||
|
{
|
||||||
|
public class TimeSpanToTextBoxMaskElementsConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
HashSet<int> maskElements = new HashSet<int>();
|
||||||
|
|
||||||
|
if (Math.Floor(((TimeSpan)value).TotalHours) > 0) maskElements.Add(int.Parse(Math.Floor(((TimeSpan)value).TotalHours).ToString()[0].ToString()));
|
||||||
|
if (Math.Floor(((TimeSpan)value).TotalMinutes) > 0)
|
||||||
|
{
|
||||||
|
if (Math.Floor(((TimeSpan)value).TotalHours) > 0) maskElements.Add(5);
|
||||||
|
else maskElements.Add(int.Parse(((TimeSpan)value).Minutes.ToString()[0].ToString()));
|
||||||
|
}
|
||||||
|
if (Math.Floor(((TimeSpan)value).TotalMinutes) > 0) maskElements.Add(5);
|
||||||
|
else maskElements.Add(int.Parse(((TimeSpan)value).Seconds.ToString()[0].ToString()));
|
||||||
|
|
||||||
|
List<string> maskElementsString = new List<string>();
|
||||||
|
foreach (int i in maskElements)
|
||||||
|
{
|
||||||
|
if (i != 9) maskElementsString.Add($"{i}:[0-{i}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join(',', maskElementsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
VDownload/Resources/Converters.xaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:converters="using:VDownload.Converters">
|
||||||
|
<converters:StringToVisibilityConverter x:Key="StringToVisibilityConverter"/>
|
||||||
|
<converters:TimeSpanToTextBoxMaskConverter x:Key="TimeSpanToTextBoxMaskConverter"/>
|
||||||
|
<converters:TimeSpanToTextBoxMaskElementsConverter x:Key="TimeSpanToTextBoxMaskElementsConverter"/>
|
||||||
|
</ResourceDictionary>
|
||||||
29
VDownload/Resources/Icons.xaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
|
<ResourceDictionary x:Key="Light">
|
||||||
|
<SvgImageSource x:Key="AuthorIcon" UriSource="ms-appx:///Assets/Icons/AuthorLight.svg"/>
|
||||||
|
<SvgImageSource x:Key="ViewsIcon" UriSource="ms-appx:///Assets/Icons/ViewsLight.svg"/>
|
||||||
|
<SvgImageSource x:Key="DateIcon" UriSource="ms-appx:///Assets/Icons/DateLight.svg"/>
|
||||||
|
<SvgImageSource x:Key="DurationIcon" UriSource="ms-appx:///Assets/Icons/DurationLight.svg"/>
|
||||||
|
<SvgImageSource x:Key="MediaTypeIcon" UriSource="ms-appx:///Assets/Icons/MediaTypeLight.svg"/>
|
||||||
|
<SvgImageSource x:Key="QualityIcon" UriSource="ms-appx:///Assets/Icons/QualityLight.svg"/>
|
||||||
|
<SvgImageSource x:Key="TrimIcon" UriSource="ms-appx:///Assets/Icons/TrimLight.svg"/>
|
||||||
|
<SvgImageSource x:Key="FileIcon" UriSource="ms-appx:///Assets/Icons/FileLight.svg"/>
|
||||||
|
<SvgImageSource x:Key="LocationIcon" UriSource="ms-appx:///Assets/Icons/LocationLight.svg"/>
|
||||||
|
</ResourceDictionary>
|
||||||
|
<ResourceDictionary x:Key="Dark">
|
||||||
|
<SvgImageSource x:Key="AuthorIcon" UriSource="ms-appx:///Assets/Icons/AuthorDark.svg"/>
|
||||||
|
<SvgImageSource x:Key="ViewsIcon" UriSource="ms-appx:///Assets/Icons/ViewsDark.svg"/>
|
||||||
|
<SvgImageSource x:Key="DateIcon" UriSource="ms-appx:///Assets/Icons/DateDark.svg"/>
|
||||||
|
<SvgImageSource x:Key="DurationIcon" UriSource="ms-appx:///Assets/Icons/DurationDark.svg"/>
|
||||||
|
<SvgImageSource x:Key="MediaTypeIcon" UriSource="ms-appx:///Assets/Icons/MediaTypeDark.svg"/>
|
||||||
|
<SvgImageSource x:Key="QualityIcon" UriSource="ms-appx:///Assets/Icons/QualityDark.svg"/>
|
||||||
|
<SvgImageSource x:Key="TrimIcon" UriSource="ms-appx:///Assets/Icons/TrimDark.svg"/>
|
||||||
|
<SvgImageSource x:Key="FileIcon" UriSource="ms-appx:///Assets/Icons/FileDark.svg"/>
|
||||||
|
<SvgImageSource x:Key="LocationIcon" UriSource="ms-appx:///Assets/Icons/LocationDark.svg"/>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
|
<SvgImageSource x:Key="ErrorIcon" UriSource="ms-appx:///Assets/Icons/Error.svg"/>
|
||||||
|
</ResourceDictionary>
|
||||||
@@ -117,6 +117,9 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<data name="CloseErrorDialogButtonText" xml:space="preserve">
|
||||||
|
<value>OK</value>
|
||||||
|
</data>
|
||||||
<data name="HomeOptionsBarAddPlaylistButton.Label" xml:space="preserve">
|
<data name="HomeOptionsBarAddPlaylistButton.Label" xml:space="preserve">
|
||||||
<value>Add playlist</value>
|
<value>Add playlist</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -169,6 +172,54 @@ The number in the numberbox indicades how many videos will be got from playlist.
|
|||||||
<data name="HomeOptionsBarLoadSubscripionsButton.Width" xml:space="preserve">
|
<data name="HomeOptionsBarLoadSubscripionsButton.Width" xml:space="preserve">
|
||||||
<value>120</value>
|
<value>120</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="HomeOptionsBarPlaylistSearchingErrorDialogTitle" xml:space="preserve">
|
||||||
|
<value>Playlist search error</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeOptionsBarPlaylistSearchingInternetConnectionErrorDialogDescription" xml:space="preserve">
|
||||||
|
<value>Unable to connect to servers. Check your internet connection.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeOptionsBarPlaylistSearchingTwitchAccessTokenNotFoundErrorDialogDescription" xml:space="preserve">
|
||||||
|
<value>To get information about Twitch playlists (Channels), you have to link your Twitch account with VDownload. Go to Sources page to sign in.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeOptionsBarPlaylistSearchingTwitchAccessTokenNotValidErrorDialogDescription" xml:space="preserve">
|
||||||
|
<value>There is a problem with linked Twitch account. Check Twitch login status in Sources page.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeOptionsBarVideoSearchingErrorDialogTitle" xml:space="preserve">
|
||||||
|
<value>Video search error</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeOptionsBarVideoSearchingInternetConnectionErrorDialogDescription" xml:space="preserve">
|
||||||
|
<value>Unable to connect to servers. Check your internet connection.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeOptionsBarVideoSearchingTwitchAccessTokenNotFoundErrorDialogDescription" xml:space="preserve">
|
||||||
|
<value>To get information about Twitch videos (VODs and Clips), you have to link your Twitch account with VDownload. Go to Sources page to sign in.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeOptionsBarVideoSearchingTwitchAccessTokenNotValidErrorDialogDescription" xml:space="preserve">
|
||||||
|
<value>There is a problem with linked Twitch account. Check Twitch login status in Sources page.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeVideoAddingDownloadingOptionsHeaderTextBlock.Text" xml:space="preserve">
|
||||||
|
<value>Downloading options</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeVideoAddingFileOptionsHeaderTextBlock.Text" xml:space="preserve">
|
||||||
|
<value>File options</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeVideoAddingFileSettingControl.Title" xml:space="preserve">
|
||||||
|
<value>File</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeVideoAddingLocationBrowseButton.Content" xml:space="preserve">
|
||||||
|
<value>Browse</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeVideoAddingLocationSettingControl.Title" xml:space="preserve">
|
||||||
|
<value>Location</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeVideoAddingMediaTypeSettingControl.Title" xml:space="preserve">
|
||||||
|
<value>Media type</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeVideoAddingQualitySettingControl.Title" xml:space="preserve">
|
||||||
|
<value>Quality</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomeVideoAddingTrimSettingControl.Title" xml:space="preserve">
|
||||||
|
<value>Trim</value>
|
||||||
|
</data>
|
||||||
<data name="MainPageNavigationPanelHomeItem.Content" xml:space="preserve">
|
<data name="MainPageNavigationPanelHomeItem.Content" xml:space="preserve">
|
||||||
<value>Home</value>
|
<value>Home</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -178,6 +229,15 @@ The number in the numberbox indicades how many videos will be got from playlist.
|
|||||||
<data name="MainPageNavigationPanelSubscriptionsItem.Content" xml:space="preserve">
|
<data name="MainPageNavigationPanelSubscriptionsItem.Content" xml:space="preserve">
|
||||||
<value>Subscriptions</value>
|
<value>Subscriptions</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MediaTypeAudioVideoText" xml:space="preserve">
|
||||||
|
<value>Audio & Video</value>
|
||||||
|
</data>
|
||||||
|
<data name="MediaTypeOnlyAudioText" xml:space="preserve">
|
||||||
|
<value>Only audio</value>
|
||||||
|
</data>
|
||||||
|
<data name="MediaTypeOnlyVideoText" xml:space="preserve">
|
||||||
|
<value>Only video</value>
|
||||||
|
</data>
|
||||||
<data name="SourcesMainPageHeaderText.Text" xml:space="preserve">
|
<data name="SourcesMainPageHeaderText.Text" xml:space="preserve">
|
||||||
<value>Sources</value>
|
<value>Sources</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -190,6 +250,9 @@ The number in the numberbox indicades how many videos will be got from playlist.
|
|||||||
<data name="SourcesTwitchLoginButtonTextNotLoggedIn" xml:space="preserve">
|
<data name="SourcesTwitchLoginButtonTextNotLoggedIn" xml:space="preserve">
|
||||||
<value>Sign in</value>
|
<value>Sign in</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SourcesTwitchLoginErrorDialogDescriptionInternetConnectionError" xml:space="preserve">
|
||||||
|
<value>Unable to connect to Twitch servers. Check your internet connection.</value>
|
||||||
|
</data>
|
||||||
<data name="SourcesTwitchLoginErrorDialogDescriptionUnknown" xml:space="preserve">
|
<data name="SourcesTwitchLoginErrorDialogDescriptionUnknown" xml:space="preserve">
|
||||||
<value>Unknown error</value>
|
<value>Unknown error</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -202,6 +265,9 @@ The number in the numberbox indicades how many videos will be got from playlist.
|
|||||||
<data name="SourcesTwitchSettingControl.Title" xml:space="preserve">
|
<data name="SourcesTwitchSettingControl.Title" xml:space="preserve">
|
||||||
<value>Twitch</value>
|
<value>Twitch</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SourcesTwitchSettingControlDescriptionInternetConnectionError" xml:space="preserve">
|
||||||
|
<value>Unable to connect to Twitch servers. Check your internet connection.</value>
|
||||||
|
</data>
|
||||||
<data name="SourcesTwitchSettingControlDescriptionLoggedIn" xml:space="preserve">
|
<data name="SourcesTwitchSettingControlDescriptionLoggedIn" xml:space="preserve">
|
||||||
<value>Logged in as</value>
|
<value>Logged in as</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -119,6 +119,9 @@
|
|||||||
<Compile Include="App.xaml.cs">
|
<Compile Include="App.xaml.cs">
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Converters\StringToVisibilityConverter.cs" />
|
||||||
|
<Compile Include="Converters\TimeSpanToTextBoxMaskConverter.cs" />
|
||||||
|
<Compile Include="Converters\TimeSpanToTextBoxMaskElementsConverter.cs" />
|
||||||
<Compile Include="Views\About\AboutMain.xaml.cs">
|
<Compile Include="Views\About\AboutMain.xaml.cs">
|
||||||
<DependentUpon>AboutMain.xaml</DependentUpon>
|
<DependentUpon>AboutMain.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -134,6 +137,12 @@
|
|||||||
<Compile Include="Views\Home\HomeMain.xaml.cs">
|
<Compile Include="Views\Home\HomeMain.xaml.cs">
|
||||||
<DependentUpon>HomeMain.xaml</DependentUpon>
|
<DependentUpon>HomeMain.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Views\Home\HomeVideoAddingPanel.xaml.cs">
|
||||||
|
<DependentUpon>HomeVideoAddingPanel.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Views\Home\HomeVideoPanel.xaml.cs">
|
||||||
|
<DependentUpon>HomeVideoPanel.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Views\MainPage.xaml.cs">
|
<Compile Include="Views\MainPage.xaml.cs">
|
||||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -153,46 +162,25 @@
|
|||||||
</AppxManifest>
|
</AppxManifest>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Assets\Icons\Add\NotFound.png" />
|
<Content Include="Assets\Icons\AuthorDark.svg" />
|
||||||
<Content Include="Assets\Icons\Add\Start.png" />
|
<Content Include="Assets\Icons\AuthorLight.svg" />
|
||||||
<Content Include="Assets\Icons\Error.png" />
|
<Content Include="Assets\Icons\DateDark.svg" />
|
||||||
<Content Include="Assets\Icons\MainPage\About.png" />
|
<Content Include="Assets\Icons\DateLight.svg" />
|
||||||
<Content Include="Assets\Icons\MainPage\Sources.png" />
|
<Content Include="Assets\Icons\DurationDark.svg" />
|
||||||
<Content Include="Assets\Icons\Sources\Twitch.png" />
|
<Content Include="Assets\Icons\DurationLight.svg" />
|
||||||
<Content Include="Assets\Icons\Sources\Unknown.png" />
|
<Content Include="Assets\Icons\Error.svg" />
|
||||||
<Content Include="Assets\Icons\Sources\Youtube.png" />
|
<Content Include="Assets\Icons\FileDark.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Author.png" />
|
<Content Include="Assets\Icons\FileLight.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Cancelled.png" />
|
<Content Include="Assets\Icons\LocationDark.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Date.png" />
|
<Content Include="Assets\Icons\LocationLight.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Done.png" />
|
<Content Include="Assets\Icons\MediaTypeDark.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Downloading.png" />
|
<Content Include="Assets\Icons\MediaTypeLight.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Duration.png" />
|
<Content Include="Assets\Icons\QualityDark.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Error.png" />
|
<Content Include="Assets\Icons\QualityLight.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Finalizing.png" />
|
<Content Include="Assets\Icons\TrimDark.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Idle.png" />
|
<Content Include="Assets\Icons\TrimLight.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\MediaType.png" />
|
<Content Include="Assets\Icons\ViewsDark.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\File.png" />
|
<Content Include="Assets\Icons\ViewsLight.svg" />
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Transcoding.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Quality.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Trim.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Views.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Dark\Waiting.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Author.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Cancelled.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Date.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Done.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Downloading.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Duration.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Error.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Finalizing.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Idle.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\MediaType.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\File.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Transcoding.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Quality.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Trim.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Views.png" />
|
|
||||||
<Content Include="Assets\Icons\VideoMetadata\Light\Waiting.png" />
|
|
||||||
<Content Include="Assets\Logo\Logo.png" />
|
<Content Include="Assets\Logo\Logo.png" />
|
||||||
<Content Include="Assets\Logo\LargeTile.scale-100.png" />
|
<Content Include="Assets\Logo\LargeTile.scale-100.png" />
|
||||||
<Content Include="Assets\Logo\LargeTile.scale-125.png" />
|
<Content Include="Assets\Logo\LargeTile.scale-125.png" />
|
||||||
@@ -244,13 +232,22 @@
|
|||||||
<Content Include="Assets\Logo\Wide310x150Logo.scale-150.png" />
|
<Content Include="Assets\Logo\Wide310x150Logo.scale-150.png" />
|
||||||
<Content Include="Assets\Logo\Wide310x150Logo.scale-200.png" />
|
<Content Include="Assets\Logo\Wide310x150Logo.scale-200.png" />
|
||||||
<Content Include="Assets\Logo\Wide310x150Logo.scale-400.png" />
|
<Content Include="Assets\Logo\Wide310x150Logo.scale-400.png" />
|
||||||
<Content Include="Assets\Other\UnknownThumbnail.png" />
|
<Content Include="Assets\Twitch.png" />
|
||||||
|
<Content Include="Assets\UnknownThumbnail.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ApplicationDefinition Include="App.xaml">
|
<ApplicationDefinition Include="App.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</ApplicationDefinition>
|
</ApplicationDefinition>
|
||||||
|
<Page Include="Resources\Converters.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Resources\Icons.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Views\About\AboutMain.xaml">
|
<Page Include="Views\About\AboutMain.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -271,6 +268,14 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Views\Home\HomeVideoAddingPanel.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Views\Home\HomeVideoPanel.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Views\MainPage.xaml">
|
<Page Include="Views\MainPage.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
|
|||||||
@@ -15,12 +15,17 @@
|
|||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.ThemeDictionaries>
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
<ResourceDictionary x:Key="Dark">
|
<ResourceDictionary x:Key="Dark">
|
||||||
<SolidColorBrush x:Key="HomeMainOptionBarBackgroundColor" Color="#202020"/>
|
<SolidColorBrush x:Key="HomeMainOptionBarBackgroundColor" Color="#1B1B1B"/>
|
||||||
|
<SolidColorBrush x:Key="HomeMainAddingPanelBackgroundColor" Color="#212121"/>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
<ResourceDictionary x:Key="Light">
|
<ResourceDictionary x:Key="Light">
|
||||||
<SolidColorBrush x:Key="HomeMainOptionBarBackgroundColor" Color="#F5F5F5"/>
|
<SolidColorBrush x:Key="HomeMainOptionBarBackgroundColor" Color="#F5F5F5"/>
|
||||||
|
<SolidColorBrush x:Key="HomeMainAddingPanelBackgroundColor" Color="#F5F5F5"/>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="ms-appx:///Resources/Icons.xaml"/>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</Page.Resources>
|
</Page.Resources>
|
||||||
|
|
||||||
@@ -33,10 +38,12 @@
|
|||||||
<AdaptiveTrigger MinWindowWidth="0"/>
|
<AdaptiveTrigger MinWindowWidth="0"/>
|
||||||
</VisualState.StateTriggers>
|
</VisualState.StateTriggers>
|
||||||
<VisualState.Setters>
|
<VisualState.Setters>
|
||||||
<Setter Target="HomeOptionBarButtonsStackPanel.(Grid.ColumnSpan)" Value="3"/>
|
<Setter Target="HomeOptionBarButtonsStackPanel.(Grid.ColumnSpan)" Value="4"/>
|
||||||
<Setter Target="HomeOptionBarButtonsStackPanel.(Grid.Column)" Value="0"/>
|
<Setter Target="HomeOptionBarButtonsStackPanel.(Grid.Column)" Value="0"/>
|
||||||
<Setter Target="HomeOptionsBarAddingControl.(Grid.Row)" Value="0"/>
|
<Setter Target="HomeOptionsBarAddingControl.(Grid.Row)" Value="0"/>
|
||||||
<Setter Target="HomeOptionsBarAddingControl.(Grid.ColumnSpan)" Value="3"/>
|
<Setter Target="HomeOptionsBarAddingControl.(Grid.ColumnSpan)" Value="3"/>
|
||||||
|
<Setter Target="HomeOptionsBarSearchingStatusControl.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeOptionsBarSearchingStatusControl.(Grid.Column)" Value="3"/>
|
||||||
</VisualState.Setters>
|
</VisualState.Setters>
|
||||||
</VisualState>
|
</VisualState>
|
||||||
<VisualState x:Name="Normal">
|
<VisualState x:Name="Normal">
|
||||||
@@ -45,40 +52,45 @@
|
|||||||
</VisualState.StateTriggers>
|
</VisualState.StateTriggers>
|
||||||
<VisualState.Setters>
|
<VisualState.Setters>
|
||||||
<Setter Target="HomeOptionBarButtonsStackPanel.(Grid.ColumnSpan)" Value="1"/>
|
<Setter Target="HomeOptionBarButtonsStackPanel.(Grid.ColumnSpan)" Value="1"/>
|
||||||
<Setter Target="HomeOptionBarButtonsStackPanel.(Grid.Column)" Value="2"/>
|
<Setter Target="HomeOptionBarButtonsStackPanel.(Grid.Column)" Value="3"/>
|
||||||
<Setter Target="HomeOptionsBarAddingControl.(Grid.Row)" Value="1"/>
|
<Setter Target="HomeOptionsBarAddingControl.(Grid.Row)" Value="1"/>
|
||||||
<Setter Target="HomeOptionsBarAddingControl.(Grid.ColumnSpan)" Value="1"/>
|
<Setter Target="HomeOptionsBarAddingControl.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeOptionsBarSearchingStatusControl.(Grid.Row)" Value="1"/>
|
||||||
|
<Setter Target="HomeOptionsBarSearchingStatusControl.(Grid.Column)" Value="1"/>
|
||||||
</VisualState.Setters>
|
</VisualState.Setters>
|
||||||
</VisualState>
|
</VisualState>
|
||||||
</VisualStateGroup>
|
</VisualStateGroup>
|
||||||
</VisualStateManager.VisualStateGroups>
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="1*"/>
|
<RowDefinition x:Name="HomeVideosListRow" Height="1*"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition x:Name="HomeOptionBarAndAddingPanelRow" Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- VIDEOS LIST -->
|
<!-- VIDEOS LIST -->
|
||||||
<StackPanel/>
|
<StackPanel/>
|
||||||
|
|
||||||
<!-- OPTIONS BAR AND ADDING PANEL -->
|
<!-- OPTIONS BAR AND ADDING PANEL -->
|
||||||
<Grid Grid.Row="1" CornerRadius="{ThemeResource ControlCornerRadius}" Background="{ThemeResource HomeMainOptionBarBackgroundColor}">
|
<Grid Grid.Row="1" CornerRadius="{ThemeResource ControlCornerRadius}" Background="{ThemeResource HomeMainAddingPanelBackgroundColor}">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition/>
|
<RowDefinition/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid x:Name="HomeOptionsBar" Grid.Row="1"> <!-- Options Bar -->
|
<ContentControl x:Name="HomeAddingPanel" Grid.Row="0" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"/> <!-- Adding Panel -->
|
||||||
|
<Grid x:Name="HomeOptionsBar" Grid.Row="1" Background="{ThemeResource HomeMainOptionBarBackgroundColor}"> <!-- Options Bar -->
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="50"/>
|
<ColumnDefinition Width="50"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<ContentPresenter x:Name="HomeOptionsBarAddingControl" Grid.Row="1" Grid.Column="0"/>
|
<ContentPresenter x:Name="HomeOptionsBarAddingControl" Grid.Row="1" Grid.Column="0"/>
|
||||||
<StackPanel x:Name="HomeOptionBarButtonsStackPanel" Grid.Row="1" Grid.Column="2" Margin="3,0,3,0" HorizontalAlignment="Center" Orientation="Horizontal">
|
<ContentPresenter x:Name="HomeOptionsBarSearchingStatusControl" Grid.Row="1" Grid.Column="1"/>
|
||||||
|
<StackPanel x:Name="HomeOptionBarButtonsStackPanel" Grid.Row="1" Grid.Column="3" Margin="3,0,3,0" HorizontalAlignment="Center" Orientation="Horizontal">
|
||||||
<AppBarButton x:Name="HomeOptionsBarLoadSubscripionsButton" x:Uid="HomeOptionsBarLoadSubscripionsButton" Icon="Favorite" Label="Load subscriptions" Width="120"/>
|
<AppBarButton x:Name="HomeOptionsBarLoadSubscripionsButton" x:Uid="HomeOptionsBarLoadSubscripionsButton" Icon="Favorite" Label="Load subscriptions" Width="120"/>
|
||||||
<AppBarSeparator VerticalAlignment="Center" Height="50"/>
|
<AppBarSeparator VerticalAlignment="Center" Height="50"/>
|
||||||
<AppBarToggleButton x:Name="HomeOptionsBarAddPlaylistButton" x:Uid="HomeOptionsBarAddPlaylistButton" Icon="List" Label="Add playlist" Width="85" Checked="HomeOptionsBarAddPlaylistButton_Checked" Unchecked="HomeOptionsBarAddingButtons_Unchecked"/>
|
<AppBarToggleButton x:Name="HomeOptionsBarAddPlaylistButton" x:Uid="HomeOptionsBarAddPlaylistButton" Icon="List" Label="Add playlist" Width="85" Checked="HomeOptionsBarAddPlaylistButton_Checked" Unchecked="HomeOptionsBarAddingButtons_Unchecked"/>
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading;
|
||||||
|
using VDownload.Core.Enums;
|
||||||
using VDownload.Core.EventArgsObjects;
|
using VDownload.Core.EventArgsObjects;
|
||||||
|
using VDownload.Core.Exceptions;
|
||||||
|
using VDownload.Core.Interfaces;
|
||||||
|
using VDownload.Core.Services;
|
||||||
|
using Windows.ApplicationModel.Resources;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Media.Imaging;
|
||||||
|
|
||||||
namespace VDownload.Views.Home
|
namespace VDownload.Views.Home
|
||||||
{
|
{
|
||||||
@@ -18,6 +27,18 @@ namespace VDownload.Views.Home
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
// SEARCHING STATUS CONTROLS
|
||||||
|
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"] };
|
||||||
|
|
||||||
|
CancellationTokenSource SearchingCancellationToken = new CancellationTokenSource();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region BUTTONS EVENTS
|
#region BUTTONS EVENTS
|
||||||
|
|
||||||
// ADD VIDEO BUTTON CHECKED
|
// ADD VIDEO BUTTON CHECKED
|
||||||
@@ -33,9 +54,102 @@ namespace VDownload.Views.Home
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ADD VIDEO SEARCH BUTTON CLICKED
|
// ADD VIDEO SEARCH BUTTON CLICKED
|
||||||
private void HomeOptionsBarAddVideoControl_SearchButtonClicked(object sender, VideoSearchEventArgs e)
|
private async void HomeOptionsBarAddVideoControl_SearchButtonClicked(object sender, VideoSearchEventArgs e)
|
||||||
{
|
{
|
||||||
|
HomeAddingPanel.Content = null;
|
||||||
|
|
||||||
|
// Cancel previous operations
|
||||||
|
SearchingCancellationToken.Cancel();
|
||||||
|
SearchingCancellationToken = new CancellationTokenSource();
|
||||||
|
|
||||||
|
// Set SearchingStatusControl
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusProgressRing;
|
||||||
|
|
||||||
|
// Parse url
|
||||||
|
(VideoSource Type, string ID) source = Source.GetVideoSource(e.Phrase);
|
||||||
|
|
||||||
|
// Check url
|
||||||
|
if (source.Type == VideoSource.Null)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusErrorImage;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Select video service
|
||||||
|
IVideoService videoService = null;
|
||||||
|
switch (source.Type)
|
||||||
|
{
|
||||||
|
case VideoSource.TwitchVod: videoService = new Core.Services.Sources.Twitch.Vod(source.ID); break;
|
||||||
|
case VideoSource.TwitchClip: videoService = new Core.Services.Sources.Twitch.Clip(source.ID); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get metadata and streams
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await videoService.GetMetadataAsync(SearchingCancellationToken.Token);
|
||||||
|
await videoService.GetStreamsAsync(SearchingCancellationToken.Token);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (TwitchAccessTokenNotFoundException)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusErrorImage;
|
||||||
|
ContentDialog twitchAccessTokenNotFoundErrorDialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarVideoSearchingErrorDialogTitle"),
|
||||||
|
Content = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarVideoSearchingTwitchAccessTokenNotFoundErrorDialogDescription"),
|
||||||
|
CloseButtonText = ResourceLoader.GetForCurrentView().GetString("CloseErrorDialogButtonText"),
|
||||||
|
};
|
||||||
|
await twitchAccessTokenNotFoundErrorDialog.ShowAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (TwitchAccessTokenNotValidException)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusErrorImage;
|
||||||
|
ContentDialog twitchAccessTokenNotValidErrorDialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarVideoSearchingErrorDialogTitle"),
|
||||||
|
Content = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarVideoSearchingTwitchAccessTokenNotValidErrorDialogDescription"),
|
||||||
|
CloseButtonText = ResourceLoader.GetForCurrentView().GetString("CloseErrorDialogButtonText"),
|
||||||
|
};
|
||||||
|
await twitchAccessTokenNotValidErrorDialog.ShowAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (WebException wex)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusErrorImage;
|
||||||
|
if (wex.Response == null)
|
||||||
|
{
|
||||||
|
ContentDialog internetAccessErrorDialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarVideoSearchingErrorDialogTitle"),
|
||||||
|
Content = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarVideoSearchingInternetConnectionErrorDialogDescription"),
|
||||||
|
CloseButtonText = ResourceLoader.GetForCurrentView().GetString("CloseErrorDialogButtonText"),
|
||||||
|
};
|
||||||
|
await internetAccessErrorDialog.ShowAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set searching status control to done (null)
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = null;
|
||||||
|
|
||||||
|
|
||||||
|
HomeOptionBarAndAddingPanelRow.Height = new GridLength(1, GridUnitType.Star);
|
||||||
|
HomeVideosListRow.Height = new GridLength(0);
|
||||||
|
HomeVideoAddingPanel addingPanel = new HomeVideoAddingPanel(videoService);
|
||||||
|
addingPanel.VideoAddRequest += HomeVideoAddingPanel_VideoAddRequest;
|
||||||
|
HomeAddingPanel.Content = addingPanel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HomeVideoAddingPanel_VideoAddRequest(object sender, VideoAddEventArgs e)
|
||||||
|
{
|
||||||
|
HomeOptionsBarAddVideoButton.IsChecked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -52,16 +166,99 @@ namespace VDownload.Views.Home
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ADD PLAYLIST SEARCH BUTTON CLICKED
|
// ADD PLAYLIST SEARCH BUTTON CLICKED
|
||||||
private void HomeOptionsBarAddPlaylistControl_SearchButtonClicked(object sender, PlaylistSearchEventArgs e)
|
private async void HomeOptionsBarAddPlaylistControl_SearchButtonClicked(object sender, PlaylistSearchEventArgs e)
|
||||||
{
|
{
|
||||||
|
// Cancel previous operations
|
||||||
|
SearchingCancellationToken.Cancel();
|
||||||
|
|
||||||
|
// Set SearchingStatusControl
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusProgressRing;
|
||||||
|
|
||||||
|
// Parse url
|
||||||
|
(PlaylistSource Type, string ID) source = Source.GetPlaylistSource(e.Phrase);
|
||||||
|
|
||||||
|
// Check url
|
||||||
|
if (source.Type == PlaylistSource.Null)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusErrorImage;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Select video service
|
||||||
|
IPlaylistService playlistService = null;
|
||||||
|
switch (source.Type)
|
||||||
|
{
|
||||||
|
case PlaylistSource.TwitchChannel: playlistService = new Core.Services.Sources.Twitch.Channel(source.ID); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get metadata and streams
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await playlistService.GetMetadataAsync(SearchingCancellationToken.Token);
|
||||||
|
await playlistService.GetVideosAsync(e.Count, SearchingCancellationToken.Token);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (TwitchAccessTokenNotFoundException)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusErrorImage;
|
||||||
|
ContentDialog twitchAccessTokenNotFoundErrorDialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarPlaylistSearchingErrorDialogTitle"),
|
||||||
|
Content = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarPlaylistSearchingTwitchAccessTokenNotFoundErrorDialogDescription"),
|
||||||
|
CloseButtonText = ResourceLoader.GetForCurrentView().GetString("CloseErrorDialogButtonText"),
|
||||||
|
};
|
||||||
|
await twitchAccessTokenNotFoundErrorDialog.ShowAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (TwitchAccessTokenNotValidException)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusErrorImage;
|
||||||
|
ContentDialog twitchAccessTokenNotValidErrorDialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarPlaylistSearchingErrorDialogTitle"),
|
||||||
|
Content = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarPlaylistSearchingTwitchAccessTokenNotValidErrorDialogDescription"),
|
||||||
|
CloseButtonText = ResourceLoader.GetForCurrentView().GetString("CloseErrorDialogButtonText"),
|
||||||
|
};
|
||||||
|
await twitchAccessTokenNotValidErrorDialog.ShowAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (WebException wex)
|
||||||
|
{
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = HomeOptionsBarSearchingStatusErrorImage;
|
||||||
|
if (wex.Response == null)
|
||||||
|
{
|
||||||
|
ContentDialog internetAccessErrorDialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarPlaylistSearchingErrorDialogTitle"),
|
||||||
|
Content = ResourceLoader.GetForCurrentView().GetString("HomeOptionsBarPlaylistSearchingInternetConnectionErrorDialogDescription"),
|
||||||
|
CloseButtonText = ResourceLoader.GetForCurrentView().GetString("CloseErrorDialogButtonText"),
|
||||||
|
};
|
||||||
|
await internetAccessErrorDialog.ShowAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ADDING BUTTONS UNCHECKED
|
// ADDING BUTTONS UNCHECKED
|
||||||
private void HomeOptionsBarAddingButtons_Unchecked(object sender, RoutedEventArgs e)
|
private void HomeOptionsBarAddingButtons_Unchecked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
// Cancel searching operations
|
||||||
|
SearchingCancellationToken.Cancel();
|
||||||
|
SearchingCancellationToken = new CancellationTokenSource();
|
||||||
|
|
||||||
|
HomeOptionBarAndAddingPanelRow.Height = GridLength.Auto;
|
||||||
|
HomeVideosListRow.Height = new GridLength(1, GridUnitType.Star);
|
||||||
|
|
||||||
|
HomeAddingPanel.Content = null;
|
||||||
HomeOptionsBarAddingControl.Content = null;
|
HomeOptionsBarAddingControl.Content = null;
|
||||||
|
HomeOptionsBarSearchingStatusControl.Content = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
249
VDownload/Views/Home/HomeVideoAddingPanel.xaml
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Class="VDownload.Views.Home.HomeVideoAddingPanel"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:VDownload.Views.Home"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:ex="using:Microsoft.Toolkit.Uwp.UI"
|
||||||
|
xmlns:cc="using:VDownload.Controls"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="300"
|
||||||
|
d:DesignWidth="400">
|
||||||
|
|
||||||
|
|
||||||
|
<UserControl.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="ms-appx:///Resources/Icons.xaml"/>
|
||||||
|
<ResourceDictionary Source="ms-appx:///Resources/Converters.xaml"/>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
<x:String x:Key="MetadataIconSize">16</x:String>
|
||||||
|
<x:String x:Key="MetadataTextSize">12</x:String>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</UserControl.Resources>
|
||||||
|
|
||||||
|
|
||||||
|
<Grid Padding="10" RowSpacing="40" VerticalAlignment="Stretch">
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup>
|
||||||
|
<VisualState>
|
||||||
|
<VisualState.StateTriggers>
|
||||||
|
<AdaptiveTrigger MinWindowWidth="0"/>
|
||||||
|
</VisualState.StateTriggers>
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.(Grid.Column)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.Width" Value="NaN"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelTitleAndDetailedMetadataGrid.(Grid.Column)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelTitleAndDetailedMetadataGrid.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelTitleAndDetailedMetadataGrid.(Grid.Row)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelTitleAndDetailedMetadataGrid.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorIcon.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorIcon.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorIcon.(Grid.Column)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorIcon.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.(Grid.Row)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.(Grid.Column)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.HorizontalAlignment" Value="Center"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsIcon.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsIcon.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsIcon.(Grid.Column)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsIcon.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.(Grid.Row)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.(Grid.Column)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.HorizontalAlignment" Value="Center"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateIcon.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateIcon.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateIcon.(Grid.Column)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateIcon.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.(Grid.Row)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.(Grid.Column)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.HorizontalAlignment" Value="Center"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationIcon.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationIcon.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationIcon.(Grid.Column)" Value="3"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationIcon.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.(Grid.Row)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.(Grid.Column)" Value="3"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.HorizontalAlignment" Value="Center"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDMetadataR1.Height" Value="Auto"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDMetadataR2.Height" Value="Auto"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDMetadataC1.Width" Value="1*"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDMetadataC2.Width" Value="1*"/>
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState>
|
||||||
|
<VisualState.StateTriggers>
|
||||||
|
<AdaptiveTrigger MinWindowWidth="600"/>
|
||||||
|
</VisualState.StateTriggers>
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.(Grid.Column)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelThumbnailImage.Width" Value="250"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelTitleAndDetailedMetadataGrid.(Grid.Column)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelTitleAndDetailedMetadataGrid.(Grid.ColumnSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelTitleAndDetailedMetadataGrid.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelTitleAndDetailedMetadataGrid.(Grid.RowSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorIcon.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorIcon.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorIcon.(Grid.Column)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorIcon.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.(Grid.Row)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.(Grid.Column)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelAuthorText.HorizontalAlignment" Value="Left"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsIcon.(Grid.Row)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsIcon.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsIcon.(Grid.Column)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsIcon.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.(Grid.Row)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.(Grid.Column)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelViewsText.HorizontalAlignment" Value="Left"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateIcon.(Grid.Row)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateIcon.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateIcon.(Grid.Column)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateIcon.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.(Grid.Row)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.(Grid.Column)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDateText.HorizontalAlignment" Value="Left"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationIcon.(Grid.Row)" Value="3"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationIcon.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationIcon.(Grid.Column)" Value="0"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationIcon.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.(Grid.Row)" Value="3"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.(Grid.RowSpan)" Value="1"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.(Grid.Column)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.(Grid.ColumnSpan)" Value="2"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDurationText.HorizontalAlignment" Value="Left"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDMetadataR1.Height" Value="1*"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDMetadataR2.Height" Value="1*"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDMetadataC1.Width" Value="Auto"/>
|
||||||
|
<Setter Target="HomeVideoAddingPanelDMetadataC2.Width" Value="Auto"/>
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- METADATA PANEL -->
|
||||||
|
<Grid Grid.Row="0" ColumnSpacing="10">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Image x:Name="HomeVideoAddingPanelThumbnailImage" Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="2" Source="{x:Bind ThumbnailImage}"/> <!-- Thumbnail image -->
|
||||||
|
<Grid x:Name="HomeVideoAddingPanelTitleAndDetailedMetadataGrid" Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="2">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid Grid.Row="0" VerticalAlignment="Center">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0" FontSize="18" VerticalAlignment="Center" FontWeight="SemiBold" Text="{x:Bind Title}"/>
|
||||||
|
<AppBarButton Grid.Column="1" Width="40" Height="48" Icon="{x:Bind SourceImage}" Click="HomeVideoAddingPanelSourceButton_Click"/>
|
||||||
|
<AppBarButton Grid.Column="2" Width="40" Height="48" Icon="Add" Click="HomeVideoAddingPanelAddButton_Click"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.Row="1" ColumnSpacing="10" RowSpacing="5">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition x:Name="HomeVideoAddingPanelDMetadataR1" Height="1*"/>
|
||||||
|
<RowDefinition x:Name="HomeVideoAddingPanelDMetadataR2" Height="1*"/>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition x:Name="HomeVideoAddingPanelDMetadataC1" Width="Auto"/>
|
||||||
|
<ColumnDefinition x:Name="HomeVideoAddingPanelDMetadataC2" Width="Auto"/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Image x:Name="HomeVideoAddingPanelAuthorIcon" Grid.Row="0" Grid.RowSpan="1" Grid.Column="0" Grid.ColumnSpan="2" Width="{StaticResource MetadataIconSize}" Source="{ThemeResource AuthorIcon}"/>
|
||||||
|
<TextBlock x:Name="HomeVideoAddingPanelAuthorText" Grid.Row="0" Grid.RowSpan="1" Grid.Column="2" Grid.ColumnSpan="2" HorizontalAlignment="Left" FontSize="{StaticResource MetadataTextSize}" Text="{x:Bind Author}"/>
|
||||||
|
<Image x:Name="HomeVideoAddingPanelViewsIcon" Grid.Row="1" Grid.RowSpan="1" Grid.Column="0" Grid.ColumnSpan="2" Width="{StaticResource MetadataIconSize}" Source="{ThemeResource ViewsIcon}"/>
|
||||||
|
<TextBlock x:Name="HomeVideoAddingPanelViewsText" Grid.Row="1" Grid.RowSpan="1" Grid.Column="2" Grid.ColumnSpan="2" HorizontalAlignment="Left" FontSize="{StaticResource MetadataTextSize}" Text="{x:Bind Views}"/>
|
||||||
|
<Image x:Name="HomeVideoAddingPanelDateIcon" Grid.Row="2" Grid.RowSpan="1" Grid.Column="0" Grid.ColumnSpan="2" Width="{StaticResource MetadataIconSize}" Source="{ThemeResource DateIcon}"/>
|
||||||
|
<TextBlock x:Name="HomeVideoAddingPanelDateText" Grid.Row="2" Grid.RowSpan="1" Grid.Column="2" Grid.ColumnSpan="2" HorizontalAlignment="Left" FontSize="{StaticResource MetadataTextSize}" Text="{x:Bind Date}"/>
|
||||||
|
<Image x:Name="HomeVideoAddingPanelDurationIcon" Grid.Row="3" Grid.RowSpan="1" Grid.Column="0" Grid.ColumnSpan="2" Width="{StaticResource MetadataIconSize}" Source="{ThemeResource DurationIcon}"/>
|
||||||
|
<TextBlock x:Name="HomeVideoAddingPanelDurationText" Grid.Row="3" Grid.RowSpan="1" Grid.Column="2" Grid.ColumnSpan="2" HorizontalAlignment="Left" FontSize="{StaticResource MetadataTextSize}" Text="{x:Bind Duration}"/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- PROPERTIES PANEL -->
|
||||||
|
<ScrollViewer Grid.Row="1">
|
||||||
|
<StackPanel Spacing="30">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock x:Uid="HomeVideoAddingDownloadingOptionsHeaderTextBlock" Margin="0,0,0,10" FontWeight="SemiBold"/>
|
||||||
|
<cc:SettingControl x:Uid="HomeVideoAddingMediaTypeSettingControl" Margin="0,0,0,10" Icon="{ThemeResource MediaTypeIcon}">
|
||||||
|
<cc:SettingControl.SettingContent>
|
||||||
|
<ComboBox x:Name="HomeVideoAddingMediaTypeSettingControlComboBox" Width="150" SelectionChanged="HomeVideoAddingMediaTypeSettingControlComboBox_SelectionChanged"/>
|
||||||
|
</cc:SettingControl.SettingContent>
|
||||||
|
</cc:SettingControl>
|
||||||
|
<cc:SettingControl x:Name="HomeVideoAddingQualitySettingControl" Margin="0,0,0,10" x:Uid="HomeVideoAddingQualitySettingControl" Icon="{ThemeResource QualityIcon}">
|
||||||
|
<cc:SettingControl.SettingContent>
|
||||||
|
<ComboBox x:Name="HomeVideoAddingQualitySettingControlComboBox" Width="150" SelectionChanged="HomeVideoAddingQualitySettingControlComboBox_SelectionChanged"/>
|
||||||
|
</cc:SettingControl.SettingContent>
|
||||||
|
</cc:SettingControl>
|
||||||
|
<cc:SettingControl x:Uid="HomeVideoAddingTrimSettingControl" Icon="{ThemeResource TrimIcon}">
|
||||||
|
<cc:SettingControl.SettingContent>
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||||
|
<TextBox x:Name="HomeVideoAddingTrimStartTextBox" ex:TextBoxExtensions.CustomMask="{x:Bind VideoData.Duration, Converter={StaticResource TimeSpanToTextBoxMaskElementsConverter}}" ex:TextBoxExtensions.Mask="{x:Bind VideoData.Duration, Converter={StaticResource TimeSpanToTextBoxMaskConverter}}" TextChanged="HomeVideoAddingTrimStartTextBox_TextChanged"/>
|
||||||
|
<TextBlock VerticalAlignment="Center" Text="-"/>
|
||||||
|
<TextBox x:Name="HomeVideoAddingTrimEndTextBox" ex:TextBoxExtensions.CustomMask="{x:Bind VideoData.Duration, Converter={StaticResource TimeSpanToTextBoxMaskElementsConverter}}" ex:TextBoxExtensions.Mask="{x:Bind VideoData.Duration, Converter={StaticResource TimeSpanToTextBoxMaskConverter}}" TextChanged="HomeVideoAddingTrimEndTextBox_TextChanged"/>
|
||||||
|
</StackPanel>
|
||||||
|
</cc:SettingControl.SettingContent>
|
||||||
|
</cc:SettingControl>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Spacing="10">
|
||||||
|
<TextBlock x:Uid="HomeVideoAddingFileOptionsHeaderTextBlock" FontWeight="SemiBold"/>
|
||||||
|
<cc:SettingControl x:Uid="HomeVideoAddingFileSettingControl" Icon="{ThemeResource FileIcon}">
|
||||||
|
<cc:SettingControl.SettingContent>
|
||||||
|
<Grid ColumnSpacing="10">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="100"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBox x:Name="HomeVideoAddingFilenameTextBox" Grid.Column="0" HorizontalAlignment="Stretch" MinWidth="150" MaxWidth="300" IsSpellCheckEnabled="False" TextChanged="HomeVideoAddingFilenameTextBox_TextChanged"/>
|
||||||
|
<ComboBox x:Name="HomeVideoAddingExtensionComboBox" Grid.Column="1" HorizontalAlignment="Stretch" SelectionChanged="HomeVideoAddingExtensionComboBox_SelectionChanged"/>
|
||||||
|
</Grid>
|
||||||
|
</cc:SettingControl.SettingContent>
|
||||||
|
</cc:SettingControl>
|
||||||
|
<cc:SettingControl x:Name="HomeVideoAddingLocationSettingControl" x:Uid="HomeVideoAddingLocationSettingControl" Icon="{ThemeResource LocationIcon}">
|
||||||
|
<cc:SettingControl.SettingContent>
|
||||||
|
<Button x:Uid="HomeVideoAddingLocationBrowseButton" Click="HomeVideoAddingLocationBrowseButton_Click"/>
|
||||||
|
</cc:SettingControl.SettingContent>
|
||||||
|
</cc:SettingControl>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
307
VDownload/Views/Home/HomeVideoAddingPanel.xaml.cs
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
using Microsoft.Toolkit.Uwp.UI;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VDownload.Core.Enums;
|
||||||
|
using VDownload.Core.EventArgsObjects;
|
||||||
|
using VDownload.Core.Interfaces;
|
||||||
|
using VDownload.Core.Objects;
|
||||||
|
using VDownload.Core.Services;
|
||||||
|
using Windows.ApplicationModel.Resources;
|
||||||
|
using Windows.Storage;
|
||||||
|
using Windows.Storage.AccessCache;
|
||||||
|
using Windows.Storage.Pickers;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
using Windows.UI.Xaml.Media.Imaging;
|
||||||
|
|
||||||
|
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
||||||
|
|
||||||
|
namespace VDownload.Views.Home
|
||||||
|
{
|
||||||
|
public sealed partial class HomeVideoAddingPanel : UserControl
|
||||||
|
{
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public HomeVideoAddingPanel(IVideoService videoData)
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
|
||||||
|
// Set video service object
|
||||||
|
VideoData = videoData;
|
||||||
|
|
||||||
|
// Set metadata
|
||||||
|
ThumbnailImage = new BitmapImage { UriSource = VideoData.Thumbnail ?? new Uri("ms-appx:///Assets/UnknownThumbnail.png") };
|
||||||
|
SourceImage = new BitmapIcon { ShowAsMonochrome = false, UriSource = new Uri($"ms-appx:///Assets/{VideoData.GetType().Namespace.Split(".").Last()}.png") };
|
||||||
|
Title = VideoData.Title;
|
||||||
|
Author = VideoData.Author;
|
||||||
|
Views = VideoData.Views.ToString();
|
||||||
|
Date = VideoData.Date.ToString(CultureInfo.InstalledUICulture.DateTimeFormat.ShortDatePattern);
|
||||||
|
Duration = $"{Math.Floor(VideoData.Duration.TotalHours):00}:{VideoData.Duration.Minutes:00}:{VideoData.Duration.Seconds:00}";
|
||||||
|
|
||||||
|
|
||||||
|
// Set media type
|
||||||
|
foreach (string mediaType in Enum.GetNames(typeof(MediaType)))
|
||||||
|
{
|
||||||
|
HomeVideoAddingMediaTypeSettingControlComboBox.Items.Add(ResourceLoader.GetForCurrentView().GetString($"MediaType{mediaType}Text"));
|
||||||
|
}
|
||||||
|
HomeVideoAddingMediaTypeSettingControlComboBox.SelectedIndex = (int)Config.GetValue("default_media_type");
|
||||||
|
|
||||||
|
// Set quality
|
||||||
|
foreach (Stream stream in VideoData.Streams)
|
||||||
|
{
|
||||||
|
HomeVideoAddingQualitySettingControlComboBox.Items.Add($"{stream.Height}p{(stream.FrameRate > 0 ? stream.FrameRate.ToString() : "N/A")}");
|
||||||
|
}
|
||||||
|
HomeVideoAddingQualitySettingControlComboBox.SelectedIndex = 0;
|
||||||
|
|
||||||
|
// Set trim start
|
||||||
|
if (Math.Floor(VideoData.Duration.TotalHours) > 0) HomeVideoAddingTrimStartTextBox.Text += $"{new string('0', Math.Floor(VideoData.Duration.TotalHours).ToString().Length)}:";
|
||||||
|
if (Math.Floor(VideoData.Duration.TotalMinutes) > 0) HomeVideoAddingTrimStartTextBox.Text += Math.Floor(VideoData.Duration.TotalHours) > 0 ? "00:" : $"{new string('0', VideoData.Duration.Minutes.ToString().Length)}:";
|
||||||
|
HomeVideoAddingTrimStartTextBox.Text += Math.Floor(VideoData.Duration.TotalMinutes) > 0 ? "00" : $"{new string('0', VideoData.Duration.Seconds.ToString().Length)}";
|
||||||
|
|
||||||
|
// Set trim end
|
||||||
|
if (Math.Floor(VideoData.Duration.TotalHours) > 0) HomeVideoAddingTrimEndTextBox.Text += $"{Math.Floor(VideoData.Duration.TotalHours)}:";
|
||||||
|
if (Math.Floor(VideoData.Duration.TotalMinutes) > 0) HomeVideoAddingTrimEndTextBox.Text += Math.Floor(VideoData.Duration.TotalHours) > 0 ? $"{VideoData.Duration.Minutes:00}:" : $"{VideoData.Duration.Minutes}:";
|
||||||
|
HomeVideoAddingTrimEndTextBox.Text += Math.Floor(VideoData.Duration.TotalMinutes) > 0 ? $"{VideoData.Duration.Seconds:00}" : $"{VideoData.Duration.Seconds}";
|
||||||
|
|
||||||
|
// Set filename
|
||||||
|
string temporaryFilename = (string)Config.GetValue("default_filename");
|
||||||
|
Dictionary<string, string> filenameStandardTemplates = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "<title>", VideoData.Title },
|
||||||
|
{ "<author>", VideoData.Author },
|
||||||
|
{ "<views>", VideoData.Views.ToString() },
|
||||||
|
{ "<id>", VideoData.ID },
|
||||||
|
};
|
||||||
|
foreach (KeyValuePair<string, string> template in filenameStandardTemplates) temporaryFilename = temporaryFilename.Replace(template.Key, template.Value);
|
||||||
|
Dictionary<Regex, IFormattable> filenameFormatTemplates = new Dictionary<Regex, IFormattable>()
|
||||||
|
{
|
||||||
|
{ new Regex(@"<date_pub:(?<format>.*)>"), VideoData.Date },
|
||||||
|
{ new Regex(@"<date_now:(?<format>.*)>"), DateTime.Now },
|
||||||
|
{ new Regex(@"<duration:(?<format>.*)>"), VideoData.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));
|
||||||
|
HomeVideoAddingFilenameTextBox.Text = temporaryFilename;
|
||||||
|
|
||||||
|
// Set location
|
||||||
|
if ((DefaultLocationType)Config.GetValue("default_location_type") == DefaultLocationType.Last && StorageApplicationPermissions.FutureAccessList.ContainsItem("last_media_location"))
|
||||||
|
{
|
||||||
|
Task<StorageFolder> task = StorageApplicationPermissions.FutureAccessList.GetFolderAsync("last_media_location").AsTask();
|
||||||
|
Location = task.Result;
|
||||||
|
HomeVideoAddingLocationSettingControl.Description = Location.Path;
|
||||||
|
}
|
||||||
|
else if ((DefaultLocationType)Config.GetValue("default_location_type") == DefaultLocationType.Selected && StorageApplicationPermissions.FutureAccessList.ContainsItem("selected_media_location"))
|
||||||
|
{
|
||||||
|
Task<StorageFolder> task = StorageApplicationPermissions.FutureAccessList.GetFolderAsync("selected_media_location").AsTask();
|
||||||
|
Location = task.Result;
|
||||||
|
HomeVideoAddingLocationSettingControl.Description = Location.Path;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Location = null;
|
||||||
|
HomeVideoAddingLocationSettingControl.Description = $@"{UserDataPaths.GetDefault().Downloads}\VDownload";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
// BASE VIDEO DATA
|
||||||
|
private IVideoService VideoData { get; set; }
|
||||||
|
|
||||||
|
// VIDEO DATA
|
||||||
|
private ImageSource ThumbnailImage { get; set; }
|
||||||
|
private IconElement SourceImage { get; set; }
|
||||||
|
private string Title { get; set; }
|
||||||
|
private string Author { get; set; }
|
||||||
|
private string Views { get; set; }
|
||||||
|
private string Date { get; set; }
|
||||||
|
private string Duration { get; set; }
|
||||||
|
|
||||||
|
// VIDEO OPTIONS
|
||||||
|
private MediaType MediaType { get; set; }
|
||||||
|
private Stream Stream { get; set; }
|
||||||
|
private TimeSpan TrimStart { get; set; }
|
||||||
|
private TimeSpan TrimEnd { get; set; }
|
||||||
|
private string Filename { get; set; }
|
||||||
|
private MediaFileExtension Extension { get; set; }
|
||||||
|
private StorageFolder Location { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region EVENT HANDLERS VOIDS
|
||||||
|
|
||||||
|
// MEDIA TYPE COMBOBOX SELECTION CHANGED
|
||||||
|
private void HomeVideoAddingMediaTypeSettingControlComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
MediaType = (MediaType)HomeVideoAddingMediaTypeSettingControlComboBox.SelectedIndex;
|
||||||
|
if (HomeVideoAddingMediaTypeSettingControlComboBox.SelectedIndex == (int)MediaType.OnlyAudio)
|
||||||
|
{
|
||||||
|
HomeVideoAddingQualitySettingControl.Visibility = Visibility.Collapsed;
|
||||||
|
HomeVideoAddingQualitySettingControlComboBox.SelectedIndex = VideoData.Streams.Count() - 1;
|
||||||
|
|
||||||
|
HomeVideoAddingExtensionComboBox.Items.Clear();
|
||||||
|
foreach (AudioFileExtension extension in Enum.GetValues(typeof(AudioFileExtension)))
|
||||||
|
{
|
||||||
|
HomeVideoAddingExtensionComboBox.Items.Add(extension);
|
||||||
|
}
|
||||||
|
HomeVideoAddingExtensionComboBox.SelectedIndex = (int)Config.GetValue("default_audio_extension") - 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HomeVideoAddingQualitySettingControl.Visibility = Visibility.Visible;
|
||||||
|
HomeVideoAddingQualitySettingControlComboBox.SelectedIndex = 0;
|
||||||
|
|
||||||
|
HomeVideoAddingExtensionComboBox.Items.Clear();
|
||||||
|
foreach (VideoFileExtension extension in Enum.GetValues(typeof(VideoFileExtension)))
|
||||||
|
{
|
||||||
|
HomeVideoAddingExtensionComboBox.Items.Add(extension);
|
||||||
|
}
|
||||||
|
HomeVideoAddingExtensionComboBox.SelectedIndex = (int)Config.GetValue("default_video_extension");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// QUALITY COMBOBOX SELECTION CHANGED
|
||||||
|
private void HomeVideoAddingQualitySettingControlComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
Stream = VideoData.Streams[HomeVideoAddingQualitySettingControlComboBox.SelectedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TRIM START TEXTBOX TEXT CHANGED
|
||||||
|
private void HomeVideoAddingTrimStartTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!HomeVideoAddingTrimStartTextBox.Text.Contains('_'))
|
||||||
|
{
|
||||||
|
string[] segments = HomeVideoAddingTrimStartTextBox.Text.Split(':').Reverse().ToArray();
|
||||||
|
int.TryParse(segments.ElementAtOrDefault(0), out int seconds);
|
||||||
|
int.TryParse(segments.ElementAtOrDefault(1), out int minutes);
|
||||||
|
int.TryParse(segments.ElementAtOrDefault(2), out int hours);
|
||||||
|
|
||||||
|
TimeSpan parsedTimeSpan = new TimeSpan(hours, minutes, seconds);
|
||||||
|
|
||||||
|
if (parsedTimeSpan < VideoData.Duration && parsedTimeSpan > new TimeSpan(0)) TrimStart = parsedTimeSpan;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TrimStart = new TimeSpan(0);
|
||||||
|
|
||||||
|
string newText = string.Empty;
|
||||||
|
if (Math.Floor(VideoData.Duration.TotalHours) > 0) newText += $"{new string('0', Math.Floor(VideoData.Duration.TotalHours).ToString().Length)}:";
|
||||||
|
if (Math.Floor(VideoData.Duration.TotalMinutes) > 0) newText += Math.Floor(VideoData.Duration.TotalHours) > 0 ? "00:" : $"{new string('0', VideoData.Duration.Minutes.ToString().Length)}:";
|
||||||
|
newText += Math.Floor(VideoData.Duration.TotalMinutes) > 0 ? "00" : $"{new string('0', VideoData.Duration.Seconds.ToString().Length)}";
|
||||||
|
|
||||||
|
if (newText != HomeVideoAddingTrimStartTextBox.Text) HomeVideoAddingTrimStartTextBox.Text = newText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TRIM END TEXTBOX TEXT CHANGED
|
||||||
|
private void HomeVideoAddingTrimEndTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!HomeVideoAddingTrimEndTextBox.Text.Contains('_'))
|
||||||
|
{
|
||||||
|
string[] segments = HomeVideoAddingTrimEndTextBox.Text.Split(':').Reverse().ToArray();
|
||||||
|
int.TryParse(segments.ElementAtOrDefault(0), out int seconds);
|
||||||
|
int.TryParse(segments.ElementAtOrDefault(1), out int minutes);
|
||||||
|
int.TryParse(segments.ElementAtOrDefault(2), out int hours);
|
||||||
|
|
||||||
|
TimeSpan parsedTimeSpan = new TimeSpan(hours, minutes, seconds);
|
||||||
|
|
||||||
|
if (parsedTimeSpan < VideoData.Duration && parsedTimeSpan > new TimeSpan(0)) TrimEnd = parsedTimeSpan;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TrimEnd = VideoData.Duration;
|
||||||
|
|
||||||
|
string newText = string.Empty;
|
||||||
|
if (Math.Floor(VideoData.Duration.TotalHours) > 0) newText += $"{Math.Floor(VideoData.Duration.TotalHours)}:";
|
||||||
|
if (Math.Floor(VideoData.Duration.TotalMinutes) > 0) newText += Math.Floor(VideoData.Duration.TotalHours) > 0 ? $"{TrimEnd.Minutes:00}:" : $"{TrimEnd.Minutes}:";
|
||||||
|
newText += Math.Floor(VideoData.Duration.TotalMinutes) > 0 ? $"{TrimEnd.Seconds:00}" : $"{TrimEnd.Seconds}";
|
||||||
|
|
||||||
|
if (newText != HomeVideoAddingTrimEndTextBox.Text) HomeVideoAddingTrimEndTextBox.Text = newText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILENAME TEXTBOX TEXT CHANGED
|
||||||
|
private void HomeVideoAddingFilenameTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
|
{
|
||||||
|
string oldFilename = HomeVideoAddingFilenameTextBox.Text;
|
||||||
|
string newFilename = oldFilename;
|
||||||
|
foreach (char c in System.IO.Path.GetInvalidFileNameChars()) newFilename = newFilename.Replace(c, ' ');
|
||||||
|
if (oldFilename != newFilename) HomeVideoAddingFilenameTextBox.Text = newFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXTENSION COMBOBOX SELECTION CHANGED
|
||||||
|
private void HomeVideoAddingExtensionComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
Extension = (MediaFileExtension)HomeVideoAddingExtensionComboBox.SelectedIndex + (MediaType == MediaType.OnlyAudio ? 3 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LOCATION BROWSE BUTTON CLICKED
|
||||||
|
private async void HomeVideoAddingLocationBrowseButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
FolderPicker picker = new FolderPicker
|
||||||
|
{
|
||||||
|
SuggestedStartLocation = PickerLocationId.Downloads
|
||||||
|
};
|
||||||
|
picker.FileTypeFilter.Add("*");
|
||||||
|
|
||||||
|
StorageFolder selectedFolder = await picker.PickSingleFolderAsync();
|
||||||
|
|
||||||
|
if (selectedFolder != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await (await selectedFolder.CreateFileAsync("VDownloadLocationAccessTest")).DeleteAsync();
|
||||||
|
StorageApplicationPermissions.FutureAccessList.AddOrReplace("last_media_location", selectedFolder);
|
||||||
|
Location = selectedFolder;
|
||||||
|
HomeVideoAddingLocationSettingControl.Description = Location.Path;
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SOURCE BUTTON CLICKED
|
||||||
|
public async void HomeVideoAddingPanelSourceButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// Launch the website
|
||||||
|
await Windows.System.Launcher.LaunchUriAsync(VideoData.VideoUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ADD BUTTON CLICKED
|
||||||
|
public void HomeVideoAddingPanelAddButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
VideoAddEventArgs args = new VideoAddEventArgs
|
||||||
|
{
|
||||||
|
VideoService = VideoData,
|
||||||
|
MediaType = MediaType,
|
||||||
|
Stream = Stream,
|
||||||
|
TrimStart = TrimStart,
|
||||||
|
TrimEnd = TrimEnd,
|
||||||
|
Filename = Filename,
|
||||||
|
Extension = Extension,
|
||||||
|
Location = Location,
|
||||||
|
};
|
||||||
|
VideoAddRequest?.Invoke(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region EVENT HANDLERS
|
||||||
|
|
||||||
|
public event EventHandler<VideoAddEventArgs> VideoAddRequest;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
15
VDownload/Views/Home/HomeVideoPanel.xaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Class="VDownload.Views.Home.HomeVideoPanel"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:VDownload.Views.Home"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="300"
|
||||||
|
d:DesignWidth="400">
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
27
VDownload/Views/Home/HomeVideoPanel.xaml.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Foundation.Collections;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Controls.Primitives;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
using Windows.UI.Xaml.Input;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
|
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
||||||
|
|
||||||
|
namespace VDownload.Views.Home
|
||||||
|
{
|
||||||
|
public sealed partial class HomeVideoPanel : UserControl
|
||||||
|
{
|
||||||
|
public HomeVideoPanel()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,12 +50,12 @@
|
|||||||
<muxc:NavigationView.FooterMenuItems>
|
<muxc:NavigationView.FooterMenuItems>
|
||||||
<muxc:NavigationViewItem x:Uid="MainPageNavigationPanelAboutItem" Tag="about" Content="About">
|
<muxc:NavigationViewItem x:Uid="MainPageNavigationPanelAboutItem" Tag="about" Content="About">
|
||||||
<muxc:NavigationViewItem.Icon>
|
<muxc:NavigationViewItem.Icon>
|
||||||
<BitmapIcon UriSource="ms-appx:///Assets/Icons/MainPage/About.png"/>
|
<PathIcon Data="M3331.25,1.389c-1833.78,-0 -3325.69,1492.85 -3325.69,3327.78c-0,1834.92 1491.92,3327.78 3325.69,3327.78c1833.78,0 3325.69,-1492.85 3325.69,-3327.78c0,-1834.92 -1491.92,-3327.78 -3325.69,-3327.78Zm0,499.167c1564.18,-0 2826.84,1263.45 2826.84,2828.61c0,1565.15 -1262.66,2828.61 -2826.84,2828.61c-1564.18,-0 -2826.84,-1263.46 -2826.84,-2828.61c-0,-1565.16 1262.66,-2828.61 2826.84,-2828.61Zm0,1164.72c-182.442,-0 -332.569,150.221 -332.569,332.778c-0,182.556 150.127,332.777 332.569,332.777c182.442,0 332.569,-150.221 332.569,-332.777c0,-182.557 -150.127,-332.778 -332.569,-332.778Zm-3.897,1161.15c-136.709,2.137 -247.491,116.362 -245.53,253.158l-0,1830.28c-0.017,1.177 -0.025,2.353 -0.025,3.53c-0,136.931 112.607,249.608 249.452,249.608c136.845,0 249.452,-112.677 249.452,-249.608c0,-1.177 -0.008,-2.353 -0.025,-3.53l0,-1830.28c0.017,-1.193 0.026,-2.386 0.026,-3.58c-0,-136.931 -112.607,-249.608 -249.452,-249.608c-1.3,-0 -2.599,0.01 -3.898,0.03Z"/>
|
||||||
</muxc:NavigationViewItem.Icon>
|
</muxc:NavigationViewItem.Icon>
|
||||||
</muxc:NavigationViewItem>
|
</muxc:NavigationViewItem>
|
||||||
<muxc:NavigationViewItem x:Uid="MainPageNavigationPanelSourcesItem" Tag="sources" Content="Sources">
|
<muxc:NavigationViewItem x:Uid="MainPageNavigationPanelSourcesItem" Tag="sources" Content="Sources">
|
||||||
<muxc:NavigationViewItem.Icon>
|
<muxc:NavigationViewItem.Icon>
|
||||||
<BitmapIcon UriSource="ms-appx:///Assets/Icons/MainPage/Sources.png"/>
|
<PathIcon Data="M959.759,-4.167c-33.26,0 -65.978,1.941 -98.383,5.426c-64.583,6.944 -127.292,20.746 -187.509,40.509c-302.561,99.296 -541.778,351.698 -635.887,670.935c-18.731,63.536 -31.812,129.701 -38.394,197.844c-0.011,0.119 0.012,0.242 0,0.362c-3.279,34.075 -5.142,68.472 -5.142,103.443l0,4629.63c0,559.218 435.309,1018.52 965.315,1018.52l4738.82,0c530.005,0 965.314,-459.301 965.314,-1018.52l-0,-4629.63c-0,-35.074 -1.801,-69.606 -5.142,-103.805c-6.582,-68.143 -19.663,-134.308 -38.393,-197.844c-94.109,-319.237 -333.327,-571.639 -635.887,-670.935c-60.218,-19.763 -122.926,-33.565 -187.51,-40.509c-0.113,-0.012 -0.23,0.012 -0.343,-0c-32.302,-3.501 -64.914,-5.426 -98.039,-5.426l-4738.82,0Zm-0,555.556c145.323,-0 263.267,124.444 263.267,277.778c0,153.333 -117.944,277.777 -263.267,277.777c-145.324,0 -263.268,-124.444 -263.268,-277.777c0,-153.334 117.944,-277.778 263.268,-277.778Zm877.558,-0c145.324,-0 263.268,124.444 263.268,277.778c-0,153.333 -117.944,277.777 -263.268,277.777c-145.323,0 -263.267,-124.444 -263.267,-277.777c-0,-153.334 117.944,-277.778 263.267,-277.778Zm1053.07,-0l2808.19,-0c145.323,-0 263.267,124.444 263.267,277.778c0,153.333 -117.944,277.777 -263.267,277.777l-2808.19,0c-145.323,0 -263.267,-124.444 -263.267,-277.777c-0,-153.334 117.944,-277.778 263.267,-277.778Zm-2369.41,1111.11l5616.37,0l-0,3981.48c-0,258.931 -193.374,462.963 -438.779,462.963l-4738.82,0c-245.405,0 -438.779,-204.032 -438.779,-462.963l-0,-3981.48Zm2247.03,1111.11c-166.006,3.577 -316.401,144.126 -316.401,339.265l0,1543.69c0,260.371 267.48,423.128 482.657,294.054l1285.49,-771.484c216.757,-130.185 216.757,-458.831 0,-588.831l-1285.49,-771.485c-53.794,-32.268 -110.92,-46.403 -166.256,-45.211Z"/>
|
||||||
</muxc:NavigationViewItem.Icon>
|
</muxc:NavigationViewItem.Icon>
|
||||||
</muxc:NavigationViewItem>
|
</muxc:NavigationViewItem>
|
||||||
</muxc:NavigationView.FooterMenuItems>
|
</muxc:NavigationView.FooterMenuItems>
|
||||||
|
|||||||
@@ -24,10 +24,10 @@
|
|||||||
<StackPanel Grid.Row="2" Spacing="10">
|
<StackPanel Grid.Row="2" Spacing="10">
|
||||||
<cc:SettingControl x:Name="SourcesTwitchSettingControl" x:Uid="SourcesTwitchSettingControl" Grid.Row="0" Title="Twitch"> <!-- Twitch -->
|
<cc:SettingControl x:Name="SourcesTwitchSettingControl" x:Uid="SourcesTwitchSettingControl" Grid.Row="0" Title="Twitch"> <!-- Twitch -->
|
||||||
<cc:SettingControl.Icon>
|
<cc:SettingControl.Icon>
|
||||||
<BitmapIcon UriSource="ms-appx:///Assets/Icons/Sources/Twitch.png" ShowAsMonochrome="False"/>
|
<BitmapImage UriSource="ms-appx:///Assets/Twitch.png"/>
|
||||||
</cc:SettingControl.Icon>
|
</cc:SettingControl.Icon>
|
||||||
<cc:SettingControl.SettingContent>
|
<cc:SettingControl.SettingContent>
|
||||||
<Button x:Name="SourcesTwitchLoginButton" Click="SourcesTwitchLoginButton_Click"/>
|
<Button x:Name="SourcesTwitchLoginButton" IsEnabled="False" Click="SourcesTwitchLoginButton_Click"/>
|
||||||
</cc:SettingControl.SettingContent>
|
</cc:SettingControl.SettingContent>
|
||||||
</cc:SettingControl>
|
</cc:SettingControl>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -1,25 +1,14 @@
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.Web.WebView2.Core;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using System.Text;
|
|
||||||
using Windows.ApplicationModel.Resources;
|
using Windows.ApplicationModel.Resources;
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.UI;
|
|
||||||
using Windows.UI.WindowManagement;
|
using Windows.UI.WindowManagement;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Controls.Primitives;
|
|
||||||
using Windows.UI.Xaml.Data;
|
|
||||||
using Windows.UI.Xaml.Hosting;
|
using Windows.UI.Xaml.Hosting;
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
namespace VDownload.Views.Sources
|
namespace VDownload.Views.Sources
|
||||||
@@ -43,133 +32,144 @@ namespace VDownload.Views.Sources
|
|||||||
protected override async void OnNavigatedTo(NavigationEventArgs e)
|
protected override async void OnNavigatedTo(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
// Check Twitch
|
// Check Twitch
|
||||||
string twitchAccessToken = await Core.Services.Sources.Twitch.Auth.ReadAccessTokenAsync();
|
try
|
||||||
var twitchAccessTokenValidation = await Core.Services.Sources.Twitch.Auth.ValidateAccessTokenAsync(twitchAccessToken);
|
|
||||||
if (twitchAccessToken != null && twitchAccessTokenValidation.IsValid)
|
|
||||||
{
|
{
|
||||||
Debug.WriteLine("Twitch authentication status: LOGGED_IN");
|
string twitchAccessToken = await Core.Services.Sources.Twitch.Auth.ReadAccessTokenAsync();
|
||||||
Debug.WriteLine(twitchAccessTokenValidation.ExpirationDate.Value.ToString("dd.MM.yyyy"));
|
(bool IsValid, string Login, DateTime? ExpirationDate) twitchAccessTokenValidation = await Core.Services.Sources.Twitch.Auth.ValidateAccessTokenAsync(twitchAccessToken);
|
||||||
SourcesTwitchSettingControl.Description = $"{ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionLoggedIn")} {twitchAccessTokenValidation.Login}";
|
if (twitchAccessToken != null && twitchAccessTokenValidation.IsValid)
|
||||||
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextLoggedIn");
|
{
|
||||||
|
SourcesTwitchSettingControl.Description = $"{ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionLoggedIn")} {twitchAccessTokenValidation.Login}";
|
||||||
|
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextLoggedIn");
|
||||||
|
SourcesTwitchLoginButton.IsEnabled = true;
|
||||||
|
}
|
||||||
|
else if (twitchAccessToken == null || !twitchAccessTokenValidation.IsValid)
|
||||||
|
{
|
||||||
|
if (twitchAccessToken != null) await Core.Services.Sources.Twitch.Auth.DeleteAccessTokenAsync();
|
||||||
|
SourcesTwitchSettingControl.Description = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionNotLoggedIn");
|
||||||
|
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextNotLoggedIn");
|
||||||
|
SourcesTwitchLoginButton.IsEnabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (twitchAccessToken == null || !twitchAccessTokenValidation.IsValid)
|
catch (WebException wex)
|
||||||
{
|
{
|
||||||
if (twitchAccessToken != null)
|
if (wex.Response == null)
|
||||||
{
|
{
|
||||||
Debug.WriteLine("Twitch authentication status: ACCESS_TOKEN_READ_BUT_NOT_VALID");
|
SourcesTwitchSettingControl.Description = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionInternetConnectionError");
|
||||||
await Core.Services.Sources.Twitch.Auth.DeleteAccessTokenAsync();
|
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextNotLoggedIn");
|
||||||
}
|
}
|
||||||
else
|
else throw;
|
||||||
{
|
|
||||||
Debug.WriteLine("Twitch authentication status: ACCESS_TOKEN_NOT_FOUND");
|
|
||||||
}
|
|
||||||
SourcesTwitchSettingControl.Description = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionNotLoggedIn");
|
|
||||||
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextNotLoggedIn");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TWITCH LOGIN BUTTON CLICKED
|
// TWITCH LOGIN BUTTON CLICKED
|
||||||
private async void SourcesTwitchLoginButton_Click(object sender, RoutedEventArgs e)
|
private async void SourcesTwitchLoginButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
string accessToken = await Core.Services.Sources.Twitch.Auth.ReadAccessTokenAsync();
|
try
|
||||||
var accessTokenValidation = await Core.Services.Sources.Twitch.Auth.ValidateAccessTokenAsync(accessToken);
|
|
||||||
if (accessToken != null && accessTokenValidation.IsValid)
|
|
||||||
{
|
{
|
||||||
Debug.WriteLine("Log out from Twitch (revoke and delete access token)");
|
string accessToken = await Core.Services.Sources.Twitch.Auth.ReadAccessTokenAsync();
|
||||||
|
var accessTokenValidation = await Core.Services.Sources.Twitch.Auth.ValidateAccessTokenAsync(accessToken);
|
||||||
// Revoke access token
|
if (accessToken != null && accessTokenValidation.IsValid)
|
||||||
await Core.Services.Sources.Twitch.Auth.RevokeAccessTokenAsync(accessToken);
|
|
||||||
Debug.WriteLine($"Twitch access token ({accessToken}) revoked successfully");
|
|
||||||
|
|
||||||
// Delete access token
|
|
||||||
await Core.Services.Sources.Twitch.Auth.DeleteAccessTokenAsync();
|
|
||||||
Debug.WriteLine($"Twitch access token ({accessToken}) deleted successfully");
|
|
||||||
|
|
||||||
// Update Twitch SettingControl
|
|
||||||
Debug.WriteLine("Twitch authentication status: ACCESS_TOKEN_NOT_FOUND");
|
|
||||||
SourcesTwitchSettingControl.Description = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionNotLoggedIn");
|
|
||||||
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextNotLoggedIn");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.WriteLine("Log in to Twitch (get, validate and save access token)");
|
|
||||||
|
|
||||||
// Open new window
|
|
||||||
AppWindow TwitchAuthWindow = await AppWindow.TryCreateAsync();
|
|
||||||
TwitchAuthWindow.Title = "Twitch Authentication";
|
|
||||||
|
|
||||||
WebView2 TwitchAuthWebView = new WebView2();
|
|
||||||
await TwitchAuthWebView.EnsureCoreWebView2Async();
|
|
||||||
TwitchAuthWebView.Source = Core.Services.Sources.Twitch.Auth.AuthorizationUrl;
|
|
||||||
ElementCompositionPreview.SetAppWindowContent(TwitchAuthWindow, TwitchAuthWebView);
|
|
||||||
|
|
||||||
TwitchAuthWindow.TryShowAsync();
|
|
||||||
|
|
||||||
// NavigationStarting event (only when redirected)
|
|
||||||
TwitchAuthWebView.NavigationStarting += async (s, a) =>
|
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"TwitchAuthWebView redirected to {a.Uri}");
|
// Revoke access token
|
||||||
if (new Uri(a.Uri).Host == Core.Services.Sources.Twitch.Auth.RedirectUrl.Host)
|
await Core.Services.Sources.Twitch.Auth.RevokeAccessTokenAsync(accessToken);
|
||||||
|
|
||||||
|
// Delete access token
|
||||||
|
await Core.Services.Sources.Twitch.Auth.DeleteAccessTokenAsync();
|
||||||
|
|
||||||
|
// Update Twitch SettingControl
|
||||||
|
SourcesTwitchSettingControl.Description = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionNotLoggedIn");
|
||||||
|
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextNotLoggedIn");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Open new window
|
||||||
|
AppWindow TwitchAuthWindow = await AppWindow.TryCreateAsync();
|
||||||
|
TwitchAuthWindow.Title = "Twitch Authentication";
|
||||||
|
|
||||||
|
WebView2 TwitchAuthWebView = new WebView2();
|
||||||
|
await TwitchAuthWebView.EnsureCoreWebView2Async();
|
||||||
|
TwitchAuthWebView.Source = Core.Services.Sources.Twitch.Auth.AuthorizationUrl;
|
||||||
|
ElementCompositionPreview.SetAppWindowContent(TwitchAuthWindow, TwitchAuthWebView);
|
||||||
|
|
||||||
|
TwitchAuthWindow.TryShowAsync();
|
||||||
|
|
||||||
|
// NavigationStarting event (only when redirected)
|
||||||
|
TwitchAuthWebView.NavigationStarting += async (s, a) =>
|
||||||
{
|
{
|
||||||
// Close window
|
if (new Uri(a.Uri).Host == Core.Services.Sources.Twitch.Auth.RedirectUrl.Host)
|
||||||
await TwitchAuthWindow.CloseAsync();
|
|
||||||
|
|
||||||
// Get response
|
|
||||||
string response = a.Uri.Replace(Core.Services.Sources.Twitch.Auth.RedirectUrl.OriginalString, "");
|
|
||||||
|
|
||||||
if (response[1] == '#')
|
|
||||||
{
|
{
|
||||||
// Get access token
|
// Close window
|
||||||
accessToken = response.Split('&')[0].Replace("/#access_token=", "");
|
await TwitchAuthWindow.CloseAsync();
|
||||||
Debug.WriteLine($"Twitch access token got successfully ({accessToken})");
|
|
||||||
|
|
||||||
// Check token
|
// Get response
|
||||||
accessTokenValidation = await Core.Services.Sources.Twitch.Auth.ValidateAccessTokenAsync(accessToken);
|
string response = a.Uri.Replace(Core.Services.Sources.Twitch.Auth.RedirectUrl.OriginalString, "");
|
||||||
Debug.WriteLine("Twitch access token validated successfully");
|
|
||||||
|
|
||||||
// Save token
|
if (response[1] == '#')
|
||||||
await Core.Services.Sources.Twitch.Auth.SaveAccessTokenAsync(accessToken);
|
|
||||||
Debug.WriteLine("Twitch access token saved successfully");
|
|
||||||
|
|
||||||
// Update Twitch SettingControl
|
|
||||||
Debug.WriteLine("Twitch authentication status: LOGGED_IN");
|
|
||||||
SourcesTwitchSettingControl.Description = $"{ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionLoggedIn")} {accessTokenValidation.Login}";
|
|
||||||
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextLoggedIn");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Ignored errors
|
|
||||||
string[] ignoredErrors = new[]
|
|
||||||
{
|
{
|
||||||
|
// Get access token
|
||||||
|
accessToken = response.Split('&')[0].Replace("/#access_token=", "");
|
||||||
|
|
||||||
|
// Check token
|
||||||
|
accessTokenValidation = await Core.Services.Sources.Twitch.Auth.ValidateAccessTokenAsync(accessToken);
|
||||||
|
|
||||||
|
// Save token
|
||||||
|
await Core.Services.Sources.Twitch.Auth.SaveAccessTokenAsync(accessToken);
|
||||||
|
|
||||||
|
// Update Twitch SettingControl
|
||||||
|
SourcesTwitchSettingControl.Description = $"{ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionLoggedIn")} {accessTokenValidation.Login}";
|
||||||
|
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextLoggedIn");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Ignored errors
|
||||||
|
string[] ignoredErrors = new[]
|
||||||
|
{
|
||||||
"The user denied you access",
|
"The user denied you access",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Errors translation
|
// Errors translation
|
||||||
Dictionary<string, string> errorsTranslation = new Dictionary<string, string>
|
Dictionary<string, string> errorsTranslation = new Dictionary<string, string>
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get error info
|
|
||||||
string errorInfo = (response.Split('&')[1].Replace("error_description=", "")).Replace('+', ' ');
|
|
||||||
if (!ignoredErrors.Contains(errorInfo))
|
|
||||||
{
|
|
||||||
// Error
|
|
||||||
ContentDialog loginErrorDialog = new ContentDialog
|
|
||||||
{
|
{
|
||||||
Title = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginErrorDialogTitle"),
|
|
||||||
Content = errorsTranslation.Keys.Contains(errorInfo) ? errorsTranslation[errorInfo] : $"{ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginErrorDialogDescriptionUnknown")} ({errorInfo})",
|
|
||||||
CloseButtonText = "OK",
|
|
||||||
};
|
|
||||||
await loginErrorDialog.ShowAsync();
|
|
||||||
}
|
|
||||||
Debug.WriteLine($"Log in to Twitch failed ({errorInfo})");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear cache
|
};
|
||||||
TwitchAuthWebView.CoreWebView2.CookieManager.DeleteAllCookies();
|
|
||||||
}
|
// Get error info
|
||||||
};
|
string errorInfo = (response.Split('&')[1].Replace("error_description=", "")).Replace('+', ' ');
|
||||||
|
if (!ignoredErrors.Contains(errorInfo))
|
||||||
|
{
|
||||||
|
// Error
|
||||||
|
ContentDialog loginErrorDialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginErrorDialogTitle"),
|
||||||
|
Content = errorsTranslation.Keys.Contains(errorInfo) ? errorsTranslation[errorInfo] : $"{ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginErrorDialogDescriptionUnknown")} ({errorInfo})",
|
||||||
|
CloseButtonText = ResourceLoader.GetForCurrentView().GetString("CloseErrorDialogButtonText"),
|
||||||
|
};
|
||||||
|
await loginErrorDialog.ShowAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear cache
|
||||||
|
TwitchAuthWebView.CoreWebView2.CookieManager.DeleteAllCookies();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (WebException wex)
|
||||||
|
{
|
||||||
|
if (wex.Response == null)
|
||||||
|
{
|
||||||
|
SourcesTwitchSettingControl.Description = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionInternetConnectionError");
|
||||||
|
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextNotLoggedIn");
|
||||||
|
SourcesTwitchLoginButton.IsEnabled = false;
|
||||||
|
ContentDialog internetAccessErrorDialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginErrorDialogTitle"),
|
||||||
|
Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginErrorDialogDescriptionInternetConnectionError"),
|
||||||
|
CloseButtonText = ResourceLoader.GetForCurrentView().GetString("CloseErrorDialogButtonText"),
|
||||||
|
};
|
||||||
|
await internetAccessErrorDialog.ShowAsync();
|
||||||
|
}
|
||||||
|
else throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||