diff --git a/Pixiview.Android/Pixiview.Android.csproj b/Pixiview.Android/Pixiview.Android.csproj
index 488a753..b7f1a43 100644
--- a/Pixiview.Android/Pixiview.Android.csproj
+++ b/Pixiview.Android/Pixiview.Android.csproj
@@ -42,7 +42,7 @@
true
false
true
- arm64-v8a
+ arm64-v8a;armeabi-v7a
diff --git a/Pixiview/Illust/IllustCollectionPage.cs b/Pixiview/Illust/IllustCollectionPage.cs
index d47fc14..2336c97 100644
--- a/Pixiview/Illust/IllustCollectionPage.cs
+++ b/Pixiview/Illust/IllustCollectionPage.cs
@@ -14,8 +14,9 @@ namespace Pixiview.Illust
{
public abstract class FavoriteIllustCollectionPage : IllustCollectionPage { }
public abstract class IllustDataCollectionPage : IllustCollectionPage { }
- public abstract class IllustRankingDataCollectionPage : IllustCollectionPage { }
public abstract class IllustUserDataCollectionPage : IllustCollectionPage { }
+ public abstract class IllustRankingDataCollectionPage : IllustScrollableCollectionPage { }
+ public abstract class IllustRecommendsCollectionPage : IllustScrollableCollectionPage { }
public interface IIllustCollectionPage
{
@@ -499,6 +500,68 @@ namespace Pixiview.Illust
#endregion
}
+ public abstract class IllustScrollableCollectionPage : IllustCollectionPage
+ {
+ 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,
diff --git a/Pixiview/Illust/MainPage.xaml.cs b/Pixiview/Illust/MainPage.xaml.cs
index ea96fe2..d52de59 100644
--- a/Pixiview/Illust/MainPage.xaml.cs
+++ b/Pixiview/Illust/MainPage.xaml.cs
@@ -37,6 +37,10 @@ namespace Pixiview.Illust
protected override IEnumerable 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());
}
diff --git a/Pixiview/Illust/RankingPage.xaml b/Pixiview/Illust/RankingPage.xaml
index d181b7a..4ada51a 100644
--- a/Pixiview/Illust/RankingPage.xaml
+++ b/Pixiview/Illust/RankingPage.xaml
@@ -50,7 +50,7 @@
HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
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 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)
diff --git a/Pixiview/Illust/RecommendsPage.xaml.cs b/Pixiview/Illust/RecommendsPage.xaml.cs
index 71abb67..3a9014b 100644
--- a/Pixiview/Illust/RecommendsPage.xaml.cs
+++ b/Pixiview/Illust/RecommendsPage.xaml.cs
@@ -183,6 +183,10 @@ namespace Pixiview.Illust
protected override IEnumerable 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());
}
diff --git a/Pixiview/Illust/RelatedIllustsPage.xaml b/Pixiview/Illust/RelatedIllustsPage.xaml
new file mode 100644
index 0000000..4653544
--- /dev/null
+++ b/Pixiview/Illust/RelatedIllustsPage.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Pixiview/Illust/RelatedIllustsPage.xaml.cs b/Pixiview/Illust/RelatedIllustsPage.xaml.cs
new file mode 100644
index 0000000..151c299
--- /dev/null
+++ b/Pixiview/Illust/RelatedIllustsPage.xaml.cs
@@ -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 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);
+ }
+ }
+}
diff --git a/Pixiview/Illust/UserIllustPage.xaml.cs b/Pixiview/Illust/UserIllustPage.xaml.cs
index 8a70df2..2051184 100644
--- a/Pixiview/Illust/UserIllustPage.xaml.cs
+++ b/Pixiview/Illust/UserIllustPage.xaml.cs
@@ -30,6 +30,10 @@ namespace Pixiview.Illust
protected override IEnumerable DoGetIllustList(IllustUserData data)
{
+ if (data.body == null)
+ {
+ return null;
+ }
return data.body.works.Select(i => i.Value?.ConvertToItem());
}
diff --git a/Pixiview/Illust/ViewIllustPage.xaml.cs b/Pixiview/Illust/ViewIllustPage.xaml.cs
index bda3188..0d31c46 100644
--- a/Pixiview/Illust/ViewIllustPage.xaml.cs
+++ b/Pixiview/Illust/ViewIllustPage.xaml.cs
@@ -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)
diff --git a/Pixiview/Pixiview.projitems b/Pixiview/Pixiview.projitems
index e5f73a2..2d237e4 100644
--- a/Pixiview/Pixiview.projitems
+++ b/Pixiview/Pixiview.projitems
@@ -42,6 +42,10 @@
MSBuild:UpdateDesignTimeXaml
+
+ Designer
+ MSBuild:UpdateDesignTimeXaml
+
@@ -93,6 +97,9 @@
+
+ RelatedIllustsPage.xaml
+
diff --git a/Pixiview/Utils/IllustData.cs b/Pixiview/Utils/IllustData.cs
index 8ff2985..c3eb02c 100644
--- a/Pixiview/Utils/IllustData.cs
+++ b/Pixiview/Utils/IllustData.cs
@@ -208,16 +208,16 @@ namespace Pixiview.Utils
public string userId;
public IllustTranslate translation;
public string userName;
+
+ public class IllustTranslate
+ {
+ public string en;
+ }
}
}
}
}
- public class IllustTranslate
- {
- public string en;
- }
-
public class IllustPageData : IllustResponse { }
public class IllustPageBody
{
@@ -234,6 +234,13 @@ namespace Pixiview.Utils
}
}
+ public class IllustRecommendsData : IllustResponse { }
+ public class IllustRecommendsBody
+ {
+ public Illust[] illusts;
+ public string[] nextIds;
+ }
+
public class IllustUserListData : IllustResponse { }
public class IllustUserListBody
{
diff --git a/Pixiview/Utils/Stores.cs b/Pixiview/Utils/Stores.cs
index 7b24632..266fde4 100644
--- a/Pixiview/Utils/Stores.cs
+++ b/Pixiview/Utils/Stores.cs
@@ -30,6 +30,7 @@ namespace Pixiview.Utils
private const string preloadsFolder = "preloads";
private const string thumbFolder = "img-thumb";
private const string userFolder = "user-profile";
+ private const string recommendsFolder = "recommends";
private static readonly object sync = new object();
@@ -212,7 +213,7 @@ namespace Pixiview.Utils
public static IllustRankingData LoadIllustRankingData(string mode, string date, int page, bool force = false)
{
- var file = Path.Combine(CacheFolder, $"{mode}_{date}_{page}.json");
+ var file = Path.Combine(CacheFolder, mode, $"{date}_{page}.json");
string query = $"mode={mode}";
if (mode != "male" && mode != "male_r18")
{
@@ -234,7 +235,7 @@ namespace Pixiview.Utils
referer,
namehandler: rst =>
{
- return Path.Combine(CacheFolder, $"{mode}_{rst.date}_{page}.json");
+ return Path.Combine(CacheFolder, mode, $"{rst.date}_{page}.json");
},
header: headers =>
{
@@ -248,6 +249,35 @@ namespace Pixiview.Utils
return result;
}
+ public static IllustRecommendsData LoadIllustRecommendsInitData(string id, bool force = false)
+ {
+ var file = Path.Combine(CacheFolder, recommendsFolder, $"{id}.json");
+ var result = HttpUtility.LoadObject(
+ file,
+ string.Format(Configs.UrlIllustRecommendsInit, id),
+ string.Format(Configs.RefererIllust, id),
+ force: force);
+ if (result == null || result.error)
+ {
+ App.DebugPrint($"error when load recommends init data: {result?.message}, force({force})");
+ }
+ return result;
+ }
+
+ public static IllustRecommendsData LoadIllustRecommendsListData(string id, string[] ids)
+ {
+ var ps = string.Concat(ids.Select(i => $"illust_ids%5B%5D={i}&"));
+ var result = HttpUtility.LoadObject(
+ null,
+ string.Format(Configs.UrlIllustRecommendsList, ps),
+ string.Format(Configs.RefererIllust, id));
+ if (result == null || result.error)
+ {
+ App.DebugPrint($"error when load recommends list data: {result?.message}");
+ }
+ return result;
+ }
+
public static IllustPreloadBody LoadIllustPreloadData(string id, bool force = false)
{
var file = Path.Combine(CacheFolder, preloadsFolder, $"{id}.json");
@@ -431,6 +461,8 @@ namespace Pixiview.Utils
public static string UrlIllustUserArtworks => Prefix + "ajax/user/{0}/profile/illusts?{1}work_category=illustManga&is_first_page={2}&lang=zh";
public static string UrlIllustPage => Prefix + "ajax/illust/{0}/pages?lang=zh";
public static string UrlIllustUgoira => Prefix + "ajax/illust/{0}/ugoira_meta?lang=zh";
+ public static string UrlIllustRecommendsInit => Prefix + "ajax/illust/{0}/recommend/init?limit=18&lang=zh";
+ public static string UrlIllustRecommendsList => Prefix + "ajax/illust/recommend/illusts?{0}lang=zh";
public const string UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36";
public const string AcceptImage = "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5";
public const string AcceptJson = "application/json";