diff --git a/FoxTube/Classes/DownloadAgent.cs b/FoxTube/Classes/DownloadAgent.cs index fdf36c3..af7a334 100644 --- a/FoxTube/Classes/DownloadAgent.cs +++ b/FoxTube/Classes/DownloadAgent.cs @@ -1,73 +1,72 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml; using System.IO; -using MyToolkit.Multimedia; using Windows.Storage; +using FoxTube.Classes; +using Newtonsoft.Json; +using Windows.UI.Popups; namespace FoxTube.Controls { public class DownloadAgent { - public List Items = new List(); - public event ObjectEventHandler ListChanged; - - private ApplicationDataContainer settings = ApplicationData.Current.LocalSettings; - XmlDocument doc = new XmlDocument(); + public List items = new List(); + StorageFolder roaming = ApplicationData.Current.RoamingFolder; + public DownloadAgent() { - if (settings.Values["downloadHistory"] != null) - doc.LoadXml(settings.Values["downloadHistory"] as string); - else + Initialize(); + Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += (s, a) => QuitPrompt(); + } + + public async void Initialize() + { + try { - doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null)); - doc.AppendChild(doc.CreateElement("downloads")); - settings.Values.Add("downloadHistory", doc.InnerXml); + List containers = JsonConvert.DeserializeObject>(await FileIO.ReadTextAsync(await roaming.GetFileAsync("data.json"))); + + foreach (DownloadItemContainer i in containers) + try { items.Add(new DownloadItem(i)); } + catch (FileNotFoundException) { } } - - foreach(XmlElement e in doc["downloads"].ChildNodes) - try - { - Items.Add(new DownloadItem( - e["details"]["id"].InnerText, - e["title"].InnerText, - e["snippet"]["author"].InnerText, - e["snippet"]["image"].InnerText, - e["snippet"]["duration"].InnerText, - e["snippet"]["quality"].InnerText, - e["details"]["path"].InnerText)); - } - catch { } + catch { } } - public void Add(string id, YouTubeQuality quality) + public void Add(string url) { - DownloadItem item = new DownloadItem(id, quality); - item.DownloadCanceled += Item_DownloadCanceled; - item.DownloadComplete += Item_DownloadComplete; - - Items.Add(item); - ListChanged.Invoke(item, "add"); - } - - public void Add(string id, string url) - { - - } - - private void Item_DownloadComplete(object sender, params object[] e) - { - doc["downloads"].InnerXml += e[0]; - settings.Values["downloadHistory"] = doc.InnerXml; + items.Add(new DownloadItem(url)); } private void Item_DownloadCanceled(object sender, params object[] e) { - Items.Remove(sender as DownloadItem); - ListChanged.Invoke(sender, "remove"); + items.Remove(sender as DownloadItem); + } + + public async void QuitPrompt() + { + if(items.Find(x => x.InProgress) != null) + { + MessageDialog dialog = new MessageDialog("You have some unfinished downloads. Quitting now will erase all downloaded data. Are you sure to continue?", "Some downloads are still pending"); + + dialog.Commands.Add(new UICommand("Yes", async (command) => + { + foreach (DownloadItem i in items.FindAll(x => x.InProgress)) + i.Cancel(); + items.RemoveAll(x => x.InProgress); + + List containers = new List(); + foreach (DownloadItem i in items) + containers.Add(i.Container); + + await FileIO.WriteTextAsync( + await roaming.CreateFileAsync("data.json", CreationCollisionOption.ReplaceExisting), + JsonConvert.SerializeObject(containers)); + })); + dialog.Commands.Add(new UICommand("No")); + + dialog.DefaultCommandIndex = 1; + await dialog.ShowAsync(); + } } } } diff --git a/FoxTube/Classes/DownloadItemContainer.cs b/FoxTube/Classes/DownloadItemContainer.cs new file mode 100644 index 0000000..f7e6fe2 --- /dev/null +++ b/FoxTube/Classes/DownloadItemContainer.cs @@ -0,0 +1,16 @@ +using System; +using YoutubeExplode.Models.MediaStreams; + +namespace FoxTube.Classes +{ + public class DownloadItemContainer + { + public string Title { get; set; } + public string Channel { get; set; } + public string Id { get; set; } + public Uri Path { get; set; } + public Uri Thumbnail { get; set; } + public VideoQuality Quality { get; set; } + public TimeSpan Duration { get; set; } + } +} diff --git a/FoxTube/Classes/Methods.cs b/FoxTube/Classes/Methods.cs index 1ca0a75..f7fa11e 100644 --- a/FoxTube/Classes/Methods.cs +++ b/FoxTube/Classes/Methods.cs @@ -1,11 +1,7 @@ using Google.Apis.YouTube.v3; -using Google.Apis.YouTube.v3.Data; -using MyToolkit.Multimedia; using System; -using System.Collections.Generic; using System.Diagnostics; using System.Text.RegularExpressions; -using System.Threading.Tasks; using System.Web; using Windows.ApplicationModel.Core; using Windows.System; @@ -30,6 +26,11 @@ namespace FoxTube CoreApplication.Exit(); } + public static Uri ToUri(this string url) + { + return new Uri(url); + } + public static string GetAgo(DateTime dateTime) { TimeSpan span = DateTime.Now - dateTime; @@ -105,7 +106,7 @@ namespace FoxTube } } - public static string QualityToString(YouTubeQuality quality) + /*public static string QualityToString(YouTubeQuality quality) { switch(quality) { @@ -138,7 +139,7 @@ namespace FoxTube default: return "Unknown"; } - } + }*/ public async static void ProcessLink(string url) { diff --git a/FoxTube/Controls/DownloadItem.xaml b/FoxTube/Controls/DownloadItem.xaml index 9e5b4b4..212cb5c 100644 --- a/FoxTube/Controls/DownloadItem.xaml +++ b/FoxTube/Controls/DownloadItem.xaml @@ -28,7 +28,7 @@ - + diff --git a/FoxTube/Controls/VideoPlayer.xaml.cs b/FoxTube/Controls/VideoPlayer.xaml.cs index c8930eb..e8eeefa 100644 --- a/FoxTube/Controls/VideoPlayer.xaml.cs +++ b/FoxTube/Controls/VideoPlayer.xaml.cs @@ -1,26 +1,17 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; using System.Timers; using Windows.Foundation; -using Windows.Foundation.Collections; using Windows.Storage; using Windows.UI.Core; 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 Microsoft.Toolkit.Uwp.UI.Animations; - using Google.Apis.YouTube.v3.Data; -using Google.Apis.YouTube.v3; using Windows.UI.Xaml.Media.Imaging; -using Windows.Networking.Connectivity; using System.Diagnostics; using Windows.Media; using Windows.Storage.Streams; @@ -28,17 +19,13 @@ using Windows.UI.ViewManagement; using System.Xml; using Windows.ApplicationModel.Core; using Windows.UI; -using Windows.Graphics.Display; using Windows.Media.Casting; -using MyToolkit.Multimedia; using YoutubeExplode.Models.MediaStreams; using YoutubeExplode; using YoutubeExplode.Models.ClosedCaptions; using System.Globalization; using FoxTube.Controls; using Windows.System; -using Windows.Devices.Sensors; -using Windows.System.Profile; // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 @@ -87,7 +74,7 @@ namespace FoxTube LiveCaptions captions; IReadOnlyList ccInfo; - List streamInfo; + MediaStreamInfoSet streamInfo; ApplicationDataContainer settings = ApplicationData.Current.LocalSettings; Timer t = new Timer() @@ -132,35 +119,25 @@ namespace FoxTube #region Retrieving info for CC and Media streams //Loading streams - streamInfo = (await YouTube.GetUrisAsync(item.Id)).ToList(); - foreach (YouTubeQuality q in Enum.GetValues(typeof(YouTubeQuality))) - if (streamInfo.FindAll(x => x.VideoQuality == q).Count > 1) - streamInfo.RemoveAll(x => x.VideoQuality == q && !x.HasAudio); + streamInfo = await new YoutubeClient().GetVideoMediaStreamInfosAsync(videoId); + streamInfo.Audio.ToList().ForEach(x => Debug.WriteLine($"{x.AudioEncoding} {x.Bitrate}")); - streamInfo.ForEach(x => Debug.WriteLine($"{x.HasAudio}; {x.HasVideo}; {x.VideoQuality}; {x.AudioQuality}")); - foreach (YouTubeUri i in streamInfo) - { - if (i.VideoQuality == YouTubeQuality.Quality2160P) - (quality.Items[0] as ComboBoxItem).Visibility = Visibility.Visible; - if (i.VideoQuality == YouTubeQuality.Quality1080P) - (quality.Items[1] as ComboBoxItem).Visibility = Visibility.Visible; - if (i.VideoQuality == YouTubeQuality.Quality720P) - (quality.Items[2] as ComboBoxItem).Visibility = Visibility.Visible; - if (i.VideoQuality == YouTubeQuality.Quality480P) - (quality.Items[3] as ComboBoxItem).Visibility = Visibility.Visible; - if (i.VideoQuality == YouTubeQuality.Quality360P) - (quality.Items[4] as ComboBoxItem).Visibility = Visibility.Visible; - if (i.VideoQuality == YouTubeQuality.Quality240P) - (quality.Items[5] as ComboBoxItem).Visibility = Visibility.Visible; - if (i.VideoQuality == YouTubeQuality.Quality144P) - (quality.Items[6] as ComboBoxItem).Visibility = Visibility.Visible; - } + List q = streamInfo.GetAllVideoQualities().ToList(); + q.Sort(); + q.Reverse(); + foreach (VideoQuality i in q) + quality.Items.Add(new ComboBoxItem() { Content = i.GetVideoQualityLabel() }); - int k = (int)settings.Values["quality"]; - if ((quality.Items[k] as ComboBoxItem).Visibility == Visibility.Visible) - quality.SelectedIndex = k; + string s; + if ((string)settings.Values["quality"] == "remember") + s = (string)settings.Values["rememberedQuality"]; else - quality.SelectedItem = quality.Items.First(x => (x as ComboBoxItem).Visibility == Visibility.Visible); + s = (string)settings.Values["quality"]; + + if (quality.Items.ToList().Find(x => (x as ComboBoxItem).Content as string == s) != null) + quality.SelectedItem = quality.Items.First(x => (x as ComboBoxItem).Content as string == s); + else + quality.SelectedItem = quality.Items.First(); //Loading captions ccInfo = await new YoutubeClient().GetVideoClosedCaptionTrackInfosAsync(item.Id); @@ -369,11 +346,28 @@ namespace FoxTube audioReady = false; videoReady = false; - switch((quality.SelectedItem as ComboBoxItem).Content) + settings.Values["rememberedQuality"] = (quality.SelectedItem as ComboBoxItem).Content as string; + + if(streamInfo.Muxed.ToList().Find(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string) != null) + { + isMuxed = true; + videoSource.Source = streamInfo.Muxed.First(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri(); + } + else + { + isMuxed = false; + videoSource.Source = streamInfo.Video.First(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri(); + audioSource.Source = streamInfo.Audio.First().Url.ToUri(); + } + + /*switch((quality.SelectedItem as ComboBoxItem).Content) { case "2160p": - if(streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality2160P).HasAudio) + if(streamInfo.Muxed.First(x => x.VideoQuality.)) + { isMuxed = true; + + } else { isMuxed = false; @@ -456,7 +450,7 @@ namespace FoxTube } videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality144P).Uri; break; - } + }*/ needUpdateTimecode = true; videoSource.Play(); diff --git a/FoxTube/FoxTube.csproj b/FoxTube/FoxTube.csproj index 3110a13..52e3fc3 100644 --- a/FoxTube/FoxTube.csproj +++ b/FoxTube/FoxTube.csproj @@ -97,6 +97,7 @@ App.xaml + @@ -398,7 +399,7 @@ - 1.0.1 + 1.1.0 1.30.0-beta02 @@ -419,25 +420,25 @@ 10.1805.7001 - 6.1.5 + 6.1.9 - 3.0.0 + 4.0.0 - 3.0.0 - - - 2.5.16 - - - 2.5.16 + 4.0.0 - 4.3.1 + 4.3.2 + + + 1.2.0 - 4.3.1 + 4.4.0 + + + 0.10.11 diff --git a/FoxTube/Pages/Downloads.xaml b/FoxTube/Pages/Downloads.xaml index 9a44d87..d6ca56f 100644 --- a/FoxTube/Pages/Downloads.xaml +++ b/FoxTube/Pages/Downloads.xaml @@ -5,6 +5,7 @@ xmlns:local="using:FoxTube.Pages" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:controls="using:FoxTube.Controls" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> @@ -27,7 +28,9 @@ - + + + diff --git a/FoxTube/Pages/Downloads.xaml.cs b/FoxTube/Pages/Downloads.xaml.cs index 3282afb..f48c4e6 100644 --- a/FoxTube/Pages/Downloads.xaml.cs +++ b/FoxTube/Pages/Downloads.xaml.cs @@ -11,11 +11,6 @@ using Windows.Storage.Pickers; using Windows.System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; -using Windows.UI.Xaml.Navigation; // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 #pragma warning disable CS0252 // Possible unintended reference comparison; left hand side needs cast @@ -28,33 +23,20 @@ namespace FoxTube.Pages public sealed partial class Downloads : Page { ApplicationDataContainer settings = ApplicationData.Current.LocalSettings; - DownloadAgent agent = Methods.MainPage.Agent; public Downloads() { this.InitializeComponent(); path.Text = settings.Values["defaultDownload"] as string; - - agent.ListChanged += UpdateList; - - foreach (DownloadItem item in agent.Items) - stack.Children.Add(item); - } - - private void UpdateList(object sender, params object[] e) - { - if (e[0] == "remove") - stack.Children.Remove(sender as DownloadItem); - else if (e[0] == "add") - stack.Children.Add(sender as DownloadItem); } private async void changePath_Click(object sender, RoutedEventArgs e) { FolderPicker picker = new FolderPicker() { - SuggestedStartLocation = PickerLocationId.Desktop, + SuggestedStartLocation = PickerLocationId.Downloads, ViewMode = PickerViewMode.Thumbnail }; + picker.FileTypeFilter.Add(".shit"); //Because overwise it trhows an exception StorageFolder p = await picker.PickSingleFolderAsync(); if (p != null) @@ -64,7 +46,7 @@ namespace FoxTube.Pages private async void openFolder_Click(object sender, RoutedEventArgs e) { - await Launcher.LaunchUriAsync(new Uri(settings.Values["defaultDownload"] as string)); + await Launcher.LaunchFolderAsync( await StorageFolder.GetFolderFromPathAsync(settings.Values["defaultDownload"] as string)); } } } diff --git a/FoxTube/Pages/MainPage.xaml.cs b/FoxTube/Pages/MainPage.xaml.cs index 628e56e..1d5961b 100644 --- a/FoxTube/Pages/MainPage.xaml.cs +++ b/FoxTube/Pages/MainPage.xaml.cs @@ -24,6 +24,7 @@ using System.Net; using Windows.UI.Popups; using Windows.Networking.Connectivity; using Windows.UI.Core; +using Syroot.Windows.IO; // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 @@ -48,7 +49,9 @@ namespace FoxTube this.InitializeComponent(); if (settings.Values["quality"] == null) - settings.Values.Add("quality", 1); + settings.Values.Add("quality", "remember"); + if (settings.Values["rememberedQuality"] == null) + settings.Values.Add("rememberedQuality", "1080p"); if (settings.Values["newVideoNotification"] == null) settings.Values.Add("newVideoNotification", true); @@ -70,7 +73,7 @@ namespace FoxTube settings.Values.Add("safeSearch", 0); if (settings.Values["defaultDownload"] == null) - settings.Values.Add("defaultDownload", Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\DownloadedVideos"); + settings.Values.Add("defaultDownload", Syroot.Windows.IO.KnownFolders.Downloads.Path + "\\DownloadedVideos"); if (settings.Values["notificationsHistory"] == null) { diff --git a/FoxTube/Pages/SettingsPages/General.xaml b/FoxTube/Pages/SettingsPages/General.xaml index 431c28b..cbdfac1 100644 --- a/FoxTube/Pages/SettingsPages/General.xaml +++ b/FoxTube/Pages/SettingsPages/General.xaml @@ -28,14 +28,14 @@ - - - - - - - - + + + + + + + + diff --git a/FoxTube/Pages/SettingsPages/General.xaml.cs b/FoxTube/Pages/SettingsPages/General.xaml.cs index de62173..fb0f11f 100644 --- a/FoxTube/Pages/SettingsPages/General.xaml.cs +++ b/FoxTube/Pages/SettingsPages/General.xaml.cs @@ -76,7 +76,7 @@ namespace FoxTube.Pages.SettingsPages private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e) { - settings.Values["quality"] = quality.SelectedIndex; + settings.Values["quality"] = (quality.SelectedItem as ComboBoxItem).Tag as string; } private void mobileWarning_Toggled(object sender, RoutedEventArgs e) diff --git a/FoxTube/Pages/VideoPage.xaml.cs b/FoxTube/Pages/VideoPage.xaml.cs index e2e73ce..8a632f2 100644 --- a/FoxTube/Pages/VideoPage.xaml.cs +++ b/FoxTube/Pages/VideoPage.xaml.cs @@ -1,36 +1,21 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; using Windows.Foundation; -using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; using Windows.System; - using Google.Apis.YouTube.v3.Data; using Google.Apis.YouTube.v3; using Windows.UI.Xaml.Media.Imaging; using System.Diagnostics; -using System.Timers; -using Windows.UI.Core; -using System.Threading; using Windows.ApplicationModel.DataTransfer; using Windows.Storage; using Windows.ApplicationModel; using Windows.Storage.Streams; -using Windows.UI.Popups; -using Windows.UI.Text; using Windows.UI; -using FoxTube.Pages; - -using MyToolkit.Multimedia; using FoxTube.Controls; // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 @@ -250,7 +235,7 @@ namespace FoxTube.Pages async void LoadDownloads() { - List uris = (await YouTube.GetUrisAsync(item.Id)).ToList(); + /*List uris = (await YouTube.GetUrisAsync(item.Id)).ToList(); if (uris.Count > 0) foreach (YouTubeUri u in uris) { @@ -276,12 +261,12 @@ namespace FoxTube.Pages } } else - download.Visibility = Visibility.Collapsed; + download.Visibility = Visibility.Collapsed;*/ } private void downloadItemSelected(object sender, RoutedEventArgs e) { - Methods.MainPage.Agent.Add(videoId, (sender as MenuFlyoutItem).Tag.ToString()); + Methods.MainPage.Agent.Add((sender as MenuFlyoutItem).Tag.ToString()); } async void LoadRelatedVideos()