Archived
1
0
This repository has been archived on 2026-04-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
FoxTube/FoxTube/Pages/VideoPage.xaml.cs
T
Michael Gordeev 3bca3a30be Video playback fixes
Merged to YouTubeExplode instead of MyToolkit
2018-10-21 00:49:34 +03:00

509 lines
21 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Windows.Foundation;
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.ApplicationModel;
using Windows.Storage.Streams;
using Windows.UI;
using FoxTube.Controls;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace FoxTube.Pages
{
public enum Rating { None, Like, Dislike }
public class VideoPlaylistItem
{
public int Number { get; set; }
public string Thumbnail { get; private set; } = "/Assets/videoThumbSample.png";
public string Id { get; private set; }
public string Title { get; private set; }
public VideoPlaylistItem(string image, string title, string id)
{
Thumbnail = image;
Title = title;
Id = id;
}
}
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class VideoPage : Page
{
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
public string videoId;
string playlistId = null;
public Video item;
bool wide;
bool isExtended = false;
Rating userRating = Rating.None;
public VideoPlayer player;
public CommentsPage comments;
public LoadingPage loading;
public VideoPage()
{
this.InitializeComponent();
loading = grid.Children[3] as LoadingPage;
loading.RefreshPage += refresh_Click;
player = mainContent.Children[0] as VideoPlayer;
player.SetFullSize += Player_SetFullSize;
player.NextClicked += Player_NextClicked;
comments = commentsPlaceholder.Content as CommentsPage;
DataTransferManager.GetForCurrentView().DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(Share);
if (Window.Current.Bounds.Width <= 1000)
{
Debug.WriteLine("Correcting layout...");
mainContent.Children.Remove(descriptionPanel);
pivot.Items.Insert(0, descriptionPanel);
tabsPlaceholder.Children.Remove(pivot);
mainContent.Children.Add(pivot);
grid.ColumnDefinitions[1].Width = new GridLength(0);
pivot.SelectedIndex = 0;
}
}
private void Player_NextClicked(object sender, params object[] e)
{
(relatedVideos.Children[0] as VideoCard).Button_Click(this, null);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Parameter == null || string.IsNullOrWhiteSpace((e.Parameter as string[])[0]))
loading.Error("NullReferenceException", "Unable to initialize page. Video ID is not stated.");
else
Initialize(e.Parameter as string[]);
}
public async void Initialize(string[] ids)
{
loading.Refresh();
try
{
videoId = ids[0];
if (ids[1] != null)
{
playlistId = ids[1];
List<VideoPlaylistItem> items = new List<VideoPlaylistItem>();
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;
}
else
pivot.Items.Remove(playlist);
VideosResource.ListRequest request = SecretsVault.Service.Videos.List("snippet,statistics,status,contentDetails");
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.NoAuthService.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;
}
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();
loading.Close();
}
catch (System.Net.Http.HttpRequestException)
{
loading.Error("System.Net.Http.HttpRequestException", "Unable to connect to Google servers.", true);
}
catch (Exception e)
{
loading.Error(e.GetType().ToString(), e.Message);
}
}
async void LoadDownloads()
{
/*List<YouTubeUri> uris = (await YouTube.GetUrisAsync(item.Id)).ToList();
if (uris.Count > 0)
foreach (YouTubeUri u in uris)
{
if (u.HasAudio && u.HasVideo)
{
MenuFlyoutItem menuItem = new MenuFlyoutItem()
{
Text = Methods.QualityToString(u.VideoQuality),
Tag = u.Uri.AbsoluteUri
};
menuItem.Click += downloadItemSelected;
downloadSelector.Items.Add(menuItem);
}
else if (u.HasAudio)
{
MenuFlyoutItem menuItem = new MenuFlyoutItem()
{
Text = Methods.QualityToString(u.AudioQuality),
Tag = u.Uri.AbsoluteUri
};
menuItem.Click += downloadItemSelected;
downloadSelector.Items.Add(menuItem);
}
}
else
download.Visibility = Visibility.Collapsed;*/
}
private void downloadItemSelected(object sender, RoutedEventArgs e)
{
Methods.MainPage.Agent.Add((sender as MenuFlyoutItem).Tag.ToString());
}
async void LoadRelatedVideos()
{
SearchResource.ListRequest request = SecretsVault.Service.Search.List("snippet");
request.RelatedToVideoId = videoId;
request.SafeSearch = (SearchResource.ListRequest.SafeSearchEnum)(int)settings.Values["safeSearch"];
request.MaxResults = 20;
request.Type = "video";
SearchListResponse response = await request.ExecuteAsync();
foreach (SearchResult video in response.Items)
relatedVideos.Children.Add(new VideoCard(video.Id.VideoId));
}
private void Player_SetFullSize(object sender, params object[] e)
{
isExtended = (bool)e[0];
if(isExtended)
{
grid.ColumnDefinitions[1].Width = new GridLength(0);
commandbar.Visibility = Visibility.Collapsed;
mainScroll.Margin = new Thickness(0);
mainScroll.ChangeView(0, 0, null);
mainScroll.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
mainScroll.VerticalScrollMode = ScrollMode.Disabled;
}
else
{
commandbar.Visibility = Visibility.Visible;
mainScroll.Margin = new Thickness(0,0,0,50);
mainScroll.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
mainScroll.VerticalScrollMode = ScrollMode.Auto;
if (wide)
grid.ColumnDefinitions[1].Width = new GridLength(400);
}
}
private void gotoChannel_Click(object sender, RoutedEventArgs e)
{
Methods.MainPage.GoToChannel(item.Snippet.ChannelId);
}
private async void openBrowser_Click(object sender, RoutedEventArgs e)
{
player.Pause();
string timecode = player.elapsed.TotalSeconds > 10 ?
"&t=" + (int)player.elapsed.TotalSeconds + "s" : string.Empty;
await Launcher.LaunchUriAsync(new Uri($"https://www.youtube.com/watch?v={videoId}{timecode}"));
}
public void refresh_Click(object sender, RoutedEventArgs e)
{
player = new VideoPlayer();
Initialize(new string[2] { videoId, playlistId });
}
private void grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
Debug.WriteLine(e.NewSize.Width);
if (e.NewSize.Width > 1000)
wide = true;
else
wide = false;
if (e.NewSize.Width > 1000 && mainContent.Children.Contains(pivot) && !isExtended)
{
mainContent.Children.Remove(pivot);
tabsPlaceholder.Children.Add(pivot);
pivot.Items.RemoveAt(0);
mainContent.Children.Add(descriptionPanel);
grid.ColumnDefinitions[1].Width = new GridLength(400);
pivot.SelectedIndex = 0;
}
else if (e.NewSize.Width <= 1000 && mainContent.Children.Contains(descriptionPanel))
{
mainContent.Children.Remove(descriptionPanel);
pivot.Items.Insert(0, descriptionPanel);
tabsPlaceholder.Children.Remove(pivot);
mainContent.Children.Add(pivot);
grid.ColumnDefinitions[1].Width = new GridLength(0);
pivot.SelectedIndex = 0;
}
}
private async void Share(DataTransferManager sender, DataRequestedEventArgs args)
{
player.Pause();
DataRequest request = args.Request;
request.Data.Properties.Title = item.Snippet.Title;
request.Data.Properties.Description = "Sharing a video";
// Handle errors
//request.FailWithDisplayText("Something unexpected could happen.");
// Plain text
request.Data.SetText(item.Snippet.Title + "\n" + "#YouTube #FoxTube #SharedWithFoxTube");
// Uniform Resource Identifiers (URIs)
request.Data.SetWebLink(new Uri(string.Format("https://www.youtube.com/watch?v={0}", videoId)));
// HTML
//request.Data.SetHtmlFormat("<b>Bold Text</b>");
// Because we are making async calls in the DataRequested event handler,
// we need to get the deferral first.
DataRequestDeferral deferral = request.GetDeferral();
// Make sure we always call Complete on the deferral.
try
{
StorageFile thumbnailFile = await Package.Current.InstalledLocation.GetFileAsync(item.Snippet.Thumbnails.Medium.Url);
request.Data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromFile(thumbnailFile);
StorageFile imageFile = await Package.Current.InstalledLocation.GetFileAsync(item.Snippet.Thumbnails.Medium.Url);
// Bitmaps
request.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(imageFile));
}
finally
{
deferral.Complete();
}
}
private void share_Click(object sender, RoutedEventArgs e)
{
DataTransferManager.ShowShareUI();
}
private async void dislike_Click(object sender, RoutedEventArgs e)
{
if (SecretsVault.IsAuthorized)
switch (userRating)
{
case Rating.Like:
like.Foreground = new SolidColorBrush(Colors.Gray);
likes.Text = (int.Parse(likes.Text, System.Globalization.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");
rating.Value--;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Dislike).ExecuteAsync();
userRating = Rating.Dislike;
break;
case Rating.None:
dislike.Foreground = new SolidColorBrush(Colors.Red);
dislikes.Text = (int.Parse(dislikes.Text, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0");
rating.Maximum++;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Dislike).ExecuteAsync();
userRating = Rating.Dislike;
break;
case Rating.Dislike:
dislike.Foreground = new SolidColorBrush(Colors.Gray);
dislikes.Text = (int.Parse(dislikes.Text, System.Globalization.NumberStyles.AllowThousands) - 1).ToString("0,0");
rating.Maximum--;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.None).ExecuteAsync();
break;
}
}
private async void like_Click(object sender, RoutedEventArgs e)
{
if(SecretsVault.IsAuthorized)
switch (userRating)
{
case Rating.Dislike:
dislike.Foreground = new SolidColorBrush(Colors.Gray);
dislikes.Text = (int.Parse(dislikes.Text, System.Globalization.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");
rating.Value++;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Like).ExecuteAsync();
userRating = Rating.Like;
break;
case Rating.None:
like.Foreground = new SolidColorBrush(Colors.Green);
likes.Text = (int.Parse(likes.Text, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0");
rating.Maximum++;
rating.Value++;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Like).ExecuteAsync();
userRating = Rating.Like;
break;
case Rating.Like:
like.Foreground = new SolidColorBrush(Colors.Gray);
likes.Text = (int.Parse(likes.Text, System.Globalization.NumberStyles.AllowThousands) - 1).ToString("0,0");
rating.Maximum--;
rating.Value--;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.None).ExecuteAsync();
break;
}
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
if ((e.AddedItems[0] as VideoPlaylistItem).Id != videoId)
Methods.MainPage.GoToVideo((e.AddedItems[0] as VideoPlaylistItem).Id, playlistId);
}
catch { }
}
private async void subscribe_Click(object sender, RoutedEventArgs e)
{
if (await SecretsVault.ChangeSubscriptionState(item.Snippet.ChannelId))
{
subscribe.Background = new SolidColorBrush(Colors.Transparent);
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
subscribe.Content = "Subscribed";
}
else
{
subscribe.Background = new SolidColorBrush(Colors.Red);
subscribe.Foreground = new SolidColorBrush(Colors.White);
subscribe.Content = "Subscribe";
}
}
}
}