Archived
1
0

Search page, content cards and trending tab complete

This commit is contained in:
Michael Gordeev
2018-07-25 14:50:14 +03:00
parent 76dc77fc30
commit 66b3347023
24 changed files with 531 additions and 227 deletions
+5 -5
View File
@@ -50,19 +50,19 @@ namespace FoxTube.Controls
item.DownloadComplete += Item_DownloadComplete;
Items.Add(item);
ListChanged.Invoke(item, new ObjectEventArgs("add"));
ListChanged.Invoke(item, "add");
}
private void Item_DownloadComplete(object sender, ObjectEventArgs e)
private void Item_DownloadComplete(object sender, params object[] e)
{
doc["downloads"].InnerXml += e.Parameters[0];
doc["downloads"].InnerXml += e[0];
settings.Values["downloadHistory"] = doc.InnerXml;
}
private void Item_DownloadCanceled(object sender, ObjectEventArgs e)
private void Item_DownloadCanceled(object sender, params object[] e)
{
Items.Remove(sender as DownloadItem);
ListChanged.Invoke(sender, new ObjectEventArgs("remove"));
ListChanged.Invoke(sender, "remove");
}
}
}
+18 -17
View File
@@ -20,32 +20,33 @@ namespace FoxTube
public static string GetAgo(DateTime dateTime)
{
TimeSpan span = DateTime.Now - dateTime;
if (span.TotalMinutes < 1)
return "Just now";
else if (span.Minutes == 1)
else if (Math.Round(span.TotalMinutes) == 1)
return "1 minute ago";
else if (span.TotalMinutes > 60)
return span.Minutes + " minutes ago";
else if (span.Hours == 1)
else if (span.TotalMinutes < 60)
return Math.Round(span.TotalMinutes) + " minutes ago";
else if (Math.Round(span.TotalHours) == 1)
return "1 hour ago";
else if (span.TotalHours > 24)
return span.Hours + " hours ago";
else if (span.Days == 1)
else if (span.TotalHours < 24)
return Math.Round(span.TotalHours) + " hours ago";
else if (Math.Round(span.TotalDays) == 1)
return "1 day ago";
else if (span.TotalDays > 7)
return span.Days + " days ago";
else if (span.Days == 7)
else if (span.TotalDays < 7)
return Math.Round(span.TotalDays) + " days ago";
else if (Math.Round(span.TotalDays) == 7)
return "1 week ago";
else if (span.Days > 30)
return (int)(span.Days / 7) + " weeks ago";
else if (span.Days == 30)
else if (span.TotalDays < 30)
return Math.Round(span.TotalDays / 7) + " weeks ago";
else if (Math.Round(span.TotalDays) == 30)
return "1 month ago";
else if (span.Days > 365)
return (int)(span.Days / 30) + " months ago";
else if (span.Days == 365)
else if (Math.Round(span.TotalDays) < 365)
return Math.Round(span.TotalDays / 30) + " months ago";
else if (Math.Round(span.TotalDays / 365) == 365)
return "1 year ago";
else
return (int)(span.Days / 365) + " years ago";
return Math.Round(span.TotalDays / 365) + " years ago";
}
public static void FormatText(ref TextBlock block, string text)
+51 -51
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
@@ -12,45 +13,44 @@ using Windows.Storage;
namespace FoxTube
{
public class SecretsVault
public static class SecretsVault
{
#region Static Information
public static event EventHandler AuthorizationStateChanged;
public static event ObjectEventHandler SubscriptionsChanged;
private static ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
public static NetworkCredential EmailCredential => new NetworkCredential("youwillneverknowthisadress@gmail.com", "thisisthepassword12345");
public static ClientSecrets Secrets => new ClientSecrets()
{
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
};
private static UserCredential Credential;
public static BaseClientService.Initializer Initializer => new BaseClientService.Initializer()
{
HttpClientInitializer = Credential,
ApplicationName = "FoxTube"
};
public static SecretsVault Vault => Methods.MainPage.Vault;
public static string AccountId { get; private set; }
public static bool IsAuthorized { get; private set; } = false;
public static string AccountId => Methods.MainPage.Vault.userId;
public static bool IsAuthorized => Vault.IsLoged;
public static Google.Apis.YouTube.v3.Data.Channel UserChannel => Methods.MainPage.Vault.channel;
public static List<PlaylistItem> WatchLater => Methods.MainPage.Vault.later;
public static List<PlaylistItem> UserHistory => Methods.MainPage.Vault.history;
public static List<Subscription> Subscriptions => Methods.MainPage.Vault.subs;
public static Google.Apis.YouTube.v3.Data.Channel UserChannel { get; private set; }
public static List<PlaylistItem> WatchLater { get; private set; } = new List<PlaylistItem>();
public static List<PlaylistItem> UserHistory { get; private set; } = new List<PlaylistItem>();
public static List<Subscription> Subscriptions { get; private set; } = new List<Subscription>();
public static YouTubeService NoAuthService => new YouTubeService(new BaseClientService.Initializer()
{
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
ApplicationName = "FoxTube"
});
public static YouTubeService Service
{
get
{
if (IsAuthorized)
return new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = Vault.Credential,
ApplicationName = "FoxTube"
});
return new YouTubeService(Initializer);
else
return NoAuthService;
}
@@ -65,7 +65,11 @@ namespace FoxTube
{
Snippet = new SubscriptionSnippet()
{
ChannelId = id
ResourceId = new ResourceId()
{
ChannelId = id,
Kind = "youtube#channel"
}
}
}, "snippet");
@@ -82,32 +86,29 @@ namespace FoxTube
Subscription s = null;
foreach(Subscription i in Subscriptions)
if (i.Snippet.ChannelId == id)
if (i.Snippet.ResourceId.ChannelId == id)
{
s = i;
break;
}
if (s == null)
return false;
SubscriptionsChanged.Invoke(null, "remove", Subscriptions.IndexOf(s));
await Service.Subscriptions.Delete(s.Id).ExecuteAsync(); //???
try
{
await Service.Subscriptions.Delete(s.Id).ExecuteAsync();
}
catch
{
return false;
}
SubscriptionsChanged.Invoke(null, "remove", Subscriptions.IndexOf(s));
Subscriptions.Remove(s);
return true;
}
#endregion
#region Object containers
public bool IsLoged = false;
public string userId;
public List<PlaylistItem> history = new List<PlaylistItem>();
public List<Subscription> subs = new List<Subscription>();
public List<PlaylistItem> later = new List<PlaylistItem>();
public Google.Apis.YouTube.v3.Data.Channel channel;
public UserCredential Credential;
private ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
public async void Authorize()
public static async void Authorize()
{
try { Credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(Secrets, new[] { Google.Apis.Oauth2.v2.Oauth2Service.Scope.UserinfoProfile, YouTubeService.Scope.YoutubeForceSsl }, "user", CancellationToken.None); }
catch { }
@@ -116,29 +117,29 @@ namespace FoxTube
if (settings.Values["authorized"] == null)
settings.Values.Add("authorized", true);
else settings.Values["authorized"] = true;
IsLoged = true;
IsAuthorized = true;
var request = Service.Channels.List("snippet,contentDetails");
request.Mine = true;
channel = (await request.ExecuteAsync()).Items[0];
userId = channel.Id;
UserChannel = (await request.ExecuteAsync()).Items[0];
AccountId = UserChannel.Id;
PlaylistItemsResource.ListRequest playlistRequest = Service.PlaylistItems.List("snippet");
playlistRequest.PlaylistId = channel.ContentDetails.RelatedPlaylists.WatchHistory;
playlistRequest.PlaylistId = UserChannel.ContentDetails.RelatedPlaylists.WatchHistory;
playlistRequest.MaxResults = 50;
PlaylistItemListResponse playlistResponse = await playlistRequest.ExecuteAsync();
history.Clear();
UserHistory.Clear();
foreach (PlaylistItem i in playlistResponse.Items)
history.Add(i);
UserHistory.Add(i);
playlistRequest = Service.PlaylistItems.List("snippet");
playlistRequest.PlaylistId = channel.ContentDetails.RelatedPlaylists.WatchLater;
playlistRequest.PlaylistId = UserChannel.ContentDetails.RelatedPlaylists.WatchLater;
playlistRequest.MaxResults = 50;
playlistResponse = await playlistRequest.ExecuteAsync();
later.Clear();
WatchLater.Clear();
foreach (PlaylistItem i in playlistResponse.Items)
later.Add(i);
WatchLater.Add(i);
string nextToken = playlistResponse.NextPageToken;
while (nextToken != null)
@@ -146,7 +147,7 @@ namespace FoxTube
playlistRequest.PageToken = nextToken;
playlistResponse = await playlistRequest.ExecuteAsync();
foreach (PlaylistItem i in playlistResponse.Items)
later.Add(i);
WatchLater.Add(i);
nextToken = playlistResponse.NextPageToken;
}
@@ -156,10 +157,10 @@ namespace FoxTube
subRequest.MaxResults = 50;
subRequest.Order = SubscriptionsResource.ListRequest.OrderEnum.Relevance;
SubscriptionListResponse subResponse = await subRequest.ExecuteAsync();
subs.Clear();
Subscriptions.Clear();
foreach (Subscription s in subResponse.Items)
subs.Add(s);
Subscriptions.Add(s);
nextToken = subResponse.NextPageToken;
while(nextToken != null)
@@ -167,30 +168,29 @@ namespace FoxTube
subRequest.PageToken = nextToken;
subResponse = await subRequest.ExecuteAsync();
foreach (Subscription s in subResponse.Items)
subs.Add(s);
Subscriptions.Add(s);
}
AuthorizationStateChanged.Invoke(this, null);
AuthorizationStateChanged.Invoke(null, null);
}
}
public async void Deauthenticate()
public static async void Deauthenticate()
{
if(await Credential.RevokeTokenAsync(CancellationToken.None))
{
Credential = null;
AuthorizationStateChanged.Invoke(this, null);
AuthorizationStateChanged.Invoke(null, null);
settings.Values["authorized"] = false;
}
}
public void CheckAuthorization()
public static void CheckAuthorization()
{
if (settings.Values["authorized"] == null || !(bool)settings.Values["authorized"])
IsLoged = false;
IsAuthorized = false;
else
Authorize();
}
#endregion
}
}
+6 -7
View File
@@ -14,10 +14,10 @@
<Button Padding="0" Background="Transparent" Click="Button_Click" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
<Grid Background="WhiteSmoke" BorderBrush="LightGray" BorderThickness="1">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Image Name="cover" Source="/Assets/ChannelCoverTemplate.png" Stretch="Fill"/>
<Image Name="cover" Source="/Assets/videoThumbSample.png" Stretch="UniformToFill" VerticalAlignment="Center"/>
<StackPanel Name="liveTag" Margin="5" Background="Red" BorderBrush="White" BorderThickness="1" VerticalAlignment="Bottom" HorizontalAlignment="Right" Padding="5,2,5,3" Orientation="Horizontal" Visibility="Collapsed">
<TextBlock Text="&#xEC44; " VerticalAlignment="Center" Foreground="White" FontSize="12" FontFamily="Segoe MDL2 Assets" FontWeight="Black"/>
<TextBlock Text="LIVE" VerticalAlignment="Center" Foreground="White" FontSize="12" FontWeight="Bold"/>
@@ -42,14 +42,13 @@
<TextBlock Name="uploads" Text="[Uploads counter]" Foreground="Gray"/>
</StackPanel>
</Grid>
<TextBlock Grid.Row="1" Name="description" Text="[Descrription]" TextWrapping="WrapWholeWords" Margin="5" MaxLines="5" Foreground="Gray"/>
<Grid Visibility="Collapsed" Grid.Row="1" VerticalAlignment="Bottom" Margin="10" Name="subscriptionPane">
<ToggleButton Click="subscribe_Click" Name="subscribe" HorizontalAlignment="Stretch" Height="50" Background="Red" Foreground="White" FontSize="18" FontWeight="SemiBold" Content="Subscirbe" Margin="0,0,50,0"/>
<ToggleButton Name="notify" Height="50" Width="50" FontFamily="Segoe MDL2 Assets" FontSize="18" FontWeight="SemiBold" Content="&#xE7ED;" Foreground="White" Background="Red" HorizontalAlignment="Right"/>
</Grid>
<TextBlock Grid.Row="1" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Height="50" Margin="10" TextAlignment="Center" Padding="0,16,0,0" Foreground="Gray">
<Hyperlink Click="Hyperlink_Click">Log in</Hyperlink> to manage your subscriptions
</TextBlock>
<Grid Visibility="Collapsed" Grid.Row="1" VerticalAlignment="Bottom" Margin="10" Name="subscriptionPane" Background="Red">
<ToggleButton Click="subscribe_Click" Name="subscribe" HorizontalAlignment="Stretch" Height="50" Background="Red" Foreground="White" FontSize="18" FontWeight="SemiBold" Content="Subscirbe" Margin="0,0,0,0"/>
<ToggleButton Name="notify" Height="50" Width="50" Visibility="Collapsed" FontFamily="Segoe MDL2 Assets" FontSize="18" FontWeight="SemiBold" Content="&#xE7ED;" Foreground="White" Background="Red" HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Grid>
</Button>
+15 -7
View File
@@ -38,7 +38,7 @@ namespace FoxTube.Controls
public async void Initialize(string id, string live)
{
ChannelsResource.ListRequest request = SecretsVault.NoAuthService.Channels.List("snippet,contentDetails,statistics,liveStreamingDetails");
ChannelsResource.ListRequest request = SecretsVault.NoAuthService.Channels.List("snippet,statistics,brandingSettings");
request.Id = id;
ChannelListResponse response = await request.ExecuteAsync();
@@ -46,10 +46,9 @@ namespace FoxTube.Controls
channelId = id;
title.Text = item.Snippet.Title;
description.Text = item.Snippet.Description;
subs.Text = $"{item.Statistics.SubscriberCount} subscribers";
uploads.Text = $"{item.Statistics.VideoCount} videos";
subs.Text = $"{item.Statistics.SubscriberCount:0,0} subscribers";
uploads.Text = $"{item.Statistics.VideoCount:0,0} videos";
if (live == "live")
liveTag.Visibility = Visibility.Visible;
@@ -58,8 +57,11 @@ namespace FoxTube.Controls
{
foreach(Subscription s in SecretsVault.Subscriptions)
{
if(s.Snippet.ChannelId == id)
if(s.Snippet.ResourceId.ChannelId == id)
{
subscribe.IsChecked = true;
subscribe.Content = "Subscribed";
}
}
subscriptionPane.Visibility = Visibility.Visible;
}
@@ -67,7 +69,7 @@ namespace FoxTube.Controls
try
{
avatar.ProfilePicture = new BitmapImage(new Uri(item.Snippet.Thumbnails.Medium.Url));
cover.Source = new BitmapImage(new Uri(item.BrandingSettings.Image.BannerImageUrl));
cover.Source = new BitmapImage(new Uri(item.BrandingSettings.Image.BannerTvLowImageUrl));
}
catch { }
}
@@ -79,7 +81,7 @@ namespace FoxTube.Controls
private void Hyperlink_Click(Windows.UI.Xaml.Documents.Hyperlink sender, Windows.UI.Xaml.Documents.HyperlinkClickEventArgs args)
{
SecretsVault.Vault.Authorize();
SecretsVault.Authorize();
}
private async void subscribe_Click(object sender, RoutedEventArgs e)
@@ -88,10 +90,16 @@ namespace FoxTube.Controls
{
if (!await SecretsVault.Subscribe(channelId))
subscribe.IsChecked = false;
else
subscribe.Content = "Subscribed";
}
else
{
if (!await SecretsVault.Unsubscibe(channelId))
subscribe.IsChecked = true;
else
subscribe.Content = "Subscribe";
}
}
}
}
+1 -1
View File
@@ -105,7 +105,7 @@ namespace FoxTube.Controls
</details>
</item>";
DownloadComplete.Invoke(this, new ObjectEventArgs(node));
DownloadComplete.Invoke(this, node);
}
public DownloadItem(string videoId, string videoName, string channelName, string thumbUrl, string length, string videoQuality, string path)
+51
View File
@@ -0,0 +1,51 @@
<Page
x:Class="FoxTube.Controls.PlaylistCard"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FoxTube.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
SizeChanged="UserControl_SizeChanged"
d:DesignHeight="290"
d:DesignWidth="384">
<Button Padding="0" Background="Transparent" Click="Button_Click">
<Grid Background="WhiteSmoke" BorderBrush="LightGray" BorderThickness="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="75"/>
</Grid.RowDefinitions>
<Image Name="thumbnail" Source="/Assets/videoThumbSample.png" Stretch="Fill"/>
<Grid HorizontalAlignment="Right" Width="100">
<Grid.Background>
<AcrylicBrush TintColor="#7F000000" BackgroundSource="Backdrop" AlwaysUseFallback="False" TintOpacity="1" Opacity="0.97"/>
</Grid.Background>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock HorizontalAlignment="Center" FontFamily="Segoe MDL2 Assets" Foreground="White" Text="&#xE90B;" FontSize="30"/>
<TextBlock Foreground="White" Text="[N/A]" HorizontalAlignment="Center" FontSize="20" Name="counter"/>
</StackPanel>
</Grid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="55"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Ellipse Grid.Column="0" Height="50" Width="50" Margin="5,-30,5,10" Fill="WhiteSmoke"/>
<PersonPicture Name="avatar" Grid.Column="0" Height="46" Margin="5,-30,5,0" BorderBrush="White" BorderThickness="10"/>
<TextBlock Name="channelName" Grid.Column="1" Text="[Channel name]" Foreground="Gray" Margin="0,2,0,0" FontSize="12"/>
<TextBlock Grid.Column="1" Name="date" Text="[Published at]" HorizontalAlignment="Right" Foreground="Gray" Margin="0,2,2,0" FontSize="12"/>
</Grid>
<TextBlock Grid.Row="1" Name="title" Text="[Title]" TextWrapping="WrapWholeWords" Margin="5" MaxLines="2"/>
</Grid>
</Grid>
</Button>
</Page>
+71
View File
@@ -0,0 +1,71 @@
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
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.Media.Imaging;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace FoxTube.Controls
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class PlaylistCard : Page
{
Playlist item;
string playlistId;
public PlaylistCard(string id)
{
this.InitializeComponent();
Initialize(id);
}
public async void Initialize(string id)
{
PlaylistsResource.ListRequest request = SecretsVault.NoAuthService.Playlists.List("snippet,contentDetails");
request.Id = id;
PlaylistListResponse response = await request.ExecuteAsync();
item = response.Items[0];
playlistId = id;
title.Text = item.Snippet.Title;
channelName.Text = item.Snippet.ChannelTitle;
counter.Text = item.ContentDetails.ItemCount.ToString();
date.Text = item.Snippet.PublishedAt.ToString();
ChannelsResource.ListRequest r = SecretsVault.NoAuthService.Channels.List("snippet");
r.Id = item.Snippet.ChannelId;
try
{
thumbnail.Source = new BitmapImage(new Uri(item.Snippet.Thumbnails.Standard.Url));
avatar.ProfilePicture = new BitmapImage(new Uri((await r.ExecuteAsync()).Items[0].Snippet.Thumbnails.Standard.Url));
} catch { }
}
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
Height = e.NewSize.Width * 0.75;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//Goto playlist
}
}
}
+1 -1
View File
@@ -12,7 +12,7 @@
<Button Padding="0" Background="WhiteSmoke" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Margin="2">
<StackPanel Orientation="Horizontal">
<Grid>
<Image Name="thumbnail" Source="Assets/videoThumbSample.png"/>
<Image Name="thumbnail" Source="/Assets/videoThumbSample.png"/>
<Grid HorizontalAlignment="Right" Width="100">
<Grid.Background>
<AcrylicBrush TintColor="#7F000000" BackgroundSource="Backdrop" AlwaysUseFallback="False" TintOpacity="1" Opacity="0.97"/>
-2
View File
@@ -17,7 +17,6 @@
<RowDefinition Height="*"/>
<RowDefinition Height="75"/>
</Grid.RowDefinitions>
<Grid Background="Black">
<Image Name="thumbnail" Source="/Assets/videoThumbSample.png" Stretch="Fill"/>
<Grid Background="#7FFFFFFF" Name="watched" Visibility="Collapsed">
<StackPanel Margin="5" Background="WhiteSmoke" VerticalAlignment="Top" HorizontalAlignment="Left" Padding="5,2,5,2" BorderBrush="Gray" BorderThickness="1">
@@ -31,7 +30,6 @@
<TextBlock Text="&#xEC44; " VerticalAlignment="Center" Foreground="White" FontSize="12" FontFamily="Segoe MDL2 Assets" FontWeight="Black"/>
<TextBlock Name="liveContent" Text="LIVE" VerticalAlignment="Center" Foreground="White" FontSize="12" FontWeight="Bold"/>
</StackPanel>
</Grid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
+2 -2
View File
@@ -42,7 +42,7 @@ namespace FoxTube.Controls
channelName.Text = item.Snippet.ChannelTitle;
if (item.Snippet.LiveBroadcastContent == "live")
{
views.Text = $"{item.LiveStreamingDetails.ConcurrentViewers} viewers";
views.Text = $"{item.LiveStreamingDetails.ConcurrentViewers:0,0} viewers";
if (item.LiveStreamingDetails.ScheduledStartTime.HasValue && item.LiveStreamingDetails.ScheduledEndTime.HasValue)
info.Text = $"{item.LiveStreamingDetails.ScheduledEndTime - item.LiveStreamingDetails.ScheduledStartTime} | {Methods.GetAgo(item.LiveStreamingDetails.ActualStartTime.Value)}";
else
@@ -64,7 +64,7 @@ namespace FoxTube.Controls
}
else
{
views.Text = $"{item.Statistics.ViewCount} views";
views.Text = $"{item.Statistics.ViewCount:0,0} views";
info.Text = $"{XmlConvert.ToTimeSpan(item.ContentDetails.Duration)} | {Methods.GetAgo(item.Snippet.PublishedAt.Value)}";
embed = false;
}
+1 -1
View File
@@ -736,7 +736,7 @@ namespace FoxTube
private void signin_Click(object sender, RoutedEventArgs e)
{
Methods.MainPage.Vault.Authorize();
SecretsVault.Authorize();
}
public void Pause()
+7
View File
@@ -108,6 +108,9 @@
<Compile Include="Controls\DownloadItem.xaml.cs">
<DependentUpon>DownloadItem.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\PlaylistCard.xaml.cs">
<DependentUpon>PlaylistCard.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\ShowMore.xaml.cs">
<DependentUpon>ShowMore.xaml</DependentUpon>
</Compile>
@@ -276,6 +279,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\PlaylistCard.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\ShowMore.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
+3 -1
View File
@@ -19,6 +19,8 @@ using Google.Apis.YouTube.v3.Data;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Text;
using Windows.Storage;
using FoxTube.Controls;
using FoxTube.Pages;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
@@ -81,7 +83,7 @@ namespace FoxTube
foreach(SearchResult vid in response2.Items)
{
VideoCard vCard = new VideoCard(vid.Id.VideoId);
videoGrid.AddCards(vCard);
videoGrid.Add(vCard);
}
}
+3 -3
View File
@@ -40,11 +40,11 @@ namespace FoxTube.Pages
stack.Children.Add(item);
}
private void UpdateList(object sender, ObjectEventArgs e)
private void UpdateList(object sender, params object[] e)
{
if (e.Parameters[0] == "remove")
if (e[0] == "remove")
stack.Children.Remove(sender as DownloadItem);
else if (e.Parameters[0] == "add")
else if (e[0] == "add")
stack.Children.Add(sender as DownloadItem);
}
+3 -11
View File
@@ -5,6 +5,8 @@
xmlns:local="using:FoxTube"
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:FoxTube.Controls"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Name="grid">
@@ -24,19 +26,9 @@
<TextBlock Text="Subscriptions"/>
</HyperlinkButton>
</StackPanel>
<ScrollViewer Grid.Row="1">
<Pivot Name="pivot" SelectionChanged="pivot_SelectionChanged">
<PivotItem Margin="0,-48,0,0">
</PivotItem>
<PivotItem Margin="0,-48,0,0">
<Pivot Grid.Row="1" Name="pivot" SelectionChanged="pivot_SelectionChanged"/>
</PivotItem>
<PivotItem Margin="0,-48,0,0">
</PivotItem>
</Pivot>
</ScrollViewer>
<CommandBar Grid.Row="2">
<AppBarButton Icon="Refresh" Label="Refresh page" Name="refresh" Click="refresh_Click"/>
</CommandBar>
+148 -40
View File
@@ -18,6 +18,8 @@ using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
using Windows.Storage;
using Windows.UI.Text;
using FoxTube.Controls;
using FoxTube.Pages;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
@@ -31,79 +33,134 @@ namespace FoxTube
private bool recLoaded = false;
private bool trendLoaded = false;
private bool subsLoaded = false;
VideoGrid recGrid = new VideoGrid(), trendGrid = new VideoGrid(), subsGrid = new VideoGrid();
ShowMore recMore = new ShowMore(), trendMore = new ShowMore(), subsMore = new ShowMore();
LoadingPage recLoading = new LoadingPage(), trendLoading = new LoadingPage(), subsLoading = new LoadingPage();
string trendToken, recToken, subsToken;
string reg;
public Home()
{
this.InitializeComponent();
Initialize();
}
public async void Initialize()
{
VideoGrid videoGrid = new VideoGrid();
string reg;
try
{
reg = (ApplicationData.Current.LocalSettings.Values["region"] as string).ToUpper().Remove(0, 3);
}
catch(ArgumentOutOfRangeException)
catch (ArgumentOutOfRangeException)
{
reg = (ApplicationData.Current.LocalSettings.Values["region"] as string).ToUpper();
}
pivot.Items.Clear();
recMore.Clicked += RecMore_Clicked;
trendMore.Clicked += TrendMore_Clicked;
subsMore.Clicked += SubsMore_Clicked;
Initialize();
}
private void RecMore_Clicked()
{
throw new NotImplementedException();
}
private async void TrendMore_Clicked()
{
VideosResource.ListRequest request = SecretsVault.Service.Videos.List("id");
request.MaxResults = 48;
request.PageToken = trendToken;
request.Chart = VideosResource.ListRequest.ChartEnum.MostPopular;
request.RegionCode = reg;
VideoListResponse response = await request.ExecuteAsync();
if (!string.IsNullOrWhiteSpace(response.NextPageToken))
trendToken = response.NextPageToken;
else
trendMore.Complete(true);
foreach (Google.Apis.YouTube.v3.Data.Video vid in response.Items)
{
VideoCard vCard = new VideoCard(vid.Id);
recGrid.Add(vCard);
}
trendMore.Complete();
}
private void SubsMore_Clicked()
{
throw new NotImplementedException();
}
public void Initialize()
{
pivot.Items.Clear();
if(SecretsVault.IsAuthorized)
{
navigation.Visibility = Visibility.Visible;
for(int k = 0; k < 3; k++)
{
StackPanel stack = new StackPanel();
stack.Children.Add(new VideoGrid());
stack.Children.Add(new LoadingPage());
//Initializing recommended tab
StackPanel rs = new StackPanel();
rs.Children.Add(recGrid);
rs.Children.Add(recMore);
Grid rg = new Grid();
rg.Children.Add(new ScrollViewer() { Content = rs });
rg.Children.Add(recLoading);
pivot.Items.Add(new PivotItem()
{
Margin = new Thickness(0, -48, 0, 0),
Content = stack
Content = rg
});
}
//Initializing recommended videos loading
recLoaded = true;
(((pivot.Items[0] as PivotItem).Content as StackPanel).Children[1] as LoadingPage).Block();
}
else
//Initializing trending tab
StackPanel ts = new StackPanel();
ts.Children.Add(trendGrid);
ts.Children.Add(trendMore);
Grid tg = new Grid();
tg.Children.Add(new ScrollViewer() { Content = ts });
tg.Children.Add(trendLoading);
pivot.Items.Add(new PivotItem()
{
Margin = new Thickness(0, -48, 0, 0),
Content = tg
});
//Initializing subscriptions tab
StackPanel s = new StackPanel();
s.Children.Add(subsGrid);
s.Children.Add(subsMore);
Grid g = new Grid();
StackPanel stack = new StackPanel();
stack.Children.Add(new VideoGrid());
stack.Children.Add(new HyperlinkButton()
{
g.Children.Add(new ScrollViewer() { Content = s });
g.Children.Add(subsLoading);
});
g.Children.Add(stack);
g.Children.Add(new LoadingPage());
pivot.Items.Add(new PivotItem()
{
Margin = new Thickness(0, -48, 0, 0),
Content = g
});
//Initializing recommended videos loading
request.Chart = VideosResource.ListRequest.ChartEnum.MostPopular;
request.RegionCode = reg;
VideoListResponse response = await request.ExecuteAsync();
foreach (Google.Apis.YouTube.v3.Data.Video vid in response.Items)
{
VideoCard vCard = new VideoCard(vid.Id);
videoGrid.AddCards(vCard);
LoadRecommendations();
}
trendLoaded = true;
else
{
StackPanel ts = new StackPanel();
ts.Children.Add(trendGrid);
ts.Children.Add(trendMore);
Grid tg = new Grid();
tg.Children.Add(new ScrollViewer() { Content = ts });
tg.Children.Add(trendLoading);
pivot.Items.Add(new PivotItem()
{
Margin = new Thickness(0, -48, 0, 0),
Content = tg
});
LoadTrending();
}
}
@@ -140,16 +197,67 @@ namespace FoxTube
{
case 2:
tosubs.FontWeight = FontWeights.Bold;
if (!subsLoaded)
LoadSubscriptions();
break;
case 1:
toTrending.FontWeight = FontWeights.Bold;
if (!trendLoaded)
LoadTrending();
break;
case 0:
if (pivot.Items.Count > 1)
{
toRecommended.FontWeight = FontWeights.Bold;
else toTrending.FontWeight = FontWeights.Bold;
if (!recLoaded)
LoadRecommendations();
}
else
{
toTrending.FontWeight = FontWeights.Bold;
if (!trendLoaded)
LoadTrending();
}
break;
}
}
async void LoadTrending()
{
VideosResource.ListRequest request = SecretsVault.Service.Videos.List("id");
request.MaxResults = 48;
request.Chart = VideosResource.ListRequest.ChartEnum.MostPopular;
request.RegionCode = reg;
VideoListResponse response = await request.ExecuteAsync();
if (!string.IsNullOrWhiteSpace(response.NextPageToken))
trendToken = response.NextPageToken;
else
trendMore.Complete(true);
foreach (Google.Apis.YouTube.v3.Data.Video vid in response.Items)
{
VideoCard vCard = new VideoCard(vid.Id);
trendGrid.Add(vCard);
}
trendLoading.Close();
trendLoaded = true;
}
void LoadRecommendations()
{
recLoading.Close();
recLoaded = true;
recLoading.Block();
}
void LoadSubscriptions()
{
subsLoading.Close();
subsLoaded = true;
subsLoading.Block();
}
}
}
+5 -2
View File
@@ -48,8 +48,11 @@
</Button.Flyout>
</Button>
<Button Width="50" Background="Transparent" Height="50" Visibility="Collapsed" Name="avatar" ToolTipService.ToolTip="My account">
<Button Width="50" Background="Transparent" Height="50" Visibility="Visible" Name="avatar" ToolTipService.ToolTip="My account">
<Grid>
<Ellipse Height="30" Fill="White"/>
<PersonPicture Width="30"/>
</Grid>
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem Text="My channel" Name="myChannel" Click="myChannel_Click"/>
@@ -95,7 +98,7 @@
</Grid>-->
<Grid>
<TextBox KeyUp="searchField_KeyUp" Name="searchField" ToolTipService.ToolTip="Search" Margin="4" Width="350" Height="42" Padding="10,10,45,0" PlaceholderText="Search" BorderThickness="0" Background="#7FFFFFFF" Text="DAGames" TextChanged="searchField_TextChanged" GotFocus="searchField_GotFocus"/>
<TextBox KeyUp="searchField_KeyUp" Name="searchField" ToolTipService.ToolTip="Search" Margin="4" Width="350" Height="42" Padding="10,10,45,0" PlaceholderText="Search" BorderThickness="0" Background="#7FFFFFFF" Text="kuplinov play" TextChanged="searchField_TextChanged" GotFocus="searchField_GotFocus"/>
<Button Name="searchButton" HorizontalAlignment="Right" Click="searchButton_Click"
Width="42" Height="42" Margin="4"
Background="Transparent"
+41 -12
View File
@@ -51,7 +51,6 @@ namespace FoxTube
public sealed partial class MainPage : Page
{
public SecretsVault Vault = new SecretsVault();
public DownloadAgent Agent = new DownloadAgent();
RightPaneState paneState = RightPaneState.Full;
@@ -92,22 +91,49 @@ namespace FoxTube
if (settings.Values["defaultDownload"] == null)
settings.Values.Add("defaultDownload", Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\DownloadedVideos");
content.Navigate(typeof(Home));
notificationPane.Child = notificationsCenter;
Vault.AuthorizationStateChanged += Vault_AuthorizationStateChanged;
Vault.CheckAuthorization();
SecretsVault.AuthorizationStateChanged += Vault_AuthorizationStateChanged;
SecretsVault.SubscriptionsChanged += SecretsVault_SubscriptionsChanged;
SecretsVault.CheckAuthorization();
if(!SecretsVault.IsAuthorized)
content.Navigate(typeof(Home));
}
private void Vault_AuthorizationStateChanged(object sender, EventArgs e)
private void SecretsVault_SubscriptionsChanged(object sender, params object[] args)
{
if(Vault.IsLoged)
if ((string)args[0] == "add" && subscriptionsList.Items.Count < 10)
{
Subscription s = args[1] as Subscription;
StackPanel panel = new StackPanel() { Orientation = Orientation.Horizontal };
panel.Children.Add(new PersonPicture()
{
Height = 25,
Margin = new Thickness(0, 0, 17, 0),
ProfilePicture = new BitmapImage(new Uri(s.Snippet.Thumbnails.Medium.Url))
});
panel.Children.Add(new TextBlock()
{
VerticalAlignment = VerticalAlignment.Center,
Text = s.Snippet.Title
});
subscriptionsList.Items.Add(new ListBoxItem() { Content = panel });
}
else if ((string)args[0] == "remove" && (int)args[1] < 10)
subscriptionsList.Items.RemoveAt((int)args[1]);
}
private async void Vault_AuthorizationStateChanged(object sender, EventArgs e)
{
if(SecretsVault.IsAuthorized)
{
account.Visibility = Visibility.Collapsed;
try
{
ToolTipService.SetToolTip(avatar, new ToolTip() { Content = SecretsVault.UserChannel.Snippet.Title });
(avatar.Content as PersonPicture).ProfilePicture = new BitmapImage(new Uri(SecretsVault.UserChannel.Snippet.Thumbnails.Standard.Url));
Userinfoplus info = await new Oauth2Service(SecretsVault.Initializer).Userinfo.Get().ExecuteAsync();
ToolTipService.SetToolTip(avatar, new ToolTip() { Content = info.Name });
((avatar.Content as Grid).Children[1] as PersonPicture).ProfilePicture = new BitmapImage(new Uri(info.Picture));
}
catch { }
avatar.Visibility = Visibility.Visible;
@@ -390,7 +416,7 @@ namespace FoxTube
private void signIn_Click(object sender, RoutedEventArgs e)
{
Vault.Authorize();
SecretsVault.Authorize();
}
private void myChannel_Click(object sender, RoutedEventArgs e)
@@ -400,7 +426,7 @@ namespace FoxTube
private void logout_Click(object sender, RoutedEventArgs e)
{
Vault.Deauthenticate();
SecretsVault.Deauthenticate();
}
private void searchField_TextChanged(object sender, TextChangedEventArgs e)
@@ -425,11 +451,14 @@ namespace FoxTube
private void searchButton_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(searchField.Text) || !(content.Content is Search))
if(!string.IsNullOrWhiteSpace(searchField.Text))
{
if (!(content.Content is Search))
content.Navigate(typeof(Search), searchField.Text);
else if (content.Content is Search)
else if ((content.Content as Search).Term != searchField.Text)
(content.Content as Search).Initialize(searchField.Text);
}
}
public void GoToSearch(string keyword)
{
+9 -8
View File
@@ -3,6 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FoxTube"
xmlns:pages="using:FoxTube.Pages"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:FoxTube.Controls"
@@ -20,7 +21,7 @@
<HyperlinkButton Name="toggleFilters" Click="toggleFilters_Click" Content="Show filters &#xE71C;" FontFamily="Default, Segoe MDL2 Assets" Visibility="Visible"/>
<StackPanel Name="filters" Visibility="Collapsed">
<GridView Padding="5" Visibility="Visible">
<GridView Padding="5" SelectionMode="None">
<ComboBox Name="order" Header="Sort by" Width="150" SelectedIndex="0">
<ComboBoxItem Content="Relevance"/>
<ComboBoxItem Content="Upload date"/>
@@ -28,7 +29,7 @@
<ComboBoxItem Content="Rating"/>
<ComboBoxItem Content="Title"/>
</ComboBox>
<ComboBox Name="type" Header="Type" Width="150" SelectedIndex="0">
<ComboBox Name="type" Header="Type" Width="150" SelectedIndex="0" SelectionChanged="type_SelectionChanged">
<ComboBoxItem Content="All"/>
<ComboBoxItem Content="Video"/>
<ComboBoxItem Content="Channel"/>
@@ -42,7 +43,7 @@
<ComboBoxItem Content="This month"/>
<ComboBoxItem Content="This year"/>
</ComboBox>
<ComboBox Name="duration" Header="Duration" Width="150" SelectedIndex="0">
<ComboBox Visibility="Collapsed" Name="duration" Header="Duration" Width="150" SelectedIndex="0">
<ComboBoxItem Content="Any"/>
<ComboBoxItem Content="Short (&#x3C; 4 minutes)"/>
<ComboBoxItem Content="Medium"/>
@@ -50,7 +51,7 @@
</ComboBox>
</GridView>
<StackPanel Orientation="Horizontal">
<Button Content="Features" Margin="10,0,0,10">
<Button Visibility="Collapsed" Content="Features" Name="featBtn" Margin="10,0,0,10">
<Button.Flyout>
<Flyout>
<ListView Name="features" SelectionMode="Multiple" Header="Features">
@@ -63,11 +64,11 @@
</Flyout>
</Button.Flyout>
</Button>
<Button Content="Apply" Margin="10,0,0,10"/>
<Button Content="Apply" Margin="10,0,0,10" Click="AppBarButton_Click"/>
</StackPanel>
</StackPanel>
<local:VideoGrid Name="list"/>
<controls:ShowMore Name="more" Clicked="more_Clicked" Visibility="Collapsed"/>
<pages:VideoGrid/>
<controls:ShowMore Clicked="more_Clicked"/>
</StackPanel>
</ScrollViewer>
@@ -75,6 +76,6 @@
<AppBarButton Label="Refresh" Icon="Refresh" Click="AppBarButton_Click"/>
</CommandBar>
<local:LoadingPage Name="loading" Grid.RowSpan="2" Visibility="Collapsed" RefreshPage="AppBarButton_Click"/>
<local:LoadingPage Grid.RowSpan="2" Visibility="Collapsed" RefreshPage="AppBarButton_Click"/>
</Grid>
</Page>
+42 -15
View File
@@ -1,4 +1,6 @@
using Google.Apis.YouTube.v3;
using FoxTube.Controls;
using FoxTube.Pages;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
using System;
using System.Collections.Generic;
@@ -30,9 +32,17 @@ namespace FoxTube
SearchResource.ListRequest request;
string nextToken;
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
VideoGrid list;
LoadingPage loading;
ShowMore more;
public Search()
{
this.InitializeComponent();
loading = grid.Children[2] as LoadingPage;
list = ((grid.Children[0] as ScrollViewer).Content as StackPanel).Children[4] as VideoGrid;
more = ((grid.Children[0] as ScrollViewer).Content as StackPanel).Children[5] as ShowMore;
}
public string SetResults(int? count)
@@ -50,17 +60,17 @@ namespace FoxTube
switch (result.Id.Kind)
{
case "youtube#video":
VideoCardWide vCard = new VideoCardWide(result.Id.VideoId);
VideoCard vCard = new VideoCard(result.Id.VideoId);
list.Add(vCard);
break;
case "youtube#channel":
ChannelCard cCard = new ChannelCard(result.Id.ChannelId, result.Snippet.LiveBroadcastContent);
ChannelCard cCard = new ChannelCard(result.Id.ChannelId/*, result.Snippet.LiveBroadcastContent*/);
list.Add(cCard);
break;
case "youtube#playlist":
PlaylistCardWide pCard = new PlaylistCardWide(result.Id.PlaylistId);
PlaylistCard pCard = new PlaylistCard(result.Id.PlaylistId);
list.Add(pCard);
break;
}
@@ -99,12 +109,9 @@ namespace FoxTube
request.Order = Order;
request.Type = Type;
request.PublishedAfter = Date;
if (Duration != SearchResource.ListRequest.VideoDurationEnum.Any)
if(type.SelectedIndex == 1)
{
request.Type = "video";
type.SelectedIndex = 1;
request.VideoDuration = Duration;
}
request.VideoDuration = Duration;
if (features.SelectedItems.Count > 0)
{
@@ -121,15 +128,17 @@ namespace FoxTube
if (features.SelectedItems.Contains(features.Items[4]))
request.VideoLicense = SearchResource.ListRequest.VideoLicenseEnum.CreativeCommon;
}
}
SearchListResponse response = await request.ExecuteAsync();
searchTerm.Text = $"Search results for: {Term}";
resultsCount.Text = $"Found: {SetResults(response.PageInfo.TotalResults)} item(s)";
if (response.NextPageToken != null)
{
if (!string.IsNullOrWhiteSpace(response.NextPageToken))
nextToken = response.NextPageToken;
more.Visibility = Visibility.Visible;
}
else
more.Complete(true);
list.Clear();
foreach (SearchResult item in response.Items)
AddItem(item);
@@ -146,12 +155,12 @@ namespace FoxTube
if(filters.Visibility == Visibility.Collapsed)
{
filters.Visibility = Visibility.Visible;
toggleFilters.Content = "Hide filters &#xE71C;";
toggleFilters.Content = "Hide filters ";
}
else
{
filters.Visibility = Visibility.Collapsed;
toggleFilters.Content = "Show filters &#xE71C;";
toggleFilters.Content = "Show filters ";
}
}
@@ -253,5 +262,23 @@ namespace FoxTube
else
more.Complete(true);
}
private void type_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
if (type.SelectedIndex == 1)
{
duration.Visibility = Visibility.Visible;
featBtn.Visibility = Visibility.Visible;
}
else
{
duration.Visibility = Visibility.Collapsed;
featBtn.Visibility = Visibility.Collapsed;
}
}
catch (NullReferenceException) { }
}
}
}
+2 -1
View File
@@ -31,6 +31,7 @@ using Windows.UI;
using FoxTube.Pages;
using MyToolkit.Multimedia;
using FoxTube.Controls;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
@@ -349,7 +350,7 @@ namespace FoxTube
Initialize(videoId);
}
private void LoadingScreen_RefreshPage(object sender, EventArgs e)
private void LoadingScreen_RefreshPage(object sender, RoutedEventArgs e)
{
refresh_Click(this, null);
}
+1 -1
View File
@@ -1,5 +1,5 @@
<Page
x:Class="FoxTube.VideoGrid"
x:Class="FoxTube.Pages.VideoGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FoxTube"
+7 -1
View File
@@ -19,7 +19,7 @@ using Microsoft.Toolkit.Uwp.UI.Controls;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace FoxTube
namespace FoxTube.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
@@ -36,5 +36,11 @@ namespace FoxTube
list.Items.Add(card);
empty.Visibility = Visibility.Collapsed;
}
public void Clear()
{
list.Items.Clear();
empty.Visibility = Visibility.Visible;
}
}
}