1.0-dev17 (Subscription page created)

This commit is contained in:
2022-05-05 15:06:10 +02:00
Unverified
parent b4347f2b5c
commit e23258a638
34 changed files with 121 additions and 526 deletions

View File

@@ -4,6 +4,6 @@ namespace VDownload.Core.EventArgs
{ {
public class PlaylistSearchSuccessedEventArgs : System.EventArgs public class PlaylistSearchSuccessedEventArgs : System.EventArgs
{ {
public IPlaylistService PlaylistService { get; set; } public IPlaylist PlaylistService { get; set; }
} }
} }

View File

@@ -4,6 +4,6 @@ namespace VDownload.Core.EventArgs
{ {
public class VideoSearchSuccessedEventArgs : System.EventArgs public class VideoSearchSuccessedEventArgs : System.EventArgs
{ {
public IVideoService VideoService { get; set; } public IVideo Video { get; set; }
} }
} }

View File

@@ -1,8 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VDownload.Core.Exceptions namespace VDownload.Core.Exceptions
{ {

View File

@@ -1,31 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace VDownload.Core.Interfaces
{
public interface IPlaylistService
{
#region PROPERTIES
// PLAYLIST PROPERTIES
string ID { get; }
Uri PlaylistUrl { get; }
string Name { get; }
IVideoService[] Videos { get; }
#endregion
#region METHODS
// GET PLAYLIST METADATA
Task GetMetadataAsync(CancellationToken cancellationToken = default);
// GET VIDEOS FROM PLAYLIST
Task GetVideosAsync(int numberOfVideos, CancellationToken cancellationToken = default);
#endregion
}
}

View File

@@ -1,47 +0,0 @@
using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using VDownload.Core.Enums;
using VDownload.Core.Structs;
using Windows.Storage;
namespace VDownload.Core.Interfaces
{
public interface IVideoService
{
#region PROPERTIES
// VIDEO PROPERTIES
string ID { get; }
Uri VideoUrl { get; }
Metadata Metadata { get; }
BaseStream[] BaseStreams { get; }
#endregion
#region METHODS
// GET VIDEO METADATA
Task GetMetadataAsync(CancellationToken cancellationToken = default);
// GET VIDEO STREAMS
Task GetStreamsAsync(CancellationToken cancellationToken = default);
// DOWNLOAD VIDEO
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, BaseStream baseStream, MediaFileExtension extension, MediaType mediaType, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default);
#endregion
#region EVENT HANDLERS
event EventHandler<EventArgs.ProgressChangedEventArgs> DownloadingProgressChanged;
event EventHandler<EventArgs.ProgressChangedEventArgs> ProcessingProgressChanged;
#endregion
}
}

View File

@@ -6,7 +6,7 @@ using Windows.Storage;
namespace VDownload.Core.Services namespace VDownload.Core.Services
{ {
public class Config public static class Config
{ {
#region CONSTANTS #region CONSTANTS

View File

@@ -1,54 +0,0 @@
using System.Text.RegularExpressions;
using VDownload.Core.Enums;
namespace VDownload.Core.Services
{
public class Source
{
#region CONSTANTS
// VIDEO SOURCES REGULAR EXPRESSIONS
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),
};
// PLAYLIST SOURCES REGULAR EXPRESSIONS
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
// GET VIDEO SOURCE
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);
}
// GET PLAYLIST SOURCE
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
}
}

View File

@@ -7,19 +7,22 @@ using System.Net;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using VDownload.Core.Enums;
using VDownload.Core.Exceptions; using VDownload.Core.Exceptions;
using VDownload.Core.Interfaces; using VDownload.Core.Interfaces;
using VDownload.Core.Services.Sources.Twitch.Helpers; using VDownload.Core.Services.Sources.Twitch.Helpers;
namespace VDownload.Core.Services.Sources.Twitch namespace VDownload.Core.Services.Sources.Twitch
{ {
public class Channel : IPlaylistService [Serializable]
public class Channel : IPlaylist
{ {
#region CONSTRUCTORS #region CONSTRUCTORS
public Channel(string id) public Channel(string id)
{ {
ID = id; ID = id;
Source = PlaylistSource.TwitchChannel;
} }
#endregion #endregion
@@ -29,9 +32,11 @@ namespace VDownload.Core.Services.Sources.Twitch
#region PROPERTIES #region PROPERTIES
public string ID { get; private set; } public string ID { get; private set; }
public Uri PlaylistUrl { get; private set; } public PlaylistSource Source { get; private set; }
public Uri Url { get; private set; }
public string Name { get; private set; } public string Name { get; private set; }
public IVideoService[] Videos { get; private set; } public IVideo[] Videos { get; private set; }
private string UniqueUserID { get; set; }
#endregion #endregion
@@ -55,14 +60,15 @@ namespace VDownload.Core.Services.Sources.Twitch
} }
// Create unified playlist url // Create unified playlist url
PlaylistUrl = new Uri($"https://twitch.tv/{ID}"); Url = new Uri($"https://twitch.tv/{ID}");
// Set parameters // Set parameters
if (!ID.All(char.IsDigit)) ID = (string)response["id"]; UniqueUserID = (string)response["id"];
Name = (string)response["display_name"]; Name = (string)response["display_name"];
} }
// GET CHANNEL VIDEOS // GET CHANNEL VIDEOS
public async Task GetVideosAsync(CancellationToken cancellationToken = default) => await GetVideosAsync(0, cancellationToken);
public async Task GetVideosAsync(int numberOfVideos, CancellationToken cancellationToken = default) public async Task GetVideosAsync(int numberOfVideos, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@@ -89,7 +95,7 @@ namespace VDownload.Core.Services.Sources.Twitch
JToken response = null; JToken response = null;
using (WebClient client = await Client.Helix()) using (WebClient client = await Client.Helix())
{ {
client.QueryString.Add("user_id", ID); client.QueryString.Add("user_id", UniqueUserID);
client.QueryString.Add("first", count.ToString()); client.QueryString.Add("first", count.ToString());
client.QueryString.Add("after", pagination); client.QueryString.Add("after", pagination);
response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/videos")); response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/videos"));

View File

@@ -18,13 +18,15 @@ using Windows.Storage;
namespace VDownload.Core.Services.Sources.Twitch namespace VDownload.Core.Services.Sources.Twitch
{ {
public class Clip : IVideoService [Serializable]
public class Clip : IVideo
{ {
#region CONSTRUCTORS #region CONSTRUCTORS
public Clip(string id) public Clip(string id)
{ {
ID = id; ID = id;
Source = VideoSource.TwitchClip;
} }
#endregion #endregion
@@ -33,8 +35,9 @@ namespace VDownload.Core.Services.Sources.Twitch
#region PROPERTIES #region PROPERTIES
public VideoSource Source { get; private set; }
public string ID { get; private set; } public string ID { get; private set; }
public Uri VideoUrl { get; private set; } public Uri Url { get; private set; }
public Metadata Metadata { get; private set; } public Metadata Metadata { get; private set; }
public BaseStream[] BaseStreams { get; private set; } public BaseStream[] BaseStreams { get; private set; }
@@ -60,7 +63,7 @@ namespace VDownload.Core.Services.Sources.Twitch
} }
// Create unified video url // Create unified video url
VideoUrl = new Uri($"https://clips.twitch.tv/{ID}"); Url = new Uri($"https://clips.twitch.tv/{ID}");
// Set metadata // Set metadata
Metadata = new Metadata() Metadata = new Metadata()

View File

@@ -8,17 +8,12 @@ using Windows.Storage;
namespace VDownload.Core.Services.Sources.Twitch.Helpers namespace VDownload.Core.Services.Sources.Twitch.Helpers
{ {
public class Auth public static class Auth
{ {
#region CONSTANTS #region CONSTANTS
// CLIENT ID
public readonly static string ClientID = "yukkqkwp61wsv3u1pya17crpyaa98y"; public readonly static string ClientID = "yukkqkwp61wsv3u1pya17crpyaa98y";
// GQL API CLIENT ID
public readonly static string GQLApiClientID = "kimne78kx3ncx6brgo4mv6wki5h1ko"; public readonly static string GQLApiClientID = "kimne78kx3ncx6brgo4mv6wki5h1ko";
// REDIRECT URL
public readonly static Uri RedirectUrl = new Uri("https://www.vd.com"); public readonly static Uri RedirectUrl = new Uri("https://www.vd.com");
// AUTHORIZATION URL // AUTHORIZATION URL
@@ -35,16 +30,13 @@ namespace VDownload.Core.Services.Sources.Twitch.Helpers
#region METHODS #region METHODS
// READ ACCESS TOKEN
public static async Task<string> ReadAccessTokenAsync() public static async Task<string> ReadAccessTokenAsync()
{ {
try try
{ {
// Get file
StorageFolder authDataFolder = await ApplicationData.Current.LocalCacheFolder.GetFolderAsync("AuthData"); StorageFolder authDataFolder = await ApplicationData.Current.LocalCacheFolder.GetFolderAsync("AuthData");
StorageFile authDataFile = await authDataFolder.GetFileAsync("Twitch.auth"); StorageFile authDataFile = await authDataFolder.GetFileAsync("Twitch.auth");
// Return data
return await FileIO.ReadTextAsync(authDataFile); return await FileIO.ReadTextAsync(authDataFile);
} }
catch (FileNotFoundException) catch (FileNotFoundException)
@@ -53,42 +45,33 @@ namespace VDownload.Core.Services.Sources.Twitch.Helpers
} }
} }
// SAVE ACCESS TOKEN
public static async Task SaveAccessTokenAsync(string accessToken) public static async Task SaveAccessTokenAsync(string accessToken)
{ {
// Get file
StorageFolder authDataFolder = await ApplicationData.Current.LocalCacheFolder.CreateFolderAsync("AuthData", CreationCollisionOption.OpenIfExists); StorageFolder authDataFolder = await ApplicationData.Current.LocalCacheFolder.CreateFolderAsync("AuthData", CreationCollisionOption.OpenIfExists);
StorageFile authDataFile = await authDataFolder.CreateFileAsync("Twitch.auth", CreationCollisionOption.ReplaceExisting); StorageFile authDataFile = await authDataFolder.CreateFileAsync("Twitch.auth", CreationCollisionOption.ReplaceExisting);
// Save data
await FileIO.WriteTextAsync(authDataFile, accessToken); await FileIO.WriteTextAsync(authDataFile, accessToken);
} }
// DELETE ACCESS TOKEN
public static async Task DeleteAccessTokenAsync() public static async Task DeleteAccessTokenAsync()
{ {
try try
{ {
// Get file
StorageFolder authDataFolder = await ApplicationData.Current.LocalCacheFolder.GetFolderAsync("AuthData"); StorageFolder authDataFolder = await ApplicationData.Current.LocalCacheFolder.GetFolderAsync("AuthData");
StorageFile authDataFile = await authDataFolder.GetFileAsync("Twitch.auth"); StorageFile authDataFile = await authDataFolder.GetFileAsync("Twitch.auth");
// Delete file
await authDataFile.DeleteAsync(); await authDataFile.DeleteAsync();
} }
catch (FileNotFoundException) { } catch (FileNotFoundException) { }
} }
// VALIDATE ACCESS TOKEN
public static async Task<(bool IsValid, string Login, DateTime? ExpirationDate)> ValidateAccessTokenAsync(string accessToken) public static async Task<(bool IsValid, string Login, DateTime? ExpirationDate)> ValidateAccessTokenAsync(string accessToken)
{ {
// Create client
WebClient client = new WebClient { Encoding = Encoding.UTF8 }; WebClient client = new WebClient { Encoding = Encoding.UTF8 };
client.Headers.Add("Authorization", $"Bearer {accessToken}"); client.Headers.Add("Authorization", $"Bearer {accessToken}");
try try
{ {
// Check access token
JObject response = JObject.Parse(await client.DownloadStringTaskAsync("https://id.twitch.tv/oauth2/validate")); JObject response = JObject.Parse(await client.DownloadStringTaskAsync("https://id.twitch.tv/oauth2/validate"));
string login = response["login"].ToString(); string login = response["login"].ToString();
@@ -108,13 +91,10 @@ namespace VDownload.Core.Services.Sources.Twitch.Helpers
} }
} }
// REVOKE ACCESS TOKEN
public static async Task RevokeAccessTokenAsync(string accessToken) public static async Task RevokeAccessTokenAsync(string accessToken)
{ {
// Create client
WebClient client = new WebClient { Encoding = Encoding.UTF8 }; WebClient client = new WebClient { Encoding = Encoding.UTF8 };
// Revoke access token
await client.UploadStringTaskAsync(new Uri("https://id.twitch.tv/oauth2/revoke"), $"client_id={ClientID}&token={accessToken}"); await client.UploadStringTaskAsync(new Uri("https://id.twitch.tv/oauth2/revoke"), $"client_id={ClientID}&token={accessToken}");
} }

View File

@@ -4,34 +4,28 @@ using VDownload.Core.Exceptions;
namespace VDownload.Core.Services.Sources.Twitch.Helpers namespace VDownload.Core.Services.Sources.Twitch.Helpers
{ {
internal class Client internal static class Client
{ {
internal static async Task<WebClient> Helix() internal static async Task<WebClient> Helix()
{ {
// 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();
// Check access token
var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken); var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken);
if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException(); if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException();
// Create client
WebClient client = new WebClient(); WebClient client = new WebClient();
client.Headers.Add("Authorization", $"Bearer {accessToken}"); client.Headers.Add("Authorization", $"Bearer {accessToken}");
client.Headers.Add("Client-Id", Auth.ClientID); client.Headers.Add("Client-Id", Auth.ClientID);
// Return client
return client; return client;
} }
internal static WebClient GQL() internal static WebClient GQL()
{ {
// Create client
WebClient client = new WebClient(); WebClient client = new WebClient();
client.Headers.Add("Client-Id", Auth.GQLApiClientID); client.Headers.Add("Client-Id", Auth.GQLApiClientID);
// Return client
return client; return client;
} }
} }

View File

@@ -17,13 +17,15 @@ using Windows.Storage;
namespace VDownload.Core.Services.Sources.Twitch namespace VDownload.Core.Services.Sources.Twitch
{ {
public class Vod : IVideoService [Serializable]
public class Vod : IVideo
{ {
#region CONSTRUCTORS #region CONSTRUCTORS
public Vod(string id) public Vod(string id)
{ {
ID = id; ID = id;
Source = VideoSource.TwitchVod;
} }
#endregion #endregion
@@ -32,8 +34,9 @@ namespace VDownload.Core.Services.Sources.Twitch
#region PROPERTIES #region PROPERTIES
public VideoSource Source { get; private set; }
public string ID { get; private set; } public string ID { get; private set; }
public Uri VideoUrl { get; private set; } public Uri Url { get; private set; }
public Metadata Metadata { get; private set; } public Metadata Metadata { get; private set; }
public BaseStream[] BaseStreams { get; private set; } public BaseStream[] BaseStreams { get; private set; }
@@ -72,7 +75,7 @@ namespace VDownload.Core.Services.Sources.Twitch
internal void GetMetadataAsync(JToken response) internal void GetMetadataAsync(JToken response)
{ {
// Create unified video url // Create unified video url
VideoUrl = new Uri($"https://www.twitch.tv/videos/{ID}"); Url = new Uri($"https://www.twitch.tv/videos/{ID}");
// Set metadata // Set metadata
Metadata = new Metadata() Metadata = new Metadata()

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace VDownload.Core.Services namespace VDownload.Core.Services
{ {
public class TaskId public static class TaskId
{ {
#region CONSTANTS #region CONSTANTS

View File

@@ -4,7 +4,7 @@ using System.Linq;
namespace VDownload.Core.Services namespace VDownload.Core.Services
{ {
public class TimeSpanCustomFormat public static class TimeSpanCustomFormat
{ {
// (TH:)MM:SS // (TH:)MM:SS
public static string ToOptTHBaseMMSS(TimeSpan timeSpan, params TimeSpan[] formatBase) public static string ToOptTHBaseMMSS(TimeSpan timeSpan, params TimeSpan[] formatBase)

View File

@@ -6,6 +6,7 @@ using System.Threading.Tasks;
namespace VDownload.Core.Structs namespace VDownload.Core.Structs
{ {
[Serializable]
public struct BaseStream public struct BaseStream
{ {
public Uri Url { get; set; } public Uri Url { get; set; }

View File

@@ -6,6 +6,7 @@ using System.Threading.Tasks;
namespace VDownload.Core.Structs namespace VDownload.Core.Structs
{ {
[Serializable]
public struct Metadata public struct Metadata
{ {
public string Title { get; set; } public string Title { get; set; }

View File

@@ -7,7 +7,7 @@ namespace VDownload.Core.Structs
{ {
public struct TaskData public struct TaskData
{ {
public IVideoService VideoService { get; set; } public IVideo VideoService { get; set; }
public TaskOptions TaskOptions { get; set; } public TaskOptions TaskOptions { get; set; }
} }
} }

View File

@@ -124,6 +124,7 @@
<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\PlaylistSource.cs" />
<Compile Include="Enums\SubscriptionStatus.cs" />
<Compile Include="Enums\TaskAddingRequestSource.cs" /> <Compile Include="Enums\TaskAddingRequestSource.cs" />
<Compile Include="Enums\VideoFileExtension.cs" /> <Compile Include="Enums\VideoFileExtension.cs" />
<Compile Include="Enums\VideoSource.cs" /> <Compile Include="Enums\VideoSource.cs" />
@@ -133,18 +134,21 @@
<Compile Include="EventArgs\PlaylistSearchSuccessedEventArgs.cs" /> <Compile Include="EventArgs\PlaylistSearchSuccessedEventArgs.cs" />
<Compile Include="EventArgs\VideoSearchSuccessedEventArgs.cs" /> <Compile Include="EventArgs\VideoSearchSuccessedEventArgs.cs" />
<Compile Include="Exceptions\MediaNotFoundException.cs" /> <Compile Include="Exceptions\MediaNotFoundException.cs" />
<Compile Include="Exceptions\SubscriptionExistsException.cs" />
<Compile Include="Exceptions\TwitchAccessTokenNotFoundException.cs" /> <Compile Include="Exceptions\TwitchAccessTokenNotFoundException.cs" />
<Compile Include="Exceptions\TwitchAccessTokenNotValidException.cs" /> <Compile Include="Exceptions\TwitchAccessTokenNotValidException.cs" />
<Compile Include="Interfaces\IPlaylistService.cs" /> <Compile Include="Interfaces\IPlaylist.cs" />
<Compile Include="Interfaces\IVideoService.cs" /> <Compile Include="Interfaces\IVideo.cs" />
<Compile Include="Services\Sources\Twitch\Helpers\Client.cs" /> <Compile Include="Services\Sources\Twitch\Helpers\Client.cs" />
<Compile Include="Services\Subscription.cs" />
<Compile Include="Services\SubscriptionsCollectionManagement.cs" />
<Compile Include="Services\TimeSpanCustomFormat.cs" /> <Compile Include="Services\TimeSpanCustomFormat.cs" />
<Compile Include="Structs\BaseStream.cs" /> <Compile Include="Structs\BaseStream.cs" />
<Compile Include="Structs\Metadata.cs" /> <Compile Include="Structs\Metadata.cs" />
<Compile Include="Structs\TaskData.cs" /> <Compile Include="Structs\TaskData.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\Source.cs" />
<Compile Include="Services\Sources\Twitch\Helpers\Auth.cs" /> <Compile Include="Services\Sources\Twitch\Helpers\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" />

View File

@@ -7,12 +7,16 @@
<SolidColorBrush x:Key="HomeOptionBarBackgroundColor" Color="#F5F5F5"/> <SolidColorBrush x:Key="HomeOptionBarBackgroundColor" Color="#F5F5F5"/>
<SolidColorBrush x:Key="HomePlaylistAddingVideoPanelContentBackgroundColor" Color="#F5F5F5"/> <SolidColorBrush x:Key="HomePlaylistAddingVideoPanelContentBackgroundColor" Color="#F5F5F5"/>
<SolidColorBrush x:Key="HomePlaylistAddingApplyToAllContentBackgroundColor" Color="#F5F5F5"/> <SolidColorBrush x:Key="HomePlaylistAddingApplyToAllContentBackgroundColor" Color="#F5F5F5"/>
<SolidColorBrush x:Key="SubscriptionsSubscriptionPanelBackgroundColor" Color="#F5F5F5"/>
<SolidColorBrush x:Key="SubscriptionsAddingPanelBackgroundColor" Color="#F5F5F5"/>
</ResourceDictionary> </ResourceDictionary>
<ResourceDictionary x:Key="Dark"> <ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="HomeBackgroundColor" Color="#242424"/> <SolidColorBrush x:Key="HomeBackgroundColor" Color="#242424"/>
<SolidColorBrush x:Key="HomeOptionBarBackgroundColor" Color="#1B1B1B"/> <SolidColorBrush x:Key="HomeOptionBarBackgroundColor" Color="#1B1B1B"/>
<SolidColorBrush x:Key="HomePlaylistAddingVideoPanelContentBackgroundColor" Color="#272727"/> <SolidColorBrush x:Key="HomePlaylistAddingVideoPanelContentBackgroundColor" Color="#272727"/>
<SolidColorBrush x:Key="HomePlaylistAddingApplyToAllContentBackgroundColor" Color="#272727"/> <SolidColorBrush x:Key="HomePlaylistAddingApplyToAllContentBackgroundColor" Color="#272727"/>
<SolidColorBrush x:Key="SubscriptionsSubscriptionPanelBackgroundColor" Color="#272727"/>
<SolidColorBrush x:Key="SubscriptionsAddingPanelBackgroundColor" Color="#272727"/>
</ResourceDictionary> </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries> </ResourceDictionary.ThemeDictionaries>
<SolidColorBrush x:Key="HomeTasksListPlaceholderTextColor" Color="#AAAAAA"/> <SolidColorBrush x:Key="HomeTasksListPlaceholderTextColor" Color="#AAAAAA"/>

View File

@@ -406,18 +406,6 @@ The number in the numberbox indicades how many videos will be got from playlist.
<data name="NotificationTaskEndedUnsuccessfullyHeader" xml:space="preserve"> <data name="NotificationTaskEndedUnsuccessfullyHeader" xml:space="preserve">
<value>Video downloading ended unsuccessfully</value> <value>Video downloading ended unsuccessfully</value>
</data> </data>
<data name="SourcesMainPageHeaderText.Text" xml:space="preserve">
<value>Sources</value>
</data>
<data name="SourcesTwitchLoginButton.Content" xml:space="preserve">
<value>Loading...</value>
</data>
<data name="SourcesTwitchLoginButtonTextLoggedIn" xml:space="preserve">
<value>Log out</value>
</data>
<data name="SourcesTwitchLoginButtonTextNotLoggedIn" xml:space="preserve">
<value>Sign in</value>
</data>
<data name="SourcesTwitchLoginErrorDialogDescriptionInternetConnectionError" xml:space="preserve"> <data name="SourcesTwitchLoginErrorDialogDescriptionInternetConnectionError" xml:space="preserve">
<value>Unable to connect to Twitch servers. Check your internet connection.</value> <value>Unable to connect to Twitch servers. Check your internet connection.</value>
</data> </data>
@@ -427,21 +415,51 @@ The number in the numberbox indicades how many videos will be got from playlist.
<data name="SourcesTwitchLoginErrorDialogTitle" xml:space="preserve"> <data name="SourcesTwitchLoginErrorDialogTitle" xml:space="preserve">
<value>Login to Twitch failed</value> <value>Login to Twitch failed</value>
</data> </data>
<data name="SourcesTwitchSettingControl.Description" xml:space="preserve"> <data name="Sources_HeaderTextBlock.Text" xml:space="preserve">
<value>Sources</value>
</data>
<data name="Sources_TwitchSettingControl.Description" xml:space="preserve">
<value>Loading...</value> <value>Loading...</value>
</data> </data>
<data name="SourcesTwitchSettingControl.Title" xml:space="preserve"> <data name="Sources_TwitchSettingControl.Title" xml:space="preserve">
<value>Twitch</value> <value>Twitch</value>
</data> </data>
<data name="SourcesTwitchSettingControlDescriptionInternetConnectionError" xml:space="preserve"> <data name="Sources_TwitchSettingControl_Description_AccessTokenExpired" xml:space="preserve">
<value>Your Twitch access token has expired. Please sign in.</value>
</data>
<data name="Sources_TwitchSettingControl_Description_InternetNotAvailable" xml:space="preserve">
<value>Unable to connect to Twitch servers. Check your internet connection.</value> <value>Unable to connect to Twitch servers. Check your internet connection.</value>
</data> </data>
<data name="SourcesTwitchSettingControlDescriptionLoggedIn" xml:space="preserve"> <data name="Sources_TwitchSettingControl_Description_LoggedIn" xml:space="preserve">
<value>Logged in as</value> <value>Logged in as</value>
</data> </data>
<data name="SourcesTwitchSettingControlDescriptionNotLoggedIn" xml:space="preserve"> <data name="Sources_TwitchSettingControl_Description_NotLoggedIn" xml:space="preserve">
<value>Not logged in. Twitch authentication is required to download videos.</value> <value>Not logged in. Twitch authentication is required to download videos.</value>
</data> </data>
<data name="Sources_TwitchSettingControl_LoginButton.Content" xml:space="preserve">
<value>Loading...</value>
</data>
<data name="Sources_TwitchSettingControl_LoginButton_Content_LoggedIn" xml:space="preserve">
<value>Log out</value>
</data>
<data name="Sources_TwitchSettingControl_LoginButton_Content_NotLoggedIn" xml:space="preserve">
<value>Sign in</value>
</data>
<data name="Subscriptions_AddingButton.Content" xml:space="preserve">
<value>Add</value>
</data>
<data name="Subscriptions_AddingTextBox.PlaceholderText" xml:space="preserve">
<value>Playlist URL</value>
</data>
<data name="Subscriptions_HeaderTextBlock.Text" xml:space="preserve">
<value>Subscriptions</value>
</data>
<data name="Subscriptions_SubscriptionPanel_CountTextBlock.Text" xml:space="preserve">
<value>Loading...</value>
</data>
<data name="Subscriptions_SubscriptionPanel_CountTextBlock_SyncText" xml:space="preserve">
<value>Syncing...</value>
</data>
<data name="TaskErrorInternetConnection" xml:space="preserve"> <data name="TaskErrorInternetConnection" xml:space="preserve">
<value>Internet connection error</value> <value>Internet connection error</value>
</data> </data>

View File

@@ -158,14 +158,17 @@
<Compile Include="Views\MainPage.xaml.cs"> <Compile Include="Views\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon> <DependentUpon>MainPage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\Sources\SourcesMain.xaml.cs"> <Compile Include="Views\Sources\MainPage.xaml.cs">
<DependentUpon>SourcesMain.xaml</DependentUpon> <DependentUpon>MainPage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\Settings\SettingsMain.xaml.cs"> <Compile Include="Views\Settings\SettingsMain.xaml.cs">
<DependentUpon>SettingsMain.xaml</DependentUpon> <DependentUpon>SettingsMain.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\Subscriptions\SubscriptionsMain.xaml.cs"> <Compile Include="Views\Subscriptions\Controls\SubscriptionPanel.xaml.cs">
<DependentUpon>SubscriptionsMain.xaml</DependentUpon> <DependentUpon>SubscriptionPanel.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Subscriptions\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -342,7 +345,7 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Views\Sources\SourcesMain.xaml"> <Page Include="Views\Sources\MainPage.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
@@ -350,7 +353,11 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Views\Subscriptions\SubscriptionsMain.xaml"> <Page Include="Views\Subscriptions\Controls\SubscriptionPanel.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Subscriptions\MainPage.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
@@ -369,7 +376,7 @@
<Version>7.1.2</Version> <Version>7.1.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.UI.Xaml"> <PackageReference Include="Microsoft.UI.Xaml">
<Version>2.8.0-prerelease.220118001</Version> <Version>2.8.0-prerelease.220413001</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -384,6 +391,9 @@
<ItemGroup> <ItemGroup>
<Folder Include="Properties\" /> <Folder Include="Properties\" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PRIResource Include="Strings\en-US\DialogResources.resw" />
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' "> <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion> <VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup> </PropertyGroup>

View File

@@ -30,7 +30,7 @@ namespace VDownload.Views.Home.Controls
{ {
#region CONSTRUCTORS #region CONSTRUCTORS
public HomeAddingVideoOptions(IVideoService videoService) public HomeAddingVideoOptions(IVideo videoService)
{ {
this.InitializeComponent(); this.InitializeComponent();
@@ -112,7 +112,7 @@ namespace VDownload.Views.Home.Controls
#region PROPERTIES #region PROPERTIES
// VIDEO SERVICE // VIDEO SERVICE
private IVideoService VideoService { get; set; } private IVideo VideoService { get; set; }
// TASK OPTIONS // TASK OPTIONS
public MediaType MediaType { get; private set; } public MediaType MediaType { get; private set; }

View File

@@ -8,6 +8,7 @@ using VDownload.Core.EventArgs;
using VDownload.Core.Exceptions; using VDownload.Core.Exceptions;
using VDownload.Core.Interfaces; using VDownload.Core.Interfaces;
using VDownload.Core.Services; using VDownload.Core.Services;
using VDownload.Core.Services.Sources;
using Windows.ApplicationModel.Resources; using Windows.ApplicationModel.Resources;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
@@ -52,7 +53,7 @@ namespace VDownload.Views.Home
#region EVENT HANDLERS #region EVENT HANDLERS VOIDS
// NUMBERBOX FOCUS LOST // NUMBERBOX FOCUS LOST
private void HomeOptionsBarPlaylistSearchControlMaxVideosNumberBox_LostFocus(object sender, RoutedEventArgs e) private void HomeOptionsBarPlaylistSearchControlMaxVideosNumberBox_LostFocus(object sender, RoutedEventArgs e)
@@ -73,22 +74,13 @@ namespace VDownload.Views.Home
HomeOptionsBarPlaylistSearchControlStatusControl.Content = HomeOptionsBarPlaylistSearchStatusProgressRing; HomeOptionsBarPlaylistSearchControlStatusControl.Content = HomeOptionsBarPlaylistSearchStatusProgressRing;
// Parse url // Parse url
(PlaylistSource Type, string ID) source = Source.GetPlaylistSource(HomeOptionsBarPlaylistSearchControlUrlTextBox.Text); IPlaylist playlistService = Source.GetPlaylist(HomeOptionsBarPlaylistSearchControlUrlTextBox.Text);
if (playlistService == null)
// Check url
if (source.Type == PlaylistSource.Null)
{ {
HomeOptionsBarPlaylistSearchControlStatusControl.Content = HomeOptionsBarPlaylistSearchStatusErrorImage; HomeOptionsBarPlaylistSearchControlStatusControl.Content = HomeOptionsBarPlaylistSearchStatusErrorImage;
} }
else 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 // Get metadata and streams
try try
{ {

View File

@@ -7,6 +7,7 @@ using VDownload.Core.EventArgs;
using VDownload.Core.Exceptions; using VDownload.Core.Exceptions;
using VDownload.Core.Interfaces; using VDownload.Core.Interfaces;
using VDownload.Core.Services; using VDownload.Core.Services;
using VDownload.Core.Services.Sources;
using Windows.ApplicationModel.Resources; using Windows.ApplicationModel.Resources;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
@@ -63,23 +64,15 @@ namespace VDownload.Views.Home
HomeOptionBarVideoSearchControlStatusControl.Content = HomeOptionsBarVideoSearchStatusProgressRing; HomeOptionBarVideoSearchControlStatusControl.Content = HomeOptionsBarVideoSearchStatusProgressRing;
// Parse url // Parse url
(VideoSource Type, string ID) source = Source.GetVideoSource(HomeOptionsBarVideoSearchControlUrlTextBox.Text); IVideo videoService = Source.GetVideo(HomeOptionsBarVideoSearchControlUrlTextBox.Text);
// Check url // Check url
if (source.Type == VideoSource.Null) if (videoService == null)
{ {
HomeOptionBarVideoSearchControlStatusControl.Content = HomeOptionsBarVideoSearchStatusErrorImage; HomeOptionBarVideoSearchControlStatusControl.Content = HomeOptionsBarVideoSearchStatusErrorImage;
} }
else 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 // Get metadata and streams
try try
{ {
@@ -141,7 +134,7 @@ namespace VDownload.Views.Home
HomeOptionBarVideoSearchControlStatusControl.Content = null; HomeOptionBarVideoSearchControlStatusControl.Content = null;
// Invoke search successed event // Invoke search successed event
VideoSearchSuccessed?.Invoke(this, new VideoSearchSuccessedEventArgs { VideoService = videoService }); VideoSearchSuccessed?.Invoke(this, new VideoSearchSuccessedEventArgs { Video = videoService });
} }
} }

View File

@@ -23,7 +23,7 @@ namespace VDownload.Views.Home.Controls
#region CONSTRUCTORS #region CONSTRUCTORS
public HomeSerialAddingVideoPanel(IVideoService videoService) public HomeSerialAddingVideoPanel(IVideo videoService)
{ {
this.InitializeComponent(); this.InitializeComponent();
@@ -50,7 +50,7 @@ namespace VDownload.Views.Home.Controls
#region PROPERTIES #region PROPERTIES
// BASE VIDEO DATA // BASE VIDEO DATA
public IVideoService VideoService { get; set; } public IVideo VideoService { get; set; }
// VIDEO DATA // VIDEO DATA
private ImageSource ThumbnailImage { get; set; } private ImageSource ThumbnailImage { get; set; }
@@ -81,7 +81,7 @@ namespace VDownload.Views.Home.Controls
private async void HomeSerialAddingVideoPanelSourceButton_Click(object sender, RoutedEventArgs e) private async void HomeSerialAddingVideoPanelSourceButton_Click(object sender, RoutedEventArgs e)
{ {
// Launch the website // Launch the website
await Windows.System.Launcher.LaunchUriAsync(VideoService.VideoUrl); await Windows.System.Launcher.LaunchUriAsync(VideoService.Url);
} }
// DELETE BUTTON CLICKED // DELETE BUTTON CLICKED

View File

@@ -286,7 +286,7 @@ namespace VDownload.Views.Home.Controls
private async void HomeTaskPanelSourceButton_Click(object sender, RoutedEventArgs e) private async void HomeTaskPanelSourceButton_Click(object sender, RoutedEventArgs e)
{ {
// Launch the website // Launch the website
await Windows.System.Launcher.LaunchUriAsync(Data.VideoService.VideoUrl); await Windows.System.Launcher.LaunchUriAsync(Data.VideoService.Url);
} }
// START STOP BUTTON CLICKED // START STOP BUTTON CLICKED

View File

@@ -104,7 +104,7 @@ namespace VDownload.Views.Home
HomeTasksListRow.Height = new GridLength(0); HomeTasksListRow.Height = new GridLength(0);
// Open adding panel // Open adding panel
HomeVideoAddingPanel addingPanel = new HomeVideoAddingPanel(e.VideoService); HomeVideoAddingPanel addingPanel = new HomeVideoAddingPanel(e.Video);
addingPanel.TasksAddingRequested += HomeTasksAddingRequest; addingPanel.TasksAddingRequested += HomeTasksAddingRequest;
HomeAddingPanel.Content = addingPanel; HomeAddingPanel.Content = addingPanel;
} }

View File

@@ -26,7 +26,7 @@ namespace VDownload.Views.Home
{ {
#region CONSTRUCTORS #region CONSTRUCTORS
public HomePlaylistAddingPanel(IPlaylistService playlistService) public HomePlaylistAddingPanel(IPlaylist playlistService)
{ {
this.InitializeComponent(); this.InitializeComponent();
@@ -41,7 +41,7 @@ namespace VDownload.Views.Home
#region PROPERTIES #region PROPERTIES
// BASE PLAYLIST DATA // BASE PLAYLIST DATA
private IPlaylistService PlaylistService { get; set; } private IPlaylist PlaylistService { get; set; }
// PLAYLIST DATA // PLAYLIST DATA
private IconElement SourceImage { get; set; } private IconElement SourceImage { get; set; }
@@ -84,7 +84,7 @@ namespace VDownload.Views.Home
MaxDate = PlaylistService.Videos[0].Metadata.Date; MaxDate = PlaylistService.Videos[0].Metadata.Date;
MinDuration = PlaylistService.Videos[0].Metadata.Duration; MinDuration = PlaylistService.Videos[0].Metadata.Duration;
MaxDuration = PlaylistService.Videos[0].Metadata.Duration; MaxDuration = PlaylistService.Videos[0].Metadata.Duration;
foreach (IVideoService video in PlaylistService.Videos) foreach (IVideo video in PlaylistService.Videos)
{ {
// Set mins and maxes // Set mins and maxes
if (video.Metadata.Views < MinViews) MinViews = video.Metadata.Views; if (video.Metadata.Views < MinViews) MinViews = video.Metadata.Views;
@@ -375,7 +375,7 @@ namespace VDownload.Views.Home
private async void HomePlaylistAddingPanelSourceButton_Click(object sender, RoutedEventArgs e) private async void HomePlaylistAddingPanelSourceButton_Click(object sender, RoutedEventArgs e)
{ {
// Launch the website // Launch the website
await Windows.System.Launcher.LaunchUriAsync(PlaylistService.PlaylistUrl); await Windows.System.Launcher.LaunchUriAsync(PlaylistService.Url);
} }
// ADD BUTTON CLICKED // ADD BUTTON CLICKED

View File

@@ -34,7 +34,7 @@ namespace VDownload.Views.Home
#region CONSTRUCTORS #region CONSTRUCTORS
public HomeVideoAddingPanel(IVideoService videoService) public HomeVideoAddingPanel(IVideo videoService)
{ {
this.InitializeComponent(); this.InitializeComponent();
@@ -61,7 +61,7 @@ namespace VDownload.Views.Home
#region PROPERTIES #region PROPERTIES
// BASE VIDEO DATA // BASE VIDEO DATA
private IVideoService VideoService { get; set; } private IVideo VideoService { get; set; }
// VIDEO DATA // VIDEO DATA
private ImageSource ThumbnailImage { get; set; } private ImageSource ThumbnailImage { get; set; }
@@ -91,7 +91,7 @@ namespace VDownload.Views.Home
public async void HomeVideoAddingPanelSourceButton_Click(object sender, RoutedEventArgs e) public async void HomeVideoAddingPanelSourceButton_Click(object sender, RoutedEventArgs e)
{ {
// Launch the website // Launch the website
await Windows.System.Launcher.LaunchUriAsync(VideoService.VideoUrl); await Windows.System.Launcher.LaunchUriAsync(VideoService.Url);
} }
// ADD BUTTON CLICKED // ADD BUTTON CLICKED

View File

@@ -34,9 +34,9 @@ namespace VDownload.Views
private readonly Dictionary<string, Type> Pages = new Dictionary<string, Type>() private readonly Dictionary<string, Type> Pages = new Dictionary<string, Type>()
{ {
{"home", typeof(Home.HomeMain)}, {"home", typeof(Home.HomeMain)},
{"subscriptions", typeof(Subscriptions.SubscriptionsMain)}, {"subscriptions", typeof(Subscriptions.MainPage)},
{"about", typeof(About.AboutMain)}, {"about", typeof(About.AboutMain)},
{"sources", typeof(Sources.SourcesMain)}, {"sources", typeof(Sources.MainPage)},
{"settings", typeof(Settings.SettingsMain)}, {"settings", typeof(Settings.SettingsMain)},
}; };

View File

@@ -1,36 +0,0 @@
<Page
x:Class="VDownload.Views.Sources.SourcesMain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VDownload.Views.Sources"
xmlns:cc="using:VDownload.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<ResourceDictionary Source="ms-appx:///Resources/Icons.xaml"/>
</Page.Resources>
<Grid Padding="20" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!-- HEADER TEXT -->
<TextBlock x:Name="SourcesMainPageHeaderText" x:Uid="SourcesMainPageHeaderText" Grid.Row="0" FontSize="28" FontWeight="SemiBold"/>
<!-- CONTENT -->
<StackPanel Grid.Row="1" Spacing="10">
<cc:SettingControl x:Name="SourcesTwitchSettingControl" x:Uid="SourcesTwitchSettingControl" Grid.Row="0" Icon="{StaticResource TwitchIcon}" Title="Twitch"> <!-- Twitch -->
<cc:SettingControl.SettingContent>
<Button x:Name="SourcesTwitchLoginButton" IsEnabled="False" Click="SourcesTwitchLoginButton_Click"/>
</cc:SettingControl.SettingContent>
</cc:SettingControl>
</StackPanel>
</Grid>
</Page>

View File

@@ -1,199 +0,0 @@
using Microsoft.Toolkit.Uwp.Connectivity;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Windows.ApplicationModel.Resources;
using Windows.UI.WindowManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Hosting;
using Windows.UI.Xaml.Navigation;
namespace VDownload.Views.Sources
{
public sealed partial class SourcesMain : Page
{
#region CONSTRUCTORS
public SourcesMain()
{
InitializeComponent();
}
#endregion
#region MAIN EVENT HANDLERS VOIDS
// ON NAVIGATED TO THIS PAGE (Check all services)
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
Task[] checkingTasks = new Task[1];
checkingTasks[0] = CheckTwitch();
await Task.WhenAll(checkingTasks);
}
#endregion
#region TWITCH
// CHECK TWITCH LOGIN AT START
private async Task CheckTwitch()
{
try
{
string twitchAccessToken = await Core.Services.Sources.Twitch.Helpers.Auth.ReadAccessTokenAsync();
#pragma warning disable IDE0042 // Deconstruct variable declaration
(bool IsValid, string Login, DateTime? ExpirationDate) twitchAccessTokenValidation = await Core.Services.Sources.Twitch.Helpers.Auth.ValidateAccessTokenAsync(twitchAccessToken);
#pragma warning restore IDE0042 // Deconstruct variable declaration
if (twitchAccessTokenValidation.IsValid)
{
SourcesTwitchSettingControl.Description = $"{ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionLoggedIn")} {twitchAccessTokenValidation.Login}";
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextLoggedIn");
SourcesTwitchLoginButton.IsEnabled = true;
}
else
{
if (twitchAccessToken != null) await Core.Services.Sources.Twitch.Helpers.Auth.DeleteAccessTokenAsync();
SourcesTwitchSettingControl.Description = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionNotLoggedIn");
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextNotLoggedIn");
SourcesTwitchLoginButton.IsEnabled = true;
}
}
catch (WebException)
{
if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
{
SourcesTwitchSettingControl.Description = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchSettingControlDescriptionInternetConnectionError");
SourcesTwitchLoginButton.Content = ResourceLoader.GetForCurrentView().GetString("SourcesTwitchLoginButtonTextNotLoggedIn");
SourcesTwitchLoginButton.IsEnabled = false;
}
else throw;
}
}
// TWITCH LOGIN BUTTON CLICKED
private async void SourcesTwitchLoginButton_Click(object sender, RoutedEventArgs e)
{
try
{
string accessToken = await Core.Services.Sources.Twitch.Helpers.Auth.ReadAccessTokenAsync();
var accessTokenValidation = await Core.Services.Sources.Twitch.Helpers.Auth.ValidateAccessTokenAsync(accessToken);
if (accessTokenValidation.IsValid)
{
// Revoke access token
await Core.Services.Sources.Twitch.Helpers.Auth.RevokeAccessTokenAsync(accessToken);
// Delete access token
await Core.Services.Sources.Twitch.Helpers.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";
#pragma warning disable CS8305 // Type is for evaluation purposes only and is subject to change or removal in future updates.
WebView2 TwitchAuthWebView = new WebView2();
await TwitchAuthWebView.EnsureCoreWebView2Async();
TwitchAuthWebView.Source = Core.Services.Sources.Twitch.Helpers.Auth.AuthorizationUrl;
ElementCompositionPreview.SetAppWindowContent(TwitchAuthWindow, TwitchAuthWebView);
// NavigationStarting event (only when redirected)
TwitchAuthWebView.NavigationStarting += async (s, a) =>
{
if (new Uri(a.Uri).Host == Core.Services.Sources.Twitch.Helpers.Auth.RedirectUrl.Host)
{
// Close window
await TwitchAuthWindow.CloseAsync();
// Get response
string response = a.Uri.Replace(Core.Services.Sources.Twitch.Helpers.Auth.RedirectUrl.OriginalString, "");
if (response[1] == '#')
{
// Get access token
accessToken = response.Split('&')[0].Replace("/#access_token=", "");
// Check token
accessTokenValidation = await Core.Services.Sources.Twitch.Helpers.Auth.ValidateAccessTokenAsync(accessToken);
// Save token
await Core.Services.Sources.Twitch.Helpers.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",
};
// Errors translation
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 = ResourceLoader.GetForCurrentView().GetString("CloseErrorDialogButtonText"),
};
await loginErrorDialog.ShowAsync();
}
}
await TwitchAuthWindow.TryShowAsync();
// Clear cache
TwitchAuthWebView.CoreWebView2.CookieManager.DeleteAllCookies();
}
};
#pragma warning restore CS8305 // Type is for evaluation purposes only and is subject to change or removal in future updates.
}
}
catch (WebException wex)
{
if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
{
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;
}
}
#endregion
}
}

View File

@@ -1,18 +0,0 @@
<Page
x:Class="VDownload.Views.Subscriptions.SubscriptionsMain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VDownload.Views.Subscriptions"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Padding="20" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
</Page>

View File

@@ -1,25 +0,0 @@
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;
namespace VDownload.Views.Subscriptions
{
public sealed partial class SubscriptionsMain : Page
{
public SubscriptionsMain()
{
this.InitializeComponent();
}
}
}