diff --git a/VDownload/Assets/Icons/AddVideo/NotFound.png b/VDownload/Assets/Icons/Add/NotFound.png similarity index 100% rename from VDownload/Assets/Icons/AddVideo/NotFound.png rename to VDownload/Assets/Icons/Add/NotFound.png diff --git a/VDownload/Assets/Icons/AddVideo/Start.png b/VDownload/Assets/Icons/Add/Start.png similarity index 100% rename from VDownload/Assets/Icons/AddVideo/Start.png rename to VDownload/Assets/Icons/Add/Start.png diff --git a/VDownload/Objects/Enums/PlaylistSource.cs b/VDownload/Objects/Enums/PlaylistSource.cs new file mode 100644 index 0000000..0a5517c --- /dev/null +++ b/VDownload/Objects/Enums/PlaylistSource.cs @@ -0,0 +1,9 @@ +namespace VDownload.Objects.Enums +{ + public enum PlaylistSource + { + TwitchChannel, + LocalFile, + Null, + } +} \ No newline at end of file diff --git a/VDownload/Services/Source.cs b/VDownload/Services/Source.cs index 0678f46..652430e 100644 --- a/VDownload/Services/Source.cs +++ b/VDownload/Services/Source.cs @@ -4,11 +4,15 @@ using VDownload.Objects.Enums; // System using System; using System.Linq; +using System.IO; +using Windows.Storage; +using System.Diagnostics; namespace VDownload.Services { internal class Source { + // VIDEO SOURCE public static (VideoSource, string) GetVideoSourceData(Uri url) { // Twitch VOD @@ -39,5 +43,27 @@ namespace VDownload.Services return (VideoSource.Null, ""); } } + + // PLAYLIST SOURCE + public static (PlaylistSource, string) GetPlaylistSourceData(Uri url) + { + // Local file + if (url.IsFile) + { + return (PlaylistSource.LocalFile, url.AbsolutePath); + } + + // Twitch Channel + else if (url.Host == "www.twitch.tv" && url.Segments.Length == 2) + { + return (PlaylistSource.TwitchChannel, url.Segments[url.Segments.Length - 1]); + } + + // Unknown + else + { + return (PlaylistSource.Null, ""); + } + } } } diff --git a/VDownload/Sources/PObject.cs b/VDownload/Sources/PObject.cs new file mode 100644 index 0000000..e6329d7 --- /dev/null +++ b/VDownload/Sources/PObject.cs @@ -0,0 +1,785 @@ +using Microsoft.Toolkit.Uwp.UI; +using Microsoft.UI.Xaml.Controls; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VDownload.Objects.Enums; +using VDownload.Services; +using Windows.ApplicationModel.Resources; +using Windows.Storage; +using Windows.Storage.AccessCache; +using Windows.Storage.Pickers; +using Windows.UI; +using Windows.UI.Text; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Media.Imaging; + +namespace VDownload.Sources +{ + public class PObject + { + #region INIT + + // PLAYLIST DATA + public PlaylistSource SourceType { get; private set; } + public string ID { get; private set; } + public Dictionary VObjects { get; private set; } + public StackPanel PlaylistPanel { get; set; } + private List DeletedVObjects = new List(); + private Grid DeletedVideosPanel { get; set; } + + // CONSTRUCTOR + public PObject(Uri url) + { + VObjects = new Dictionary(); + (SourceType, ID) = Source.GetPlaylistSourceData(url); + if (SourceType == PlaylistSource.Null) + { + throw new ArgumentException(); + } + } + + #endregion + + + + #region MAIN + + // GET VIDEOS + public async Task GetVideos() + { + switch (SourceType) + { + case PlaylistSource.TwitchChannel: + // TODO + break; + case PlaylistSource.Null: + throw new ArgumentException(); + } + } + + // ADD VIDEOS TO LIST + public async Task InitPlaylistPanel(StackPanel parent) + { + // Attach to panel object to PObject + PlaylistPanel = parent; + + // Add videos to panel + foreach (VObject video in VObjects.Keys.ToArray()) + { + await HandleVideoOnList(video); + } + + } + + + #endregion + + + + #region VIDEO PANEL + + // VIDEO PANEL HANDLER + private async Task HandleVideoOnList(VObject Video) + { + // Video panel + Expander videoPanel = new Expander + { + Margin = new Thickness(0, 5, 0, 5), + HorizontalAlignment = HorizontalAlignment.Stretch, + HorizontalContentAlignment = HorizontalAlignment.Stretch, + }; + + + + // Header + #region HEADER + + Grid header = new Grid + { + Margin = new Thickness(0, 15, 0, 15), + }; + header.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + header.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(15) }); + header.ColumnDefinitions.Add(new ColumnDefinition()); + header.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(15) }); + header.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + videoPanel.Header = header; + + // Thumbnail + Image thumbnailImage = new Image + { + Source = new BitmapImage { UriSource = Video.Thumbnail }, + Width = 120, + }; + Grid.SetColumn(thumbnailImage, 0); + header.Children.Add(thumbnailImage); + + + + // Metadata grid + Grid metadataGrid = new Grid(); + metadataGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + metadataGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(10) }); + metadataGrid.RowDefinitions.Add(new RowDefinition()); + Grid.SetColumn(metadataGrid, 2); + header.Children.Add(metadataGrid); + + // Title & Source icon grid + Grid titleSourceGrid = new Grid(); + titleSourceGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + titleSourceGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(10) }); + titleSourceGrid.ColumnDefinitions.Add(new ColumnDefinition()); + Grid.SetRow(titleSourceGrid, 0); + metadataGrid.Children.Add(titleSourceGrid); + + // Title textblock + TextBlock titleTextBlock = new TextBlock + { + Text = Video.Title, + FontWeight = FontWeights.Bold, + FontSize = 15, + }; + Grid.SetColumn(titleTextBlock, 2); + titleSourceGrid.Children.Add(titleTextBlock); + + // Source icon image + Image sourceIcon = new Image + { + Source = new BitmapImage { UriSource = Video.SourceIcon }, + Width = 15, + }; + Grid.SetColumn(sourceIcon, 0); + titleSourceGrid.Children.Add(sourceIcon); + + // Details grid + Grid detailedMetadataGrid = new Grid(); + detailedMetadataGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + detailedMetadataGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(8) }); + detailedMetadataGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + detailedMetadataGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + detailedMetadataGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(5) }); + detailedMetadataGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + detailedMetadataGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(20) }); + detailedMetadataGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + detailedMetadataGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(5) }); + detailedMetadataGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + Grid.SetRow(detailedMetadataGrid, 2); + metadataGrid.Children.Add(detailedMetadataGrid); + double iconSize = 12; + double textSize = 10; + + // Author icon + Image authorIcon = new Image + { + Source = new BitmapImage { UriSource = new Uri($"ms-appx:///Assets/Icons/Universal/{(Application.Current.RequestedTheme == ApplicationTheme.Dark ? "Dark" : "Light")}/Author.png") }, + Width = iconSize, + }; + Grid.SetColumn(authorIcon, 0); + Grid.SetRow(authorIcon, 0); + detailedMetadataGrid.Children.Add(authorIcon); + + // Author data textblock + TextBlock authorDataTextBlock = new TextBlock + { + Text = Video.Author, + VerticalAlignment = VerticalAlignment.Center, + FontSize = textSize, + }; + Grid.SetColumn(authorDataTextBlock, 2); + Grid.SetRow(authorDataTextBlock, 0); + detailedMetadataGrid.Children.Add(authorDataTextBlock); + + // Views icon + Image viewsIcon = new Image + { + Source = new BitmapImage { UriSource = new Uri($"ms-appx:///Assets/Icons/Universal/{(Application.Current.RequestedTheme == ApplicationTheme.Dark ? "Dark" : "Light")}/Views.png") }, + Width = iconSize, + }; + Grid.SetColumn(viewsIcon, 0); + Grid.SetRow(viewsIcon, 2); + detailedMetadataGrid.Children.Add(viewsIcon); + + // Views data textblock + TextBlock viewsDataTextBlock = new TextBlock + { + Text = Video.Views.ToString(), + VerticalAlignment = VerticalAlignment.Center, + FontSize = textSize, + }; + Grid.SetColumn(viewsDataTextBlock, 2); + Grid.SetRow(viewsDataTextBlock, 2); + detailedMetadataGrid.Children.Add(viewsDataTextBlock); + + // Date icon + Image dateIcon = new Image + { + Source = new BitmapImage { UriSource = new Uri($"ms-appx:///Assets/Icons/Universal/{(Application.Current.RequestedTheme == ApplicationTheme.Dark ? "Dark" : "Light")}/Date.png") }, + Width = iconSize, + }; + Grid.SetColumn(dateIcon, 4); + Grid.SetRow(dateIcon, 0); + detailedMetadataGrid.Children.Add(dateIcon); + + // Date data textblock + TextBlock dateDataTextBlock = new TextBlock + { + Text = Video.Date.ToString((string)Config.GetValue("date_format")), + VerticalAlignment = VerticalAlignment.Center, + FontSize = textSize, + }; + Grid.SetColumn(dateDataTextBlock, 6); + Grid.SetRow(dateDataTextBlock, 0); + detailedMetadataGrid.Children.Add(dateDataTextBlock); + + // Duration icon + Image durationIcon = new Image + { + Source = new BitmapImage { UriSource = new Uri($"ms-appx:///Assets/Icons/Universal/{(Application.Current.RequestedTheme == ApplicationTheme.Dark ? "Dark" : "Light")}/Duration.png") }, + Width = iconSize, + }; + Grid.SetColumn(durationIcon, 4); + Grid.SetRow(durationIcon, 2); + detailedMetadataGrid.Children.Add(durationIcon); + + // Duration data textblock + TextBlock durationDataTextBlock = new TextBlock + { + Text = Video.Duration.ToString(), + VerticalAlignment = VerticalAlignment.Center, + FontSize = textSize, + }; + Grid.SetColumn(durationDataTextBlock, 6); + Grid.SetRow(durationDataTextBlock, 2); + detailedMetadataGrid.Children.Add(durationDataTextBlock); + + + + // Delete button + AppBarButton deleteButton = new AppBarButton + { + Icon = new SymbolIcon(Symbol.Clear), + Width = 40, + Height = 48, + VerticalAlignment = VerticalAlignment.Center, + }; + deleteButton.Click += (object sender, RoutedEventArgs e) => + { + PlaylistPanel.Children.Remove(videoPanel); + VObjects.Remove(Video); + DeletedVObjects.Add(Video); + DeletedVideosPanelHandler(); + }; + Grid.SetColumn(deleteButton, 4); + header.Children.Add(deleteButton); + + #endregion + + + + // Content + #region CONTENT + + Grid content = new Grid + { + HorizontalAlignment = HorizontalAlignment.Stretch, + //Margin = new Thickness(0, 15, 0, 15), + }; + content.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + content.RowDefinitions.Add(new RowDefinition { Height = new GridLength(50) }); + content.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + videoPanel.Content = content; + + + + // Download options + Grid downloadOptionsGrid = new Grid + { + HorizontalAlignment = HorizontalAlignment.Stretch, + }; + downloadOptionsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + downloadOptionsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(30) }); + downloadOptionsGrid.ColumnDefinitions.Add(new ColumnDefinition()); + Grid.SetRow(downloadOptionsGrid, 0); + content.Children.Add(downloadOptionsGrid); + + // Media type + Grid mediaTypeGrid = new Grid(); + mediaTypeGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + mediaTypeGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(8) }); + mediaTypeGrid.RowDefinitions.Add(new RowDefinition()); + mediaTypeGrid.RowDefinitions.Add(new RowDefinition()); + mediaTypeGrid.RowDefinitions.Add(new RowDefinition()); + Grid.SetColumn(mediaTypeGrid, 0); + downloadOptionsGrid.Children.Add(mediaTypeGrid); + + // Media type textblock + TextBlock AddPlaylistVideoDownloadOptionsMediaTypeTextBlock = new TextBlock + { + Text = ResourceLoader.GetForCurrentView().GetString("AddPlaylistVideoDownloadOptionsMediaTypeTextBlock"), + FontWeight = FontWeights.SemiBold, + HorizontalAlignment = HorizontalAlignment.Center, + }; + Grid.SetRow(AddPlaylistVideoDownloadOptionsMediaTypeTextBlock, 0); + mediaTypeGrid.Children.Add(AddPlaylistVideoDownloadOptionsMediaTypeTextBlock); + + // Media type radiobutton (AV) + RadioButton AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonAV = new RadioButton + { + Content = ResourceLoader.GetForCurrentView().GetString("AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonAV"), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + GroupName = $"QualityRadiobuttons{Video.UniqueID}" + }; + Grid.SetRow(AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonAV, 2); + mediaTypeGrid.Children.Add(AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonAV); + + // Media type radiobutton (A) + RadioButton AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonA = new RadioButton + { + Content = ResourceLoader.GetForCurrentView().GetString("AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonA"), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Center, + GroupName = $"QualityRadiobuttons{Video.UniqueID}" + }; + Grid.SetRow(AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonA, 3); + mediaTypeGrid.Children.Add(AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonA); + + // Media type radiobutton (V) + RadioButton AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonV = new RadioButton + { + Content = ResourceLoader.GetForCurrentView().GetString("AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonV"), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Bottom, + GroupName = $"QualityRadiobuttons{Video.UniqueID}" + }; + Grid.SetRow(AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonV, 4); + mediaTypeGrid.Children.Add(AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonV); + + // Separator + AppBarSeparator AddPlaylistVideoDownloadOptionsSeparator = new AppBarSeparator + { + VerticalAlignment = VerticalAlignment.Stretch, + HorizontalAlignment = HorizontalAlignment.Center, + }; + Grid.SetColumn(AddPlaylistVideoDownloadOptionsSeparator, 1); + downloadOptionsGrid.Children.Add(AddPlaylistVideoDownloadOptionsSeparator); + + // Quality & Trim grid + Grid qualityTrimGrid = new Grid + { + HorizontalAlignment = HorizontalAlignment.Stretch, + }; + qualityTrimGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + qualityTrimGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(20) }); + qualityTrimGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + Grid.SetColumn(qualityTrimGrid, 2); + downloadOptionsGrid.Children.Add(qualityTrimGrid); + + // Quality grid + Grid qualityGrid = new Grid + { + HorizontalAlignment = HorizontalAlignment.Stretch, + }; + qualityGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + qualityGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(8) }); + qualityGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + Grid.SetRow(qualityGrid, 0); + qualityTrimGrid.Children.Add(qualityGrid); + + // Quality textblock + TextBlock AddPlaylistVideoDownloadOptionsQualityTextBlock = new TextBlock + { + Text = ResourceLoader.GetForCurrentView().GetString("AddPlaylistVideoDownloadOptionsQualityTextBlock"), + FontWeight = FontWeights.SemiBold, + HorizontalAlignment = HorizontalAlignment.Center, + }; + Grid.SetRow(AddPlaylistVideoDownloadOptionsQualityTextBlock, 0); + qualityGrid.Children.Add(AddPlaylistVideoDownloadOptionsQualityTextBlock); + + // Quality combobox + ComboBox AddPlaylistVideoDownloadOptionsQualityComboBox = new ComboBox + { + HorizontalAlignment = HorizontalAlignment.Stretch, + }; + Grid.SetRow(AddPlaylistVideoDownloadOptionsQualityComboBox, 2); + qualityGrid.Children.Add(AddPlaylistVideoDownloadOptionsQualityComboBox); + + // Trim grid + Grid trimGrid = new Grid(); + trimGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + trimGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(8) }); + trimGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + Grid.SetRow(trimGrid, 2); + qualityTrimGrid.Children.Add(trimGrid); + + // Trim textblock + TextBlock AddPlaylistVideoDownloadOptionsTrimTextBlock = new TextBlock + { + Text = ResourceLoader.GetForCurrentView().GetString("AddPlaylistVideoDownloadOptionsTrimTextBlock"), + FontWeight = FontWeights.SemiBold, + HorizontalAlignment = HorizontalAlignment.Center, + }; + Grid.SetRow(AddPlaylistVideoDownloadOptionsTrimTextBlock, 0); + trimGrid.Children.Add(AddPlaylistVideoDownloadOptionsTrimTextBlock); + + // Trim textbox grid + Grid trimTextBoxGrid = new Grid(); + trimTextBoxGrid.ColumnDefinitions.Add(new ColumnDefinition()); + trimTextBoxGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(8) }); + trimTextBoxGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + trimTextBoxGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(8) }); + trimTextBoxGrid.ColumnDefinitions.Add(new ColumnDefinition()); + Grid.SetRow(trimTextBoxGrid, 2); + trimGrid.Children.Add(trimTextBoxGrid); + + // Trim start textbox + TextBox AddPlaylistVideoDownloadOptionsTrimStartTextBox = new TextBox(); + TextBoxExtensions.SetCustomMask(AddPlaylistVideoDownloadOptionsTrimStartTextBox, "5:[0-5]"); + TextBoxExtensions.SetMask(AddPlaylistVideoDownloadOptionsTrimStartTextBox, "99:59:59"); + Grid.SetColumn(AddPlaylistVideoDownloadOptionsTrimStartTextBox, 0); + trimTextBoxGrid.Children.Add(AddPlaylistVideoDownloadOptionsTrimStartTextBox); + + // Trim separator + TextBlock AddPlaylistVideoDownloadOptionsTrimSeparatorTextBlock = new TextBlock + { + Text = "-", + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + }; + Grid.SetColumn(AddPlaylistVideoDownloadOptionsTrimSeparatorTextBlock, 2); + trimTextBoxGrid.Children.Add(AddPlaylistVideoDownloadOptionsTrimSeparatorTextBlock); + + // Trim end textbox + TextBox AddPlaylistVideoDownloadOptionsTrimEndTextBox = new TextBox(); + TextBoxExtensions.SetCustomMask(AddPlaylistVideoDownloadOptionsTrimEndTextBox, "5:[0-5]"); + TextBoxExtensions.SetMask(AddPlaylistVideoDownloadOptionsTrimEndTextBox, "99:59:59"); + Grid.SetColumn(AddPlaylistVideoDownloadOptionsTrimEndTextBox, 4); + trimTextBoxGrid.Children.Add(AddPlaylistVideoDownloadOptionsTrimEndTextBox); + + + + // File & location + Grid fileLocationGrid = new Grid + { + HorizontalAlignment = HorizontalAlignment.Stretch, + }; + fileLocationGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + fileLocationGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(10) }); + fileLocationGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + fileLocationGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + fileLocationGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(15) }); + fileLocationGrid.ColumnDefinitions.Add(new ColumnDefinition()); + Grid.SetRow(fileLocationGrid, 4); + content.Children.Add(fileLocationGrid); + + // File textblock + TextBlock AddPlaylistVideoFileDataTextBlock = new TextBlock + { + Text = ResourceLoader.GetForCurrentView().GetString("AddPlaylistVideoFileDataTextBlock"), + FontWeight = FontWeights.SemiBold, + VerticalAlignment = VerticalAlignment.Center, + }; + Grid.SetRow(AddPlaylistVideoFileDataTextBlock, 0); + Grid.SetColumn(AddPlaylistVideoFileDataTextBlock, 0); + fileLocationGrid.Children.Add(AddPlaylistVideoFileDataTextBlock); + + // File grid + Grid fileGrid = new Grid + { + HorizontalAlignment = HorizontalAlignment.Stretch, + }; + fileGrid.ColumnDefinitions.Add(new ColumnDefinition()); + fileGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(15) }); + fileGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + Grid.SetRow(fileGrid, 0); + Grid.SetColumn(fileGrid, 2); + fileLocationGrid.Children.Add(fileGrid); + + // Filename textbox + TextBox AddPlaylistVideoFileDataFilenameTextBox = new TextBox(); + Grid.SetColumn(AddPlaylistVideoFileDataFilenameTextBox, 0); + fileGrid.Children.Add(AddPlaylistVideoFileDataFilenameTextBox); + + // Extension combobox + ComboBox AddPlaylistVideoFileDataExtensionComboBox = new ComboBox + { + Width = 80 + }; + Grid.SetColumn(AddPlaylistVideoFileDataExtensionComboBox, 2); + fileGrid.Children.Add(AddPlaylistVideoFileDataExtensionComboBox); + + // Location textblock + TextBlock AddPlaylistVideoLocationDataTextBlock = new TextBlock + { + Text = ResourceLoader.GetForCurrentView().GetString("AddPlaylistVideoLocationDataTextBlock"), + FontWeight = FontWeights.SemiBold, + VerticalAlignment = VerticalAlignment.Center, + }; + Grid.SetRow(AddPlaylistVideoLocationDataTextBlock, 2); + Grid.SetColumn(AddPlaylistVideoLocationDataTextBlock, 0); + fileLocationGrid.Children.Add(AddPlaylistVideoLocationDataTextBlock); + + // Location grid + Grid locationGrid = new Grid + { + HorizontalAlignment = HorizontalAlignment.Stretch, + }; + locationGrid.ColumnDefinitions.Add(new ColumnDefinition()); + locationGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0) }); + locationGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + Grid.SetRow(locationGrid, 2); + Grid.SetColumn(locationGrid, 2); + fileLocationGrid.Children.Add(locationGrid); + + // Location data textblock + TextBlock AddPlaylistVideoLocationDataLocationTextBlock = new TextBlock + { + Text = "//Location", + FontSize = 11, + VerticalAlignment = VerticalAlignment.Center, + }; + Grid.SetColumn(AddPlaylistVideoLocationDataLocationTextBlock, 0); + locationGrid.Children.Add(AddPlaylistVideoLocationDataLocationTextBlock); + + // Location selection button + Button AddPlaylistVideoLocationDataChooseLocationButton = new Button + { + Content = "...", + }; + Grid.SetColumn(AddPlaylistVideoLocationDataChooseLocationButton, 2); + locationGrid.Children.Add(AddPlaylistVideoLocationDataChooseLocationButton); + + #endregion + + + + // Set items in quality combobox + foreach (string q in Video.Streams.Keys) + { + AddPlaylistVideoDownloadOptionsQualityComboBox.Items.Add(q); + } + + // Set items in extension combobox + foreach (string x in Video.MediaType == "A" ? Config.DefaultAudioExtensionList : Config.DefaultVideoExtensionList) + { + AddPlaylistVideoFileDataExtensionComboBox.Items.Add(x); + } + + // Set quality option + if (Video.MediaType == "A") + { + AddPlaylistVideoDownloadOptionsQualityComboBox.SelectedValue = ResourceLoader.GetForCurrentView().GetString("AddVideoQualityNoVideoStream"); + AddPlaylistVideoDownloadOptionsQualityComboBox.IsEnabled = false; + } + else + { + AddPlaylistVideoDownloadOptionsQualityComboBox.SelectedValue = Video.SelectedQuality; + AddPlaylistVideoDownloadOptionsQualityComboBox.IsEnabled = true; + } + + // Set trim options + AddPlaylistVideoDownloadOptionsTrimStartTextBox.Text = Video.TrimStart.ToString(); + AddPlaylistVideoDownloadOptionsTrimEndTextBox.Text = Video.TrimEnd.ToString(); + + // Set media type option + switch (Video.MediaType) + { + case "AV": AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonAV.IsChecked = true; break; + case "V": AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonV.IsChecked = true; break; + case "A": AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonA.IsChecked = true; break; + default: AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonAV.IsChecked = true; break; + } + + // Set filename option + AddPlaylistVideoFileDataFilenameTextBox.Text = Video.Filename; + + // Set extension option + AddPlaylistVideoFileDataExtensionComboBox.SelectedItem = Video.Extension; + + // Set location option + if (StorageApplicationPermissions.FutureAccessList.ContainsItem("save")) + { + Video.CustomSaveLocation = await StorageApplicationPermissions.FutureAccessList.GetFolderAsync("save"); + AddPlaylistVideoLocationDataLocationTextBlock.Text = Video.CustomSaveLocation.Path; + Video.FilePath = $@"{(Video.CustomSaveLocation.Path[Video.CustomSaveLocation.Path.Length - 1] == '\\' ? Video.CustomSaveLocation.Path : Video.CustomSaveLocation.Path + '\\')}{Video.Filename}.{Video.Extension.ToLower()}"; + } + else + { + AddPlaylistVideoLocationDataLocationTextBlock.Text = $@"{UserDataPaths.GetDefault().Downloads}\VDownload\"; + Video.FilePath = $@"{UserDataPaths.GetDefault().Downloads}\VDownload\{Video.Filename}.{Video.Extension.ToLower()}"; + } + + // Set event handlers + AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonAV.Checked += (object sender, RoutedEventArgs e) => + { + Video.MediaType = "AV"; + AddPlaylistVideoDownloadOptionsQualityComboBox.IsEnabled = true; + AddPlaylistVideoDownloadOptionsQualityComboBox.SelectedValue = Video.Streams.Keys.ToArray()[0]; + AddPlaylistVideoFileDataExtensionComboBox.Items.Clear(); + foreach (string x in Config.DefaultVideoExtensionList) + { + AddPlaylistVideoFileDataExtensionComboBox.Items.Add(x); + } + AddPlaylistVideoFileDataExtensionComboBox.SelectedItem = Config.GetValue("default_video_extension"); + }; + AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonA.Checked += (object sender, RoutedEventArgs e) => + { + Video.MediaType = "A"; + AddPlaylistVideoDownloadOptionsQualityComboBox.IsEnabled = false; + AddPlaylistVideoDownloadOptionsQualityComboBox.SelectedValue = ResourceLoader.GetForCurrentView().GetString("AddPlaylistVideoQualityNoVideoStream"); + AddPlaylistVideoFileDataExtensionComboBox.Items.Clear(); + foreach (string x in Config.DefaultAudioExtensionList) + { + AddPlaylistVideoFileDataExtensionComboBox.Items.Add(x); + } + AddPlaylistVideoFileDataExtensionComboBox.SelectedItem = Config.GetValue("default_audio_extension"); + }; + AddPlaylistVideoDownloadOptionsMediaTypeRadiobuttonV.Checked += (object sender, RoutedEventArgs e) => + { + Video.MediaType = "V"; + AddPlaylistVideoDownloadOptionsQualityComboBox.IsEnabled = true; + AddPlaylistVideoDownloadOptionsQualityComboBox.SelectedValue = Video.Streams.Keys.ToArray()[0]; + AddPlaylistVideoFileDataExtensionComboBox.Items.Clear(); + foreach (string x in Config.DefaultVideoExtensionList) + { + AddPlaylistVideoFileDataExtensionComboBox.Items.Add(x); + } + AddPlaylistVideoFileDataExtensionComboBox.SelectedItem = Config.GetValue("default_video_extension"); + }; + AddPlaylistVideoDownloadOptionsQualityComboBox.SelectionChanged += (object sender, SelectionChangedEventArgs e) => + { + if (Video.MediaType == "A") + Video.SelectedQuality = Video.Streams.Keys.ToArray()[0]; + else + Video.SelectedQuality = (string)AddPlaylistVideoDownloadOptionsQualityComboBox.SelectedItem; + }; + AddPlaylistVideoDownloadOptionsTrimStartTextBox.TextChanged += (object sender, TextChangedEventArgs e) => + { + try + { + Video.TrimStart = TimeSpan.Parse(AddPlaylistVideoDownloadOptionsTrimStartTextBox.Text); + } + catch { } + }; + AddPlaylistVideoDownloadOptionsTrimEndTextBox.TextChanged += (object sender, TextChangedEventArgs e) => + { + try + { + Video.TrimEnd = TimeSpan.Parse(AddPlaylistVideoDownloadOptionsTrimEndTextBox.Text); + } + catch { } + }; + AddPlaylistVideoFileDataFilenameTextBox.TextChanged += (object sender, TextChangedEventArgs e) => + { + foreach (char c in Path.GetInvalidFileNameChars()) + { + AddPlaylistVideoFileDataFilenameTextBox.Text = AddPlaylistVideoFileDataFilenameTextBox.Text.Replace(c, ' '); + } + Video.Filename = AddPlaylistVideoFileDataFilenameTextBox.Text; + if (Video.CustomSaveLocation != null) + Video.FilePath = $@"{(Video.CustomSaveLocation.Path[Video.CustomSaveLocation.Path.Length - 1] == '\\' ? Video.CustomSaveLocation.Path : Video.CustomSaveLocation.Path + '\\')}{Video.Filename}.{Video.Extension.ToLower()}"; + else + Video.FilePath = $@"{UserDataPaths.GetDefault().Downloads}\VDownload\{Video.Filename}.{Video.Extension.ToLower()}"; + }; + AddPlaylistVideoFileDataExtensionComboBox.SelectionChanged += (object sender, SelectionChangedEventArgs e) => + { + if (!(AddPlaylistVideoFileDataExtensionComboBox.SelectedItem == null)) + { + Video.Extension = (string)AddPlaylistVideoFileDataExtensionComboBox.SelectedItem; + if (Video.CustomSaveLocation != null) + Video.FilePath = $@"{(Video.CustomSaveLocation.Path[Video.CustomSaveLocation.Path.Length - 1] == '\\' ? Video.CustomSaveLocation.Path : Video.CustomSaveLocation.Path + '\\')}{Video.Filename}.{Video.Extension.ToLower()}"; + else + Video.FilePath = $@"{UserDataPaths.GetDefault().Downloads}\VDownload\{Video.Filename}.{Video.Extension.ToLower()}"; + } + }; + AddPlaylistVideoLocationDataChooseLocationButton.Click += async (object sender, RoutedEventArgs e) => + { + FolderPicker picker = new FolderPicker(); + picker.SuggestedStartLocation = PickerLocationId.ComputerFolder; + picker.FileTypeFilter.Add("*"); + StorageFolder folder = await picker.PickSingleFolderAsync(); + if (folder != null) + { + try + { + await (await folder.CreateFileAsync("VDownloadLocationAccessTest")).DeleteAsync(); + Video.CustomSaveLocation = folder; + AddPlaylistVideoLocationDataLocationTextBlock.Text = Video.CustomSaveLocation.Path[Video.CustomSaveLocation.Path.Length - 1] == '\\' ? Video.CustomSaveLocation.Path : Video.CustomSaveLocation.Path + '\\'; + Video.FilePath = $@"{(Video.CustomSaveLocation.Path[Video.CustomSaveLocation.Path.Length - 1] == '\\' ? Video.CustomSaveLocation.Path : Video.CustomSaveLocation.Path + '\\')}{Video.Filename}.{Video.Extension.ToLower()}"; + } + catch { } + } + }; + + + + // Add panel + VObjects[Video] = AddPlaylistVideoLocationDataLocationTextBlock; + PlaylistPanel.Children.Add(videoPanel); + } + + // HANDLE DELETED VIDEOS PANEL + private void DeletedVideosPanelHandler() + { + if (DeletedVideosPanel == null) + { + // Init panel + DeletedVideosPanel = new Grid + { + Background = new SolidColorBrush((Color)Application.Current.Resources["SystemChromeMediumHighColor"]), + BorderThickness = new Thickness(10), + BorderBrush = new SolidColorBrush((Color)Application.Current.Resources["SystemChromeMediumHighColor"]), + CornerRadius = new CornerRadius(1), + Margin = new Thickness(0, 5, 0, 5), + }; + DeletedVideosPanel.ColumnDefinitions.Add(new ColumnDefinition()); + DeletedVideosPanel.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(10) }); + DeletedVideosPanel.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + + // Textblock + TextBlock AddPlaylistDeletedVideosPanelTextBlock = new TextBlock + { + Text = ResourceLoader.GetForCurrentView().GetString("AddPlaylistDeletedVideosPanelTextBlock").Replace("{x}", DeletedVObjects.Count.ToString()), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Center, + }; + Grid.SetColumn(AddPlaylistDeletedVideosPanelTextBlock, 0); + DeletedVideosPanel.Children.Add(AddPlaylistDeletedVideosPanelTextBlock); + + // Button + Button AddPlaylistDeletedVideosPanelButton = new Button + { + Content = ResourceLoader.GetForCurrentView().GetString("AddPlaylistDeletedVideosPanelButton") + }; + AddPlaylistDeletedVideosPanelButton.Click += async (object sender, RoutedEventArgs e) => + { + foreach (VObject v in DeletedVObjects) + { + await HandleVideoOnList(v); + } + DeletedVObjects.Clear(); + PlaylistPanel.Children.Remove(DeletedVideosPanel); + DeletedVideosPanel = null; + }; + Grid.SetColumn(AddPlaylistDeletedVideosPanelButton, 2); + DeletedVideosPanel.Children.Add(AddPlaylistDeletedVideosPanelButton); + + // Add panel + PlaylistPanel.Children.Add(DeletedVideosPanel); + } + else + { + ((TextBlock)DeletedVideosPanel.Children[0]).Text = ResourceLoader.GetForCurrentView().GetString("AddPlaylistDeletedVideosPanelTextBlock").Replace("{x}", DeletedVObjects.Count.ToString()); + } + } + + #endregion + } +} diff --git a/VDownload/Sources/Twitch/Channel.cs b/VDownload/Sources/Twitch/Channel.cs new file mode 100644 index 0000000..0b23577 --- /dev/null +++ b/VDownload/Sources/Twitch/Channel.cs @@ -0,0 +1,89 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace VDownload.Sources.Twitch +{ + internal class Channel + { + #region INIT + + // ID + private string ID { get; set; } + + // CONSTRUCTOR + public Channel(string id) + { + ID = id; + } + + #endregion + + + + #region MAIN + + // GET VIDEOS + public async Task GetVideos() + { + // Client settings + WebClient Client = new WebClient(); + Client.Headers.Add("Accept", "application/vnd.twitchtv.v5+json"); + Client.Headers.Add("Client-ID", "uo6dggojyb8d6soh92zknwmi5ej1q2"); + + // Get channel id + Uri requestUri; + JObject response; + if (!ID.All(char.IsDigit)) + { + Debug.WriteLine(ID); + requestUri = new Uri($"https://api.twitch.tv/kraken/users?login={ID}"); + response = JObject.Parse(await Client.DownloadStringTaskAsync(requestUri)); + response = (JObject)response["users"][0]; + } + else + { + requestUri = new Uri($"https://api.twitch.tv/kraken/users/{ID}"); + response = JObject.Parse(await Client.DownloadStringTaskAsync(requestUri)); + } + string id = response["_id"].ToString(); + + // Get list + List videos = new List(); + int offset = 0; + do + { + Client = new WebClient(); + Client.Headers.Add("Accept", "application/vnd.twitchtv.v5+json"); + Client.Headers.Add("Client-ID", "v8kfhyc2980it9e7t5hhc7baukzuj2"); + + requestUri = new Uri($"https://api.twitch.tv/kraken/channels/{id}/videos?limit=100&offset={offset}"); + response = JObject.Parse(await Client.DownloadStringTaskAsync(requestUri)); + foreach (var v in response["videos"]) + { + Debug.WriteLine(v["_id"].ToString().Replace("v", "")); + videos.Add(v["_id"].ToString().Replace("v", "")); + } + + if (response["videos"].ToArray().Length == 100) + { + offset += 100; + } + else + { + break; + } + } while (true); + + // Return videos + return videos.ToArray(); + } + + #endregion + } +} diff --git a/VDownload/Sources/VObject.cs b/VDownload/Sources/VObject.cs index c4c9544..7bd20b5 100644 --- a/VDownload/Sources/VObject.cs +++ b/VDownload/Sources/VObject.cs @@ -27,7 +27,7 @@ namespace VDownload.Sources #region INIT // VIDEO METADATA - private string UniqueID { get; set; } + public string UniqueID { get; private set; } public VideoSource SourceType { get; private set; } public string ID { get; private set; } public string Title { get; private set; } @@ -78,6 +78,8 @@ namespace VDownload.Sources VideoSourceHandler = new Twitch.Clip(ID); SourceIcon = new Uri("ms-appx:///Assets/Icons/Sources/Twitch.png"); break; + default: + throw new ArgumentException(); } UniqueID = Videos.GetUniqueID(); } @@ -612,7 +614,7 @@ namespace VDownload.Sources Grid.SetColumn(buttonsGrid, 2); baseGrid.Children.Add(buttonsGrid); - // Source icon + // Source button AppBarButton sourceButton = new AppBarButton { Icon = new BitmapIcon { UriSource = SourceIcon, ShowAsMonochrome = false }, diff --git a/VDownload/Strings/en-US/Resources.resw b/VDownload/Strings/en-US/Resources.resw index 1bc6390..ede1bbd 100644 --- a/VDownload/Strings/en-US/Resources.resw +++ b/VDownload/Strings/en-US/Resources.resw @@ -117,6 +117,66 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Cancel + + + Add + + + ADD PLAYLIST + + + Restore + + + {x} videos removed + + + Apply + + + Location + + + Playlist not found. Try again. + + + Search + + + Paste URL and click "Search" button + + + URL + + + Only audio + + + Normal + + + Only video + + + Media type + + + Quality + + + Trim + + + File + + + Location + + + Only audio + Cancel @@ -159,6 +219,12 @@ Paste URL and click "Search" button + + Add playlist + + + 85 + Add video diff --git a/VDownload/VDownload.csproj b/VDownload/VDownload.csproj index 711330d..b1f6cd3 100644 --- a/VDownload/VDownload.csproj +++ b/VDownload/VDownload.csproj @@ -119,15 +119,33 @@ App.xaml + + + + + AddPlaylistBase.xaml + + + AddPlaylistLoading.xaml + + + AddPlaylistMain.xaml + + + AddPlaylistNotFound.xaml + + + AddPlaylistStart.xaml + AddVideoBase.xaml @@ -154,8 +172,8 @@ - - + + @@ -250,6 +268,26 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -292,6 +330,7 @@ + 14.0 diff --git a/VDownload/Views/AddPlaylist/AddPlaylistBase.xaml b/VDownload/Views/AddPlaylist/AddPlaylistBase.xaml new file mode 100644 index 0000000..353e78e --- /dev/null +++ b/VDownload/Views/AddPlaylist/AddPlaylistBase.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + +