Pixiview/Gallery/Illust/RecommendsPage.xaml.cs
2021-08-04 10:27:41 +08:00

370 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Gallery.UI;
using Gallery.UI.Theme;
using Gallery.Utils;
using Xamarin.Forms;
namespace Gallery.Illust
{
public partial class RecommendsPage : IllustDataCollectionPage
{
public static readonly BindableProperty UsersProperty = BindableProperty.Create(
nameof(Users), typeof(List<IllustUserItem>), typeof(RecommendsPage));
public static readonly BindableProperty UserColumnsProperty = BindableProperty.Create(
nameof(UserColumns), typeof(int), typeof(RecommendsPage), 1);
public static readonly BindableProperty UserRecommendsVisibleProperty = BindableProperty.Create(
nameof(UserRecommendsVisible), typeof(bool), typeof(RecommendsPage));
public List<IllustUserItem> Users
{
get => (List<IllustUserItem>)GetValue(UsersProperty);
set => SetValue(UsersProperty, value);
}
public int UserColumns
{
get => (int)GetValue(UserColumnsProperty);
set => SetValue(UserColumnsProperty, value);
}
public bool UserRecommendsVisible
{
get => (bool)GetValue(UserRecommendsVisibleProperty);
set => SetValue(UserRecommendsVisibleProperty, value);
}
private IllustData illustData;
public RecommendsPage()
{
Resources.Add("cardView", GetCardViewTemplate());
Resources.Add("userCardView", GetUserCardViewTemplate());
InitializeComponent();
}
protected override bool NeedCookie => true;
protected override ActivityIndicator LoadingIndicator => activityLoading;
public override void OnUnload()
{
base.OnUnload();
Users = null;
}
private Image GetUserCardViewImage(int column, CornerMask masks, string source, string parameter)
{
Image image;
if (masks == CornerMask.None)
{
image = new Image();
}
else
{
image = new RoundImage
{
CornerRadius = 10,
CornerMasks = masks
};
}
image.HorizontalOptions = LayoutOptions.Fill;
image.Aspect = Aspect.AspectFill;
image.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = commandIllustImageTapped
}
.Binding(TapGestureRecognizer.CommandParameterProperty, parameter));
image.SetBinding(Image.SourceProperty, source);
if (column > 0)
{
Grid.SetColumn(image, column);
}
Grid.SetRow(image, 1);
return image;
}
private DataTemplate GetUserCardViewTemplate()
{
return new DataTemplate(() =>
{
return new Grid
{
RowSpacing = 0,
ColumnSpacing = 0,
RowDefinitions =
{
new RowDefinition { Height = 40 },
new RowDefinition { Height = 120 }
},
ColumnDefinitions =
{
new ColumnDefinition(),
new ColumnDefinition(),
new ColumnDefinition()
},
Children =
{
// stacklayout: user
new Grid
{
ColumnDefinitions =
{
new ColumnDefinition { Width = 30 },
new ColumnDefinition()
},
Padding = new Thickness(8, 0, 8, 8),
Children =
{
// user icon
new CircleImage
{
WidthRequest = 30,
HeightRequest = 30,
Aspect = Aspect.AspectFill
}
.Binding(Image.SourceProperty, nameof(IllustUserItem.ProfileImage)),
// user name
new Label
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.Center,
LineBreakMode = LineBreakMode.TailTruncation,
FontSize = StyleDefinition.FontSizeSmall
}
.Binding(Label.TextProperty, nameof(IllustUserItem.UserName))
.DynamicResource(Label.TextColorProperty, ThemeBase.SubTextColor)
.GridColumn(1),
},
GestureRecognizers =
{
new TapGestureRecognizer
{
Command = commandUserTapped
}
.Binding(TapGestureRecognizer.CommandParameterProperty, ".")
}
}
.GridColumnSpan(3),
GetUserCardViewImage(0, CornerMask.Left,
$"{nameof(IllustUserItem.Image1Item)}.{nameof(IllustItem.Image)}",
nameof(IllustUserItem.Image1Item)),
GetUserCardViewImage(1, CornerMask.None,
$"{nameof(IllustUserItem.Image2Item)}.{nameof(IllustItem.Image)}",
nameof(IllustUserItem.Image2Item)),
GetUserCardViewImage(2, CornerMask.Right,
$"{nameof(IllustUserItem.Image3Item)}.{nameof(IllustItem.Image)}",
nameof(IllustUserItem.Image3Item))
}
};
});
}
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
int columns;
if (width > height)
{
columns = isPhone ? 2 : 3;
}
else
{
columns = isPhone ? 1 : 2;
}
if (UserColumns != columns)
{
UserColumns = columns;
#if DEBUG
App.DebugPrint($"change user columns to {columns}");
#endif
}
}
protected override void DoIllustsLoaded(IllustCollection collection, bool bottom)
{
//IsLoading = false;
if (illustData != null)
{
IllustCollection = collection;
Task.Run(() => DoLoadUserRecommendsData(illustData));
}
else
{
base.DoIllustsLoaded(collection, bottom);
}
}
protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data, out int tag)
{
tag = 0;
if (data.body == null)
{
return null;
}
return data.body.page.recommend.ids.Select(id =>
data.body.thumbnails.illust.FirstOrDefault(l => (l.illustId ?? l.id) == id)?.ConvertToItem());
}
protected override IllustData DoLoadIllustData(bool force)
{
illustData = Stores.LoadIllustData(force);
return illustData;
}
private void DoLoadUserRecommendsData(IllustData data)
{
var r18 = Configs.IsOnR18;
var defaultImage = StyleDefinition.DownloadBackground;
var users = data.body.page.recommendUser.Select(u =>
{
var usrId = u.id.ToString();
var usr = data.body.users.FirstOrDefault(r => r.userId == usrId);
if (usr == null)
{
return null;
}
IllustItem item1 = null, item2 = null, item3 = null;
if (u.illustIds != null)
{
var length = u.illustIds.Length;
if (length > 0)
{
var id = u.illustIds[0];
item1 = data.body.thumbnails.illust.FirstOrDefault(l => (l.illustId ?? l.id) == id)?.ConvertToItem(defaultImage);
}
if (length > 1)
{
var id = u.illustIds[1];
item2 = data.body.thumbnails.illust.FirstOrDefault(l => (l.illustId ?? l.id) == id)?.ConvertToItem(defaultImage);
}
if (length > 2)
{
var id = u.illustIds[2];
item3 = data.body.thumbnails.illust.FirstOrDefault(l => (l.illustId ?? l.id) == id)?.ConvertToItem(defaultImage);
}
}
if (!r18)
{
if (item1?.IsRestrict == true ||
item2?.IsRestrict == true ||
item3?.IsRestrict == true)
{
return null;
}
}
return new IllustUserItem
{
UserId = usrId,
UserName = usr.name,
ProfileUrl = usr.image,
Image1Item = item1,
Image2Item = item2,
Image3Item = item3
};
}).Where(u => u != null);
var list = new List<IllustUserItem>(users);
activityLoading.Animate("margin", top =>
{
activityLoading.Margin = new Thickness(0, top, 0, 0);
},
16, -40, easing: Easing.CubicIn, finished: (v, r) =>
{
IsLoading = false;
UserRecommendsVisible = list.Count > 0;
#if __IOS__
Device.StartTimer(TimeSpan.FromMilliseconds(48), () =>
#else
Device.StartTimer(TimeSpan.FromMilliseconds(150), () =>
#endif
{
Users = list;
Illusts = IllustCollection;
return false;
});
});
DoLoadUserRecommendsImages(list);
}
private void DoLoadUserRecommendsImages(List<IllustUserItem> users)
{
foreach (var user in users)
{
if (user.ProfileUrl != null)
{
var userImage = Stores.LoadUserProfileImage(user.ProfileUrl, true);
if (userImage != null)
{
user.ProfileImage = userImage;
}
}
Task.WaitAll(
Task.Run(() => DoLoadUserRecommendsImage(user.Image1Item)),
Task.Run(() => DoLoadUserRecommendsImage(user.Image2Item)),
Task.Run(() => DoLoadUserRecommendsImage(user.Image3Item)));
}
}
private void DoLoadUserRecommendsImage(IllustItem illust)
{
if (illust.ImageUrl != null)
{
var url = Configs.GetThumbnailUrl(illust.ImageUrl);
var image = Stores.LoadPreviewImage(url, false);
if (image == null)
{
image = Stores.LoadThumbnailImage(url, true);
}
if (image != null)
{
illust.Image = image;
}
}
}
private async void Refresh_Clicked(object sender, EventArgs e)
{
if (IsLoading)
{
return;
}
await ScrollToTopAsync(scrollView);
StartLoad(true);
}
}
public class IllustUserItem : BindableObject, IIllustItem
{
//public static readonly BindableProperty Image1Property = BindableProperty.Create(
// nameof(Image1), typeof(ImageSource), typeof(IllustUserItem));
public static readonly BindableProperty ProfileImageProperty = BindableProperty.Create(
nameof(ProfileImage), typeof(ImageSource), typeof(IllustUserItem));
//public ImageSource Image1
//{
// get => (ImageSource)GetValue(Image1Property);
// set => SetValue(Image1Property, value);
//}
public ImageSource ProfileImage
{
get => (ImageSource)GetValue(ProfileImageProperty);
set => SetValue(ProfileImageProperty, value);
}
public string UserId { get; set; }
public string UserName { get; set; }
public IllustItem Image1Item { get; set; }
public IllustItem Image2Item { get; set; }
public IllustItem Image3Item { get; set; }
public string ProfileUrl { get; set; }
public bool IsFavorite { get; }
public string BookmarkId { get; }
}
}