From 0782f9a506b296f32b580ca6b1aadaeb12301d64 Mon Sep 17 00:00:00 2001 From: Michael Gordeev Date: Fri, 29 Jun 2018 01:00:33 +0300 Subject: [PATCH] Development 1.1 --- FoxTube/App.xaml.cs | 2 +- FoxTube/Classes/Methods.cs | 74 +++ FoxTube/{ => Classes}/Notification.cs | 0 FoxTube/Classes/SecretsVault.cs | 135 +++++ FoxTube/{ => Controls}/ChannelCard.xaml | 0 FoxTube/{ => Controls}/ChannelCard.xaml.cs | 2 +- FoxTube/Controls/CommentCard.xaml | 82 +++ FoxTube/Controls/CommentCard.xaml.cs | 159 ++++++ FoxTube/Controls/NotificationsCenter.xaml | 26 + FoxTube/Controls/NotificationsCenter.xaml.cs | 161 ++++++ FoxTube/{ => Controls}/PlaylistCardWide.xaml | 11 +- .../{ => Controls}/PlaylistCardWide.xaml.cs | 7 +- FoxTube/{ => Controls}/VideoCard.xaml | 19 +- FoxTube/{ => Controls}/VideoCard.xaml.cs | 40 +- FoxTube/{ => Controls}/VideoCardWide.xaml | 10 +- FoxTube/{ => Controls}/VideoCardWide.xaml.cs | 42 +- FoxTube/{ => Controls}/VideoPlayer.xaml | 94 ++-- FoxTube/{ => Controls}/VideoPlayer.xaml.cs | 382 ++++++++++++-- FoxTube/FoxTube.csproj | 118 +++-- FoxTube/MainPage.xaml | 217 -------- FoxTube/{ => Pages}/Channel.xaml | 0 FoxTube/{ => Pages}/Channel.xaml.cs | 6 +- FoxTube/Pages/CommentsPage.xaml | 54 ++ FoxTube/Pages/CommentsPage.xaml.cs | 137 +++++ FoxTube/{ => Pages}/Feedback.xaml | 0 FoxTube/{ => Pages}/Feedback.xaml.cs | 2 +- FoxTube/{ => Pages}/General.xaml | 0 FoxTube/{ => Pages}/General.xaml.cs | 0 FoxTube/{ => Pages}/Home.xaml | 0 FoxTube/{ => Pages}/Home.xaml.cs | 2 +- FoxTube/{ => Pages}/LoadingPage.xaml | 18 +- FoxTube/{ => Pages}/LoadingPage.xaml.cs | 30 +- FoxTube/Pages/MainPage.xaml | 241 +++++++++ FoxTube/{ => Pages}/MainPage.xaml.cs | 275 +++++----- FoxTube/{ => Pages}/Search.xaml | 0 FoxTube/{ => Pages}/Search.xaml.cs | 2 +- FoxTube/{ => Pages}/Settings.xaml | 2 +- FoxTube/{ => Pages}/Settings.xaml.cs | 0 FoxTube/{ => Pages}/Translate.xaml | 0 FoxTube/{ => Pages}/Translate.xaml.cs | 2 +- FoxTube/Pages/Video.xaml | 139 ++++++ FoxTube/Pages/Video.xaml.cs | 472 ++++++++++++++++++ FoxTube/{ => Pages}/VideoGrid.xaml | 0 FoxTube/{ => Pages}/VideoGrid.xaml.cs | 0 FoxTube/SecretsVault.cs | 112 ----- FoxTube/SubLayer.xaml.cs | 4 +- FoxTube/Video.xaml | 60 --- FoxTube/Video.xaml.cs | 89 ---- 48 files changed, 2403 insertions(+), 825 deletions(-) create mode 100644 FoxTube/Classes/Methods.cs rename FoxTube/{ => Classes}/Notification.cs (100%) create mode 100644 FoxTube/Classes/SecretsVault.cs rename FoxTube/{ => Controls}/ChannelCard.xaml (100%) rename FoxTube/{ => Controls}/ChannelCard.xaml.cs (97%) create mode 100644 FoxTube/Controls/CommentCard.xaml create mode 100644 FoxTube/Controls/CommentCard.xaml.cs create mode 100644 FoxTube/Controls/NotificationsCenter.xaml create mode 100644 FoxTube/Controls/NotificationsCenter.xaml.cs rename FoxTube/{ => Controls}/PlaylistCardWide.xaml (78%) rename FoxTube/{ => Controls}/PlaylistCardWide.xaml.cs (86%) rename FoxTube/{ => Controls}/VideoCard.xaml (64%) rename FoxTube/{ => Controls}/VideoCard.xaml.cs (52%) rename FoxTube/{ => Controls}/VideoCardWide.xaml (82%) rename FoxTube/{ => Controls}/VideoCardWide.xaml.cs (52%) rename FoxTube/{ => Controls}/VideoPlayer.xaml (71%) rename FoxTube/{ => Controls}/VideoPlayer.xaml.cs (56%) delete mode 100644 FoxTube/MainPage.xaml rename FoxTube/{ => Pages}/Channel.xaml (100%) rename FoxTube/{ => Pages}/Channel.xaml.cs (96%) create mode 100644 FoxTube/Pages/CommentsPage.xaml create mode 100644 FoxTube/Pages/CommentsPage.xaml.cs rename FoxTube/{ => Pages}/Feedback.xaml (100%) rename FoxTube/{ => Pages}/Feedback.xaml.cs (98%) rename FoxTube/{ => Pages}/General.xaml (100%) rename FoxTube/{ => Pages}/General.xaml.cs (100%) rename FoxTube/{ => Pages}/Home.xaml (100%) rename FoxTube/{ => Pages}/Home.xaml.cs (95%) rename FoxTube/{ => Pages}/LoadingPage.xaml (72%) rename FoxTube/{ => Pages}/LoadingPage.xaml.cs (69%) create mode 100644 FoxTube/Pages/MainPage.xaml rename FoxTube/{ => Pages}/MainPage.xaml.cs (72%) rename FoxTube/{ => Pages}/Search.xaml (100%) rename FoxTube/{ => Pages}/Search.xaml.cs (97%) rename FoxTube/{ => Pages}/Settings.xaml (99%) rename FoxTube/{ => Pages}/Settings.xaml.cs (100%) rename FoxTube/{ => Pages}/Translate.xaml (100%) rename FoxTube/{ => Pages}/Translate.xaml.cs (97%) create mode 100644 FoxTube/Pages/Video.xaml create mode 100644 FoxTube/Pages/Video.xaml.cs rename FoxTube/{ => Pages}/VideoGrid.xaml (100%) rename FoxTube/{ => Pages}/VideoGrid.xaml.cs (100%) delete mode 100644 FoxTube/SecretsVault.cs delete mode 100644 FoxTube/Video.xaml delete mode 100644 FoxTube/Video.xaml.cs diff --git a/FoxTube/App.xaml.cs b/FoxTube/App.xaml.cs index 23e4051..2882eb7 100644 --- a/FoxTube/App.xaml.cs +++ b/FoxTube/App.xaml.cs @@ -66,7 +66,7 @@ namespace FoxTube // When the navigation stack isn't restored navigate to the first page, // configuring the new page by passing required information as a navigation // parameter - rootFrame.Navigate(typeof(SubLayer), e.Arguments); + rootFrame.Navigate(typeof(MainPage), e.Arguments); } // Ensure the current window is active Window.Current.Activate(); diff --git a/FoxTube/Classes/Methods.cs b/FoxTube/Classes/Methods.cs new file mode 100644 index 0000000..35759d7 --- /dev/null +++ b/FoxTube/Classes/Methods.cs @@ -0,0 +1,74 @@ +using System; +using System.Text.RegularExpressions; +using Windows.UI; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Documents; +using Windows.UI.Xaml.Media; + +namespace FoxTube +{ + class Methods + { + public static MainPage MainPage + { + get { return (Window.Current.Content as Frame).Content as MainPage; } + } + + public static string GetAgo(DateTime dateTime) + { + TimeSpan span = DateTime.Now - dateTime; + if (span.TotalMinutes < 1) + return "Just now"; + else if (span.Minutes == 1) + return "1 minute ago"; + else if (span.TotalMinutes > 60) + return span.Minutes + " minutes ago"; + else if (span.Hours == 1) + return "1 hour ago"; + else if (span.TotalHours > 24) + return span.Hours + " hours ago"; + else if (span.Days == 1) + return "1 day ago"; + else if (span.TotalDays > 7) + return span.Days + " days ago"; + else if (span.Days == 7) + return "1 week ago"; + else if (span.Days > 30) + return (int)(span.Days / 7) + " weeks ago"; + else if (span.Days == 30) + return "1 month ago"; + else if (span.Days > 365) + return (int)(span.Days / 30) + " months ago"; + else if (span.Days == 365) + return "1 year ago"; + else + return (int)(span.Days / 365) + " years ago"; + } + + public static void FormatText(ref TextBlock block, string text) + { + block.Inlines.Clear(); + + Regex regx = new Regex(@"(http(s)?://[\S]+|www.[\S]+|[\S]+@[\S]+)", RegexOptions.IgnoreCase); + Regex isWWW = new Regex(@"(http[s]?://[\S]+|www.[\S]+)"); + Regex isEmail = new Regex(@"[\S]+@[\S]+"); + foreach (var item in regx.Split(text)) + { + if (isWWW.IsMatch(item)) + { + Hyperlink link = new Hyperlink { NavigateUri = new Uri(item.ToLower().StartsWith("http") ? item : $"http://{item}"), Foreground = new SolidColorBrush(Colors.Red) }; + link.Inlines.Add(new Run { Text = item }); + block.Inlines.Add(link); + } + else if (isEmail.IsMatch(item)) + { + Hyperlink link = new Hyperlink { NavigateUri = new Uri($"mailto:{item}"), Foreground = new SolidColorBrush(Colors.Red) }; + link.Inlines.Add(new Run { Text = item }); + block.Inlines.Add(link); + } + else block.Inlines.Add(new Run { Text = item }); + } + } + } +} diff --git a/FoxTube/Notification.cs b/FoxTube/Classes/Notification.cs similarity index 100% rename from FoxTube/Notification.cs rename to FoxTube/Classes/Notification.cs diff --git a/FoxTube/Classes/SecretsVault.cs b/FoxTube/Classes/SecretsVault.cs new file mode 100644 index 0000000..d1250e1 --- /dev/null +++ b/FoxTube/Classes/SecretsVault.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using System.Diagnostics; +using System.Text.RegularExpressions; +using Windows.UI.Xaml.Media; +using Windows.UI; +using Windows.UI.Xaml.Documents; +using System.Net; +using System.Threading; + +using Google.Apis.Auth.OAuth2; +using Google.Apis.Auth.OAuth2.Flows; +using Google.Apis.Services; +using Google.Apis.Util.Store; +using Google.Apis.YouTube.v3; +using Google.Apis.Auth.OAuth2.Responses; + +namespace FoxTube +{ + public class SecretsVault + { + #region Static Information + public static NetworkCredential EmailCredential { get => new NetworkCredential("youwillneverknowthisadress@gmail.com", "thisisthepassword12345"); } + private static string YoutubeApi { get => "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0"; } + private static string ApplicationName { get => "FoxTube"; } + private static ClientSecrets Secrets + { + get => new ClientSecrets() + { + ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com", + ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_" + }; + } + public static bool IsAuthorized { get => Methods.MainPage.Vault.IsLoged; } + + public static YouTubeService NoAuthService + { + get => new YouTubeService(new BaseClientService.Initializer() + { + ApiKey = YoutubeApi, + ApplicationName = ApplicationName + }); + } + + public static YouTubeService Service + { + get => new YouTubeService(new BaseClientService.Initializer() + { + HttpClientInitializer = Methods.MainPage.Vault.Credential, + ApplicationName = ApplicationName + }); + } + #endregion + + #region Object containers + public bool IsLoged = false; + public TokenResponse Token; + private UserCredential Credential; + public event EventHandler AuthorizationStateChanged; + + public SecretsVault() + { + CheckAuthorization(); + } + + public async Task Authorize() + { + + + Credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(Secrets, new[] { Google.Apis.Oauth2.v2.Oauth2Service.Scope.UserinfoProfile, YouTubeService.Scope.YoutubeForceSsl }, "user", CancellationToken.None); + AuthorizationStateChanged.Invoke(this, null); + } + + public async void CheckAuthorization() + { + var token = await new AuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer() + { + ClientSecrets = Secrets, + DataStore = null + }).LoadTokenAsync("user", CancellationToken.None); + if (token == null) + IsLoged = false; + else + { + IsLoged = true; + Credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(Secrets, new[] { Google.Apis.Oauth2.v2.Oauth2Service.Scope.UserinfoProfile, YouTubeService.Scope.YoutubeForceSsl }, "user", CancellationToken.None); + AuthorizationStateChanged.Invoke(this, null); + } + } + #endregion + + #region User credentials + private List credentials = new List(); //Test variable simulating actual credentials storage + + public void AddAccount() + { + + + credentials.Add( + new UserCredential( + new AuthorizationCodeFlow( + new GoogleAuthorizationCodeFlow.Initializer() + { + ClientSecrets = Secrets, + DataStore = null //TO-DO: Replace with new PasswordsVaultDataStore() + }), + "userId", + new TokenResponse() + { + AccessToken = "done", + ExpiresInSeconds = 1, + IdToken = "done", + TokenType = "done", + RefreshToken = "done", + Scope = "youtube" + })); + } + + public void DeleteAccount(int index) + { + credentials.RemoveAt(index); + } + + public UserCredential RetrieveAccount(int index) + { + return credentials[index]; + } + #endregion + } +} diff --git a/FoxTube/ChannelCard.xaml b/FoxTube/Controls/ChannelCard.xaml similarity index 100% rename from FoxTube/ChannelCard.xaml rename to FoxTube/Controls/ChannelCard.xaml diff --git a/FoxTube/ChannelCard.xaml.cs b/FoxTube/Controls/ChannelCard.xaml.cs similarity index 97% rename from FoxTube/ChannelCard.xaml.cs rename to FoxTube/Controls/ChannelCard.xaml.cs index eb5a296..c169f9e 100644 --- a/FoxTube/ChannelCard.xaml.cs +++ b/FoxTube/Controls/ChannelCard.xaml.cs @@ -59,7 +59,7 @@ namespace FoxTube private void Button_Click(object sender, RoutedEventArgs e) { - SecretsVault.SubLayer.Main.GoToChannel(channelId); + Methods.MainPage.GoToChannel(channelId); } } } diff --git a/FoxTube/Controls/CommentCard.xaml b/FoxTube/Controls/CommentCard.xaml new file mode 100644 index 0000000..41d172f --- /dev/null +++ b/FoxTube/Controls/CommentCard.xaml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -59,13 +76,10 @@ - - - + + @@ -97,8 +111,8 @@ - - + + @@ -109,7 +123,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/FoxTube/Pages/CommentsPage.xaml.cs b/FoxTube/Pages/CommentsPage.xaml.cs new file mode 100644 index 0000000..579e55c --- /dev/null +++ b/FoxTube/Pages/CommentsPage.xaml.cs @@ -0,0 +1,137 @@ +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; + +using Google.Apis.YouTube.v3; +using Google.Apis.YouTube.v3.Data; +using FoxTube.Controls; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace FoxTube.Pages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class CommentsPage : Page + { + string threadId; + string nextPageToken; + + CommentThreadsResource.ListRequest.OrderEnum order = CommentThreadsResource.ListRequest.OrderEnum.Relevance; + + public CommentsPage() + { + this.InitializeComponent(); + } + + public async void Initialize(Google.Apis.YouTube.v3.Data.Video video) + { + threadId = video.Id; + + counter.Text = string.Format("{0:0,0} Comments", video.Statistics.CommentCount); + + var request = SecretsVault.NoAuthService.CommentThreads.List("snippet,replies"); + request.Order = order; + request.VideoId = video.Id; + request.TextFormat = CommentThreadsResource.ListRequest.TextFormatEnum.PlainText; + var response = await request.ExecuteAsync(); + + if(response.NextPageToken != null) + { + nextPageToken = response.NextPageToken; + more.Visibility = Visibility.Visible; + } + + foreach (CommentThread comment in response.Items) + placeholder.Children.Add(new CommentCard(comment)); + } + + private async void more_Click(object sender, RoutedEventArgs e) + { + more.Visibility = Visibility.Collapsed; + moreLoading.Visibility = Visibility.Visible; + + var request = SecretsVault.NoAuthService.CommentThreads.List("snippet,replies"); + request.Order = order; + request.VideoId = threadId; + request.TextFormat = CommentThreadsResource.ListRequest.TextFormatEnum.PlainText; + request.PageToken = nextPageToken; + var response = await request.ExecuteAsync(); + + foreach (CommentThread comment in response.Items) + placeholder.Children.Add(new CommentCard(comment)); + + if(response.NextPageToken != null) + { + nextPageToken = response.NextPageToken; + more.Visibility = Visibility.Visible; + } + moreLoading.Visibility = Visibility.Collapsed; + } + + private async void toRelevance_Click(object sender, RoutedEventArgs e) + { + if(order != CommentThreadsResource.ListRequest.OrderEnum.Relevance) + { + more.Visibility = Visibility.Collapsed; + moreLoading.Visibility = Visibility.Visible; + + order = CommentThreadsResource.ListRequest.OrderEnum.Relevance; + orderBtn.Content = "Relevance"; + + placeholder.Children.Clear(); + + var request = SecretsVault.NoAuthService.CommentThreads.List("snippet,replies"); + request.Order = order; + request.VideoId = threadId; + request.TextFormat = CommentThreadsResource.ListRequest.TextFormatEnum.PlainText; + var response = await request.ExecuteAsync(); + + nextPageToken = response.NextPageToken; + foreach (CommentThread comment in response.Items) + placeholder.Children.Add(new CommentCard(comment)); + + more.Visibility = Visibility.Visible; + moreLoading.Visibility = Visibility.Collapsed; + } + } + + private async void toDate_Click(object sender, RoutedEventArgs e) + { + if (order != CommentThreadsResource.ListRequest.OrderEnum.Time) + { + more.Visibility = Visibility.Collapsed; + moreLoading.Visibility = Visibility.Visible; + + order = CommentThreadsResource.ListRequest.OrderEnum.Time; + orderBtn.Content = "Publish date"; + + placeholder.Children.Clear(); + + var request = SecretsVault.NoAuthService.CommentThreads.List("snippet,replies"); + request.Order = order; + request.VideoId = threadId; + var response = await request.ExecuteAsync(); + + nextPageToken = response.NextPageToken; + foreach (CommentThread comment in response.Items) + placeholder.Children.Add(new CommentCard(comment)); + + more.Visibility = Visibility.Visible; + moreLoading.Visibility = Visibility.Collapsed; + } + } + } +} diff --git a/FoxTube/Feedback.xaml b/FoxTube/Pages/Feedback.xaml similarity index 100% rename from FoxTube/Feedback.xaml rename to FoxTube/Pages/Feedback.xaml diff --git a/FoxTube/Feedback.xaml.cs b/FoxTube/Pages/Feedback.xaml.cs similarity index 98% rename from FoxTube/Feedback.xaml.cs rename to FoxTube/Pages/Feedback.xaml.cs index 6f7952b..c82ae3a 100644 --- a/FoxTube/Feedback.xaml.cs +++ b/FoxTube/Pages/Feedback.xaml.cs @@ -101,7 +101,7 @@ namespace FoxTube { SmtpClient client = new SmtpClient("smtp.gmail.com", 587); client.EnableSsl = true; - client.Credentials = new NetworkCredential("youwillneverknowthisadress@gmail.com", "thisisthepassword12345"); + client.Credentials = SecretsVault.EmailCredential; try { diff --git a/FoxTube/General.xaml b/FoxTube/Pages/General.xaml similarity index 100% rename from FoxTube/General.xaml rename to FoxTube/Pages/General.xaml diff --git a/FoxTube/General.xaml.cs b/FoxTube/Pages/General.xaml.cs similarity index 100% rename from FoxTube/General.xaml.cs rename to FoxTube/Pages/General.xaml.cs diff --git a/FoxTube/Home.xaml b/FoxTube/Pages/Home.xaml similarity index 100% rename from FoxTube/Home.xaml rename to FoxTube/Pages/Home.xaml diff --git a/FoxTube/Home.xaml.cs b/FoxTube/Pages/Home.xaml.cs similarity index 95% rename from FoxTube/Home.xaml.cs rename to FoxTube/Pages/Home.xaml.cs index a9dd6d5..ec6d20c 100644 --- a/FoxTube/Home.xaml.cs +++ b/FoxTube/Pages/Home.xaml.cs @@ -53,7 +53,7 @@ namespace FoxTube grid.RowDefinitions[0].Height = new GridLength(0); #region Request-Response - VideosResource.ListRequest request = SecretsVault.YoutubeService.Videos.List("snippet,contentDetails,statistics"); + VideosResource.ListRequest request = SecretsVault.NoAuthService.Videos.List("snippet,contentDetails,statistics"); request.Chart = VideosResource.ListRequest.ChartEnum.MostPopular; request.RegionCode = reg; request.MaxResults = 48; diff --git a/FoxTube/LoadingPage.xaml b/FoxTube/Pages/LoadingPage.xaml similarity index 72% rename from FoxTube/LoadingPage.xaml rename to FoxTube/Pages/LoadingPage.xaml index afbbcf0..0531f9f 100644 --- a/FoxTube/LoadingPage.xaml +++ b/FoxTube/Pages/LoadingPage.xaml @@ -6,33 +6,37 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" - Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> + Background="White"> - + - + + - + + + + + + + + + + + + + + + + + + + + - - - - - - - - -