diff --git a/FoxTube/Controls/VideoCard.xaml.cs b/FoxTube/Controls/VideoCard.xaml.cs index 4ad9977..3ca5301 100644 --- a/FoxTube/Controls/VideoCard.xaml.cs +++ b/FoxTube/Controls/VideoCard.xaml.cs @@ -16,7 +16,7 @@ namespace FoxTube.Controls public string videoId; Video item; - bool embed = true; + bool embed = false; public VideoCard(string id, string playlist = null) { this.InitializeComponent(); diff --git a/FoxTube/Controls/VideoPlayer.xaml b/FoxTube/Controls/VideoPlayer.xaml index 0a9a56f..5ab4024 100644 --- a/FoxTube/Controls/VideoPlayer.xaml +++ b/FoxTube/Controls/VideoPlayer.xaml @@ -2,10 +2,8 @@ x:Class="FoxTube.VideoPlayer" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:local="using:FoxTube" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" xmlns:controls1="using:FoxTube.Controls" mc:Ignorable="d" d:DesignHeight="1080" @@ -27,7 +25,7 @@ - + diff --git a/FoxTube/Controls/VideoPlayer.xaml.cs b/FoxTube/Controls/VideoPlayer.xaml.cs index 0c163ce..87b6f82 100644 --- a/FoxTube/Controls/VideoPlayer.xaml.cs +++ b/FoxTube/Controls/VideoPlayer.xaml.cs @@ -27,8 +27,6 @@ using System.Globalization; using FoxTube.Controls; using Windows.System; -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - namespace FoxTube { public sealed partial class VideoPlayer : UserControl @@ -53,6 +51,7 @@ namespace FoxTube public event ObjectEventHandler SetFullSize; public event ObjectEventHandler NextClicked; + public Button Next => next; bool isMuxed = false; bool audioReady = false; diff --git a/FoxTube/Pages/VideoPage.xaml b/FoxTube/Pages/VideoPage.xaml index 3e4c9b9..9bba390 100644 --- a/FoxTube/Pages/VideoPage.xaml +++ b/FoxTube/Pages/VideoPage.xaml @@ -6,8 +6,6 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:pages="using:FoxTube.Pages" - xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" - xmlns:ui="using:Microsoft.Advertising.WinRT.UI" xmlns:controls1="using:FoxTube.Controls" mc:Ignorable="d"> @@ -37,12 +35,6 @@ - @@ -82,26 +74,7 @@ - - - - - - - - - - - - - - - - - - - - + diff --git a/FoxTube/Pages/VideoPage.xaml.cs b/FoxTube/Pages/VideoPage.xaml.cs index 36f4765..15e7a60 100644 --- a/FoxTube/Pages/VideoPage.xaml.cs +++ b/FoxTube/Pages/VideoPage.xaml.cs @@ -1,22 +1,23 @@ -using System; +using FoxTube.Controls; +using Google.Apis.YouTube.v3; +using Google.Apis.YouTube.v3.Data; +using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; using System.Linq; +using Windows.ApplicationModel.DataTransfer; using Windows.Foundation; +using Windows.Storage; +using Windows.System; +using Windows.UI; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; -using Windows.UI.Xaml.Navigation; -using Windows.System; -using Google.Apis.YouTube.v3.Data; -using Google.Apis.YouTube.v3; using Windows.UI.Xaml.Media.Imaging; -using System.Diagnostics; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using Windows.UI; -using FoxTube.Controls; -using YoutubeExplode.Models.MediaStreams; +using Windows.UI.Xaml.Navigation; using YoutubeExplode; +using YoutubeExplode.Models.MediaStreams; namespace FoxTube.Pages { @@ -57,6 +58,8 @@ namespace FoxTube.Pages public CommentsPage comments; public LoadingPage loading; + DispatcherTimer liveTimer; + public VideoPage() { InitializeComponent(); @@ -86,7 +89,10 @@ namespace FoxTube.Pages private void Player_NextClicked(object sender, params object[] e) { - (relatedVideos.Children[0] as VideoCard).Button_Click(this, null); + if (playlistId != null) + playlistList.SelectedIndex++; + else + (relatedVideos.Children[0] as VideoCard).Button_Click(this, null); } protected override void OnNavigatedTo(NavigationEventArgs e) @@ -107,123 +113,20 @@ namespace FoxTube.Pages videoId = ids[0]; if (ids[1] != null) - { - playlistId = ids[1]; - List items = new List(); - VideoPlaylistItem selection = null; - - PlaylistsResource.ListRequest playlistRequest = SecretsVault.Service.Playlists.List("snippet,contentDetails"); - playlistRequest.Id = ids[1]; - Playlist playlistItem = (await playlistRequest.ExecuteAsync()).Items[0]; - - playlistName.Text = playlistItem.Snippet.Title; - playlistChannel.Text = playlistItem.Snippet.ChannelTitle; - - PlaylistItemsResource.ListRequest listRequest = SecretsVault.Service.PlaylistItems.List("snippet"); - listRequest.MaxResults = 50; - listRequest.PlaylistId = ids[1]; - PlaylistItemListResponse listResponse = await listRequest.ExecuteAsync(); - - foreach (PlaylistItem i in listResponse.Items) - { - items.Add(new VideoPlaylistItem(i.Snippet.Thumbnails.Medium.Url, i.Snippet.Title, i.Snippet.ResourceId.VideoId)); - if (items.Last().Id == videoId) - selection = items.Last(); - } - - string token = listResponse.NextPageToken; - while(!string.IsNullOrWhiteSpace(token)) - { - listRequest.PageToken = token; - listResponse = await listRequest.ExecuteAsync(); - - foreach (PlaylistItem i in listResponse.Items) - { - items.Add(new VideoPlaylistItem(i.Snippet.Thumbnails.Medium.Url, i.Snippet.Title, i.Snippet.ResourceId.VideoId)); - if (items.Last().Id == videoId) - selection = items.Last(); - } - - token = listResponse.NextPageToken; - } - - for (int k = 0; k < items.Count; k++) - items[k].Number = k + 1; - - playlistCounter.Text = $"{items.IndexOf(selection) + 1}/{playlistItem.ContentDetails.ItemCount}"; - - playlistList.ItemsSource = items; - playlistList.SelectedItem = selection; - pivot.SelectedItem = playlist; - } + LoadPlaylist(ids[1]); else pivot.Items.Remove(playlist); - VideosResource.ListRequest request = SecretsVault.Service.Videos.List("snippet,statistics,status,contentDetails"); + VideosResource.ListRequest request = SecretsVault.Service.Videos.List("snippet,statistics,status,contentDetails,liveStreamingDetails"); request.Id = ids[0]; item = (await request.ExecuteAsync()).Items[0]; - title.Text = item.Snippet.Title; - Methods.FormatText(ref description, item.Snippet.Description); - - publishedAt.Text = item.Snippet.PublishedAt.ToString(); - if (item.Status.License == "youtube") - license.Text = "Standard YouTube License"; - else license.Text = "Creative Commons Attribution license (reuse allowed)"; - - VideoCategoriesResource.ListRequest categoryRequest = SecretsVault.Service.VideoCategories.List("snippet"); - categoryRequest.Id = item.Snippet.CategoryId; - category.Text = (await categoryRequest.ExecuteAsync()).Items[0].Snippet.Title; - - views.Text = $"{item.Statistics.ViewCount:0,0} views"; - dislikes.Text = $"{item.Statistics.DislikeCount:0,0}"; - likes.Text = $"{item.Statistics.LikeCount:0,0}"; - rating.Value = (double)item.Statistics.DislikeCount / (double)(item.Statistics.DislikeCount + item.Statistics.LikeCount) * 100; - - if (SecretsVault.IsAuthorized) - { - VideoGetRatingResponse ratingResponse = await SecretsVault.Service.Videos.GetRating(ids[0]).ExecuteAsync(); - if (ratingResponse.Items[0].Rating == "like") - { - userRating = Rating.Like; - like.Foreground = new SolidColorBrush(Colors.Green); - } - else if (ratingResponse.Items[0].Rating == "dislike") - { - userRating = Rating.Dislike; - dislike.Foreground = new SolidColorBrush(Colors.Red); - } - - foreach (Subscription s in SecretsVault.Subscriptions) - { - if (s.Snippet.ResourceId.ChannelId == item.Snippet.ChannelId) - { - subscribe.Background = new SolidColorBrush(Colors.Transparent); - subscribe.Foreground = new SolidColorBrush(Colors.Gray); - subscribe.Content = "Subscribed"; - } - } - subscribe.Visibility = Visibility.Visible; - } + if (item.Snippet.LiveBroadcastContent == "none") + LoadStats(); else - { - download.Visibility = Visibility.Collapsed; - addTo.Visibility = Visibility.Collapsed; - subscribe.Visibility = Visibility.Collapsed; - } + LoadStream(); - ChannelsResource.ListRequest channelRequest = SecretsVault.Service.Channels.List("snippet, statistics"); - channelRequest.Id = item.Snippet.ChannelId; - var item1 = (await channelRequest.ExecuteAsync()).Items[0]; - - channelAvatar.ProfilePicture = new BitmapImage(new Uri(item1.Snippet.Thumbnails.Medium.Url)); - channelName.Text = item.Snippet.ChannelTitle; - subscribers.Text = $"{item1.Statistics.SubscriberCount:0,0} subscribers"; - - comments.Initialize(item); - player.Initialize(item, item1.Snippet.Thumbnails.Medium.Url); - LoadRelatedVideos(); - LoadDownloads(); + LoadInfo(); loading.Close(); } @@ -237,6 +140,155 @@ namespace FoxTube.Pages } } + async void LoadPlaylist(string id) + { + playlistId = id; + List items = new List(); + VideoPlaylistItem selection = null; + + //Retrieving data + PlaylistsResource.ListRequest playlistRequest = SecretsVault.Service.Playlists.List("snippet,contentDetails"); + playlistRequest.Id = id; + Playlist playlistItem = (await playlistRequest.ExecuteAsync()).Items[0]; + + PlaylistItemsResource.ListRequest listRequest = SecretsVault.Service.PlaylistItems.List("snippet"); + listRequest.MaxResults = 50; + listRequest.PlaylistId = id; + PlaylistItemListResponse listResponse = await listRequest.ExecuteAsync(); + + foreach (PlaylistItem i in listResponse.Items) + { + items.Add(new VideoPlaylistItem(i.Snippet.Thumbnails.Medium.Url, i.Snippet.Title, i.Snippet.ResourceId.VideoId)); + if (items.Last().Id == videoId) + selection = items.Last(); + } + + string token = listResponse.NextPageToken; + while (!string.IsNullOrWhiteSpace(token)) + { + listRequest.PageToken = token; + listResponse = await listRequest.ExecuteAsync(); + + foreach (PlaylistItem i in listResponse.Items) + { + items.Add(new VideoPlaylistItem(i.Snippet.Thumbnails.Medium.Url, i.Snippet.Title, i.Snippet.ResourceId.VideoId)); + if (items.Last().Id == videoId) + selection = items.Last(); + } + + token = listResponse.NextPageToken; + } + + for (int k = 0; k < items.Count; k++) + items[k].Number = k + 1; + + //Setting data + playlistName.Text = playlistItem.Snippet.Title; + playlistChannel.Text = playlistItem.Snippet.ChannelTitle; + + playlistCounter.Text = $"{items.IndexOf(selection) + 1}/{playlistItem.ContentDetails.ItemCount}"; + + playlistList.ItemsSource = items; + playlistList.SelectedItem = selection; + pivot.SelectedItem = playlist; + + if (playlistList.SelectedIndex == playlistList.Items.Count - 1) + player.Next.Visibility = Visibility.Collapsed; + } + + async void LoadInfo() + { + //Setting meta + title.Text = item.Snippet.Title; + Methods.FormatText(ref description, item.Snippet.Description); + + //Setting channel button + ChannelsResource.ListRequest channelRequest = SecretsVault.Service.Channels.List("snippet, statistics"); + channelRequest.Id = item.Snippet.ChannelId; + var item1 = (await channelRequest.ExecuteAsync()).Items[0]; + + channelAvatar.ProfilePicture = new BitmapImage(new Uri(item1.Snippet.Thumbnails.Medium.Url)); + channelName.Text = item.Snippet.ChannelTitle; + subscribers.Text = $"{item1.Statistics.SubscriberCount:0,0} subscribers"; + + //Setting ratings + dislikes.Text = $"{item.Statistics.DislikeCount:0,0}"; + likes.Text = $"{item.Statistics.LikeCount:0,0}"; + rating.Value = (double)item.Statistics.DislikeCount / (double)(item.Statistics.DislikeCount + item.Statistics.LikeCount) * 100; + + //Setting category + VideoCategoriesResource.ListRequest categoryRequest = SecretsVault.Service.VideoCategories.List("snippet"); + categoryRequest.Id = item.Snippet.CategoryId; + category.Text = (await categoryRequest.ExecuteAsync()).Items[0].Snippet.Title; + + //Setting User's rate + if (SecretsVault.IsAuthorized) + { + VideoGetRatingResponse ratingResponse = await SecretsVault.Service.Videos.GetRating(videoId).ExecuteAsync(); + if (ratingResponse.Items[0].Rating == "like") + { + userRating = Rating.Like; + like.Foreground = new SolidColorBrush(Colors.Green); + } + else if (ratingResponse.Items[0].Rating == "dislike") + { + userRating = Rating.Dislike; + dislike.Foreground = new SolidColorBrush(Colors.Red); + } + + foreach (Subscription s in SecretsVault.Subscriptions) + { + if (s.Snippet.ResourceId.ChannelId == item.Snippet.ChannelId) + { + subscribe.Background = new SolidColorBrush(Colors.Transparent); + subscribe.Foreground = new SolidColorBrush(Colors.Gray); + subscribe.Content = "Subscribed"; + } + } + subscribe.Visibility = Visibility.Visible; + } + else + { + download.Visibility = Visibility.Collapsed; + addTo.Visibility = Visibility.Collapsed; + subscribe.Visibility = Visibility.Collapsed; + } + + //Initializing player + player.Initialize(item, item1.Snippet.Thumbnails.Medium.Url); + + LoadRelatedVideos(); + } + + void LoadStream() + { + liveTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(10) }; + liveTimer.Tick += LiveStatsUpdate; + liveTimer.Start(); + LiveStatsUpdate(); + + commentsPlaceholder.Header = "Chat"; + //TODO: Initialize chat + download.Visibility = Visibility.Collapsed; + } + + private async void LiveStatsUpdate(object sender = null, object e = null) + { + VideosResource.ListRequest request = SecretsVault.Service.Videos.List("liveStreamingDetails"); + request.Id = videoId; + Video video = (await request.ExecuteAsync()).Items[0]; + + views.Text = $"{item.LiveStreamingDetails.ConcurrentViewers} viewers"; + } + + void LoadStats() + { + views.Text = $"{item.Statistics.ViewCount:0,0} views"; + + comments.Initialize(item); + LoadDownloads(); + } + async void LoadDownloads() { try @@ -275,6 +327,8 @@ namespace FoxTube.Pages async void LoadRelatedVideos() { SearchResource.ListRequest request = SecretsVault.Service.Search.List("snippet"); + request.RegionCode = CultureInfo.GetCultures(CultureTypes.AllCultures).Find(i => i.IetfLanguageTag == SettingsStorage.Region).IetfLanguageTag.Remove(0, 3); + request.RelevanceLanguage = CultureInfo.GetCultures(CultureTypes.AllCultures).Find(i => i.IetfLanguageTag == SettingsStorage.Region).TwoLetterISOLanguageName; request.RelatedToVideoId = videoId; request.SafeSearch = (SearchResource.ListRequest.SafeSearchEnum)(int)settings.Values["safeSearch"]; request.MaxResults = 20; @@ -388,10 +442,10 @@ namespace FoxTube.Pages { case Rating.Like: like.Foreground = new SolidColorBrush(Colors.Gray); - likes.Text = (int.Parse(likes.Text, System.Globalization.NumberStyles.AllowThousands) - 1).ToString("0,0"); + likes.Text = (int.Parse(likes.Text, NumberStyles.AllowThousands) - 1).ToString("0,0"); dislike.Foreground = new SolidColorBrush(Colors.Red); - dislikes.Text = (int.Parse(dislikes.Text, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0"); + dislikes.Text = (int.Parse(dislikes.Text, NumberStyles.AllowThousands) + 1).ToString("0,0"); rating.Value--; await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Dislike).ExecuteAsync(); @@ -400,7 +454,7 @@ namespace FoxTube.Pages case Rating.None: dislike.Foreground = new SolidColorBrush(Colors.Red); - dislikes.Text = (int.Parse(dislikes.Text, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0"); + dislikes.Text = (int.Parse(dislikes.Text, NumberStyles.AllowThousands) + 1).ToString("0,0"); rating.Maximum++; await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Dislike).ExecuteAsync(); @@ -409,7 +463,7 @@ namespace FoxTube.Pages case Rating.Dislike: dislike.Foreground = new SolidColorBrush(Colors.Gray); - dislikes.Text = (int.Parse(dislikes.Text, System.Globalization.NumberStyles.AllowThousands) - 1).ToString("0,0"); + dislikes.Text = (int.Parse(dislikes.Text, NumberStyles.AllowThousands) - 1).ToString("0,0"); rating.Maximum--; await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.None).ExecuteAsync(); break; @@ -423,10 +477,10 @@ namespace FoxTube.Pages { case Rating.Dislike: dislike.Foreground = new SolidColorBrush(Colors.Gray); - dislikes.Text = (int.Parse(dislikes.Text, System.Globalization.NumberStyles.AllowThousands) - 1).ToString("0,0"); + dislikes.Text = (int.Parse(dislikes.Text, NumberStyles.AllowThousands) - 1).ToString("0,0"); like.Foreground = new SolidColorBrush(Colors.Green); - likes.Text = (int.Parse(likes.Text, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0"); + likes.Text = (int.Parse(likes.Text, NumberStyles.AllowThousands) + 1).ToString("0,0"); rating.Value++; await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Like).ExecuteAsync(); @@ -435,7 +489,7 @@ namespace FoxTube.Pages case Rating.None: like.Foreground = new SolidColorBrush(Colors.Green); - likes.Text = (int.Parse(likes.Text, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0"); + likes.Text = (int.Parse(likes.Text, NumberStyles.AllowThousands) + 1).ToString("0,0"); rating.Maximum++; rating.Value++; await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Like).ExecuteAsync(); @@ -445,7 +499,7 @@ namespace FoxTube.Pages case Rating.Like: like.Foreground = new SolidColorBrush(Colors.Gray); - likes.Text = (int.Parse(likes.Text, System.Globalization.NumberStyles.AllowThousands) - 1).ToString("0,0"); + likes.Text = (int.Parse(likes.Text, NumberStyles.AllowThousands) - 1).ToString("0,0"); rating.Maximum--; rating.Value--; await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.None).ExecuteAsync();