From 3a80c0826b4dd9a4f489c9a5bb64efd275808507 Mon Sep 17 00:00:00 2001 From: Tsanie Lily Date: Thu, 14 May 2020 22:22:16 +0800 Subject: [PATCH] feature: view related illusts --- Pixiview.Android/Pixiview.Android.csproj | 2 +- Pixiview/Illust/IllustCollectionPage.cs | 65 ++++++++++++++- Pixiview/Illust/MainPage.xaml.cs | 4 + Pixiview/Illust/RankingPage.xaml | 2 +- Pixiview/Illust/RankingPage.xaml.cs | 80 +++++-------------- Pixiview/Illust/RecommendsPage.xaml.cs | 4 + Pixiview/Illust/RelatedIllustsPage.xaml | 26 ++++++ Pixiview/Illust/RelatedIllustsPage.xaml.cs | 92 ++++++++++++++++++++++ Pixiview/Illust/UserIllustPage.xaml.cs | 4 + Pixiview/Illust/ViewIllustPage.xaml.cs | 9 ++- Pixiview/Pixiview.projitems | 7 ++ Pixiview/Utils/IllustData.cs | 17 ++-- Pixiview/Utils/Stores.cs | 36 ++++++++- 13 files changed, 278 insertions(+), 70 deletions(-) create mode 100644 Pixiview/Illust/RelatedIllustsPage.xaml create mode 100644 Pixiview/Illust/RelatedIllustsPage.xaml.cs 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";