Added Subscriptions page and updated subscriptions management
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
using FoxTube.Utils;
|
using FoxTube.Utils;
|
||||||
|
using Google.Apis.YouTube.v3.Data;
|
||||||
using SQLitePCL;
|
using SQLitePCL;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using Windows.Devices.PointOfService;
|
using Windows.Devices.PointOfService;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
@@ -47,7 +49,7 @@ namespace FoxTube
|
|||||||
public static string ToHex(this Color color) =>
|
public static string ToHex(this Color color) =>
|
||||||
$"#{color.R:X}{color.G:X}{color.B:X}";
|
$"#{color.R:X}{color.G:X}{color.B:X}";
|
||||||
|
|
||||||
public static Color FromHex(this Color parent, string hex)
|
public static Color FromHex(string hex)
|
||||||
{
|
{
|
||||||
hex = hex.Replace("#", "");
|
hex = hex.Replace("#", "");
|
||||||
List<byte> values = new List<byte>();
|
List<byte> values = new List<byte>();
|
||||||
@@ -126,5 +128,14 @@ namespace FoxTube
|
|||||||
else
|
else
|
||||||
return Math.Round(span.TotalDays / 365) + " " + "years ago";
|
return Math.Round(span.TotalDays / 365) + " " + "years ago";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<Channel> GetChannel(string channelId, string part)
|
||||||
|
{
|
||||||
|
var request = UserManagement.Service.Channels.List(part);
|
||||||
|
request.Id = channelId;
|
||||||
|
request.MaxResults = 1;
|
||||||
|
|
||||||
|
return (await request.ExecuteAsync()).Items.FirstOrDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,6 +130,7 @@
|
|||||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Models\Subscription.cs" />
|
||||||
<Compile Include="Services\DownloadsCenter.cs" />
|
<Compile Include="Services\DownloadsCenter.cs" />
|
||||||
<Compile Include="Extensions.cs" />
|
<Compile Include="Extensions.cs" />
|
||||||
<Compile Include="Utils\Feedback.cs" />
|
<Compile Include="Utils\Feedback.cs" />
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using Google.Apis.YouTube.v3.Data;
|
||||||
|
|
||||||
|
namespace FoxTube.Models
|
||||||
|
{
|
||||||
|
public class Subscription
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string ChannelId { get; set; }
|
||||||
|
public string SubscriptionId { get; set; }
|
||||||
|
public ThumbnailDetails Avatar { get; set; }
|
||||||
|
public ImageSettings Banner { get; set; }
|
||||||
|
public ulong? SubscribersCount { get; set; }
|
||||||
|
public ulong VideosCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
+64
-19
@@ -30,26 +30,24 @@ namespace FoxTube.Models
|
|||||||
|
|
||||||
public async Task<bool> UpdateSubscriptionState(string channelId)
|
public async Task<bool> UpdateSubscriptionState(string channelId)
|
||||||
{
|
{
|
||||||
if (Subscriptions.Exists(x => x.Snippet.ResourceId.ChannelId == channelId))
|
if (Subscriptions.Find(i => i.ChannelId == channelId) is Subscription subscription)
|
||||||
{
|
{
|
||||||
Subscription s = Subscriptions.Find(x => x.Snippet.ResourceId.ChannelId == channelId);
|
try { await Service.Subscriptions.Delete(subscription.SubscriptionId).ExecuteAsync(); }
|
||||||
|
|
||||||
try { await Service.Subscriptions.Delete(s.Id).ExecuteAsync(); }
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Metrics.SendReport(new Exception("Failed to unsubscribe", e));
|
Metrics.SendReport(new Exception("Failed to unsubscribe", e));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserManagement.SubscriptionsChangedInvoker(this, s);
|
UserManagement.SubscriptionsChangedInvoker(this, subscription);
|
||||||
Subscriptions.Remove(s);
|
Subscriptions.Remove(subscription);
|
||||||
|
|
||||||
SaveSubscriptions();
|
SaveSubscriptions();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var request = Service.Subscriptions.Insert(new Subscription()
|
var request = Service.Subscriptions.Insert(new Google.Apis.YouTube.v3.Data.Subscription()
|
||||||
{
|
{
|
||||||
Snippet = new SubscriptionSnippet()
|
Snippet = new SubscriptionSnippet()
|
||||||
{
|
{
|
||||||
@@ -59,14 +57,27 @@ namespace FoxTube.Models
|
|||||||
Kind = "youtube#channel"
|
Kind = "youtube#channel"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, "snippet");
|
}, "id");
|
||||||
|
|
||||||
Subscription s = await request.ExecuteAsync();
|
var subscriptionData = await request.ExecuteAsync();
|
||||||
if (s == null)
|
if (subscriptionData == null)
|
||||||
return false;
|
return false;
|
||||||
Subscriptions.Add(s);
|
|
||||||
|
|
||||||
UserManagement.SubscriptionsChangedInvoker(this, s);
|
Channel channel = await Extensions.GetChannel(subscriptionData.Snippet.ChannelId, "snippet,statistics,brandingSettins");
|
||||||
|
|
||||||
|
subscription = new Subscription
|
||||||
|
{
|
||||||
|
Title = channel.Snippet.Title,
|
||||||
|
ChannelId = channel.Id,
|
||||||
|
SubscriptionId = subscriptionData.Id,
|
||||||
|
VideosCount = channel.Statistics.VideoCount.Value,
|
||||||
|
SubscribersCount = channel.Statistics.SubscriberCount,
|
||||||
|
Avatar = channel.Snippet.Thumbnails,
|
||||||
|
Banner = channel.BrandingSettings.Image
|
||||||
|
};
|
||||||
|
Subscriptions.Add(subscription);
|
||||||
|
|
||||||
|
UserManagement.SubscriptionsChangedInvoker(this, subscription);
|
||||||
|
|
||||||
SaveSubscriptions();
|
SaveSubscriptions();
|
||||||
return true;
|
return true;
|
||||||
@@ -76,7 +87,7 @@ namespace FoxTube.Models
|
|||||||
private void SaveSubscriptions()
|
private void SaveSubscriptions()
|
||||||
{
|
{
|
||||||
Dictionary<string, string> subs = Subscriptions.Select(i =>
|
Dictionary<string, string> subs = Subscriptions.Select(i =>
|
||||||
new KeyValuePair<string, string>(i.Snippet.ResourceId.ChannelId, i.Snippet.Thumbnails.Default__?.Url))
|
new KeyValuePair<string, string>(i.ChannelId, i.Avatar.Default__?.Url))
|
||||||
as Dictionary<string, string>;
|
as Dictionary<string, string>;
|
||||||
|
|
||||||
ApplicationData.Current.RoamingSettings.Values[$"Subscriptions.{UserInfo.Id}"] = JsonConvert.SerializeObject(subs);
|
ApplicationData.Current.RoamingSettings.Values[$"Subscriptions.{UserInfo.Id}"] = JsonConvert.SerializeObject(subs);
|
||||||
@@ -99,9 +110,22 @@ namespace FoxTube.Models
|
|||||||
|
|
||||||
user.UserInfo = await new Oauth2Service(initializer).Userinfo.Get().ExecuteAsync();
|
user.UserInfo = await new Oauth2Service(initializer).Userinfo.Get().ExecuteAsync();
|
||||||
|
|
||||||
|
var request = user.Service.Channels.List("snippet,contentDetails,brandingSettings");
|
||||||
|
request.Mine = true;
|
||||||
|
user.Channel = request.Execute().Items[0];
|
||||||
|
|
||||||
// TODO: Retrieve history and WL
|
// TODO: Retrieve history and WL
|
||||||
|
|
||||||
SubscriptionsResource.ListRequest subRequest = user.Service.Subscriptions.List("snippet");
|
await user.LoadSubscriptions();
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadSubscriptions()
|
||||||
|
{
|
||||||
|
Subscriptions.Clear();
|
||||||
|
|
||||||
|
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;
|
||||||
@@ -112,16 +136,37 @@ namespace FoxTube.Models
|
|||||||
subResponse = await subRequest.ExecuteAsync();
|
subResponse = await subRequest.ExecuteAsync();
|
||||||
subRequest.PageToken = subResponse.NextPageToken;
|
subRequest.PageToken = subResponse.NextPageToken;
|
||||||
|
|
||||||
user.Subscriptions.AddRange(subResponse.Items);
|
Subscriptions.AddRange(subResponse.Items.Select(i => new Subscription
|
||||||
|
{
|
||||||
|
Title = i.Snippet.Title,
|
||||||
|
ChannelId = i.Snippet.ResourceId.ChannelId,
|
||||||
|
SubscriptionId = i.Id,
|
||||||
|
Avatar = i.Snippet.Thumbnails,
|
||||||
|
Description = i.Snippet.Description
|
||||||
|
}));
|
||||||
|
|
||||||
} while (!string.IsNullOrWhiteSpace(subRequest.PageToken));
|
} while (!string.IsNullOrWhiteSpace(subRequest.PageToken));
|
||||||
|
|
||||||
|
var request = Service.Channels.List("statistics,brandingSettings");
|
||||||
|
request.Id = string.Join(',', Subscriptions.Select(i => i.ChannelId));
|
||||||
|
request.MaxResults = 50;
|
||||||
|
ChannelListResponse response;
|
||||||
|
|
||||||
var request = user.Service.Channels.List("snippet,contentDetails,brandingSettings");
|
if (Subscriptions.Count > 0)
|
||||||
request.Mine = true;
|
do
|
||||||
user.Channel = request.Execute().Items[0];
|
{
|
||||||
|
response = await request.ExecuteAsync();
|
||||||
|
request.PageToken = response.NextPageToken;
|
||||||
|
|
||||||
return user;
|
Subscriptions.ForEach(i =>
|
||||||
|
{
|
||||||
|
Channel channel = response.Items.FirstOrDefault(c => c.Id == i.ChannelId);
|
||||||
|
i.Banner = channel.BrandingSettings.Image;
|
||||||
|
i.SubscribersCount = channel.Statistics.HiddenSubscriberCount.Value ? null : channel.Statistics.SubscriberCount;
|
||||||
|
i.VideosCount = channel.Statistics.VideoCount.Value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
while (!string.IsNullOrWhiteSpace(request.PageToken));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ using FoxTube.Models;
|
|||||||
using YouTube;
|
using YouTube;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using FoxTube.Utils;
|
using FoxTube.Utils;
|
||||||
using YoutubeExplode;
|
using YoutubeExplode;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using Google.Apis.YouTube.v3.Data;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Media.Imaging;
|
using Windows.UI.Xaml.Media.Imaging;
|
||||||
|
using FoxTube.Models;
|
||||||
|
|
||||||
namespace FoxTube.Utils
|
namespace FoxTube.Utils
|
||||||
{
|
{
|
||||||
@@ -65,19 +65,19 @@ namespace FoxTube.Utils
|
|||||||
{
|
{
|
||||||
Height = 20,
|
Height = 20,
|
||||||
Margin = new Thickness(-5, 0, 15, 0),
|
Margin = new Thickness(-5, 0, 15, 0),
|
||||||
ProfilePicture = new BitmapImage().LoadImage(subscription.Snippet.Thumbnails.Default__.Url, 20, 20)
|
ProfilePicture = new BitmapImage().LoadImage(subscription.Avatar.Default__.Url, 20, 20)
|
||||||
});
|
});
|
||||||
|
|
||||||
stack.Children.Add(new TextBlock
|
stack.Children.Add(new TextBlock
|
||||||
{
|
{
|
||||||
FontSize = 14,
|
FontSize = 14,
|
||||||
Text = subscription.Snippet.Title
|
Text = subscription.Title
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Microsoft.UI.Xaml.Controls.NavigationViewItem
|
return new Microsoft.UI.Xaml.Controls.NavigationViewItem
|
||||||
{
|
{
|
||||||
Content = stack,
|
Content = stack,
|
||||||
Tag = subscription.Snippet.ChannelId
|
Tag = subscription.ChannelId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
{
|
{
|
||||||
Home,
|
Home,
|
||||||
Settings,
|
Settings,
|
||||||
Downloads
|
Downloads,
|
||||||
|
Subscriptions
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Navigation
|
public static class Navigation
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
{
|
{
|
||||||
NavigationTarget.Settings => typeof(Views.Settings),
|
NavigationTarget.Settings => typeof(Views.Settings),
|
||||||
NavigationTarget.Downloads => typeof(Views.Downloads),
|
NavigationTarget.Downloads => typeof(Views.Downloads),
|
||||||
|
NavigationTarget.Subscriptions => typeof(Views.Subscriptions),
|
||||||
_ => UserManagement.Authorized ? typeof(Views.Home) : typeof(Views.HomeSections.Trending),
|
_ => UserManagement.Authorized ? typeof(Views.Home) : typeof(Views.HomeSections.Trending),
|
||||||
},
|
},
|
||||||
parameters);
|
parameters);
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using FoxTube.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace FoxTube.Converters
|
||||||
|
{
|
||||||
|
public class SubscriptionDataConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
Subscription subscription = (Subscription)value;
|
||||||
|
List<string> data = new List<string>();
|
||||||
|
if (subscription.SubscribersCount.HasValue)
|
||||||
|
data.Add($"{GetTruncatedSubscribersCount(subscription.SubscribersCount)} subscribers");
|
||||||
|
|
||||||
|
data.Add($"{subscription.VideosCount} videos");
|
||||||
|
return string.Join(" • ", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language) =>
|
||||||
|
throw new NotImplementedException();
|
||||||
|
|
||||||
|
private string GetTruncatedSubscribersCount(ulong? count)
|
||||||
|
{
|
||||||
|
if (!count.HasValue)
|
||||||
|
return "-";
|
||||||
|
|
||||||
|
if (count > 1000000)
|
||||||
|
return Math.Round(count.Value / (double)1000000, 1) + "M";
|
||||||
|
else if (count > 1000)
|
||||||
|
return Math.Round(count.Value / (double)1000, 1) + "k";
|
||||||
|
else
|
||||||
|
return count.Value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -138,6 +138,7 @@
|
|||||||
<Compile Include="Controls\ItemsGrid.xaml.cs">
|
<Compile Include="Controls\ItemsGrid.xaml.cs">
|
||||||
<DependentUpon>ItemsGrid.xaml</DependentUpon>
|
<DependentUpon>ItemsGrid.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Converters\SubscriptionDataConverter.cs" />
|
||||||
<Compile Include="MainPage.xaml.cs">
|
<Compile Include="MainPage.xaml.cs">
|
||||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
using FoxTube.Controls.Dialogs;
|
using FoxTube.Controls.Dialogs;
|
||||||
using FoxTube.Utils;
|
using FoxTube.Utils;
|
||||||
using FoxTube.Services;
|
using FoxTube.Services;
|
||||||
using Google.Apis.YouTube.v3.Data;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Windows.ApplicationModel.Core;
|
using Windows.ApplicationModel.Core;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using FoxTube.Models;
|
||||||
|
|
||||||
// TODO: Fix header (UI)
|
// TODO: Fix header (UI)
|
||||||
namespace FoxTube
|
namespace FoxTube
|
||||||
@@ -69,6 +69,9 @@ namespace FoxTube
|
|||||||
case "Downloads":
|
case "Downloads":
|
||||||
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag as string == "downloads");
|
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag as string == "downloads");
|
||||||
break;
|
break;
|
||||||
|
case "Subscriptions":
|
||||||
|
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag as string == "subscriptions");
|
||||||
|
break;
|
||||||
case "Home":
|
case "Home":
|
||||||
case "Trending":
|
case "Trending":
|
||||||
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag as string == "home");
|
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag as string == "home");
|
||||||
@@ -86,7 +89,7 @@ namespace FoxTube
|
|||||||
|
|
||||||
private void NavigationViewControl_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
|
private void NavigationViewControl_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
|
||||||
{
|
{
|
||||||
(NavigationTarget target, object parameters) suggestedTransition = (NavigationTarget.Home, null);
|
(NavigationTarget target, object parameters) suggestedTransition;
|
||||||
|
|
||||||
if (args.IsSettingsInvoked)
|
if (args.IsSettingsInvoked)
|
||||||
suggestedTransition = (NavigationTarget.Settings, null);
|
suggestedTransition = (NavigationTarget.Settings, null);
|
||||||
@@ -95,6 +98,7 @@ namespace FoxTube
|
|||||||
{
|
{
|
||||||
"home" => (NavigationTarget.Home, null),
|
"home" => (NavigationTarget.Home, null),
|
||||||
"downloads" => (NavigationTarget.Downloads, null),
|
"downloads" => (NavigationTarget.Downloads, null),
|
||||||
|
"subscriptions" => (NavigationTarget.Subscriptions, null),
|
||||||
_ => (NavigationTarget.Home, null) // TODO: Navigate to channel
|
_ => (NavigationTarget.Home, null) // TODO: Navigate to channel
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,7 +139,7 @@ namespace FoxTube
|
|||||||
if (authorized && UserManagement.CurrentUser.Subscriptions.Count > 0)
|
if (authorized && UserManagement.CurrentUser.Subscriptions.Count > 0)
|
||||||
{
|
{
|
||||||
NavigationViewControl.MenuItems.Add(new NavigationViewItemHeader { Content = "Subscriptions" });
|
NavigationViewControl.MenuItems.Add(new NavigationViewItemHeader { Content = "Subscriptions" });
|
||||||
UserManagement.CurrentUser.Subscriptions.GetRange(0, Math.Min(UserManagement.CurrentUser.Subscriptions.Count, 10)).ForEach(i =>
|
UserManagement.CurrentUser.Subscriptions.ToList().GetRange(0, Math.Min(UserManagement.CurrentUser.Subscriptions.Count, 10)).ForEach(i =>
|
||||||
NavigationViewControl.MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(i)));
|
NavigationViewControl.MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +154,7 @@ namespace FoxTube
|
|||||||
|
|
||||||
private void UsersControl_SubscriptionsChanged(object sender, Subscription subscription)
|
private void UsersControl_SubscriptionsChanged(object sender, Subscription subscription)
|
||||||
{
|
{
|
||||||
if (NavigationViewControl.MenuItems.FirstOrDefault(i => ((NavigationViewItemBase)i).Tag as string == subscription.Snippet.ChannelId) is NavigationViewItem container)
|
if (NavigationViewControl.MenuItems.FirstOrDefault(i => ((NavigationViewItemBase)i).Tag as string == subscription.ChannelId) is NavigationViewItem container)
|
||||||
{
|
{
|
||||||
NavigationViewControl.MenuItems.Remove(container);
|
NavigationViewControl.MenuItems.Remove(container);
|
||||||
|
|
||||||
@@ -166,6 +170,22 @@ namespace FoxTube
|
|||||||
NavigationViewControl.MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(subscription));
|
NavigationViewControl.MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(subscription));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateSubscriptions()
|
||||||
|
{
|
||||||
|
// Add general menu items
|
||||||
|
NavigationViewControl.MenuItems.Clear();
|
||||||
|
MenuItemsList.GetMenuItems(UserManagement.Authorized).ForEach(i =>
|
||||||
|
NavigationViewControl.MenuItems.Add(i));
|
||||||
|
|
||||||
|
// Add subscriptions list to the menu
|
||||||
|
if (UserManagement.Authorized && UserManagement.CurrentUser.Subscriptions.Count > 0)
|
||||||
|
{
|
||||||
|
NavigationViewControl.MenuItems.Add(new NavigationViewItemHeader { Content = "Subscriptions" });
|
||||||
|
UserManagement.CurrentUser.Subscriptions.ToList().GetRange(0, Math.Min(UserManagement.CurrentUser.Subscriptions.Count, 10)).ForEach(i =>
|
||||||
|
NavigationViewControl.MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Navigation actions
|
#region Navigation actions
|
||||||
|
|||||||
@@ -1,40 +1,81 @@
|
|||||||
<Page
|
<Page
|
||||||
xmlns:models="using:FoxTube.Core.Models"
|
NavigationCacheMode="Enabled"
|
||||||
x:Class="FoxTube.Views.Subscriptions"
|
x:Class="FoxTube.Views.Subscriptions"
|
||||||
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.Views"
|
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:data="using:FoxTube.Models"
|
||||||
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
xmlns:converters="using:FoxTube.Converters" xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<ListView Padding="10" SelectionMode="None">
|
<Page.Resources>
|
||||||
<ListViewItem Padding="0" HorizontalAlignment="Left">
|
<converters:SubscriptionDataConverter x:Name="converter"/>
|
||||||
<Grid Height="150" Width="700" Padding="20" ColumnSpacing="20" CornerRadius="20">
|
</Page.Resources>
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="auto"/>
|
|
||||||
<ColumnDefinition/>
|
|
||||||
<ColumnDefinition Width="auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<Grid.Background>
|
<Grid>
|
||||||
<ImageBrush ImageSource="https://yt3.ggpht.com/TckH7MhPH7UcxPnHeEj6R78xe1uOmrlHdUD1Usy7sr36xLDzl86NxAyfmDOIUrxl6kpiBgtKgA=w1060-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj"/>
|
<RefreshContainer RefreshRequested="RefreshContainer_RefreshRequested">
|
||||||
</Grid.Background>
|
<ListView Padding="10" SelectionMode="None" IsItemClickEnabled="True" Name="list" ItemClick="List_ItemClick">
|
||||||
|
<ListView.ItemContainerTransitions>
|
||||||
|
<TransitionCollection>
|
||||||
|
<EntranceThemeTransition IsStaggeringEnabled="True"/>
|
||||||
|
<AddDeleteThemeTransition/>
|
||||||
|
</TransitionCollection>
|
||||||
|
</ListView.ItemContainerTransitions>
|
||||||
|
<ListView.ItemContainerStyle>
|
||||||
|
<Style TargetType="ListViewItem">
|
||||||
|
<Setter Property="Padding" Value="0"/>
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||||
|
<Setter Property="Margin" Value="0,0,0,10"/>
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="data:Subscription">
|
||||||
|
<Grid Height="140" Padding="20" ColumnSpacing="20" CornerRadius="20" RequestedTheme="Dark">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Grid Grid.ColumnSpan="3" Margin="-20">
|
<Grid.Background>
|
||||||
<Grid.Background>
|
<ImageBrush ImageSource="{Binding Path=Banner.BannerImageUrl}" Stretch="UniformToFill"/>
|
||||||
<AcrylicBrush TintColor="Black" TintOpacity=".5" Opacity=".97"/>
|
</Grid.Background>
|
||||||
</Grid.Background>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<controls:ImageEx CornerRadius="999" Source="https://yt3.ggpht.com/a/AGF-l7_hHK5yjEPhlM72Tmk26zoOVkNx88pWoZnFVQ=s88-c-k-c0xffffffff-no-rj-mo"/>
|
<Grid Grid.ColumnSpan="3" Margin="-20">
|
||||||
|
<Grid.Background>
|
||||||
|
<AcrylicBrush TintColor="Black" TintOpacity=".5"/>
|
||||||
|
</Grid.Background>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<StackPanel Grid.Column="1">
|
<PersonPicture ProfilePicture="{Binding Path=Avatar.Medium.Url}"/>
|
||||||
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="[BadComedian]"/>
|
|
||||||
<TextBlock Text="Обзоры кино. Юмор, ирония, ненависть, плохие российские / зарубежные фильмы. 
ПРИЯТНОГО ПРОСМОТРА." TextTrimming="CharacterEllipsis" TextWrapping="WrapWholeWords" MaxLines="4"/>
|
<StackPanel Grid.Column="1">
|
||||||
</StackPanel>
|
<TextBlock Style="{StaticResource TitleTextBlockStyle}" Text="{Binding Path=Title}" MaxLines="1" TextTrimming="CharacterEllipsis"/>
|
||||||
</Grid>
|
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding Converter={StaticResource converter}}" MaxLines="1" TextTrimming="WordEllipsis"/>
|
||||||
</ListViewItem>
|
<TextBlock Text="{Binding Path=Description}" MaxLines="2"/>
|
||||||
</ListView>
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Grid.Column="2">
|
||||||
|
<StackPanel.Resources>
|
||||||
|
<Style TargetType="Button" BasedOn="{StaticResource ButtonRevealStyle}">
|
||||||
|
<Setter Property="Height" Value="50"/>
|
||||||
|
<Setter Property="MinWidth" Value="50"/>
|
||||||
|
<Setter Property="FontSize" Value="20"/>
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
</Style>
|
||||||
|
</StackPanel.Resources>
|
||||||
|
<Button Content="Subscribed" Width="200" Click="Unsubscribe" Tag="{Binding Path=ChannelId}"/>
|
||||||
|
<Button Content="" FontFamily="Segoe MDL2 Assets" Visibility="Collapsed"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
|
</RefreshContainer>
|
||||||
|
|
||||||
|
<controls:Loading IsLoading="False" x:Name="loadingScreen" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<ProgressRing Width="50" Height="50" IsActive="True"/>
|
||||||
|
</controls:Loading>
|
||||||
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@@ -1,13 +1,57 @@
|
|||||||
using Windows.UI.Xaml.Controls;
|
using FoxTube.Attributes;
|
||||||
|
using FoxTube.Models;
|
||||||
|
using System.Linq;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
namespace FoxTube.Views
|
namespace FoxTube.Views
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// User's subscriptions list
|
/// User's subscriptions list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Refreshable]
|
||||||
public sealed partial class Subscriptions : Page
|
public sealed partial class Subscriptions : Page
|
||||||
{
|
{
|
||||||
public Subscriptions() =>
|
public Subscriptions()
|
||||||
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
list.ItemsSource = UserManagement.CurrentUser.Subscriptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void List_ItemClick(object sender, ItemClickEventArgs e)
|
||||||
|
{
|
||||||
|
// TODO: Navigate to channel
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Unsubscribe(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
loadingScreen.IsLoading = true;
|
||||||
|
await UserManagement.CurrentUser.UpdateSubscriptionState((sender as Button).Tag as string);
|
||||||
|
list.ItemsSource = UserManagement.CurrentUser.Subscriptions;
|
||||||
|
loadingScreen.IsLoading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
|
||||||
|
if (e.NavigationMode == NavigationMode.Refresh)
|
||||||
|
RefreshSubscriptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshContainer_RefreshRequested(RefreshContainer sender, RefreshRequestedEventArgs args) =>
|
||||||
|
RefreshSubscriptions();
|
||||||
|
|
||||||
|
private async void RefreshSubscriptions()
|
||||||
|
{
|
||||||
|
loadingScreen.IsLoading = true;
|
||||||
|
|
||||||
|
await UserManagement.CurrentUser.LoadSubscriptions();
|
||||||
|
list.ItemsSource = UserManagement.CurrentUser.Subscriptions;
|
||||||
|
|
||||||
|
MainPage.Current.UpdateSubscriptions();
|
||||||
|
|
||||||
|
loadingScreen.IsLoading = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user