feature: view related illusts

This commit is contained in:
2020-05-14 22:22:16 +08:00
parent 29fd8e9667
commit 3a80c0826b
13 changed files with 278 additions and 70 deletions

View File

@@ -14,8 +14,9 @@ namespace Pixiview.Illust
{
public abstract class FavoriteIllustCollectionPage : IllustCollectionPage<IllustItem[]> { }
public abstract class IllustDataCollectionPage : IllustCollectionPage<IllustData> { }
public abstract class IllustRankingDataCollectionPage : IllustCollectionPage<IllustRankingData> { }
public abstract class IllustUserDataCollectionPage : IllustCollectionPage<IllustUserData> { }
public abstract class IllustRankingDataCollectionPage : IllustScrollableCollectionPage<IllustRankingData> { }
public abstract class IllustRecommendsCollectionPage : IllustScrollableCollectionPage<IllustRecommendsData> { }
public interface IIllustCollectionPage
{
@@ -499,6 +500,68 @@ namespace Pixiview.Illust
#endregion
}
public abstract class IllustScrollableCollectionPage<T> : IllustCollectionPage<T>
{
protected const int SCROLL_OFFSET = 33;
protected static readonly object sync = new object();
private double lastScrollY = double.MinValue;
private double offset;
protected bool ScrollingDown(double y)
{
return y > lastScrollY;
}
protected void SetOffset(double off)
{
offset = off;
}
protected abstract bool CheckRefresh();
protected override void DoIllustsLoaded(IllustCollection collection)
{
var now = IllustCollection;
if (now == null)
{
IllustCollection = collection;
Illusts = collection;
}
else
{
now = new IllustCollection(now.Concat(collection));
IllustCollection = now;
Illusts = now;
}
}
protected void OnScrolled(double y)
{
lastScrollY = y;
if (y > 0 && offset > 0 && y - topOffset > offset)
{
bool refresh = false;
lock (sync)
{
if (IsLoading)
{
return;
}
if (CheckRefresh())
{
refresh = true;
}
}
if (refresh)
{
App.DebugPrint("start to load next page");
StartLoad(true);
}
}
}
}
public enum ScrollDirection
{
Stop,

View File

@@ -37,6 +37,10 @@ namespace Pixiview.Illust
protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data)
{
if (data.body == null)
{
return null;
}
return data.body.page.follow.Select(i =>
data.body.thumbnails.illust.FirstOrDefault(l => l.illustId == i.ToString())?.ConvertToItem());
}

View File

@@ -50,7 +50,7 @@
HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
<u:FlowLayout ItemsSource="{Binding Illusts}" MaxHeightChanged="FlowLayout_MaxHeightChanged"
HorizontalOptions="Fill" Column="{Binding Columns}"
Margin="16, 16, 16, 16" RowSpacing="16" ColumnSpacing="16"
Margin="16" RowSpacing="16" ColumnSpacing="16"
ItemTemplate="{StaticResource cardView}"/>
</ScrollView>
<u:BlurryPanel x:Name="panelFilter" VerticalOptions="Start" Opacity="0"

View File

@@ -13,7 +13,6 @@ namespace Pixiview.Illust
public partial class RankingPage : IllustRankingDataCollectionPage
{
private static readonly string[] segmentDates = { "daily", "weekly", "monthly", "male" };
private static readonly object sync = new object();
public static readonly BindableProperty SegmentDateProperty = BindableProperty.Create(
nameof(SegmentDate), typeof(int), typeof(RankingPage), propertyChanged: OnSegmentDatePropertyChanged);
@@ -77,11 +76,9 @@ namespace Pixiview.Illust
}
public Command<string> ToolbarCommand { get; private set; }
private double lastScrollY = double.MinValue;
private bool previousEnabled;
private bool dateEnabled;
private bool nextEnabled;
private double offset;
private bool isFilterVisible;
private string lastQueryKey;
@@ -111,8 +108,6 @@ namespace Pixiview.Illust
currentPage = 1;
datePicker.MinimumDate = new DateTime(2007, 9, 13);
MaximumDate = DateTime.Now;
App.DebugPrint("page loaded.");
}
protected override void OnDisappearing()
@@ -128,30 +123,6 @@ namespace Pixiview.Illust
}
}
private void FlowLayout_MaxHeightChanged(object sender, HeightEventArgs e)
{
if (e.ContentHeight > 0)
{
offset = e.ContentHeight - scrollView.Bounds.Height - 33;
}
}
protected override void DoIllustsLoaded(IllustCollection collection)
{
var now = IllustCollection;
if (now == null)
{
IllustCollection = collection;
Illusts = collection;
}
else
{
now = new IllustCollection(now.Concat(collection));
IllustCollection = now;
Illusts = now;
}
}
protected override IEnumerable<IllustItem> DoGetIllustList(IllustRankingData data)
{
return data.contents.Select(i => i.ConvertToItem());
@@ -162,10 +133,6 @@ namespace Pixiview.Illust
var data = Stores.LoadIllustRankingData(lastQueryKey, queryDate, currentPage, force);
if (data != null)
{
//if (data.contents.Length * data.page < data.rank_total)
//{
// nextPage = currentPage + 1;
//}
if (int.TryParse(data.next, out int next))
{
nextPage = next;
@@ -330,10 +297,29 @@ namespace Pixiview.Illust
ToggleFilterPanel(!isFilterVisible);
}
private void FlowLayout_MaxHeightChanged(object sender, HeightEventArgs e)
{
if (e.ContentHeight > 0)
{
SetOffset(e.ContentHeight - scrollView.Bounds.Height - SCROLL_OFFSET);
}
}
protected override bool CheckRefresh()
{
if (nextPage == currentPage + 1)
{
currentPage = nextPage;
App.DebugPrint($"loading page {nextPage}");
return true;
}
return false;
}
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
var y = e.ScrollY;
if (y > lastScrollY)
if (ScrollingDown(y))
{
// down
if (isFilterVisible)
@@ -341,31 +327,7 @@ namespace Pixiview.Illust
ToggleFilterPanel(false);
}
}
lastScrollY = y;
if (y > 0 && offset > 0 && y - topOffset > offset)
{
bool refresh = false;
lock (sync)
{
if (IsLoading)
{
return;
}
App.DebugPrint("bottom arrived.");
if (nextPage == currentPage + 1)
{
currentPage = nextPage;
refresh = true;
App.DebugPrint($"loading page {nextPage}");
}
}
if (refresh)
{
App.DebugPrint($"start to load page {nextPage}");
StartLoad(true);
}
}
OnScrolled(y);
}
private void Filter_Clicked(object sender, EventArgs e)

