@@ -53,7 +53,6 @@ namespace FoxTube
|
||||
|
||||
public event ObjectEventHandler SetFullSize;
|
||||
public event ObjectEventHandler NextClicked;
|
||||
public Button Next => next;
|
||||
|
||||
bool isMuxed = false;
|
||||
bool audioReady = false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" IgnorableNamespaces="uap mp uap3">
|
||||
<Identity Name="foxtube-5d1cba1f-d7d5-472b-acb7-beb360bab268" Publisher="CN=Michael Gordeev" Version="0.2.1812.0" />
|
||||
<Identity Name="foxtube-5d1cba1f-d7d5-472b-acb7-beb360bab268" Publisher="CN=XFox" Version="1.0.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="5d1cba1f-d7d5-472b-acb7-beb360bab268" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>FoxTube</DisplayName>
|
||||
|
||||
@@ -392,13 +392,6 @@ namespace FoxTube
|
||||
nav.IsBackEnabled = true;
|
||||
else
|
||||
nav.IsBackEnabled = false;
|
||||
|
||||
if (content.SourcePageType == typeof(Home) || content.SourcePageType == typeof(Settings) || content.SourcePageType == typeof(Subscriptions))
|
||||
{
|
||||
nav.ExpandedModeThresholdWidth = 1008;
|
||||
if (nav.DisplayMode == NavigationViewDisplayMode.Expanded)
|
||||
nav.IsPaneOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void MaximizeVideo()
|
||||
@@ -410,9 +403,6 @@ namespace FoxTube
|
||||
videoPlaceholder.Margin = new Thickness(0);
|
||||
|
||||
nav.IsBackEnabled = true;
|
||||
|
||||
nav.ExpandedModeThresholdWidth = short.MaxValue;
|
||||
nav.IsPaneOpen = false;
|
||||
}
|
||||
|
||||
public void Fullscreen(bool on)
|
||||
@@ -451,6 +441,7 @@ namespace FoxTube
|
||||
(videoPlaceholder.Content as VideoPage).player.pointerCaptured = false;
|
||||
videoPlaceholder.Content = null;
|
||||
Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Arrow, 0);
|
||||
MaximizeVideo();
|
||||
|
||||
if (content.CanGoBack)
|
||||
nav.IsBackEnabled = true;
|
||||
@@ -674,7 +665,7 @@ namespace FoxTube
|
||||
nav.IsPaneOpen = true;
|
||||
}
|
||||
else
|
||||
nav.ExpandedModeThresholdWidth = short.MaxValue;
|
||||
nav.ExpandedModeThresholdWidth = int.MaxValue;
|
||||
|
||||
if (videoPlaceholder.Content != null && videoPlaceholder.HorizontalAlignment == HorizontalAlignment.Stretch)
|
||||
MinimizeAsInitializer();
|
||||
|
||||
@@ -82,7 +82,26 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<TextBlock Name="description" Text="[Description]" IsTextSelectionEnabled="True" TextWrapping="WrapWholeWords"/>
|
||||
<TextBlock Margin="0,20" Name="category" Text="Category: "/>
|
||||
<Grid Margin="0,20,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="20"/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Text="Published at: "/>
|
||||
<TextBlock Grid.Row="1" Text="Category: "/>
|
||||
<TextBlock Grid.Row="2" Text="License: "/>
|
||||
|
||||
<TextBlock Name="publishedAt" Grid.Column="2" Text="[Publishing date]"/>
|
||||
<TextBlock Name="category" Grid.Column="2" Grid.Row="1" Padding="0" Text="[Category]"/>
|
||||
<TextBlock Name="license" Grid.Column="2" Grid.Row="2" Text="[License type]"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</PivotItem>
|
||||
</StackPanel>
|
||||
|
||||
+129
-173
@@ -20,7 +20,7 @@ using FoxTube.Controls;
|
||||
using YoutubeExplode.Models.MediaStreams;
|
||||
using YoutubeExplode;
|
||||
|
||||
//TODO: Refactor page sizing algorythm; Cleanup code
|
||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
namespace FoxTube.Pages
|
||||
{
|
||||
@@ -61,8 +61,6 @@ namespace FoxTube.Pages
|
||||
public CommentsPage comments;
|
||||
public LoadingPage loading;
|
||||
|
||||
DispatcherTimer liveTimer;
|
||||
|
||||
public VideoPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -92,10 +90,7 @@ namespace FoxTube.Pages
|
||||
|
||||
private void Player_NextClicked(object sender, params object[] e)
|
||||
{
|
||||
if(playlistId != null)
|
||||
playlistList.SelectedIndex++;
|
||||
else
|
||||
(relatedVideos.Children[0] as VideoCard).Button_Click(this, null);
|
||||
(relatedVideos.Children[0] as VideoCard).Button_Click(this, null);
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
@@ -116,20 +111,123 @@ namespace FoxTube.Pages
|
||||
videoId = ids[0];
|
||||
|
||||
if (ids[1] != null)
|
||||
LoadPlaylist(ids[1]);
|
||||
{
|
||||
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,liveStreamingDetails");
|
||||
VideosResource.ListRequest request = SecretsVault.Service.Videos.List("snippet,statistics,status,contentDetails");
|
||||
request.Id = ids[0];
|
||||
item = (await request.ExecuteAsync()).Items[0];
|
||||
|
||||
if (item.Snippet.LiveBroadcastContent == "none")
|
||||
LoadStats();
|
||||
else
|
||||
LoadStream();
|
||||
title.Text = item.Snippet.Title;
|
||||
Methods.FormatText(ref description, item.Snippet.Description);
|
||||
|
||||
LoadInfo();
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
download.Visibility = Visibility.Collapsed;
|
||||
addTo.Visibility = Visibility.Collapsed;
|
||||
subscribe.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -143,155 +241,6 @@ namespace FoxTube.Pages
|
||||
}
|
||||
}
|
||||
|
||||
async void LoadPlaylist(string id)
|
||||
{
|
||||
playlistId = id;
|
||||
List<VideoPlaylistItem> items = new List<VideoPlaylistItem>();
|
||||
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.NoAuthService.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
|
||||
@@ -302,10 +251,9 @@ namespace FoxTube.Pages
|
||||
MenuFlyoutItem menuItem = new MenuFlyoutItem()
|
||||
{
|
||||
Text = i.VideoQualityLabel,
|
||||
Tag = new { i, i.VideoQualityLabel }
|
||||
Tag = new object[] { i, i.VideoQualityLabel }
|
||||
};
|
||||
menuItem.Click += (sender, e) =>
|
||||
DownloadAgent.Add(((sender as MenuFlyoutItem).Tag as object[])[0] as MediaStreamInfo, item, ((sender as MenuFlyoutItem).Tag as object[])[1] as string);
|
||||
menuItem.Click += downloadItemSelected;
|
||||
downloadSelector.Items.Add(menuItem);
|
||||
}
|
||||
|
||||
@@ -314,17 +262,20 @@ namespace FoxTube.Pages
|
||||
Text = "Audio track",
|
||||
Tag = new object[] { infoSet.Audio[0], "Audio only" }
|
||||
};
|
||||
audioItem.Click += (sender, e) =>
|
||||
DownloadAgent.Add(((sender as MenuFlyoutItem).Tag as object[])[0] as MediaStreamInfo, item, ((sender as MenuFlyoutItem).Tag as object[])[1] as string);
|
||||
audioItem.Click += downloadItemSelected;
|
||||
downloadSelector.Items.Add(audioItem);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine($"{e.GetType()}: '{e.Message}'");
|
||||
download.Visibility = Visibility.Collapsed;
|
||||
loading.Error(e.GetType().ToString(), e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadItemSelected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DownloadAgent.Add(((sender as MenuFlyoutItem).Tag as object[])[0] as MediaStreamInfo, item, ((sender as MenuFlyoutItem).Tag as object[])[1] as string);
|
||||
}
|
||||
|
||||
async void LoadRelatedVideos()
|
||||
{
|
||||
SearchResource.ListRequest request = SecretsVault.Service.Search.List("snippet");
|
||||
@@ -381,7 +332,8 @@ namespace FoxTube.Pages
|
||||
|
||||
public void refresh_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Methods.MainPage.GoToVideo(videoId, playlistId);
|
||||
player = new VideoPlayer();
|
||||
Initialize(new string[2] { videoId, playlistId });
|
||||
}
|
||||
|
||||
private void grid_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
@@ -536,8 +488,12 @@ namespace FoxTube.Pages
|
||||
|
||||
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if ((e.AddedItems[0] as VideoPlaylistItem).Id != videoId)
|
||||
Methods.MainPage.GoToVideo((e.AddedItems[0] as VideoPlaylistItem).Id, playlistId);
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user