Version 0.2.181224
@@ -1,13 +1,10 @@
|
|||||||
using Google.Apis.Auth.OAuth2;
|
using Google.Apis.Services;
|
||||||
using Google.Apis.Services;
|
|
||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using Windows.ApplicationModel.Background;
|
using Windows.ApplicationModel.Background;
|
||||||
@@ -16,141 +13,98 @@ using Windows.UI.Notifications;
|
|||||||
|
|
||||||
namespace FoxTube.Background
|
namespace FoxTube.Background
|
||||||
{
|
{
|
||||||
public delegate void NotificationHandler(object sender, Notification item);
|
|
||||||
|
|
||||||
public sealed class BackgroundProcessor : IBackgroundTask
|
public sealed class BackgroundProcessor : IBackgroundTask
|
||||||
{
|
{
|
||||||
public static event NotificationHandler NotificationRecieved;
|
|
||||||
|
|
||||||
List<Notification> Notifications = new List<Notification>();
|
|
||||||
private DateTime lastCheck = DateTime.Now;
|
private DateTime lastCheck = DateTime.Now;
|
||||||
|
|
||||||
private ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
private ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
||||||
|
|
||||||
private ClientSecrets Secrets => new ClientSecrets()
|
|
||||||
{
|
|
||||||
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
|
|
||||||
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
|
|
||||||
};
|
|
||||||
private YouTubeService Service => new YouTubeService(new BaseClientService.Initializer()
|
private YouTubeService Service => new YouTubeService(new BaseClientService.Initializer()
|
||||||
{
|
{
|
||||||
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
||||||
ApplicationName = "FoxTube"
|
ApplicationName = "FoxTube"
|
||||||
});
|
});
|
||||||
|
|
||||||
XmlDocument doc = new XmlDocument();
|
|
||||||
BackgroundTaskDeferral def;
|
BackgroundTaskDeferral def;
|
||||||
|
|
||||||
public void Run(IBackgroundTaskInstance taskInstance)
|
public async void Run(IBackgroundTaskInstance taskInstance)
|
||||||
{
|
{
|
||||||
def = taskInstance.GetDeferral();
|
|
||||||
if (settings.Values["lastCheck"] == null)
|
|
||||||
settings.Values.Add("lastCheck", XmlConvert.ToString(DateTime.Now, "YYYY-MM-DDThh:mm:ss"));
|
|
||||||
else lastCheck = XmlConvert.ToDateTime(settings.Values["lastCheck"] as string, XmlDateTimeSerializationMode.Unspecified);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
doc.LoadXml(settings.Values["notificationsHistory"] as string);
|
def = taskInstance.GetDeferral();
|
||||||
}
|
|
||||||
catch
|
if (settings.Values["lastCheck"] == null)
|
||||||
{
|
{
|
||||||
|
settings.Values.Add("lastCheck", DateTime.Now.ToString());
|
||||||
|
def.Complete();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
lastCheck = DateTime.Parse(settings.Values["lastCheck"] as string);
|
||||||
|
|
||||||
|
bool[] notificationsSettings = JsonConvert.DeserializeObject<bool[]>(await FileIO.ReadTextAsync(await ApplicationData.Current.RoamingFolder.GetFileAsync("notifications.json")));
|
||||||
|
if (notificationsSettings[0])
|
||||||
CheckAnnouncements();
|
CheckAnnouncements();
|
||||||
CheckAccount();
|
if (notificationsSettings[1])
|
||||||
|
await CheckAccount();
|
||||||
SendNSave();
|
}
|
||||||
|
catch { }
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
settings.Values["lastCheck"] = DateTime.Now.ToString();
|
||||||
def.Complete();
|
def.Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
async void CheckAccount()
|
|
||||||
{
|
|
||||||
UserCredential credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(Secrets, new[] { Google.Apis.Oauth2.v2.Oauth2Service.Scope.UserinfoProfile, YouTubeService.Scope.YoutubeForceSsl }, "user", CancellationToken.None);
|
|
||||||
if (credential == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SubscriptionsResource.ListRequest subRequest = new YouTubeService(new BaseClientService.Initializer()
|
|
||||||
{
|
|
||||||
HttpClientInitializer = credential,
|
|
||||||
ApplicationName = "FoxTube"
|
|
||||||
}).Subscriptions.List("snippet");
|
|
||||||
subRequest.Mine = true;
|
|
||||||
subRequest.MaxResults = 50;
|
|
||||||
SubscriptionListResponse subResponse = await subRequest.ExecuteAsync();
|
|
||||||
Dictionary<string, string> subs = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
foreach (Subscription s in subResponse.Items)
|
|
||||||
subs.Add(s.Snippet.ResourceId.ChannelId, s.Snippet.Thumbnails.Standard.Url);
|
|
||||||
|
|
||||||
string nextToken = subResponse.NextPageToken;
|
|
||||||
while (nextToken != null)
|
|
||||||
{
|
|
||||||
subRequest.PageToken = nextToken;
|
|
||||||
subResponse = await subRequest.ExecuteAsync();
|
|
||||||
nextToken = subResponse.NextPageToken;
|
|
||||||
|
|
||||||
foreach (Subscription s in subResponse.Items)
|
|
||||||
subs.Add(s.Snippet.ResourceId.ChannelId, s.Snippet.Thumbnails.Standard.Url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(var s in subs)
|
async Task CheckAccount()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, string> subscriptions = JsonConvert.DeserializeObject<Dictionary<string, string>>(await FileIO.ReadTextAsync(await ApplicationData.Current.RoamingFolder.GetFileAsync("background.json")));
|
||||||
|
|
||||||
|
List<SearchResult> results = new List<SearchResult>();
|
||||||
|
|
||||||
|
foreach (var s in subscriptions)
|
||||||
{
|
{
|
||||||
SearchResource.ListRequest request = Service.Search.List("snippet");
|
SearchResource.ListRequest request = Service.Search.List("snippet");
|
||||||
request.PublishedAfter = lastCheck;
|
request.PublishedAfter = lastCheck;
|
||||||
request.ChannelId = s.Key;
|
request.ChannelId = s.Key;
|
||||||
request.Type = "video";
|
request.Type = "video";
|
||||||
|
request.MaxResults = 5;
|
||||||
SearchListResponse response = await request.ExecuteAsync();
|
SearchListResponse response = await request.ExecuteAsync();
|
||||||
|
|
||||||
foreach (var i in response.Items)
|
foreach (SearchResult i in response.Items)
|
||||||
Notifications.Add(new Notification("video", i.Id.VideoId,
|
{
|
||||||
i.Snippet.ChannelTitle,
|
results.Add(i);
|
||||||
i.Snippet.Title,
|
|
||||||
i.Snippet.PublishedAt.Value,
|
ToastNotificationManager.CreateToastNotifier().Show(
|
||||||
i.Snippet.Thumbnails.Standard.Url,
|
Notification.GetVideoToast(i.Id.VideoId, i.Snippet.ChannelId, i.Snippet.Title, i.Snippet.ChannelTitle, i.Snippet.Thumbnails.Medium.Url, s.Value));
|
||||||
s.Value));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
results.OrderBy(i => i.Snippet.PublishedAt);
|
||||||
|
|
||||||
|
TileUpdater updater = TileUpdateManager.CreateTileUpdaterForApplication();
|
||||||
|
updater.EnableNotificationQueue(true);
|
||||||
|
updater.Clear();
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
updater.Update(Tiles.GetTileLayout(results[i].Snippet.Title, results[i].Snippet.ChannelTitle, results[i].Snippet.Thumbnails.Medium.Url, subscriptions[results[i].Snippet.ChannelId]));
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
void CheckAnnouncements()
|
void CheckAnnouncements()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
XmlDocument doc = new XmlDocument();
|
XmlDocument doc = new XmlDocument();
|
||||||
doc.Load(XmlReader.Create("http://foxgame.hol.es/foxtube-messages.xml"));
|
doc.Load(XmlReader.Create("http://foxgame-studio.000webhostapp.com/foxtube-messages.xml"));
|
||||||
if ((XmlConvert.ToDateTimeOffset((doc["posts"].FirstChild as XmlElement).GetAttribute("time"), "YYYY-MM-DDThh:mm:ss") - lastCheck.ToUniversalTime()).TotalSeconds > 0)
|
if ((DateTime.Parse((doc["posts"].FirstChild as XmlElement).GetAttribute("time")) - lastCheck).TotalSeconds > 0)
|
||||||
Notifications.Add(new Notification("internal", (doc["posts"].FirstChild as XmlElement).GetAttribute("id"),
|
ToastNotificationManager.CreateToastNotifier().Show(
|
||||||
|
Notification.GetInternalToast(doc["posts"].FirstChild["id"].InnerText,
|
||||||
doc["posts"].FirstChild["header"].InnerText,
|
doc["posts"].FirstChild["header"].InnerText,
|
||||||
doc["posts"].FirstChild["notificationHeader"].InnerText,
|
doc["posts"].FirstChild["content"].InnerText,
|
||||||
XmlConvert.ToDateTimeOffset((doc["posts"].FirstChild as XmlElement).GetAttribute("time"), "YYYY-MM-DDThh:mm:ss"),
|
doc["posts"].FirstChild["thumbnail"].InnerText,
|
||||||
(doc["posts"].FirstChild as XmlElement).GetAttribute("image"), (doc["posts"].FirstChild as XmlElement).GetAttribute("avatar")));
|
doc["posts"].FirstChild["avatar"].InnerText));
|
||||||
}
|
|
||||||
|
|
||||||
void SendNotification(Notification notification)
|
|
||||||
{
|
|
||||||
ToastNotificationManager.CreateToastNotifier().Show(notification.GetToast());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendNSave()
|
|
||||||
{
|
|
||||||
foreach (Notification n in Notifications)
|
|
||||||
{
|
|
||||||
NotificationRecieved.Invoke(this, n);
|
|
||||||
doc["history"].InnerXml += n.GetXml();
|
|
||||||
}
|
|
||||||
settings.Values.Add("notificationsHistory", doc.InnerXml);
|
|
||||||
|
|
||||||
foreach (Notification n in Notifications)
|
|
||||||
switch (n.Type)
|
|
||||||
{
|
|
||||||
case NotificationType.Video:
|
|
||||||
if ((bool)settings.Values["newVideoNotification"])
|
|
||||||
SendNotification(n);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NotificationType.Internal:
|
|
||||||
SendNotification(n);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
<AssemblyName>FoxTube.Background</AssemblyName>
|
<AssemblyName>FoxTube.Background</AssemblyName>
|
||||||
<DefaultLanguage>en-US</DefaultLanguage>
|
<DefaultLanguage>en-US</DefaultLanguage>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.17134.0</TargetPlatformVersion>
|
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.17763.0</TargetPlatformVersion>
|
||||||
<TargetPlatformMinVersion>10.0.15063.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
|
||||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BackgroundProcessor.cs" />
|
<Compile Include="BackgroundProcessor.cs" />
|
||||||
<Compile Include="Notification.cs" />
|
<Compile Include="ResourceCreators.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,235 +0,0 @@
|
|||||||
using System;
|
|
||||||
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;
|
|
||||||
|
|
||||||
namespace FoxTube.Background
|
|
||||||
{
|
|
||||||
public enum NotificationType
|
|
||||||
{
|
|
||||||
Video, Comment, Post, Internal, Changelog
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class Notification
|
|
||||||
{
|
|
||||||
public string Channel { get; set; }
|
|
||||||
public string Content { get; set; }
|
|
||||||
public DateTimeOffset TimeStamp { get; set; }
|
|
||||||
public NotificationType Type { get; set; }
|
|
||||||
public string Avatar { get; set; }
|
|
||||||
public string Thumbnail { get; set; }
|
|
||||||
public string Id { get; set; }
|
|
||||||
|
|
||||||
public Notification(string type, string id,
|
|
||||||
string channelName, string content, DateTimeOffset date,
|
|
||||||
string thumbnailUrl, string avatarUrl)
|
|
||||||
{
|
|
||||||
Channel = channelName;
|
|
||||||
Content = content;
|
|
||||||
TimeStamp = date;
|
|
||||||
Id = id;
|
|
||||||
Type = TypeConversion(type);
|
|
||||||
Avatar = avatarUrl ?? "ms-appx:///Assets/Icons/Profile.png";
|
|
||||||
Thumbnail = thumbnailUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Notification(string xmlSource)
|
|
||||||
{
|
|
||||||
System.Xml.XmlDocument d = new System.Xml.XmlDocument();
|
|
||||||
d.InnerXml = xmlSource;
|
|
||||||
System.Xml.XmlElement xml = d["item"];
|
|
||||||
|
|
||||||
Channel = xml["channelName"].InnerText;
|
|
||||||
Content = xml["content"].InnerText;
|
|
||||||
TimeStamp = DateTimeOffset.Parse(xml.GetAttribute("time"));
|
|
||||||
Id = xml.GetAttribute("id");
|
|
||||||
Type = TypeConversion(xml.GetAttribute("type"));
|
|
||||||
Avatar = xml["images"].GetAttribute("avatar");
|
|
||||||
Thumbnail = xml["images"].GetAttribute("thumbnail");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetXml()
|
|
||||||
{
|
|
||||||
return $@"<item time='{TimeStamp.ToString("YYYY-MM-DDThh:mm:ss")}' type='{TypeConversion(Type)}' id='{Id}'>
|
|
||||||
<images thumbnail='{Thumbnail}' avatar='{Avatar}'/>
|
|
||||||
<channelName>{Channel}</channelName>
|
|
||||||
<content>{Content}</content>
|
|
||||||
</item>";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Button GetNotification()
|
|
||||||
{
|
|
||||||
StackPanel stackPanel = new StackPanel() { Margin = new Thickness(10, 0, 0, 0) };
|
|
||||||
|
|
||||||
//Channel
|
|
||||||
switch (Type)
|
|
||||||
{
|
|
||||||
case NotificationType.Internal:
|
|
||||||
stackPanel.Children.Add(new TextBlock()
|
|
||||||
{
|
|
||||||
FontSize = 14,
|
|
||||||
FontStyle = Windows.UI.Text.FontStyle.Italic,
|
|
||||||
Foreground = new SolidColorBrush(Colors.Gray),
|
|
||||||
Text = "Developer's message"
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NotificationType.Changelog:
|
|
||||||
stackPanel.Children.Add(new TextBlock()
|
|
||||||
{
|
|
||||||
FontSize = 14,
|
|
||||||
FontStyle = Windows.UI.Text.FontStyle.Italic,
|
|
||||||
Foreground = new SolidColorBrush(Colors.Gray),
|
|
||||||
Text = "Changelog"
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NotificationType.Video:
|
|
||||||
stackPanel.Children.Add(new TextBlock()
|
|
||||||
{
|
|
||||||
FontSize = 14,
|
|
||||||
FontStyle = Windows.UI.Text.FontStyle.Italic,
|
|
||||||
Foreground = new SolidColorBrush(Colors.Gray),
|
|
||||||
Text = $"{Channel} uploaded new video"
|
|
||||||
});
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
XmlDocument template = new XmlDocument();
|
|
||||||
switch (Type)
|
|
||||||
{
|
|
||||||
case NotificationType.Video:
|
|
||||||
template.LoadXml($@"<toast launch='video={Id}'>
|
|
||||||
<visual>
|
|
||||||
<binding template='ToastGeneric'>
|
|
||||||
<image placement='appLogoOverride' hint-crop='circle' src='{Avatar}'/>
|
|
||||||
<text>{Content}</text>
|
|
||||||
<text>{Channel} uploaded a new video</text>
|
|
||||||
<image src='{Thumbnail}'/>
|
|
||||||
</binding>
|
|
||||||
</visual>
|
|
||||||
|
|
||||||
<actions>
|
|
||||||
<action content='Watch later'
|
|
||||||
activationType='background'
|
|
||||||
arguments='video&{Id}&later'/>
|
|
||||||
<action content='Go to channel'
|
|
||||||
arguments='video&{Id}&channel'/>
|
|
||||||
</actions>
|
|
||||||
</toast>");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NotificationType.Changelog:
|
|
||||||
template.LoadXml($@"<toast launch='{Id}'>
|
|
||||||
<visual>
|
|
||||||
<binding template='ToastGeneric'>
|
|
||||||
<image placement='hero' src='http://foxgame.hol.es/FoxTubeAssets/WhatsNewThumb.png'/>
|
|
||||||
<image placement='appLogoOverride' hint-crop='circle' src='http://foxgame.hol.es/FoxTubeAssets/NewsAvatar.png'/>
|
|
||||||
<text>{Content}</text>
|
|
||||||
<text>{Channel}</text>
|
|
||||||
</binding>
|
|
||||||
</visual>
|
|
||||||
</toast>");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NotificationType.Internal:
|
|
||||||
template.LoadXml($@"<toast launch='internal={Id}'>
|
|
||||||
<visual>
|
|
||||||
<binding template='ToastGeneric'>
|
|
||||||
<image placement='hero' src='{Thumbnail}'/>
|
|
||||||
<image placement='appLogoOverride' hint-crop='circle' src='{Avatar}'/>
|
|
||||||
<text>{Content}</text>
|
|
||||||
<text hint-maxLines='5'>{Channel}</text>
|
|
||||||
</binding>
|
|
||||||
</visual>
|
|
||||||
</toast>");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ToastNotification(template);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string TypeConversion(NotificationType type)
|
|
||||||
{
|
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
case NotificationType.Comment:
|
|
||||||
return "comment";
|
|
||||||
case NotificationType.Post:
|
|
||||||
return "post";
|
|
||||||
case NotificationType.Video:
|
|
||||||
return "video";
|
|
||||||
case NotificationType.Changelog:
|
|
||||||
return "changelog";
|
|
||||||
default:
|
|
||||||
return "internal";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private NotificationType TypeConversion(string type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case "comment":
|
|
||||||
return NotificationType.Comment;
|
|
||||||
case "post":
|
|
||||||
return NotificationType.Post;
|
|
||||||
case "video":
|
|
||||||
return NotificationType.Video;
|
|
||||||
case "changelog":
|
|
||||||
return NotificationType.Changelog;
|
|
||||||
default:
|
|
||||||
return NotificationType.Internal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
using Windows.Data.Xml.Dom;
|
||||||
|
using Windows.UI.Notifications;
|
||||||
|
|
||||||
|
namespace FoxTube.Background
|
||||||
|
{
|
||||||
|
public static class Notification
|
||||||
|
{
|
||||||
|
public static ToastNotification GetChangelogToast(string version)
|
||||||
|
{
|
||||||
|
XmlDocument template = new XmlDocument();
|
||||||
|
|
||||||
|
template.LoadXml($@"<toast activationType='foreground' launch='changelog|{version}'>
|
||||||
|
<visual>
|
||||||
|
<binding template='ToastGeneric'>
|
||||||
|
<image placement='hero' src='http://foxgame-studio.000webhostapp.com/FoxTubeAssets/WhatsNewThumb.png'/>
|
||||||
|
<image placement='appLogoOverride' hint-crop='circle' src='http://foxgame-studio.000webhostapp.com/FoxTubeAssets/NewsAvatar.png'/>
|
||||||
|
<text>Changelog</text>
|
||||||
|
<text>See what's new in version {version}</text>
|
||||||
|
</binding>
|
||||||
|
</visual>
|
||||||
|
</toast>");
|
||||||
|
|
||||||
|
return new ToastNotification(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ToastNotification GetVideoToast(string id, string channelId, string title, string channel, string thumbnail, string avatar)
|
||||||
|
{
|
||||||
|
XmlDocument template = new XmlDocument();
|
||||||
|
|
||||||
|
template.LoadXml($@"<toast activationType='foreground' launch='video|{id}'>
|
||||||
|
<visual>
|
||||||
|
<binding template='ToastGeneric'>
|
||||||
|
<image placement='hero' src='{thumbnail.Replace("&", "%26")}'/>
|
||||||
|
<image placement='appLogoOverride' hint-crop='circle' src='{avatar.Replace("&", "%26") ?? "http://foxgame-studio.000webhostapp.com/FoxTubeAssets/LogoAvatar.png"}'/>
|
||||||
|
<text>{title}</text>
|
||||||
|
<text>{channel} uploaded a new video</text>
|
||||||
|
</binding>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<actions>
|
||||||
|
<action content='Add to Watch later' activationType='background' arguments='later|{id}'/>
|
||||||
|
<action content='Go to channel' activationType='foreground' arguments='channel|{channelId}'/>
|
||||||
|
</actions>
|
||||||
|
</toast>");
|
||||||
|
|
||||||
|
return new ToastNotification(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ToastNotification GetInternalToast(string id, string header, string content, string thumbnail, string avatar)
|
||||||
|
{
|
||||||
|
XmlDocument template = new XmlDocument();
|
||||||
|
|
||||||
|
template.LoadXml($@"<toast activationType='foreground' launch='inbox|{id}'>
|
||||||
|
<visual>
|
||||||
|
<binding template='ToastGeneric'>
|
||||||
|
<image placement='hero' src='{thumbnail ?? "http://foxgame-studio.000webhostapp.com/FoxTubeAssets/AnnouncementThumb.png"}'/>
|
||||||
|
<image placement='appLogoOverride' hint-crop='circle' src='{avatar ?? "http://foxgame-studio.000webhostapp.com/FoxTubeAssets/LogoAvatar.png"}'/>
|
||||||
|
<text>{header}</text>
|
||||||
|
<text hint-maxLines='5'>{content}</text>
|
||||||
|
</binding>
|
||||||
|
</visual>
|
||||||
|
</toast>");
|
||||||
|
|
||||||
|
return new ToastNotification(template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Tiles
|
||||||
|
{
|
||||||
|
public static TileNotification GetTileLayout(string title, string channel, string thumbnail, string avatar)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
|
||||||
|
doc.LoadXml($@" <tile>
|
||||||
|
<visual>
|
||||||
|
|
||||||
|
<binding template='TileMedium' branding='none'>
|
||||||
|
<image placement='peek' src='{avatar?.Replace("&", "%26")}'/>
|
||||||
|
<image placement='background' src='{thumbnail?.Replace("&", "%26")}'/>
|
||||||
|
<text hint-style='base' hint-overlay='60'>{channel}</text>
|
||||||
|
<text hint-wrap='true' hint-style='captionSubtle'>{title}</text>
|
||||||
|
</binding>
|
||||||
|
|
||||||
|
<binding template='TileWide' Branding='nameAndLogo'>
|
||||||
|
<image placement='background' hint-overlay='60' src='{thumbnail?.Replace("&", "%26")}'/>
|
||||||
|
<group>
|
||||||
|
<subgroup hint-weight='33'>
|
||||||
|
<image src='{avatar?.Replace("&", "%26")}' hint-crop='circle' />
|
||||||
|
</subgroup>
|
||||||
|
<subgroup hint-textStacking='center'>
|
||||||
|
<text hint-style='base'>{channel}</text>
|
||||||
|
<text hint-wrap='true' hint-style='captionSubtle'>{title}</text>
|
||||||
|
</subgroup>
|
||||||
|
</group>
|
||||||
|
</binding>
|
||||||
|
|
||||||
|
<binding template='TileLarge' hint-textStacking='top' Branding='nameAndLogo'>
|
||||||
|
<image placement='background' hint-overlay='60' src='{thumbnail?.Replace("&", "%26")}'/>
|
||||||
|
<group>
|
||||||
|
<subgroup hint-weight='33'>
|
||||||
|
<image src='{avatar?.Replace("&", "%26")}' hint-crop='circle' />
|
||||||
|
</subgroup>
|
||||||
|
<subgroup hint-textStacking='center'>
|
||||||
|
<text hint-style='base'>{channel}</text>
|
||||||
|
<text hint-wrap='true' hint-style='captionSubtle'>{title}</text>
|
||||||
|
</subgroup>
|
||||||
|
</group>
|
||||||
|
</binding>
|
||||||
|
</visual>
|
||||||
|
</tile>");
|
||||||
|
|
||||||
|
return new TileNotification(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,17 @@
|
|||||||
using System;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
using System.Globalization;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.ApplicationModel;
|
using Windows.ApplicationModel;
|
||||||
using Windows.ApplicationModel.Activation;
|
using Windows.ApplicationModel.Activation;
|
||||||
using Windows.ApplicationModel.Core;
|
using Windows.ApplicationModel.Background;
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.Globalization;
|
using Windows.Globalization;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
using Windows.UI;
|
using Windows.System;
|
||||||
using Windows.UI.Core;
|
using Windows.System.Power;
|
||||||
using Windows.UI.ViewManagement;
|
using Windows.UI.Notifications;
|
||||||
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 Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
namespace FoxTube
|
namespace FoxTube
|
||||||
@@ -33,12 +25,11 @@ namespace FoxTube
|
|||||||
/// Initializes the singleton application object. This is the first line of authored code
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
|
||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
try
|
SettingsStorage.LoadData();
|
||||||
{
|
|
||||||
switch((int)settings.Values["themeMode"])
|
switch (SettingsStorage.Theme)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
RequestedTheme = ApplicationTheme.Light;
|
RequestedTheme = ApplicationTheme.Light;
|
||||||
@@ -47,22 +38,10 @@ namespace FoxTube
|
|||||||
RequestedTheme = ApplicationTheme.Dark;
|
RequestedTheme = ApplicationTheme.Dark;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch { }
|
|
||||||
try
|
ApplicationLanguages.PrimaryLanguageOverride = SettingsStorage.Language;
|
||||||
{
|
InitializeComponent();
|
||||||
if (settings.Values["language"] == null)
|
Suspending += OnSuspending;
|
||||||
{
|
|
||||||
List<string> cultures = new List<string>() { "ua", "ru", "by", "kz", "kg", "md", "lv", "ee" };
|
|
||||||
if (cultures.Contains(CultureInfo.InstalledUICulture.ThreeLetterISOLanguageName))
|
|
||||||
settings.Values.Add("language", "ru-RU");
|
|
||||||
else
|
|
||||||
settings.Values.Add("language", "en-US");
|
|
||||||
}
|
|
||||||
ApplicationLanguages.PrimaryLanguageOverride = (string)settings.Values["language"];
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
this.InitializeComponent();
|
|
||||||
this.Suspending += OnSuspending;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -72,8 +51,6 @@ namespace FoxTube
|
|||||||
/// <param name="e">Details about the launch request and process.</param>
|
/// <param name="e">Details about the launch request and process.</param>
|
||||||
protected override void OnLaunched(LaunchActivatedEventArgs e)
|
protected override void OnLaunched(LaunchActivatedEventArgs e)
|
||||||
{
|
{
|
||||||
SecretsVault.CheckAuthorization();
|
|
||||||
|
|
||||||
Frame rootFrame = Window.Current.Content as Frame;
|
Frame rootFrame = Window.Current.Content as Frame;
|
||||||
|
|
||||||
// Do not repeat app initialization when the Window already has content,
|
// Do not repeat app initialization when the Window already has content,
|
||||||
@@ -85,11 +62,6 @@ namespace FoxTube
|
|||||||
|
|
||||||
rootFrame.NavigationFailed += OnNavigationFailed;
|
rootFrame.NavigationFailed += OnNavigationFailed;
|
||||||
|
|
||||||
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
|
|
||||||
{
|
|
||||||
//TODO: Load state from previously suspended application
|
|
||||||
}
|
|
||||||
|
|
||||||
// Place the frame in the current Window
|
// Place the frame in the current Window
|
||||||
Window.Current.Content = rootFrame;
|
Window.Current.Content = rootFrame;
|
||||||
}
|
}
|
||||||
@@ -107,7 +79,149 @@ namespace FoxTube
|
|||||||
Window.Current.Activate();
|
Window.Current.Activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
|
ActivateToastBackgoundTask();
|
||||||
|
ActivateBackgoundTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes background task for processing toast notifications' clicks
|
||||||
|
/// </summary>
|
||||||
|
public async void ActivateToastBackgoundTask()
|
||||||
|
{
|
||||||
|
const string taskName = "FoxtubeToastBackground";
|
||||||
|
if (BackgroundTaskRegistration.AllTasks.Any(i => i.Value.Name.Equals(taskName)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var backgroundRequest = await BackgroundExecutionManager.RequestAccessAsync();
|
||||||
|
var saverRequest = PowerManager.EnergySaverStatus;
|
||||||
|
if (backgroundRequest == BackgroundAccessStatus.DeniedBySystemPolicy || backgroundRequest == BackgroundAccessStatus.DeniedByUser)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BackgroundTaskBuilder builder = new BackgroundTaskBuilder() { Name = taskName };
|
||||||
|
builder.SetTrigger(new ToastNotificationActionTrigger());
|
||||||
|
|
||||||
|
BackgroundTaskRegistration registration = builder.Register();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes background task for checking user's subscriptions and poping toast notifications when new video is uploaded
|
||||||
|
/// </summary>
|
||||||
|
public async void ActivateBackgoundTask()
|
||||||
|
{
|
||||||
|
const string taskName = "FoxtubeBackgound";
|
||||||
|
if (BackgroundTaskRegistration.AllTasks.Any(i => i.Value.Name.Equals(taskName)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var backgroundRequest = await BackgroundExecutionManager.RequestAccessAsync();
|
||||||
|
var saverRequest = PowerManager.EnergySaverStatus;
|
||||||
|
if (backgroundRequest == BackgroundAccessStatus.DeniedBySystemPolicy || backgroundRequest == BackgroundAccessStatus.DeniedByUser || saverRequest == EnergySaverStatus.On)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BackgroundTaskBuilder builder = new BackgroundTaskBuilder()
|
||||||
|
{
|
||||||
|
Name = taskName,
|
||||||
|
IsNetworkRequested = true,
|
||||||
|
TaskEntryPoint = "FoxTube.Background.BackgroundProcessor"
|
||||||
|
};
|
||||||
|
builder.SetTrigger(new TimeTrigger(15, false));
|
||||||
|
|
||||||
|
BackgroundTaskRegistration registration = builder.Register();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
|
||||||
|
{
|
||||||
|
var deferral = args.TaskInstance.GetDeferral();
|
||||||
|
base.OnBackgroundActivated(args);
|
||||||
|
|
||||||
|
if (args.TaskInstance.Task.Name == "FoxtubeToastBackground" && args.TaskInstance.TriggerDetails is ToastNotificationActionTriggerDetail details)
|
||||||
|
{
|
||||||
|
string[] arguments = details.Argument.Split('|');
|
||||||
|
|
||||||
|
switch (arguments[0])
|
||||||
|
{
|
||||||
|
case "later":
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!SecretsVault.IsAuthorized)
|
||||||
|
SecretsVault.CheckAuthorization(false);
|
||||||
|
if (!SecretsVault.IsAuthorized)
|
||||||
|
throw new Exception("Not authenticated");
|
||||||
|
|
||||||
|
PlaylistItem item = new PlaylistItem()
|
||||||
|
{
|
||||||
|
Snippet = new PlaylistItemSnippet()
|
||||||
|
{
|
||||||
|
ResourceId = new ResourceId()
|
||||||
|
{
|
||||||
|
Kind = "youtube#video",
|
||||||
|
VideoId = arguments[1]
|
||||||
|
},
|
||||||
|
PlaylistId = "WL"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await SecretsVault.Service.PlaylistItems.Insert(item, "snippet").ExecuteAsync();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(e.Message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "download":
|
||||||
|
await Launcher.LaunchFileAsync(await StorageFile.GetFileFromPathAsync(arguments[1]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deferral.Complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnActivated(IActivatedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnActivated(e);
|
||||||
|
|
||||||
|
Frame rootFrame = Window.Current.Content as Frame;
|
||||||
|
|
||||||
|
if (rootFrame == null)
|
||||||
|
{
|
||||||
|
rootFrame = new Frame();
|
||||||
|
rootFrame.NavigationFailed += OnNavigationFailed;
|
||||||
|
|
||||||
|
Window.Current.Content = rootFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rootFrame.Content == null)
|
||||||
|
{
|
||||||
|
rootFrame.Navigate(typeof(MainPage));
|
||||||
|
}
|
||||||
|
|
||||||
|
Window.Current.Activate();
|
||||||
|
|
||||||
|
if (e is ToastNotificationActivatedEventArgs)
|
||||||
|
{
|
||||||
|
string[] args = (e as ToastNotificationActivatedEventArgs).Argument.Split('|');
|
||||||
|
switch (args[0])
|
||||||
|
{
|
||||||
|
case "changelog":
|
||||||
|
case "inbox":
|
||||||
|
Methods.MainPage.GoToDeveloper(args[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "video":
|
||||||
|
Methods.MainPage.GoToVideo(args[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "channel":
|
||||||
|
Methods.MainPage.GoToChannel(args[1]);
|
||||||
|
break;
|
||||||
|
case "download":
|
||||||
|
Methods.MainPage.GoToDownloads();
|
||||||
|
break;
|
||||||
|
case "dcancel":
|
||||||
|
DownloadAgent.Remove(args[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -130,7 +244,8 @@ namespace FoxTube
|
|||||||
private void OnSuspending(object sender, SuspendingEventArgs e)
|
private void OnSuspending(object sender, SuspendingEventArgs e)
|
||||||
{
|
{
|
||||||
var deferral = e.SuspendingOperation.GetDeferral();
|
var deferral = e.SuspendingOperation.GetDeferral();
|
||||||
//TODO: Save application state and stop any background activity
|
SettingsStorage.ExportSettings();
|
||||||
|
DownloadAgent.QuitPrompt();
|
||||||
deferral.Complete();
|
deferral.Complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
@@ -1,71 +1,75 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
using FoxTube.Classes;
|
using FoxTube.Classes;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Windows.UI.Popups;
|
using YoutubeExplode.Models.MediaStreams;
|
||||||
|
using Google.Apis.YouTube.v3.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using FoxTube.Controls;
|
||||||
|
|
||||||
namespace FoxTube.Controls
|
namespace FoxTube
|
||||||
{
|
{
|
||||||
public class DownloadAgent
|
public static class DownloadAgent
|
||||||
{
|
{
|
||||||
public List<DownloadItem> items = new List<DownloadItem>();
|
public static List<DownloadItem> items = new List<DownloadItem>();
|
||||||
StorageFolder roaming = ApplicationData.Current.RoamingFolder;
|
private static ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
||||||
|
public static StorageFolder Downloads { get; set; }
|
||||||
|
|
||||||
public DownloadAgent()
|
public static async void Initialize()
|
||||||
{
|
|
||||||
Initialize();
|
|
||||||
Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += (s, a) => QuitPrompt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Initialize()
|
|
||||||
{
|
{
|
||||||
|
Downloads = await KnownFolders.VideosLibrary.CreateFolderAsync("FoxTube", CreationCollisionOption.OpenIfExists);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<DownloadItemContainer> containers = JsonConvert.DeserializeObject<List<DownloadItemContainer>>(await FileIO.ReadTextAsync(await roaming.GetFileAsync("data.json")));
|
List<DownloadItemContainer> containers = JsonConvert.DeserializeObject<List<DownloadItemContainer>>((string)settings.Values["downloads"]);
|
||||||
|
containers.ForEach(i => items.Add(new DownloadItem(i)));
|
||||||
foreach (DownloadItemContainer i in containers)
|
|
||||||
try { items.Add(new DownloadItem(i)); }
|
|
||||||
catch (FileNotFoundException) { }
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(string url)
|
public static void Add(MediaStreamInfo info, Video meta, string qualty)
|
||||||
{
|
{
|
||||||
items.Add(new DownloadItem(url));
|
items.Insert(0, new DownloadItem(info, meta, qualty));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Item_DownloadCanceled(object sender, params object[] e)
|
public static void CancelItem(string id)
|
||||||
{
|
{
|
||||||
items.Remove(sender as DownloadItem);
|
DownloadItem item = items.Find(x => x.Container.Id == id);
|
||||||
|
if (item == null || !item.InProgress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
item.CancelPrompt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void QuitPrompt()
|
public static void Remove(string id)
|
||||||
{
|
{
|
||||||
if(items.Find(x => x.InProgress) != null)
|
DownloadItem item = items.Find(x => x.Container.Id == id);
|
||||||
{
|
if (item == 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");
|
return;
|
||||||
|
|
||||||
dialog.Commands.Add(new UICommand("Yes", async (command) =>
|
if (item.InProgress)
|
||||||
|
item.Cancel();
|
||||||
|
else
|
||||||
|
items.Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void QuitPrompt()
|
||||||
{
|
{
|
||||||
foreach (DownloadItem i in items.FindAll(x => x.InProgress))
|
foreach (DownloadItem i in items.FindAll(i => i.InProgress))
|
||||||
i.Cancel();
|
i.Cancel();
|
||||||
items.RemoveAll(x => x.InProgress);
|
|
||||||
|
|
||||||
List<DownloadItemContainer> containers = new List<DownloadItemContainer>();
|
List<DownloadItemContainer> containers = new List<DownloadItemContainer>();
|
||||||
foreach (DownloadItem i in items)
|
items.ForEach(i => containers.Add(i.Container));
|
||||||
containers.Add(i.Container);
|
|
||||||
|
|
||||||
await FileIO.WriteTextAsync(
|
string data = JsonConvert.SerializeObject(containers);
|
||||||
await roaming.CreateFileAsync("data.json", CreationCollisionOption.ReplaceExisting),
|
|
||||||
JsonConvert.SerializeObject(containers));
|
|
||||||
}));
|
|
||||||
dialog.Commands.Add(new UICommand("No"));
|
|
||||||
|
|
||||||
dialog.DefaultCommandIndex = 1;
|
try
|
||||||
await dialog.ShowAsync();
|
{
|
||||||
|
settings.Values["downloads"] = data;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
settings.Values.Add("downloads", data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using YoutubeExplode.Models.MediaStreams;
|
using Windows.Storage;
|
||||||
|
|
||||||
namespace FoxTube.Classes
|
namespace FoxTube.Classes
|
||||||
{
|
{
|
||||||
@@ -8,9 +8,10 @@ namespace FoxTube.Classes
|
|||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string Channel { get; set; }
|
public string Channel { get; set; }
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public Uri Path { get; set; }
|
public string Name { get; set; }
|
||||||
|
public string Extension { get; set; }
|
||||||
public Uri Thumbnail { get; set; }
|
public Uri Thumbnail { get; set; }
|
||||||
public VideoQuality Quality { get; set; }
|
public string Quality { get; set; }
|
||||||
public TimeSpan Duration { get; set; }
|
public TimeSpan Duration { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ namespace FoxTube.Classes
|
|||||||
public InboxItemType Type { get; set; } = InboxItemType.Default;
|
public InboxItemType Type { get; set; } = InboxItemType.Default;
|
||||||
public DateTime TimeStamp { get; set; }
|
public DateTime TimeStamp { get; set; }
|
||||||
|
|
||||||
public string PatchVersion { get; set; }
|
|
||||||
public string Subject { get; set; }
|
public string Subject { get; set; }
|
||||||
public string Content { get; set; }
|
public string Content { get; set; }
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
@@ -41,20 +40,19 @@ namespace FoxTube.Classes
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (Type == InboxItemType.PatchNote)
|
if (Type == InboxItemType.PatchNote)
|
||||||
return $"What's new in v{PatchVersion}";
|
return $"What's new in v{Id}";
|
||||||
else
|
else
|
||||||
return Subject;
|
return Subject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public InboxItem(string version, string content, string timeStamp, string id)
|
public InboxItem(string version, string content, string timeStamp)
|
||||||
{
|
{
|
||||||
Type = InboxItemType.PatchNote;
|
Type = InboxItemType.PatchNote;
|
||||||
PatchVersion = version;
|
|
||||||
Content = content;
|
Content = content;
|
||||||
TimeStamp = DateTime.Parse(timeStamp);
|
TimeStamp = DateTime.Parse(timeStamp);
|
||||||
Id = id;
|
Id = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InboxItem(string title, string content, DateTime timeStamp, string id)
|
public InboxItem(string title, string content, DateTime timeStamp, string id)
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using Windows.ApplicationModel.Core;
|
using Windows.ApplicationModel.Core;
|
||||||
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
|
using Windows.Storage;
|
||||||
|
using Windows.Storage.Streams;
|
||||||
using Windows.System;
|
using Windows.System;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
@@ -31,6 +37,33 @@ namespace FoxTube
|
|||||||
return new Uri(url);
|
return new Uri(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ForEach<T>(this IEnumerable<T> array, Action<T> action)
|
||||||
|
{
|
||||||
|
array.ToList().ForEach(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Find<T>(this IEnumerable<T> array, Predicate<T> match)
|
||||||
|
{
|
||||||
|
return array.ToList().Find(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<T> FindAll<T>(this IEnumerable<T> array, Predicate<T> match)
|
||||||
|
{
|
||||||
|
return array.ToList().FindAll(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ReplaceInvalidChars(this string str, char newValue)
|
||||||
|
{
|
||||||
|
foreach (char i in Path.GetInvalidFileNameChars())
|
||||||
|
str = str.Replace(i, newValue);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Last(this string[] arr)
|
||||||
|
{
|
||||||
|
return arr[arr.Length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
public static string GetAgo(DateTime dateTime)
|
public static string GetAgo(DateTime dateTime)
|
||||||
{
|
{
|
||||||
TimeSpan span = DateTime.Now - dateTime;
|
TimeSpan span = DateTime.Now - dateTime;
|
||||||
@@ -204,5 +237,29 @@ namespace FoxTube
|
|||||||
await Launcher.LaunchUriAsync(new Uri(url));
|
await Launcher.LaunchUriAsync(new Uri(url));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async void Share(DataRequestedEventArgs args, string thumbnail, string title, string url, string type)
|
||||||
|
{
|
||||||
|
DataRequest request = args.Request;
|
||||||
|
request.Data.Properties.Title = title;
|
||||||
|
request.Data.Properties.Description = $"Sharing a {type}";
|
||||||
|
|
||||||
|
request.Data.SetText(title + "\n" + "#YouTube #FoxTube #SharedWithFoxTube");
|
||||||
|
request.Data.SetWebLink(url.ToUri());
|
||||||
|
|
||||||
|
DataRequestDeferral deferral = request.GetDeferral();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StorageFile thumbnailFile = await StorageFile.CreateStreamedFileFromUriAsync("tempThumb.jpg", thumbnail.ToUri(), null);
|
||||||
|
request.Data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromFile(thumbnailFile);
|
||||||
|
StorageFile imageFile = thumbnailFile;
|
||||||
|
|
||||||
|
request.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(imageFile));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
deferral.Complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using static Google.Apis.YouTube.v3.SearchResource.ListRequest;
|
using static Google.Apis.YouTube.v3.SearchResource.ListRequest;
|
||||||
|
|
||||||
namespace FoxTube
|
namespace FoxTube
|
||||||
{
|
{
|
||||||
public delegate void Event();
|
public delegate void Event();
|
||||||
|
|
||||||
public delegate void ObjectEventHandler(object sender, params object[] args);
|
public delegate void ObjectEventHandler(object sender = null, params object[] args);
|
||||||
|
|
||||||
/*public class SearchParameters
|
|
||||||
{
|
|
||||||
public string ChannelId { get; set; }
|
|
||||||
public string Term { get; set; }
|
|
||||||
|
|
||||||
public SearchParameters(string channelId, string term)
|
|
||||||
{
|
|
||||||
ChannelId = channelId;
|
|
||||||
Term = term;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public class SearchParameters
|
public class SearchParameters
|
||||||
{
|
{
|
||||||
@@ -1,75 +1,72 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Net;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Google.Apis.Auth.OAuth2;
|
using Google.Apis.Auth.OAuth2;
|
||||||
using Google.Apis.Auth.OAuth2.Flows;
|
|
||||||
using Google.Apis.Services;
|
using Google.Apis.Services;
|
||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
using Windows.UI.Popups;
|
|
||||||
|
|
||||||
namespace FoxTube
|
namespace FoxTube
|
||||||
{
|
{
|
||||||
public static class SecretsVault
|
public static class SecretsVault
|
||||||
{
|
{
|
||||||
public static event EventHandler AuthorizationStateChanged;
|
#region Properties
|
||||||
|
//Events
|
||||||
|
public static event ObjectEventHandler AuthorizationStateChanged;
|
||||||
public static event ObjectEventHandler SubscriptionsChanged;
|
public static event ObjectEventHandler SubscriptionsChanged;
|
||||||
|
public static event Event NotPurchased; //Rising when app finds out that it's not a PRO version
|
||||||
|
|
||||||
private static ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
//Private properties
|
||||||
public static NetworkCredential EmailCredential => new NetworkCredential("youwillneverknowthisadress@gmail.com", "thisisthepassword12345");
|
private static ClientSecrets Secrets => new ClientSecrets()
|
||||||
public static ClientSecrets Secrets => new ClientSecrets()
|
|
||||||
{
|
{
|
||||||
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
|
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
|
||||||
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
|
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
|
||||||
};
|
};
|
||||||
private static UserCredential Credential;
|
private static YouTubeService NoAuthService => new YouTubeService(new BaseClientService.Initializer()
|
||||||
|
{
|
||||||
|
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
||||||
|
ApplicationName = "FoxTube"
|
||||||
|
});
|
||||||
public static BaseClientService.Initializer Initializer => new BaseClientService.Initializer()
|
public static BaseClientService.Initializer Initializer => new BaseClientService.Initializer()
|
||||||
{
|
{
|
||||||
HttpClientInitializer = Credential,
|
HttpClientInitializer = Credential,
|
||||||
ApplicationName = "FoxTube"
|
ApplicationName = "FoxTube"
|
||||||
};
|
};
|
||||||
|
public static YouTubeService Service => IsAuthorized ? new YouTubeService(Initializer) : NoAuthService;
|
||||||
|
public static bool AdsDisabled { get; private set; } = true;
|
||||||
|
|
||||||
public static string AccountId { get; private set; }
|
//User info
|
||||||
public static bool IsAuthorized { get; private set; } = false;
|
public static bool IsAuthorized => Credential != null;
|
||||||
|
private static UserCredential Credential { get; set; }
|
||||||
|
|
||||||
|
public static string AccountId => UserChannel?.Id;
|
||||||
public static Channel UserChannel { get; private set; }
|
public static Channel UserChannel { get; private set; }
|
||||||
public static List<PlaylistItem> WatchLater { get; private set; } = new List<PlaylistItem>();
|
|
||||||
public static List<PlaylistItem> UserHistory { get; private set; } = new List<PlaylistItem>();
|
|
||||||
public static List<Subscription> Subscriptions { get; private set; } = new List<Subscription>();
|
|
||||||
|
|
||||||
public static YouTubeService NoAuthService => new YouTubeService(new BaseClientService.Initializer()
|
public static List<Subscription> Subscriptions { get; } = new List<Subscription>();
|
||||||
{
|
#endregion
|
||||||
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
|
||||||
ApplicationName = "FoxTube"
|
|
||||||
});
|
|
||||||
public static YouTubeService Service
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (IsAuthorized)
|
|
||||||
return new YouTubeService(Initializer);
|
|
||||||
else
|
|
||||||
return NoAuthService;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
/// <summary>
|
||||||
|
/// Subscribes or unsibscribes authorized user from the channel
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The ID of channel which has to be added/removed</param>
|
||||||
|
/// <returns>Returns 'true' if channel is in subscriptions now; 'false' if it's not</returns>
|
||||||
public static async Task<bool> ChangeSubscriptionState(string id)
|
public static async Task<bool> ChangeSubscriptionState(string id)
|
||||||
{
|
{
|
||||||
if (!IsAuthorized)
|
if (!IsAuthorized)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(Subscriptions.Find(x => x.Snippet.ResourceId.ChannelId == id) != null)
|
if(Subscriptions.Exists(x => x.Snippet.ResourceId.ChannelId == id))
|
||||||
{
|
{
|
||||||
Subscription s = Subscriptions.Find(x => x.Snippet.ResourceId.ChannelId == id);
|
Subscription s = Subscriptions.Find(x => x.Snippet.ResourceId.ChannelId == id);
|
||||||
|
|
||||||
try { await Service.Subscriptions.Delete(s.Id).ExecuteAsync(); }
|
try { await Service.Subscriptions.Delete(s.Id).ExecuteAsync(); }
|
||||||
catch { return true; }
|
catch { return true; }
|
||||||
|
|
||||||
SubscriptionsChanged.Invoke(null, "remove", Subscriptions.IndexOf(s));
|
SubscriptionsChanged?.Invoke(null, "remove", Subscriptions.IndexOf(s));
|
||||||
Subscriptions.Remove(s);
|
Subscriptions.Remove(s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -91,69 +88,20 @@ namespace FoxTube
|
|||||||
if (s == null)
|
if (s == null)
|
||||||
return false;
|
return false;
|
||||||
Subscriptions.Add(s);
|
Subscriptions.Add(s);
|
||||||
SubscriptionsChanged.Invoke(null, "add", s);
|
SubscriptionsChanged?.Invoke(null, "add", s);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<bool> Subscribe(string id)
|
/// <summary>
|
||||||
{
|
/// Prompts to add an Youtube account and retrieves its info when successful
|
||||||
if (!IsAuthorized)
|
/// </summary>
|
||||||
return false;
|
/// <param name="retrieveSubs">Loads user's subscriptions if true</param>
|
||||||
|
public static async void Authorize(bool retrieveSubs = true)
|
||||||
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> Unsubscibe(string id)
|
|
||||||
{
|
|
||||||
if (!IsAuthorized)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Subscription s = null;
|
|
||||||
foreach(Subscription i in Subscriptions)
|
|
||||||
if (i.Snippet.ResourceId.ChannelId == id)
|
|
||||||
{
|
|
||||||
s = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (s == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Service.Subscriptions.Delete(s.Id).ExecuteAsync();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SubscriptionsChanged.Invoke(null, "remove", Subscriptions.IndexOf(s));
|
|
||||||
Subscriptions.Remove(s);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async void Authorize()
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#region Retrieving user's credential
|
||||||
Credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
|
Credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
|
||||||
Secrets,
|
Secrets,
|
||||||
new[]
|
new[]
|
||||||
@@ -164,121 +112,98 @@ namespace FoxTube
|
|||||||
"user",
|
"user",
|
||||||
CancellationToken.None);
|
CancellationToken.None);
|
||||||
|
|
||||||
if (Credential != null)
|
if (Credential == null || !retrieveSubs)
|
||||||
{
|
goto InvokeEvent;
|
||||||
if (settings.Values["authorized"] == null)
|
|
||||||
settings.Values.Add("authorized", true);
|
|
||||||
else settings.Values["authorized"] = true;
|
|
||||||
IsAuthorized = true;
|
|
||||||
|
|
||||||
|
SettingsStorage.HasAccount = true;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Retrieving user's data
|
||||||
var request = Service.Channels.List("snippet,contentDetails");
|
var request = Service.Channels.List("snippet,contentDetails");
|
||||||
request.Mine = true;
|
request.Mine = true;
|
||||||
UserChannel = (await request.ExecuteAsync()).Items[0];
|
UserChannel = (await request.ExecuteAsync()).Items[0];
|
||||||
AccountId = UserChannel.Id;
|
|
||||||
|
|
||||||
PlaylistItemsResource.ListRequest playlistRequest = Service.PlaylistItems.List("snippet");
|
|
||||||
playlistRequest.PlaylistId = UserChannel.ContentDetails.RelatedPlaylists.WatchHistory;
|
|
||||||
playlistRequest.MaxResults = 50;
|
|
||||||
PlaylistItemListResponse playlistResponse = await playlistRequest.ExecuteAsync();
|
|
||||||
UserHistory.Clear();
|
|
||||||
foreach (PlaylistItem i in playlistResponse.Items)
|
|
||||||
UserHistory.Add(i);
|
|
||||||
|
|
||||||
playlistRequest = Service.PlaylistItems.List("snippet");
|
|
||||||
playlistRequest.PlaylistId = UserChannel.ContentDetails.RelatedPlaylists.WatchLater;
|
|
||||||
playlistRequest.MaxResults = 50;
|
|
||||||
playlistResponse = await playlistRequest.ExecuteAsync();
|
|
||||||
WatchLater.Clear();
|
|
||||||
|
|
||||||
foreach (PlaylistItem i in playlistResponse.Items)
|
|
||||||
WatchLater.Add(i);
|
|
||||||
|
|
||||||
string nextToken = playlistResponse.NextPageToken;
|
|
||||||
while (nextToken != null)
|
|
||||||
{
|
|
||||||
playlistRequest.PageToken = nextToken;
|
|
||||||
playlistResponse = await playlistRequest.ExecuteAsync();
|
|
||||||
foreach (PlaylistItem i in playlistResponse.Items)
|
|
||||||
WatchLater.Add(i);
|
|
||||||
|
|
||||||
nextToken = playlistResponse.NextPageToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
SubscriptionsResource.ListRequest subRequest = Service.Subscriptions.List("snippet");
|
SubscriptionsResource.ListRequest subRequest = Service.Subscriptions.List("snippet");
|
||||||
subRequest.Mine = true;
|
subRequest.Mine = true;
|
||||||
subRequest.MaxResults = 50;
|
subRequest.MaxResults = 50;
|
||||||
subRequest.Order = SubscriptionsResource.ListRequest.OrderEnum.Relevance;
|
subRequest.Order = SubscriptionsResource.ListRequest.OrderEnum.Relevance;
|
||||||
SubscriptionListResponse subResponse = await subRequest.ExecuteAsync();
|
SubscriptionListResponse subResponse;
|
||||||
|
string nextToken = null;
|
||||||
Subscriptions.Clear();
|
Subscriptions.Clear();
|
||||||
|
|
||||||
foreach (Subscription s in subResponse.Items)
|
do
|
||||||
Subscriptions.Add(s);
|
|
||||||
|
|
||||||
nextToken = subResponse.NextPageToken;
|
|
||||||
while (nextToken != null)
|
|
||||||
{
|
{
|
||||||
subRequest.PageToken = nextToken;
|
subRequest.PageToken = nextToken;
|
||||||
subResponse = await subRequest.ExecuteAsync();
|
subResponse = await subRequest.ExecuteAsync();
|
||||||
foreach (Subscription s in subResponse.Items)
|
foreach (Subscription s in subResponse.Items)
|
||||||
Subscriptions.Add(s);
|
Subscriptions.Add(s);
|
||||||
}
|
nextToken = subResponse.NextPageToken;
|
||||||
}
|
|
||||||
|
} while (!string.IsNullOrWhiteSpace(nextToken));
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
//Saving user's subscriptions for background task
|
||||||
|
SaveSubscriptions();
|
||||||
|
|
||||||
|
InvokeEvent:
|
||||||
|
AuthorizationStateChanged?.Invoke(args: IsAuthorized);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
MessageDialog dialog = new MessageDialog("We were unabled to retrieve your account information due to weak internet connection or Google servers' problems. PLease, try again later", "Failed to connect");
|
AuthorizationStateChanged?.Invoke(args: new bool?[] { null });
|
||||||
|
}
|
||||||
dialog.Commands.Add(new UICommand("Try again", (command) =>
|
|
||||||
{
|
|
||||||
Authorize();
|
|
||||||
}));
|
|
||||||
dialog.Commands.Add(new UICommand("Quit", (command) =>
|
|
||||||
{
|
|
||||||
Methods.CloseApp();
|
|
||||||
}));
|
|
||||||
dialog.Commands.Add(new UICommand("Close"));
|
|
||||||
|
|
||||||
await dialog.ShowAsync();
|
|
||||||
|
|
||||||
IsAuthorized = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthorizationStateChanged.Invoke(null, null);
|
/// <summary>
|
||||||
|
/// Saves user's subscriptions keypairs (channel ID: avatar URL) into "background.json" file for concurrent background processing
|
||||||
|
/// </summary>
|
||||||
|
public static async void SaveSubscriptions()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> subs = new Dictionary<string, string>();
|
||||||
|
Subscriptions.ForEach(x => subs.Add(x.Snippet.ResourceId.ChannelId, x.Snippet.Thumbnails.Medium.Url));
|
||||||
|
await FileIO.WriteTextAsync(
|
||||||
|
await ApplicationData.Current.RoamingFolder.CreateFileAsync("background.json", CreationCollisionOption.ReplaceExisting),
|
||||||
|
JsonConvert.SerializeObject(subs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deauthenticates current user
|
||||||
|
/// </summary>
|
||||||
public static async void Deauthenticate()
|
public static async void Deauthenticate()
|
||||||
{
|
{
|
||||||
if(await Credential.RevokeTokenAsync(CancellationToken.None))
|
if(await Credential.RevokeTokenAsync(CancellationToken.None))
|
||||||
{
|
{
|
||||||
Credential = null;
|
Credential = null;
|
||||||
IsAuthorized = false;
|
AuthorizationStateChanged?.Invoke(args: false);
|
||||||
AuthorizationStateChanged.Invoke(null, null);
|
SettingsStorage.HasAccount = false;
|
||||||
settings.Values["authorized"] = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CheckAuthorization()
|
/// <summary>
|
||||||
|
/// Checks if any user has already been logged in. If has, calls *Authorize()* to retrieve his info
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="retrieveSubs">Loads user's subscriptions if true</param>
|
||||||
|
public static void CheckAuthorization(bool retrieveSubs = true)
|
||||||
{
|
{
|
||||||
if (settings.Values["authorized"] == null || !(bool)settings.Values["authorized"])
|
if (SettingsStorage.HasAccount)
|
||||||
IsAuthorized = false;
|
Authorize(retrieveSubs);
|
||||||
else
|
else AuthorizationStateChanged.Invoke(args: false);
|
||||||
Authorize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool AdsDisabled { get; private set; } = true;
|
/// <summary>
|
||||||
|
/// Connects to MS Store and checks if user has bought ad-free
|
||||||
|
/// </summary>
|
||||||
public static void CheckAddons()
|
public static void CheckAddons()
|
||||||
{
|
{
|
||||||
//TO-DO: Check addons list
|
//TODO: Check addons list
|
||||||
bool purchased = true;
|
bool purchased = true;
|
||||||
|
|
||||||
if(!purchased)
|
if(!purchased)
|
||||||
{
|
{
|
||||||
AdsDisabled = false;
|
AdsDisabled = false;
|
||||||
NotPurchased.Invoke();
|
NotPurchased?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
public static event Event NotPurchased;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,194 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using Windows.ApplicationModel;
|
||||||
|
using Windows.Storage;
|
||||||
|
|
||||||
|
namespace FoxTube
|
||||||
|
{
|
||||||
|
public static class SettingsStorage
|
||||||
|
{
|
||||||
|
public static string VideoQuality
|
||||||
|
{
|
||||||
|
get { return (string)settings[0]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[0] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static string RememberedQuality
|
||||||
|
{
|
||||||
|
get { return (string)settings[1]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[1] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool VideoNotifications
|
||||||
|
{
|
||||||
|
get { return (bool)settings[2]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[2] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool DevNotifications
|
||||||
|
{
|
||||||
|
get { return (bool)settings[3]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[3] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CheckConnection
|
||||||
|
{
|
||||||
|
get { return (bool)settings[4]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[4] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool Autoplay
|
||||||
|
{
|
||||||
|
get { return (bool)settings[5]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[5] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static int Volume
|
||||||
|
{
|
||||||
|
get { return Convert.ToInt32(settings[6]); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[6] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Language
|
||||||
|
{
|
||||||
|
get { return (string)settings[7]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[7] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static string Region
|
||||||
|
{
|
||||||
|
get { return (string)settings[8]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[8] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static int SafeSearch
|
||||||
|
{
|
||||||
|
get { return Convert.ToInt32(settings[9]); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[9] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Theme
|
||||||
|
{
|
||||||
|
get { return Convert.ToInt32(settings[10]); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[10] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool HasAccount
|
||||||
|
{
|
||||||
|
get { return (bool)settings[11]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
settings[11] = value;
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Version
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (storage.Values["ver"] == null)
|
||||||
|
{
|
||||||
|
PackageVersion ver = Package.Current.Id.Version;
|
||||||
|
storage.Values["version"] = $"{ver.Major}.{ver.Minor}";
|
||||||
|
return $"{ver.Major}.{ver.Minor}";
|
||||||
|
}
|
||||||
|
else return (string)storage.Values["version"];
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
storage.Values["version"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Settings storage
|
||||||
|
private static readonly ApplicationDataContainer storage = ApplicationData.Current.LocalSettings;
|
||||||
|
|
||||||
|
//Predefined preferences
|
||||||
|
private static object[] settings = new object[]
|
||||||
|
{
|
||||||
|
"remember",
|
||||||
|
"1080p",
|
||||||
|
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
100,
|
||||||
|
|
||||||
|
(new[] { "ua", "ru", "by", "kz", "kg", "md", "lv", "ee" }).Contains(CultureInfo.InstalledUICulture.TwoLetterISOLanguageName) ? "ru-RU" : "en-US",
|
||||||
|
CultureInfo.CurrentCulture.Name,
|
||||||
|
0,
|
||||||
|
|
||||||
|
2,
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
public static void LoadData()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
settings = JsonConvert.DeserializeObject<object[]>(storage.Values["settings"] as string);
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async void SaveData()
|
||||||
|
{
|
||||||
|
storage.Values["settings"] = JsonConvert.SerializeObject(settings);
|
||||||
|
ExportSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async void ExportSettings()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool[] notificationsSettings = new[] { VideoNotifications, DevNotifications };
|
||||||
|
await FileIO.WriteTextAsync(
|
||||||
|
await ApplicationData.Current.RoamingFolder.CreateFileAsync("notifications.json", CreationCollisionOption.ReplaceExisting),
|
||||||
|
JsonConvert.SerializeObject(notificationsSettings));
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Class="FoxTube.Controls.Advert"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:ad="using:Microsoft.Advertising.WinRT.UI"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Grid Name="grid" SizeChanged="Grid_SizeChanged">
|
||||||
|
<ad:AdControl VerticalAlignment="Top"
|
||||||
|
Name="ad" ApplicationId="{x:Bind AppId}"
|
||||||
|
AdUnitId="{x:Bind AdUnitId}"
|
||||||
|
Height="50"
|
||||||
|
Width="300"/>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace FoxTube.Controls
|
||||||
|
{
|
||||||
|
public sealed partial class Advert : UserControl
|
||||||
|
{
|
||||||
|
public string AdUnitId { get; set; } = "test";
|
||||||
|
public string AppId => "3f83fe91-d6be-434d-a0ae-7351c5a997f1";
|
||||||
|
public bool OverrideSize { get; set; } = false;
|
||||||
|
|
||||||
|
public new double Height
|
||||||
|
{
|
||||||
|
get { return ad.Height; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ad.Height = value;
|
||||||
|
OverrideSize = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public new double Width
|
||||||
|
{
|
||||||
|
get { return ad.Width; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ad.Width = value;
|
||||||
|
OverrideSize = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Advert()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
if (!SecretsVault.AdsDisabled)
|
||||||
|
Visibility = Visibility.Visible;
|
||||||
|
else
|
||||||
|
Visibility = Visibility.Collapsed;
|
||||||
|
SecretsVault.NotPurchased += () => Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (OverrideSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(grid.ActualWidth >= 728)
|
||||||
|
{
|
||||||
|
ad.Width = 728;
|
||||||
|
ad.Height = 90;
|
||||||
|
}
|
||||||
|
else if (grid.ActualWidth >= 640)
|
||||||
|
{
|
||||||
|
ad.Width = 640;
|
||||||
|
ad.Height = 100;
|
||||||
|
}
|
||||||
|
else if (grid.ActualWidth >= 320)
|
||||||
|
{
|
||||||
|
ad.Width = 320;
|
||||||
|
ad.Height = 50;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ad.Width = 300;
|
||||||
|
ad.Height = 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ namespace FoxTube.Controls
|
|||||||
|
|
||||||
public async void Initialize(string id, string live)
|
public async void Initialize(string id, string live)
|
||||||
{
|
{
|
||||||
ChannelsResource.ListRequest request = SecretsVault.NoAuthService.Channels.List("snippet,statistics,brandingSettings");
|
ChannelsResource.ListRequest request = SecretsVault.Service.Channels.List("snippet,statistics,brandingSettings");
|
||||||
request.Id = id;
|
request.Id = id;
|
||||||
ChannelListResponse response = await request.ExecuteAsync();
|
ChannelListResponse response = await request.ExecuteAsync();
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
<UserControl
|
|
||||||
x:Class="FoxTube.Controls.ChannelCardWide"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:FoxTube"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
Height="150">
|
|
||||||
|
|
||||||
<Button Padding="0" Background="WhiteSmoke" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Margin="2" VerticalAlignment="Stretch" Click="Button_Click">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="125"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<PersonPicture Name="avatar" Width="125"/>
|
|
||||||
<StackPanel Orientation="Vertical" Grid.Column="1" Padding="10,5,5,5" VerticalAlignment="Center">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<TextBlock Name="channelName" Text="IGP" FontSize="18"/>
|
|
||||||
<StackPanel Name="liveTag" Margin="5,0,0,0" BorderBrush="Red" BorderThickness="2" VerticalAlignment="Center" HorizontalAlignment="Right" Padding="5,0,5,0" Height="20" Orientation="Horizontal" Visibility="Collapsed">
|
|
||||||
<TextBlock Text=" " VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Red" FontSize="12" FontFamily="Segoe MDL2 Assets" Margin="0,1,0,0" FontWeight="Black"/>
|
|
||||||
<TextBlock Text="LIVE" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Red" FontSize="12" FontWeight="Bold"/>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
<TextBlock Name="subscribers" Text="120,452 subscribers" Foreground="Gray"/>
|
|
||||||
<TextBlock Name="videoCount" Foreground="Gray" Text="563,000 videos"/>
|
|
||||||
<StackPanel Orientation="Horizontal" Margin="0,5,0,0" Name="subscriptionPane">
|
|
||||||
<ToggleButton Grid.Column="2" Height="40" Width="200" Background="Red" Foreground="White" FontSize="18" FontWeight="SemiBold" Content="Subscirbe"/>
|
|
||||||
<ToggleButton Grid.Column="3" Height="40" Width="40" FontFamily="Segoe MDL2 Assets" FontSize="18" FontWeight="SemiBold" Content="" Foreground="White" Background="Red"/>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</Button>
|
|
||||||
</UserControl>
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
|
||||||
using Windows.UI.Xaml.Media.Imaging;
|
|
||||||
using Google.Apis.Services;
|
|
||||||
using Google.Apis.YouTube.v3;
|
|
||||||
using Google.Apis.YouTube.v3.Data;
|
|
||||||
|
|
||||||
namespace FoxTube.Controls
|
|
||||||
{
|
|
||||||
public sealed partial class ChannelCardWide : UserControl
|
|
||||||
{
|
|
||||||
string channelId;
|
|
||||||
public ChannelCardWide(string id, string live)
|
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
Initialize(id, live);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Initialize(string id, string live)
|
|
||||||
{
|
|
||||||
YouTubeService ytService = new YouTubeService(new BaseClientService.Initializer()
|
|
||||||
{
|
|
||||||
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
|
||||||
ApplicationName = this.GetType().ToString()
|
|
||||||
});
|
|
||||||
|
|
||||||
ChannelsResource.ListRequest request = ytService.Channels.List("snippet,contentDetails,statistics");
|
|
||||||
request.Id = id;
|
|
||||||
ChannelListResponse response = await request.ExecuteAsync();
|
|
||||||
|
|
||||||
var item = response.Items[0];
|
|
||||||
|
|
||||||
channelId = id;
|
|
||||||
|
|
||||||
channelName.Text = item.Snippet.Title;
|
|
||||||
subscribers.Text = string.Format("{0} subscribers", item.Statistics.SubscriberCount);
|
|
||||||
videoCount.Text = string.Format("{0} videos", item.Statistics.VideoCount);
|
|
||||||
|
|
||||||
avatar.ProfilePicture = new BitmapImage(new Uri(item.Snippet.Thumbnails.Medium.Url));
|
|
||||||
if (live == "live")
|
|
||||||
liveTag.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Button_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
Methods.MainPage.GoToChannel(channelId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
d:DesignWidth="1500">
|
d:DesignWidth="1500">
|
||||||
|
|
||||||
<!--<Button HorizontalAlignment="Stretch" Background="WhiteSmoke" Height="100" Padding="0" HorizontalContentAlignment="Stretch"/>-->
|
<!--<Button HorizontalAlignment="Stretch" Background="WhiteSmoke" Height="100" Padding="0" HorizontalContentAlignment="Stretch"/>-->
|
||||||
<Grid Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}" Height="100">
|
<Grid Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}" Height="100" HorizontalAlignment="Stretch" Margin="5">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
@@ -19,10 +19,11 @@
|
|||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Image Name="thumbnail" Source="/Assets/videoThumbSample.png"/>
|
<Image Name="thumbnail" Source="/Assets/videoThumbSample.png"/>
|
||||||
<TextBlock Name="title" Grid.Column="1" Margin="5" TextWrapping="WrapWholeWords" Text="[Title]" FontSize="20" MaxLines="3"/>
|
<TextBlock Name="title" Grid.Column="1" Margin="5" TextWrapping="WrapWholeWords" Text="[Title]" FontSize="20" MaxLines="2"/>
|
||||||
|
<TextBlock Margin="5" Name="path" Grid.Column="1" VerticalAlignment="Bottom" Text="C://Users/Michael Gordeev/Downloads/[Title].mp4" Foreground="LightGray" MaxLines="1" TextWrapping="WrapWholeWords"/>
|
||||||
|
|
||||||
<StackPanel Grid.Column="2" Margin="5">
|
<StackPanel Grid.Column="2" Margin="5">
|
||||||
<TextBlock Text="Extension:" Foreground="Gray"/>
|
<TextBlock Text="Extension:" Foreground="Gray" Name="ext"/>
|
||||||
<TextBlock Text="Quality:" Foreground="Gray" Name="quality"/>
|
<TextBlock Text="Quality:" Foreground="Gray" Name="quality"/>
|
||||||
<TextBlock Text="Duration:" Foreground="Gray" Name="duration"/>
|
<TextBlock Text="Duration:" Foreground="Gray" Name="duration"/>
|
||||||
<TextBlock Text="Author:" Foreground="Gray" Name="channel"/>
|
<TextBlock Text="Author:" Foreground="Gray" Name="channel"/>
|
||||||
@@ -43,10 +44,10 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Name="progressPanel" Grid.Column="4" Margin="10">
|
<StackPanel Name="progressPanel" Grid.Column="4" Margin="10">
|
||||||
<TextBlock Name="status" Text="Initializing..." HorizontalAlignment="Left"/>
|
<TextBlock Name="status" Text="Downloading..." HorizontalAlignment="Left"/>
|
||||||
<ProgressBar Name="progressBar" Width="200" IsIndeterminate="True" Foreground="Red"/>
|
<ProgressBar Name="progressBar" Width="200" Maximum="1" IsIndeterminate="True" Foreground="Red"/>
|
||||||
<TextBlock Name="perc" Text="--%"/>
|
<TextBlock Name="perc" Text="--%"/>
|
||||||
<Button Content="Cancel" Name="cancel" Click="cancel_Click" HorizontalAlignment="Right"/>
|
<Button Content="Cancel" Name="cancel" Click="CancelPrompt" HorizontalAlignment="Right"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -2,80 +2,191 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using System.Net;
|
|
||||||
using Windows.UI.Xaml.Media.Imaging;
|
using Windows.UI.Xaml.Media.Imaging;
|
||||||
using Windows.System;
|
using Windows.System;
|
||||||
using FoxTube.Classes;
|
using FoxTube.Classes;
|
||||||
using YoutubeExplode.Models.MediaStreams;
|
using YoutubeExplode.Models.MediaStreams;
|
||||||
|
using YoutubeExplode;
|
||||||
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
using Windows.Storage;
|
||||||
|
using Google.Apis.YouTube.v3.Data;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Xml;
|
||||||
|
using Windows.UI.Popups;
|
||||||
|
using Windows.UI.Notifications;
|
||||||
|
using Microsoft.Toolkit.Uwp.Notifications;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FoxTube.Controls
|
namespace FoxTube.Controls
|
||||||
{
|
{
|
||||||
public sealed partial class DownloadItem : UserControl
|
public sealed partial class DownloadItem : UserControl
|
||||||
{
|
{
|
||||||
public DownloadItemContainer Container { get; private set; }
|
public DownloadItemContainer Container { get; private set; }
|
||||||
|
public StorageFile file;
|
||||||
public bool InProgress { get; set; } = false;
|
public bool InProgress { get; set; } = false;
|
||||||
|
|
||||||
public DownloadItem(string url)
|
readonly YoutubeClient client = new YoutubeClient();
|
||||||
|
readonly CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
|
CancellationToken token;
|
||||||
|
readonly Progress<double> progress = new Progress<double>();
|
||||||
|
private readonly NotificationData data = new NotificationData();
|
||||||
|
|
||||||
|
DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
|
||||||
|
double percentage;
|
||||||
|
|
||||||
|
public DownloadItem(MediaStreamInfo info, Video meta, string q)
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
Download(url);
|
Download(info, meta, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownloadItem(DownloadItemContainer container)
|
public DownloadItem(DownloadItemContainer container)
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Container = container;
|
Container = container;
|
||||||
if (!File.Exists(container.Path.AbsolutePath))
|
Initialize();
|
||||||
throw new FileNotFoundException();
|
}
|
||||||
|
|
||||||
|
public async void Initialize()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file = await DownloadAgent.Downloads.GetFileAsync(Container.Name);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
DownloadAgent.Remove(Container.Id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
title.Text = Container.Title;
|
title.Text = Container.Title;
|
||||||
|
path.Text = file.Name;
|
||||||
thumbnail.Source = new BitmapImage(Container.Thumbnail);
|
thumbnail.Source = new BitmapImage(Container.Thumbnail);
|
||||||
quality.Text = $"Quality: {Container.Quality.GetVideoQualityLabel()}";
|
quality.Text = $"Quality: {Container.Quality}";
|
||||||
duration.Text = $"Duration: {Container.Duration}";
|
duration.Text = $"Duration: {Container.Duration}";
|
||||||
channel.Text = $"Author: {Container.Channel}";
|
channel.Text = $"Author: {Container.Channel}";
|
||||||
|
ext.Text = $"Extension: {Container.Extension}";
|
||||||
|
|
||||||
progressPanel.Visibility = Visibility.Collapsed;
|
progressPanel.Visibility = Visibility.Collapsed;
|
||||||
donePanel.Visibility = Visibility.Visible;
|
donePanel.Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Download(string url)
|
async void Download(MediaStreamInfo info, Video meta, string q)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InProgress = true;
|
||||||
|
Container = new DownloadItemContainer();
|
||||||
|
|
||||||
|
token = cts.Token;
|
||||||
|
progress.ProgressChanged += (s, e) => percentage = e;
|
||||||
|
timer.Tick += (s, e) => UpdateInfo(percentage);
|
||||||
|
|
||||||
|
file = await DownloadAgent.Downloads.CreateFileAsync($"{meta.Snippet.Title.ReplaceInvalidChars('_')}.{info.Container.GetFileExtension()}", CreationCollisionOption.GenerateUniqueName);
|
||||||
|
Container.Name = file.Name;
|
||||||
|
|
||||||
|
ToastContent toastContent = new ToastContent()
|
||||||
|
{
|
||||||
|
Visual = new ToastVisual()
|
||||||
|
{
|
||||||
|
BindingGeneric = new ToastBindingGeneric()
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new AdaptiveText() { Text = "Downloading a video" },
|
||||||
|
new AdaptiveProgressBar()
|
||||||
|
{
|
||||||
|
Title = meta.Snippet.Title,
|
||||||
|
Status = "Downloading...",
|
||||||
|
Value = new BindableProgressBarValue("value")
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateInfo(object sender, DownloadProgressChangedEventArgs e)
|
|
||||||
{
|
|
||||||
progressBar.Value = e.ProgressPercentage;
|
|
||||||
perc.Text = $"{e.ProgressPercentage}%";
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
private void DownloadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
|
Actions = new ToastActionsCustom()
|
||||||
{
|
{
|
||||||
/*progressPanel.Visibility = Visibility.Collapsed;
|
Buttons =
|
||||||
|
{
|
||||||
|
new ToastButton("Cancel", $"dcancel|{Container.Id}")
|
||||||
|
{
|
||||||
|
ActivationType = ToastActivationType.Background
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Launch = "download",
|
||||||
|
ActivationType = ToastActivationType.Foreground
|
||||||
|
};
|
||||||
|
|
||||||
|
data.Values["value"] = "0";
|
||||||
|
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toastContent.GetXml()) { Tag = $"download|{meta.Id}", Data = data });
|
||||||
|
|
||||||
|
Container.Channel = meta.Snippet.ChannelTitle;
|
||||||
|
Container.Duration = XmlConvert.ToTimeSpan(meta.ContentDetails.Duration);
|
||||||
|
Container.Id = meta.Id;
|
||||||
|
Container.Quality = q;
|
||||||
|
Container.Thumbnail = meta.Snippet.Thumbnails.Medium.Url.ToUri();
|
||||||
|
Container.Title = meta.Snippet.Title;
|
||||||
|
Container.Extension = info.Container.GetFileExtension();
|
||||||
|
|
||||||
|
thumbnail.Source = new BitmapImage(new Uri(meta.Snippet.Thumbnails.Medium.Url));
|
||||||
|
title.Text = meta.Snippet.Title;
|
||||||
|
ext.Text = $"Extension: {info.Container.GetFileExtension()}";
|
||||||
|
quality.Text = $"Quality: {q}";
|
||||||
|
duration.Text = $"Duration: {XmlConvert.ToTimeSpan(meta.ContentDetails.Duration)}";
|
||||||
|
channel.Text = $"Author: {meta.Snippet.ChannelTitle}";
|
||||||
|
path.Text = file.Name;
|
||||||
|
|
||||||
|
progressPanel.Visibility = Visibility.Visible;
|
||||||
|
donePanel.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
timer.Start();
|
||||||
|
|
||||||
|
await client.DownloadMediaStreamAsync(info, await file.OpenStreamForWriteAsync(), progress, token);
|
||||||
|
|
||||||
|
progressPanel.Visibility = Visibility.Collapsed;
|
||||||
donePanel.Visibility = Visibility.Visible;
|
donePanel.Visibility = Visibility.Visible;
|
||||||
|
|
||||||
string node = $@"<item>
|
InProgress = false;
|
||||||
<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, node);*/
|
if (!cts.IsCancellationRequested)
|
||||||
|
DownloadCompleted();
|
||||||
|
}
|
||||||
|
catch (TaskCanceledException) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateInfo(double e)
|
||||||
|
{
|
||||||
|
progressBar.Value = e;
|
||||||
|
perc.Text = $"{(int)e * 100}%";
|
||||||
|
|
||||||
|
data.Values["value"] = e.ToString();
|
||||||
|
ToastNotificationManager.CreateToastNotifier().Update(data, $"download|{Container.Id}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DownloadCompleted()
|
||||||
|
{
|
||||||
|
Windows.Data.Xml.Dom.XmlDocument template = new Windows.Data.Xml.Dom.XmlDocument();
|
||||||
|
template.LoadXml($@"<toast activationType='background' launch='download|{file.Path}'>
|
||||||
|
<visual>
|
||||||
|
<binding template='ToastGeneric'>
|
||||||
|
<text>Download complete</text>
|
||||||
|
<text>{Container.Title}</text>
|
||||||
|
</binding>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<actions>
|
||||||
|
<action content='Go to original'
|
||||||
|
activationType='foreground'
|
||||||
|
arguments='video|{Container.Id}'/>
|
||||||
|
</actions>
|
||||||
|
</toast>");
|
||||||
|
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(template) { Tag = $"download|{Container.Id}" });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void open_Click(object sender, RoutedEventArgs e)
|
private async void open_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
await Launcher.LaunchUriAsync(Container.Path);
|
await Launcher.LaunchFileAsync(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void gotoOriginal_Click(object sender, RoutedEventArgs e)
|
private void gotoOriginal_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -83,30 +194,44 @@ namespace FoxTube.Controls
|
|||||||
Methods.MainPage.GoToVideo(Container.Id);
|
Methods.MainPage.GoToVideo(Container.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Cancel()
|
public async void Cancel()
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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...";
|
status.Text = "Cancelling...";
|
||||||
progressBar.IsIndeterminate = true;
|
progressBar.IsIndeterminate = true;
|
||||||
cancel.IsEnabled = false;
|
cancel.IsEnabled = false;
|
||||||
client.CancelAsync();
|
cts.Cancel();
|
||||||
DownloadCanceled.Invoke(this, null);
|
try
|
||||||
}));
|
{
|
||||||
|
await file.DeleteAsync();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
Windows.Data.Xml.Dom.XmlDocument template = new Windows.Data.Xml.Dom.XmlDocument();
|
||||||
|
template.LoadXml($@"<toast activationType='foreground' launch='download'>
|
||||||
|
<visual>
|
||||||
|
<binding template='ToastGeneric'>
|
||||||
|
<text>Download canceled</text>
|
||||||
|
<text>{Container.Title}</text>
|
||||||
|
</binding>
|
||||||
|
</visual>
|
||||||
|
</toast>");
|
||||||
|
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(template) { Tag = $"download|{Container.Id}" });
|
||||||
|
|
||||||
|
DownloadAgent.Remove(Container.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void CancelPrompt(object sender = null, RoutedEventArgs e = null)
|
||||||
|
{
|
||||||
|
if(InProgress)
|
||||||
|
{
|
||||||
|
MessageDialog dialog = new MessageDialog("Are you sure?", "Cancelling download");
|
||||||
|
|
||||||
|
dialog.Commands.Add(new UICommand("Yes", (command) => Cancel()));
|
||||||
dialog.Commands.Add(new UICommand("No"));
|
dialog.Commands.Add(new UICommand("No"));
|
||||||
|
|
||||||
dialog.DefaultCommandIndex = 1;
|
dialog.DefaultCommandIndex = 1;
|
||||||
await dialog.ShowAsync();
|
await dialog.ShowAsync();
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
<UserControl
|
|
||||||
x:Class="FoxTube.NotificationsCenter"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:FoxTube"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="400"
|
|
||||||
d:DesignWidth="300">
|
|
||||||
|
|
||||||
|
|
||||||
<StackPanel Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" Width="300" Margin="-10" MinHeight="400">
|
|
||||||
<Grid Height="50">
|
|
||||||
<TextBlock Text="Notifications" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold"/>
|
|
||||||
<Button Visibility="Collapsed" Background="Transparent" Foreground="Gray" FontFamily="Segoe MDL2 Assets" Content="" Height="50" Width="50" HorizontalAlignment="Right" ToolTipService.ToolTip="Clear all" Name="clear" Click="clear_Click"/>
|
|
||||||
</Grid>
|
|
||||||
<TextBlock Text="You have no any notification" Name="noNotifications" Foreground="Gray" FontStyle="Italic" Padding="10" Visibility="Visible"/>
|
|
||||||
<ScrollViewer>
|
|
||||||
<StackPanel Name="array"/>
|
|
||||||
</ScrollViewer>
|
|
||||||
</StackPanel>
|
|
||||||
</UserControl>
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
using FoxTube.Background;
|
|
||||||
using Microsoft.Toolkit.Uwp.Notifications;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using System.Xml;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.Storage;
|
|
||||||
using Windows.UI;
|
|
||||||
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 User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
|
||||||
|
|
||||||
namespace FoxTube
|
|
||||||
{
|
|
||||||
public sealed partial class NotificationsCenter : UserControl
|
|
||||||
{
|
|
||||||
List<Notification> notifications = new List<Notification>();
|
|
||||||
|
|
||||||
private ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
|
||||||
XmlDocument doc = new XmlDocument();
|
|
||||||
public NotificationsCenter()
|
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Initialize()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
doc.LoadXml(settings.Values["notificationsHistory"] as string);
|
|
||||||
foreach (XmlElement n in doc["history"].ChildNodes)
|
|
||||||
AddNotification(new Notification(n.ToString()));
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
BackgroundProcessor.NotificationRecieved += NewNotification;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NewNotification(object sender, Notification item)
|
|
||||||
{
|
|
||||||
AddNotification(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clear_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
array.Children.Clear();
|
|
||||||
notifications.Clear();
|
|
||||||
doc["history"].InnerXml = "";
|
|
||||||
settings.Values["notificationsHistory"] = doc.InnerXml;
|
|
||||||
clear.Visibility = Visibility.Collapsed;
|
|
||||||
noNotifications.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddNotification(Notification notification)
|
|
||||||
{
|
|
||||||
notifications.Add(notification);
|
|
||||||
Methods.MainPage.GotNotification();
|
|
||||||
noNotifications.Visibility = Visibility.Collapsed;
|
|
||||||
clear.Visibility = Visibility.Visible;
|
|
||||||
|
|
||||||
Button item = notification.GetNotification();
|
|
||||||
item.Click += Notification_Click;
|
|
||||||
|
|
||||||
array.Children.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Notification_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
Notification n = notifications[array.Children.IndexOf(sender as Button)];
|
|
||||||
switch(n.Type)
|
|
||||||
{
|
|
||||||
case NotificationType.Changelog:
|
|
||||||
case NotificationType.Internal:
|
|
||||||
Methods.MainPage.GoToDeveloper(n.Id);
|
|
||||||
break;
|
|
||||||
case NotificationType.Video:
|
|
||||||
Methods.MainPage.GoToVideo(n.Id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +1,29 @@
|
|||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
using System;
|
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;
|
||||||
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.Imaging;
|
using Windows.UI.Xaml.Media.Imaging;
|
||||||
using Windows.UI.Xaml.Navigation;
|
|
||||||
|
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
|
||||||
|
|
||||||
namespace FoxTube.Controls
|
namespace FoxTube.Controls
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
/// Playlist card control
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class PlaylistCard : Page
|
public sealed partial class PlaylistCard : Page
|
||||||
{
|
{
|
||||||
Playlist item;
|
Playlist item;
|
||||||
string playlistId;
|
public string playlistId;
|
||||||
|
|
||||||
public PlaylistCard(string id)
|
public PlaylistCard(string id)
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
Initialize(id);
|
Initialize(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Initialize(string id)
|
public async void Initialize(string id)
|
||||||
{
|
{
|
||||||
PlaylistsResource.ListRequest request = SecretsVault.NoAuthService.Playlists.List("snippet,contentDetails");
|
PlaylistsResource.ListRequest request = SecretsVault.Service.Playlists.List("snippet,contentDetails");
|
||||||
request.Id = id;
|
request.Id = id;
|
||||||
PlaylistListResponse response = await request.ExecuteAsync();
|
PlaylistListResponse response = await request.ExecuteAsync();
|
||||||
|
|
||||||
@@ -48,7 +35,7 @@ namespace FoxTube.Controls
|
|||||||
counter.Text = item.ContentDetails.ItemCount.ToString();
|
counter.Text = item.ContentDetails.ItemCount.ToString();
|
||||||
date.Text = Methods.GetAgo(item.Snippet.PublishedAt.Value);
|
date.Text = Methods.GetAgo(item.Snippet.PublishedAt.Value);
|
||||||
|
|
||||||
ChannelsResource.ListRequest r = SecretsVault.NoAuthService.Channels.List("snippet");
|
ChannelsResource.ListRequest r = SecretsVault.Service.Channels.List("snippet");
|
||||||
r.Id = item.Snippet.ChannelId;
|
r.Id = item.Snippet.ChannelId;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
<UserControl
|
|
||||||
x:Class="FoxTube.PlaylistCardWide"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:FoxTube"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
Height="175">
|
|
||||||
|
|
||||||
<Button Padding="0" Background="WhiteSmoke" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Margin="2">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<Grid>
|
|
||||||
<Image Name="thumbnail" Source="/Assets/videoThumbSample.png"/>
|
|
||||||
<Grid HorizontalAlignment="Right" Width="100">
|
|
||||||
<Grid.Background>
|
|
||||||
<AcrylicBrush TintColor="#7F000000" BackgroundSource="Backdrop" AlwaysUseFallback="False" TintOpacity="1" Opacity="0.97"/>
|
|
||||||
</Grid.Background>
|
|
||||||
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
|
|
||||||
<TextBlock HorizontalAlignment="Center" FontFamily="Segoe MDL2 Assets" Foreground="White" Text="" FontSize="30"/>
|
|
||||||
<TextBlock Foreground="White" Text="[N/A]" HorizontalAlignment="Center" FontSize="20" Name="thumbCount"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid Margin="10" HorizontalAlignment="Stretch">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="75"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<StackPanel Orientation="Vertical">
|
|
||||||
<TextBlock Name="title" TextWrapping="WrapWholeWords" Text="[Title]" FontSize="20" MaxLines="2"/>
|
|
||||||
<TextBlock Name="info" Text="[Published at] | [Video count]" Foreground="Gray"/>
|
|
||||||
</StackPanel>
|
|
||||||
<Grid Grid.Row="1" Name="authorData">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="75"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<PersonPicture Name="avatar" Width="75" HorizontalAlignment="Left"/>
|
|
||||||
<StackPanel Orientation="Vertical" Grid.Column="1" Padding="10,5,5,5" VerticalAlignment="Center">
|
|
||||||
<TextBlock Name="channelName" Text="[Channel name]" FontSize="18"/>
|
|
||||||
<TextBlock Name="channelSubs" Text="[Subscribers]" Foreground="Gray"/>
|
|
||||||
<HyperlinkButton Name="channelLink" Content="Go to channel" Padding="0" Click="channelLink_Click"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
</UserControl>
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
|
||||||
using Windows.UI.Xaml.Controls.Primitives;
|
|
||||||
using Windows.UI.Xaml.Data;
|
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
using Windows.UI.Xaml.Media.Imaging;
|
|
||||||
using Windows.UI.Xaml.Navigation;
|
|
||||||
|
|
||||||
using Google.Apis.Services;
|
|
||||||
using Google.Apis.YouTube.v3;
|
|
||||||
using Google.Apis.YouTube.v3.Data;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Threading;
|
|
||||||
using Google.Apis.Util.Store;
|
|
||||||
|
|
||||||
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
|
||||||
|
|
||||||
namespace FoxTube
|
|
||||||
{
|
|
||||||
public sealed partial class PlaylistCardWide : UserControl
|
|
||||||
{
|
|
||||||
public string playlistId;
|
|
||||||
Playlist item;
|
|
||||||
public PlaylistCardWide(string id, bool hideAuthor = false)
|
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
Initialize(id, hideAuthor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Initialize(string id, bool hideAuthor)
|
|
||||||
{
|
|
||||||
PlaylistsResource.ListRequest request = SecretsVault.NoAuthService.Playlists.List("snippet,contentDetails");
|
|
||||||
request.Id = id;
|
|
||||||
PlaylistListResponse response = await request.ExecuteAsync();
|
|
||||||
|
|
||||||
item = response.Items[0];
|
|
||||||
|
|
||||||
playlistId = id;
|
|
||||||
|
|
||||||
title.Text = item.Snippet.Title;
|
|
||||||
info.Text = string.Format("{0} | {1} videos", item.Snippet.PublishedAt, item.ContentDetails.ItemCount);
|
|
||||||
thumbCount.Text = item.ContentDetails.ItemCount.ToString();
|
|
||||||
thumbnail.Source = new BitmapImage(new Uri(item.Snippet.Thumbnails.Medium.Url));
|
|
||||||
|
|
||||||
if (hideAuthor)
|
|
||||||
authorData.Visibility = Visibility.Collapsed;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var request1 = SecretsVault.NoAuthService.Channels.List("snippet,contentDetails,statistics");
|
|
||||||
request1.Id = item.Snippet.ChannelId;
|
|
||||||
ChannelListResponse response1 = await request1.ExecuteAsync();
|
|
||||||
|
|
||||||
var item1 = response1.Items[0];
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void channelLink_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
Methods.MainPage.GoToChannel(item.Snippet.ChannelId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,10 +18,11 @@
|
|||||||
<RowDefinition Height="75"/>
|
<RowDefinition Height="75"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Image Name="thumbnail" Source="/Assets/videoThumbSample.png" Stretch="Fill"/>
|
<Image Name="thumbnail" Source="/Assets/videoThumbSample.png" Stretch="Fill"/>
|
||||||
<Grid Background="{ThemeResource ButtonBackgroundThemeBrush}" Name="watched" Visibility="Collapsed">
|
<Grid Background="#7F000000" Name="watched" Visibility="Collapsed">
|
||||||
<StackPanel Margin="5" Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}" VerticalAlignment="Top" HorizontalAlignment="Left" Padding="5,2,5,2" BorderBrush="Gray" BorderThickness="1">
|
<StackPanel Margin="5" Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}" VerticalAlignment="Top" HorizontalAlignment="Left" Padding="5,2,5,2" BorderBrush="Gray" BorderThickness="1">
|
||||||
<TextBlock Text="Watched" Foreground="Gray" FontSize="12"/>
|
<TextBlock Text="Watched" Foreground="Gray" FontSize="12"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<ProgressBar VerticalAlignment="Bottom" Margin="54,0,0,0" Foreground="Red" Name="leftOn"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<StackPanel Margin="0,0,5,5" Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}" VerticalAlignment="Bottom" HorizontalAlignment="Right" Padding="5,2,5,3">
|
<StackPanel Margin="0,0,5,5" Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}" VerticalAlignment="Bottom" HorizontalAlignment="Right" Padding="5,2,5,3">
|
||||||
<TextBlock Name="info" Text="[Duration] | [Published at]" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Gray" FontSize="12"/>
|
<TextBlock Name="info" Text="[Duration] | [Published at]" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Gray" FontSize="12"/>
|
||||||
@@ -50,4 +51,15 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Button>
|
</Button>
|
||||||
|
<UserControl.ContextFlyout>
|
||||||
|
<MenuFlyout>
|
||||||
|
<MenuFlyoutItem Icon="Play" Text="Play"/>
|
||||||
|
<MenuFlyoutItem Icon="Contact" Text="View channel"/>
|
||||||
|
<MenuFlyoutSeparator/>
|
||||||
|
<MenuFlyoutItem Icon="Link" Text="Copy link"/>
|
||||||
|
<MenuFlyoutItem Icon="Share" Text="Share"/>
|
||||||
|
<MenuFlyoutSeparator/>
|
||||||
|
<MenuFlyoutItem Icon="Download" Text="Download"/>
|
||||||
|
</MenuFlyout>
|
||||||
|
</UserControl.ContextFlyout>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -30,9 +30,7 @@ namespace FoxTube.Controls
|
|||||||
|
|
||||||
public async void Initialize(string id, string playlist = null)
|
public async void Initialize(string id, string playlist = null)
|
||||||
{
|
{
|
||||||
YouTubeService ytService = SecretsVault.NoAuthService;
|
VideosResource.ListRequest request = SecretsVault.Service.Videos.List("snippet,contentDetails,statistics,liveStreamingDetails");
|
||||||
|
|
||||||
VideosResource.ListRequest request = ytService.Videos.List("snippet,contentDetails,statistics,liveStreamingDetails");
|
|
||||||
request.Id = id;
|
request.Id = id;
|
||||||
VideoListResponse response = await request.ExecuteAsync();
|
VideoListResponse response = await request.ExecuteAsync();
|
||||||
|
|
||||||
@@ -71,7 +69,7 @@ namespace FoxTube.Controls
|
|||||||
embed = false;
|
embed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var request1 = ytService.Channels.List("snippet");
|
var request1 = SecretsVault.Service.Channels.List("snippet");
|
||||||
request1.Id = item.Snippet.ChannelId;
|
request1.Id = item.Snippet.ChannelId;
|
||||||
ChannelListResponse response1 = await request1.ExecuteAsync();
|
ChannelListResponse response1 = await request1.ExecuteAsync();
|
||||||
|
|
||||||
@@ -82,12 +80,11 @@ namespace FoxTube.Controls
|
|||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
foreach(PlaylistItem i in SecretsVault.UserHistory)
|
/*if(SecretsVault.UserHistory.Exists(x => x.Id == videoId))
|
||||||
if (i.Snippet.ResourceId.VideoId == id)
|
|
||||||
{
|
{
|
||||||
watched.Visibility = Visibility.Visible;
|
watched.Visibility = Visibility.Visible;
|
||||||
break;
|
leftOn.Value = SecretsVault.UserHistory.Find(x => x.Id == videoId).LeftOn;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Button_Click(object sender, RoutedEventArgs e)
|
public async void Button_Click(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
<UserControl
|
|
||||||
x:Class="FoxTube.VideoCardWide"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:FoxTube"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
Height="175">
|
|
||||||
|
|
||||||
<Button Padding="0" Background="WhiteSmoke" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Margin="2" Click="Button_Click">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<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="*"/>
|
|
||||||
<RowDefinition Height="75"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<StackPanel Orientation="Vertical">
|
|
||||||
<TextBlock Name="title" TextWrapping="WrapWholeWords" Text="[Title]" FontSize="20" MaxLines="2"/>
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<TextBlock Name="info" Text="[Duration] | [Published at] | [views]" Foreground="Gray"/>
|
|
||||||
<StackPanel Name="liveTag" Margin="5,0,0,0" BorderBrush="Red" BorderThickness="2" VerticalAlignment="Center" HorizontalAlignment="Right" Padding="5,0,5,0" Height="20" Orientation="Horizontal" Visibility="Collapsed">
|
|
||||||
<TextBlock Text=" " VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Red" FontSize="12" FontFamily="Segoe MDL2 Assets" Margin="0,1,0,0" FontWeight="Black"/>
|
|
||||||
<TextBlock Name="liveContent" Text="LIVE" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Red" FontSize="12" FontWeight="Bold"/>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
<!--<TextBlock MaxLines="4" Foreground="Gray" Margin="0,5,0,0" Text="Bendy and the Ink Machine: Chapter 4 Gameplay Part 1 - The Most Horrific Thing Yet! Bertrum Boss Fight! - Welcome back to Bendy and the Ink Machine! Today in Bendy and the Ink Machine, we check out Chapter 4, the latest and most terrifying chapter yet! We discover new secrets and find a man alive...kind of. Let's play Bendy and the Ink Machine Chapter 4!"/>-->
|
|
||||||
</StackPanel>
|
|
||||||
<Grid Grid.Row="1" Name="authorData">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="75"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<PersonPicture Name="avatar" Width="75" HorizontalAlignment="Left"/>
|
|
||||||
<StackPanel Orientation="Vertical" Grid.Column="1" Padding="10,5,5,5" VerticalAlignment="Center">
|
|
||||||
<TextBlock Name="channelName" Text="[Channel name]" FontSize="18"/>
|
|
||||||
<TextBlock Name="channelSubs" Text="[Subscribers]" Foreground="Gray"/>
|
|
||||||
<HyperlinkButton Name="channelLink" Content="Go to channel" Padding="0" Click="channelLink_Click"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
</UserControl>
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
|
||||||
using Windows.UI.Xaml.Controls.Primitives;
|
|
||||||
using Windows.UI.Xaml.Data;
|
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
using Windows.UI.Xaml.Media.Imaging;
|
|
||||||
using Windows.UI.Xaml.Navigation;
|
|
||||||
|
|
||||||
using Google.Apis.Services;
|
|
||||||
using Google.Apis.YouTube.v3;
|
|
||||||
using Google.Apis.YouTube.v3.Data;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Threading;
|
|
||||||
using Google.Apis.Util.Store;
|
|
||||||
using System.Xml;
|
|
||||||
using Windows.System;
|
|
||||||
|
|
||||||
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
|
||||||
|
|
||||||
namespace FoxTube
|
|
||||||
{
|
|
||||||
public sealed partial class VideoCardWide : UserControl
|
|
||||||
{
|
|
||||||
public string videoId;
|
|
||||||
Google.Apis.YouTube.v3.Data.Video item;
|
|
||||||
|
|
||||||
bool embed = false;
|
|
||||||
public VideoCardWide(string id)
|
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
Initialize(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Initialize(string id)
|
|
||||||
{
|
|
||||||
YouTubeService ytService = SecretsVault.NoAuthService;
|
|
||||||
|
|
||||||
VideosResource.ListRequest request = ytService.Videos.List("snippet,contentDetails,statistics,liveStreamingDetails");
|
|
||||||
request.Id = id;
|
|
||||||
VideoListResponse response = await request.ExecuteAsync();
|
|
||||||
|
|
||||||
item = response.Items[0];
|
|
||||||
|
|
||||||
videoId = id;
|
|
||||||
|
|
||||||
title.Text = item.Snippet.Title;
|
|
||||||
|
|
||||||
string duration;
|
|
||||||
if (item.ContentDetails.Duration != null || 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);
|
|
||||||
}
|
|
||||||
else duration = string.Empty;
|
|
||||||
|
|
||||||
info.Text = string.Format("{0}{1} | {2}", duration, Methods.GetAgo(item.Snippet.PublishedAt.Value), (item.LiveStreamingDetails != null && item.LiveStreamingDetails.ConcurrentViewers.HasValue) ? item.LiveStreamingDetails.ConcurrentViewers + " viewers" : item.Statistics.ViewCount + " views");
|
|
||||||
thumbnail.Source = new BitmapImage(new Uri(item.Snippet.Thumbnails.Medium.Url));
|
|
||||||
if (item.Snippet.LiveBroadcastContent == "live")
|
|
||||||
{
|
|
||||||
embed = true;
|
|
||||||
liveTag.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
else if(item.Snippet.LiveBroadcastContent == "upcoming")
|
|
||||||
{
|
|
||||||
embed = true;
|
|
||||||
TimeSpan span;
|
|
||||||
if (item.LiveStreamingDetails.ScheduledStartTime != null && (item.LiveStreamingDetails.ScheduledStartTime - DateTime.Now).Value.TotalMilliseconds > 0)
|
|
||||||
{
|
|
||||||
span = (TimeSpan)(item.LiveStreamingDetails.ScheduledStartTime - DateTime.Now);
|
|
||||||
liveContent.Text = "Goes live in " + string.Format("{0}{1:00}:{2:00}:{3:00}", span.Days != 0 ? span.Days + ":" : "", span.Hours, span.Minutes, span.Seconds);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
liveContent.Text = "Upcoming";
|
|
||||||
liveTag.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
var request1 = ytService.Channels.List("snippet,contentDetails,statistics");
|
|
||||||
request1.Id = item.Snippet.ChannelId;
|
|
||||||
ChannelListResponse response1 = await request1.ExecuteAsync();
|
|
||||||
|
|
||||||
var item1 = response1.Items[0];
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
Methods.MainPage.GoToChannel(item.Snippet.ChannelId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Button_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
if (embed)
|
|
||||||
await Launcher.LaunchUriAsync(new Uri(string.Format("https://www.youtube.com/watch?v={0}", videoId)));
|
|
||||||
else
|
|
||||||
Methods.MainPage.GoToVideo(videoId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
<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"/>
|
||||||
<Grid VerticalAlignment="Top" Margin="0,18,0,0" Height="2">
|
<Grid VerticalAlignment="Top" Margin="0,15,0,0" Height="2">
|
||||||
<ProgressBar Background="#66FFFFFF" Foreground="LightGray" Name="bufferingLevel"/>
|
<ProgressBar Background="#66FFFFFF" Foreground="LightGray" Name="bufferingLevel"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Slider PointerCaptureLost="seek_PointerCaptureLost" ValueChanged="seek_ValueChanged" Name="seek" VerticalAlignment="Top" ToolTipService.ToolTip="Seek" IsThumbToolTipEnabled="False" Background="Transparent" HorizontalAlignment="Stretch"/>
|
<Slider PointerCaptureLost="seek_PointerCaptureLost" ValueChanged="seek_ValueChanged" Name="seek" VerticalAlignment="Top" ToolTipService.ToolTip="Seek" IsThumbToolTipEnabled="False" Background="Transparent" HorizontalAlignment="Stretch"/>
|
||||||
@@ -168,5 +168,13 @@
|
|||||||
<Button Name="signin" Click="signin_Click" Content="Sign in now" Foreground="White" Background="Gray" HorizontalAlignment="Right" Grid.Column="1" Margin="0,0,10,0"/>
|
<Button Name="signin" Click="signin_Click" Content="Sign in now" Foreground="White" Background="Gray" HorizontalAlignment="Right" Grid.Column="1" Margin="0,0,10,0"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid Background="#E5000000" Visibility="Collapsed">
|
||||||
|
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Name="errorPlate">
|
||||||
|
<TextBlock Text="Something went wrong..." HorizontalAlignment="Center" FontSize="20"/>
|
||||||
|
<TextBlock Text="Video ID: " HorizontalAlignment="Center" IsTextSelectionEnabled="True" FontSize="20"/>
|
||||||
|
<TextBlock Text="Error type: " HorizontalAlignment="Center" IsTextSelectionEnabled="True" FontSize="20"/>
|
||||||
|
<TextBlock Text="Message: " HorizontalAlignment="Center" IsTextSelectionEnabled="True" FontSize="20"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -112,6 +112,8 @@ namespace FoxTube
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async void Initialize(Video meta, string channelAvatar)
|
public async void Initialize(Video meta, string channelAvatar)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
item = meta;
|
item = meta;
|
||||||
avatar = channelAvatar;
|
avatar = channelAvatar;
|
||||||
@@ -134,7 +136,7 @@ namespace FoxTube
|
|||||||
else
|
else
|
||||||
s = (string)settings.Values["quality"];
|
s = (string)settings.Values["quality"];
|
||||||
|
|
||||||
if (quality.Items.ToList().Find(x => (x as ComboBoxItem).Content as string == s) != null)
|
if (quality.Items.ToList().Exists(x => (x as ComboBoxItem).Content as string == s))
|
||||||
quality.SelectedItem = quality.Items.First(x => (x as ComboBoxItem).Content as string == s);
|
quality.SelectedItem = quality.Items.First(x => (x as ComboBoxItem).Content as string == s);
|
||||||
else
|
else
|
||||||
quality.SelectedItem = quality.Items.First();
|
quality.SelectedItem = quality.Items.First();
|
||||||
@@ -149,7 +151,7 @@ namespace FoxTube
|
|||||||
Tag = cc
|
Tag = cc
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if(ccInfo.Count > 0)
|
if (ccInfo.Count > 0)
|
||||||
subsLang.SelectedIndex = 0;
|
subsLang.SelectedIndex = 0;
|
||||||
else
|
else
|
||||||
captionsBtn.Visibility = Visibility.Collapsed;
|
captionsBtn.Visibility = Visibility.Collapsed;
|
||||||
@@ -157,14 +159,14 @@ namespace FoxTube
|
|||||||
|
|
||||||
if (item.ContentDetails.ContentRating != null)
|
if (item.ContentDetails.ContentRating != null)
|
||||||
{
|
{
|
||||||
if(SecretsVault.IsAuthorized && settings.Values["showMature"] != null)
|
if (SecretsVault.IsAuthorized && settings.Values["showMature"] != null)
|
||||||
{
|
{
|
||||||
Visibility = Visibility.Visible;
|
Visibility = Visibility.Visible;
|
||||||
proceedMature.Visibility = Visibility.Visible;
|
proceedMature.Visibility = Visibility.Visible;
|
||||||
matureBlock.Visibility = Visibility.Visible;
|
matureBlock.Visibility = Visibility.Visible;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(!SecretsVault.IsAuthorized)
|
else if (!SecretsVault.IsAuthorized)
|
||||||
{
|
{
|
||||||
Visibility = Visibility.Visible;
|
Visibility = Visibility.Visible;
|
||||||
signReq.Visibility = Visibility.Visible;
|
signReq.Visibility = Visibility.Visible;
|
||||||
@@ -203,10 +205,25 @@ namespace FoxTube
|
|||||||
systemControls.ButtonPressed += SystemControls_Engaged;
|
systemControls.ButtonPressed += SystemControls_Engaged;
|
||||||
systemControls.IsEnabled = true;
|
systemControls.IsEnabled = true;
|
||||||
|
|
||||||
|
//SecretsVault.HistoryAdd(videoId, elapsed, total);
|
||||||
|
|
||||||
t.Start();
|
t.Start();
|
||||||
|
|
||||||
Visibility = Visibility.Visible;
|
Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
RaiseError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RaiseError(Exception e)
|
||||||
|
{
|
||||||
|
((TextBlock)errorPlate.Children[1]).Text = $"Video ID: {videoId}";
|
||||||
|
((TextBlock)errorPlate.Children[2]).Text = $"Error type: {e.GetType()}";
|
||||||
|
((TextBlock)errorPlate.Children[3]).Text = $"Message: {e.Message}";
|
||||||
|
((Grid)errorPlate.Parent).Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
private async void SystemControls_Engaged(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
|
private async void SystemControls_Engaged(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
|
||||||
{
|
{
|
||||||
@@ -348,7 +365,7 @@ namespace FoxTube
|
|||||||
|
|
||||||
settings.Values["rememberedQuality"] = (quality.SelectedItem as ComboBoxItem).Content as string;
|
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)
|
if(streamInfo.Muxed.ToList().Exists(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string))
|
||||||
{
|
{
|
||||||
isMuxed = true;
|
isMuxed = true;
|
||||||
videoSource.Source = streamInfo.Muxed.First(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri();
|
videoSource.Source = streamInfo.Muxed.First(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri();
|
||||||
@@ -612,6 +629,8 @@ namespace FoxTube
|
|||||||
systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
|
systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SecretsVault.HistoryAdd(videoId, elapsed, total);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void miniView_Click(object sender, RoutedEventArgs e)
|
private async void miniView_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -634,8 +653,7 @@ namespace FoxTube
|
|||||||
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||||
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||||
|
|
||||||
CoreApplicationViewTitleBar coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
|
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
|
||||||
coreTitleBar.ExtendViewIntoTitleBar = true;
|
|
||||||
|
|
||||||
mainControls.Visibility = Visibility.Collapsed;
|
mainControls.Visibility = Visibility.Collapsed;
|
||||||
header.Visibility = Visibility.Collapsed;
|
header.Visibility = Visibility.Collapsed;
|
||||||
@@ -651,8 +669,6 @@ namespace FoxTube
|
|||||||
{
|
{
|
||||||
await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default);
|
await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default);
|
||||||
|
|
||||||
//Methods.MainPage.SetTitleBar();
|
|
||||||
|
|
||||||
mainControls.Visibility = Visibility.Visible;
|
mainControls.Visibility = Visibility.Visible;
|
||||||
header.Visibility = Visibility.Visible;
|
header.Visibility = Visibility.Visible;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<AssemblyName>FoxTube</AssemblyName>
|
<AssemblyName>FoxTube</AssemblyName>
|
||||||
<DefaultLanguage>en-US</DefaultLanguage>
|
<DefaultLanguage>en-US</DefaultLanguage>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.17134.0</TargetPlatformVersion>
|
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.17763.0</TargetPlatformVersion>
|
||||||
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
|
||||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
@@ -19,6 +19,13 @@
|
|||||||
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
|
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
|
||||||
<PackageCertificateKeyFile>FoxTube_TemporaryKey.pfx</PackageCertificateKeyFile>
|
<PackageCertificateKeyFile>FoxTube_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||||
<PackageCertificateThumbprint>E33236F6F6066A373DFA92A7B7C1467B1EF0BA81</PackageCertificateThumbprint>
|
<PackageCertificateThumbprint>E33236F6F6066A373DFA92A7B7C1467B1EF0BA81</PackageCertificateThumbprint>
|
||||||
|
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||||
|
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
|
||||||
|
<AppxPackageDir>C:\Users\Michael Gordeev\Downloads\FoxTube dists\0.2.1812-2\</AppxPackageDir>
|
||||||
|
<AppxBundle>Always</AppxBundle>
|
||||||
|
<AppxBundlePlatforms>x86|x64|arm</AppxBundlePlatforms>
|
||||||
|
<AppInstallerUpdateFrequency>1</AppInstallerUpdateFrequency>
|
||||||
|
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -100,7 +107,11 @@
|
|||||||
<Compile Include="Classes\DownloadItemContainer.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\SearchPaameters.cs" />
|
||||||
|
<Compile Include="Classes\SettingsStorage.cs" />
|
||||||
|
<Compile Include="Controls\Advert.xaml.cs">
|
||||||
|
<DependentUpon>Advert.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Controls\ChannelCard.xaml.cs">
|
<Compile Include="Controls\ChannelCard.xaml.cs">
|
||||||
<DependentUpon>ChannelCard.xaml</DependentUpon>
|
<DependentUpon>ChannelCard.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -123,9 +134,6 @@
|
|||||||
<Compile Include="Pages\ChannelPage.xaml.cs">
|
<Compile Include="Pages\ChannelPage.xaml.cs">
|
||||||
<DependentUpon>ChannelPage.xaml</DependentUpon>
|
<DependentUpon>ChannelPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Controls\ChannelCardWide.xaml.cs">
|
|
||||||
<DependentUpon>ChannelCardWide.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Pages\CommentsPage.xaml.cs">
|
<Compile Include="Pages\CommentsPage.xaml.cs">
|
||||||
<DependentUpon>CommentsPage.xaml</DependentUpon>
|
<DependentUpon>CommentsPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -153,12 +161,6 @@
|
|||||||
<Compile Include="Pages\MainPage.xaml.cs">
|
<Compile Include="Pages\MainPage.xaml.cs">
|
||||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Controls\NotificationsCenter.xaml.cs">
|
|
||||||
<DependentUpon>NotificationsCenter.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Controls\PlaylistCardWide.xaml.cs">
|
|
||||||
<DependentUpon>PlaylistCardWide.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Pages\PlaylistPage.xaml.cs">
|
<Compile Include="Pages\PlaylistPage.xaml.cs">
|
||||||
<DependentUpon>PlaylistPage.xaml</DependentUpon>
|
<DependentUpon>PlaylistPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -173,18 +175,12 @@
|
|||||||
<Compile Include="Pages\Settings.xaml.cs">
|
<Compile Include="Pages\Settings.xaml.cs">
|
||||||
<DependentUpon>Settings.xaml</DependentUpon>
|
<DependentUpon>Settings.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Pages\SettingsPages\Translate.xaml.cs">
|
|
||||||
<DependentUpon>Translate.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Pages\VideoPage.xaml.cs">
|
<Compile Include="Pages\VideoPage.xaml.cs">
|
||||||
<DependentUpon>VideoPage.xaml</DependentUpon>
|
<DependentUpon>VideoPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Controls\VideoCard.xaml.cs">
|
<Compile Include="Controls\VideoCard.xaml.cs">
|
||||||
<DependentUpon>VideoCard.xaml</DependentUpon>
|
<DependentUpon>VideoCard.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Controls\VideoCardWide.xaml.cs">
|
|
||||||
<DependentUpon>VideoCardWide.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Pages\VideoGrid.xaml.cs">
|
<Compile Include="Pages\VideoGrid.xaml.cs">
|
||||||
<DependentUpon>VideoGrid.xaml</DependentUpon>
|
<DependentUpon>VideoGrid.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -280,6 +276,10 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</ApplicationDefinition>
|
</ApplicationDefinition>
|
||||||
|
<Page Include="Controls\Advert.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Controls\ChannelCard.xaml">
|
<Page Include="Controls\ChannelCard.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -308,10 +308,6 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Controls\ChannelCardWide.xaml">
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Pages\CommentsPage.xaml">
|
<Page Include="Pages\CommentsPage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -348,14 +344,6 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Controls\NotificationsCenter.xaml">
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Controls\PlaylistCardWide.xaml">
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Pages\PlaylistPage.xaml">
|
<Page Include="Pages\PlaylistPage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -368,10 +356,6 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Pages\SettingsPages\Translate.xaml">
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Pages\Subscriptions.xaml">
|
<Page Include="Pages\Subscriptions.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -384,10 +368,6 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Controls\VideoCardWide.xaml">
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Pages\VideoGrid.xaml">
|
<Page Include="Pages\VideoGrid.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -431,11 +411,8 @@
|
|||||||
<PackageReference Include="runtime.win10-arm64.runtime.native.System.IO.Compression">
|
<PackageReference Include="runtime.win10-arm64.runtime.native.System.IO.Compression">
|
||||||
<Version>4.3.2</Version>
|
<Version>4.3.2</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Syroot.Windows.IO.KnownFolders">
|
|
||||||
<Version>1.2.0</Version>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="YoutubeExplode">
|
<PackageReference Include="YoutubeExplode">
|
||||||
<Version>4.4.0</Version>
|
<Version>4.5.1</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="YoutubeExtractor">
|
<PackageReference Include="YoutubeExtractor">
|
||||||
<Version>0.10.11</Version>
|
<Version>0.10.11</Version>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<toast launch="action=viewPhoto&photoId=92187">
|
<toast launch="action=viewPhoto&photoId=92187">
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<posts>
|
<posts>
|
||||||
<post time="YYYY-MM-DDThh:mm:ss-03" image="http://foxtube.hol.es/foxtube/FILE_NAME.png Hero image (not implemented yet)" id="0">
|
<post time="YYYY-MM-DDThh:mm:ss-03" id="0">
|
||||||
<notificationHeader>Short headline for toast notifications</notificationHeader>
|
<thumbnail></thumbnail>
|
||||||
|
<avatar></avatar>
|
||||||
<header>Main headline for full post</header>
|
<header>Main headline for full post</header>
|
||||||
<content>Announcement body (beware of special characters)</content>
|
<content>Announcement body (beware of special characters)</content>
|
||||||
</post>
|
</post>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
|
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" IgnorableNamespaces="uap mp uap3">
|
||||||
<Identity Name="foxtube-5d1cba1f-d7d5-472b-acb7-beb360bab268" Publisher="CN=XFox" Version="1.0.0.0" />
|
<Identity Name="foxtube-5d1cba1f-d7d5-472b-acb7-beb360bab268" Publisher="CN=Michael Gordeev" Version="0.2.18122.0" />
|
||||||
<mp:PhoneIdentity PhoneProductId="5d1cba1f-d7d5-472b-acb7-beb360bab268" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
<mp:PhoneIdentity PhoneProductId="5d1cba1f-d7d5-472b-acb7-beb360bab268" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||||
<Properties>
|
<Properties>
|
||||||
<DisplayName>FoxTube</DisplayName>
|
<DisplayName>FoxTube</DisplayName>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
</Resources>
|
</Resources>
|
||||||
<Applications>
|
<Applications>
|
||||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="FoxTube.App" ResourceGroup="foxtube">
|
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="FoxTube.App" ResourceGroup="foxtube">
|
||||||
<uap:VisualElements DisplayName="FoxTube" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="YouTube Client" BackgroundColor="transparent">
|
<uap:VisualElements DisplayName="FoxTube" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="YouTube Client" BackgroundColor="red">
|
||||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" ShortName="FoxTube" Square310x310Logo="Assets\LargeTile.png" Square71x71Logo="Assets\SmallTile.png">
|
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" ShortName="FoxTube" Square310x310Logo="Assets\LargeTile.png" Square71x71Logo="Assets\SmallTile.png">
|
||||||
<uap:ShowNameOnTiles>
|
<uap:ShowNameOnTiles>
|
||||||
<uap:ShowOn Tile="square150x150Logo" />
|
<uap:ShowOn Tile="square150x150Logo" />
|
||||||
@@ -25,9 +25,23 @@
|
|||||||
</uap:DefaultTile>
|
</uap:DefaultTile>
|
||||||
<uap:SplashScreen Image="Assets\SplashScreen.png" BackgroundColor="red" />
|
<uap:SplashScreen Image="Assets\SplashScreen.png" BackgroundColor="red" />
|
||||||
</uap:VisualElements>
|
</uap:VisualElements>
|
||||||
|
<Extensions>
|
||||||
|
<Extension Category="windows.backgroundTasks" EntryPoint="FoxTube.Background.BackgroundProcessor">
|
||||||
|
<BackgroundTasks>
|
||||||
|
<Task Type="general" />
|
||||||
|
<Task Type="systemEvent" />
|
||||||
|
<Task Type="timer" />
|
||||||
|
<Task Type="pushNotification" />
|
||||||
|
<uap:Task Type="chatMessageNotification" />
|
||||||
|
<uap:Task Type="mediaProcessing" />
|
||||||
|
</BackgroundTasks>
|
||||||
|
</Extension>
|
||||||
|
</Extensions>
|
||||||
</Application>
|
</Application>
|
||||||
</Applications>
|
</Applications>
|
||||||
<Capabilities>
|
<Capabilities>
|
||||||
<Capability Name="internetClient" />
|
<Capability Name="internetClient" />
|
||||||
|
<uap3:Capability Name="backgroundMediaPlayback" />
|
||||||
|
<uap:Capability Name="videosLibrary" />
|
||||||
</Capabilities>
|
</Capabilities>
|
||||||
</Package>
|
</Package>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<Hyperlink Click="Hyperlink_Click">Log in</Hyperlink> to manage your subscriptions
|
<Hyperlink Click="Hyperlink_Click">Log in</Hyperlink> to manage your subscriptions
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|
||||||
<Grid Visibility="Visible" Grid.Column="2" VerticalAlignment="Bottom" Margin="10" Name="subscriptionPane" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
<Grid Visibility="Collapsed" Grid.Column="2" VerticalAlignment="Bottom" Margin="10" Name="subscriptionPane" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<Button Click="subscribe_Click" Name="subscribe" Width="250" Height="50" Background="Red" Foreground="White" FontSize="18" FontWeight="SemiBold" Content="Subscirbe"/>
|
<Button Click="subscribe_Click" Name="subscribe" Width="250" Height="50" Background="Red" Foreground="White" FontSize="18" FontWeight="SemiBold" Content="Subscirbe"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,44 +1,25 @@
|
|||||||
using System;
|
using System;
|
||||||
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 Google.Apis.Services;
|
|
||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
using Windows.UI.Xaml.Media.Imaging;
|
using Windows.UI.Xaml.Media.Imaging;
|
||||||
using Windows.UI.Text;
|
|
||||||
using Windows.Storage;
|
|
||||||
using FoxTube.Controls;
|
using FoxTube.Controls;
|
||||||
using FoxTube.Pages;
|
|
||||||
using Windows.ApplicationModel.DataTransfer;
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
using Windows.ApplicationModel;
|
|
||||||
using Windows.Storage.Streams;
|
|
||||||
using Windows.System;
|
using Windows.System;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
|
||||||
|
|
||||||
namespace FoxTube.Pages
|
namespace FoxTube.Pages
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
/// Channel page
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class ChannelPage : Page
|
public sealed partial class ChannelPage : Page
|
||||||
{
|
{
|
||||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
|
||||||
|
|
||||||
public string channelId;
|
public string channelId;
|
||||||
public Channel item;
|
public Channel item;
|
||||||
|
|
||||||
@@ -54,7 +35,7 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
public ChannelPage()
|
public ChannelPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
loading = grid.Children[2] as LoadingPage;
|
loading = grid.Children[2] as LoadingPage;
|
||||||
playlistLoading = playlists.Children[1] as LoadingPage;
|
playlistLoading = playlists.Children[1] as LoadingPage;
|
||||||
|
|
||||||
@@ -136,18 +117,11 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
if (SecretsVault.IsAuthorized)
|
if (SecretsVault.IsAuthorized)
|
||||||
{
|
{
|
||||||
bool b = false;
|
if (SecretsVault.Subscriptions.Any(i => i.Snippet.ResourceId.ChannelId == channelId))
|
||||||
foreach (Subscription s in SecretsVault.Subscriptions)
|
|
||||||
{
|
{
|
||||||
if (s.Snippet.ResourceId.ChannelId == item.Id)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"{s.Snippet.ResourceId.ChannelId} ({item.Snippet.Title}: {item.Id})");
|
|
||||||
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";
|
||||||
b = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
subscriptionPane.Visibility = Visibility.Visible;
|
subscriptionPane.Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
@@ -290,7 +264,7 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
private void refresh_Click(object sender, RoutedEventArgs e)
|
private void refresh_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Initialize(channelId);
|
Methods.MainPage.GoToChannel(channelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void inBrowser_Click(object sender, RoutedEventArgs e)
|
private async void inBrowser_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -306,45 +280,13 @@ namespace FoxTube.Pages
|
|||||||
DataTransferManager.ShowShareUI();
|
DataTransferManager.ShowShareUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Share(DataTransferManager sender, DataRequestedEventArgs args)
|
private void Share(DataTransferManager sender, DataRequestedEventArgs args)
|
||||||
{
|
{
|
||||||
DataRequest request = args.Request;
|
Methods.Share(args,
|
||||||
request.Data.Properties.Title = item.Snippet.Title;
|
item.Snippet.Thumbnails.Medium.Url,
|
||||||
request.Data.Properties.Description = "Sharing a channel";
|
item.Snippet.Title,
|
||||||
|
string.IsNullOrWhiteSpace(item.Snippet.CustomUrl) ? $"https://www.youtube.com/channel/{item.Id}" : $"https://www.youtube.com/user/{item.Snippet.CustomUrl}",
|
||||||
// Handle errors
|
"channel");
|
||||||
//request.FailWithDisplayText("Something unexpected could happen.");
|
|
||||||
|
|
||||||
// Plain text
|
|
||||||
request.Data.SetText(item.Snippet.Title + "\n" + "#YouTube #FoxTube #SharedWithFoxTube");
|
|
||||||
|
|
||||||
// Uniform Resource Identifiers (URIs)
|
|
||||||
if(!string.IsNullOrWhiteSpace(item.Snippet.CustomUrl))
|
|
||||||
request.Data.SetWebLink(new Uri($"https://www.youtube.com/user/{item.Snippet.CustomUrl}"));
|
|
||||||
else
|
|
||||||
request.Data.SetWebLink(new Uri($"https://www.youtube.com/channel/{item.Id}"));
|
|
||||||
|
|
||||||
// HTML
|
|
||||||
//request.Data.SetHtmlFormat("<b>Bold Text</b>");
|
|
||||||
|
|
||||||
// Because we are making async calls in the DataRequested event handler,
|
|
||||||
// we need to get the deferral first.
|
|
||||||
DataRequestDeferral deferral = request.GetDeferral();
|
|
||||||
|
|
||||||
// Make sure we always call Complete on the deferral.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StorageFile thumbnailFile = await Package.Current.InstalledLocation.GetFileAsync(item.Snippet.Thumbnails.Medium.Url);
|
|
||||||
request.Data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromFile(thumbnailFile);
|
|
||||||
StorageFile imageFile = await Package.Current.InstalledLocation.GetFileAsync(item.Snippet.Thumbnails.Medium.Url);
|
|
||||||
|
|
||||||
// Bitmaps
|
|
||||||
request.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(imageFile));
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
deferral.Complete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,17 @@
|
|||||||
x:Class="FoxTube.Pages.CommentsPage"
|
x:Class="FoxTube.Pages.CommentsPage"
|
||||||
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"
|
||||||
xmlns:local="using:FoxTube"
|
|
||||||
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"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
|
||||||
<Grid Name="grid">
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="auto"/>
|
<RowDefinition Height="auto"/>
|
||||||
<RowDefinition/>
|
<RowDefinition/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid>
|
<Grid Name="grid">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="auto"/>
|
<RowDefinition Height="auto"/>
|
||||||
<RowDefinition Height="30"/>
|
<RowDefinition Height="30"/>
|
||||||
@@ -45,7 +44,7 @@
|
|||||||
<ScrollViewer Grid.Row="1" Name="scroll">
|
<ScrollViewer Grid.Row="1" Name="scroll">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<StackPanel Name="placeholder"/>
|
<StackPanel Name="placeholder"/>
|
||||||
<HyperlinkButton Name="more" Click="more_Click" HorizontalAlignment="Center" Foreground="Red" Content="Show more"/>
|
<HyperlinkButton Visibility="Collapsed" Name="more" Click="more_Click" HorizontalAlignment="Center" Foreground="Red" Content="Show more"/>
|
||||||
<ProgressBar Name="moreLoading" Visibility="Collapsed" IsIndeterminate="True" Foreground="Red"/>
|
<ProgressBar Name="moreLoading" Visibility="Collapsed" IsIndeterminate="True" Foreground="Red"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|||||||
@@ -1,17 +1,6 @@
|
|||||||
using System;
|
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;
|
||||||
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 Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
@@ -34,7 +23,7 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
public CommentsPage()
|
public CommentsPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Initialize(Video video)
|
public async void Initialize(Video video)
|
||||||
@@ -43,6 +32,8 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
if (!SecretsVault.IsAuthorized)
|
if (!SecretsVault.IsAuthorized)
|
||||||
grid.RowDefinitions[0].Height = new GridLength(0);
|
grid.RowDefinitions[0].Height = new GridLength(0);
|
||||||
|
else
|
||||||
|
grid.RowDefinitions[0].Height = GridLength.Auto;
|
||||||
|
|
||||||
counter.Text = string.Format("{0:0,0} Comments", video.Statistics.CommentCount);
|
counter.Text = string.Format("{0:0,0} Comments", video.Statistics.CommentCount);
|
||||||
|
|
||||||
|
|||||||
@@ -9,28 +9,29 @@
|
|||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
|
||||||
<Grid Padding="5">
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="auto"/>
|
<RowDefinition Height="auto"/>
|
||||||
<RowDefinition/>
|
<RowDefinition/>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<StackPanel>
|
<Grid Margin="10">
|
||||||
<TextBlock FontSize="28" Text="Downloads"/>
|
|
||||||
<Grid VerticalAlignment="Top">
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition/>
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button Name="openFolder" Click="openFolder_Click" Content="Open folder" Margin="5"/>
|
<TextBlock Name="path" IsTextSelectionEnabled="True" TextWrapping="WrapWholeWords"/>
|
||||||
<TextBlock Name="path" IsTextSelectionEnabled="True" Grid.Column="1" Text="C://Users/Admin/Downloads" VerticalAlignment="Center"/>
|
<Button Grid.Column="1" Content="Open folder" Name="open" Click="Open_Click" VerticalAlignment="Center"/>
|
||||||
<Button Name="changePath" Click="changePath_Click" Grid.Column="2" Content="Change path" Margin="5"/>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
|
||||||
<ScrollViewer Grid.Row="1">
|
<ScrollViewer Grid.Row="1">
|
||||||
<StackPanel Margin="5" Name="stack">
|
<StackPanel Name="stack"/>
|
||||||
<ListView ItemsSource="{Binding Path=Methods.MainPage.agent.items}" SelectionMode="None"/>
|
|
||||||
</StackPanel>
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1" Name="empty" HorizontalAlignment="Center" VerticalAlignment="Top" FontSize="28" Text="You haven't downloaded anything yet" Margin="10" TextWrapping="WrapWholeWords" Foreground="Gray" FontWeight="SemiBold"/>
|
||||||
|
|
||||||
|
<CommandBar DefaultLabelPosition="Right" Grid.Row="2">
|
||||||
|
<AppBarButton Label="Refresh" Icon="Refresh" Click="Refresh"/>
|
||||||
|
</CommandBar>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ 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.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
|
|
||||||
|
|
||||||
namespace FoxTube.Pages
|
namespace FoxTube.Pages
|
||||||
{
|
{
|
||||||
@@ -22,31 +22,49 @@ namespace FoxTube.Pages
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class Downloads : Page
|
public sealed partial class Downloads : Page
|
||||||
{
|
{
|
||||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
|
||||||
public Downloads()
|
public Downloads()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
path.Text = settings.Values["defaultDownload"] as string;
|
SetPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void changePath_Click(object sender, RoutedEventArgs e)
|
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
FolderPicker picker = new FolderPicker()
|
base.OnNavigatedFrom(e);
|
||||||
{
|
stack.Children.Clear();
|
||||||
SuggestedStartLocation = PickerLocationId.Downloads,
|
|
||||||
ViewMode = PickerViewMode.Thumbnail
|
|
||||||
};
|
|
||||||
picker.FileTypeFilter.Add(".shit"); //Because overwise it trhows an exception
|
|
||||||
|
|
||||||
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)
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
await Launcher.LaunchFolderAsync( await StorageFolder.GetFolderFromPathAsync(settings.Values["defaultDownload"] as string));
|
base.OnNavigatedTo(e);
|
||||||
|
DownloadAgent.items.ForEach(i =>
|
||||||
|
{
|
||||||
|
stack.Children.Add(i);
|
||||||
|
i.Initialize();
|
||||||
|
});
|
||||||
|
empty.Visibility = stack.Children.Count > 0 ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPath()
|
||||||
|
{
|
||||||
|
path.Text = DownloadAgent.Downloads.Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Refresh(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
stack.Children.Clear();
|
||||||
|
|
||||||
|
DownloadAgent.items.ForEach(i =>
|
||||||
|
{
|
||||||
|
stack.Children.Add(i);
|
||||||
|
i.Initialize();
|
||||||
|
});
|
||||||
|
empty.Visibility = stack.Children.Count > 0 ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Open_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
await Launcher.LaunchFolderAsync(DownloadAgent.Downloads);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,16 +12,17 @@
|
|||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
|
||||||
<Grid Name="grid">
|
<Grid Name="grid">
|
||||||
<ScrollViewer Margin="0,0,0,50">
|
<Grid.RowDefinitions>
|
||||||
<StackPanel Name="stack">
|
<RowDefinition/>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<ScrollViewer Name="scroll">
|
||||||
<local:VideoGrid/>
|
<local:VideoGrid/>
|
||||||
<controls:ShowMore Clicked="ShowMore_Clicked"/>
|
|
||||||
</StackPanel>
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
<CommandBar VerticalAlignment="Bottom">
|
<CommandBar Grid.Row="1" DefaultLabelPosition="Right">
|
||||||
|
<AppBarButton Icon="Refresh" Label="Refresh" Name="refresh" Click="Refresh_Click"/>
|
||||||
<AppBarButton Label="Open in browser" Icon="Globe" Name="toBrowser" Click="toBrowser_Click"/>
|
<AppBarButton Label="Open in browser" Icon="Globe" Name="toBrowser" Click="toBrowser_Click"/>
|
||||||
<AppBarButton Label="Refresh" Icon="Refresh" Name="refresh" Click="refresh_Click"/>
|
|
||||||
</CommandBar>
|
</CommandBar>
|
||||||
<foxtube:LoadingPage Visibility="Collapsed"/>
|
<foxtube:LoadingPage Visibility="Collapsed" Grid.RowSpan="2"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@@ -1,17 +1,8 @@
|
|||||||
using FoxTube.Controls;
|
using FoxTube.Controls;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using Windows.System;
|
||||||
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 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
|
||||||
@@ -24,15 +15,19 @@ namespace FoxTube.Pages
|
|||||||
public sealed partial class History : Page
|
public sealed partial class History : Page
|
||||||
{
|
{
|
||||||
LoadingPage loading;
|
LoadingPage loading;
|
||||||
ShowMore more;
|
|
||||||
VideoGrid list;
|
VideoGrid list;
|
||||||
|
|
||||||
public History()
|
public History()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
|
||||||
loading = grid.Children[2] as LoadingPage;
|
loading = grid.Children[2] as LoadingPage;
|
||||||
more = stack.Children[1] as ShowMore;
|
list = scroll.Content as VideoGrid;
|
||||||
list = stack.Children[0] as VideoGrid;
|
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,22 +35,15 @@ namespace FoxTube.Pages
|
|||||||
{
|
{
|
||||||
loading.Refresh();
|
loading.Refresh();
|
||||||
|
|
||||||
more.Complete(true);
|
loading.Close();
|
||||||
|
|
||||||
loading.Block();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowMore_Clicked()
|
private async void toBrowser_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
await Launcher.LaunchUriAsync(new Uri("youtube.com/feed/history"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toBrowser_Click(object sender, RoutedEventArgs e)
|
private void Refresh_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refresh_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<Page
|
<Page
|
||||||
NavigationCacheMode="Enabled"
|
|
||||||
x:Class="FoxTube.Home"
|
x:Class="FoxTube.Home"
|
||||||
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"
|
||||||
@@ -16,13 +15,10 @@
|
|||||||
<RowDefinition Height="auto"/>
|
<RowDefinition Height="auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Pivot Name="pivot" SelectionChanged="pivot_SelectionChanged" SelectedIndex="1">
|
<Pivot Name="pivot" SelectionChanged="pivot_SelectionChanged">
|
||||||
<PivotItem Header="Recommended" Name="recommended">
|
<PivotItem Header="Recommended" Name="recommended">
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<StackPanel>
|
<StackPanel/>
|
||||||
<pages:VideoGrid/>
|
|
||||||
<controls:ShowMore Clicked="RecMore_Clicked"/>
|
|
||||||
</StackPanel>
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</PivotItem>
|
</PivotItem>
|
||||||
<PivotItem Header="Trending" Name="trending">
|
<PivotItem Header="Trending" Name="trending">
|
||||||
@@ -35,10 +31,7 @@
|
|||||||
</PivotItem>
|
</PivotItem>
|
||||||
<PivotItem Header="Subscriptions" Name="subscriptions">
|
<PivotItem Header="Subscriptions" Name="subscriptions">
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<StackPanel>
|
<StackPanel/>
|
||||||
<pages:VideoGrid/>
|
|
||||||
<controls:ShowMore Clicked="SubsMore_Clicked"/>
|
|
||||||
</StackPanel>
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</PivotItem>
|
</PivotItem>
|
||||||
</Pivot>
|
</Pivot>
|
||||||
|
|||||||
@@ -1,68 +1,39 @@
|
|||||||
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.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.Globalization;
|
|
||||||
|
|
||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
using Windows.UI.Text;
|
|
||||||
using FoxTube.Controls;
|
using FoxTube.Controls;
|
||||||
using FoxTube.Pages;
|
using FoxTube.Pages;
|
||||||
using System.Collections.ObjectModel;
|
using System.Globalization;
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
|
||||||
|
|
||||||
namespace FoxTube
|
namespace FoxTube
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
/// Home page
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class Home : Page
|
public sealed partial class Home : Page
|
||||||
{
|
{
|
||||||
private bool recLoaded = false;
|
|
||||||
private bool trendLoaded = false;
|
private bool trendLoaded = false;
|
||||||
private bool subsLoaded = false;
|
|
||||||
|
|
||||||
VideoGrid recGrid, trendGrid, subsGrid;
|
VideoGrid trendGrid;
|
||||||
ShowMore recMore, trendMore, subsMore;
|
ShowMore trendMore;
|
||||||
LoadingPage loading;
|
LoadingPage loading;
|
||||||
|
|
||||||
string trendToken, recToken;
|
string trendToken;
|
||||||
Dictionary<string, string> subsTokens = new Dictionary<string, string>();
|
Dictionary<string, string> subsTokens = new Dictionary<string, string>();
|
||||||
string reg;
|
string reg;
|
||||||
|
|
||||||
public Home()
|
public Home()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
try
|
reg = CultureInfo.GetCultures(CultureTypes.AllCultures).Find(i => i.IetfLanguageTag == SettingsStorage.Region).IetfLanguageTag.Remove(0, 3);
|
||||||
{
|
|
||||||
reg = (ApplicationData.Current.LocalSettings.Values["region"] as string).ToLower().Remove(0, 3);
|
|
||||||
}
|
|
||||||
catch (ArgumentOutOfRangeException)
|
|
||||||
{
|
|
||||||
reg = (ApplicationData.Current.LocalSettings.Values["region"] as string).ToUpper();
|
|
||||||
}
|
|
||||||
|
|
||||||
recGrid = ((recommended.Content as ScrollViewer).Content as StackPanel).Children[0] as VideoGrid;
|
|
||||||
trendGrid = ((trending.Content as ScrollViewer).Content as StackPanel).Children[0] as VideoGrid;
|
trendGrid = ((trending.Content as ScrollViewer).Content as StackPanel).Children[0] as VideoGrid;
|
||||||
subsGrid = ((subscriptions.Content as ScrollViewer).Content as StackPanel).Children[0] as VideoGrid;
|
trendMore = ((trending.Content as ScrollViewer).Content as StackPanel).Children[1] as ShowMore;
|
||||||
|
|
||||||
recMore = ((recommended.Content as ScrollViewer).Content as StackPanel).Children[1] as ShowMore;
|
|
||||||
trendMore = ((trending.Content as ScrollViewer).Content as StackPanel).Children[1] as ShowMore; ;
|
|
||||||
subsMore = ((subscriptions.Content as ScrollViewer).Content as StackPanel).Children[1] as ShowMore;
|
|
||||||
|
|
||||||
loading = grid.Children[2] as LoadingPage;
|
loading = grid.Children[2] as LoadingPage;
|
||||||
|
|
||||||
@@ -71,12 +42,7 @@ namespace FoxTube
|
|||||||
|
|
||||||
private void refreshPage(object sender, RoutedEventArgs e)
|
private void refreshPage(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
(Parent as Frame).Navigate(typeof(Home));
|
Methods.MainPage.GoToHome();
|
||||||
}
|
|
||||||
|
|
||||||
private void RecMore_Clicked()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void TrendMore_Clicked()
|
private async void TrendMore_Clicked()
|
||||||
@@ -99,7 +65,7 @@ namespace FoxTube
|
|||||||
foreach (Video vid in response.Items)
|
foreach (Video vid in response.Items)
|
||||||
{
|
{
|
||||||
VideoCard vCard = new VideoCard(vid.Id);
|
VideoCard vCard = new VideoCard(vid.Id);
|
||||||
recGrid.Add(vCard);
|
trendGrid.Add(vCard);
|
||||||
}
|
}
|
||||||
trendMore.Complete();
|
trendMore.Complete();
|
||||||
}
|
}
|
||||||
@@ -109,45 +75,6 @@ namespace FoxTube
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SubsMore_Clicked()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
List<SearchResult> items = new List<SearchResult>();
|
|
||||||
Dictionary<string, string> pairs = new Dictionary<string, string>();
|
|
||||||
SearchResource.ListRequest request = SecretsVault.Service.Search.List("snippet");
|
|
||||||
request.Type = "video";
|
|
||||||
request.MaxResults = 10;
|
|
||||||
request.Order = SearchResource.ListRequest.OrderEnum.Date;
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, string> i in subsTokens)
|
|
||||||
{
|
|
||||||
request.ChannelId = i.Key;
|
|
||||||
request.PageToken = i.Value;
|
|
||||||
SearchListResponse response = await request.ExecuteAsync();
|
|
||||||
foreach (SearchResult result in response.Items)
|
|
||||||
items.Add(result);
|
|
||||||
if (response.NextPageToken != null)
|
|
||||||
pairs.Add(i.Value, response.NextPageToken);
|
|
||||||
}
|
|
||||||
if (pairs.Count == 0)
|
|
||||||
subsMore.Complete(true);
|
|
||||||
else
|
|
||||||
subsTokens = pairs;
|
|
||||||
|
|
||||||
items = items.OrderByDescending(x => x.Snippet.PublishedAt).ToList();
|
|
||||||
|
|
||||||
foreach (SearchResult i in items)
|
|
||||||
subsGrid.Add(new VideoCard(i.Id.VideoId));
|
|
||||||
|
|
||||||
subsMore.Complete();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
subsMore.Complete(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
if(SecretsVault.IsAuthorized)
|
if(SecretsVault.IsAuthorized)
|
||||||
@@ -164,11 +91,11 @@ namespace FoxTube
|
|||||||
private void pivot_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void pivot_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
loading.Close();
|
loading.Close();
|
||||||
if (pivot.SelectedItem == recommended && !recLoaded)
|
if (pivot.SelectedItem == recommended)
|
||||||
LoadRecommendations();
|
LoadRecommendations();
|
||||||
else if (pivot.SelectedItem == trending && !trendLoaded)
|
else if (pivot.SelectedItem == trending && !trendLoaded)
|
||||||
LoadTrending();
|
LoadTrending();
|
||||||
else if (pivot.SelectedItem == subscriptions && !subsLoaded)
|
else if (pivot.SelectedItem == subscriptions)
|
||||||
LoadSubscriptions();
|
LoadSubscriptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,63 +142,31 @@ namespace FoxTube
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
loading.Refresh();
|
loading.Refresh();
|
||||||
|
throw new NotImplementedException("This page has not implemented yet.");
|
||||||
throw new NotImplementedException();
|
|
||||||
|
|
||||||
loading.Close();
|
|
||||||
recLoaded = true;
|
|
||||||
}
|
}
|
||||||
catch (System.Net.Http.HttpRequestException)
|
catch (System.Net.Http.HttpRequestException)
|
||||||
{
|
{
|
||||||
recLoaded = false;
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
recLoaded = false;
|
|
||||||
loading.Error(e.GetType().ToString(), e.Message);
|
loading.Error(e.GetType().ToString(), e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async void LoadSubscriptions()
|
void LoadSubscriptions()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
loading.Refresh();
|
loading.Refresh();
|
||||||
List<SearchResult> items = new List<SearchResult>();
|
throw new NotImplementedException("This page has not implemented yet.");
|
||||||
SearchResource.ListRequest request = SecretsVault.Service.Search.List("snippet");
|
|
||||||
request.Type = "video";
|
|
||||||
request.MaxResults = 10;
|
|
||||||
request.Order = SearchResource.ListRequest.OrderEnum.Date;
|
|
||||||
|
|
||||||
foreach (Subscription i in SecretsVault.Subscriptions)
|
|
||||||
{
|
|
||||||
request.ChannelId = i.Snippet.ResourceId.ChannelId;
|
|
||||||
SearchListResponse response = await request.ExecuteAsync();
|
|
||||||
foreach (SearchResult result in response.Items)
|
|
||||||
items.Add(result);
|
|
||||||
if (response.NextPageToken != null)
|
|
||||||
subsTokens.Add(i.Snippet.ResourceId.ChannelId, response.NextPageToken);
|
|
||||||
}
|
|
||||||
if (subsTokens.Count == 0)
|
|
||||||
subsMore.Complete(true);
|
|
||||||
|
|
||||||
items = items.OrderByDescending(x => x.Snippet.PublishedAt).ToList();
|
|
||||||
|
|
||||||
foreach (SearchResult i in items)
|
|
||||||
subsGrid.Add(new VideoCard(i.Id.VideoId));
|
|
||||||
|
|
||||||
loading.Close();
|
|
||||||
subsLoaded = true;
|
|
||||||
}
|
}
|
||||||
catch (System.Net.Http.HttpRequestException)
|
catch (System.Net.Http.HttpRequestException)
|
||||||
{
|
{
|
||||||
subsLoaded = false;
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
subsLoaded = false;
|
|
||||||
loading.Error(e.GetType().ToString(), e.Message);
|
loading.Error(e.GetType().ToString(), e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,36 +2,15 @@
|
|||||||
x:Class="FoxTube.MainPage"
|
x:Class="FoxTube.MainPage"
|
||||||
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"
|
||||||
xmlns:local="using:FoxTube"
|
|
||||||
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:ads="using:Microsoft.Advertising.WinRT.UI"
|
|
||||||
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
|
||||||
xmlns:pages="using:FoxTube.Pages"
|
|
||||||
xmlns:Windows10version1803="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 6)"
|
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">
|
PreviewKeyUp="Page_PreviewKeyUp">
|
||||||
|
|
||||||
<Grid Name="grid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
<Grid Name="grid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<VisualStateManager.VisualStateGroups>
|
<NavigationView Header="Home" SelectedItem="toHome" Windows10version1803:BackRequested="nav_BackRequested" Windows10version1803:PaneTitle="FoxTube" OpenPaneLength="300" Name="nav" SelectionChanged="nav_SelectionChanged">
|
||||||
<VisualStateGroup>
|
|
||||||
<VisualState>
|
|
||||||
<VisualState.StateTriggers>
|
|
||||||
<AdaptiveTrigger MinWindowWidth="641"/>
|
|
||||||
</VisualState.StateTriggers>
|
|
||||||
|
|
||||||
<VisualState.Setters>
|
|
||||||
<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>
|
|
||||||
</VisualStateGroup>
|
|
||||||
</VisualStateManager.VisualStateGroups>
|
|
||||||
<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"/>
|
||||||
@@ -45,71 +24,58 @@
|
|||||||
</NavigationViewItem>
|
</NavigationViewItem>
|
||||||
<NavigationViewItem x:Uid="/Main/liked" Icon="Like" Content="Liked videos" Name="toLiked" Visibility="Collapsed"/>
|
<NavigationViewItem x:Uid="/Main/liked" Icon="Like" Content="Liked videos" Name="toLiked" Visibility="Collapsed"/>
|
||||||
<NavigationViewItem x:Uid="/Main/later" Icon="Clock" Content="Watch later" Name="toLater" Visibility="Collapsed"/>
|
<NavigationViewItem x:Uid="/Main/later" Icon="Clock" Content="Watch later" Name="toLater" Visibility="Collapsed"/>
|
||||||
<NavigationViewItem x:Uid="/Main/downloads" Icon="Download" Content="Downloads" Name="toDownloads" Visibility="Collapsed"/>
|
<NavigationViewItem x:Uid="/Main/downloads" Icon="Download" Content="Downloads" Name="toDownloads"/>
|
||||||
<NavigationViewItemHeader x:Uid="/Main/subscriptions" Content="Subscriptions" Name="subsHeader" Visibility="Collapsed"/>
|
<NavigationViewItemHeader x:Uid="/Main/subscriptions" Content="Subscriptions" Name="subsHeader" Visibility="Collapsed"/>
|
||||||
</NavigationView.MenuItems>
|
</NavigationView.MenuItems>
|
||||||
|
|
||||||
<NavigationView.PaneFooter>
|
<NavigationView.PaneFooter>
|
||||||
<StackPanel>
|
<NavigationViewList>
|
||||||
<Button Visibility="Visible" Name="feedback" Click="feedback_Click" Height="40" HorizontalAlignment="Stretch" Background="Transparent" HorizontalContentAlignment="Left">
|
<NavigationViewItem x:Uid="/Main/feedback" Name="feedback" Content="Give a feedback" Tapped="feedback_Click">
|
||||||
|
<NavigationViewItem.Icon>
|
||||||
|
<FontIcon Glyph=""/>
|
||||||
|
</NavigationViewItem.Icon>
|
||||||
|
</NavigationViewItem>
|
||||||
|
|
||||||
|
<NavigationViewItem x:Uid="/Main/adsFree" Content="Remove ads" Visibility="Collapsed" Name="removeAds">
|
||||||
|
<NavigationViewItem.Icon>
|
||||||
|
<FontIcon Glyph=""/>
|
||||||
|
</NavigationViewItem.Icon>
|
||||||
|
</NavigationViewItem>
|
||||||
|
|
||||||
|
<NavigationViewItem Name="account" Tapped="openContext">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<FontIcon Glyph="" FontSize="16" Margin="6,0,16,0"/>
|
<FontIcon Glyph="" FontSize="16" Margin="0,0,16,0"/>
|
||||||
<TextBlock x:Uid="/Main/feedback" Text="Give a feedback"/>
|
<TextBlock x:Uid="/Main/signIn" Text="Add account"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Button>
|
|
||||||
<Button Visibility="Collapsed" Name="removeAds" Height="40" HorizontalAlignment="Stretch" Background="Transparent" HorizontalContentAlignment="Left">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<FontIcon Glyph="" FontSize="16" Margin="6,0,16,0"/>
|
|
||||||
<TextBlock x:Uid="/Main/adsFree" Text="Remove ads"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
</StackPanel>
|
|
||||||
</NavigationView.PaneFooter>
|
|
||||||
|
|
||||||
<NavigationView.AutoSuggestBox>
|
<NavigationViewItem.ContextFlyout>
|
||||||
<AutoSuggestBox x:Name="search" QueryIcon="Find" QuerySubmitted="search_QuerySubmitted" TextChanged="search_TextChanged" x:Uid="/Main/searchPlaceholder" PlaceholderText="Search"/>
|
|
||||||
</NavigationView.AutoSuggestBox>
|
|
||||||
|
|
||||||
<NavigationView.Header>
|
|
||||||
<Grid Name="headerGrid" Margin="0,-10,0,0">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<TextBlock FontSize="24" VerticalAlignment="Center" Text="Home" Name="header"/>
|
|
||||||
<StackPanel Orientation="Horizontal" Grid.Column="1">
|
|
||||||
<Button Name="notificationMenu" Click="notificationMenu_Click"
|
|
||||||
FontFamily="Segoe MDL2 Assets" Content=""
|
|
||||||
Width="50" Height="42" Background="Transparent" x:Uid="notifications" ToolTipService.ToolTip="Notifications">
|
|
||||||
<Button.Flyout>
|
|
||||||
<Flyout Content="{x:Bind notificationsCenter}"/>
|
|
||||||
</Button.Flyout>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button Name="account"
|
|
||||||
FontFamily="Segoe MDL2 Assets" Content=""
|
|
||||||
Width="50" Height="42" Background="Transparent" x:Uid="signIn" ToolTipService.ToolTip="Sign in">
|
|
||||||
<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"/>
|
||||||
<MenuFlyoutItem x:Uid="/Main/signNew" Text="Create new Google account" Name="createAccount" Click="createAccount_Click"/>
|
<MenuFlyoutItem x:Uid="/Main/signNew" Text="Create new Google account" Name="createAccount" Click="createAccount_Click"/>
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</Button.Flyout>
|
</NavigationViewItem.ContextFlyout>
|
||||||
</Button>
|
</NavigationViewItem>
|
||||||
|
|
||||||
<Button Width="50" Background="Transparent" Height="42" Visibility="Collapsed" Name="avatar">
|
<NavigationViewItem Visibility="Collapsed" Name="avatar" Tapped="openContext" Padding="-5">
|
||||||
<PersonPicture Width="30" ToolTipService.ToolTip="My account" x:Uid="myAccount"/>
|
<StackPanel Orientation="Horizontal" Padding="5">
|
||||||
<Button.Flyout>
|
<PersonPicture Height="20" Margin="-5,0,15,0"/>
|
||||||
|
<TextBlock Name="myName" Text="My account"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<NavigationViewItem.ContextFlyout>
|
||||||
<MenuFlyout>
|
<MenuFlyout>
|
||||||
<MenuFlyoutItem x:Uid="/Main/myChannelContext" Text="My channel" Name="myChannel" Click="myChannel_Click"/>
|
<MenuFlyoutItem x:Uid="/Main/myChannelContext" Text="My channel" Name="myChannel" Click="myChannel_Click"/>
|
||||||
<MenuFlyoutSeparator/>
|
<MenuFlyoutSeparator/>
|
||||||
<MenuFlyoutItem x:Uid="/Main/signOut" Text="Log out" Name="logout" Click="logout_Click"/>
|
<MenuFlyoutItem x:Uid="/Main/signOut" Text="Log out" Name="logout" Click="logout_Click"/>
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</Button.Flyout>
|
</NavigationViewItem.ContextFlyout>
|
||||||
</Button>
|
</NavigationViewItem>
|
||||||
</StackPanel>
|
</NavigationViewList>
|
||||||
</Grid>
|
</NavigationView.PaneFooter>
|
||||||
</NavigationView.Header>
|
|
||||||
|
<NavigationView.AutoSuggestBox>
|
||||||
|
<AutoSuggestBox x:Name="search" QueryIcon="Find" QuerySubmitted="search_QuerySubmitted" TextChanged="search_TextChanged" x:Uid="/Main/searchPlaceholder" PlaceholderText="Search"/>
|
||||||
|
</NavigationView.AutoSuggestBox>
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Frame Name="content" Navigated="content_Navigated"/>
|
<Frame Name="content" Navigated="content_Navigated"/>
|
||||||
|
|||||||
@@ -9,122 +9,61 @@ using Windows.UI.Xaml.Navigation;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Windows.UI.Notifications;
|
using Windows.UI.Notifications;
|
||||||
using Windows.UI.Xaml.Media.Imaging;
|
using Windows.UI.Xaml.Media.Imaging;
|
||||||
using Windows.Storage;
|
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
using System.Globalization;
|
|
||||||
using Windows.ApplicationModel.Core;
|
using Windows.ApplicationModel.Core;
|
||||||
using Windows.System;
|
using Windows.System;
|
||||||
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.Pages;
|
using FoxTube.Pages;
|
||||||
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 Windows.UI.Core;
|
||||||
using Syroot.Windows.IO;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
|
||||||
|
|
||||||
namespace FoxTube
|
namespace FoxTube
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public enum Sender { Menu, Frame, None }
|
public enum Sender { Menu, Frame, None }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Main app's layout
|
||||||
|
/// </summary>
|
||||||
public sealed partial class MainPage : Page
|
public sealed partial class MainPage : Page
|
||||||
{
|
{
|
||||||
public DownloadAgent Agent = new DownloadAgent();
|
|
||||||
|
|
||||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
|
||||||
|
|
||||||
NotificationsCenter notificationsCenter = new NotificationsCenter();
|
|
||||||
Sender s = Sender.None;
|
Sender s = Sender.None;
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
if (settings.Values["quality"] == null)
|
|
||||||
settings.Values.Add("quality", "remember");
|
|
||||||
if (settings.Values["rememberedQuality"] == null)
|
|
||||||
settings.Values.Add("rememberedQuality", "1080p");
|
|
||||||
|
|
||||||
if (settings.Values["newVideoNotification"] == null)
|
|
||||||
settings.Values.Add("newVideoNotification", true);
|
|
||||||
if (settings.Values["newmessagesNotification"] == null)
|
|
||||||
settings.Values.Add("newmessagesNotification", true);
|
|
||||||
|
|
||||||
if (settings.Values["moblieWarning"] == null)
|
|
||||||
settings.Values.Add("moblieWarning", false);
|
|
||||||
if (settings.Values["videoAutoplay"] == null)
|
|
||||||
settings.Values.Add("videoAutoplay", true);
|
|
||||||
if (settings.Values["themeMode"] == null)
|
|
||||||
settings.Values.Add("themeMode", 2);
|
|
||||||
if (settings.Values["volume"] == null)
|
|
||||||
settings.Values.Add("volume", 100);
|
|
||||||
|
|
||||||
if (settings.Values["region"] == null)
|
|
||||||
settings.Values.Add("region", CultureInfo.CurrentCulture.Name);
|
|
||||||
if (settings.Values["safeSearch"] == null)
|
|
||||||
settings.Values.Add("safeSearch", 0);
|
|
||||||
|
|
||||||
if (settings.Values["defaultDownload"] == null)
|
|
||||||
settings.Values.Add("defaultDownload", Syroot.Windows.IO.KnownFolders.Downloads.Path + "\\DownloadedVideos");
|
|
||||||
|
|
||||||
if (settings.Values["notificationsHistory"] == null)
|
|
||||||
{
|
|
||||||
XmlDocument doc = new XmlDocument();
|
|
||||||
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null));
|
|
||||||
doc.AppendChild(doc.CreateElement("history"));
|
|
||||||
settings.Values.Add("notificationsHistory", doc.InnerXml);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//Comparing current version with last recorded version. If doesn't match, poping up changelog notification
|
||||||
PackageVersion ver = Package.Current.Id.Version;
|
PackageVersion ver = Package.Current.Id.Version;
|
||||||
if (settings.Values["ver"] == null)
|
if(SettingsStorage.Version != $"{ver.Major}.{ver.Minor}")
|
||||||
settings.Values.Add("ver", $"{ver.Major}.{ver.Minor}");
|
|
||||||
|
|
||||||
if((string)settings.Values["ver"] != $"{ver.Major}.{ver.Minor}")
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
XmlDocument changelog = new XmlDocument();
|
XmlDocument changelog = new XmlDocument();
|
||||||
changelog.Load("http://foxgame.hol.es/foxtube-changelog.xml");
|
changelog.Load("http://foxgame-studio.000webhostapp.com/foxtube-changelog.xml");
|
||||||
XmlElement e = changelog["items"].ChildNodes[0] as XmlElement;
|
XmlElement e = changelog["items"].ChildNodes[0] as XmlElement;
|
||||||
|
|
||||||
XmlDocument doc = new XmlDocument();
|
ToastNotificationManager.CreateToastNotifier().Show(FoxTube.Background.Notification.GetChangelogToast(e.GetAttribute("version")));
|
||||||
doc.LoadXml(settings.Values["notificationsHistory"] as string);
|
|
||||||
|
|
||||||
Background.Notification n = new Background.Notification("changelog",
|
SettingsStorage.Version = $"{ver.Major}.{ver.Minor}";
|
||||||
$"changelog-{e.GetAttribute("version").Replace('.', '-')}",
|
|
||||||
"Changelog",
|
|
||||||
$"What's new in version {e.GetAttribute("version")}",
|
|
||||||
DateTime.Parse(e.GetAttribute("time")),
|
|
||||||
"http://foxgame.hol.es/FoxTubeAssets/WhatsNewThumb.png",
|
|
||||||
"http://foxgame.hol.es/FoxTubeAssets/NewsAvatar.png");
|
|
||||||
|
|
||||||
doc["history"].InnerXml += n.GetXml();
|
|
||||||
settings.Values["notificationsHistory"] = doc.InnerXml;
|
|
||||||
|
|
||||||
ToastNotificationManager.CreateToastNotifier().Show(n.GetToast());
|
|
||||||
|
|
||||||
settings.Values["ver"] = $"{ver.Major}.{ver.Minor}";
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
}
|
|
||||||
notificationsCenter.Initialize();
|
|
||||||
|
|
||||||
SecretsVault.AuthorizationStateChanged += Vault_AuthorizationStateChanged;
|
|
||||||
SecretsVault.SubscriptionsChanged += SecretsVault_SubscriptionsChanged;
|
|
||||||
SetTitleBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
|
||||||
{
|
{
|
||||||
base.OnNavigatedTo(e);
|
Debug.WriteLine("Unable to retrieve changelog");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SecretsVault.AuthorizationStateChanged += AuthorizationStateChanged;
|
||||||
|
SecretsVault.SubscriptionsChanged += SecretsVault_SubscriptionsChanged;
|
||||||
|
SecretsVault.NotPurchased += () => removeAds.Visibility = Visibility.Visible;
|
||||||
|
SecretsVault.CheckAuthorization();
|
||||||
|
SecretsVault.CheckAddons();
|
||||||
|
|
||||||
SetTitleBar();
|
SetTitleBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,65 +77,87 @@ namespace FoxTube
|
|||||||
{
|
{
|
||||||
var titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
var titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
||||||
|
|
||||||
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
titleBar.BackgroundColor = Colors.Red;
|
||||||
|
titleBar.ButtonBackgroundColor = Colors.Red;
|
||||||
titleBar.ButtonHoverBackgroundColor = Colors.IndianRed;
|
titleBar.ButtonHoverBackgroundColor = Colors.IndianRed;
|
||||||
titleBar.ButtonPressedBackgroundColor = Colors.DarkRed;
|
titleBar.ButtonPressedBackgroundColor = Colors.DarkRed;
|
||||||
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
titleBar.ButtonInactiveBackgroundColor = Colors.Black;
|
||||||
|
titleBar.ForegroundColor = Colors.White;
|
||||||
|
|
||||||
if((int)settings.Values["themeMode"] == 2)
|
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = false;
|
||||||
{
|
|
||||||
Color uiTheme = new UISettings().GetColorValue(UIColorType.Background);
|
|
||||||
if (uiTheme == Colors.Black)
|
|
||||||
titleBar.ButtonForegroundColor = Colors.White;
|
|
||||||
else
|
|
||||||
titleBar.ButtonForegroundColor = Colors.Black;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (RequestedTheme == ElementTheme.Dark)
|
|
||||||
titleBar.ButtonForegroundColor = Colors.White;
|
|
||||||
else if (RequestedTheme == ElementTheme.Light)
|
|
||||||
titleBar.ButtonForegroundColor = Colors.Black;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreApplicationViewTitleBar coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
|
|
||||||
coreTitleBar.ExtendViewIntoTitleBar = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when subscriptions are edited to edit menu
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
private void SecretsVault_SubscriptionsChanged(object sender, params object[] args)
|
private void SecretsVault_SubscriptionsChanged(object sender, params object[] args)
|
||||||
{
|
{
|
||||||
if ((string)args[0] == "add" && nav.MenuItems.Count < 19)
|
if ((string)args[0] == "add" && nav.MenuItems.Count < 19)
|
||||||
{
|
{
|
||||||
|
subsHeader.Visibility = Visibility.Visible;
|
||||||
|
|
||||||
Subscription s = args[1] as Subscription;
|
Subscription s = args[1] as Subscription;
|
||||||
StackPanel panel = new StackPanel() { Orientation = Orientation.Horizontal };
|
StackPanel panel = new StackPanel()
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
Padding = new Thickness(5)
|
||||||
|
};
|
||||||
panel.Children.Add(new PersonPicture()
|
panel.Children.Add(new PersonPicture()
|
||||||
{
|
{
|
||||||
Height = 20,
|
Height = 20,
|
||||||
Margin = new Thickness(0, 0, 13, 0),
|
Margin = new Thickness(-5, 0, 15, 0),
|
||||||
ProfilePicture = new BitmapImage(new Uri(s.Snippet.Thumbnails.Medium.Url))
|
ProfilePicture = new BitmapImage(new Uri(s.Snippet.Thumbnails.Medium.Url))
|
||||||
});
|
});
|
||||||
panel.Children.Add(new TextBlock() { Text = s.Snippet.Title });
|
panel.Children.Add(new TextBlock() { Text = s.Snippet.Title });
|
||||||
nav.MenuItems.Add(new NavigationViewItem()
|
nav.MenuItems.Add(new NavigationViewItem()
|
||||||
{
|
{
|
||||||
Content = panel,
|
Content = panel,
|
||||||
Name = (nav.MenuItems.Count - 9).ToString()
|
Name = (nav.MenuItems.Count - 9).ToString(),
|
||||||
|
Padding = new Thickness(-5)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if ((string)args[0] == "remove" && (int)args[1] < 10)
|
else if ((string)args[0] == "remove" && (int)args[1] < 10)
|
||||||
|
{
|
||||||
nav.MenuItems.RemoveAt((int)args[1] + 9);
|
nav.MenuItems.RemoveAt((int)args[1] + 9);
|
||||||
|
if(SecretsVault.Subscriptions.Count >= 10)
|
||||||
|
{
|
||||||
|
Subscription s = SecretsVault.Subscriptions[9];
|
||||||
|
StackPanel panel = new StackPanel()
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
Padding = new Thickness(5)
|
||||||
|
};
|
||||||
|
panel.Children.Add(new PersonPicture()
|
||||||
|
{
|
||||||
|
Height = 20,
|
||||||
|
Margin = new Thickness(-5, 0, 15, 0),
|
||||||
|
ProfilePicture = new BitmapImage(new Uri(s.Snippet.Thumbnails.Medium.Url))
|
||||||
|
});
|
||||||
|
panel.Children.Add(new TextBlock() { Text = s.Snippet.Title });
|
||||||
|
nav.MenuItems.Add(new NavigationViewItem()
|
||||||
|
{
|
||||||
|
Content = panel,
|
||||||
|
Name = (nav.MenuItems.Count - 9).ToString(),
|
||||||
|
Padding = new Thickness(-5)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Vault_AuthorizationStateChanged(object sender, EventArgs e)
|
|
||||||
|
private async void AuthorizationStateChanged(object sender, params object[] e)
|
||||||
{
|
{
|
||||||
if(SecretsVault.IsAuthorized)
|
if(e[0] as bool? == true)
|
||||||
{
|
{
|
||||||
account.Visibility = Visibility.Collapsed;
|
account.Visibility = Visibility.Collapsed;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Userinfoplus info = await new Oauth2Service(SecretsVault.Initializer).Userinfo.Get().ExecuteAsync();
|
Userinfoplus info = await new Oauth2Service(SecretsVault.Initializer).Userinfo.Get().ExecuteAsync();
|
||||||
|
|
||||||
ToolTipService.SetToolTip(avatar, new ToolTip() { Content = info.Name });
|
myName.Text = info.Name;
|
||||||
(avatar.Content as PersonPicture).ProfilePicture = new BitmapImage(new Uri(info.Picture));
|
((avatar.Content as StackPanel).Children[0] as PersonPicture).ProfilePicture = new BitmapImage(new Uri(info.Picture));
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
avatar.Visibility = Visibility.Visible;
|
avatar.Visibility = Visibility.Visible;
|
||||||
@@ -207,8 +168,6 @@ namespace FoxTube
|
|||||||
toHistory.Visibility = Visibility.Visible;
|
toHistory.Visibility = Visibility.Visible;
|
||||||
toLiked.Visibility = Visibility.Visible;
|
toLiked.Visibility = Visibility.Visible;
|
||||||
toLater.Visibility = Visibility.Visible;
|
toLater.Visibility = Visibility.Visible;
|
||||||
toDownloads.Visibility = Visibility.Visible;
|
|
||||||
subsHeader.Visibility = Visibility.Visible;
|
|
||||||
|
|
||||||
if (SecretsVault.Subscriptions.Count > 0)
|
if (SecretsVault.Subscriptions.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -217,24 +176,29 @@ namespace FoxTube
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Subscription s = SecretsVault.Subscriptions[k];
|
Subscription s = SecretsVault.Subscriptions[k];
|
||||||
StackPanel panel = new StackPanel() { Orientation = Orientation.Horizontal };
|
StackPanel panel = new StackPanel()
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
Padding = new Thickness(5)
|
||||||
|
};
|
||||||
panel.Children.Add(new PersonPicture()
|
panel.Children.Add(new PersonPicture()
|
||||||
{
|
{
|
||||||
Height = 20,
|
Height = 20,
|
||||||
Margin = new Thickness(0, 0, 13, 0),
|
Margin = new Thickness(-5, 0, 15, 0),
|
||||||
ProfilePicture = new BitmapImage(new Uri(s.Snippet.Thumbnails.Medium.Url))
|
ProfilePicture = new BitmapImage(new Uri(s.Snippet.Thumbnails.Medium.Url))
|
||||||
});
|
});
|
||||||
panel.Children.Add(new TextBlock() { Text = s.Snippet.Title });
|
panel.Children.Add(new TextBlock() { Text = s.Snippet.Title });
|
||||||
nav.MenuItems.Add(new NavigationViewItem()
|
nav.MenuItems.Add(new NavigationViewItem()
|
||||||
{
|
{
|
||||||
Content = panel,
|
Content = panel,
|
||||||
Name = k.ToString()
|
Name = k.ToString(),
|
||||||
|
Padding = new Thickness(-5)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch { continue; }
|
catch { continue; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (e[0] as bool? == false)
|
||||||
{
|
{
|
||||||
account.Visibility = Visibility.Visible;
|
account.Visibility = Visibility.Visible;
|
||||||
avatar.Visibility = Visibility.Collapsed;
|
avatar.Visibility = Visibility.Collapsed;
|
||||||
@@ -245,32 +209,41 @@ namespace FoxTube
|
|||||||
toHistory.Visibility = Visibility.Collapsed;
|
toHistory.Visibility = Visibility.Collapsed;
|
||||||
toLiked.Visibility = Visibility.Collapsed;
|
toLiked.Visibility = Visibility.Collapsed;
|
||||||
toLater.Visibility = Visibility.Collapsed;
|
toLater.Visibility = Visibility.Collapsed;
|
||||||
toDownloads.Visibility = Visibility.Collapsed;
|
|
||||||
subsHeader.Visibility = Visibility.Collapsed;
|
subsHeader.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
subsHeader.Visibility = Visibility.Collapsed;
|
subsHeader.Visibility = Visibility.Collapsed;
|
||||||
for(int k = 9; k < nav.MenuItems.Count; k++)
|
for(int k = 9; k < nav.MenuItems.Count; k++)
|
||||||
nav.MenuItems.RemoveAt(k);
|
nav.MenuItems.RemoveAt(k);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageDialog dialog = new MessageDialog("We were unabled to retrieve your account information due to weak internet connection or Google servers' problems. PLease, try again later", "Failed to connect");
|
||||||
|
|
||||||
|
dialog.Commands.Add(new UICommand("Try again", (command) =>
|
||||||
|
{
|
||||||
|
SecretsVault.Authorize();
|
||||||
|
}));
|
||||||
|
dialog.Commands.Add(new UICommand("Quit", (command) =>
|
||||||
|
{
|
||||||
|
Methods.CloseApp();
|
||||||
|
}));
|
||||||
|
|
||||||
|
dialog.CancelCommandIndex = 1;
|
||||||
|
dialog.DefaultCommandIndex = 0;
|
||||||
|
|
||||||
|
await dialog.ShowAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e[0] as bool? != null)
|
||||||
|
DownloadAgent.Initialize();
|
||||||
|
|
||||||
nav.SelectedItem = toHome;
|
|
||||||
content.Navigate(typeof(Home));
|
content.Navigate(typeof(Home));
|
||||||
|
|
||||||
if (videoPlaceholder.Content != null)
|
if (videoPlaceholder.Content != null)
|
||||||
GoToVideo((videoPlaceholder.Content as VideoPage).videoId);
|
GoToVideo((videoPlaceholder.Content as VideoPage).videoId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GotNotification()
|
private async void feedback_Click(object sender, TappedRoutedEventArgs e)
|
||||||
{
|
|
||||||
notificationMenu.Content = "\xED0C";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notificationMenu_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
notificationMenu.Content = "\xED0D";
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void feedback_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
{
|
||||||
await Launcher.LaunchUriAsync(new Uri("feedback-hub:"));
|
await Launcher.LaunchUriAsync(new Uri("feedback-hub:"));
|
||||||
}
|
}
|
||||||
@@ -287,7 +260,7 @@ namespace FoxTube
|
|||||||
|
|
||||||
private void myChannel_Click(object sender, RoutedEventArgs e)
|
private void myChannel_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
content.Navigate(typeof(Channel), SecretsVault.UserChannel.Id);
|
GoToChannel(SecretsVault.AccountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logout_Click(object sender, RoutedEventArgs e)
|
private void logout_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -298,26 +271,27 @@ namespace FoxTube
|
|||||||
public void GoToSearch(SearchParameters args)
|
public void GoToSearch(SearchParameters args)
|
||||||
{
|
{
|
||||||
nav.IsPaneOpen = false;
|
nav.IsPaneOpen = false;
|
||||||
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();
|
|
||||||
content.Navigate(typeof(ChannelPage), id);
|
content.Navigate(typeof(ChannelPage), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GoToHome()
|
||||||
|
{
|
||||||
|
content.Navigate(typeof(Home));
|
||||||
|
}
|
||||||
|
|
||||||
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}");
|
bool cancel = false;
|
||||||
try
|
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 (SettingsStorage.CheckConnection && (connection.NetworkCostType == NetworkCostType.Fixed || connection.NetworkCostType == NetworkCostType.Variable))
|
||||||
{
|
{
|
||||||
bool cancel = false;
|
|
||||||
MessageDialog dialog = new MessageDialog("You are on metered connection now. Additional charges may apply. Do you want to continue?")
|
MessageDialog dialog = new MessageDialog("You are on metered connection now. Additional charges may apply. Do you want to continue?")
|
||||||
{
|
{
|
||||||
DefaultCommandIndex = 2,
|
DefaultCommandIndex = 2,
|
||||||
@@ -325,41 +299,62 @@ namespace FoxTube
|
|||||||
};
|
};
|
||||||
dialog.Commands.Add(new UICommand("Yes"));
|
dialog.Commands.Add(new UICommand("Yes"));
|
||||||
dialog.Commands.Add(new UICommand("No", (command) => cancel = true));
|
dialog.Commands.Add(new UICommand("No", (command) => cancel = true));
|
||||||
|
if(SecretsVault.IsAuthorized)
|
||||||
dialog.Commands.Add(new UICommand("Add to 'Watch later' playlist", (command) =>
|
dialog.Commands.Add(new UICommand("Add to 'Watch later' playlist", (command) =>
|
||||||
{
|
{
|
||||||
//TO-DO: Adding video to "Watch later"
|
try
|
||||||
|
{
|
||||||
|
PlaylistItem item = new PlaylistItem()
|
||||||
|
{
|
||||||
|
Snippet = new PlaylistItemSnippet()
|
||||||
|
{
|
||||||
|
ResourceId = new ResourceId()
|
||||||
|
{
|
||||||
|
Kind = "youtube#video",
|
||||||
|
VideoId = id
|
||||||
|
},
|
||||||
|
PlaylistId = "WL"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SecretsVault.Service.PlaylistItems.Insert(item, "snippet").Execute();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(e.Message);
|
||||||
|
}
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}));
|
}));
|
||||||
await dialog.ShowAsync();
|
|
||||||
|
|
||||||
if (cancel)
|
await dialog.ShowAsync();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
if (cancel)
|
||||||
nav.IsPaneOpen = false;
|
return;
|
||||||
|
|
||||||
videoPlaceholder.Content = null;
|
videoPlaceholder.Content = null;
|
||||||
MaximizeVideo();
|
|
||||||
Fullscreen(false);
|
Fullscreen(false);
|
||||||
|
|
||||||
videoPlaceholder.Navigate(typeof(VideoPage), new string[2] { id, playlistId });
|
videoPlaceholder.Navigate(typeof(VideoPage), new string[2] { id, playlistId });
|
||||||
|
MaximizeVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GoToDeveloper(string id)
|
public void GoToDeveloper(string id)
|
||||||
{
|
{
|
||||||
MinimizeAsInitializer();
|
|
||||||
content.Navigate(typeof(Settings), $"inbox&{id}");
|
content.Navigate(typeof(Settings), $"inbox&{id}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GoToPlaylist(string id)
|
public void GoToPlaylist(string id)
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"Playlist id: {id}");
|
|
||||||
MinimizeAsInitializer();
|
|
||||||
content.Navigate(typeof(PlaylistPage), id);
|
content.Navigate(typeof(PlaylistPage), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GoToDownloads()
|
||||||
|
{
|
||||||
|
content.Navigate(typeof(Downloads));
|
||||||
|
}
|
||||||
|
|
||||||
private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
|
private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (videoPlaceholder.Content != null)
|
if (videoPlaceholder.Content != null)
|
||||||
@@ -392,6 +387,30 @@ namespace FoxTube
|
|||||||
nav.IsBackEnabled = true;
|
nav.IsBackEnabled = true;
|
||||||
else
|
else
|
||||||
nav.IsBackEnabled = false;
|
nav.IsBackEnabled = false;
|
||||||
|
|
||||||
|
Dictionary<Type, Action> switchCase = new Dictionary<Type, Action>()
|
||||||
|
{
|
||||||
|
{ typeof(Settings), () => nav.Header = "Settings" },
|
||||||
|
{ typeof(ChannelPage), () => nav.Header = "Channel" },
|
||||||
|
{ typeof(PlaylistPage), () => nav.Header = "Playlist" },
|
||||||
|
{ typeof(Search), () => nav.Header = "Search" },
|
||||||
|
{ typeof(Subscriptions), () => nav.Header = "Subscriptions" },
|
||||||
|
{ typeof(History), () => nav.Header = "History" },
|
||||||
|
{ typeof(Home), () => nav.Header = "Home" },
|
||||||
|
{ typeof(Downloads), () => nav.Header = "Downloads" }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (content.SourcePageType == typeof(Home) || content.SourcePageType == typeof(Settings) || content.SourcePageType == typeof(Subscriptions))
|
||||||
|
{
|
||||||
|
nav.ExpandedModeThresholdWidth = 1008;
|
||||||
|
if (nav.DisplayMode == NavigationViewDisplayMode.Expanded)
|
||||||
|
nav.IsPaneOpen = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
nav.ExpandedModeThresholdWidth = short.MaxValue;
|
||||||
|
|
||||||
|
try { switchCase[content.SourcePageType](); }
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MaximizeVideo()
|
public void MaximizeVideo()
|
||||||
@@ -403,24 +422,38 @@ namespace FoxTube
|
|||||||
videoPlaceholder.Margin = new Thickness(0);
|
videoPlaceholder.Margin = new Thickness(0);
|
||||||
|
|
||||||
nav.IsBackEnabled = true;
|
nav.IsBackEnabled = true;
|
||||||
|
|
||||||
|
if (videoPlaceholder.Content != null)
|
||||||
|
{
|
||||||
|
nav.Header = "Video";
|
||||||
|
nav.ExpandedModeThresholdWidth = short.MaxValue;
|
||||||
|
nav.IsPaneOpen = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Fullscreen(bool on)
|
public void Fullscreen(bool on)
|
||||||
{
|
{
|
||||||
if (on)
|
if (on)
|
||||||
{
|
{
|
||||||
|
nav.CompactModeThresholdWidth = short.MaxValue;
|
||||||
|
nav.ExpandedModeThresholdWidth = short.MaxValue;
|
||||||
nav.OpenPaneLength = 0;
|
nav.OpenPaneLength = 0;
|
||||||
nav.CompactPaneLength = 0;
|
nav.CompactPaneLength = 0;
|
||||||
if ((videoPlaceholder.Content as VideoPage).player.MiniView)
|
nav.Margin = new Thickness(0, -45, 0, 0);
|
||||||
nav.Margin = new Thickness(0, -80, 0, 0);
|
|
||||||
else
|
|
||||||
nav.Margin = new Thickness(0, -91, 0, 0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
nav.CompactModeThresholdWidth = 641;
|
||||||
|
nav.ExpandedModeThresholdWidth = 1008;
|
||||||
nav.Margin = new Thickness(0);
|
nav.Margin = new Thickness(0);
|
||||||
|
if (videoPlaceholder.Content != null && nav.IsPaneOpen)
|
||||||
|
nav.IsPaneOpen = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
nav.OpenPaneLength = 300;
|
nav.OpenPaneLength = 300;
|
||||||
nav.CompactPaneLength = 48;
|
nav.CompactPaneLength = 40;
|
||||||
|
}
|
||||||
|
SetTitleBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,6 +505,9 @@ namespace FoxTube
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void nav_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
|
private void nav_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Menu selection changed");
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (s == Sender.None)
|
if (s == Sender.None)
|
||||||
{
|
{
|
||||||
@@ -501,19 +537,21 @@ namespace FoxTube
|
|||||||
else
|
else
|
||||||
s = Sender.None;
|
s = Sender.None;
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
public 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>()
|
||||||
{
|
{
|
||||||
{ typeof(Settings), () => header.Text = "Settings" },
|
{ typeof(Settings), () => nav.Header = "Settings" },
|
||||||
{ typeof(ChannelPage), () => header.Text = "Channel" },
|
{ typeof(ChannelPage), () => nav.Header = "Channel" },
|
||||||
{ typeof(PlaylistPage), () => header.Text = "Playlist" },
|
{ typeof(PlaylistPage), () => nav.Header = "Playlist" },
|
||||||
{ typeof(Search), () => header.Text = "Search" },
|
{ typeof(Search), () => nav.Header = "Search" },
|
||||||
{ typeof(Subscriptions), () => header.Text = "Subscriptions" },
|
{ typeof(Subscriptions), () => nav.Header = "Subscriptions" },
|
||||||
{ typeof(History), () => header.Text = "History" },
|
{ typeof(History), () => nav.Header = "History" },
|
||||||
{ typeof(Home), () => header.Text = "Home" },
|
{ typeof(Home), () => nav.Header = "Home" },
|
||||||
{ typeof(Downloads), () => header.Text = "Downloads" }
|
{ typeof(Downloads), () => nav.Header = "Downloads" }
|
||||||
};
|
};
|
||||||
|
|
||||||
try { switchCase[e.SourcePageType](); }
|
try { switchCase[e.SourcePageType](); }
|
||||||
@@ -654,17 +692,12 @@ namespace FoxTube
|
|||||||
nav.IsPaneOpen = true;
|
nav.IsPaneOpen = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nav.ExpandedModeThresholdWidth = int.MaxValue;
|
nav.ExpandedModeThresholdWidth = short.MaxValue;
|
||||||
|
|
||||||
if (videoPlaceholder.Content != null && videoPlaceholder.HorizontalAlignment == HorizontalAlignment.Stretch)
|
if (videoPlaceholder.Content != null && videoPlaceholder.HorizontalAlignment == HorizontalAlignment.Stretch)
|
||||||
MinimizeAsInitializer();
|
MinimizeAsInitializer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toChannel_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
GoToChannel(SecretsVault.UserChannel.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void nav_BackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
|
private void nav_BackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
|
||||||
{
|
{
|
||||||
if (videoPlaceholder.Content != null)
|
if (videoPlaceholder.Content != null)
|
||||||
@@ -673,8 +706,6 @@ namespace FoxTube
|
|||||||
CloseVideo();
|
CloseVideo();
|
||||||
else if (videoPlaceholder.HorizontalAlignment == HorizontalAlignment.Stretch)
|
else if (videoPlaceholder.HorizontalAlignment == HorizontalAlignment.Stretch)
|
||||||
MinimizeAsInitializer();
|
MinimizeAsInitializer();
|
||||||
else
|
|
||||||
content.GoBack();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
content.GoBack();
|
content.GoBack();
|
||||||
@@ -688,5 +719,10 @@ namespace FoxTube
|
|||||||
(videoPlaceholder.Content as VideoPage).player.KeyUpPressed(sender, e);
|
(videoPlaceholder.Content as VideoPage).player.KeyUpPressed(sender, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void openContext(object sender, TappedRoutedEventArgs e)
|
||||||
|
{
|
||||||
|
((NavigationViewItem)sender).ContextFlyout.ShowAt((NavigationViewItem)sender);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,32 +2,18 @@
|
|||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.ApplicationModel;
|
|
||||||
using Windows.ApplicationModel.DataTransfer;
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
using Windows.Foundation;
|
using Windows.Foundation;
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.Storage;
|
|
||||||
using Windows.Storage.Streams;
|
|
||||||
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.Media.Imaging;
|
using Windows.UI.Xaml.Media.Imaging;
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
|
||||||
|
|
||||||
namespace FoxTube.Pages
|
namespace FoxTube.Pages
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
/// Playlist page
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class PlaylistPage : Page
|
public sealed partial class PlaylistPage : Page
|
||||||
{
|
{
|
||||||
@@ -39,7 +25,7 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
public PlaylistPage()
|
public PlaylistPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
loading = grid.Children[2] as LoadingPage;
|
loading = grid.Children[2] as LoadingPage;
|
||||||
list = ((grid.Children[0] as ScrollViewer).Content as Grid).Children[1] as VideoGrid;
|
list = ((grid.Children[0] as ScrollViewer).Content as Grid).Children[1] as VideoGrid;
|
||||||
loading.RefreshPage += refresh_Click;
|
loading.RefreshPage += refresh_Click;
|
||||||
@@ -129,7 +115,7 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
private void refresh_Click(object sender, RoutedEventArgs e)
|
private void refresh_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Initialize(playlistId);
|
Methods.MainPage.GoToPlaylist(playlistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void share_Click(object sender, RoutedEventArgs e)
|
private void share_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -137,42 +123,13 @@ namespace FoxTube.Pages
|
|||||||
DataTransferManager.ShowShareUI();
|
DataTransferManager.ShowShareUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Share(DataTransferManager sender, DataRequestedEventArgs args)
|
private void Share(DataTransferManager sender, DataRequestedEventArgs args)
|
||||||
{
|
{
|
||||||
DataRequest request = args.Request;
|
Methods.Share(args,
|
||||||
request.Data.Properties.Title = item.Snippet.Title;
|
item.Snippet.Thumbnails.Medium.Url,
|
||||||
request.Data.Properties.Description = "Sharing a playlist";
|
item.Snippet.Title,
|
||||||
|
$"https://www.youtube.com/playlist?list={item.Id}",
|
||||||
// Handle errors
|
"playlist");
|
||||||
//request.FailWithDisplayText("Something unexpected could happen.");
|
|
||||||
|
|
||||||
// Plain text
|
|
||||||
request.Data.SetText(item.Snippet.Title + "\n" + "#YouTube #FoxTube #SharedWithFoxTube");
|
|
||||||
|
|
||||||
// Uniform Resource Identifiers (URIs)
|
|
||||||
request.Data.SetWebLink(new Uri($"https://www.youtube.com/playlist?list={item.Id}"));
|
|
||||||
|
|
||||||
// HTML
|
|
||||||
//request.Data.SetHtmlFormat("<b>Bold Text</b>");
|
|
||||||
|
|
||||||
// Because we are making async calls in the DataRequested event handler,
|
|
||||||
// we need to get the deferral first.
|
|
||||||
DataRequestDeferral deferral = request.GetDeferral();
|
|
||||||
|
|
||||||
// Make sure we always call Complete on the deferral.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StorageFile thumbnailFile = await Package.Current.InstalledLocation.GetFileAsync(item.Snippet.Thumbnails.Medium.Url);
|
|
||||||
request.Data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromFile(thumbnailFile);
|
|
||||||
StorageFile imageFile = await Package.Current.InstalledLocation.GetFileAsync(item.Snippet.Thumbnails.Medium.Url);
|
|
||||||
|
|
||||||
// Bitmaps
|
|
||||||
request.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(imageFile));
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
deferral.Complete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,29 +3,17 @@ using FoxTube.Pages;
|
|||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
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 Windows.UI.Xaml.Navigation;
|
||||||
using Windows.System;
|
using Windows.System;
|
||||||
|
using System.Globalization;
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
|
||||||
|
|
||||||
namespace FoxTube
|
namespace FoxTube
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
/// Search page
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class Search : Page
|
public sealed partial class Search : Page
|
||||||
{
|
{
|
||||||
@@ -40,7 +28,7 @@ namespace FoxTube
|
|||||||
|
|
||||||
public Search()
|
public Search()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
loading = grid.Children[2] as LoadingPage;
|
loading = grid.Children[2] as LoadingPage;
|
||||||
list = ((grid.Children[0] as ScrollViewer).Content as StackPanel).Children[4] as VideoGrid;
|
list = ((grid.Children[0] as ScrollViewer).Content as StackPanel).Children[4] as VideoGrid;
|
||||||
more = ((grid.Children[0] as ScrollViewer).Content as StackPanel).Children[5] as ShowMore;
|
more = ((grid.Children[0] as ScrollViewer).Content as StackPanel).Children[5] as ShowMore;
|
||||||
@@ -108,14 +96,10 @@ namespace FoxTube
|
|||||||
}
|
}
|
||||||
request.Q = arg.Term;
|
request.Q = arg.Term;
|
||||||
request.SafeSearch = (SearchResource.ListRequest.SafeSearchEnum)(int)settings.Values["safeSearch"];
|
request.SafeSearch = (SearchResource.ListRequest.SafeSearchEnum)(int)settings.Values["safeSearch"];
|
||||||
try
|
|
||||||
{
|
request.RegionCode = CultureInfo.GetCultures(CultureTypes.AllCultures).Find(i => i.IetfLanguageTag == SettingsStorage.Region).IetfLanguageTag.Remove(0, 3);
|
||||||
request.RelevanceLanguage = settings.Values["region"].ToString().Remove(2).ToLower();
|
request.RelevanceLanguage = CultureInfo.GetCultures(CultureTypes.AllCultures).Find(i => i.IetfLanguageTag == SettingsStorage.Region).TwoLetterISOLanguageName;
|
||||||
}
|
|
||||||
catch (ArgumentOutOfRangeException)
|
|
||||||
{
|
|
||||||
request.RelevanceLanguage = settings.Values["region"].ToString().ToLower();
|
|
||||||
}
|
|
||||||
request.MaxResults = 48;
|
request.MaxResults = 48;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -185,7 +169,7 @@ namespace FoxTube
|
|||||||
|
|
||||||
private void AppBarButton_Click(object sender, RoutedEventArgs e)
|
private void AppBarButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Initialize(Parameters);
|
Methods.MainPage.GoToSearch(Parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void more_Clicked()
|
private async void more_Clicked()
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ namespace FoxTube
|
|||||||
public sealed partial class Settings : Page
|
public sealed partial class Settings : Page
|
||||||
{
|
{
|
||||||
bool inboxLoaded = false;
|
bool inboxLoaded = false;
|
||||||
|
string inboxId = null;
|
||||||
public Settings()
|
public Settings()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
@@ -38,21 +39,21 @@ namespace FoxTube
|
|||||||
base.OnNavigatedTo(e);
|
base.OnNavigatedTo(e);
|
||||||
if(!string.IsNullOrWhiteSpace(e.Parameter as string))
|
if(!string.IsNullOrWhiteSpace(e.Parameter as string))
|
||||||
{
|
{
|
||||||
if ((e.Parameter as string).Contains("inbox"))
|
if ((e.Parameter as string).Contains("inbox") || (e.Parameter as string).Contains("changelog"))
|
||||||
{
|
{
|
||||||
pivot.SelectedIndex = 3;
|
if ((string)e.Parameter != "inbox" && (string)e.Parameter != "changelog")
|
||||||
if ((string)e.Parameter != "inbox")
|
inboxId = e.Parameter as string;
|
||||||
((pivot.SelectedItem as PivotItem).Content as Inbox).Open((e.Parameter as string).Split('&')[1]);
|
pivot.SelectedIndex = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
switch(e.Parameter as string)
|
switch(e.Parameter as string)
|
||||||
{
|
{
|
||||||
case "about":
|
case "about":
|
||||||
pivot.SelectedIndex = 2;
|
pivot.SelectedIndex = 1;
|
||||||
break;
|
break;
|
||||||
case "translate":
|
/*case "translate":
|
||||||
pivot.SelectedIndex = 3;
|
pivot.SelectedIndex = 3;
|
||||||
break;
|
break;*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,6 +64,11 @@ namespace FoxTube
|
|||||||
{
|
{
|
||||||
(((pivot.Items[2] 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;
|
||||||
|
if(inboxId != null)
|
||||||
|
{
|
||||||
|
(((pivot.Items[2] as PivotItem).Content as ScrollViewer).Content as Inbox).Open(inboxId as string);
|
||||||
|
inboxId = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
|
|
||||||
<TextBlock x:Uid="/General/notifications" Text="Notifications" FontSize="22"/>
|
<TextBlock x:Uid="/General/notifications" Text="Notifications" FontSize="22"/>
|
||||||
<ToggleSwitch x:Uid="/General/newVideo" Name="newVideo" OnContent="Notify when someone of your subscriptions uploaded new video" OffContent="Notify when someone of your subscriptions uploaded new video" Toggled="notification_IsEnabledChanged"/>
|
<ToggleSwitch x:Uid="/General/newVideo" Name="newVideo" OnContent="Notify when someone of your subscriptions uploaded new video" OffContent="Notify when someone of your subscriptions uploaded new video" Toggled="notification_IsEnabledChanged"/>
|
||||||
|
<ToggleSwitch Name="devNews" OnContent="Recieve messages from developers" OffContent="Recieve messages from developers" Toggled="devNews_Toggled"/>
|
||||||
|
|
||||||
<TextBlock x:Uid="/General/color" Text="Color mode" FontSize="22"/>
|
<TextBlock x:Uid="/General/color" Text="Color mode" FontSize="22"/>
|
||||||
<RadioButton x:Uid="/General/colorLight" Content="Light" Name="light" GroupName="color" Checked="RadioButton_Checked"/>
|
<RadioButton x:Uid="/General/colorLight" Content="Light" Name="light" GroupName="color" Checked="RadioButton_Checked"/>
|
||||||
|
|||||||
@@ -1,48 +1,42 @@
|
|||||||
using System;
|
using System.Globalization;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.ApplicationModel.Core;
|
using Windows.ApplicationModel.Core;
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.Storage;
|
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
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
|
|
||||||
|
|
||||||
namespace FoxTube.Pages.SettingsPages
|
namespace FoxTube.Pages.SettingsPages
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
/// Settings page with general preferences
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class General : Page
|
public sealed partial class General : Page
|
||||||
{
|
{
|
||||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
|
||||||
public General()
|
public General()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
language.SelectedIndex = (string)settings.Values["language"] == "en-US"? 0 : 1;
|
language.SelectedItem = language.Items.Find(i => ((ComboBoxItem)i).Tag.ToString() == SettingsStorage.Language);
|
||||||
quality.SelectedIndex = (int)settings.Values["quality"];
|
CultureInfo.GetCultures(CultureTypes.AllCultures).FindAll(i => !i.IsNeutralCulture).ForEach(i =>
|
||||||
|
{
|
||||||
|
region.Items.Add(new ComboBoxItem
|
||||||
|
{
|
||||||
|
Content = i.DisplayName,
|
||||||
|
Tag = i.IetfLanguageTag
|
||||||
|
});
|
||||||
|
if (i.IetfLanguageTag == SettingsStorage.Region)
|
||||||
|
region.SelectedItem = region.Items.Last();
|
||||||
|
});
|
||||||
|
safeSearch.SelectedIndex = SettingsStorage.SafeSearch;
|
||||||
|
|
||||||
newVideo.IsOn = (bool)settings.Values["newVideoNotification"];
|
quality.SelectedItem = quality.Items.ToList().Find(i => ((ComboBoxItem)i).Tag.ToString() == SettingsStorage.VideoQuality);
|
||||||
|
mobileWarning.IsOn = SettingsStorage.CheckConnection;
|
||||||
|
autoplay.IsOn = SettingsStorage.Autoplay;
|
||||||
|
|
||||||
mobileWarning.IsOn = (bool)settings.Values["moblieWarning"];
|
newVideo.IsOn = SettingsStorage.VideoNotifications;
|
||||||
autoplay.IsOn = (bool)settings.Values["videoAutoplay"];
|
devNews.IsOn = SettingsStorage.DevNotifications;
|
||||||
|
|
||||||
safeSearch.SelectedIndex = (int)settings.Values["safeSearch"];
|
switch(SettingsStorage.Theme)
|
||||||
|
|
||||||
switch((int)settings.Values["themeMode"])
|
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
light.IsChecked = true;
|
light.IsChecked = true;
|
||||||
@@ -54,79 +48,68 @@ namespace FoxTube.Pages.SettingsPages
|
|||||||
system.IsChecked = true;
|
system.IsChecked = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (CultureInfo culture in CultureInfo.GetCultures(CultureTypes.AllCultures))
|
|
||||||
{
|
|
||||||
region.Items.Add(culture.DisplayName);
|
|
||||||
if (culture.Name == (string)settings.Values["region"])
|
|
||||||
region.SelectedIndex = region.Items.Count - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void language_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void language_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if ((string)settings.Values["language"] != (language.SelectedItem as ComboBoxItem).Tag.ToString())
|
if (SettingsStorage.Language == (language.SelectedItem as ComboBoxItem).Tag.ToString())
|
||||||
{
|
return;
|
||||||
settings.Values["language"] = (language.SelectedItem as ComboBoxItem).Tag.ToString();
|
|
||||||
|
SettingsStorage.Language = (language.SelectedItem as ComboBoxItem).Tag.ToString();
|
||||||
restartNote.Visibility = Visibility.Visible;
|
restartNote.Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
restartNote.Visibility = Visibility.Collapsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
settings.Values["quality"] = (quality.SelectedItem as ComboBoxItem).Tag as string;
|
SettingsStorage.VideoQuality = (quality.SelectedItem as ComboBoxItem).Tag as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mobileWarning_Toggled(object sender, RoutedEventArgs e)
|
private void mobileWarning_Toggled(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
settings.Values["moblieWarning"] = mobileWarning.IsOn;
|
SettingsStorage.CheckConnection = mobileWarning.IsOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void autoplay_Toggled(object sender, RoutedEventArgs e)
|
private void autoplay_Toggled(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
SettingsStorage.Autoplay = autoplay.IsOn;
|
||||||
settings.Values["videoAutoplay"] = autoplay.IsOn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notification_IsEnabledChanged(object sender, RoutedEventArgs e)
|
private void notification_IsEnabledChanged(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
settings.Values["newVideoNotification"] = newVideo.IsOn;
|
SettingsStorage.VideoNotifications = newVideo.IsOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void region_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void region_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
settings.Values["region"] = CultureInfo.GetCultures(CultureTypes.AllCultures)[region.SelectedIndex].Name;
|
SettingsStorage.Region = CultureInfo.GetCultures(CultureTypes.AllCultures)[region.SelectedIndex].Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void safeSearch_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void safeSearch_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
settings.Values["safeSearch"] = safeSearch.SelectedIndex;
|
SettingsStorage.SafeSearch = safeSearch.SelectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RadioButton_Checked(object sender, RoutedEventArgs e)
|
private void RadioButton_Checked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender == light && (int)settings.Values["themeMode"] != 0)
|
if (sender == light && SettingsStorage.Theme != 0)
|
||||||
{
|
{
|
||||||
settings.Values["themeMode"] = 0;
|
SettingsStorage.Theme = 0;
|
||||||
Methods.MainPage.RequestedTheme = ElementTheme.Light;
|
Methods.MainPage.RequestedTheme = ElementTheme.Light;
|
||||||
}
|
}
|
||||||
if (sender == dark && (int)settings.Values["themeMode"] != 1)
|
else if (sender == dark && SettingsStorage.Theme != 1)
|
||||||
{
|
{
|
||||||
settings.Values["themeMode"] = 1;
|
SettingsStorage.Theme = 1;
|
||||||
Methods.MainPage.RequestedTheme = ElementTheme.Dark;
|
Methods.MainPage.RequestedTheme = ElementTheme.Dark;
|
||||||
}
|
}
|
||||||
if (sender == system && (int)settings.Values["themeMode"] != 2)
|
else if (sender == system && SettingsStorage.Theme != 2)
|
||||||
{
|
{
|
||||||
settings.Values["themeMode"] = 2;
|
SettingsStorage.Theme = 2;
|
||||||
Color uiTheme = (new Windows.UI.ViewManagement.UISettings()).GetColorValue(Windows.UI.ViewManagement.UIColorType.Background);
|
Color uiTheme = new Windows.UI.ViewManagement.UISettings().GetColorValue(Windows.UI.ViewManagement.UIColorType.Background);
|
||||||
if (uiTheme == Colors.Black)
|
if (uiTheme == Colors.Black)
|
||||||
Methods.MainPage.RequestedTheme = ElementTheme.Dark;
|
Methods.MainPage.RequestedTheme = ElementTheme.Dark;
|
||||||
else
|
else
|
||||||
Methods.MainPage.RequestedTheme = ElementTheme.Light;
|
Methods.MainPage.RequestedTheme = ElementTheme.Light;
|
||||||
}
|
}
|
||||||
|
|
||||||
Methods.MainPage.SetTitleBar();
|
Methods.MainPage.SetTitleBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,5 +117,10 @@ namespace FoxTube.Pages.SettingsPages
|
|||||||
{
|
{
|
||||||
CoreApplication.Exit();
|
CoreApplication.Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void devNews_Toggled(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
SettingsStorage.DevNotifications = devNews.IsOn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ namespace FoxTube.Pages.SettingsPages
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class Inbox : Page
|
public sealed partial class Inbox : Page
|
||||||
{
|
{
|
||||||
List<InboxItem> backup = new List<InboxItem>();
|
|
||||||
List<InboxItem> items = new List<InboxItem>();
|
List<InboxItem> items = new List<InboxItem>();
|
||||||
public Inbox()
|
public Inbox()
|
||||||
{
|
{
|
||||||
@@ -40,62 +39,51 @@ namespace FoxTube.Pages.SettingsPages
|
|||||||
{
|
{
|
||||||
XmlDocument doc = new XmlDocument();
|
XmlDocument doc = new XmlDocument();
|
||||||
|
|
||||||
doc.Load("http://foxgame.hol.es/foxtube-changelog.xml");
|
doc.Load("http://foxgame-studio.000webhostapp.com/foxtube-changelog.xml");
|
||||||
foreach (XmlElement e in doc["items"].ChildNodes)
|
foreach (XmlElement e in doc["items"].ChildNodes)
|
||||||
items.Add(new InboxItem(
|
items.Add(new InboxItem(
|
||||||
e.GetAttribute("version"),
|
e.GetAttribute("version"),
|
||||||
e["content"].InnerText,
|
e["content"].InnerText,
|
||||||
e.GetAttribute("time"),
|
e.GetAttribute("time")));
|
||||||
e.GetAttribute("id")
|
|
||||||
));
|
|
||||||
|
|
||||||
doc.Load("http://foxgame.hol.es/foxtube-messages.xml");
|
doc.Load("http://foxgame-studio.000webhostapp.com/foxtube-messages.xml");
|
||||||
foreach (XmlElement e in doc["posts"].ChildNodes)
|
foreach (XmlElement e in doc["posts"].ChildNodes)
|
||||||
items.Add(new InboxItem(
|
items.Add(new InboxItem(
|
||||||
e["header"].InnerText,
|
e["header"].InnerText,
|
||||||
e["content"].InnerText,
|
e["content"].InnerText,
|
||||||
DateTime.Parse(e.GetAttribute("time")),
|
DateTime.Parse(e["time"].InnerText),
|
||||||
e.GetAttribute("id")
|
e["id"].InnerText
|
||||||
));
|
));
|
||||||
|
|
||||||
items.OrderBy(item => item.TimeStamp);
|
items.OrderBy(item => item.TimeStamp);
|
||||||
|
|
||||||
foreach (InboxItem i in items)
|
|
||||||
backup.Add(i);
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
list.ItemsSource = items;
|
items.ForEach(i => list.Items.Add(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filter_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void filter_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
items.Clear();
|
list.Items.Clear();
|
||||||
list.ItemsSource = null;
|
|
||||||
|
|
||||||
switch (filter.SelectedIndex)
|
switch (filter.SelectedIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
foreach (InboxItem i in backup)
|
items.ForEach(i => list.Items.Add(i));
|
||||||
items.Add(i);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
foreach (InboxItem i in backup)
|
List<InboxItem> messages = items.FindAll(i => i.Type == InboxItemType.Default);
|
||||||
if(i.Type == InboxItemType.Default)
|
messages.ForEach(i => list.Items.Add(i));
|
||||||
items.Add(i);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
foreach (InboxItem i in backup)
|
List<InboxItem> notes = items.FindAll(i => i.Type == InboxItemType.PatchNote);
|
||||||
if (i.Type == InboxItemType.PatchNote)
|
notes.ForEach(i => list.Items.Add(i));
|
||||||
items.Add(i);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
list.ItemsSource = items;
|
|
||||||
}
|
}
|
||||||
catch(NullReferenceException) { }
|
catch(NullReferenceException) { }
|
||||||
}
|
}
|
||||||
@@ -141,11 +129,12 @@ namespace FoxTube.Pages.SettingsPages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Open(string id)
|
public void Open(string arg)
|
||||||
{
|
{
|
||||||
|
string id = arg.Split('&')[1];
|
||||||
InboxItem item = items.Find(x => x.Id == id);
|
InboxItem item = items.Find(x => x.Id == id);
|
||||||
if(item != null)
|
if(item != null)
|
||||||
list.SelectedIndex = items.IndexOf(item);
|
list.SelectedItem = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
<Page
|
|
||||||
x:Class="FoxTube.Pages.SettingsPages.Translate"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:FoxTube"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
mc:Ignorable="d">
|
|
||||||
|
|
||||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
|
||||||
<StackPanel Orientation="Vertical" Margin="10">
|
|
||||||
<TextBlock Text="Help us translate this app" FontSize="28"/>
|
|
||||||
<TextBlock TextWrapping="WrapWholeWords" Text="You can help us make this app even better by contributing to its development by translating this app. You can choose a brand new language to translate or edit mistakes in existing translations." Margin="0,0,0,10"/>
|
|
||||||
<StackPanel BorderThickness="2" BorderBrush="OrangeRed" MaxWidth="500" HorizontalAlignment="Left" Margin="0,0,0,10" Padding="0,0,0,3">
|
|
||||||
<TextBlock Foreground="OrangeRed" FontWeight="SemiBold" TextWrapping="WrapWholeWords" Text="Attention! This tool is used to help us to provide our app to more people from other countries. Please, don't send not done language packs. Thanks in advance ;)" Margin="5"/>
|
|
||||||
</StackPanel>
|
|
||||||
<TextBlock Text="It's quite simple:" Margin="0,0,0,10"/>
|
|
||||||
|
|
||||||
<ComboBox Header="1. Choose language you want to translate" PlaceholderText="Choose language..." Name="LangList" Margin="0,0,0,10" MinWidth="350" SelectionChanged="LangList_SelectionChanged"/>
|
|
||||||
|
|
||||||
<TextBlock Text="2. Import language pack file to your PC" Margin="0,0,0,10"/>
|
|
||||||
|
|
||||||
<Button Content="Export to PC (.xml)" Margin="0,0,0,10" Name="export" Click="export_Click" IsEnabled="False"/>
|
|
||||||
|
|
||||||
<TextBlock TextWrapping="WrapWholeWords" Text="3. Open file with any text editor you want (Notepad, Wordpad, Notepad++, VS Code, etc.)" Margin="0,0,0,10"/>
|
|
||||||
<TextBlock TextWrapping="WrapWholeWords" Text="4. Edit file by translating nececcary words and sentences" Margin="0,0,0,10"/>
|
|
||||||
<TextBlock Text="5. Upload final package to our servers" Margin="0,0,0,10"/>
|
|
||||||
|
|
||||||
<StackPanel Name="submitNotification" Visibility="Collapsed" BorderThickness="2" BorderBrush="OrangeRed" Width="350" HorizontalAlignment="Left" Margin="0,0,0,10" Padding="0,0,0,3">
|
|
||||||
<TextBlock Foreground="OrangeRed" FontWeight="SemiBold" Text="Attention! Once you submitted this language pack you won't be able to contribute to the language anymore. Think twice before continuing" TextWrapping="WrapWholeWords" Margin="5"/>
|
|
||||||
</StackPanel>
|
|
||||||
<Button Content="Choose file to upload" Margin="-1,0,0,10" HorizontalAlignment="Left" VerticalAlignment="Top" Name="upload" IsEnabled="False" Click="upload_Click"/>
|
|
||||||
<ProgressBar Width="250" HorizontalAlignment="Left" IsIndeterminate="True" Name="uploadingProgress" Visibility="Collapsed"/>
|
|
||||||
<TextBlock TextWrapping="WrapWholeWords" Text="It takes about 2-3 weeks to process new language pack and include it to the next update" Margin="0,0,0,10"/>
|
|
||||||
<TextBlock Text="Thank you for your help 😚"/>
|
|
||||||
<TextBlock Text="Best wishes,"/>
|
|
||||||
<TextBlock Text=" XFox"/>
|
|
||||||
<StackPanel Orientation="Horizontal" BorderBrush="Green" BorderThickness="5" Margin="0,10,30,0" Visibility="Collapsed" Name="greenResult">
|
|
||||||
<TextBlock FontFamily="Segoe MDL2 Assets" Text="" FontSize="40" Foreground="Green" Margin="5"/>
|
|
||||||
<StackPanel>
|
|
||||||
<TextBlock Text="Your language pack has been sent!" Foreground="Green" FontWeight="Bold" FontSize="20"/>
|
|
||||||
<TextBlock Text="Thank you! It's very imortant for us. Thank you for helping us making the app better" Foreground="Green"/>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Orientation="Horizontal" BorderBrush="OrangeRed" BorderThickness="5" Margin="0,10,30,0" Visibility="Collapsed" Name="denied">
|
|
||||||
<TextBlock FontFamily="Segoe MDL2 Assets" Text="" FontSize="40" Foreground="OrangeRed" Margin="5"/>
|
|
||||||
<StackPanel>
|
|
||||||
<TextBlock Text="You have already contributed to this language" Foreground="OrangeRed" FontWeight="Bold" FontSize="20"/>
|
|
||||||
<TextBlock Text="To prevent spaming our mailbox we allow our users to contribute to each language only 1 time" Foreground="OrangeRed"/>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</Page>
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
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 Windows.Storage.Pickers;
|
|
||||||
using Windows.Storage;
|
|
||||||
using System.Net.Mail;
|
|
||||||
using System.Net;
|
|
||||||
using Windows.UI.Popups;
|
|
||||||
|
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
|
||||||
|
|
||||||
namespace FoxTube.Pages.SettingsPages
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
|
||||||
/// </summary>
|
|
||||||
public sealed partial class Translate : Page
|
|
||||||
{
|
|
||||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
|
||||||
int selectedLanguage;
|
|
||||||
public Translate()
|
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
foreach (CultureInfo culture in CultureInfo.GetCultures(CultureTypes.AllCultures))
|
|
||||||
LangList.Items.Add(culture.DisplayName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void export_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
FileSavePicker picker = new FileSavePicker();
|
|
||||||
picker.CommitButtonText = "Export";
|
|
||||||
picker.DefaultFileExtension = ".xml";
|
|
||||||
picker.SuggestedFileName = "foxtube_langpack_" + CultureInfo.GetCultures(CultureTypes.AllCultures)[selectedLanguage];
|
|
||||||
picker.SuggestedStartLocation = PickerLocationId.Desktop;
|
|
||||||
picker.FileTypeChoices.Add("Language pack scheme", new List<string>() { ".xml" });
|
|
||||||
|
|
||||||
StorageFile file = await picker.PickSaveFileAsync();
|
|
||||||
if(file != null)
|
|
||||||
await FileIO.WriteTextAsync(file, GetPackage(selectedLanguage));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LangList_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
selectedLanguage = LangList.SelectedIndex;
|
|
||||||
|
|
||||||
greenResult.Visibility = Visibility.Collapsed;
|
|
||||||
denied.Visibility = Visibility.Collapsed;
|
|
||||||
|
|
||||||
if (settings.Values[CultureInfo.GetCultures(CultureTypes.AllCultures)[selectedLanguage] + "_sent"] == null)
|
|
||||||
{
|
|
||||||
export.IsEnabled = true;
|
|
||||||
upload.IsEnabled = true;
|
|
||||||
submitNotification.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
export.IsEnabled = false;
|
|
||||||
upload.IsEnabled = false;
|
|
||||||
denied.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void upload_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
FileOpenPicker picker = new FileOpenPicker()
|
|
||||||
{
|
|
||||||
CommitButtonText = "Upload",
|
|
||||||
SuggestedStartLocation = PickerLocationId.Desktop
|
|
||||||
};
|
|
||||||
picker.FileTypeFilter.Clear();
|
|
||||||
picker.FileTypeFilter.Add(".xml");
|
|
||||||
|
|
||||||
StorageFile file = await picker.PickSingleFileAsync();
|
|
||||||
if (file != null)
|
|
||||||
{
|
|
||||||
MailMessage msg = new MailMessage();
|
|
||||||
msg.To.Add("foxgameofficial+foxtube@gmail.com");
|
|
||||||
msg.From = new MailAddress("foxgameofficial+foxtube@gmail.com");
|
|
||||||
msg.Subject = "FoxTube language pack contribution";
|
|
||||||
msg.Body = string.Format("Language: {0}\nLanguage code: {1}", CultureInfo.GetCultures(CultureTypes.AllCultures)[selectedLanguage].EnglishName, CultureInfo.GetCultures(CultureTypes.AllCultures)[selectedLanguage]);
|
|
||||||
msg.Attachments.Add(new Attachment(file.Path));
|
|
||||||
|
|
||||||
SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
|
|
||||||
client.EnableSsl = true;
|
|
||||||
client.Credentials = SecretsVault.EmailCredential;
|
|
||||||
|
|
||||||
upload.IsEnabled = false;
|
|
||||||
export.IsEnabled = false;
|
|
||||||
uploadingProgress.Visibility = Visibility.Visible;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
client.Send(msg);
|
|
||||||
greenResult.Visibility = Visibility.Visible;
|
|
||||||
submitNotification.Visibility = Visibility.Collapsed;
|
|
||||||
settings.Values.Add(CultureInfo.GetCultures(CultureTypes.AllCultures)[selectedLanguage] + "_sent", true);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
uploadingProgress.Visibility = Visibility.Collapsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetPackage(int cultureIndex)
|
|
||||||
{
|
|
||||||
return "langpack";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
<controls:AdaptiveGridView ItemsSource="{x:Bind list}" DesiredWidth="250" Margin="5,0,0,0">
|
<controls:AdaptiveGridView ItemsSource="{x:Bind list}" DesiredWidth="250" Margin="5,0,0,0">
|
||||||
<controls:AdaptiveGridView.ItemTemplate>
|
<controls:AdaptiveGridView.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Button HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Padding="5">
|
<Button HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Padding="5" Tag="{Binding Path=Snippet.ResourceId.ChannelId}" Click="Button_Click">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="55"/>
|
<ColumnDefinition Width="55"/>
|
||||||
|
|||||||
@@ -28,5 +28,10 @@ namespace FoxTube.Pages
|
|||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Button_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Methods.MainPage.GoToChannel(((Button)sender).Tag.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
xmlns:local="using:FoxTube"
|
xmlns:local="using:FoxTube"
|
||||||
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:Microsoft.Toolkit.Uwp.UI.Controls"
|
xmlns:ui="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
||||||
xmlns:ui="using:Microsoft.Advertising.WinRT.UI"
|
xmlns:controls="using:FoxTube.Controls"
|
||||||
x:Name="root"
|
x:Name="root"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
@@ -15,7 +15,8 @@
|
|||||||
<RowDefinition Height="auto"/>
|
<RowDefinition Height="auto"/>
|
||||||
<RowDefinition/>
|
<RowDefinition/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<controls:AdaptiveGridView Name="list" OneRowModeEnabled="False" DesiredWidth="384" SelectionMode="None" Grid.Row="1"/>
|
<controls:Advert/>
|
||||||
|
<ui:AdaptiveGridView Name="list" OneRowModeEnabled="False" DesiredWidth="384" SelectionMode="None" Grid.Row="1"/>
|
||||||
<TextBlock Name="empty" Text="Ø" FontSize="200" Foreground="Gray" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.RowSpan="2"/>
|
<TextBlock Name="empty" Text="Ø" FontSize="200" Foreground="Gray" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.RowSpan="2"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
xmlns:pages="using:FoxTube.Pages"
|
xmlns:pages="using:FoxTube.Pages"
|
||||||
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
||||||
xmlns:ui="using:Microsoft.Advertising.WinRT.UI"
|
xmlns:ui="using:Microsoft.Advertising.WinRT.UI"
|
||||||
|
xmlns:controls1="using:FoxTube.Controls"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
|
||||||
@@ -36,6 +37,12 @@
|
|||||||
<local:VideoPlayer/>
|
<local:VideoPlayer/>
|
||||||
<PivotItem Header="Description" Name="descriptionPanel">
|
<PivotItem Header="Description" Name="descriptionPanel">
|
||||||
<StackPanel Margin="0,10">
|
<StackPanel Margin="0,10">
|
||||||
|
<Button Visibility="Collapsed">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<FontIcon Glyph="" Margin="0,0,10,0"/>
|
||||||
|
<TextBlock Text="Continue watching from HH:MM:SS"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
<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>
|
||||||
@@ -106,7 +113,47 @@
|
|||||||
<MenuFlyout x:Name="downloadSelector"/>
|
<MenuFlyout x:Name="downloadSelector"/>
|
||||||
</AppBarButton.Flyout>
|
</AppBarButton.Flyout>
|
||||||
</AppBarButton>
|
</AppBarButton>
|
||||||
<AppBarButton Label="Add to" Icon="Add" IsEnabled="False"/>
|
<AppBarButton Name="addTo" Label="Add to" Icon="Add">
|
||||||
|
<AppBarButton.Flyout>
|
||||||
|
<Flyout>
|
||||||
|
<ScrollViewer Margin="-12" MaxHeight="300">
|
||||||
|
<NavigationViewList Width="200" IsMultiSelectCheckBoxEnabled="True" SelectionMode="Multiple">
|
||||||
|
<NavigationViewItem Content="Watch later">
|
||||||
|
<NavigationViewItem.Icon>
|
||||||
|
<FontIcon Glyph=""/>
|
||||||
|
</NavigationViewItem.Icon>
|
||||||
|
</NavigationViewItem>
|
||||||
|
<NavigationViewItem Content="New playlist">
|
||||||
|
<NavigationViewItem.Icon>
|
||||||
|
<FontIcon Glyph=""/>
|
||||||
|
</NavigationViewItem.Icon>
|
||||||
|
</NavigationViewItem>
|
||||||
|
<NavigationViewItemHeader Content="Other playlists"/>
|
||||||
|
<NavigationViewItem Content="My playlist">
|
||||||
|
<NavigationViewItem.Icon>
|
||||||
|
<FontIcon Glyph=""/>
|
||||||
|
</NavigationViewItem.Icon>
|
||||||
|
</NavigationViewItem>
|
||||||
|
<NavigationViewItem Content="Cats">
|
||||||
|
<NavigationViewItem.Icon>
|
||||||
|
<FontIcon Glyph=""/>
|
||||||
|
</NavigationViewItem.Icon>
|
||||||
|
</NavigationViewItem>
|
||||||
|
<NavigationViewItem Content="Dogs">
|
||||||
|
<NavigationViewItem.Icon>
|
||||||
|
<FontIcon Glyph=""/>
|
||||||
|
</NavigationViewItem.Icon>
|
||||||
|
</NavigationViewItem>
|
||||||
|
<NavigationViewItem Content="Another playlist">
|
||||||
|
<NavigationViewItem.Icon>
|
||||||
|
<FontIcon Glyph=""/>
|
||||||
|
</NavigationViewItem.Icon>
|
||||||
|
</NavigationViewItem>
|
||||||
|
</NavigationViewList>
|
||||||
|
</ScrollViewer>
|
||||||
|
</Flyout>
|
||||||
|
</AppBarButton.Flyout>
|
||||||
|
</AppBarButton>
|
||||||
<AppBarButton Name="refresh" Click="refresh_Click" Icon="Refresh" Label="Refresh page"/>
|
<AppBarButton Name="refresh" Click="refresh_Click" Icon="Refresh" Label="Refresh page"/>
|
||||||
<AppBarButton Name="share" Click="share_Click" Icon="Share" Label="Share"/>
|
<AppBarButton Name="share" Click="share_Click" Icon="Share" Label="Share"/>
|
||||||
<AppBarButton Name="openBrowser" Click="openBrowser_Click" Icon="Globe" Label="Open in browser"/>
|
<AppBarButton Name="openBrowser" Click="openBrowser_Click" Icon="Globe" Label="Open in browser"/>
|
||||||
@@ -116,7 +163,10 @@
|
|||||||
<Pivot Grid.Row="1" Name="pivot" SelectedIndex="0" IsHeaderItemsCarouselEnabled="False">
|
<Pivot Grid.Row="1" Name="pivot" SelectedIndex="0" IsHeaderItemsCarouselEnabled="False">
|
||||||
<PivotItem Header="Suggestions">
|
<PivotItem Header="Suggestions">
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
|
<StackPanel>
|
||||||
|
<controls1:Advert/>
|
||||||
<StackPanel Name="relatedVideos"/>
|
<StackPanel Name="relatedVideos"/>
|
||||||
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</PivotItem>
|
</PivotItem>
|
||||||
<PivotItem Header="Comments" Name="commentsPlaceholder">
|
<PivotItem Header="Comments" Name="commentsPlaceholder">
|
||||||
|
|||||||
@@ -13,12 +13,10 @@ using Windows.UI.Xaml.Media.Imaging;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Windows.ApplicationModel.DataTransfer;
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
using Windows.ApplicationModel;
|
|
||||||
using Windows.Storage.Streams;
|
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
using FoxTube.Controls;
|
using FoxTube.Controls;
|
||||||
|
using YoutubeExplode.Models.MediaStreams;
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
using YoutubeExplode;
|
||||||
|
|
||||||
namespace FoxTube.Pages
|
namespace FoxTube.Pages
|
||||||
{
|
{
|
||||||
@@ -40,7 +38,7 @@ namespace FoxTube.Pages
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
/// Video page
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class VideoPage : Page
|
public sealed partial class VideoPage : Page
|
||||||
{
|
{
|
||||||
@@ -61,7 +59,7 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
public VideoPage()
|
public VideoPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
loading = grid.Children[3] as LoadingPage;
|
loading = grid.Children[3] as LoadingPage;
|
||||||
loading.RefreshPage += refresh_Click;
|
loading.RefreshPage += refresh_Click;
|
||||||
player = mainContent.Children[0] as VideoPlayer;
|
player = mainContent.Children[0] as VideoPlayer;
|
||||||
@@ -173,7 +171,7 @@ namespace FoxTube.Pages
|
|||||||
license.Text = "Standard YouTube License";
|
license.Text = "Standard YouTube License";
|
||||||
else license.Text = "Creative Commons Attribution license (reuse allowed)";
|
else license.Text = "Creative Commons Attribution license (reuse allowed)";
|
||||||
|
|
||||||
VideoCategoriesResource.ListRequest categoryRequest = SecretsVault.NoAuthService.VideoCategories.List("snippet");
|
VideoCategoriesResource.ListRequest categoryRequest = SecretsVault.Service.VideoCategories.List("snippet");
|
||||||
categoryRequest.Id = item.Snippet.CategoryId;
|
categoryRequest.Id = item.Snippet.CategoryId;
|
||||||
category.Text = (await categoryRequest.ExecuteAsync()).Items[0].Snippet.Title;
|
category.Text = (await categoryRequest.ExecuteAsync()).Items[0].Snippet.Title;
|
||||||
|
|
||||||
@@ -207,6 +205,12 @@ namespace FoxTube.Pages
|
|||||||
}
|
}
|
||||||
subscribe.Visibility = Visibility.Visible;
|
subscribe.Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
download.Visibility = Visibility.Collapsed;
|
||||||
|
addTo.Visibility = Visibility.Collapsed;
|
||||||
|
subscribe.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
ChannelsResource.ListRequest channelRequest = SecretsVault.Service.Channels.List("snippet, statistics");
|
ChannelsResource.ListRequest channelRequest = SecretsVault.Service.Channels.List("snippet, statistics");
|
||||||
channelRequest.Id = item.Snippet.ChannelId;
|
channelRequest.Id = item.Snippet.ChannelId;
|
||||||
@@ -235,38 +239,37 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
async void LoadDownloads()
|
async void LoadDownloads()
|
||||||
{
|
{
|
||||||
/*List<YouTubeUri> uris = (await YouTube.GetUrisAsync(item.Id)).ToList();
|
try
|
||||||
if (uris.Count > 0)
|
|
||||||
foreach (YouTubeUri u in uris)
|
|
||||||
{
|
{
|
||||||
if (u.HasAudio && u.HasVideo)
|
MediaStreamInfoSet infoSet = await new YoutubeClient().GetVideoMediaStreamInfosAsync(videoId);
|
||||||
|
foreach (MuxedStreamInfo i in infoSet.Muxed)
|
||||||
{
|
{
|
||||||
MenuFlyoutItem menuItem = new MenuFlyoutItem()
|
MenuFlyoutItem menuItem = new MenuFlyoutItem()
|
||||||
{
|
{
|
||||||
Text = Methods.QualityToString(u.VideoQuality),
|
Text = i.VideoQualityLabel,
|
||||||
Tag = u.Uri.AbsoluteUri
|
Tag = new object[] { i, i.VideoQualityLabel }
|
||||||
};
|
};
|
||||||
menuItem.Click += downloadItemSelected;
|
menuItem.Click += downloadItemSelected;
|
||||||
downloadSelector.Items.Add(menuItem);
|
downloadSelector.Items.Add(menuItem);
|
||||||
}
|
}
|
||||||
else if (u.HasAudio)
|
|
||||||
|
MenuFlyoutItem audioItem = new MenuFlyoutItem()
|
||||||
{
|
{
|
||||||
MenuFlyoutItem menuItem = new MenuFlyoutItem()
|
Text = "Audio track",
|
||||||
{
|
Tag = new object[] { infoSet.Audio[0], "Audio only" }
|
||||||
Text = Methods.QualityToString(u.AudioQuality),
|
|
||||||
Tag = u.Uri.AbsoluteUri
|
|
||||||
};
|
};
|
||||||
menuItem.Click += downloadItemSelected;
|
audioItem.Click += downloadItemSelected;
|
||||||
downloadSelector.Items.Add(menuItem);
|
downloadSelector.Items.Add(audioItem);
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
loading.Error(e.GetType().ToString(), e.Message);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
download.Visibility = Visibility.Collapsed;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadItemSelected(object sender, RoutedEventArgs e)
|
private void downloadItemSelected(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Methods.MainPage.Agent.Add((sender as MenuFlyoutItem).Tag.ToString());
|
DownloadAgent.Add(((sender as MenuFlyoutItem).Tag as object[])[0] as MediaStreamInfo, item, ((sender as MenuFlyoutItem).Tag as object[])[1] as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
async void LoadRelatedVideos()
|
async void LoadRelatedVideos()
|
||||||
@@ -325,8 +328,7 @@ namespace FoxTube.Pages
|
|||||||
|
|
||||||
public void refresh_Click(object sender, RoutedEventArgs e)
|
public void refresh_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
player = new VideoPlayer();
|
Methods.MainPage.GoToVideo(videoId, playlistId);
|
||||||
Initialize(new string[2] { videoId, playlistId });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grid_SizeChanged(object sender, SizeChangedEventArgs e)
|
private void grid_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||||
@@ -363,43 +365,15 @@ namespace FoxTube.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Share(DataTransferManager sender, DataRequestedEventArgs args)
|
private void Share(DataTransferManager sender, DataRequestedEventArgs args)
|
||||||
{
|
{
|
||||||
player.Pause();
|
player.Pause();
|
||||||
DataRequest request = args.Request;
|
|
||||||
request.Data.Properties.Title = item.Snippet.Title;
|
|
||||||
request.Data.Properties.Description = "Sharing a video";
|
|
||||||
|
|
||||||
// Handle errors
|
Methods.Share(args,
|
||||||
//request.FailWithDisplayText("Something unexpected could happen.");
|
item.Snippet.Thumbnails.Medium.Url,
|
||||||
|
item.Snippet.Title,
|
||||||
// Plain text
|
$"https://www.youtube.com/watch?v={videoId}",
|
||||||
request.Data.SetText(item.Snippet.Title + "\n" + "#YouTube #FoxTube #SharedWithFoxTube");
|
"video");
|
||||||
|
|
||||||
// Uniform Resource Identifiers (URIs)
|
|
||||||
request.Data.SetWebLink(new Uri(string.Format("https://www.youtube.com/watch?v={0}", videoId)));
|
|
||||||
|
|
||||||
// HTML
|
|
||||||
//request.Data.SetHtmlFormat("<b>Bold Text</b>");
|
|
||||||
|
|
||||||
// Because we are making async calls in the DataRequested event handler,
|
|
||||||
// we need to get the deferral first.
|
|
||||||
DataRequestDeferral deferral = request.GetDeferral();
|
|
||||||
|
|
||||||
// Make sure we always call Complete on the deferral.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StorageFile thumbnailFile = await Package.Current.InstalledLocation.GetFileAsync(item.Snippet.Thumbnails.Medium.Url);
|
|
||||||
request.Data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromFile(thumbnailFile);
|
|
||||||
StorageFile imageFile = await Package.Current.InstalledLocation.GetFileAsync(item.Snippet.Thumbnails.Medium.Url);
|
|
||||||
|
|
||||||
// Bitmaps
|
|
||||||
request.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(imageFile));
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
deferral.Complete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void share_Click(object sender, RoutedEventArgs e)
|
private void share_Click(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -117,13 +117,13 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="adsFree.Text" xml:space="preserve">
|
<data name="adsFree.Content" xml:space="preserve">
|
||||||
<value>Remove ads</value>
|
<value>Remove ads</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="downloads.Content" xml:space="preserve">
|
<data name="downloads.Content" xml:space="preserve">
|
||||||
<value>Downloads</value>
|
<value>Downloads</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="feedback.Text" xml:space="preserve">
|
<data name="feedback.Content" xml:space="preserve">
|
||||||
<value>Give a feedback</value>
|
<value>Give a feedback</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="history.Content" xml:space="preserve">
|
<data name="history.Content" xml:space="preserve">
|
||||||
|
|||||||
@@ -117,13 +117,13 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="adsFree.Text" xml:space="preserve">
|
<data name="adsFree.Content" xml:space="preserve">
|
||||||
<value>Убрать рекламу</value>
|
<value>Убрать рекламу</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="downloads.Content" xml:space="preserve">
|
<data name="downloads.Content" xml:space="preserve">
|
||||||
<value>Загрузки</value>
|
<value>Загрузки</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="feedback.Text" xml:space="preserve">
|
<data name="feedback.Content" xml:space="preserve">
|
||||||
<value>Оставить отзыв</value>
|
<value>Оставить отзыв</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="history.Content" xml:space="preserve">
|
<data name="history.Content" xml:space="preserve">
|
||||||
|
|||||||
|
After Width: | Height: | Size: 19 KiB |