Archived
1
0
This repository has been archived on 2026-04-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
FoxTube/FoxTube/Controls/VideoCard.xaml.cs
T
Michael Gordeev b0ecac7c02 Fixed xml escape symbols in notifications title
Fixed ChannelCard
Added "Share" button to VideoCard
2019-04-13 19:25:54 +03:00

449 lines
18 KiB
C#

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
using Windows.UI.Xaml.Media.Imaging;
using Windows.System;
using Windows.ApplicationModel.DataTransfer;
using Windows.ApplicationModel.Resources;
using Microsoft.AppCenter.Analytics;
using System.Collections.Generic;
using YoutubeExplode;
using Windows.UI.Popups;
using YoutubeExplode.Models.MediaStreams;
using Windows.Foundation;
namespace FoxTube.Controls
{
/// <summary>
/// Video item card
/// </summary>
public sealed partial class VideoCard : UserControl
{
ResourceLoader resources = ResourceLoader.GetForCurrentView("Cards");
public string playlistId;
public string videoId;
Video item;
public VideoCard(string id, string playlist = null)
{
InitializeComponent();
Initialize(id, playlist);
}
public VideoCard(Video meta, string playlist = null)
{
InitializeComponent();
item = meta;
playlistId = playlist;
LoadMeta();
}
public async void Initialize(string id, string playlist = null)
{
try
{
videoId = id;
playlistId = playlist;
VideosResource.ListRequest request = SecretsVault.Service.Videos.List("snippet,contentDetails,statistics,liveStreamingDetails");
request.Id = id;
item = (await request.ExecuteAsync()).Items[0];
title.Text = item.Snippet.Title;
channelName.Text = item.Snippet.ChannelTitle;
if (item.Snippet.Title == "Deleted video")
{
ContextFlyout = null;
show.Begin();
return;
}
if (item.Snippet.LiveBroadcastContent == "live")
{
views.Text = $"{item.LiveStreamingDetails.ConcurrentViewers:0,0} {resources.GetString("/Cards/viewers")}";
if (item.LiveStreamingDetails.ScheduledStartTime.HasValue && item.LiveStreamingDetails.ScheduledEndTime.HasValue)
info.Text = $"{item.LiveStreamingDetails.ScheduledEndTime - item.LiveStreamingDetails.ActualStartTime} | {Methods.GetAgo(item.LiveStreamingDetails.ActualStartTime.Value)}";
else
info.Text = Methods.GetAgo(item.LiveStreamingDetails.ActualStartTime.Value);
liveTag.Visibility = Visibility.Visible;
download.Visibility = Visibility.Collapsed;
}
else if (item.Snippet.LiveBroadcastContent == "upcoming")
{
views.Text = "";
if (item.LiveStreamingDetails.ScheduledStartTime.HasValue && item.LiveStreamingDetails.ScheduledEndTime.HasValue)
info.Text = $"{item.LiveStreamingDetails.ScheduledEndTime - item.LiveStreamingDetails.ScheduledStartTime} | {item.LiveStreamingDetails.ScheduledStartTime}";
else
info.Text = $"{Methods.GetAgo(item.Snippet.PublishedAt.Value)}";
liveTag.Visibility = Visibility.Visible;
if (item.LiveStreamingDetails.ScheduledStartTime.HasValue)
liveContent.Text = resources.GetString("/Cards/goesLive") + (item.LiveStreamingDetails.ScheduledStartTime.Value > DateTime.Now ? " " : " -") + (item.LiveStreamingDetails.ScheduledStartTime.Value - DateTime.Now).ToString(@"hh\:mm\:ss");
else liveContent.Text = resources.GetString("/Cards/upcoming");
download.Visibility = Visibility.Collapsed;
}
else
{
views.Text = $"{item.Statistics.ViewCount:0,0} {resources.GetString("/Cards/views")}";
info.Text = $"{item.ContentDetails.Duration.GetDuration()} | {Methods.GetAgo(item.Snippet.PublishedAt.Value)}";
LoadDownloads();
}
LoadAddTo();
try { thumbnail.Source = new BitmapImage(item.Snippet.Thumbnails.Medium.Url.ToUri()); }
catch { }
try { avatar.ProfilePicture = new BitmapImage((await new YoutubeClient().GetChannelAsync(item.Snippet.ChannelId)).LogoUrl.ToUri()) { DecodePixelWidth = 46, DecodePixelHeight = 46 }; }
catch { }
if(SecretsVault.History.Contains(videoId))
watched.Visibility = Visibility.Visible;
show.Begin();
}
catch (Exception e)
{
Visibility = Visibility.Collapsed;
Analytics.TrackEvent("VideoCard loading failed", new Dictionary<string, string>()
{
{ "Exception", e.GetType().ToString() },
{ "Message", e.Message },
{ "Video ID", videoId }
});
}
}
async void LoadDownloads()
{
try
{
// TODO: Localize context menu
MediaStreamInfoSet infoSet = await new YoutubeClient().GetVideoMediaStreamInfosAsync(videoId);
foreach (MuxedStreamInfo i in infoSet.Muxed)
{
MenuFlyoutItem menuItem = new MenuFlyoutItem()
{
Text = i.VideoQualityLabel,
Tag = new object[] { i, i.VideoQualityLabel }
};
menuItem.Click += downloadItemSelected;
download.Items.Add(menuItem);
}
MenuFlyoutItem audioItem = new MenuFlyoutItem()
{
Text = resources.GetString("/VideoPage/audio"),
Tag = new object[] { infoSet.Audio[0], resources.GetString("/Cards/audioOnly") }
};
audioItem.Click += downloadItemSelected;
download.Items.Add(audioItem);
}
catch
{
download.Visibility = Visibility.Collapsed;
}
}
private void downloadItemSelected(object sender, RoutedEventArgs e)
{
DownloadAgent.Add(((sender as MenuFlyoutItem).Tag as object[])[0] as MediaStreamInfo, item, ((sender as MenuFlyoutItem).Tag as object[])[1] as string);
}
public async void LoadMeta()
{
videoId = item.Id;
title.Text = item.Snippet.Title;
channelName.Text = item.Snippet.ChannelTitle;
if (item.Snippet.LiveBroadcastContent == "live")
{
views.Text = $"{item.LiveStreamingDetails.ConcurrentViewers:0,0} {resources.GetString("/Cards/viewers")}";
if (item.LiveStreamingDetails.ScheduledStartTime.HasValue && item.LiveStreamingDetails.ScheduledEndTime.HasValue)
info.Text = $"{item.LiveStreamingDetails.ScheduledEndTime - item.LiveStreamingDetails.ActualStartTime} | {Methods.GetAgo(item.LiveStreamingDetails.ActualStartTime.Value)}";
else
info.Text = Methods.GetAgo(item.LiveStreamingDetails.ActualStartTime.Value);
liveTag.Visibility = Visibility.Visible;
}
else if (item.Snippet.LiveBroadcastContent == "upcoming")
{
views.Text = "";
if (item.LiveStreamingDetails.ScheduledStartTime.HasValue && item.LiveStreamingDetails.ScheduledEndTime.HasValue)
info.Text = $"{item.LiveStreamingDetails.ScheduledEndTime - item.LiveStreamingDetails.ScheduledStartTime} | {item.LiveStreamingDetails.ScheduledStartTime}";
else
info.Text = $"{Methods.GetAgo(item.Snippet.PublishedAt.Value)}";
liveTag.Visibility = Visibility.Visible;
if (item.LiveStreamingDetails.ScheduledStartTime.HasValue)
liveContent.Text = $"{resources.GetString("/Cards/goesLive")} {item.LiveStreamingDetails.ScheduledStartTime - DateTime.Now}";
else liveContent.Text = resources.GetString("/Cards/upcoming");
}
else
{
views.Text = $"{item.Statistics.ViewCount:0,0} {resources.GetString("/Cards/views")}";
info.Text = $"{item.ContentDetails.Duration.GetDuration()} | {Methods.GetAgo(item.Snippet.PublishedAt.Value)}";
}
try { thumbnail.Source = new BitmapImage(item.Snippet.Thumbnails.Medium.Url.ToUri()); }
catch { }
try { avatar.ProfilePicture = new BitmapImage((await new YoutubeClient().GetChannelAsync(item.Snippet.ChannelId)).LogoUrl.ToUri()) { DecodePixelHeight = 50, DecodePixelWidth = 50 }; }
catch { }
if (SecretsVault.History.Contains(videoId))
watched.Visibility = Visibility.Visible;
show.Begin();
}
public async void Button_Click(object sender, RoutedEventArgs e)
{
if (item.ContentDetails.ContentRating != null)
{
if (SecretsVault.IsAuthorized)
{
if (SettingsStorage.Mature == MatureState.Blocked)
{
MessageDialog dialog = new MessageDialog(resources.GetString("/VideoPage/matureText"), resources.GetString("/VideoPage/wantContinue"));
dialog.Commands.Add(new UICommand(resources.GetString("/VideoPage/yes"), null, true));
dialog.Commands.Add(new UICommand(resources.GetString("/VideoPage/always"), (command) => SettingsStorage.Mature = MatureState.Allowed, true));
dialog.Commands.Add(new UICommand(resources.GetString("/VideoPage/no"), null, false));
dialog.CancelCommandIndex = 2;
dialog.DefaultCommandIndex = 0;
if (!(bool)(await dialog.ShowAsync()).Id)
return;
}
}
else
{
MessageDialog dialog = new MessageDialog(resources.GetString("/VideoPage/matureText"), resources.GetString("/VideoPage/signRequired"));
dialog.Commands.Add(new UICommand(resources.GetString("/VideoPage/signin"), (command) => SecretsVault.Authorize()));
dialog.Commands.Add(new UICommand(resources.GetString("/VideoPage/cancel")));
dialog.CancelCommandIndex = 1;
dialog.DefaultCommandIndex = 0;
await dialog.ShowAsync();
return;
}
}
Methods.MainPage.GoToVideo(videoId, playlistId);
}
private void Share(DataTransferManager sender, DataRequestedEventArgs args)
{
Methods.Share(args,
item.Snippet.Thumbnails.Medium.Url,
item.Snippet.Title,
$"https://www.youtube.com/watch?v={videoId}",
resources.GetString("/Cards/videoShare"));
}
private void share_Click(object sender, RoutedEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(Share);
DataTransferManager.ShowShareUI();
}
private void ViewChannel_Click(object sender, RoutedEventArgs e)
{
Methods.MainPage.GoToChannel(item.Snippet.ChannelId);
}
private void GetLink_Click(object sender, RoutedEventArgs e)
{
DataPackage data = new DataPackage();
data.SetText($"https://www.youtube.com/watch?v={videoId}");
Clipboard.SetContent(data);
}
private async void InBrowser_Click(object sender, RoutedEventArgs e)
{
await Launcher.LaunchUriAsync($"https://www.youtube.com/watch?v={videoId}".ToUri());
}
private void Thumbnail_ImageOpened(object sender, RoutedEventArgs e)
{
showThumb.Begin();
}
private async void NewPlaylist_Click(object sender, RoutedEventArgs e)
{
// TODO: Localize strings
StackPanel stack = new StackPanel();
stack.Children.Add(new TextBox
{
PlaceholderText = "Enter playlist name"
});
ComboBox comboBox = new ComboBox
{
Header = "Availablity",
SelectedIndex = 0,
HorizontalAlignment = HorizontalAlignment.Stretch
};
comboBox.Items.Add(new ComboBoxItem { Content = "Public" });
comboBox.Items.Add(new ComboBoxItem { Content = "Private" });
comboBox.Items.Add(new ComboBoxItem { Content = "Direct link" });
stack.Children.Add(comboBox);
ContentDialog playlistDialog = new ContentDialog
{
PrimaryButtonText = "Create and add",
CloseButtonText = "Cancel",
DefaultButton = ContentDialogButton.Primary,
Title = "New playlist",
Content = stack
};
playlistDialog.PrimaryButtonClick += PlaylistDialog_PrimaryButtonClick;
await playlistDialog.ShowAsync();
}
private async void PlaylistDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
string privacy = "private";
switch (((sender.Content as StackPanel).Children[1] as ComboBox).SelectedIndex)
{
case 0:
privacy = "public";
break;
case 1:
privacy = "private";
break;
case 2:
privacy = "unlisted";
break;
}
Playlist newItem = new Playlist
{
Snippet = new PlaylistSnippet
{
Title = ((sender.Content as StackPanel).Children[0] as TextBox).Text
},
Status = new PlaylistStatus
{
PrivacyStatus = privacy,
}
};
Playlist i;
try { i = await SecretsVault.Service.Playlists.Insert(newItem, "snippet,status").ExecuteAsync(); }
catch
{
return;
}
ToggleMenuFlyoutItem menuItem = new ToggleMenuFlyoutItem
{
Text = i.Snippet.Title,
IsChecked = true,
Tag = i,
Icon = new FontIcon
{
Glyph = "\xE728"
}
};
menuItem.Click += Item_Click;
addTo.Items.Add(menuItem);
Item_Click(menuItem, null);
}
private void Wl_Click(object sender, RoutedEventArgs e)
{
}
async void LoadAddTo()
{
if (SecretsVault.UserChannel == null)
{
addTo.Visibility = Visibility.Collapsed;
return;
}
if (SecretsVault.WatchLater.Contains(item.Id))
(addTo.Items[1] as ToggleMenuFlyoutItem).IsChecked = true;
PlaylistsResource.ListRequest request = SecretsVault.Service.Playlists.List("snippet");
request.Mine = true;
request.MaxResults = 50;
PlaylistListResponse response = await request.ExecuteAsync();
PlaylistItemsResource.ListRequest itemRequest = SecretsVault.Service.PlaylistItems.List("snippet");
itemRequest.VideoId = item.Id;
foreach (Playlist i in response.Items)
{
itemRequest.PlaylistId = i.Id;
ToggleMenuFlyoutItem menuItem = new ToggleMenuFlyoutItem
{
Text = i.Snippet.Title,
IsChecked = (await itemRequest.ExecuteAsync()).Items.Count > 0,
Tag = i,
Icon = new FontIcon
{
Glyph = "\xE728"
}
};
menuItem.Click += Item_Click;
addTo.Items.Add(menuItem);
}
}
private async void Item_Click(object sender, RoutedEventArgs e)
{
if (((ToggleMenuFlyoutItem)sender).IsChecked)
{
try
{
PlaylistItem playlist = new PlaylistItem
{
Snippet = new PlaylistItemSnippet
{
PlaylistId = (((ToggleMenuFlyoutItem)sender).Tag as Playlist).Id,
ResourceId = new ResourceId
{
VideoId = item.Id,
Kind = "youtube#video"
}
}
};
PlaylistItemsResource.InsertRequest request = SecretsVault.Service.PlaylistItems.Insert(playlist, "snippet");
await request.ExecuteAsync();
}
catch
{
((ToggleMenuFlyoutItem)sender).IsChecked = false;
}
}
else
{
try
{
PlaylistItemsResource.ListRequest itemRequest = SecretsVault.Service.PlaylistItems.List("snippet");
itemRequest.VideoId = item.Id;
itemRequest.PlaylistId = ((Playlist)((ToggleMenuFlyoutItem)sender).Tag).Id;
PlaylistItemsResource.DeleteRequest request = SecretsVault.Service.PlaylistItems.Delete((await itemRequest.ExecuteAsync()).Items[0].Id);
await request.ExecuteAsync();
}
catch
{
((ToggleMenuFlyoutItem)sender).IsChecked = true;
}
}
}
}
}