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:
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
{
|
|
||||||
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null));
|
|
||||||
doc.AppendChild(doc.CreateElement("downloads"));
|
|
||||||
settings.Values.Add("downloadHistory", doc.InnerXml);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(XmlElement e in doc["downloads"].ChildNodes)
|
public async void Initialize()
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Items.Add(new DownloadItem(
|
List<DownloadItemContainer> containers = JsonConvert.DeserializeObject<List<DownloadItemContainer>>(await FileIO.ReadTextAsync(await roaming.GetFileAsync("data.json")));
|
||||||
e["details"]["id"].InnerText,
|
|
||||||
e["title"].InnerText,
|
foreach (DownloadItemContainer i in containers)
|
||||||
e["snippet"]["author"].InnerText,
|
try { items.Add(new DownloadItem(i)); }
|
||||||
e["snippet"]["image"].InnerText,
|
catch (FileNotFoundException) { }
|
||||||
e["snippet"]["duration"].InnerText,
|
|
||||||
e["snippet"]["quality"].InnerText,
|
|
||||||
e["details"]["path"].InnerText));
|
|
||||||
}
|
}
|
||||||
catch { }
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -91,18 +91,13 @@ 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.Background = new SolidColorBrush(Colors.Transparent);
|
||||||
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
|
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
|
||||||
subscribe.Content = "Subscribed";
|
subscribe.Content = "Subscribed";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if (await SecretsVault.Unsubscibe(channelId))
|
|
||||||
{
|
{
|
||||||
subscribe.Background = new SolidColorBrush(Colors.Red);
|
subscribe.Background = new SolidColorBrush(Colors.Red);
|
||||||
subscribe.Foreground = new SolidColorBrush(Colors.White);
|
subscribe.Foreground = new SolidColorBrush(Colors.White);
|
||||||
@@ -111,4 +106,3 @@ namespace FoxTube.Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -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="" FontSize="20"/>
|
FontFamily="Segoe MDL2 Assets" Text="" 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="" />
|
Content="" />
|
||||||
<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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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="" FontFamily="Segoe MDL2 Assets" FontSize="30" HorizontalAlignment="Center"/>
|
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="30" HorizontalAlignment="Center"/>
|
||||||
|
|||||||
@@ -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 event ObjectEventHandler DownloadCanceled;
|
public DownloadItem(string url)
|
||||||
public event ObjectEventHandler DownloadComplete;
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
Download(url);
|
||||||
|
}
|
||||||
|
|
||||||
WebClient client = new WebClient();
|
public DownloadItem(DownloadItemContainer container)
|
||||||
|
|
||||||
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))
|
||||||
}
|
|
||||||
|
|
||||||
async void Download(string id, YouTubeQuality q)
|
|
||||||
{
|
|
||||||
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();
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Download(string url)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,6 +39,7 @@ namespace FoxTube.Controls
|
|||||||
TimeSpan currentPosition = Player.Position;
|
TimeSpan currentPosition = Player.Position;
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
if(!isClosed)
|
||||||
captions.ForEach((x) =>
|
captions.ForEach((x) =>
|
||||||
{
|
{
|
||||||
if (Player.Position >= x.Start && Player.Position <= x.End)
|
if (Player.Position >= x.Start && Player.Position <= x.End)
|
||||||
@@ -56,13 +58,18 @@ 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);
|
||||||
|
|
||||||
|
if (!isAutoGenerated)
|
||||||
foreach (XmlElement i in doc["timedtext"]["body"].ChildNodes)
|
foreach (XmlElement i in doc["timedtext"]["body"].ChildNodes)
|
||||||
captions.Add(new Caption(int.Parse(i.GetAttribute("t")), int.Parse(i.GetAttribute("d")), i.InnerText));
|
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("'", "'")));
|
||||||
|
|
||||||
captions.ForEach((x) =>
|
captions.ForEach((x) =>
|
||||||
{
|
{
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Video quality">
|
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" 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>
|
||||||
|
|||||||
@@ -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)
|
||||||
break;
|
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;
|
||||||
|
}*/
|
||||||
|
|
||||||
needUpdateTimecode = true;
|
needUpdateTimecode = true;
|
||||||
videoSource.Play();
|
videoSource.Play();
|
||||||
@@ -367,7 +475,9 @@ namespace FoxTube
|
|||||||
{
|
{
|
||||||
if (subsSwitch.IsOn)
|
if (subsSwitch.IsOn)
|
||||||
{
|
{
|
||||||
|
if (ccInfo[subsLang.SelectedIndex].IsAutoGenerated)
|
||||||
|
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url.Replace("format=3", "format=0"), true);
|
||||||
|
else
|
||||||
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url);
|
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -399,9 +509,47 @@ 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)
|
||||||
|
if((audioReady && videoReady) || isMuxed)
|
||||||
videoSource.Play();
|
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)
|
||||||
{
|
{
|
||||||
if(videoSource.CurrentState == MediaElementState.Playing && needUpdateTimecode)
|
if(videoSource.CurrentState == MediaElementState.Playing && needUpdateTimecode)
|
||||||
@@ -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
@@ -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>
|
||||||
|
|||||||
@@ -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,25 +250,19 @@ 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.Background = new SolidColorBrush(Colors.Transparent);
|
||||||
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
|
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
|
||||||
subscribe.Content = "Subscribed";
|
subscribe.Content = "Subscribed";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if (await SecretsVault.Unsubscibe(channelId))
|
|
||||||
{
|
{
|
||||||
subscribe.Background = new SolidColorBrush(Colors.Red);
|
subscribe.Background = new SolidColorBrush(Colors.Red);
|
||||||
subscribe.Foreground = new SolidColorBrush(Colors.White);
|
subscribe.Foreground = new SolidColorBrush(Colors.White);
|
||||||
subscribe.Content = "Subscribe";
|
subscribe.Content = "Subscribe";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void Hyperlink_Click(Windows.UI.Xaml.Documents.Hyperlink sender, Windows.UI.Xaml.Documents.HyperlinkClickEventArgs args)
|
private void Hyperlink_Click(Windows.UI.Xaml.Documents.Hyperlink sender, Windows.UI.Xaml.Documents.HyperlinkClickEventArgs args)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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=""
|
FontFamily="Segoe MDL2 Assets" Content=""
|
||||||
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=""
|
FontFamily="Segoe MDL2 Assets" Content=""
|
||||||
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>
|
||||||
|
|||||||
@@ -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,17 +297,22 @@ 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)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Video id: {id}; Playlist id: {playlistId}");
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var connection = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();
|
var connection = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();
|
||||||
if ((bool)settings.Values["moblieWarning"] && (connection.NetworkCostType == NetworkCostType.Fixed || connection.NetworkCostType == NetworkCostType.Variable))
|
if ((bool)settings.Values["moblieWarning"] && (connection.NetworkCostType == NetworkCostType.Fixed || connection.NetworkCostType == NetworkCostType.Variable))
|
||||||
@@ -340,6 +335,8 @@ namespace FoxTube
|
|||||||
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);
|
||||||
}
|
}
|
||||||
@@ -369,10 +367,18 @@ namespace FoxTube
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void MinimizeAsInitializer()
|
public void MinimizeAsInitializer()
|
||||||
|
{
|
||||||
|
if(videoPlaceholder.Content != null)
|
||||||
|
{
|
||||||
|
if ((videoPlaceholder.Content as VideoPage).loading.State != LoadingState.Loaded)
|
||||||
|
CloseVideo();
|
||||||
|
else
|
||||||
{
|
{
|
||||||
try { (videoPlaceholder.Content as VideoPage).player.minimize_Click(this, null); }
|
try { (videoPlaceholder.Content as VideoPage).player.minimize_Click(this, null); }
|
||||||
catch { }
|
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,6 +444,7 @@ namespace FoxTube
|
|||||||
|
|
||||||
private void search_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
|
private void search_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
|
||||||
{
|
{
|
||||||
|
if(!string.IsNullOrWhiteSpace(search.Text))
|
||||||
GoToSearch(new SearchParameters(search.Text));
|
GoToSearch(new SearchParameters(search.Text));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,9 +535,16 @@ namespace FoxTube
|
|||||||
} },
|
} },
|
||||||
{ typeof(ChannelPage), () =>
|
{ typeof(ChannelPage), () =>
|
||||||
{
|
{
|
||||||
|
if(sender.GetType() != typeof(ChannelPage))
|
||||||
|
{
|
||||||
|
Methods.NeedToResponse = true;
|
||||||
|
s = Sender.None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Methods.NeedToResponse = false;
|
||||||
if(SecretsVault.IsAuthorized)
|
if(SecretsVault.IsAuthorized)
|
||||||
{
|
{
|
||||||
if((content.Content as ChannelPage).channelId == SecretsVault.AccountId)
|
if((content.Content as ChannelPage).channelId == SecretsVault.UserChannel.Id)
|
||||||
{
|
{
|
||||||
if(nav.SelectedItem != toChannel)
|
if(nav.SelectedItem != toChannel)
|
||||||
nav.SelectedItem = toChannel;
|
nav.SelectedItem = toChannel;
|
||||||
@@ -551,14 +566,23 @@ namespace FoxTube
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!found)
|
if(!found)
|
||||||
|
{
|
||||||
nav.SelectedItem = null;
|
nav.SelectedItem = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
nav.SelectedItem = null;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,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"
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -244,7 +242,7 @@ namespace FoxTube
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/>
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"/>
|
||||||
|
|||||||
@@ -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"/>
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,8 @@
|
|||||||
<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">
|
||||||
|
<StackPanel Margin="0,10">
|
||||||
<TextBlock IsTextSelectionEnabled="True" Name="title" Text="[Video title]" FontSize="25" TextWrapping="WrapWholeWords" HorizontalTextAlignment="Start"/>
|
<TextBlock IsTextSelectionEnabled="True" Name="title" Text="[Video title]" FontSize="25" TextWrapping="WrapWholeWords" HorizontalTextAlignment="Start"/>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
@@ -95,15 +96,14 @@
|
|||||||
<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"/>
|
||||||
|
|||||||
@@ -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,40 +337,31 @@ 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);
|
mainContent.Children.Remove(pivot);
|
||||||
tabsPlaceholder.Children.Add(pivot);
|
tabsPlaceholder.Children.Add(pivot);
|
||||||
|
|
||||||
(pivot.Items[0] as PivotItem).Content = null;
|
|
||||||
pivot.Items.RemoveAt(0);
|
pivot.Items.RemoveAt(0);
|
||||||
mainContent.Children.Add(descriptionPanel);
|
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);
|
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);
|
||||||
}
|
|
||||||
|
|
||||||
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,18 +491,13 @@ 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.Background = new SolidColorBrush(Colors.Transparent);
|
||||||
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
|
subscribe.Foreground = new SolidColorBrush(Colors.Gray);
|
||||||
subscribe.Content = "Subscribed";
|
subscribe.Content = "Subscribed";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if (await SecretsVault.Unsubscibe(item.Snippet.ChannelId))
|
|
||||||
{
|
{
|
||||||
subscribe.Background = new SolidColorBrush(Colors.Red);
|
subscribe.Background = new SolidColorBrush(Colors.Red);
|
||||||
subscribe.Foreground = new SolidColorBrush(Colors.White);
|
subscribe.Foreground = new SolidColorBrush(Colors.White);
|
||||||
@@ -541,4 +506,3 @@ namespace FoxTube.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user