feature: sync online favorites

This commit is contained in:
Tsanie Lily 2020-05-18 21:36:59 +08:00
parent d6c235d6ef
commit 508bab3395
6 changed files with 215 additions and 9 deletions

View File

@ -191,7 +191,7 @@ namespace Pixiview
var distinct = favObj.Illusts.Where(f => !list.Any(i => i.Id == f.Id)).ToList();
list.InsertRange(0, distinct);
favNow.Illusts = list;
//favNow.Illusts = list;
Stores.SaveFavoritesIllusts();
}

View File

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Pixiview.Resources;
using Pixiview.UI;
using Pixiview.Utils;
using Xamarin.Essentials;
using Xamarin.Forms;
@ -81,9 +84,105 @@ namespace Pixiview.Illust
return;
}
await ScrollToTopAsync(scrollView);
flag = false;
lastUpdated = default;
StartLoad(true);
IsLoading = true;
var offset = 16 - IndicatorMarginTop;
activityLoading.Margin = new Thickness(0, loadingOffset - offset, 0, offset);
activityLoading.Animate("margin", top =>
{
activityLoading.Margin = new Thickness(0, top, 0, offset);
},
loadingOffset - offset, 16 - offset, easing: Easing.CubicOut, finished: (v, r) =>
{
Task.Run(() =>
{
var list = Stores.LoadOnlineFavorites();
if (list != null && list.Length > 0)
{
MainThread.BeginInvokeOnMainThread(() => ConfirmNext(list));
}
else
{
flag = false;
lastUpdated = default;
MainThread.BeginInvokeOnMainThread(() => StartLoad(true));
}
});
});
}
private async void ConfirmNext(IllustItem[] list)
{
var cancel = ResourceHelper.Cancel;
var combine = ResourceHelper.FavoritesCombine;
var replace = ResourceHelper.FavoritesReplace;
var result = await DisplayActionSheet(
ResourceHelper.FavoritesOperation,
cancel,
combine,
replace);
if (result == cancel)
{
return;
}
if (result == replace)
{
Stores.GetFavoriteObject().Illusts = new FavoriteList(list);
}
else if (result == combine)
{
// combine
var favNow = Stores.GetFavoriteObject();
var nows = favNow.Illusts;
list = list.Where(f => !nows.Any(i => i.Id == f.Id)).ToArray();
for (var i = 0; i < list.Length; i++)
{
list[i].Image = StyleDefinition.DownloadBackground;
}
nows.InsertRange(0, list);
}
else
{
return;
}
ParallelTask.Start(0, list.Length, Configs.MaxPageThreads, i =>
{
var illustItem = list[i];
var data = Stores.LoadIllustPreloadData(illustItem.Id);
if (data != null && data.illust.TryGetValue(illustItem.Id, out var illust))
{
illust.CopyToItem(illustItem);
if (data.user.TryGetValue(illust.userId, out var user))
{
illustItem.ProfileUrl = user.image;
}
return true;
}
App.DebugError("load.favorite", $"cannot fetch preload data, {illustItem.Id}, disposed.");
return false;
}, () =>
{
Stores.SaveFavoritesIllusts();
MainThread.BeginInvokeOnMainThread(() =>
{
var offset = 16 - IndicatorMarginTop;
activityLoading.Animate("margin", top =>
{
activityLoading.Margin = new Thickness(0, top, 0, offset);
},
16 - offset, loadingOffset - offset, easing: Easing.CubicIn, finished: (v, r) =>
{
IsLoading = false;
flag = false;
lastUpdated = default;
StartLoad();
});
});
});
}
private async void ShareFavorites_Clicked(object sender, EventArgs e)

View File

@ -514,6 +514,11 @@ namespace Pixiview.Illust
}
else
{
var item = favorites[index];
if (illust.BookmarkId == null && item.BookmarkId != null)
{
illust.BookmarkId = item.BookmarkId;
}
illust.IsFavorite = false;
favorites.RemoveAt(index);
FavoriteIcon = fontIconNotLove;

View File

@ -95,13 +95,13 @@ namespace Pixiview.Utils
public class ParallelTask : IDisposable
{
public static ParallelTask Start(int from, int toExclusive, int maxCount, Predicate<int> action)
public static ParallelTask Start(int from, int toExclusive, int maxCount, Predicate<int> action, Action complete = null)
{
if (toExclusive <= from)
{
return null;
}
var task = new ParallelTask(from, toExclusive, maxCount, action);
var task = new ParallelTask(from, toExclusive, maxCount, action, complete);
Task.Run(task.Start);
return task;
}
@ -114,8 +114,9 @@ namespace Pixiview.Utils
private readonly int from;
private readonly int to;
private readonly Predicate<int> action;
private readonly Action complete;
private ParallelTask(int from, int to, int maxCount, Predicate<int> action)
private ParallelTask(int from, int to, int maxCount, Predicate<int> action, Action complete)
{
if (maxCount <= 0)
{
@ -129,6 +130,7 @@ namespace Pixiview.Utils
this.from = from;
this.to = to;
this.action = action;
this.complete = complete;
}
private void Start()
@ -182,6 +184,7 @@ namespace Pixiview.Utils
});
}
App.DebugPrint($"parallel task done");
complete?.Invoke();
}
public void Dispose()

