DownloadAgent
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using MyToolkit.Multimedia;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
@@ -70,5 +72,40 @@ namespace FoxTube
|
||||
else block.Inlines.Add(new Run { Text = item });
|
||||
}
|
||||
}
|
||||
|
||||
public static string QualityToString(YouTubeQuality quality)
|
||||
{
|
||||
switch(quality)
|
||||
{
|
||||
case YouTubeQuality.NotAvailable:
|
||||
return "N/A";
|
||||
case YouTubeQuality.Quality1080P:
|
||||
return "1080p";
|
||||
case YouTubeQuality.Quality144P:
|
||||
return "144p";
|
||||
case YouTubeQuality.Quality2160P:
|
||||
return "2160p";
|
||||
case YouTubeQuality.Quality240P:
|
||||
return "240p";
|
||||
case YouTubeQuality.Quality270P:
|
||||
return "270p";
|
||||
case YouTubeQuality.Quality360P:
|
||||
return "360p";
|
||||
case YouTubeQuality.Quality480P:
|
||||
return "480p";
|
||||
case YouTubeQuality.Quality520P:
|
||||
return "520p";
|
||||
case YouTubeQuality.Quality720P:
|
||||
return "720p";
|
||||
case YouTubeQuality.QualityHigh:
|
||||
return "[Audio only] High quality";
|
||||
case YouTubeQuality.QualityLow:
|
||||
return "[Audio only] Low quality";
|
||||
case YouTubeQuality.QualityMedium:
|
||||
return "[Audio only] Medium quality";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+143
-16
@@ -3,6 +3,11 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Data.Xml.Dom;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Notifications;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
|
||||
@@ -10,35 +15,157 @@ namespace FoxTube
|
||||
{
|
||||
public enum NotificationType
|
||||
{
|
||||
NewVideo, NewComment, NewPost, Update
|
||||
Video, Comment, Post, Internal
|
||||
}
|
||||
|
||||
public class Notification
|
||||
{
|
||||
public string Header { get; set; }
|
||||
public string message { get; set; }
|
||||
public DateTime time { get; set; }
|
||||
public string Channel { get; set; }
|
||||
public string Content { get; set; }
|
||||
public DateTime TimeStamp { get; set; }
|
||||
public NotificationType Type { get; set; }
|
||||
public string Avatar { get; set; }
|
||||
public string Thumbnail { get; set; }
|
||||
|
||||
public Notification(string header, string content, DateTime date, NotificationType type, string avatar = "ms-appx:///Assets/NewsAvatar.png", string thumbnail = "ms-appx:///Assets/AnnouncementThumb.png")
|
||||
public Notification(NotificationType type,
|
||||
string channelName, string content, DateTime date,
|
||||
string thumbnailUrl, string avatarUrl = "ms-appx:///Assets/Icons/Profile.png")
|
||||
{
|
||||
Header = header;
|
||||
message = content;
|
||||
time = date;
|
||||
Channel = channelName;
|
||||
Content = content;
|
||||
TimeStamp = date;
|
||||
Type = type;
|
||||
Avatar = avatar;
|
||||
Thumbnail = thumbnail;
|
||||
Avatar = avatarUrl;
|
||||
Thumbnail = thumbnailUrl;
|
||||
}
|
||||
|
||||
public string returnTimecode(bool twelveFormat = true)
|
||||
public UIElement GetNotification()
|
||||
{
|
||||
TimeSpan diff = DateTime.Now - time;
|
||||
if (diff.TotalDays == 0)
|
||||
return string.Format("{0}:{1}", time.Hour, time.Minute);
|
||||
else
|
||||
return string.Format("{0}/{1} {2}:{3}", time.Month, time.Day, time.Hour, time.Minute);
|
||||
StackPanel stackPanel = new StackPanel() { Margin = new Thickness(10, 0, 0, 0) };
|
||||
|
||||
//Channel
|
||||
switch (Type)
|
||||
{
|
||||
case NotificationType.Comment:
|
||||
stackPanel.Children.Add(new TextBlock()
|
||||
{
|
||||
FontSize = 14,
|
||||
FontStyle = Windows.UI.Text.FontStyle.Italic,
|
||||
Foreground = new SolidColorBrush(Colors.Gray),
|
||||
Text = string.Format("{0} replied to your comment", Channel)
|
||||
});
|
||||
break;
|
||||
|
||||
case NotificationType.Internal:
|
||||
stackPanel.Children.Add(new TextBlock()
|
||||
{
|
||||
FontSize = 14,
|
||||
FontStyle = Windows.UI.Text.FontStyle.Italic,
|
||||
Foreground = new SolidColorBrush(Colors.Gray),
|
||||
Text = Channel
|
||||
});
|
||||
break;
|
||||
|
||||
case NotificationType.Post:
|
||||
stackPanel.Children.Add(new TextBlock()
|
||||
{
|
||||
FontSize = 14,
|
||||
FontStyle = Windows.UI.Text.FontStyle.Italic,
|
||||
Foreground = new SolidColorBrush(Colors.Gray),
|
||||
Text = string.Format("{0} published new post", Channel)
|
||||
});
|
||||
break;
|
||||
|
||||
case NotificationType.Video:
|
||||
stackPanel.Children.Add(new TextBlock()
|
||||
{
|
||||
FontSize = 14,
|
||||
FontStyle = Windows.UI.Text.FontStyle.Italic,
|
||||
Foreground = new SolidColorBrush(Colors.Gray),
|
||||
Text = string.Format("{0} uploaded new video", Channel)
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
//Content
|
||||
stackPanel.Children.Add(new TextBlock()
|
||||
{
|
||||
TextWrapping = TextWrapping.WrapWholeWords,
|
||||
Text = Content,
|
||||
});
|
||||
//Time
|
||||
stackPanel.Children.Add(new TextBlock()
|
||||
{
|
||||
FontSize = 13,
|
||||
Foreground = new SolidColorBrush(Colors.Gray),
|
||||
Text = TimeStamp.ToString()
|
||||
});
|
||||
PersonPicture avatar = new PersonPicture()
|
||||
{
|
||||
Height = 50,
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
ProfilePicture = string.IsNullOrWhiteSpace(Avatar) ? null : new BitmapImage(new Uri(Avatar))
|
||||
};
|
||||
|
||||
Grid grid = new Grid();
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(50) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition());
|
||||
|
||||
grid.Children.Add(avatar);
|
||||
Grid.SetColumn(stackPanel, 1);
|
||||
grid.Children.Add(stackPanel);
|
||||
|
||||
Button item = new Button()
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
HorizontalContentAlignment = HorizontalAlignment.Left,
|
||||
Background = new SolidColorBrush(Colors.Transparent),
|
||||
Content = grid
|
||||
};
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public ToastNotification GetToast(int assignedId)
|
||||
{
|
||||
System.Xml.XmlDocument template = new System.Xml.XmlDocument();
|
||||
switch(Type)
|
||||
{
|
||||
case NotificationType.Comment:
|
||||
template.Load("ms-appx:///Assets/Notifications/Comment.xml");
|
||||
template["toast"]["visual"]["binding"]["image"].SetAttribute("src", Avatar);
|
||||
template["toast"]["visual"]["binding"].ChildNodes[1].InnerText = string.Format("{0} posted a new comment", Channel);
|
||||
template["toast"]["visual"]["binding"].LastChild.InnerText = Content;
|
||||
break;
|
||||
|
||||
case NotificationType.Video:
|
||||
template.Load("ms-appx:///Assets/Notifications/Video.xml");
|
||||
(template["toast"]["visual"]["binding"].FirstChild as System.Xml.XmlElement).SetAttribute("src", Avatar);
|
||||
template["toast"]["visual"]["binding"].ChildNodes[1].InnerText = string.Format("{0} uploaded a new video", Channel);
|
||||
template["toast"]["visual"]["binding"].ChildNodes[2].InnerText = Content;
|
||||
(template["toast"]["visual"]["binding"].LastChild as System.Xml.XmlElement).SetAttribute("src", Thumbnail);
|
||||
break;
|
||||
|
||||
case NotificationType.Internal:
|
||||
template.Load("ms-appx:///Assets/Notifications/Internal.xml");
|
||||
if(!string.IsNullOrWhiteSpace(Thumbnail))
|
||||
(template["toast"]["visual"]["binding"].FirstChild as System.Xml.XmlElement).SetAttribute("src", Avatar);
|
||||
template["toast"]["visual"]["binding"].LastChild.InnerText = Channel;
|
||||
break;
|
||||
|
||||
case NotificationType.Post:
|
||||
template.Load("ms-appx:///Assets/Notifications/Video.xml");
|
||||
(template["toast"]["visual"]["binding"].FirstChild as System.Xml.XmlElement).SetAttribute("src", Thumbnail);
|
||||
(template["toast"]["visual"]["binding"].ChildNodes[1] as System.Xml.XmlElement).SetAttribute("src", Avatar);
|
||||
template["toast"]["visual"]["binding"].ChildNodes[2].InnerText = string.Format("{0} published a new post", Channel);
|
||||
template["toast"]["visual"]["binding"].ChildNodes[3].InnerText = Content;
|
||||
break;
|
||||
}
|
||||
|
||||
XmlDocument toastXml = new XmlDocument();
|
||||
toastXml.LoadXml(template.InnerXml);
|
||||
|
||||
return new ToastNotification(toastXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public class ObjectEventArgs : EventArgs
|
||||
{
|
||||
public List<object> Parameters = new List<object>();
|
||||
public ObjectEventArgs(params object[] args)
|
||||
{
|
||||
foreach (object a in args)
|
||||
Parameters.Add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,47 +24,50 @@ using Google.Apis.Util.Store;
|
||||
using Google.Apis.YouTube.v3;
|
||||
using Google.Apis.Auth.OAuth2.Responses;
|
||||
using Windows.Storage;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public class SecretsVault
|
||||
{
|
||||
#region Static Information
|
||||
public static NetworkCredential EmailCredential { get => new NetworkCredential("youwillneverknowthisadress@gmail.com", "thisisthepassword12345"); }
|
||||
public static SecretsVault Vault { get => Methods.MainPage.Vault; }
|
||||
public static NetworkCredential EmailCredential => new NetworkCredential("youwillneverknowthisadress@gmail.com", "thisisthepassword12345");
|
||||
private static ClientSecrets Secrets => new ClientSecrets()
|
||||
{
|
||||
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
|
||||
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
|
||||
};
|
||||
|
||||
public static SecretsVault Vault => Methods.MainPage.Vault;
|
||||
|
||||
public static string AccountId => Methods.MainPage.Vault.userId;
|
||||
private static ClientSecrets Secrets
|
||||
{
|
||||
get => new ClientSecrets()
|
||||
{
|
||||
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
|
||||
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
|
||||
};
|
||||
}
|
||||
public static bool IsAuthorized { get => Vault.IsLoged; }
|
||||
public static bool IsAuthorized => Vault.IsLoged;
|
||||
|
||||
public static YouTubeService NoAuthService
|
||||
public static Google.Apis.YouTube.v3.Data.Channel UserChannel => Methods.MainPage.Vault.channel;
|
||||
public static List<KeyValuePair<string, string>> WatchLater => Methods.MainPage.Vault.later;
|
||||
public static List<string> UserHistory => Methods.MainPage.Vault.history;
|
||||
public static List<string> Subscriptions => Methods.MainPage.Vault.subs;
|
||||
|
||||
public static YouTubeService NoAuthService => new YouTubeService(new BaseClientService.Initializer()
|
||||
{
|
||||
get => new YouTubeService(new BaseClientService.Initializer()
|
||||
{
|
||||
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
||||
ApplicationName = "FoxTube"
|
||||
});
|
||||
}
|
||||
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
||||
ApplicationName = "FoxTube"
|
||||
});
|
||||
|
||||
public static YouTubeService Service
|
||||
public static YouTubeService Service => new YouTubeService(new BaseClientService.Initializer()
|
||||
{
|
||||
get => new YouTubeService(new BaseClientService.Initializer()
|
||||
{
|
||||
HttpClientInitializer = Vault.Credential,
|
||||
ApplicationName = "FoxTube"
|
||||
});
|
||||
}
|
||||
HttpClientInitializer = Vault.Credential,
|
||||
ApplicationName = "FoxTube"
|
||||
});
|
||||
#endregion
|
||||
|
||||
#region Object containers
|
||||
public bool IsLoged = false;
|
||||
public string userId;
|
||||
public List<string> history = new List<string>();
|
||||
public List<string> subs = new List<string>();
|
||||
public List<KeyValuePair<string, string>> later = new List<KeyValuePair<string, string>>();
|
||||
public Google.Apis.YouTube.v3.Data.Channel channel;
|
||||
public UserCredential Credential;
|
||||
public event EventHandler AuthorizationStateChanged;
|
||||
|
||||
@@ -78,9 +81,56 @@ namespace FoxTube
|
||||
AuthorizationStateChanged.Invoke(this, null);
|
||||
}
|
||||
|
||||
var request = Service.Channels.List("snippet");
|
||||
var request = Service.Channels.List("snippet,contentDetails");
|
||||
request.Mine = true;
|
||||
userId = (await request.ExecuteAsync()).Items[0].Id;
|
||||
channel = (await request.ExecuteAsync()).Items[0];
|
||||
userId = channel.Id;
|
||||
|
||||
var historyRequest = Service.PlaylistItems.List("snippet");
|
||||
historyRequest.PlaylistId = channel.ContentDetails.RelatedPlaylists.WatchHistory;
|
||||
historyRequest.MaxResults = 50;
|
||||
var response = await historyRequest.ExecuteAsync();
|
||||
history.Clear();
|
||||
foreach (PlaylistItem i in response.Items)
|
||||
history.Add(i.Snippet.ResourceId.VideoId);
|
||||
|
||||
var laterRequest = Service.PlaylistItems.List("snippet");
|
||||
laterRequest.PlaylistId = channel.ContentDetails.RelatedPlaylists.WatchLater;
|
||||
laterRequest.MaxResults = 50;
|
||||
var laterResponse = await laterRequest.ExecuteAsync();
|
||||
later.Clear();
|
||||
|
||||
foreach (PlaylistItem i in laterResponse.Items)
|
||||
later.Add(new KeyValuePair<string, string>(i.Id, i.Snippet.ResourceId.VideoId));
|
||||
|
||||
string nextToken = laterResponse.NextPageToken;
|
||||
while (nextToken != null)
|
||||
{
|
||||
laterRequest.PageToken = nextToken;
|
||||
laterResponse = await laterRequest.ExecuteAsync();
|
||||
foreach (PlaylistItem i in laterResponse.Items)
|
||||
later.Add(new KeyValuePair<string, string>(i.Id, i.Snippet.ResourceId.VideoId));
|
||||
|
||||
nextToken = laterResponse.NextPageToken;
|
||||
}
|
||||
|
||||
SubscriptionsResource.ListRequest subRequest = SecretsVault.Service.Subscriptions.List("snippet");
|
||||
subRequest.Mine = true;
|
||||
subRequest.MaxResults = 50;
|
||||
SubscriptionListResponse subResponse = await subRequest.ExecuteAsync();
|
||||
subs.Clear();
|
||||
|
||||
foreach (Subscription s in subResponse.Items)
|
||||
subs.Add(s.Snippet.ResourceId.ChannelId);
|
||||
|
||||
nextToken = subResponse.NextPageToken;
|
||||
while(nextToken != null)
|
||||
{
|
||||
subRequest.PageToken = nextToken;
|
||||
subResponse = await subRequest.ExecuteAsync();
|
||||
foreach (Subscription s in subResponse.Items)
|
||||
subs.Add(s.Snippet.ResourceId.ChannelId);
|
||||
}
|
||||
}
|
||||
|
||||
public async void Deauthenticate()
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
using MyToolkit.Multimedia;
|
||||
|
||||
namespace FoxTube.Controls
|
||||
{
|
||||
public class DownloadAgent
|
||||
{
|
||||
public List<DownloadItem> Items = new List<DownloadItem>();
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
string path = $@"{Directory.GetCurrentDirectory()}\DownloadHistory.xml";
|
||||
public DownloadAgent()
|
||||
{
|
||||
if (File.Exists(path))
|
||||
doc.Load(path);
|
||||
else
|
||||
{
|
||||
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null));
|
||||
doc.AppendChild(doc.CreateElement("downloads"));
|
||||
doc.Save(path);
|
||||
}
|
||||
|
||||
foreach(XmlElement e in doc["downloads"].ChildNodes)
|
||||
try
|
||||
{
|
||||
Items.Add(new DownloadItem(
|
||||
e["details"]["id"].InnerText,
|
||||
e["title"].InnerText,
|
||||
e["snippet"]["author"].InnerText,
|
||||
e["snippet"]["image"].InnerText,
|
||||
e["snippet"]["duration"].InnerText,
|
||||
e["snippet"]["quality"].InnerText,
|
||||
e["details"]["path"].InnerText));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public void Add(string id, YouTubeQuality quality)
|
||||
{
|
||||
DownloadItem item = new DownloadItem(id, quality);
|
||||
item.DownloadCanceled += Item_DownloadCanceled;
|
||||
item.DownloadComplete += Item_DownloadComplete;
|
||||
|
||||
Items.Add(item);
|
||||
}
|
||||
|
||||
private void Item_DownloadComplete(object sender, EventArgs e)
|
||||
{
|
||||
doc["downloads"].AppendChild((e as ObjectEventArgs).Parameters[0] as XmlElement);
|
||||
}
|
||||
|
||||
private void Item_DownloadCanceled(object sender, EventArgs e)
|
||||
{
|
||||
Items.Remove(sender as DownloadItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<UserControl
|
||||
x:Class="FoxTube.Controls.DownloadItem"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="100"
|
||||
d:DesignWidth="1500">
|
||||
|
||||
<!--<Button HorizontalAlignment="Stretch" Background="WhiteSmoke" Height="100" Padding="0" HorizontalContentAlignment="Stretch"/>-->
|
||||
<Grid Background="WhiteSmoke" Height="100">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Name="thumbnail" Source="/Assets/videoThumbSample.png"/>
|
||||
<TextBlock Name="title" Grid.Column="1" Margin="5" TextWrapping="WrapWholeWords" Text="[Title]" FontSize="20" MaxLines="3"/>
|
||||
|
||||
<StackPanel Grid.Column="2" Margin="5">
|
||||
<TextBlock Text="Extension:" Foreground="Gray"/>
|
||||
<TextBlock Text="Quality:" Foreground="Gray" Name="quality"/>
|
||||
<TextBlock Text="Duration:" Foreground="Gray" Name="duration"/>
|
||||
<TextBlock Text="Author:" Foreground="Gray" Name="channel"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Name="donePanel" Grid.Column="3" Orientation="Horizontal" Visibility="Collapsed">
|
||||
<Button Name="open" Click="open_Click" Width="80" Height="80" Padding="0" Background="Transparent">
|
||||
<StackPanel>
|
||||
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="30" HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="Open" TextWrapping="WrapWholeWords" HorizontalTextAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Name="gotoOriginal" Click="gotoOriginal_Click" Width="80" Height="80" Padding="0" Background="Transparent">
|
||||
<StackPanel>
|
||||
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="30" HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="Go to original" TextWrapping="WrapWholeWords" HorizontalTextAlignment="Center" HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<StackPanel Name="progressPanel" Grid.Column="4" Margin="10">
|
||||
<TextBlock Name="status" Text="Initializing..." HorizontalAlignment="Left"/>
|
||||
<ProgressBar Name="progressBar" Width="200" IsIndeterminate="True" Foreground="Red"/>
|
||||
<TextBlock Name="perc" Text="--%"/>
|
||||
<Button Content="Cancel" Name="cancel" Click="cancel_Click" HorizontalAlignment="Right"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
using System.Net;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
using Windows.System;
|
||||
using MyToolkit.Multimedia;
|
||||
using Windows.Storage;
|
||||
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
|
||||
|
||||
namespace FoxTube.Controls
|
||||
{
|
||||
public sealed partial class DownloadItem : UserControl
|
||||
{
|
||||
string uri;
|
||||
string Id;
|
||||
|
||||
public event EventHandler DownloadCanceled;
|
||||
public event EventHandler DownloadComplete;
|
||||
|
||||
WebClient client = new WebClient();
|
||||
|
||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
||||
public DownloadItem(string id, YouTubeQuality q)
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
client.DownloadFileCompleted += DownloadCompleted;
|
||||
client.DownloadProgressChanged += UpdateInfo;
|
||||
|
||||
try
|
||||
{
|
||||
Download(id, q);
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (client.IsBusy)
|
||||
client.CancelAsync();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
async void Download(string id, YouTubeQuality q)
|
||||
{
|
||||
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%";
|
||||
}
|
||||
|
||||
private void UpdateInfo(object sender, DownloadProgressChangedEventArgs e)
|
||||
{
|
||||
progressBar.Value = e.ProgressPercentage;
|
||||
perc.Text = $"{e.ProgressPercentage}%";
|
||||
}
|
||||
|
||||
private void DownloadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
|
||||
{
|
||||
progressPanel.Visibility = Visibility.Collapsed;
|
||||
donePanel.Visibility = Visibility.Visible;
|
||||
|
||||
XmlElement node = new XmlDocument().CreateElement("item");
|
||||
node.InnerXml = $@"<item>
|
||||
<title{title.Text}></title>
|
||||
<snippet>
|
||||
<quality>{quality.Text.Split(' ')[1]}</quality>
|
||||
<duration>{duration.Text.Split(' ')[1]}</duration>
|
||||
<author>{channel.Text.Split(' ')[1]}</author>
|
||||
</snippet>
|
||||
<details>
|
||||
<path>{uri}</path>
|
||||
<id>{Id}</id>
|
||||
</details>
|
||||
</item>";
|
||||
|
||||
DownloadComplete.Invoke(this, new ObjectEventArgs(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)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(uri))
|
||||
await Launcher.LaunchUriAsync(new Uri(uri));
|
||||
}
|
||||
|
||||
private void gotoOriginal_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Methods.MainPage.GoToVideo(Id);
|
||||
}
|
||||
|
||||
private async void cancel_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if(client.IsBusy)
|
||||
{
|
||||
MessageDialog dialog = new MessageDialog("Are you sure?", "Cancelling download");
|
||||
|
||||
dialog.Commands.Add(new UICommand("Yes", (command) =>
|
||||
{
|
||||
status.Text = "Cancelling...";
|
||||
progressBar.IsIndeterminate = true;
|
||||
cancel.IsEnabled = false;
|
||||
client.CancelAsync();
|
||||
DownloadCanceled.Invoke(this, null);
|
||||
}));
|
||||
dialog.Commands.Add(new UICommand("No"));
|
||||
|
||||
dialog.DefaultCommandIndex = 1;
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,11 @@
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0" Background="Black">
|
||||
<Image Name="thumbnail" Source="Assets/videoThumbSample.png" Stretch="Fill"/>
|
||||
<Grid Background="#7FFFFFFF" Name="watched" Visibility="Collapsed">
|
||||
<StackPanel Margin="5" Background="WhiteSmoke" VerticalAlignment="Top" HorizontalAlignment="Left" Padding="5,2,5,2" BorderBrush="Gray" BorderThickness="1">
|
||||
<TextBlock Text="Watched" Foreground="Gray" FontSize="12"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<StackPanel Margin="0,0,5,5" Background="WhiteSmoke" VerticalAlignment="Bottom" HorizontalAlignment="Right" Padding="5,2,5,0" Height="20">
|
||||
<TextBlock Name="info" Text="[Duration] | [Published at]" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Gray" FontSize="12"/>
|
||||
</StackPanel>
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace FoxTube
|
||||
views.Text = string.Format("{0} views", item.Statistics.ViewCount);
|
||||
|
||||
string duration;
|
||||
if (item.ContentDetails.Duration != null || item.ContentDetails.Duration != "")
|
||||
if (!string.IsNullOrWhiteSpace(item.ContentDetails.Duration))
|
||||
{
|
||||
TimeSpan ts = XmlConvert.ToTimeSpan(item.ContentDetails.Duration);
|
||||
duration = string.Format("{0}{1:00}:{2:00} | ", ts.Hours == 0 ? "" : ts.Hours + ":", ts.Minutes, ts.Seconds);
|
||||
@@ -94,6 +94,9 @@ namespace FoxTube
|
||||
|
||||
avatar.ProfilePicture = new BitmapImage(new Uri(item1.Snippet.Thumbnails.Medium.Url));
|
||||
channelName.Text = item1.Snippet.Title;
|
||||
|
||||
if (SecretsVault.UserHistory.Contains(item.Id))
|
||||
watched.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private async void Button_Click(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -11,7 +11,14 @@
|
||||
|
||||
<Button Padding="0" Background="WhiteSmoke" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Margin="2" Click="Button_Click">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Name="thumbnail" Source="Assets/videoThumbSample.png"/>
|
||||
<Grid>
|
||||
<Image Name="thumbnail" Source="Assets/videoThumbSample.png"/>
|
||||
<Grid Background="#7FFFFFFF" Name="watched" Visibility="Collapsed">
|
||||
<StackPanel Margin="5" Background="WhiteSmoke" VerticalAlignment="Top" HorizontalAlignment="Left" Padding="5,2,5,2" BorderBrush="Gray" BorderThickness="1">
|
||||
<TextBlock Text="Watched" Foreground="Gray" FontSize="12"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Margin="10" HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
|
||||
@@ -91,6 +91,9 @@ namespace FoxTube
|
||||
avatar.ProfilePicture = new BitmapImage(new Uri(item1.Snippet.Thumbnails.Medium.Url));
|
||||
channelName.Text = item1.Snippet.Title;
|
||||
channelSubs.Text = string.Format("{0} subscribers", item1.Statistics.SubscriberCount);
|
||||
|
||||
if (SecretsVault.UserHistory.Contains(item.Id))
|
||||
watched.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void channelLink_Click(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -97,9 +97,14 @@
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Classes\Methods.cs" />
|
||||
<Compile Include="Classes\ObjectEventArgs.cs" />
|
||||
<Compile Include="Controls\CommentCard.xaml.cs">
|
||||
<DependentUpon>CommentCard.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\DownloadAgent.cs" />
|
||||
<Compile Include="Controls\DownloadItem.xaml.cs">
|
||||
<DependentUpon>DownloadItem.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\SuggestionsQueries.xaml.cs">
|
||||
<DependentUpon>SuggestionsQueries.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -112,6 +117,9 @@
|
||||
<Compile Include="Pages\CommentsPage.xaml.cs">
|
||||
<DependentUpon>CommentsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\Downloads.xaml.cs">
|
||||
<DependentUpon>Downloads.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\Feedback.xaml.cs">
|
||||
<DependentUpon>Feedback.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -173,6 +181,8 @@
|
||||
<Content Include="Assets\AnnouncementThumb.png" />
|
||||
<Content Include="Assets\ChannelCoverTemplate.png" />
|
||||
<Content Include="Assets\FoxGame.png" />
|
||||
<Content Include="Assets\Icons\Profile.png" />
|
||||
<Content Include="Assets\Icons\Send.png" />
|
||||
<Content Include="Assets\LargeTile.scale-100.png" />
|
||||
<Content Include="Assets\LargeTile.scale-125.png" />
|
||||
<Content Include="Assets\LargeTile.scale-150.png" />
|
||||
@@ -217,6 +227,24 @@
|
||||
<Content Include="Assets\Wide310x150Logo.scale-125.png" />
|
||||
<Content Include="Assets\Wide310x150Logo.scale-150.png" />
|
||||
<Content Include="Assets\Wide310x150Logo.scale-400.png" />
|
||||
<Content Include="Notifications\Comment.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Notifications\Download.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Notifications\DownloadComplete.xml" />
|
||||
<Content Include="Notifications\downloadHistorySample.xml" />
|
||||
<Content Include="Notifications\Internal.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Notifications\Post.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Notifications\ServerLogSamlpe.xml" />
|
||||
<Content Include="Notifications\Video.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Properties\Default.rd.xml" />
|
||||
<Content Include="Assets\LockScreenLogo.scale-200.png" />
|
||||
<Content Include="Assets\SplashScreen.scale-200.png" />
|
||||
@@ -234,6 +262,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\DownloadItem.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\SuggestionsQueries.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -250,6 +282,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\Downloads.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\Feedback.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -343,6 +379,9 @@
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls">
|
||||
<Version>3.0.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MyToolkit">
|
||||
<Version>2.5.16</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MyToolkit.Extended">
|
||||
<Version>2.5.16</Version>
|
||||
</PackageReference>
|
||||
@@ -353,6 +392,12 @@
|
||||
<ItemGroup>
|
||||
<None Include="FoxTube_TemporaryKey.pfx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FoxTube.Background\FoxTube.Background.csproj">
|
||||
<Project>{fc9128d7-e3aa-48ed-8641-629794b88b28}</Project>
|
||||
<Name>FoxTube.Background</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<toast launch="action=openThread&threadId=92187">
|
||||
<visual>
|
||||
<binding template="ToastGeneric">
|
||||
<image placement="appLogoOverride" hint-crop="circle" src="Assets/Icons/Profile.png"/>
|
||||
<text>[ChannelName] posted a new comment</text>
|
||||
<text>[VideoName]</text>
|
||||
</binding>
|
||||
</visual>
|
||||
|
||||
<actions>
|
||||
<input id="textBox" type="text" placeHolderContent="Send a reply"/>
|
||||
|
||||
<action content="Send" imageUri="Assets/Icons/Send.png"
|
||||
hint-inputId="textBox" activationType="background"
|
||||
arguments="action=reply&threadId=92187"/>
|
||||
|
||||
<action content="Like"
|
||||
arguments="action=commentPhoto&photoId=92187"/>
|
||||
<action content="Go to comment"
|
||||
arguments="action=commentPhoto&photoId=92187"/>
|
||||
</actions>
|
||||
</toast>
|
||||
@@ -0,0 +1 @@
|
||||
<toast launch="action=viewPhoto&photoId=92187">
|
||||
@@ -0,0 +1 @@
|
||||
<toast launch="action=viewPhoto&photoId=92187">
|
||||
@@ -0,0 +1 @@
|
||||
<toast launch="action=openThread&threadId=92187">
|
||||
@@ -0,0 +1 @@
|
||||
<toast launch="action=openThread&threadId=92187">
|
||||
@@ -0,0 +1,7 @@
|
||||
<posts>
|
||||
<post time="YYYY-MM-DDThh:mm:ss-03" image="http://foxtube.hol.es/foxtube/FILE_NAME.png Hero image (not implemented yet)">
|
||||
<notificationHeader>Short headline for toast notifications</notificationHeader>
|
||||
<header>Main headline for full post</header>
|
||||
<content>Announcement body (beware of special characters)</content>
|
||||
</post>
|
||||
</posts>
|
||||
@@ -0,0 +1 @@
|
||||
<toast launch="action=viewPhoto&photoId=92187">
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<downloads>
|
||||
<item>
|
||||
<title></title>
|
||||
<snippet>
|
||||
<quality></quality>
|
||||
<duration></duration>
|
||||
<author></author>
|
||||
<image></image>
|
||||
</snippet>
|
||||
<details>
|
||||
<path></path>
|
||||
<id></id>
|
||||
</details>
|
||||
</item>
|
||||
</downloads>
|
||||
@@ -0,0 +1,33 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Pages.Downloads"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube.Pages"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid Padding="5">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="28" Text="Downloads"/>
|
||||
<Grid VerticalAlignment="Top">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Name="openFolder" Click="openFolder_Click" Content="Open folder" Margin="5"/>
|
||||
<TextBlock Name="path" IsTextSelectionEnabled="True" Grid.Column="1" Text="C://Users/Admin/Downloads" VerticalAlignment="Center"/>
|
||||
<Button Name="changePath" Click="changePath_Click" Grid.Column="2" Content="Change path" Margin="5"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<StackPanel Margin="5" Name="stack"/>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,58 @@
|
||||
using FoxTube.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
namespace FoxTube.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class Downloads : Page
|
||||
{
|
||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
||||
public Downloads()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
path.Text = settings.Values["defaultDownload"] as string;
|
||||
|
||||
foreach (DownloadItem item in Methods.MainPage.Agent.Items)
|
||||
stack.Children.Add(item);
|
||||
}
|
||||
|
||||
private async void changePath_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
FolderPicker picker = new FolderPicker()
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.Desktop,
|
||||
ViewMode = PickerViewMode.Thumbnail
|
||||
};
|
||||
|
||||
StorageFolder p = await picker.PickSingleFolderAsync();
|
||||
if (p != null)
|
||||
settings.Values["defaultDownload"] = p.Path;
|
||||
path.Text = settings.Values["defaultDownload"] as string;
|
||||
}
|
||||
|
||||
private async void openFolder_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await Launcher.LaunchUriAsync(new Uri(settings.Values["defaultDownload"] as string));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ namespace FoxTube
|
||||
public sealed partial class MainPage : Page
|
||||
{
|
||||
public SecretsVault Vault = new SecretsVault();
|
||||
public DownloadAgent Agent = new DownloadAgent();
|
||||
|
||||
RightPaneState paneState = RightPaneState.Full;
|
||||
bool isForcedCollapsed = false;
|
||||
@@ -95,6 +96,9 @@ namespace FoxTube
|
||||
if (settings.Values["safeSearch"] == null)
|
||||
settings.Values.Add("safeSearch", 0);
|
||||
|
||||
if (settings.Values["defaultDownload"] == null)
|
||||
settings.Values.Add("defaultDownload", Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\DownloadedVideos");
|
||||
|
||||
content.Navigate(typeof(Home));
|
||||
|
||||
Vault.AuthorizationStateChanged += Vault_AuthorizationStateChanged;
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace FoxTube
|
||||
}
|
||||
catch
|
||||
{
|
||||
MessageDialog message = new MessageDialog("We was unable to send your feedback due to connection problems or internal server error. Please, try again later.", "Failed to send your feedback");
|
||||
MessageDialog message = new MessageDialog("We were unable to send your feedback due to connection problems or internal server error. Please, try again later.", "Failed to send your feedback");
|
||||
await message.ShowAsync();
|
||||
export.IsEnabled = true;
|
||||
upload.IsEnabled = true;
|
||||
|
||||
@@ -87,20 +87,26 @@
|
||||
<CommandBar VerticalAlignment="Bottom" Name="commandbar">
|
||||
<AppBarButton Name="download" Icon="Download" Label="Download video">
|
||||
<AppBarButton.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyout x:Name="downloadSelector">
|
||||
<MenuFlyoutItem Text="Select quality:" IsEnabled="False"/>
|
||||
<MenuFlyoutSeparator/>
|
||||
<MenuFlyoutItem Text="No items are available" IsEnabled="False"/>
|
||||
</MenuFlyout>
|
||||
</AppBarButton.Flyout>
|
||||
</AppBarButton>
|
||||
<AppBarToggleButton Name="addLater" Icon="Clock" Label="Watch later" Visibility="Collapsed"/>
|
||||
<AppBarToggleButton Name="addLater" Click="addLater_Click" Icon="Clock" Label="Watch later" Visibility="Collapsed"/>
|
||||
<AppBarButton Name="refresh" Click="refresh_Click" Icon="Refresh" Label="Refresh page"/>
|
||||
<AppBarButton Name="share" Click="share_Click" Icon="Share" Label="Share"/>
|
||||
<AppBarButton Name="openBrowser" Click="openBrowser_Click" Icon="Globe" Label="Open in browser"/>
|
||||
|
||||
<CommandBar.SecondaryCommands>
|
||||
<AppBarButton Name="addToPlaylist" Icon="Add" Label="Add to playlist" Visibility="Collapsed"/>
|
||||
<AppBarButton Name="addToPlaylist" Click="addToPlaylist_Click" Icon="Add" Label="Add to playlist" Visibility="Collapsed">
|
||||
<AppBarButton.Flyout>
|
||||
<MenuFlyout>
|
||||
|
||||
</MenuFlyout>
|
||||
</AppBarButton.Flyout>
|
||||
</AppBarButton>
|
||||
<AppBarButton Icon="Flag" Label="Report this video" Visibility="Collapsed"/>
|
||||
</CommandBar.SecondaryCommands>
|
||||
</CommandBar>
|
||||
|
||||
+112
-5
@@ -30,6 +30,8 @@ using Windows.UI.Text;
|
||||
using Windows.UI;
|
||||
using FoxTube.Pages;
|
||||
|
||||
using MyToolkit.Multimedia;
|
||||
|
||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
namespace FoxTube
|
||||
@@ -41,11 +43,16 @@ namespace FoxTube
|
||||
/// </summary>
|
||||
public sealed partial class Video : Page
|
||||
{
|
||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
||||
|
||||
string videoId;
|
||||
Google.Apis.YouTube.v3.Data.Video item;
|
||||
|
||||
List<string> downloads = new List<string>();
|
||||
|
||||
bool wide;
|
||||
bool isExtended = false;
|
||||
bool isAddedToLater = false;
|
||||
|
||||
Rating userRating = Rating.None;
|
||||
|
||||
@@ -82,6 +89,7 @@ namespace FoxTube
|
||||
grid.ColumnDefinitions[1].Width = new GridLength(0);
|
||||
|
||||
pivot.SelectedIndex = 0;
|
||||
pivot_SelectionChanged(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +150,8 @@ namespace FoxTube
|
||||
|
||||
channelAvatar.ProfilePicture = new BitmapImage(new Uri(item1.Snippet.Thumbnails.Medium.Url));
|
||||
channelName.Text = item.Snippet.ChannelTitle;
|
||||
subscribers.Text = item1.Statistics.SubscriberCount + " subscribers";
|
||||
subscribers.Text = string.Format("{0:0,0} subscribers", item1.Statistics.SubscriberCount);
|
||||
|
||||
|
||||
if(SecretsVault.IsAuthorized)
|
||||
{
|
||||
@@ -157,6 +166,15 @@ namespace FoxTube
|
||||
userRating = Rating.Dislike;
|
||||
dislike.Foreground = new SolidColorBrush(Colors.Red);
|
||||
}
|
||||
|
||||
/*addLater.Visibility = Visibility.Visible;
|
||||
addToPlaylist.Visibility = Visibility.Visible;
|
||||
|
||||
if (SecretsVault.WatchLater.Contains(item.Id))
|
||||
{
|
||||
isAddedToLater = true;
|
||||
addLater.IsChecked = true;
|
||||
}*/
|
||||
}
|
||||
|
||||
player = new VideoPlayer(item, item1.Snippet.Thumbnails.Medium.Url);
|
||||
@@ -164,11 +182,30 @@ namespace FoxTube
|
||||
|
||||
playerPlaceholder.Children.Add(player);
|
||||
|
||||
LoadDownloads();
|
||||
|
||||
Thread.Sleep(1000);
|
||||
grid.Visibility = Visibility.Visible;
|
||||
LoadingScreen.Visibility = Visibility.Collapsed;
|
||||
|
||||
LoadRelatedVideos();
|
||||
|
||||
if (SecretsVault.IsAuthorized && SecretsVault.UserHistory[0] != item.Id)
|
||||
{
|
||||
await SecretsVault.Service.PlaylistItems.Insert(new PlaylistItem()
|
||||
{
|
||||
Snippet = new PlaylistItemSnippet()
|
||||
{
|
||||
ResourceId = new ResourceId()
|
||||
{
|
||||
Kind = "youtube#video",
|
||||
VideoId = item.Id
|
||||
},
|
||||
PlaylistId = SecretsVault.UserChannel.ContentDetails.RelatedPlaylists.WatchHistory
|
||||
}
|
||||
}, "snippet").ExecuteAsync();
|
||||
SecretsVault.UserHistory.Insert(0, item.Id);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -176,6 +213,46 @@ namespace FoxTube
|
||||
}
|
||||
}
|
||||
|
||||
async void LoadDownloads()
|
||||
{
|
||||
Debug.WriteLine("Loading download options...");
|
||||
downloadSelector.Items.Clear();
|
||||
|
||||
YouTubeUri[] uris = await YouTube.GetUrisAsync(item.Id);
|
||||
if (uris.Length > 0)
|
||||
foreach (YouTubeUri u in uris)
|
||||
{
|
||||
if (u.HasAudio && u.HasVideo)
|
||||
{
|
||||
downloads.Add(u.Uri.AbsoluteUri);
|
||||
MenuFlyoutItem menuItem = new MenuFlyoutItem()
|
||||
{
|
||||
Text = Methods.QualityToString(u.VideoQuality)
|
||||
};
|
||||
menuItem.Click += downloadItemSelected;
|
||||
downloadSelector.Items.Add(menuItem);
|
||||
}
|
||||
else if (u.HasAudio)
|
||||
{
|
||||
downloads.Add(u.Uri.AbsoluteUri);
|
||||
MenuFlyoutItem menuItem = new MenuFlyoutItem()
|
||||
{
|
||||
Text = Methods.QualityToString(u.AudioQuality)
|
||||
};
|
||||
menuItem.Click += downloadItemSelected;
|
||||
downloadSelector.Items.Add(menuItem);
|
||||
}
|
||||
}
|
||||
else
|
||||
download.Visibility = Visibility.Collapsed;
|
||||
Debug.WriteLine("Done");
|
||||
}
|
||||
|
||||
private void downloadItemSelected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
async void LoadRelatedVideos()
|
||||
{
|
||||
loadingRelated.Refresh();
|
||||
@@ -183,6 +260,7 @@ namespace FoxTube
|
||||
|
||||
SearchResource.ListRequest request = SecretsVault.IsAuthorized? SecretsVault.Service.Search.List("snippet") : SecretsVault.NoAuthService.Search.List("snippet");
|
||||
request.RelatedToVideoId = videoId;
|
||||
request.SafeSearch = (SearchResource.ListRequest.SafeSearchEnum)(int)settings.Values["safeSearch"];
|
||||
request.MaxResults = 20;
|
||||
request.Type = "video";
|
||||
|
||||
@@ -297,8 +375,6 @@ namespace FoxTube
|
||||
|
||||
toDescription.Visibility = Visibility.Collapsed;
|
||||
grid.ColumnDefinitions[1].Width = new GridLength(400);
|
||||
|
||||
pivot.SelectedIndex = 0;
|
||||
}
|
||||
else if (e.NewSize.Width <= 1000 & e.PreviousSize.Width > 1000)
|
||||
{
|
||||
@@ -317,9 +393,10 @@ namespace FoxTube
|
||||
|
||||
toDescription.Visibility = Visibility.Visible;
|
||||
grid.ColumnDefinitions[1].Width = new GridLength(0);
|
||||
|
||||
pivot.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
pivot.SelectedIndex = 0;
|
||||
pivot_SelectionChanged(this, null);
|
||||
}
|
||||
|
||||
private void toDescription_Click(object sender, RoutedEventArgs e)
|
||||
@@ -500,5 +577,35 @@ namespace FoxTube
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async void addLater_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
isAddedToLater = !isAddedToLater;
|
||||
if(isAddedToLater)
|
||||
{
|
||||
PlaylistItem pi = await SecretsVault.Service.PlaylistItems.Insert(new PlaylistItem()
|
||||
{
|
||||
Snippet = new PlaylistItemSnippet()
|
||||
{
|
||||
ResourceId = new ResourceId()
|
||||
{
|
||||
Kind = "youtube#video",
|
||||
VideoId = item.Id
|
||||
},
|
||||
PlaylistId = SecretsVault.UserChannel.ContentDetails.RelatedPlaylists.WatchLater
|
||||
}
|
||||
}, "snippet").ExecuteAsync();
|
||||
SecretsVault.WatchLater.Insert(0, new KeyValuePair<string, string>(pi.Id, item.Id));
|
||||
}
|
||||
else
|
||||
{
|
||||
//await SecretsVault.Service.PlaylistItems.Delete(SecretsVault.WatchLater[])
|
||||
}
|
||||
}
|
||||
|
||||
private void addToPlaylist_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user