feature: view related illusts
This commit is contained in:
parent
29fd8e9667
commit
3a80c0826b
@ -42,7 +42,7 @@
|
||||
<AndroidManagedSymbols>true</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
<AndroidCreatePackagePerAbi>true</AndroidCreatePackagePerAbi>
|
||||
<AndroidSupportedAbis>arm64-v8a</AndroidSupportedAbis>
|
||||
<AndroidSupportedAbis>arm64-v8a;armeabi-v7a</AndroidSupportedAbis>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android" />
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
}
|
||||
|
26
Pixiview/Illust/RelatedIllustsPage.xaml
Normal file
26
Pixiview/Illust/RelatedIllustsPage.xaml
Normal 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>
|
92
Pixiview/Illust/RelatedIllustsPage.xaml.cs
Normal file
92
Pixiview/Illust/RelatedIllustsPage.xaml.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -42,6 +42,10 @@
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Resources\Languages\zh-CN.xml" />
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Illust\RelatedIllustsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)App.cs" />
|
||||
@ -93,6 +97,9 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)UI\BlurryPanel.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Utils\IllustLegacy.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Utils\HttpUtility.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Illust\RelatedIllustsPage.xaml.cs">
|
||||
<DependentUpon>RelatedIllustsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="$(MSBuildThisFileDirectory)Illust\" />
|
||||
|
@ -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<IllustPageBody[]> { }
|
||||
public class IllustPageBody
|
||||
{
|
||||
@ -234,6 +234,13 @@ namespace Pixiview.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public class IllustRecommendsData : IllustResponse<IllustRecommendsBody> { }
|
||||
public class IllustRecommendsBody
|
||||
{
|
||||
public Illust[] illusts;
|
||||
public string[] nextIds;
|
||||
}
|
||||
|
||||
public class IllustUserListData : IllustResponse<IllustUserListBody> { }
|
||||
public class IllustUserListBody
|
||||
{
|
||||
|
@ -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<IllustRecommendsData>(
|
||||
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<IllustRecommendsData>(
|
||||
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";
|
||||
|
Loading…
x
Reference in New Issue
Block a user