View File

@ -17,7 +17,8 @@ namespace Pixiview.Utils
HttpContent post = null,
Action<HttpRequestHeaders> header = null,
Func<T, string> namehandler = null,
Func<string, string> action = null)
Func<string, string> action = null,
Func<string, T> @return = null)
{
string content = null;
if (post == null && !force && file != null && File.Exists(file))
@ -89,6 +90,11 @@ namespace Pixiview.Utils
{
content = action(content);
}
if (@return != null)
{
error = null;
return @return(content);
}
}
catch (Exception ex)
{

View File

@ -5,6 +5,7 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Pixiview.Illust;
using Xamarin.Essentials;
@ -478,6 +479,94 @@ namespace Pixiview.Utils
return result;
}
private static readonly Regex regexIllust = new Regex(
@"book_id\[\]"" value=""([0-9]+)"".*data-src=""([^""]+)"".*data-id=""([0-9]+)"".*" +
@"data-tags=""([^""]+)"".*data-user-id=""([0-9]+)"".*" +
@"class=""title"" title=""([^""]+)"".*data-user_name=""([^""]+)"".*" +
@"_bookmark-icon-inline""></i>([0-9]+)</a>",
RegexOptions.Compiled);
public static IllustItem[] LoadOnlineFavorites()
{
var list = new List<IllustItem>();
int p = 1;
while (p > 0)
{
var url = Configs.UrlFavoriteList;
if (p > 1)
{
url += $"&p={p}";
}
var array = HttpUtility.LoadObject(
null,
url,
null,
out _,
action: content =>
{
// page
p = -1;
var index = content.IndexOf("<span class=\"next\"><a href=\"?rest=show&amp;p=");
if (index > 0)
{
var page = content.Substring(index + 45, content.IndexOf('\"', index + 45) - index - 45);
if (int.TryParse(page, out var next))
{
p = next;
}
}
// list
index = content.IndexOf("<li class=\"image-item\">");
if (index < 0)
{
return null;
}
content = content.Substring(index + 23);
index = content.IndexOf("</li></ul><div class=\"clear\"></div>");
if (index < 0)
{
return null;
}
return content.Substring(0, index);
},
@return: content =>
{
if (content == null)
{
return null;
}
var lines = content.Split("</li><li class=\"image-item\">");
var illusts = new IllustItem[lines.Length];
for (var i = 0; i < illusts.Length; i++)
{
var line = lines[i];
var m = regexIllust.Match(line);
if (m.Success)
{
illusts[i] = new IllustItem
{
IsFavorite = true,
BookmarkId = m.Groups[1].Value,
ImageUrl = m.Groups[2].Value,
Id = m.Groups[3].Value,
Tags = m.Groups[4].Value.Split(' '),
UserId = m.Groups[5].Value,
Title = m.Groups[6].Value,
UserName = m.Groups[7].Value,
RatingCount = int.Parse(m.Groups[8].Value)
};
}
}
return illusts;
});
if (array != null && array.Length > 0)
{
list.AddRange(array);
}
}
return list.ToArray();
}
public static ImageSource LoadIllustImage(string url)
{
return LoadImage(url, PersonalFolder, imageFolder);
@ -561,6 +650,9 @@ namespace Pixiview.Utils
{
public bool Changed { get; private set; }
public FavoriteList() : base() { }
public FavoriteList(IEnumerable<IllustItem> collection) : base(collection) { }
public new void Insert(int index, IllustItem item)
{
base.Insert(index, item);
@ -603,7 +695,7 @@ namespace Pixiview.Utils
public const string QueryDateKey = "query_date";
public const int MaxPageThreads = 3;
public const int MaxThreads = 6;
public const int MaxThreads = 4;
public const string Referer = "https://www.pixiv.net/";
public const string RefererIllust = "https://www.pixiv.net/artworks/{0}";
public const string RefererIllustRanking = "https://www.pixiv.net/ranking.php?{0}";
@ -700,6 +792,7 @@ namespace Pixiview.Utils
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 static string UrlFavoriteList => Prefix + "bookmark.php?rest=show";
public static string BookmarkAdd => Prefix + "ajax/illusts/bookmarks/add";
public static string BookmarkRpc => Prefix + "rpc/index.php";