Archived
1
0

Merged PR 17: Version 0.2.181021

- Closed captions fixes
- Merged to YoutubeExplode instead of MyToolkit for video sources
- Video playback fixes
- Internal links support
- Subscription button fixed
- Comments threads fixes and improvements (highlighting author's and user's names)
- General bug fixes
This commit is contained in:
Michael Gordeev
2018-10-20 22:03:04 +00:00
parent cc117a161c
commit f637c18e22
32 changed files with 863 additions and 591 deletions
+7
View File
@@ -22,5 +22,12 @@ namespace FoxTube.Classes
Duration = TimeSpan.FromMilliseconds(duration); Duration = TimeSpan.FromMilliseconds(duration);
Text = text; Text = text;
} }
public Caption(double startTime, double duration, string text)
{
Start = TimeSpan.FromSeconds(startTime);
Duration = TimeSpan.FromSeconds(duration);
Text = text;
}
} }
} }
+49 -45
View File
@@ -1,68 +1,72 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.IO; using System.IO;
using MyToolkit.Multimedia;
using Windows.Storage; using Windows.Storage;
using FoxTube.Classes;
using Newtonsoft.Json;
using Windows.UI.Popups;
namespace FoxTube.Controls namespace FoxTube.Controls
{ {
public class DownloadAgent public class DownloadAgent
{ {
public List<DownloadItem> Items = new List<DownloadItem>(); public List<DownloadItem> items = new List<DownloadItem>();
public event ObjectEventHandler ListChanged; StorageFolder roaming = ApplicationData.Current.RoamingFolder;
private ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
XmlDocument doc = new XmlDocument();
public DownloadAgent() public DownloadAgent()
{ {
if (settings.Values["downloadHistory"] != null) Initialize();
doc.LoadXml(settings.Values["downloadHistory"] as string); Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += (s, a) => QuitPrompt();
else }
public async void Initialize()
{
try
{ {
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null)); List<DownloadItemContainer> containers = JsonConvert.DeserializeObject<List<DownloadItemContainer>>(await FileIO.ReadTextAsync(await roaming.GetFileAsync("data.json")));
doc.AppendChild(doc.CreateElement("downloads"));
settings.Values.Add("downloadHistory", doc.InnerXml); foreach (DownloadItemContainer i in containers)
try { items.Add(new DownloadItem(i)); }
catch (FileNotFoundException) { }
} }
catch { }
foreach(XmlElement e in doc["downloads"].ChildNodes)
try
{
Items.Add(new DownloadItem(
e["details"]["id"].InnerText,
e["title"].InnerText,
e["snippet"]["author"].InnerText,
e["snippet"]["image"].InnerText,
e["snippet"]["duration"].InnerText,
e["snippet"]["quality"].InnerText,
e["details"]["path"].InnerText));
}
catch { }
} }
public void Add(string id, YouTubeQuality quality) public void Add(string url)
{ {
DownloadItem item = new DownloadItem(id, quality); items.Add(new DownloadItem(url));
item.DownloadCanceled += Item_DownloadCanceled;
item.DownloadComplete += Item_DownloadComplete;
Items.Add(item);
ListChanged.Invoke(item, "add");
}
private void Item_DownloadComplete(object sender, params object[] e)
{
doc["downloads"].InnerXml += e[0];
settings.Values["downloadHistory"] = doc.InnerXml;
} }
private void Item_DownloadCanceled(object sender, params object[] e) private void Item_DownloadCanceled(object sender, params object[] e)
{ {
Items.Remove(sender as DownloadItem); items.Remove(sender as DownloadItem);
ListChanged.Invoke(sender, "remove"); }
public async void QuitPrompt()
{
if(items.Find(x => x.InProgress) != null)
{
MessageDialog dialog = new MessageDialog("You have some unfinished downloads. Quitting now will erase all downloaded data. Are you sure to continue?", "Some downloads are still pending");
dialog.Commands.Add(new UICommand("Yes", async (command) =>
{
foreach (DownloadItem i in items.FindAll(x => x.InProgress))
i.Cancel();
items.RemoveAll(x => x.InProgress);
List<DownloadItemContainer> containers = new List<DownloadItemContainer>();
foreach (DownloadItem i in items)
containers.Add(i.Container);
await FileIO.WriteTextAsync(
await roaming.CreateFileAsync("data.json", CreationCollisionOption.ReplaceExisting),
JsonConvert.SerializeObject(containers));
}));
dialog.Commands.Add(new UICommand("No"));
dialog.DefaultCommandIndex = 1;
await dialog.ShowAsync();
}
} }
} }
} }
+16
View File
@@ -0,0 +1,16 @@
using System;
using YoutubeExplode.Models.MediaStreams;
namespace FoxTube.Classes
{
public class DownloadItemContainer
{
public string Title { get; set; }
public string Channel { get; set; }
public string Id { get; set; }
public Uri Path { get; set; }
public Uri Thumbnail { get; set; }
public VideoQuality Quality { get; set; }
public TimeSpan Duration { get; set; }
}
}
+76 -4
View File
@@ -1,9 +1,10 @@
using MyToolkit.Multimedia; using Google.Apis.YouTube.v3;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Web;
using Windows.ApplicationModel.Core; using Windows.ApplicationModel.Core;
using Windows.System;
using Windows.UI; using Windows.UI;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
@@ -14,6 +15,7 @@ namespace FoxTube
{ {
public static class Methods public static class Methods
{ {
public static bool NeedToResponse { get; set; } = false;
public static MainPage MainPage public static MainPage MainPage
{ {
get { return (Window.Current.Content as Frame).Content as MainPage; } get { return (Window.Current.Content as Frame).Content as MainPage; }
@@ -24,6 +26,11 @@ namespace FoxTube
CoreApplication.Exit(); CoreApplication.Exit();
} }
public static Uri ToUri(this string url)
{
return new Uri(url);
}
public static string GetAgo(DateTime dateTime) public static string GetAgo(DateTime dateTime)
{ {
TimeSpan span = DateTime.Now - dateTime; TimeSpan span = DateTime.Now - dateTime;
@@ -69,7 +76,8 @@ namespace FoxTube
{ {
try try
{ {
Hyperlink link = new Hyperlink { NavigateUri = new Uri(item), Foreground = new SolidColorBrush(Colors.Red) }; Hyperlink link = new Hyperlink();
link.Click += (s, arg) => { ProcessLink(item); };
link.Inlines.Add(new Run { Text = item }); link.Inlines.Add(new Run { Text = item });
block.Inlines.Add(link); block.Inlines.Add(link);
} }
@@ -98,7 +106,7 @@ namespace FoxTube
} }
} }
public static string QualityToString(YouTubeQuality quality) /*public static string QualityToString(YouTubeQuality quality)
{ {
switch(quality) switch(quality)
{ {
@@ -131,6 +139,70 @@ namespace FoxTube
default: default:
return "Unknown"; return "Unknown";
} }
}*/
public async static void ProcessLink(string url)
{
try
{
Debug.WriteLine($"Processing link: {url}");
if (url.Contains("youtube.com/") || url.Contains("youtu.be/"))
{
Debug.WriteLine("This is an internal youtube link");
url = url.Replace("https://", "").Replace("http://", "").Replace("wwww.", "").Replace("//", "");
Debug.WriteLine($"Prepared link: {url}");
if (url.Contains("/playlist"))
{
Debug.WriteLine($"This is a playlist link. ID: {HttpUtility.ParseQueryString(url).Get("list")}");
MainPage.GoToPlaylist(HttpUtility.ParseQueryString(url).Get("list"));
}
else if (url.Contains("youtu.be/"))
{
Debug.WriteLine($"This is obfuscated video link. Video ID: {url.Split('/')[1]}");
MainPage.GoToVideo(url.Split('/')[1]);
}
else if (url.Contains("/watch"))
{
Debug.WriteLine($"This is regular video link. Video ID: {HttpUtility.ParseQueryString(url).Get("v")}");
MainPage.GoToVideo(HttpUtility.ParseQueryString(url).Get(0), HttpUtility.ParseQueryString(url).Get("list"));
}
else if (url.Contains("/v/"))
{
Debug.WriteLine($"This is video link. ID: {url.Split('/')[2].Split('?')[0]}");
MainPage.GoToVideo(url.Split('/')[2].Split('?')[0]);
}
else if (url.Contains("/channel/"))
{
Debug.WriteLine($"This is channel link. ID: {url.Split('/')[2]}");
MainPage.GoToChannel(url.Split('/')[2]);
}
else if (url.Contains("/user/"))
{
Debug.WriteLine($"This is channel link with username. Username: {url.Split('/')[2]}");
ChannelsResource.ListRequest request = SecretsVault.Service.Channels.List("id");
Debug.WriteLine(request.ForUsername = url.Split('/')[2]);
request.MaxResults = 1;
MainPage.GoToChannel((await request.ExecuteAsync()).Items[0].Id);
}
else if (url.Contains("/c/"))
{
Debug.WriteLine($"This is channel link with custom url. Custom name: {url.Split('/')[2]}");
SearchResource.ListRequest request = SecretsVault.Service.Search.List("id");
Debug.WriteLine(request.Q = url.Split('/')[2]);
request.MaxResults = 1;
MainPage.GoToChannel((await request.ExecuteAsync()).Items[0].Id.ChannelId);
}
else
throw new Exception();
}
else
throw new Exception();
}
catch
{
await Launcher.LaunchUriAsync(new Uri(url));
}
} }
} }
} }
-1
View File
@@ -121,7 +121,6 @@ namespace FoxTube
public string Channel { get; private set; } public string Channel { get; private set; }
public Filters Filter { get; private set; } = new Filters(); public Filters Filter { get; private set; } = new Filters();
public SearchParameters(string term) public SearchParameters(string term)
{ {
Term = term; Term = term;
+41
View File
@@ -57,6 +57,45 @@ namespace FoxTube
} }
} }
public static async Task<bool> ChangeSubscriptionState(string id)
{
if (!IsAuthorized)
return false;
if(Subscriptions.Find(x => x.Snippet.ResourceId.ChannelId == id) != null)
{
Subscription s = Subscriptions.Find(x => x.Snippet.ResourceId.ChannelId == id);
try { await Service.Subscriptions.Delete(s.Id).ExecuteAsync(); }
catch { return true; }
SubscriptionsChanged.Invoke(null, "remove", Subscriptions.IndexOf(s));
Subscriptions.Remove(s);
return false;
}
else
{
var request = Service.Subscriptions.Insert(new Subscription()
{
Snippet = new SubscriptionSnippet()
{
ResourceId = new ResourceId()
{
ChannelId = id,
Kind = "youtube#channel"
}
}
}, "snippet");
Subscription s = await request.ExecuteAsync();
if (s == null)
return false;
Subscriptions.Add(s);
SubscriptionsChanged.Invoke(null, "add", s);
return true;
}
}
public static async Task<bool> Subscribe(string id) public static async Task<bool> Subscribe(string id)
{ {
if (!IsAuthorized) if (!IsAuthorized)
@@ -75,6 +114,8 @@ namespace FoxTube
}, "snippet"); }, "snippet");
Subscription s = await request.ExecuteAsync(); Subscription s = await request.ExecuteAsync();
if (s == null)
return false;
Subscriptions.Add(s); Subscriptions.Add(s);
SubscriptionsChanged.Invoke(null, "add", s); SubscriptionsChanged.Invoke(null, "add", s);
return true; return true;
+7 -13
View File
@@ -91,23 +91,17 @@ namespace FoxTube.Controls
private async void subscribe_Click(object sender, RoutedEventArgs e) private async void subscribe_Click(object sender, RoutedEventArgs e)
{ {
if (subscribe.Background == new SolidColorBrush(Colors.Red)) if (await SecretsVault.ChangeSubscriptionState(channelId))
{ {
if (await SecretsVault.Subscribe(channelId)) subscribe.Background = new SolidColorBrush(Colors.Transparent);
{ subscribe.Foreground = new SolidColorBrush(Colors.Gray);
subscribe.Background = new SolidColorBrush(Colors.Transparent); subscribe.Content = "Subscribed";
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
subscribe.Content = "Subscribed";
}
} }
else else
{ {
if (await SecretsVault.Unsubscibe(channelId)) subscribe.Background = new SolidColorBrush(Colors.Red);
{ subscribe.Foreground = new SolidColorBrush(Colors.White);
subscribe.Background = new SolidColorBrush(Colors.Red); subscribe.Content = "Subscribe";
subscribe.Foreground = new SolidColorBrush(Colors.White);
subscribe.Content = "Subscribe";
}
} }
} }
} }
+13 -10
View File
@@ -23,15 +23,20 @@
<PersonPicture Tapped="avatar_Tapped" Name="avatar" Height="50" Margin="5" VerticalAlignment="Top"/> <PersonPicture Tapped="avatar_Tapped" Name="avatar" Height="50" Margin="5" VerticalAlignment="Top"/>
<Grid Grid.Column="1" Margin="5"> <Grid Grid.Column="1" Margin="5">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition/> <RowDefinition/>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Name="meta" TextWrapping="WrapWholeWords" Foreground="Gray" FontSize="13" Text="[Author's name] | [Published time span] [?](edited)"/> <TextBlock Name="author" TextWrapping="WrapWholeWords" Foreground="Gray" FontSize="13" Text="[Author's name]"/>
<TextBlock Name="text" IsTextSelectionEnabled="True" TextWrapping="WrapWholeWords" Grid.Row="1" Text="[Content]"/> <Border Name="authorBorder" HorizontalAlignment="Left" Background="Red" CornerRadius="5" Visibility="Collapsed">
<TextBlock Name="specialAuthor" TextWrapping="WrapWholeWords" Foreground="White" FontSize="13" Text="[Author's name]" Padding="2,0,2,2"/>
</Border>
<TextBlock Name="meta" Grid.Row="1" TextWrapping="WrapWholeWords" Foreground="Gray" FontSize="13" Text="[Published time span] [?](edited)"/>
<TextBlock Name="text" IsTextSelectionEnabled="True" TextWrapping="WrapWholeWords" Grid.Row="2" Text="[Content]"/>
<StackPanel Grid.Row="1" Name="editor" Visibility="Collapsed"> <StackPanel Grid.Row="2" Name="editor" Visibility="Collapsed">
<TextBox Name="editorText" Text="[Content]" AcceptsReturn="True" Height="Auto" TextChanged="editorText_TextChanged"/> <TextBox Name="editorText" Text="[Content]" AcceptsReturn="True" TextWrapping="Wrap" TextChanged="editorText_TextChanged"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,5,0,5"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,5,0,5">
<Button Name="editorClose" Content="Cancel" Click="editorClose_Click"/> <Button Name="editorClose" Content="Cancel" Click="editorClose_Click"/>
<Button Name="editorSend" Content="Submit" Margin="5,0,0,0" Click="editorSend_Click"/> <Button Name="editorSend" Content="Submit" Margin="5,0,0,0" Click="editorSend_Click"/>
@@ -39,7 +44,7 @@
<ProgressBar Name="editorSending" Foreground="Red" IsIndeterminate="True" Visibility="Collapsed"/> <ProgressBar Name="editorSending" Foreground="Red" IsIndeterminate="True" Visibility="Collapsed"/>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal"> <StackPanel Grid.Row="3" Orientation="Horizontal">
<TextBlock Name="upvote" Foreground="Gray" Padding="0" <TextBlock Name="upvote" Foreground="Gray" Padding="0"
VerticalAlignment="Center" Margin="0,0,5,0" VerticalAlignment="Center" Margin="0,0,5,0"
FontFamily="Segoe MDL2 Assets" Text="&#xE19F;" FontSize="20"/> FontFamily="Segoe MDL2 Assets" Text="&#xE19F;" FontSize="20"/>
@@ -77,10 +82,11 @@
</StackPanel> </StackPanel>
</Button> </Button>
</StackPanel> </StackPanel>
<ProgressBar Grid.Row="3" VerticalAlignment="Bottom" IsIndeterminate="True" Visibility="Collapsed" Name="commentsLoading"/>
</Grid> </Grid>
</Grid> </Grid>
<TextBox Grid.Row="1" Name="reply" TextChanged="reply_TextChanged" BorderThickness="0" Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" AcceptsReturn="True" MaxLength="500" <TextBox Grid.Row="1" Name="reply" TextChanged="reply_TextChanged" TextWrapping="Wrap" BorderThickness="0" Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" AcceptsReturn="True" MaxLength="500"
Padding="5" Margin="0,0,32,0" Padding="5" Margin="0,0,32,0"
PlaceholderText="Enter your reply..."/> PlaceholderText="Enter your reply..."/>
<Button Grid.Row="1" Name="send" Click="send_Click" IsEnabled="False" HorizontalAlignment="Right" VerticalAlignment="Top" <Button Grid.Row="1" Name="send" Click="send_Click" IsEnabled="False" HorizontalAlignment="Right" VerticalAlignment="Top"
@@ -91,9 +97,6 @@
Content="&#xE122;" /> Content="&#xE122;" />
<ProgressBar Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" IsIndeterminate="True" Foreground="Red" Name="sending" Visibility="Collapsed"/> <ProgressBar Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" IsIndeterminate="True" Foreground="Red" Name="sending" Visibility="Collapsed"/>
<StackPanel Grid.Row="2" Name="repliesPlaceholder"> <StackPanel Grid.Row="2" Margin="60,0,0,0" Name="replies"/>
<StackPanel Margin="60,0,0,0" Name="replies"/>
<local:ShowMore Clicked="more_Click"/>
</StackPanel>
</Grid> </Grid>
</UserControl> </UserControl>
+75 -49
View File
@@ -26,21 +26,18 @@ namespace FoxTube.Controls
public enum CommentType { TopLevel, Reply } public enum CommentType { TopLevel, Reply }
public sealed partial class CommentCard : UserControl public sealed partial class CommentCard : UserControl
{ {
ShowMore more;
Comment item; Comment item;
CommentThread thread; CommentThread thread;
bool repliesLoaded = false;
CommentType type = CommentType.TopLevel; CommentType type = CommentType.TopLevel;
string NextPageToken;
public CommentCard(CommentThread comment) public CommentCard(CommentThread comment)
{ {
this.InitializeComponent(); this.InitializeComponent();
more = repliesPlaceholder.Children[1] as ShowMore;
Initialize(comment); Initialize(comment);
} }
public async void Initialize(CommentThread comment) public void Initialize(CommentThread comment)
{ {
item = comment.Snippet.TopLevelComment; item = comment.Snippet.TopLevelComment;
thread = comment; thread = comment;
@@ -60,31 +57,26 @@ namespace FoxTube.Controls
rating.Text = comment.Snippet.TopLevelComment.Snippet.LikeCount.HasValue ? comment.Snippet.TopLevelComment.Snippet.LikeCount.ToString() : ""; rating.Text = comment.Snippet.TopLevelComment.Snippet.LikeCount.HasValue ? comment.Snippet.TopLevelComment.Snippet.LikeCount.ToString() : "";
if (item.Snippet.AuthorChannelId.ToString().Split('"')[3] == SecretsVault.AccountId) if (item.Snippet.AuthorChannelId.ToString().Split('"')[3] == SecretsVault.AccountId)
{
specialAuthor.Text = comment.Snippet.TopLevelComment.Snippet.AuthorDisplayName;
authorBorder.Visibility = Visibility.Visible;
author.Visibility = Visibility.Collapsed;
editBtn.Visibility = Visibility.Visible; editBtn.Visibility = Visibility.Visible;
}
else if (item.Snippet.AuthorChannelId.ToString().Split('"')[3] == Methods.MainPage.GetCurrentItem().Snippet.ChannelId)
{
specialAuthor.Text = comment.Snippet.TopLevelComment.Snippet.AuthorDisplayName;
authorBorder.Visibility = Visibility.Visible;
author.Visibility = Visibility.Collapsed;
}
else
author.Text = comment.Snippet.TopLevelComment.Snippet.AuthorDisplayName;
meta.Text = string.Format("{0} | {1} {2}", comment.Snippet.TopLevelComment.Snippet.AuthorDisplayName, Methods.GetAgo(comment.Snippet.TopLevelComment.Snippet.PublishedAt.Value), comment.Snippet.TopLevelComment.Snippet.UpdatedAt != comment.Snippet.TopLevelComment.Snippet.PublishedAt ? "(edited)" : ""); meta.Text = string.Format("{0} {1}", Methods.GetAgo(comment.Snippet.TopLevelComment.Snippet.PublishedAt.Value), comment.Snippet.TopLevelComment.Snippet.UpdatedAt != comment.Snippet.TopLevelComment.Snippet.PublishedAt ? "(edited)" : "");
Methods.FormatText(ref text, comment.Snippet.TopLevelComment.Snippet.TextDisplay); Methods.FormatText(ref text, comment.Snippet.TopLevelComment.Snippet.TextDisplay);
try { avatar.ProfilePicture = new BitmapImage(new Uri(comment.Snippet.TopLevelComment.Snippet.AuthorProfileImageUrl)); } try { avatar.ProfilePicture = new BitmapImage(new Uri(comment.Snippet.TopLevelComment.Snippet.AuthorProfileImageUrl)); }
catch { } catch { }
if(comment.Snippet.TotalReplyCount > 0)
{
var request = SecretsVault.Service.Comments.List("snippet");
request.ParentId = item.Id;
request.TextFormat = CommentsResource.ListRequest.TextFormatEnum.PlainText;
request.MaxResults = 10;
var response = await request.ExecuteAsync();
if (response.NextPageToken != null)
NextPageToken = response.NextPageToken;
else
more.Visibility = Visibility.Collapsed;
foreach (Comment c in response.Items.Reverse())
replies.Children.Add(new CommentCard(c));
}
} }
public CommentCard(Comment comment) public CommentCard(Comment comment)
@@ -110,7 +102,23 @@ namespace FoxTube.Controls
else else
rating.Text = comment.Snippet.LikeCount.HasValue ? comment.Snippet.LikeCount.ToString() : ""; rating.Text = comment.Snippet.LikeCount.HasValue ? comment.Snippet.LikeCount.ToString() : "";
meta.Text = string.Format("{0} | {1} {2}", comment.Snippet.AuthorDisplayName, Methods.GetAgo(comment.Snippet.PublishedAt.Value), comment.Snippet.UpdatedAt.Value != comment.Snippet.PublishedAt.Value ? "(edited)" : ""); if (item.Snippet.AuthorChannelId.ToString().Split('"')[3] == SecretsVault.AccountId)
{
specialAuthor.Text = comment.Snippet.AuthorDisplayName;
authorBorder.Visibility = Visibility.Visible;
author.Visibility = Visibility.Collapsed;
editBtn.Visibility = Visibility.Visible;
}
else if (item.Snippet.AuthorChannelId.ToString().Split('"')[3] == Methods.MainPage.GetCurrentItem().Snippet.ChannelId)
{
specialAuthor.Text = comment.Snippet.AuthorDisplayName;
authorBorder.Visibility = Visibility.Visible;
author.Visibility = Visibility.Collapsed;
}
else
author.Text = comment.Snippet.AuthorDisplayName;
meta.Text = string.Format("{0} {1}", comment.Snippet.AuthorDisplayName, Methods.GetAgo(comment.Snippet.PublishedAt.Value), comment.Snippet.UpdatedAt.Value != comment.Snippet.PublishedAt.Value ? "(edited)" : "");
Methods.FormatText(ref text, comment.Snippet.TextDisplay); Methods.FormatText(ref text, comment.Snippet.TextDisplay);
try { avatar.ProfilePicture = new BitmapImage(new Uri(comment.Snippet.AuthorProfileImageUrl)); } try { avatar.ProfilePicture = new BitmapImage(new Uri(comment.Snippet.AuthorProfileImageUrl)); }
@@ -125,10 +133,45 @@ namespace FoxTube.Controls
grid.RowDefinitions[1].Height = new GridLength(0); grid.RowDefinitions[1].Height = new GridLength(0);
} }
private void showReplies_Click(object sender, RoutedEventArgs e) private async void showReplies_Click(object sender, RoutedEventArgs e)
{ {
if (grid.RowDefinitions[2].Height == new GridLength(0)) if (grid.RowDefinitions[2].Height == new GridLength(0))
{
if(type == CommentType.TopLevel && !repliesLoaded)
{
commentsLoading.Visibility = Visibility.Visible;
var request = SecretsVault.Service.Comments.List("snippet");
request.ParentId = item.Id;
request.TextFormat = CommentsResource.ListRequest.TextFormatEnum.PlainText;
request.MaxResults = 50;
string token;
IList<Comment> list = new List<Comment>();
var response = await request.ExecuteAsync();
token = response.NextPageToken;
foreach (Comment i in response.Items)
list.Add(i);
while(token != null)
{
request.PageToken = token;
response = await request.ExecuteAsync();
token = response.NextPageToken;
foreach (Comment i in response.Items)
list.Add(i);
}
foreach (Comment c in list.Reverse())
replies.Children.Add(new CommentCard(c));
repliesLoaded = true;
commentsLoading.Visibility = Visibility.Collapsed;
}
grid.RowDefinitions[2].Height = GridLength.Auto; grid.RowDefinitions[2].Height = GridLength.Auto;
}
else else
grid.RowDefinitions[2].Height = new GridLength(0); grid.RowDefinitions[2].Height = new GridLength(0);
} }
@@ -138,27 +181,6 @@ namespace FoxTube.Controls
Methods.MainPage.GoToChannel(item.Snippet.AuthorChannelId.ToString().Split('"')[3]); Methods.MainPage.GoToChannel(item.Snippet.AuthorChannelId.ToString().Split('"')[3]);
} }
private async void more_Click()
{
var request = SecretsVault.NoAuthService.Comments.List("snippet");
request.ParentId = item.Id;
request.MaxResults = 10;
request.PageToken = NextPageToken;
request.TextFormat = CommentsResource.ListRequest.TextFormatEnum.PlainText;
var response = await request.ExecuteAsync();
foreach (Comment c in response.Items.Reverse())
replies.Children.Add(new CommentCard(c));
if (response.NextPageToken != null)
{
NextPageToken = response.NextPageToken;
more.Complete();
}
else
more.Complete(true);
}
private void reply_TextChanged(object sender, TextChangedEventArgs e) private void reply_TextChanged(object sender, TextChangedEventArgs e)
{ {
if (reply.Text.Length == 0) if (reply.Text.Length == 0)
@@ -196,7 +218,7 @@ namespace FoxTube.Controls
private void editorClose_Click(object sender, RoutedEventArgs e) private void editorClose_Click(object sender, RoutedEventArgs e)
{ {
((grid.Children[0] as Grid).Children[1] as Grid).RowDefinitions[2].Height = GridLength.Auto; ((grid.Children[0] as Grid).Children[1] as Grid).RowDefinitions[3].Height = GridLength.Auto;
text.Visibility = Visibility.Visible; text.Visibility = Visibility.Visible;
editor.Visibility = Visibility.Collapsed; editor.Visibility = Visibility.Collapsed;
} }
@@ -214,11 +236,15 @@ namespace FoxTube.Controls
item.Snippet.UpdatedAt = DateTime.Now; item.Snippet.UpdatedAt = DateTime.Now;
if (type == CommentType.Reply) if (type == CommentType.Reply)
{
await SecretsVault.Service.Comments.Update(item, "snippet").ExecuteAsync(); await SecretsVault.Service.Comments.Update(item, "snippet").ExecuteAsync();
Initialize(item);
}
else else
{ {
thread.Snippet.TopLevelComment = item; thread.Snippet.TopLevelComment = item;
await SecretsVault.Service.CommentThreads.Update(thread, "snippet").ExecuteAsync(); await SecretsVault.Service.CommentThreads.Update(thread, "snippet").ExecuteAsync();
Initialize(thread);
} }
editorClose_Click(this, null); editorClose_Click(this, null);
@@ -243,7 +269,7 @@ namespace FoxTube.Controls
private void editBtn_Click(object sender, RoutedEventArgs e) private void editBtn_Click(object sender, RoutedEventArgs e)
{ {
((grid.Children[0] as Grid).Children[1] as Grid).RowDefinitions[2].Height = new GridLength(0); ((grid.Children[0] as Grid).Children[1] as Grid).RowDefinitions[3].Height = new GridLength(0);
text.Visibility = Visibility.Collapsed; text.Visibility = Visibility.Collapsed;
editorText.Text = text.Text; editorText.Text = text.Text;
editor.Visibility = Visibility.Visible; editor.Visibility = Visibility.Visible;
+1 -1
View File
@@ -28,7 +28,7 @@
<TextBlock Text="Author:" Foreground="Gray" Name="channel"/> <TextBlock Text="Author:" Foreground="Gray" Name="channel"/>
</StackPanel> </StackPanel>
<StackPanel Name="donePanel" Grid.Column="3" Orientation="Horizontal" Visibility="Collapsed"> <StackPanel Name="donePanel" Grid.Column="3" Orientation="Horizontal" Visibility="Visible">
<Button Name="open" Click="open_Click" Width="80" Height="80" Padding="0" Background="Transparent"> <Button Name="open" Click="open_Click" Width="80" Height="80" Padding="0" Background="Transparent">
<StackPanel> <StackPanel>
<TextBlock Text="&#xED25;" FontFamily="Segoe MDL2 Assets" FontSize="30" HorizontalAlignment="Center"/> <TextBlock Text="&#xED25;" FontFamily="Segoe MDL2 Assets" FontSize="30" HorizontalAlignment="Center"/>
+37 -84
View File
@@ -1,26 +1,12 @@
using System; using System;
using System.Collections.Generic;
using System.IO; 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;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Net; using System.Net;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
using Windows.System; using Windows.System;
using MyToolkit.Multimedia; using FoxTube.Classes;
using Windows.Storage; using YoutubeExplode.Models.MediaStreams;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
using Windows.UI.Popups;
using System.Xml;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
@@ -28,55 +14,36 @@ namespace FoxTube.Controls
{ {
public sealed partial class DownloadItem : UserControl public sealed partial class DownloadItem : UserControl
{ {
string uri; public DownloadItemContainer Container { get; private set; }
string Id; public bool InProgress { get; set; } = false;
public DownloadItem(string url)
{
this.InitializeComponent();
Download(url);
}
public event ObjectEventHandler DownloadCanceled; public DownloadItem(DownloadItemContainer container)
public event ObjectEventHandler DownloadComplete;
WebClient client = new WebClient();
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
public DownloadItem(string id, YouTubeQuality q)
{ {
this.InitializeComponent(); this.InitializeComponent();
client.DownloadFileCompleted += DownloadCompleted; Container = container;
client.DownloadProgressChanged += UpdateInfo; if (!File.Exists(container.Path.AbsolutePath))
throw new FileNotFoundException();
title.Text = Container.Title;
thumbnail.Source = new BitmapImage(Container.Thumbnail);
quality.Text = $"Quality: {Container.Quality.GetVideoQualityLabel()}";
duration.Text = $"Duration: {Container.Duration}";
channel.Text = $"Author: {Container.Channel}";
progressPanel.Visibility = Visibility.Collapsed;
donePanel.Visibility = Visibility.Visible;
} }
async void Download(string id, YouTubeQuality q) void Download(string url)
{ {
try
{
Id = id;
VideosResource.ListRequest request = SecretsVault.NoAuthService.Videos.List("snippet");
request.Id = id;
var response = (await request.ExecuteAsync()).Items[0];
Uri url = (await YouTube.GetVideoUriAsync(id, q)).Uri;
client.DownloadFileAsync(url, settings.Values["defaultDownload"] as string + $@"\{response.Snippet.Title} - {response.Snippet.ChannelTitle}.mp4");
thumbnail.Source = new BitmapImage(new Uri(response.Snippet.Thumbnails.Standard.Url));
title.Text = response.Snippet.Title;
channel.Text = $"Author: {response.Snippet.ChannelTitle}";
quality.Text = $"Quality: {Methods.QualityToString(q)}"; TimeSpan ts = XmlConvert.ToTimeSpan(response.ContentDetails.Duration);
duration.Text = string.Format("Duration: {0}{1:00}:{2:00} | ", ts.Hours == 0 ? "" : ts.Hours + ":", ts.Minutes, ts.Seconds);
uri = settings.Values["defaultDownload"] as string + $@"\{response.Snippet.Title} - {response.Snippet.ChannelTitle}.mp4";
status.Text = "Downloading...";
perc.Text = "0%";
}
catch
{
if (client.IsBusy)
client.CancelAsync();
await new MessageDialog("We were unable to download video due to connection problems or internal YouTube server error. Please, try again later.", "Failed to download").ShowAsync();
throw new FileNotFoundException();
}
} }
private void UpdateInfo(object sender, DownloadProgressChangedEventArgs e) private void UpdateInfo(object sender, DownloadProgressChangedEventArgs e)
@@ -87,7 +54,7 @@ namespace FoxTube.Controls
private void DownloadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) private void DownloadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{ {
progressPanel.Visibility = Visibility.Collapsed; /*progressPanel.Visibility = Visibility.Collapsed;
donePanel.Visibility = Visibility.Visible; donePanel.Visibility = Visibility.Visible;
string node = $@"<item> string node = $@"<item>
@@ -103,41 +70,27 @@ namespace FoxTube.Controls
</details> </details>
</item>"; </item>";
DownloadComplete.Invoke(this, node); DownloadComplete.Invoke(this, node);*/
}
public DownloadItem(string videoId, string videoName, string channelName, string thumbUrl, string length, string videoQuality, string path)
{
if (!File.Exists(path))
throw new FileNotFoundException();
title.Text = videoName;
thumbnail.Source = new BitmapImage(new Uri(thumbUrl));
quality.Text = $"Quality: {videoQuality}";
duration.Text = $"Duration: {length}";
channel.Text = $"Author: {channelName}";
progressPanel.Visibility = Visibility.Collapsed;
donePanel.Visibility = Visibility.Visible;
uri = path;
Id = videoId;
} }
private async void open_Click(object sender, RoutedEventArgs e) private async void open_Click(object sender, RoutedEventArgs e)
{ {
if (!string.IsNullOrWhiteSpace(uri)) await Launcher.LaunchUriAsync(Container.Path);
await Launcher.LaunchUriAsync(new Uri(uri));
} }
private void gotoOriginal_Click(object sender, RoutedEventArgs e) private void gotoOriginal_Click(object sender, RoutedEventArgs e)
{ {
Methods.MainPage.GoToVideo(Id); Methods.MainPage.GoToVideo(Container.Id);
} }
private async void cancel_Click(object sender, RoutedEventArgs e) public void Cancel()
{ {
if(client.IsBusy)
}
private void cancel_Click(object sender, RoutedEventArgs e)
{
/*if(client.IsBusy)
{ {
MessageDialog dialog = new MessageDialog("Are you sure?", "Cancelling download"); MessageDialog dialog = new MessageDialog("Are you sure?", "Cancelling download");
@@ -153,7 +106,7 @@ namespace FoxTube.Controls
dialog.DefaultCommandIndex = 1; dialog.DefaultCommandIndex = 1;
await dialog.ShowAsync(); await dialog.ShowAsync();
} }*/
} }
} }
} }
+30 -13
View File
@@ -23,6 +23,7 @@ namespace FoxTube.Controls
public sealed partial class LiveCaptions : UserControl public sealed partial class LiveCaptions : UserControl
{ {
public MediaElement Player { get; set; } public MediaElement Player { get; set; }
private bool isClosed = false;
DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(10) }; DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(10) };
List<Caption> captions = new List<Caption>(); List<Caption> captions = new List<Caption>();
Caption currentCaption = null; Caption currentCaption = null;
@@ -38,16 +39,17 @@ namespace FoxTube.Controls
TimeSpan currentPosition = Player.Position; TimeSpan currentPosition = Player.Position;
bool found = false; bool found = false;
captions.ForEach((x) => if(!isClosed)
{ captions.ForEach((x) =>
if (Player.Position >= x.Start && Player.Position <= x.End)
{ {
currentCaption = x; if (Player.Position >= x.Start && Player.Position <= x.End)
text.Text = currentCaption.Text; {
Visibility = Visibility.Visible; currentCaption = x;
found = true; text.Text = currentCaption.Text;
} Visibility = Visibility.Visible;
}); found = true;
}
});
if (!found) if (!found)
{ {
@@ -56,17 +58,22 @@ namespace FoxTube.Controls
} }
} }
public void Initialize(string source) public void Initialize(string source, bool isAutoGenerated = false)
{ {
captions.Clear();
XmlDocument doc = new XmlDocument(); XmlDocument doc = new XmlDocument();
doc.Load(source); doc.Load(source);
foreach (XmlElement i in doc["timedtext"]["body"].ChildNodes) if (!isAutoGenerated)
captions.Add(new Caption(int.Parse(i.GetAttribute("t")), int.Parse(i.GetAttribute("d")), i.InnerText)); foreach (XmlElement i in doc["timedtext"]["body"].ChildNodes)
captions.Add(new Caption(int.Parse(i.GetAttribute("t")), int.Parse(i.GetAttribute("d")), i.InnerText));
else
foreach (XmlElement i in doc["transcript"].ChildNodes)
captions.Add(new Caption(double.Parse(i.GetAttribute("start")), double.Parse(i.GetAttribute("dur")), i.InnerText.Replace("<font color=\"#E5E5E5\">", "").Replace("<font color=\"#CCCCCC\">", "").Replace("</font>", "").Replace("&#39;", "'")));
captions.ForEach((x) => captions.ForEach((x) =>
{ {
if(Player.Position > x.Start && Player.Position < x.End) if (Player.Position > x.Start && Player.Position < x.End)
{ {
currentCaption = x; currentCaption = x;
text.Text = currentCaption.Text; text.Text = currentCaption.Text;
@@ -84,5 +91,15 @@ namespace FoxTube.Controls
Visibility = Visibility.Collapsed; Visibility = Visibility.Collapsed;
timer.Stop(); timer.Stop();
} }
public void Hide()
{
isClosed = true;
}
public void Show()
{
isClosed = false;
}
} }
} }
+8 -14
View File
@@ -13,11 +13,11 @@
RequestedTheme="Dark" RequestedTheme="Dark"
PointerMoved="UserControl_PointerMoved" PointerMoved="UserControl_PointerMoved"
PointerExited="UserControl_PointerExited" PointerExited="UserControl_PointerExited"
PointerEntered="UserControl_PointerEntered" PointerEntered="UserControl_PointerEntered">
KeyUp="UserControl_KeyUp">
<Grid Background="White" Name="grid" Tapped="UserControl_Tapped"> <Grid Background="White" Name="grid" Tapped="UserControl_Tapped">
<MediaElement IsDoubleTapEnabled="False" CurrentStateChanged="videoSource_CurrentStateChanged" AutoPlay="False" Name="videoSource" AreTransportControlsEnabled="False" PosterSource="ms-appx:///Assets/videoThumbSample.png"/> <MediaElement Width="0" Height="0" VerticalAlignment="Top" HorizontalAlignment="Right" Name="audioSource" MediaOpened="videoSource_Opened" BufferingProgressChanged="videoSource_BufferingProgressChanged"/>
<MediaElement IsDoubleTapEnabled="False" CurrentStateChanged="videoSource_CurrentStateChanged" AutoPlay="False" MediaOpened="videoSource_Opened" BufferingProgressChanged="videoSource_BufferingProgressChanged" Volume="0" Name="videoSource" AreTransportControlsEnabled="False" PosterSource="ms-appx:///Assets/videoThumbSample.png"/>
<controls1:LiveCaptions Player="{x:Bind videoSource}" Visibility="Collapsed"/> <controls1:LiveCaptions Player="{x:Bind videoSource}" Visibility="Collapsed"/>
@@ -98,7 +98,10 @@
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<TextBlock Name="elapsedTime" Foreground="White" Text="[Elapsed]" VerticalAlignment="Bottom" HorizontalAlignment="Left" ToolTipService.ToolTip="Time elapsed"/> <TextBlock Name="elapsedTime" Foreground="White" Text="[Elapsed]" VerticalAlignment="Bottom" HorizontalAlignment="Left" ToolTipService.ToolTip="Time elapsed"/>
<TextBlock Name="remainingTime" Foreground="White" Text="[Remaining]" VerticalAlignment="Bottom" HorizontalAlignment="Right" ToolTipService.ToolTip="Time remaining"/> <TextBlock Name="remainingTime" Foreground="White" Text="[Remaining]" VerticalAlignment="Bottom" HorizontalAlignment="Right" ToolTipService.ToolTip="Time remaining"/>
<Slider PointerCaptureLost="seek_PointerCaptureLost" ValueChanged="seek_ValueChanged" Name="seek" VerticalAlignment="Top" ToolTipService.ToolTip="Seek" IsThumbToolTipEnabled="False" HorizontalAlignment="Stretch"/> <Grid VerticalAlignment="Top" Margin="0,18,0,0" Height="2">
<ProgressBar Background="#66FFFFFF" Foreground="LightGray" Name="bufferingLevel"/>
</Grid>
<Slider PointerCaptureLost="seek_PointerCaptureLost" ValueChanged="seek_ValueChanged" Name="seek" VerticalAlignment="Top" ToolTipService.ToolTip="Seek" IsThumbToolTipEnabled="False" Background="Transparent" HorizontalAlignment="Stretch"/>
</Grid> </Grid>
<StackPanel Grid.Column="2" Orientation="Horizontal"> <StackPanel Grid.Column="2" Orientation="Horizontal">
@@ -120,16 +123,7 @@
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE713;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Video quality"> <Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE713;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Video quality">
<Button.Flyout> <Button.Flyout>
<Flyout> <Flyout>
<ComboBox Width="225" Header="Quality" Name="quality" SelectionChanged="quality_SelectionChanged"> <ComboBox Width="225" Header="Quality" Name="quality" SelectionChanged="quality_SelectionChanged"/>
<!--<ComboBoxItem Content="Auto"/>-->
<ComboBoxItem Content="2160P" Visibility="Collapsed"/>
<ComboBoxItem Content="1080p" Visibility="Collapsed"/>
<ComboBoxItem Content="720p" Visibility="Collapsed"/>
<ComboBoxItem Content="480p" Visibility="Collapsed"/>
<ComboBoxItem Content="360p" Visibility="Collapsed"/>
<ComboBoxItem Content="240p" Visibility="Collapsed"/>
<ComboBoxItem Content="144p" Visibility="Collapsed"/>
</ComboBox>
</Flyout> </Flyout>
</Button.Flyout> </Button.Flyout>
</Button> </Button>
+238 -76
View File
@@ -1,26 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Timers; using System.Timers;
using Windows.Foundation; using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage; using Windows.Storage;
using Windows.UI.Core; using Windows.UI.Core;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Microsoft.Toolkit.Uwp.UI.Animations;
using Google.Apis.YouTube.v3.Data; using Google.Apis.YouTube.v3.Data;
using Google.Apis.YouTube.v3;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
using Windows.Networking.Connectivity;
using System.Diagnostics; using System.Diagnostics;
using Windows.Media; using Windows.Media;
using Windows.Storage.Streams; using Windows.Storage.Streams;
@@ -28,13 +19,13 @@ using Windows.UI.ViewManagement;
using System.Xml; using System.Xml;
using Windows.ApplicationModel.Core; using Windows.ApplicationModel.Core;
using Windows.UI; using Windows.UI;
using Windows.Graphics.Display;
using Windows.Media.Casting; using Windows.Media.Casting;
using YoutubeExplode.Models.MediaStreams; using YoutubeExplode.Models.MediaStreams;
using YoutubeExplode; using YoutubeExplode;
using YoutubeExplode.Models.ClosedCaptions; using YoutubeExplode.Models.ClosedCaptions;
using System.Globalization; using System.Globalization;
using FoxTube.Controls; using FoxTube.Controls;
using Windows.System;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
@@ -44,14 +35,31 @@ namespace FoxTube
{ {
public string videoId; public string videoId;
public bool miniView = false; private bool miniview = false;
public bool MiniView
{
get { return miniview; }
set
{
miniview = value;
if (value)
captions.Hide();
else
captions.Show();
}
}
private bool fullScreen = false; private bool fullScreen = false;
public bool pointerCaptured = false; public bool pointerCaptured = false;
public event ObjectEventHandler SetFullSize; public event ObjectEventHandler SetFullSize;
public event ObjectEventHandler NextClicked; public event ObjectEventHandler NextClicked;
bool isMuxed = false;
bool audioReady = false;
bool videoReady = false;
CoreCursor cursorBackup = Window.Current.CoreWindow.PointerCursor; CoreCursor cursorBackup = Window.Current.CoreWindow.PointerCursor;
Point cursorPositionBackup;
public TimeSpan elapsed; public TimeSpan elapsed;
TimeSpan remaining; TimeSpan remaining;
@@ -65,7 +73,6 @@ namespace FoxTube
SystemMediaTransportControls systemControls = SystemMediaTransportControls.GetForCurrentView(); SystemMediaTransportControls systemControls = SystemMediaTransportControls.GetForCurrentView();
LiveCaptions captions; LiveCaptions captions;
YoutubeClient client = new YoutubeClient();
IReadOnlyList<ClosedCaptionTrackInfo> ccInfo; IReadOnlyList<ClosedCaptionTrackInfo> ccInfo;
MediaStreamInfoSet streamInfo; MediaStreamInfoSet streamInfo;
@@ -86,13 +93,20 @@ namespace FoxTube
this.InitializeComponent(); this.InitializeComponent();
Visibility = Visibility.Collapsed; Visibility = Visibility.Collapsed;
if (!ApplicationView.GetForCurrentView().IsViewModeSupported(ApplicationViewMode.CompactOverlay)) if (!ApplicationView.GetForCurrentView().IsViewModeSupported(ApplicationViewMode.CompactOverlay))
miniViewBtn.Visibility = Visibility.Collapsed;; miniViewBtn.Visibility = Visibility.Collapsed;
captions = grid.Children[1] as LiveCaptions; captions = grid.Children[2] as LiveCaptions;
volume.Value = Convert.ToDouble(settings.Values["volume"]); volume.Value = Convert.ToDouble(settings.Values["volume"]);
videoSource.AutoPlay = (bool)settings.Values["videoAutoplay"]; videoSource.AutoPlay = (bool)settings.Values["videoAutoplay"];
videoSource.MediaEnded += (s, arg) =>
{
seek.Value = seek.Maximum;
seekIndicator.Value = seekIndicator.Maximum;
seekTimer.Stop();
};
audioSource.CurrentStateChanged += AudioSource_CurrentStateChanged;
t.Elapsed += T_Elapsed; t.Elapsed += T_Elapsed;
seekTimer.Elapsed += SeekTimer_Elapsed; seekTimer.Elapsed += SeekTimer_Elapsed;
} }
@@ -105,39 +119,36 @@ namespace FoxTube
#region Retrieving info for CC and Media streams #region Retrieving info for CC and Media streams
//Loading streams //Loading streams
streamInfo = await client.GetVideoMediaStreamInfosAsync(item.Id); streamInfo = await new YoutubeClient().GetVideoMediaStreamInfosAsync(videoId);
foreach(MuxedStreamInfo i in streamInfo.Muxed) streamInfo.Audio.ToList().ForEach(x => Debug.WriteLine($"{x.AudioEncoding} {x.Bitrate}"));
{
if (i.VideoQuality == VideoQuality.High2160)
(quality.Items[0] as ComboBoxItem).Visibility = Visibility.Visible;
if (i.VideoQuality == VideoQuality.High1080)
(quality.Items[1] as ComboBoxItem).Visibility = Visibility.Visible;
if (i.VideoQuality == VideoQuality.High720)
(quality.Items[2] as ComboBoxItem).Visibility = Visibility.Visible;
if (i.VideoQuality == VideoQuality.Medium480)
(quality.Items[3] as ComboBoxItem).Visibility = Visibility.Visible;
if (i.VideoQuality == VideoQuality.Medium360)
(quality.Items[4] as ComboBoxItem).Visibility = Visibility.Visible;
if (i.VideoQuality == VideoQuality.Low240)
(quality.Items[5] as ComboBoxItem).Visibility = Visibility.Visible;
if (i.VideoQuality == VideoQuality.Low144)
(quality.Items[6] as ComboBoxItem).Visibility = Visibility.Visible;
}
int k = (int)settings.Values["quality"]; List<VideoQuality> q = streamInfo.GetAllVideoQualities().ToList();
if ((quality.Items[k] as ComboBoxItem).Visibility == Visibility.Visible) q.Sort();
quality.SelectedIndex = k; q.Reverse();
foreach (VideoQuality i in q)
quality.Items.Add(new ComboBoxItem() { Content = i.GetVideoQualityLabel() });
string s;
if ((string)settings.Values["quality"] == "remember")
s = (string)settings.Values["rememberedQuality"];
else else
quality.SelectedItem = quality.Items.First(x => (x as ComboBoxItem).Visibility == Visibility.Visible); s = (string)settings.Values["quality"];
if (quality.Items.ToList().Find(x => (x as ComboBoxItem).Content as string == s) != null)
quality.SelectedItem = quality.Items.First(x => (x as ComboBoxItem).Content as string == s);
else
quality.SelectedItem = quality.Items.First();
//Loading captions //Loading captions
ccInfo = await client.GetVideoClosedCaptionTrackInfosAsync(item.Id); ccInfo = await new YoutubeClient().GetVideoClosedCaptionTrackInfosAsync(item.Id);
foreach (ClosedCaptionTrackInfo cc in ccInfo) foreach (ClosedCaptionTrackInfo cc in ccInfo)
{
subsLang.Items.Add(new ComboBoxItem() subsLang.Items.Add(new ComboBoxItem()
{ {
Content = string.Format("{1}{0}", CultureInfo.GetCultureInfo(cc.Language.Code).DisplayName, cc.IsAutoGenerated ? " (Auto-generated)" : ""), Content = string.Format("{0}{1}", CultureInfo.GetCultureInfo(cc.Language.Code).DisplayName, cc.IsAutoGenerated ? " (Auto-generated)" : ""),
Tag = cc Tag = cc
}); });
}
if(ccInfo.Count > 0) if(ccInfo.Count > 0)
subsLang.SelectedIndex = 0; subsLang.SelectedIndex = 0;
else else
@@ -232,22 +243,30 @@ namespace FoxTube
{ {
seek.Value = videoSource.Position.TotalSeconds; seek.Value = videoSource.Position.TotalSeconds;
seekIndicator.Value = seek.Value; seekIndicator.Value = seek.Value;
/*if (Math.Round(videoSource.Position.TotalSeconds, 1) != Math.Round(audioSource.Position.TotalSeconds, 1))
{
Debug.WriteLine($"Correcting tracks synchronization (Video track position: {videoSource.Position}; Audio track position: {audioSource.Position})");
audioSource.Position = videoSource.Position;
}*/
} }
void Elapsed() void Elapsed()
{ {
controls.Visibility = Visibility.Collapsed; controls.Visibility = Visibility.Collapsed;
if (!miniView) if (!MiniView)
touchCentral.Visibility = Visibility.Collapsed; touchCentral.Visibility = Visibility.Collapsed;
if (pointerCaptured) if (pointerCaptured)
{
cursorPositionBackup = Window.Current.CoreWindow.PointerPosition;
Window.Current.CoreWindow.PointerCursor = null; Window.Current.CoreWindow.PointerCursor = null;
}
seekIndicator.Visibility = Visibility.Collapsed; seekIndicator.Visibility = Visibility.Collapsed;
t.Stop(); t.Stop();
} }
public void UpdateSize() public void UpdateSize()
{ {
if(miniView) if(MiniView)
{ {
Height = Window.Current.Bounds.Height; Height = Window.Current.Bounds.Height;
Debug.WriteLine("Video player aspect ratio has been corrected."); Debug.WriteLine("Video player aspect ratio has been corrected.");
@@ -258,19 +277,19 @@ namespace FoxTube
{ {
double v = volume.Value; double v = volume.Value;
if (v == 0) if (v == 0)
muteBtn.Content = openVolume.Content = ""; muteBtn.Content = openVolume.Content = "\xE74F";
else if (v <= 25 && v > 0) else if (v <= 25 && v > 0)
muteBtn.Content = openVolume.Content = ""; muteBtn.Content = openVolume.Content = "\xE992";
else if (v <= 50 && v > 25) else if (v <= 50 && v > 25)
muteBtn.Content = openVolume.Content = ""; muteBtn.Content = openVolume.Content = "\xE993";
else if (v <= 75 && v > 50) else if (v <= 75 && v > 50)
muteBtn.Content = openVolume.Content = ""; muteBtn.Content = openVolume.Content = "\xE994";
else if (v > 75) else if (v > 75)
muteBtn.Content = openVolume.Content = ""; muteBtn.Content = openVolume.Content = "\xE995";
settings.Values["volume"] = volume.Value; settings.Values["volume"] = volume.Value;
videoSource.Volume = volume.Value * 0.01; audioSource.Volume = videoSource.Volume = volume.Value * 0.01;
} }
private void muteBtn_Click(object sender, RoutedEventArgs e) private void muteBtn_Click(object sender, RoutedEventArgs e)
@@ -298,13 +317,17 @@ namespace FoxTube
private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e) private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e)
{ {
if (cursorPositionBackup == null)
cursorPositionBackup = Window.Current.CoreWindow.PointerPosition;
else if (cursorPositionBackup == Window.Current.CoreWindow.PointerPosition)
return;
ShowControls(); ShowControls();
} }
void ShowControls() void ShowControls()
{ {
controls.Visibility = Visibility.Visible; controls.Visibility = Visibility.Visible;
if (miniView) if (MiniView)
seekIndicator.Visibility = Visibility.Visible; seekIndicator.Visibility = Visibility.Visible;
if (pointerCaptured) if (pointerCaptured)
Window.Current.CoreWindow.PointerCursor = cursorBackup; Window.Current.CoreWindow.PointerCursor = cursorBackup;
@@ -317,32 +340,117 @@ namespace FoxTube
try try
{ {
videoSource.Pause(); videoSource.Pause();
audioSource.Source = null;
timecodeBackup = videoSource.Position.TotalSeconds; timecodeBackup = videoSource.Position.TotalSeconds;
switch((quality.SelectedItem as ComboBoxItem).Content) audioReady = false;
videoReady = false;
settings.Values["rememberedQuality"] = (quality.SelectedItem as ComboBoxItem).Content as string;
if(streamInfo.Muxed.ToList().Find(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string) != null)
{
isMuxed = true;
videoSource.Source = streamInfo.Muxed.First(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri();
}
else
{
isMuxed = false;
videoSource.Source = streamInfo.Video.First(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri();
audioSource.Source = streamInfo.Audio.First().Url.ToUri();
}
/*switch((quality.SelectedItem as ComboBoxItem).Content)
{ {
case "2160p": case "2160p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.High2160).Url); if(streamInfo.Muxed.First(x => x.VideoQuality.))
{
isMuxed = true;
}
else
{
isMuxed = false;
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityHigh && !x.HasVideo) ??
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
}
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality2160P).Uri;
break; break;
case "1080p": case "1080p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.High1080).Url); if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality1080P).HasAudio)
isMuxed = true;
else
{
isMuxed = false;
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityHigh && !x.HasVideo) ??
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
}
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality1080P).Uri;
break; break;
case "720p": case "720p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.High720).Url); if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality720P).HasAudio)
isMuxed = true;
else
{
isMuxed = false;
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityHigh && !x.HasVideo) ??
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
}
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality720P).Uri;
break; break;
case "480p": case "480p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Medium480).Url); if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality480P).HasAudio)
isMuxed = true;
else
{
isMuxed = false;
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
}
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality480P).Uri;
break; break;
case "360p": case "360p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Medium360).Url); if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality360P).HasAudio)
isMuxed = true;
else
{
isMuxed = false;
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
}
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality360P).Uri;
break; break;
case "240p": case "240p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Low240).Url); if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality240P).HasAudio)
isMuxed = true;
else
{
isMuxed = false;
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
}
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality240P).Uri;
break; break;
case "144p": case "144p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Low144).Url); if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality144P).HasAudio)
isMuxed = true;
else
{
isMuxed = false;
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
}
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality144P).Uri;
break; break;
} }*/
needUpdateTimecode = true; needUpdateTimecode = true;
videoSource.Play(); videoSource.Play();
@@ -367,8 +475,10 @@ namespace FoxTube
{ {
if (subsSwitch.IsOn) if (subsSwitch.IsOn)
{ {
if (ccInfo[subsLang.SelectedIndex].IsAutoGenerated)
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url); captions.Initialize(ccInfo[subsLang.SelectedIndex].Url.Replace("format=3", "format=0"), true);
else
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url);
} }
else else
captions.Close(); captions.Close();
@@ -399,7 +509,45 @@ namespace FoxTube
if (videoSource.CurrentState == MediaElementState.Playing) if (videoSource.CurrentState == MediaElementState.Playing)
videoSource.Pause(); videoSource.Pause();
else if (videoSource.CurrentState == MediaElementState.Paused) else if (videoSource.CurrentState == MediaElementState.Paused)
videoSource.Play(); if((audioReady && videoReady) || isMuxed)
videoSource.Play();
}
private void AudioSource_CurrentStateChanged(object sender, RoutedEventArgs e)
{
switch (audioSource.CurrentState)
{
case MediaElementState.Buffering:
if(videoSource.CurrentState != MediaElementState.Buffering)
videoSource.Pause();
break;
case MediaElementState.Playing:
if (videoSource.CurrentState == MediaElementState.Paused)
videoSource.Play();
else if (videoSource.CurrentState == MediaElementState.Buffering)
audioSource.Pause();
break;
}
}
private void videoSource_Opened(object sender, RoutedEventArgs arg)
{
if(!isMuxed)
{
if(sender == videoSource)
{
videoReady = true;
if (audioReady && ((timecodeBackup == 0 && (bool)settings.Values["videoAutoplay"]) || timecodeBackup > 0))
play_Click(this, null);
}
else if(sender == audioSource)
{
audioReady = true;
if (videoReady && ((timecodeBackup == 0 && (bool)settings.Values["videoAutoplay"]) || timecodeBackup > 0))
play_Click(this, null);
}
}
} }
private void videoSource_CurrentStateChanged(object sender, RoutedEventArgs e) private void videoSource_CurrentStateChanged(object sender, RoutedEventArgs e)
@@ -413,6 +561,8 @@ namespace FoxTube
switch(videoSource.CurrentState) switch(videoSource.CurrentState)
{ {
case MediaElementState.Buffering: case MediaElementState.Buffering:
audioSource.Position = videoSource.Position;
audioSource.Pause();
bufferingBar.Visibility = Visibility.Visible; bufferingBar.Visibility = Visibility.Visible;
seek.IsEnabled = false; seek.IsEnabled = false;
@@ -426,6 +576,8 @@ namespace FoxTube
break; break;
case MediaElementState.Paused: case MediaElementState.Paused:
if(audioSource.CurrentState != MediaElementState.Buffering)
audioSource.Pause();
bufferingBar.Visibility = Visibility.Collapsed; bufferingBar.Visibility = Visibility.Collapsed;
seek.IsEnabled = true; seek.IsEnabled = true;
@@ -439,12 +591,15 @@ namespace FoxTube
break; break;
case MediaElementState.Playing: case MediaElementState.Playing:
audioSource.Play();
bufferingBar.Visibility = Visibility.Collapsed; bufferingBar.Visibility = Visibility.Collapsed;
seek.IsEnabled = true; seek.IsEnabled = true;
play.IsEnabled = true; play.IsEnabled = true;
touchPlay.IsEnabled = true; touchPlay.IsEnabled = true;
seekTimer.Start();
play.Content = "\xE103"; play.Content = "\xE103";
touchPlay.Content = "\xE103"; touchPlay.Content = "\xE103";
@@ -452,6 +607,7 @@ namespace FoxTube
break; break;
default: default:
audioSource.Pause();
bufferingBar.Visibility = Visibility.Collapsed; bufferingBar.Visibility = Visibility.Collapsed;
systemControls.PlaybackStatus = MediaPlaybackStatus.Closed; systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
break; break;
@@ -461,10 +617,10 @@ namespace FoxTube
private async void miniView_Click(object sender, RoutedEventArgs e) private async void miniView_Click(object sender, RoutedEventArgs e)
{ {
ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar; ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
miniView = !miniView; MiniView = !MiniView;
SetFullSize(this, miniView); SetFullSize(this, MiniView);
if (miniView) if (MiniView)
{ {
if (fullScreen) if (fullScreen)
{ {
@@ -590,7 +746,7 @@ namespace FoxTube
Width = 432; Width = 432;
Height = 243; Height = 243;
miniView = true; MiniView = true;
Methods.MainPage.MinimizeVideo(); Methods.MainPage.MinimizeVideo();
mainControls.Visibility = Visibility.Collapsed; mainControls.Visibility = Visibility.Collapsed;
@@ -607,6 +763,8 @@ namespace FoxTube
private void close_Click(object sender, RoutedEventArgs e) private void close_Click(object sender, RoutedEventArgs e)
{ {
systemControls.IsEnabled = false; systemControls.IsEnabled = false;
pointerCaptured = false;
Elapsed();
Methods.MainPage.CloseVideo(); Methods.MainPage.CloseVideo();
} }
@@ -617,7 +775,7 @@ namespace FoxTube
Width = double.NaN; Width = double.NaN;
Height = double.NaN; Height = double.NaN;
miniView = false; MiniView = false;
Methods.MainPage.MaximizeVideo(); Methods.MainPage.MaximizeVideo();
mainControls.Visibility = Visibility.Visible; mainControls.Visibility = Visibility.Visible;
@@ -655,38 +813,38 @@ namespace FoxTube
private void playPauseArea_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e) private void playPauseArea_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{ {
if (miniView && ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay) if (MiniView && ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay)
miniView_Click(this, null); miniView_Click(this, null);
else if (miniView && ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.Default) else if (MiniView && ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.Default)
maximize_Click(this, null); maximize_Click(this, null);
else if (fullScreen) else if (fullScreen)
fullscreen_Click(this, null); fullscreen_Click(this, null);
else if (!miniView && !fullScreen) else if (!MiniView && !fullScreen)
fullscreen_Click(this, null); fullscreen_Click(this, null);
} }
private void playPauseArea_Tapped(object sender, TappedRoutedEventArgs e) private void playPauseArea_Tapped(object sender, TappedRoutedEventArgs e)
{ {
if (e.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse && !miniView) if (e.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse && !MiniView)
play_Click(this, null); play_Click(this, null);
} }
private void UserControl_KeyUp(object sender, KeyRoutedEventArgs e) public void KeyUpPressed(object sender, KeyRoutedEventArgs e)
{ {
switch(e.Key) switch(e.Key)
{ {
case Windows.System.VirtualKey.Escape: case VirtualKey.Escape:
case Windows.System.VirtualKey.F11: case VirtualKey.F11:
if (fullScreen) if (fullScreen)
fullscreen_Click(this, null); fullscreen_Click(this, null);
break; break;
case Windows.System.VirtualKey.Space: case VirtualKey.Space:
play_Click(this, null); play_Click(this, null);
break; break;
case Windows.System.VirtualKey.Left: case VirtualKey.Left:
back10_Click(this, null); back10_Click(this, null);
break; break;
case Windows.System.VirtualKey.Right: case VirtualKey.Right:
fwd30_Click(this, null); fwd30_Click(this, null);
break; break;
} }
@@ -694,8 +852,12 @@ namespace FoxTube
private void subsLang_SelectionChanged(object sender, SelectionChangedEventArgs e) private void subsLang_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
if (subsSwitch.IsOn) LoadTrack();
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url); }
private void videoSource_BufferingProgressChanged(object sender, RoutedEventArgs e)
{
bufferingLevel.Value = (audioSource.Source != null && videoSource.BufferingProgress > audioSource.BufferingProgress ? audioSource.BufferingProgress : videoSource.BufferingProgress) * 100;
} }
} }
} }
+13 -12
View File
@@ -97,6 +97,7 @@
<DependentUpon>App.xaml</DependentUpon> <DependentUpon>App.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Classes\Caption.cs" /> <Compile Include="Classes\Caption.cs" />
<Compile Include="Classes\DownloadItemContainer.cs" />
<Compile Include="Classes\InboxItem.cs" /> <Compile Include="Classes\InboxItem.cs" />
<Compile Include="Classes\Methods.cs" /> <Compile Include="Classes\Methods.cs" />
<Compile Include="Classes\ObjectEventArgs.cs" /> <Compile Include="Classes\ObjectEventArgs.cs" />
@@ -398,7 +399,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AdaptiveCards.Rendering.Uwp"> <PackageReference Include="AdaptiveCards.Rendering.Uwp">
<Version>1.0.1</Version> <Version>1.1.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Google.Apis"> <PackageReference Include="Google.Apis">
<Version>1.30.0-beta02</Version> <Version>1.30.0-beta02</Version>
@@ -419,25 +420,25 @@
<Version>10.1805.7001</Version> <Version>10.1805.7001</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform"> <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.1.5</Version> <Version>6.1.9</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications"> <PackageReference Include="Microsoft.Toolkit.Uwp.Notifications">
<Version>3.0.0</Version> <Version>4.0.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls"> <PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls">
<Version>3.0.0</Version> <Version>4.0.0</Version>
</PackageReference>
<PackageReference Include="MyToolkit">
<Version>2.5.16</Version>
</PackageReference>
<PackageReference Include="MyToolkit.Extended">
<Version>2.5.16</Version>
</PackageReference> </PackageReference>
<PackageReference Include="runtime.win10-arm64.runtime.native.System.IO.Compression"> <PackageReference Include="runtime.win10-arm64.runtime.native.System.IO.Compression">
<Version>4.3.1</Version> <Version>4.3.2</Version>
</PackageReference>
<PackageReference Include="Syroot.Windows.IO.KnownFolders">
<Version>1.2.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="YoutubeExplode"> <PackageReference Include="YoutubeExplode">
<Version>4.3.1</Version> <Version>4.4.0</Version>
</PackageReference>
<PackageReference Include="YoutubeExtractor">
<Version>0.10.11</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+10 -16
View File
@@ -86,6 +86,9 @@ namespace FoxTube.Pages
try try
{ {
channelId = id; channelId = id;
if (Methods.NeedToResponse)
Methods.MainPage.content_Navigated(this, null);
ChannelsResource.ListRequest request = SecretsVault.Service.Channels.List("snippet,statistics,brandingSettings"); ChannelsResource.ListRequest request = SecretsVault.Service.Channels.List("snippet,statistics,brandingSettings");
request.Id = id; request.Id = id;
if (content.Items.Count == 4) if (content.Items.Count == 4)
@@ -133,8 +136,6 @@ namespace FoxTube.Pages
if (SecretsVault.IsAuthorized) if (SecretsVault.IsAuthorized)
{ {
SecretsVault.Subscriptions.ForEach(x => Debug.WriteLine($"{x.Snippet.Title}: {x.Snippet.ResourceId.ChannelId}"));
Debug.WriteLine($"Current channel ID: {item.Id}");
bool b = false; bool b = false;
foreach (Subscription s in SecretsVault.Subscriptions) foreach (Subscription s in SecretsVault.Subscriptions)
{ {
@@ -148,7 +149,6 @@ namespace FoxTube.Pages
break; break;
} }
} }
Debug.WriteLine($"Channel was found: {b}");
subscriptionPane.Visibility = Visibility.Visible; subscriptionPane.Visibility = Visibility.Visible;
} }
@@ -250,23 +250,17 @@ namespace FoxTube.Pages
private async void subscribe_Click(object sender, RoutedEventArgs e) private async void subscribe_Click(object sender, RoutedEventArgs e)
{ {
if (subscribe.Background == new SolidColorBrush(Colors.Red)) if(await SecretsVault.ChangeSubscriptionState(channelId))
{ {
if (await SecretsVault.Subscribe(channelId)) subscribe.Background = new SolidColorBrush(Colors.Transparent);
{ subscribe.Foreground = new SolidColorBrush(Colors.Gray);
subscribe.Background = new SolidColorBrush(Colors.Transparent); subscribe.Content = "Subscribed";
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
subscribe.Content = "Subscribed";
}
} }
else else
{ {
if (await SecretsVault.Unsubscibe(channelId)) subscribe.Background = new SolidColorBrush(Colors.Red);
{ subscribe.Foreground = new SolidColorBrush(Colors.White);
subscribe.Background = new SolidColorBrush(Colors.Red); subscribe.Content = "Subscribe";
subscribe.Foreground = new SolidColorBrush(Colors.White);
subscribe.Content = "Subscribe";
}
} }
} }
+1 -1
View File
@@ -18,7 +18,7 @@
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition Height="30"/> <RowDefinition Height="30"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBox x:Uid="/CommentsPage/textbox" Margin="5,5,42,5" PlaceholderText="Add a public comment" Name="newComment" VerticalAlignment="Center" MinHeight="32" MaxHeight="100" Height="auto" AcceptsReturn="True"/> <TextBox x:Uid="/CommentsPage/textbox" Margin="5,5,42,5" PlaceholderText="Add a public comment" Name="newComment" VerticalAlignment="Center" MinHeight="32" TextWrapping="Wrap" AcceptsReturn="True"/>
<Button HorizontalAlignment="Right" Name="send" Click="send_Click" VerticalAlignment="Top" <Button HorizontalAlignment="Right" Name="send" Click="send_Click" VerticalAlignment="Top"
Height="32" Width="32" Height="32" Width="32"
Margin="0,5,5,0" Padding="0" Margin="0,5,5,0" Padding="0"
+4 -1
View File
@@ -5,6 +5,7 @@
xmlns:local="using:FoxTube.Pages" xmlns:local="using:FoxTube.Pages"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:FoxTube.Controls"
mc:Ignorable="d" mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
@@ -27,7 +28,9 @@
</Grid> </Grid>
</StackPanel> </StackPanel>
<ScrollViewer Grid.Row="1"> <ScrollViewer Grid.Row="1">
<StackPanel Margin="5" Name="stack"/> <StackPanel Margin="5" Name="stack">
<ListView ItemsSource="{Binding Path=Methods.MainPage.agent.items}" SelectionMode="None"/>
</StackPanel>
</ScrollViewer> </ScrollViewer>
</Grid> </Grid>
</Page> </Page>
+3 -21
View File
@@ -11,11 +11,6 @@ using Windows.Storage.Pickers;
using Windows.System; using Windows.System;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
#pragma warning disable CS0252 // Possible unintended reference comparison; left hand side needs cast #pragma warning disable CS0252 // Possible unintended reference comparison; left hand side needs cast
@@ -28,33 +23,20 @@ namespace FoxTube.Pages
public sealed partial class Downloads : Page public sealed partial class Downloads : Page
{ {
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings; ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
DownloadAgent agent = Methods.MainPage.Agent;
public Downloads() public Downloads()
{ {
this.InitializeComponent(); this.InitializeComponent();
path.Text = settings.Values["defaultDownload"] as string; path.Text = settings.Values["defaultDownload"] as string;
agent.ListChanged += UpdateList;
foreach (DownloadItem item in agent.Items)
stack.Children.Add(item);
}
private void UpdateList(object sender, params object[] e)
{
if (e[0] == "remove")
stack.Children.Remove(sender as DownloadItem);
else if (e[0] == "add")
stack.Children.Add(sender as DownloadItem);
} }
private async void changePath_Click(object sender, RoutedEventArgs e) private async void changePath_Click(object sender, RoutedEventArgs e)
{ {
FolderPicker picker = new FolderPicker() FolderPicker picker = new FolderPicker()
{ {
SuggestedStartLocation = PickerLocationId.Desktop, SuggestedStartLocation = PickerLocationId.Downloads,
ViewMode = PickerViewMode.Thumbnail ViewMode = PickerViewMode.Thumbnail
}; };
picker.FileTypeFilter.Add(".shit"); //Because overwise it trhows an exception
StorageFolder p = await picker.PickSingleFolderAsync(); StorageFolder p = await picker.PickSingleFolderAsync();
if (p != null) if (p != null)
@@ -64,7 +46,7 @@ namespace FoxTube.Pages
private async void openFolder_Click(object sender, RoutedEventArgs e) private async void openFolder_Click(object sender, RoutedEventArgs e)
{ {
await Launcher.LaunchUriAsync(new Uri(settings.Values["defaultDownload"] as string)); await Launcher.LaunchFolderAsync( await StorageFolder.GetFolderFromPathAsync(settings.Values["defaultDownload"] as string));
} }
} }
} }
+12 -6
View File
@@ -8,8 +8,10 @@
xmlns:ads="using:Microsoft.Advertising.WinRT.UI" xmlns:ads="using:Microsoft.Advertising.WinRT.UI"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:pages="using:FoxTube.Pages" xmlns:pages="using:FoxTube.Pages"
xmlns:Windows10version1803="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 6)"
mc:Ignorable="d" mc:Ignorable="d"
SizeChanged="Page_SizeChanged"> SizeChanged="Page_SizeChanged"
PreviewKeyUp="Page_PreviewKeyUp">
<Grid Name="grid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid Name="grid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups> <VisualStateManager.VisualStateGroups>
@@ -21,11 +23,15 @@
<VisualState.Setters> <VisualState.Setters>
<Setter Target="header.FontSize" Value="28"/> <Setter Target="header.FontSize" Value="28"/>
<Setter Target="headerGrid.Margin" Value="10,25,0,0"/>
<Setter Target="account.Height" Value="50"/>
<Setter Target="notificationMenu.Height" Value="50"/>
<Setter Target="avatar.Height" Value="50"/>
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateManager.VisualStateGroups> </VisualStateManager.VisualStateGroups>
<NavigationView SelectedItem="toHome" BackRequested="nav_BackRequested" PaneTitle="FoxTube" OpenPaneLength="300" Name="nav" SelectionChanged="nav_SelectionChanged"> <NavigationView SelectedItem="toHome" Windows10version1803:BackRequested="nav_BackRequested" Windows10version1803:PaneTitle="FoxTube" OpenPaneLength="300" Name="nav" SelectionChanged="nav_SelectionChanged">
<NavigationView.MenuItems> <NavigationView.MenuItems>
<NavigationViewItem x:Uid="/Main/home" Icon="Home" Content="Home" Name="toHome"/> <NavigationViewItem x:Uid="/Main/home" Icon="Home" Content="Home" Name="toHome"/>
@@ -65,7 +71,7 @@
</NavigationView.AutoSuggestBox> </NavigationView.AutoSuggestBox>
<NavigationView.Header> <NavigationView.Header>
<Grid Margin="10,25,0,0"> <Grid Name="headerGrid" Margin="0,-10,0,0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition/> <ColumnDefinition/>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
@@ -74,7 +80,7 @@
<StackPanel Orientation="Horizontal" Grid.Column="1"> <StackPanel Orientation="Horizontal" Grid.Column="1">
<Button Name="notificationMenu" Click="notificationMenu_Click" <Button Name="notificationMenu" Click="notificationMenu_Click"
FontFamily="Segoe MDL2 Assets" Content="&#xED0D;" FontFamily="Segoe MDL2 Assets" Content="&#xED0D;"
Width="50" Height="50" Background="Transparent" x:Uid="notifications" ToolTipService.ToolTip="Notifications"> Width="50" Height="42" Background="Transparent" x:Uid="notifications" ToolTipService.ToolTip="Notifications">
<Button.Flyout> <Button.Flyout>
<Flyout Content="{x:Bind notificationsCenter}"/> <Flyout Content="{x:Bind notificationsCenter}"/>
</Button.Flyout> </Button.Flyout>
@@ -82,7 +88,7 @@
<Button Name="account" <Button Name="account"
FontFamily="Segoe MDL2 Assets" Content="&#xE8FA;" FontFamily="Segoe MDL2 Assets" Content="&#xE8FA;"
Width="50" Height="50" Background="Transparent" x:Uid="signIn" ToolTipService.ToolTip="Sign in"> Width="50" Height="42" Background="Transparent" x:Uid="signIn" ToolTipService.ToolTip="Sign in">
<Button.Flyout> <Button.Flyout>
<MenuFlyout> <MenuFlyout>
<MenuFlyoutItem x:Uid="/Main/signEx" Text="Sign in with existing account" Name="signIn" Click="signIn_Click"/> <MenuFlyoutItem x:Uid="/Main/signEx" Text="Sign in with existing account" Name="signIn" Click="signIn_Click"/>
@@ -91,7 +97,7 @@
</Button.Flyout> </Button.Flyout>
</Button> </Button>
<Button Width="50" Background="Transparent" Height="50" Visibility="Collapsed" Name="avatar"> <Button Width="50" Background="Transparent" Height="42" Visibility="Collapsed" Name="avatar">
<PersonPicture Width="30" ToolTipService.ToolTip="My account" x:Uid="myAccount"/> <PersonPicture Width="30" ToolTipService.ToolTip="My account" x:Uid="myAccount"/>
<Button.Flyout> <Button.Flyout>
<MenuFlyout> <MenuFlyout>
+103 -70
View File
@@ -1,48 +1,30 @@
using System; using System;
using System.Collections.Generic; 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; using Windows.UI;
using Windows.UI.ViewManagement; using Windows.UI.ViewManagement;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Shapes;
using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation; using Windows.UI.Xaml.Navigation;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.Toolkit.Uwp.Notifications;
using Windows.UI.Notifications; using Windows.UI.Notifications;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
using Windows.Storage; using Windows.Storage;
using System.Xml; using System.Xml;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data; using Google.Apis.YouTube.v3.Data;
using System.Threading.Tasks;
using System.Threading;
using Google.Apis.Util.Store;
using System.Globalization; using System.Globalization;
using Windows.ApplicationModel.Core; using Windows.ApplicationModel.Core;
using Windows.System; using Windows.System;
using Windows.UI.Xaml.Documents;
using Google.Apis.Oauth2.v2; using Google.Apis.Oauth2.v2;
using Google.Apis.Oauth2.v2.Data; using Google.Apis.Oauth2.v2.Data;
using FoxTube.Controls; using FoxTube.Controls;
using FoxTube.Pages; using FoxTube.Pages;
using Microsoft.Toolkit.Uwp.UI.Controls;
using Windows.ApplicationModel; using Windows.ApplicationModel;
using System.Net; using System.Net;
using Windows.UI.Popups; using Windows.UI.Popups;
using Windows.Networking.Connectivity; using Windows.Networking.Connectivity;
using Windows.UI.Core;
using Syroot.Windows.IO;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
@@ -67,7 +49,9 @@ namespace FoxTube
this.InitializeComponent(); this.InitializeComponent();
if (settings.Values["quality"] == null) if (settings.Values["quality"] == null)
settings.Values.Add("quality", 1); settings.Values.Add("quality", "remember");
if (settings.Values["rememberedQuality"] == null)
settings.Values.Add("rememberedQuality", "1080p");
if (settings.Values["newVideoNotification"] == null) if (settings.Values["newVideoNotification"] == null)
settings.Values.Add("newVideoNotification", true); settings.Values.Add("newVideoNotification", true);
@@ -89,7 +73,7 @@ namespace FoxTube
settings.Values.Add("safeSearch", 0); settings.Values.Add("safeSearch", 0);
if (settings.Values["defaultDownload"] == null) if (settings.Values["defaultDownload"] == null)
settings.Values.Add("defaultDownload", Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\DownloadedVideos"); settings.Values.Add("defaultDownload", Syroot.Windows.IO.KnownFolders.Downloads.Path + "\\DownloadedVideos");
if (settings.Values["notificationsHistory"] == null) if (settings.Values["notificationsHistory"] == null)
{ {
@@ -144,6 +128,12 @@ namespace FoxTube
SetTitleBar(); SetTitleBar();
} }
public Video GetCurrentItem()
{
try { return (videoPlaceholder.Content as VideoPage).item; }
catch { return null; }
}
public void SetTitleBar() public void SetTitleBar()
{ {
var titleBar = ApplicationView.GetForCurrentView().TitleBar; var titleBar = ApplicationView.GetForCurrentView().TitleBar;
@@ -307,39 +297,46 @@ namespace FoxTube
public void GoToSearch(SearchParameters args) public void GoToSearch(SearchParameters args)
{ {
nav.IsPaneOpen = false;
MinimizeAsInitializer(); MinimizeAsInitializer();
content.Navigate(typeof(Search), args); content.Navigate(typeof(Search), args);
} }
public void GoToChannel(string id) public void GoToChannel(string id)
{ {
Debug.WriteLine($"Channel id: {id}");
MinimizeAsInitializer(); MinimizeAsInitializer();
content.Navigate(typeof(ChannelPage), id); content.Navigate(typeof(ChannelPage), id);
} }
public async void GoToVideo(string id, string playlistId = null) public async void GoToVideo(string id, string playlistId = null)
{ {
var connection = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost(); Debug.WriteLine($"Video id: {id}; Playlist id: {playlistId}");
if ((bool)settings.Values["moblieWarning"] && (connection.NetworkCostType == NetworkCostType.Fixed || connection.NetworkCostType == NetworkCostType.Variable)) try
{ {
bool cancel = false; var connection = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();
MessageDialog dialog = new MessageDialog("You are on metered connection now. Additional charges may apply. Do you want to continue?") if ((bool)settings.Values["moblieWarning"] && (connection.NetworkCostType == NetworkCostType.Fixed || connection.NetworkCostType == NetworkCostType.Variable))
{ {
DefaultCommandIndex = 2, bool cancel = false;
CancelCommandIndex = 1 MessageDialog dialog = new MessageDialog("You are on metered connection now. Additional charges may apply. Do you want to continue?")
}; {
dialog.Commands.Add(new UICommand("Yes")); DefaultCommandIndex = 2,
dialog.Commands.Add(new UICommand("No", (command) => cancel = true)); CancelCommandIndex = 1
dialog.Commands.Add(new UICommand("Add to 'Watch later' playlist", (command) => };
{ dialog.Commands.Add(new UICommand("Yes"));
//TO-DO: Adding video to "Watch later" dialog.Commands.Add(new UICommand("No", (command) => cancel = true));
cancel = true; dialog.Commands.Add(new UICommand("Add to 'Watch later' playlist", (command) =>
})); {
await dialog.ShowAsync(); //TO-DO: Adding video to "Watch later"
cancel = true;
}));
await dialog.ShowAsync();
if (cancel) if (cancel)
return; return;
}
} }
catch { }
nav.IsPaneOpen = false; nav.IsPaneOpen = false;
@@ -358,6 +355,7 @@ namespace FoxTube
public void GoToPlaylist(string id) public void GoToPlaylist(string id)
{ {
Debug.WriteLine($"Playlist id: {id}");
MinimizeAsInitializer(); MinimizeAsInitializer();
content.Navigate(typeof(PlaylistPage), id); content.Navigate(typeof(PlaylistPage), id);
} }
@@ -370,8 +368,16 @@ namespace FoxTube
public void MinimizeAsInitializer() public void MinimizeAsInitializer()
{ {
try { (videoPlaceholder.Content as VideoPage).player.minimize_Click(this, null); } if(videoPlaceholder.Content != null)
catch { } {
if ((videoPlaceholder.Content as VideoPage).loading.State != LoadingState.Loaded)
CloseVideo();
else
{
try { (videoPlaceholder.Content as VideoPage).player.minimize_Click(this, null); }
catch { }
}
}
} }
public void MinimizeVideo() public void MinimizeVideo()
@@ -405,7 +411,7 @@ namespace FoxTube
{ {
nav.OpenPaneLength = 0; nav.OpenPaneLength = 0;
nav.CompactPaneLength = 0; nav.CompactPaneLength = 0;
if ((videoPlaceholder.Content as VideoPage).player.miniView) if ((videoPlaceholder.Content as VideoPage).player.MiniView)
nav.Margin = new Thickness(0, -80, 0, 0); nav.Margin = new Thickness(0, -80, 0, 0);
else else
nav.Margin = new Thickness(0, -91, 0, 0); nav.Margin = new Thickness(0, -91, 0, 0);
@@ -427,6 +433,7 @@ namespace FoxTube
} }
(videoPlaceholder.Content as VideoPage).player.pointerCaptured = false; (videoPlaceholder.Content as VideoPage).player.pointerCaptured = false;
videoPlaceholder.Content = null; videoPlaceholder.Content = null;
Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Arrow, 0);
MaximizeVideo(); MaximizeVideo();
if (content.CanGoBack) if (content.CanGoBack)
@@ -437,7 +444,8 @@ namespace FoxTube
private void search_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) private void search_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{ {
GoToSearch(new SearchParameters(search.Text)); if(!string.IsNullOrWhiteSpace(search.Text))
GoToSearch(new SearchParameters(search.Text));
} }
private void search_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) private void search_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
@@ -494,7 +502,7 @@ namespace FoxTube
s = Sender.None; s = Sender.None;
} }
private void content_Navigated(object sender, NavigationEventArgs e) public void content_Navigated(object sender, NavigationEventArgs e)
{ {
Dictionary<Type, Action> switchCase = new Dictionary<Type, Action>() Dictionary<Type, Action> switchCase = new Dictionary<Type, Action>()
{ {
@@ -527,38 +535,54 @@ namespace FoxTube
} }, } },
{ typeof(ChannelPage), () => { typeof(ChannelPage), () =>
{ {
if(SecretsVault.IsAuthorized) if(sender.GetType() != typeof(ChannelPage))
{ {
if((content.Content as ChannelPage).channelId == SecretsVault.AccountId) Methods.NeedToResponse = true;
s = Sender.None;
return;
}
Methods.NeedToResponse = false;
if(SecretsVault.IsAuthorized)
{ {
if(nav.SelectedItem != toChannel) if((content.Content as ChannelPage).channelId == SecretsVault.UserChannel.Id)
nav.SelectedItem = toChannel; {
if(nav.SelectedItem != toChannel)
nav.SelectedItem = toChannel;
else
s = Sender.None;
}
else else
s = Sender.None; {
bool found = false;
for(int k = 0; k < SecretsVault.Subscriptions.Count && k < 10; k++)
if(SecretsVault.Subscriptions[k].Snippet.ResourceId.ChannelId == (content.Content as ChannelPage).channelId)
{
if(nav.SelectedItem != nav.MenuItems[k + 9])
nav.SelectedItem = nav.MenuItems[k + 9];
else
s = Sender.None;
found = true;
break;
}
if(!found)
{
nav.SelectedItem = null;
}
}
} }
else else
{ nav.SelectedItem = null;
bool found = false;
for(int k = 0; k < SecretsVault.Subscriptions.Count && k < 10; k++)
if(SecretsVault.Subscriptions[k].Snippet.ResourceId.ChannelId == (content.Content as ChannelPage).channelId)
{
if(nav.SelectedItem != nav.MenuItems[k + 9])
nav.SelectedItem = nav.MenuItems[k + 9];
else
s = Sender.None;
found = true;
break;
}
if(!found)
nav.SelectedItem = null;
}
}
else
nav.SelectedItem = null;
} }, } },
{ typeof(PlaylistPage), () => { typeof(PlaylistPage), () =>
{ {
if(sender.GetType() != typeof(PlaylistPage))
{
Methods.NeedToResponse = true;
s = Sender.None;
return;
}
Methods.NeedToResponse = false;
if((content.Content as PlaylistPage).playlistId == SecretsVault.UserChannel.ContentDetails.RelatedPlaylists.Likes) if((content.Content as PlaylistPage).playlistId == SecretsVault.UserChannel.ContentDetails.RelatedPlaylists.Likes)
{ {
if(nav.SelectedItem != toLiked) if(nav.SelectedItem != toLiked)
@@ -609,7 +633,7 @@ namespace FoxTube
} } } }
}; };
try { navCase[e.SourcePageType](); } try { navCase[content.SourcePageType](); }
catch catch
{ {
nav.SelectedItem = null; nav.SelectedItem = null;
@@ -623,7 +647,7 @@ namespace FoxTube
else else
nav.IsBackEnabled = false; nav.IsBackEnabled = false;
if (e.SourcePageType == typeof(Home) || e.SourcePageType == typeof(Settings) || e.SourcePageType == typeof(Subscriptions)) if (content.SourcePageType == typeof(Home) || content.SourcePageType == typeof(Settings) || content.SourcePageType == typeof(Subscriptions))
{ {
nav.ExpandedModeThresholdWidth = 1008; nav.ExpandedModeThresholdWidth = 1008;
if (nav.DisplayMode == NavigationViewDisplayMode.Expanded) if (nav.DisplayMode == NavigationViewDisplayMode.Expanded)
@@ -655,5 +679,14 @@ namespace FoxTube
else else
content.GoBack(); content.GoBack();
} }
private void Page_PreviewKeyUp(object sender, KeyRoutedEventArgs e)
{
if(videoPlaceholder.Content != null && FocusManager.GetFocusedElement().GetType() != typeof(TextBox))
{
e.Handled = true;
(videoPlaceholder.Content as VideoPage).player.KeyUpPressed(sender, e);
}
}
} }
} }
+3
View File
@@ -62,6 +62,9 @@ namespace FoxTube.Pages
try try
{ {
playlistId = id; playlistId = id;
if (Methods.NeedToResponse)
Methods.MainPage.content_Navigated(this, null);
PlaylistsResource.ListRequest request = SecretsVault.Service.Playlists.List("snippet,contentDetails"); PlaylistsResource.ListRequest request = SecretsVault.Service.Playlists.List("snippet,contentDetails");
request.Id = id; request.Id = id;
-1
View File
@@ -1,5 +1,4 @@
<Page <Page
NavigationCacheMode="Enabled"
x:Class="FoxTube.Search" x:Class="FoxTube.Search"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+7 -9
View File
@@ -92,13 +92,11 @@ namespace FoxTube
} }
public async void Initialize(SearchParameters arg, bool forceInitialization = false) public async void Initialize(SearchParameters arg)
{ {
if (Parameters != null && arg.Term == Parameters.Term && !forceInitialization)
return;
loading.Refresh(); loading.Refresh();
//try try
{ {
Parameters = arg; Parameters = arg;
request = SecretsVault.Service.Search.List("id,snippet"); request = SecretsVault.Service.Search.List("id,snippet");
@@ -161,14 +159,14 @@ namespace FoxTube
loading.Close(); loading.Close();
} }
/*catch (System.Net.Http.HttpRequestException) catch (System.Net.Http.HttpRequestException)
{ {
loading.Error("System.Net.Http.HttpRequestException", "Unable to connect to Google servers.", true); loading.Error("System.Net.Http.HttpRequestException", "Unable to connect to Google servers.", true);
} }
catch (Exception e) catch (Exception e)
{ {
loading.Error(e.GetType().ToString(), e.Message); loading.Error(e.GetType().ToString(), e.Message);
}*/ }
} }
private void toggleFilters_Click(object sender, RoutedEventArgs e) private void toggleFilters_Click(object sender, RoutedEventArgs e)
@@ -187,7 +185,7 @@ namespace FoxTube
private void AppBarButton_Click(object sender, RoutedEventArgs e) private void AppBarButton_Click(object sender, RoutedEventArgs e)
{ {
Initialize(Parameters, true); Initialize(Parameters);
} }
private async void more_Clicked() private async void more_Clicked()
@@ -243,8 +241,8 @@ namespace FoxTube
Parameters.Filter.Type = (SearchParameters.Filters.Enumerations.Type)type.SelectedIndex; Parameters.Filter.Type = (SearchParameters.Filters.Enumerations.Type)type.SelectedIndex;
Parameters.Filter.Date = (SearchParameters.Filters.Enumerations.Date)date.SelectedIndex; Parameters.Filter.Date = (SearchParameters.Filters.Enumerations.Date)date.SelectedIndex;
Parameters.Filter.Duration = (SearchParameters.Filters.Enumerations.Duration)duration.SelectedIndex; Parameters.Filter.Duration = (SearchParameters.Filters.Enumerations.Duration)duration.SelectedIndex;
Methods.MainPage.GoToSearch(Parameters); Initialize(Parameters);
} }
} }
} }
+2 -2
View File
@@ -21,11 +21,11 @@
<settingspages:About/> <settingspages:About/>
</ScrollViewer> </ScrollViewer>
</PivotItem> </PivotItem>
<PivotItem Header="Help us translate this app" x:Uid="/Settings/helpTranslate"> <!--<PivotItem Header="Help us translate this app" x:Uid="/Settings/helpTranslate">
<ScrollViewer> <ScrollViewer>
<settingspages:Translate/> <settingspages:Translate/>
</ScrollViewer> </ScrollViewer>
</PivotItem> </PivotItem>-->
<PivotItem Header="Inbox" x:Uid="/Settings/inbox"> <PivotItem Header="Inbox" x:Uid="/Settings/inbox">
<ScrollViewer> <ScrollViewer>
<settingspages:Inbox/> <settingspages:Inbox/>
+3 -3
View File
@@ -40,7 +40,7 @@ namespace FoxTube
{ {
if ((e.Parameter as string).Contains("inbox")) if ((e.Parameter as string).Contains("inbox"))
{ {
pivot.SelectedIndex = 4; pivot.SelectedIndex = 3;
if ((string)e.Parameter != "inbox") if ((string)e.Parameter != "inbox")
((pivot.SelectedItem as PivotItem).Content as Inbox).Open((e.Parameter as string).Split('&')[1]); ((pivot.SelectedItem as PivotItem).Content as Inbox).Open((e.Parameter as string).Split('&')[1]);
} }
@@ -59,9 +59,9 @@ namespace FoxTube
private void pivot_SelectionChanged(object sender, SelectionChangedEventArgs e) private void pivot_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
if (pivot.SelectedIndex == 3 && !inboxLoaded) if (pivot.SelectedIndex == 2 && !inboxLoaded)
{ {
(((pivot.Items[3] as PivotItem).Content as ScrollViewer).Content as Inbox).LoadItems(); (((pivot.Items[2] as PivotItem).Content as ScrollViewer).Content as Inbox).LoadItems();
inboxLoaded = true; inboxLoaded = true;
} }
} }
+1 -1
View File
@@ -41,7 +41,7 @@
<TextBlock><Run x:Uid="/About/vk">Vkontakte:</Run> <Hyperlink NavigateUri="https://vk.com/XFox.Mike">@XFox.Mike</Hyperlink></TextBlock> <TextBlock><Run x:Uid="/About/vk">Vkontakte:</Run> <Hyperlink NavigateUri="https://vk.com/XFox.Mike">@XFox.Mike</Hyperlink></TextBlock>
<TextBlock>YouTube: <Hyperlink NavigateUri="https://youtube.com/c/FoxGameStudioChannel">@FoxGameStudioChannel</Hyperlink></TextBlock> <TextBlock>YouTube: <Hyperlink NavigateUri="https://youtube.com/c/FoxGameStudioChannel">@FoxGameStudioChannel</Hyperlink></TextBlock>
<TextBlock>E-mail: <Hyperlink NavigateUri="mailto:michael.xfox@outlook.com">michael.xfox@outlook.com</Hyperlink></TextBlock> <TextBlock>E-mail: <Hyperlink NavigateUri="mailto:michael.xfox@outlook.com">michael.xfox@outlook.com</Hyperlink></TextBlock>
<TextBlock Margin="0,0,0,10"> <Run x:Uid="/About/myBlog">My blog (Russian language only):</Run> <Hyperlink NavigateUri="https://michael-xfox.com">https://michael-xfox.com</Hyperlink></TextBlock> <TextBlock Visibility="Collapsed" Margin="0,0,0,10"> <Run x:Uid="/About/myBlog">My blog (Russian language only):</Run> <Hyperlink NavigateUri="https://michael-xfox.com">https://michael-xfox.com</Hyperlink></TextBlock>
<TextBlock x:Uid="/About/legal" Text="Legal stuff" FontSize="22" FontWeight="SemiBold"/> <TextBlock x:Uid="/About/legal" Text="Legal stuff" FontSize="22" FontWeight="SemiBold"/>
<HyperlinkButton x:Uid="/About/ourPrivacy" Content="Our Privacy Policy" NavigateUri="https://michael-xfox.com/foxtubepp.txt" Padding="0,5,0,0"/> <HyperlinkButton x:Uid="/About/ourPrivacy" Content="Our Privacy Policy" NavigateUri="https://michael-xfox.com/foxtubepp.txt" Padding="0,5,0,0"/>
+8 -8
View File
@@ -28,14 +28,14 @@
<TextBlock x:Uid="/General/playback" Text="Playback" FontSize="22"/> <TextBlock x:Uid="/General/playback" Text="Playback" FontSize="22"/>
<ComboBox x:Uid="/General/quality" Width="250" Header="Default video playback quality" Name="quality" SelectionChanged="quality_SelectionChanged"> <ComboBox x:Uid="/General/quality" Width="250" Header="Default video playback quality" Name="quality" SelectionChanged="quality_SelectionChanged">
<ComboBoxItem x:Uid="/General/remember" Content="Remember my choice"/> <ComboBoxItem Tag="remember" x:Uid="/General/remember" Content="Remember my choice"/>
<ComboBoxItem Content="2160p"/> <ComboBoxItem Tag="2160p" Content="2160p"/>
<ComboBoxItem Content="1080p"/> <ComboBoxItem Tag="1080p" Content="1080p"/>
<ComboBoxItem Content="720p"/> <ComboBoxItem Tag="720p" Content="720p"/>
<ComboBoxItem Content="480p"/> <ComboBoxItem Tag="480p" Content="480p"/>
<ComboBoxItem Content="360p"/> <ComboBoxItem Tag="360p" Content="360p"/>
<ComboBoxItem Content="240p"/> <ComboBoxItem Tag="240p" Content="240p"/>
<ComboBoxItem Content="144p"/> <ComboBoxItem Tag="144p" Content="144p"/>
</ComboBox> </ComboBox>
<ToggleSwitch x:Uid="/General/metered" OnContent="Notify when playing on metered connection" OffContent="Notify when playing on metered connection" Name="mobileWarning" Toggled="mobileWarning_Toggled"/> <ToggleSwitch x:Uid="/General/metered" OnContent="Notify when playing on metered connection" OffContent="Notify when playing on metered connection" Name="mobileWarning" Toggled="mobileWarning_Toggled"/>
<ToggleSwitch x:Uid="/General/autoplay" OnContent="Play videos automatically" OffContent="Play videos automatically" Name="autoplay" Toggled="autoplay_Toggled"/> <ToggleSwitch x:Uid="/General/autoplay" OnContent="Play videos automatically" OffContent="Play videos automatically" Name="autoplay" Toggled="autoplay_Toggled"/>
+1 -1
View File
@@ -76,7 +76,7 @@ namespace FoxTube.Pages.SettingsPages
private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e) private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
settings.Values["quality"] = quality.SelectedIndex; settings.Values["quality"] = (quality.SelectedItem as ComboBoxItem).Tag as string;
} }
private void mobileWarning_Toggled(object sender, RoutedEventArgs e) private void mobileWarning_Toggled(object sender, RoutedEventArgs e)
@@ -119,6 +119,7 @@ namespace FoxTube.Pages.SettingsPages
{ {
content.Text = ""; content.Text = "";
title.Text = ""; title.Text = "";
list.SelectedItem = null;
block.Visibility = Visibility.Visible; block.Visibility = Visibility.Visible;
} }
+52 -52
View File
@@ -34,76 +34,76 @@
<ScrollViewer Margin="0,0,0,50" Name="mainScroll"> <ScrollViewer Margin="0,0,0,50" Name="mainScroll">
<StackPanel Orientation="Vertical" Name="mainContent"> <StackPanel Orientation="Vertical" Name="mainContent">
<local:VideoPlayer/> <local:VideoPlayer/>
<StackPanel Margin="10" Name="descriptionPanel"> <PivotItem Header="Description" Name="descriptionPanel">
<TextBlock IsTextSelectionEnabled="True" Name="title" Text="[Video title]" FontSize="25" TextWrapping="WrapWholeWords" HorizontalTextAlignment="Start"/> <StackPanel Margin="0,10">
<Grid> <TextBlock IsTextSelectionEnabled="True" Name="title" Text="[Video title]" FontSize="25" TextWrapping="WrapWholeWords" HorizontalTextAlignment="Start"/>
<Grid.RowDefinitions> <Grid>
<RowDefinition Height="Auto"/> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
</Grid.RowDefinitions> <RowDefinition Height="Auto"/>
<Button Padding="0" Background="Transparent" Margin="5" Name="gotoChannel" Click="gotoChannel_Click"> </Grid.RowDefinitions>
<StackPanel Orientation="Horizontal"> <Button Padding="0" Background="Transparent" Margin="5" Name="gotoChannel" Click="gotoChannel_Click">
<PersonPicture Name="channelAvatar" Width="90"/> <StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical" Grid.Column="1" Padding="5" VerticalAlignment="Center"> <PersonPicture Name="channelAvatar" Width="90"/>
<TextBlock Name="channelName" Text="[Channel name]" FontSize="18"/> <StackPanel Orientation="Vertical" Grid.Column="1" Padding="5" VerticalAlignment="Center">
<TextBlock Name="subscribers" Text="[subscribers]" Foreground="Gray" Margin="0,0,0,5"/> <TextBlock Name="channelName" Text="[Channel name]" FontSize="18"/>
<Button Click="subscribe_Click" Grid.Column="2" Height="30" Width="200" Background="Red" Foreground="White" FontSize="14" FontWeight="SemiBold" Content="Subscirbe" Name="subscribe"/> <TextBlock Name="subscribers" Text="[subscribers]" Foreground="Gray" Margin="0,0,0,5"/>
<Button Click="subscribe_Click" Grid.Column="2" Height="30" Width="200" Background="Red" Foreground="White" FontSize="14" FontWeight="SemiBold" Content="Subscirbe" Name="subscribe"/>
</StackPanel>
</StackPanel> </StackPanel>
</StackPanel> </Button>
</Button> <StackPanel HorizontalAlignment="Stretch" Name="ratingPanel" Grid.Row="1">
<StackPanel HorizontalAlignment="Stretch" Name="ratingPanel" Grid.Row="1"> <TextBlock Name="views" Text="[views]" FontSize="24" Foreground="Gray"/>
<TextBlock Name="views" Text="[views]" FontSize="24" Foreground="Gray"/> <ProgressBar Name="rating" Background="Green" Foreground="Red"/>
<ProgressBar Name="rating" Background="Green" Foreground="Red"/> <Grid>
<Grid> <FontIcon Foreground="Gray"
<FontIcon Foreground="Gray"
HorizontalAlignment="Left" HorizontalAlignment="Left"
FontSize="40" FontSize="40"
Name="dislike" Tapped="dislike_Click" Name="dislike" Tapped="dislike_Click"
Glyph="&#xE19E;"/> Glyph="&#xE19E;"/>
<FontIcon Foreground="Gray" <FontIcon Foreground="Gray"
HorizontalAlignment="Right" HorizontalAlignment="Right"
FontSize="40" FontSize="40"
Name="like" Tapped="like_Click" Name="like" Tapped="like_Click"
Glyph="&#xE19F;"/> Glyph="&#xE19F;"/>
</Grid> </Grid>
<Grid> <Grid>
<TextBlock Foreground="Gray" Text="[dislikes]" Name="dislikes"/> <TextBlock Foreground="Gray" Text="[dislikes]" Name="dislikes"/>
<TextBlock HorizontalAlignment="Right" Foreground="Gray" Text="[likes]" Name="likes"/> <TextBlock HorizontalAlignment="Right" Foreground="Gray" Text="[likes]" Name="likes"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</Grid> </Grid>
<TextBlock Name="description" Text="[Description]" IsTextSelectionEnabled="True" TextWrapping="WrapWholeWords"/> <TextBlock Name="description" Text="[Description]" IsTextSelectionEnabled="True" TextWrapping="WrapWholeWords"/>
<Grid Margin="0,20,0,0"> <Grid Margin="0,20,0,0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/> <ColumnDefinition Width="auto"/>
<ColumnDefinition Width="20"/> <ColumnDefinition Width="20"/>
<ColumnDefinition Width="auto"/> <ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Text="Published at: "/> <TextBlock Text="Published at: "/>
<TextBlock Grid.Row="1" Text="Category: "/> <TextBlock Grid.Row="1" Text="Category: "/>
<TextBlock Grid.Row="2" Text="License: "/> <TextBlock Grid.Row="2" Text="License: "/>
<TextBlock Name="publishedAt" Grid.Column="2" Text="[Publishing date]"/> <TextBlock Name="publishedAt" Grid.Column="2" Text="[Publishing date]"/>
<TextBlock Name="category" Grid.Column="2" Grid.Row="1" Padding="0" Text="[Category]"/> <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]"/> <TextBlock Name="license" Grid.Column="2" Grid.Row="2" Text="[License type]"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</PivotItem>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
<CommandBar VerticalAlignment="Bottom" Name="commandbar"> <CommandBar VerticalAlignment="Bottom" Name="commandbar">
<AppBarButton Icon="Download" Label="Download video" Name="download"> <AppBarButton Icon="Download" Label="Download video" Name="download">
<AppBarButton.Flyout> <AppBarButton.Flyout>
<MenuFlyout x:Name="downloadSelector"> <MenuFlyout x:Name="downloadSelector"/>
<MenuFlyoutItem Text="No items are available" IsEnabled="False"/>
</MenuFlyout>
</AppBarButton.Flyout> </AppBarButton.Flyout>
</AppBarButton> </AppBarButton>
<AppBarButton Label="Add to" Icon="Add" IsEnabled="False"/> <AppBarButton Label="Add to" Icon="Add" IsEnabled="False"/>
+41 -77
View File
@@ -1,36 +1,21 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation; using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; 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;
using Windows.UI.Xaml.Navigation; using Windows.UI.Xaml.Navigation;
using Windows.System; using Windows.System;
using Google.Apis.YouTube.v3.Data; using Google.Apis.YouTube.v3.Data;
using Google.Apis.YouTube.v3; using Google.Apis.YouTube.v3;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
using System.Diagnostics; using System.Diagnostics;
using System.Timers;
using Windows.UI.Core;
using System.Threading;
using Windows.ApplicationModel.DataTransfer; using Windows.ApplicationModel.DataTransfer;
using Windows.Storage; using Windows.Storage;
using Windows.ApplicationModel; using Windows.ApplicationModel;
using Windows.Storage.Streams; using Windows.Storage.Streams;
using Windows.UI.Popups;
using Windows.UI.Text;
using Windows.UI; using Windows.UI;
using FoxTube.Pages;
using MyToolkit.Multimedia;
using FoxTube.Controls; using FoxTube.Controls;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
@@ -63,9 +48,7 @@ namespace FoxTube.Pages
public string videoId; public string videoId;
string playlistId = null; string playlistId = null;
Video item; public Video item;
List<string> downloads = new List<string>();
bool wide; bool wide;
bool isExtended = false; bool isExtended = false;
@@ -92,11 +75,7 @@ namespace FoxTube.Pages
{ {
Debug.WriteLine("Correcting layout..."); Debug.WriteLine("Correcting layout...");
mainContent.Children.Remove(descriptionPanel); mainContent.Children.Remove(descriptionPanel);
pivot.Items.Insert(0, new PivotItem() pivot.Items.Insert(0, descriptionPanel);
{
Content = descriptionPanel,
Header = "Description"
});
tabsPlaceholder.Children.Remove(pivot); tabsPlaceholder.Children.Remove(pivot);
mainContent.Children.Add(pivot); mainContent.Children.Add(pivot);
@@ -256,40 +235,38 @@ namespace FoxTube.Pages
async void LoadDownloads() async void LoadDownloads()
{ {
downloadSelector.Items.Clear(); /*List<YouTubeUri> uris = (await YouTube.GetUrisAsync(item.Id)).ToList();
if (uris.Count > 0)
YouTubeUri[] uris = await YouTube.GetUrisAsync(item.Id);
if (uris.Length > 0)
foreach (YouTubeUri u in uris) foreach (YouTubeUri u in uris)
{ {
if (u.HasAudio && u.HasVideo) if (u.HasAudio && u.HasVideo)
{ {
downloads.Add(u.Uri.AbsoluteUri);
MenuFlyoutItem menuItem = new MenuFlyoutItem() MenuFlyoutItem menuItem = new MenuFlyoutItem()
{ {
Text = Methods.QualityToString(u.VideoQuality) Text = Methods.QualityToString(u.VideoQuality),
Tag = u.Uri.AbsoluteUri
}; };
menuItem.Click += downloadItemSelected; menuItem.Click += downloadItemSelected;
downloadSelector.Items.Add(menuItem); downloadSelector.Items.Add(menuItem);
} }
else if (u.HasAudio) else if (u.HasAudio)
{ {
downloads.Add(u.Uri.AbsoluteUri);
MenuFlyoutItem menuItem = new MenuFlyoutItem() MenuFlyoutItem menuItem = new MenuFlyoutItem()
{ {
Text = Methods.QualityToString(u.AudioQuality) Text = Methods.QualityToString(u.AudioQuality),
Tag = u.Uri.AbsoluteUri
}; };
menuItem.Click += downloadItemSelected; menuItem.Click += downloadItemSelected;
downloadSelector.Items.Add(menuItem); downloadSelector.Items.Add(menuItem);
} }
} }
else else
download.Visibility = Visibility.Collapsed; download.Visibility = Visibility.Collapsed;*/
} }
private void downloadItemSelected(object sender, RoutedEventArgs e) private void downloadItemSelected(object sender, RoutedEventArgs e)
{ {
throw new NotImplementedException(); Methods.MainPage.Agent.Add((sender as MenuFlyoutItem).Tag.ToString());
} }
async void LoadRelatedVideos() async void LoadRelatedVideos()
@@ -360,39 +337,30 @@ namespace FoxTube.Pages
else else
wide = false; wide = false;
if (e.NewSize.Width > 1000 && e.PreviousSize.Width <= 1000 && !isExtended) if (e.NewSize.Width > 1000 && mainContent.Children.Contains(pivot) && !isExtended)
{ {
if (mainContent.Children.Contains(pivot)) mainContent.Children.Remove(pivot);
{ tabsPlaceholder.Children.Add(pivot);
mainContent.Children.Remove(pivot);
tabsPlaceholder.Children.Add(pivot); pivot.Items.RemoveAt(0);
mainContent.Children.Add(descriptionPanel);
(pivot.Items[0] as PivotItem).Content = null;
pivot.Items.RemoveAt(0);
mainContent.Children.Add(descriptionPanel);
}
grid.ColumnDefinitions[1].Width = new GridLength(400); grid.ColumnDefinitions[1].Width = new GridLength(400);
pivot.SelectedIndex = 0;
} }
else if (e.NewSize.Width <= 1000 & e.PreviousSize.Width > 1000) else if (e.NewSize.Width <= 1000 && mainContent.Children.Contains(descriptionPanel))
{ {
if (mainContent.Children.Contains(descriptionPanel)) mainContent.Children.Remove(descriptionPanel);
{ pivot.Items.Insert(0, descriptionPanel);
mainContent.Children.Remove(descriptionPanel);
pivot.Items.Insert(0, new PivotItem() tabsPlaceholder.Children.Remove(pivot);
{ mainContent.Children.Add(pivot);
Content = descriptionPanel,
Header = "Description"
});
tabsPlaceholder.Children.Remove(pivot);
mainContent.Children.Add(pivot);
}
grid.ColumnDefinitions[1].Width = new GridLength(0); grid.ColumnDefinitions[1].Width = new GridLength(0);
}
pivot.SelectedIndex = 0; pivot.SelectedIndex = 0;
}
} }
private async void Share(DataTransferManager sender, DataRequestedEventArgs args) private async void Share(DataTransferManager sender, DataRequestedEventArgs args)
@@ -450,7 +418,7 @@ namespace FoxTube.Pages
dislike.Foreground = new SolidColorBrush(Colors.Red); 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, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0");
rating.Value = (int)((item.Statistics.LikeCount - 1) / (item.Statistics.DislikeCount + item.Statistics.LikeCount) * 100); rating.Value--;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Dislike).ExecuteAsync(); await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Dislike).ExecuteAsync();
userRating = Rating.Dislike; userRating = Rating.Dislike;
@@ -459,7 +427,7 @@ namespace FoxTube.Pages
case Rating.None: case Rating.None:
dislike.Foreground = new SolidColorBrush(Colors.Red); 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, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0");
rating.Value = (int)((item.Statistics.LikeCount) / (item.Statistics.DislikeCount + item.Statistics.LikeCount + 1) * 100); rating.Maximum++;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Dislike).ExecuteAsync(); await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Dislike).ExecuteAsync();
userRating = Rating.Dislike; userRating = Rating.Dislike;
@@ -468,7 +436,7 @@ namespace FoxTube.Pages
case Rating.Dislike: case Rating.Dislike:
dislike.Foreground = new SolidColorBrush(Colors.Gray); 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, System.Globalization.NumberStyles.AllowThousands) - 1).ToString("0,0");
rating.Value = (int)((item.Statistics.LikeCount) / (item.Statistics.DislikeCount + item.Statistics.LikeCount - 1) * 100); rating.Maximum--;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.None).ExecuteAsync(); await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.None).ExecuteAsync();
break; break;
} }
@@ -485,7 +453,7 @@ namespace FoxTube.Pages
like.Foreground = new SolidColorBrush(Colors.Green); 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, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0");
rating.Value = (int)((item.Statistics.LikeCount + 1) / (item.Statistics.DislikeCount + item.Statistics.LikeCount) * 100); rating.Value++;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Like).ExecuteAsync(); await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Like).ExecuteAsync();
userRating = Rating.Like; userRating = Rating.Like;
@@ -494,7 +462,8 @@ namespace FoxTube.Pages
case Rating.None: case Rating.None:
like.Foreground = new SolidColorBrush(Colors.Green); 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, System.Globalization.NumberStyles.AllowThousands) + 1).ToString("0,0");
rating.Value = (int)((item.Statistics.LikeCount + 1) / (item.Statistics.DislikeCount + item.Statistics.LikeCount + 1) * 100); rating.Maximum++;
rating.Value++;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Like).ExecuteAsync(); await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.Like).ExecuteAsync();
userRating = Rating.Like; userRating = Rating.Like;
@@ -503,7 +472,8 @@ namespace FoxTube.Pages
case Rating.Like: case Rating.Like:
like.Foreground = new SolidColorBrush(Colors.Gray); 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, System.Globalization.NumberStyles.AllowThousands) - 1).ToString("0,0");
rating.Value = (int)((item.Statistics.LikeCount - 1) / (item.Statistics.DislikeCount + item.Statistics.LikeCount - 1) * 100); rating.Maximum--;
rating.Value--;
await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.None).ExecuteAsync(); await SecretsVault.Service.Videos.Rate(videoId, VideosResource.RateRequest.RatingEnum.None).ExecuteAsync();
break; break;
} }
@@ -521,23 +491,17 @@ namespace FoxTube.Pages
private async void subscribe_Click(object sender, RoutedEventArgs e) private async void subscribe_Click(object sender, RoutedEventArgs e)
{ {
if (subscribe.Background == new SolidColorBrush(Colors.Red)) if (await SecretsVault.ChangeSubscriptionState(item.Snippet.ChannelId))
{ {
if (await SecretsVault.Subscribe(item.Snippet.ChannelId)) subscribe.Background = new SolidColorBrush(Colors.Transparent);
{ subscribe.Foreground = new SolidColorBrush(Colors.Gray);
subscribe.Background = new SolidColorBrush(Colors.Transparent); subscribe.Content = "Subscribed";
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
subscribe.Content = "Subscribed";
}
} }
else else
{ {
if (await SecretsVault.Unsubscibe(item.Snippet.ChannelId)) subscribe.Background = new SolidColorBrush(Colors.Red);
{ subscribe.Foreground = new SolidColorBrush(Colors.White);
subscribe.Background = new SolidColorBrush(Colors.Red); subscribe.Content = "Subscribe";
subscribe.Foreground = new SolidColorBrush(Colors.White);
subscribe.Content = "Subscribe";
}
} }
} }
} }