View File

@@ -183,6 +183,10 @@ namespace Pixiview.Illust
protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data)
{
if (data.body == null)
{
return null;
}
return data.body.page.recommend.Select(id =>
data.body.thumbnails.illust.FirstOrDefault(l => l.illustId == id)?.ConvertToItem());
}

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<i:IllustRecommendsCollectionPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:i="clr-namespace:Pixiview.Illust"
xmlns:u="clr-namespace:Pixiview.UI"
xmlns:r="clr-namespace:Pixiview.Resources"
x:Class="Pixiview.Illust.RelatedIllustsPage"
Title="{r:Text RelatedIllusts}"
BackgroundColor="{DynamicResource WindowColor}">
<Grid>
<ScrollView x:Name="scrollView" Scrolled="ScrollView_Scrolled"
HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
<u:FlowLayout ItemsSource="{Binding Illusts}" MaxHeightChanged="FlowLayout_MaxHeightChanged"
HorizontalOptions="Fill" Column="{Binding Columns}"
Margin="16" RowSpacing="16" ColumnSpacing="16"
ItemTemplate="{StaticResource cardView}"/>
</ScrollView>
<Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
IsVisible="{Binding IsLoading}"
HorizontalOptions="Center" VerticalOptions="Center"
BackgroundColor="{DynamicResource MaskColor}">
<ActivityIndicator IsRunning="True" IsVisible="True"
Color="{DynamicResource WindowColor}"/>
</Frame>
</Grid>
</i:IllustRecommendsCollectionPage>

View File

@@ -0,0 +1,92 @@
using System.Collections.Generic;
using System.Linq;
using Pixiview.UI;
using Pixiview.Utils;
using Xamarin.Forms;
namespace Pixiview.Illust
{
public partial class RelatedIllustsPage : IllustRecommendsCollectionPage
{
private readonly IllustItem illustItem;
private int startIndex;
private int nextIndex;
private string[] illustIds;
public RelatedIllustsPage(IllustItem item)
{
illustItem = item;
Resources.Add("cardView", GetCardViewTemplate());
InitializeComponent();
startIndex = -1;
nextIndex = 0;
}
protected override IEnumerable<IllustItem> DoGetIllustList(IllustRecommendsData data)
{
if (data.body == null)
{
return null;
}
return data.body.illusts.Select(i => i.ConvertToItem());
}
protected override IllustRecommendsData DoLoadIllustData(bool force)
{
IllustRecommendsData data;
if (startIndex < 0)
{
// init
data = Stores.LoadIllustRecommendsInitData(illustItem.Id, force);
if (data == null || data.body == null)
{
return null;
}
illustIds = data.body.nextIds;
}
else
{
if (illustIds == null || startIndex >= illustIds.Length)
{
return null;
}
var ids = illustIds.Skip(startIndex).Take(18).ToArray();
nextIndex = startIndex + ids.Length;
if (ids.Length == 0 || nextIndex >= illustIds.Length)
{
// done
App.DebugPrint($"download completed: {startIndex}");
return null;
}
data = Stores.LoadIllustRecommendsListData(illustItem.Id, ids);
}
return data;
}
private void FlowLayout_MaxHeightChanged(object sender, HeightEventArgs e)
{
if (e.ContentHeight > 0)
{
SetOffset(e.ContentHeight - scrollView.Bounds.Height - SCROLL_OFFSET);
}
}
protected override bool CheckRefresh()
{
if (nextIndex > startIndex)
{
startIndex = nextIndex;
return true;
}
return false;
}
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
var y = e.ScrollY;
OnScrolled(y);
}
}
}

View File

@@ -30,6 +30,10 @@ namespace Pixiview.Illust
protected override IEnumerable<IllustItem> DoGetIllustList(IllustUserData data)
{
if (data.body == null)
{
return null;
}
return data.body.works.Select(i => i.Value?.ConvertToItem());
}

View File

@@ -509,9 +509,11 @@ namespace Pixiview.Illust
{
extras.Add(share);
}
var saveOriginal = ResourceHelper.SaveOriginal;
var userDetail = ResourceHelper.UserDetail;
extras.Add(userDetail);
var related = ResourceHelper.RelatedIllusts;
extras.Add(related);
var saveOriginal = ResourceHelper.SaveOriginal;
var illustItem = IllustItem;
var result = await DisplayActionSheet(
@@ -536,6 +538,11 @@ namespace Pixiview.Illust
var page = new UserIllustPage(illustItem);
await Navigation.PushAsync(page);
}
else if (result == related)
{
var page = new RelatedIllustsPage(illustItem);
await Navigation.PushAsync(page);
}
}
private async void SaveOriginalImage(IllustDetailItem item)