From d6c235d6ef9127e35eaa1d9c5a39930da34f951c Mon Sep 17 00:00:00 2001 From: Tsanie Lily Date: Mon, 18 May 2020 18:45:24 +0800 Subject: [PATCH] feature: single illust bookmark sync --- Pixiview.Android/Pixiview.Android.csproj | 1 + .../Renderers/OptionPickerRenderer.cs | 29 +++++ Pixiview.iOS/Pixiview.iOS.csproj | 1 + .../Renderers/OptionPickerRenderer.cs | 22 ++++ Pixiview/App.cs | 5 +- Pixiview/AppShell.xaml.cs | 22 +++- Pixiview/Illust/IllustCollectionPage.cs | 2 + Pixiview/Illust/ViewIllustPage.xaml.cs | 111 +++++++++++++----- Pixiview/OptionPage.xaml | 2 + Pixiview/OptionPage.xaml.cs | 25 ++++ Pixiview/Resources/Languages/zh-CN.xml | 5 + Pixiview/Resources/ResourceHelper.cs | 4 + Pixiview/UI/OptionCell.cs | 37 +++++- Pixiview/Utils/HttpUtility.cs | 39 +++++- Pixiview/Utils/IllustData.cs | 24 ++++ Pixiview/Utils/IllustLegacy.cs | 3 + Pixiview/Utils/Stores.cs | 83 +++++++++++++ 17 files changed, 368 insertions(+), 47 deletions(-) create mode 100644 Pixiview.Android/Renderers/OptionPickerRenderer.cs create mode 100644 Pixiview.iOS/Renderers/OptionPickerRenderer.cs diff --git a/Pixiview.Android/Pixiview.Android.csproj b/Pixiview.Android/Pixiview.Android.csproj index 47aaf0d..f4b971c 100644 --- a/Pixiview.Android/Pixiview.Android.csproj +++ b/Pixiview.Android/Pixiview.Android.csproj @@ -81,6 +81,7 @@ + diff --git a/Pixiview.Android/Renderers/OptionPickerRenderer.cs b/Pixiview.Android/Renderers/OptionPickerRenderer.cs new file mode 100644 index 0000000..ed987bf --- /dev/null +++ b/Pixiview.Android/Renderers/OptionPickerRenderer.cs @@ -0,0 +1,29 @@ +using Android.Content; +using Android.Graphics.Drawables; +using Pixiview.Droid.Renderers; +using Pixiview.UI; +using Xamarin.Forms; +using Xamarin.Forms.Platform.Android; + +[assembly: ExportRenderer(typeof(OptionPicker), typeof(OptionPickerRenderer))] +namespace Pixiview.Droid.Renderers +{ + public class OptionPickerRenderer : PickerRenderer + { + public OptionPickerRenderer(Context context) : base(context) + { + } + + protected override void OnElementChanged(ElementChangedEventArgs e) + { + base.OnElementChanged(e); + + if (e.NewElement != null) + { + var drawable = new ColorDrawable(e.NewElement.BackgroundColor.ToAndroid()); + Control.Gravity = Android.Views.GravityFlags.Right; + Control.SetBackground(drawable); + } + } + } +} diff --git a/Pixiview.iOS/Pixiview.iOS.csproj b/Pixiview.iOS/Pixiview.iOS.csproj index 894b5e9..0de050d 100644 --- a/Pixiview.iOS/Pixiview.iOS.csproj +++ b/Pixiview.iOS/Pixiview.iOS.csproj @@ -84,6 +84,7 @@ + diff --git a/Pixiview.iOS/Renderers/OptionPickerRenderer.cs b/Pixiview.iOS/Renderers/OptionPickerRenderer.cs new file mode 100644 index 0000000..8c316a7 --- /dev/null +++ b/Pixiview.iOS/Renderers/OptionPickerRenderer.cs @@ -0,0 +1,22 @@ +using Pixiview.iOS.Renderers; +using Xamarin.Forms; +using Xamarin.Forms.Platform.iOS; + +[assembly: ExportRenderer(typeof(Picker), typeof(OptionPickerRenderer))] +namespace Pixiview.iOS.Renderers +{ + public class OptionPickerRenderer : PickerRenderer + { + protected override void OnElementChanged(ElementChangedEventArgs e) + { + base.OnElementChanged(e); + + var control = Control; + if (control != null) + { + control.TextAlignment = UIKit.UITextAlignment.Right; + control.BorderStyle = UIKit.UITextBorderStyle.None; + } + } + } +} diff --git a/Pixiview/App.cs b/Pixiview/App.cs index 037dd68..ea67e0c 100644 --- a/Pixiview/App.cs +++ b/Pixiview/App.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; -using System.Threading.Tasks; using Pixiview.Illust; using Pixiview.Resources; using Pixiview.UI.Theme; @@ -35,10 +34,8 @@ namespace Pixiview Configs.SetCookie(Preferences.Get(Configs.CookieKey, null)); Configs.SetUserId(Preferences.Get(Configs.UserIdKey, null)); - // login info - Task.Run(() => AppShell.Current.DoLoginInformation()); - Configs.IsOnR18 = Preferences.Get(Configs.IsOnR18Key, false); + Configs.SyncFavType = (SyncType)Preferences.Get(Configs.SyncFavTypeKey, 0); var isProxied = Preferences.Get(Configs.IsProxiedKey, false); if (isProxied) { diff --git a/Pixiview/AppShell.xaml.cs b/Pixiview/AppShell.xaml.cs index c19c26b..e1da9c3 100644 --- a/Pixiview/AppShell.xaml.cs +++ b/Pixiview/AppShell.xaml.cs @@ -50,6 +50,8 @@ namespace Pixiview public event EventHandler NavigationBarHeightChanged; public event EventHandler StatusBarHeightChanged; + private bool firstLoading = true; + public AppShell() { BindingContext = this; @@ -58,6 +60,16 @@ namespace Pixiview App.DebugPrint($"folder: {Stores.PersonalFolder}"); } + protected override void OnNavigated(ShellNavigatedEventArgs args) + { + if (firstLoading) + { + firstLoading = false; + // login info + Task.Run(() => DoLoginInformation(true)); + } + } + public void SetNavigationBarHeight(double height) { NavigationBarOffset = new Thickness(0, height, 0, 0); @@ -153,10 +165,14 @@ namespace Pixiview Preferences.Set(Configs.ProfileIdKey, userId); Preferences.Set(Configs.ProfileImageKey, img); } - UserProfileName = name; - UserProfileId = $"@{userId}"; + UserProfileName = name ?? ResourceHelper.Guest; + UserProfileId = string.IsNullOrEmpty(userId) + ? string.Empty + : $"@{userId}"; - UserProfileImage = Stores.LoadUserProfileImage(img); + UserProfileImage = img == null + ? StyleDefinition.ProfileNone + : Stores.LoadUserProfileImage(img); } } diff --git a/Pixiview/Illust/IllustCollectionPage.cs b/Pixiview/Illust/IllustCollectionPage.cs index 61ca47e..ce6887b 100644 --- a/Pixiview/Illust/IllustCollectionPage.cs +++ b/Pixiview/Illust/IllustCollectionPage.cs @@ -837,6 +837,8 @@ namespace Pixiview.Illust [JsonProperty] public string Id { get; set; } [JsonProperty] + public string BookmarkId { get; set; } + [JsonProperty] public DateTime FavoriteDateUtc { get; set; } [JsonProperty] public string ImageUrl { get; set; } diff --git a/Pixiview/Illust/ViewIllustPage.xaml.cs b/Pixiview/Illust/ViewIllustPage.xaml.cs index 8b4bb80..2220c28 100644 --- a/Pixiview/Illust/ViewIllustPage.xaml.cs +++ b/Pixiview/Illust/ViewIllustPage.xaml.cs @@ -133,6 +133,7 @@ namespace Pixiview.Illust private readonly object sync = new object(); private int downloaded = 0; private int pageCount; + private bool isPreloading; public ViewIllustPage(IllustItem illust, bool save) { @@ -383,28 +384,7 @@ namespace Pixiview.Illust if (i == 0 && illustItem.ImageUrl == null) { // maybe open from a link - var preload = Stores.LoadIllustPreloadData(illustItem.Id); - if (preload != null && preload.illust.TryGetValue(illustItem.Id, out var illust)) - { - illust.CopyToItem(illustItem); - MainThread.BeginInvokeOnMainThread(() => - { - var count = illustItem.PageCount; - pageCount = count; - Title = illustItem.Title; - IsAnimateSliderVisible = illustItem.IsAnimeVisible; - if (count > 1) - { - IsPageVisible = true; - ProgressVisible = true; - PagePositionText = $"1/{count}"; - } - }); - if (preload.user.TryGetValue(illust.userId, out var user)) - { - illustItem.ProfileUrl = user.image; - } - } + DoForcePreload(false); } } @@ -434,13 +414,7 @@ namespace Pixiview.Illust private void DoLoadImage(int index, bool force = false) { var items = Illusts; - if (index == 0 && force) - { - // error, refresh all - Task.Run(() => DoLoadImages(true)); - return; - } - if (index < 0 || index >= items.Length) + if (index < 0 || (!force && index >= items.Length)) { App.DebugPrint($"invalid index: {index}"); return; @@ -525,12 +499,13 @@ namespace Pixiview.Illust } } - private void Favorite_Clicked(object sender, EventArgs e) + private async void Favorite_Clicked(object sender, EventArgs e) { var favorites = Stores.Favorites; var illust = IllustItem; var index = favorites.FindIndex(i => i.Id == illust.Id); - if (index < 0) + bool add = index < 0; + if (add) { illust.IsFavorite = true; illust.FavoriteDateUtc = DateTime.UtcNow; @@ -543,6 +518,40 @@ namespace Pixiview.Illust favorites.RemoveAt(index); FavoriteIcon = fontIconNotLove; } + + if (Configs.SyncFavType == SyncType.None) + { + return; + } + if (Configs.SyncFavType == SyncType.Prompt) + { + var ok = await DisplayAlert( + ResourceHelper.Title, + ResourceHelper.ConfirmSyncFavorite, + ResourceHelper.Yes, + ResourceHelper.No); + if (!ok) + { + return; + } + } + + if (add) + { + var id = await Task.Run(() => Stores.AddBookmark(illust.Id)); + if (id != null) + { + illust.BookmarkId = id; + } + } + else + { + var bookmarkId = illust.BookmarkId; + if (!string.IsNullOrEmpty(bookmarkId)) + { + _ = Task.Run(() => Stores.DeleteBookmark(bookmarkId)); + } + } } private void Image_Tapped(object sender, EventArgs e) @@ -582,9 +591,47 @@ namespace Pixiview.Illust CurrentAnimeFrame = e.FrameIndex; } + private void DoForcePreload(bool force) + { + isPreloading = true; + var illustItem = IllustItem; + // force to reload + var preload = Stores.LoadIllustPreloadData(illustItem.Id, force); + if (preload != null && preload.illust.TryGetValue(illustItem.Id, out var illust)) + { + illust.CopyToItem(illustItem); + MainThread.BeginInvokeOnMainThread(() => + { + var count = illustItem.PageCount; + pageCount = count; + Title = illustItem.Title; + IsAnimateSliderVisible = illustItem.IsAnimeVisible; + if (count > 1) + { + IsPageVisible = true; + ProgressVisible = true; + PagePositionText = $"1/{count}"; + } + }); + if (preload.user.TryGetValue(illust.userId, out var user)) + { + illustItem.ProfileUrl = user.image; + } + } + isPreloading = false; + } + private void Refresh_Clicked(object sender, EventArgs e) { - Task.Run(() => DoLoadImage(CurrentPage, true)); + if (isPreloading) + { + return; + } + Task.Run(() => + { + DoForcePreload(true); + DoLoadImage(CurrentPage, true); + }); } private async void More_Clicked(object sender, EventArgs e) diff --git a/Pixiview/OptionPage.xaml b/Pixiview/OptionPage.xaml index 9d86cc4..26ddf88 100644 --- a/Pixiview/OptionPage.xaml +++ b/Pixiview/OptionPage.xaml @@ -15,6 +15,8 @@ + (bool)GetValue(IsOnR18Property); set => SetValue(IsOnR18Property, value); } + public int SyncFavType + { + get => (int)GetValue(SyncFavTypeProperty); + set => SetValue(SyncFavTypeProperty, value); + } public bool IsProxied { get => (bool)GetValue(IsProxiedProperty); @@ -49,6 +57,14 @@ namespace Pixiview { BindingContext = this; InitializeComponent(); + + optionFavSync.Items = new[] + { + ResourceHelper.SyncNo, + ResourceHelper.SyncPrompt, + ResourceHelper.SyncAuto, + }; + SyncFavType = 0; } protected override void OnAppearing() @@ -56,6 +72,7 @@ namespace Pixiview base.OnAppearing(); IsOnR18 = Configs.IsOnR18; + SyncFavType = (int)Configs.SyncFavType; var proxy = Configs.Proxy; if (proxy != null) { @@ -78,6 +95,7 @@ namespace Pixiview base.OnDisappearing(); var r18 = IsOnR18; + var syncType = SyncFavType; var proxied = IsProxied; if (Configs.IsOnR18 != r18) @@ -87,6 +105,13 @@ namespace Pixiview App.DebugPrint($"r-18 filter: {r18}"); } + if ((int)Configs.SyncFavType != syncType) + { + Preferences.Set(Configs.SyncFavTypeKey, syncType); + Configs.SyncFavType = (SyncType)syncType; + App.DebugPrint($"favorite sync type changed to {Configs.SyncFavType}"); + } + var proxy = Configs.Proxy; var h = Host?.Trim(); _ = int.TryParse(Port, out int pt); diff --git a/Pixiview/Resources/Languages/zh-CN.xml b/Pixiview/Resources/Languages/zh-CN.xml index 11b8187..6241aba 100644 --- a/Pixiview/Resources/Languages/zh-CN.xml +++ b/Pixiview/Resources/Languages/zh-CN.xml @@ -29,6 +29,10 @@ {0} 最受欢迎 一般 R-18 + 收藏同步类型 + 不同步 + 提示同步 + 自动同步 已关注 推荐 按用户 @@ -53,4 +57,5 @@ 视频已保存,是否继续? 视频已导出到照片库。 无法获取返回结果。 + 要同步收藏吗? \ No newline at end of file diff --git a/Pixiview/Resources/ResourceHelper.cs b/Pixiview/Resources/ResourceHelper.cs index a6fff42..cb26e8e 100644 --- a/Pixiview/Resources/ResourceHelper.cs +++ b/Pixiview/Resources/ResourceHelper.cs @@ -17,6 +17,9 @@ namespace Pixiview.Resources public static string Yes => GetResource(nameof(Yes)); public static string No => GetResource(nameof(No)); public static string R18 => GetResource(nameof(R18)); + public static string SyncNo => GetResource(nameof(SyncNo)); + public static string SyncPrompt => GetResource(nameof(SyncPrompt)); + public static string SyncAuto => GetResource(nameof(SyncAuto)); public static string Operation => GetResource(nameof(Operation)); public static string SaveOriginal => GetResource(nameof(SaveOriginal)); public static string Share => GetResource(nameof(Share)); @@ -34,6 +37,7 @@ namespace Pixiview.Resources public static string AlreadySavedVideo => GetResource(nameof(AlreadySavedVideo)); public static string ExportSuccess => GetResource(nameof(ExportSuccess)); public static string FailedResponse => GetResource(nameof(FailedResponse)); + public static string ConfirmSyncFavorite => GetResource(nameof(ConfirmSyncFavorite)); static readonly Dictionary dict = new Dictionary(); diff --git a/Pixiview/UI/OptionCell.cs b/Pixiview/UI/OptionCell.cs index d408333..6691d54 100644 --- a/Pixiview/UI/OptionCell.cs +++ b/Pixiview/UI/OptionCell.cs @@ -1,10 +1,12 @@ -using Pixiview.UI.Theme; +using System.Collections; +using Pixiview.UI.Theme; using Pixiview.Utils; using Xamarin.Forms; namespace Pixiview.UI { public class OptionEntry : Entry { } + public class OptionPicker : Picker { } public abstract class OptionCell : ViewCell { @@ -27,8 +29,8 @@ namespace Pixiview.UI Padding = new Thickness(20, 0), ColumnDefinitions = { - new ColumnDefinition { Width = new GridLength(.2, GridUnitType.Star) }, - new ColumnDefinition { Width = new GridLength(.8, GridUnitType.Star) } + new ColumnDefinition { Width = new GridLength(.3, GridUnitType.Star) }, + new ColumnDefinition { Width = new GridLength(.7, GridUnitType.Star) } }, Children = { @@ -65,6 +67,35 @@ namespace Pixiview.UI }.Binding(Switch.IsToggledProperty, nameof(IsToggled), BindingMode.TwoWay); } + public class OptionDropCell : OptionCell + { + public static readonly BindableProperty ItemsProperty = BindableProperty.Create( + nameof(Items), typeof(IList), typeof(OptionDropCell)); + public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create( + nameof(SelectedIndex), typeof(int), typeof(OptionDropCell)); + + public IList Items + { + get => (IList)GetValue(ItemsProperty); + set => SetValue(ItemsProperty, value); + } + public int SelectedIndex + { + get => (int)GetValue(SelectedIndexProperty); + set => SetValue(SelectedIndexProperty, value); + } + + protected override View Content => new OptionPicker + { + HorizontalOptions = LayoutOptions.Fill, + VerticalOptions = LayoutOptions.Center + } + .Binding(Picker.ItemsSourceProperty, nameof(Items)) + .Binding(Picker.SelectedIndexProperty, nameof(SelectedIndex), BindingMode.TwoWay) + .DynamicResource(Picker.TextColorProperty, ThemeBase.TextColor) + .DynamicResource(VisualElement.BackgroundColorProperty, ThemeBase.OptionTintColor); + } + public class OptionEntryCell : OptionCell { public static readonly BindableProperty TextProperty = BindableProperty.Create( diff --git a/Pixiview/Utils/HttpUtility.cs b/Pixiview/Utils/HttpUtility.cs index a9fd6a3..7a181cb 100644 --- a/Pixiview/Utils/HttpUtility.cs +++ b/Pixiview/Utils/HttpUtility.cs @@ -13,12 +13,14 @@ namespace Pixiview.Utils { public static T LoadObject(string file, string url, string referer, out string error, bool force = false, + bool nojson = false, + HttpContent post = null, Action header = null, Func namehandler = null, Func action = null) { string content = null; - if (!force && file != null && File.Exists(file)) + if (post == null && !force && file != null && File.Exists(file)) { try { @@ -31,6 +33,11 @@ namespace Pixiview.Utils } if (content == null) { + bool noToken = string.IsNullOrEmpty(Configs.CsrfToken); + if (noToken) + { + post = null; + } var response = Download(url, headers => { if (referer != null) @@ -44,6 +51,11 @@ namespace Pixiview.Utils { headers.Add("Cookie", cookie); } + if (post != null && !noToken) + { + headers.Add("Origin", Configs.Referer); + headers.Add("X-Csrf-Token", Configs.CsrfToken); + } if (header == null) { var userId = Configs.UserId; @@ -56,12 +68,18 @@ namespace Pixiview.Utils { header(headers); } - }); + }, post); if (response == null) { error = "response is null"; return default; } + if (!response.IsSuccessStatusCode) + { + App.DebugPrint($"http failed with code: {response.StatusCode}"); + error = response.StatusCode.ToString(); + return default; + } using (response) { try @@ -124,7 +142,14 @@ namespace Pixiview.Utils try { error = null; - return JsonConvert.DeserializeObject(content); + if (nojson) + { + return JsonConvert.DeserializeObject("{}"); + } + else + { + return JsonConvert.DeserializeObject(content); + } } catch (Exception ex) { @@ -172,7 +197,7 @@ namespace Pixiview.Utils } } - private static HttpResponseMessage Download(string url, Action headerAction) + private static HttpResponseMessage Download(string url, Action headerAction, HttpContent post = null) { App.DebugPrint($"GET: {url}"); var uri = new Uri(url); @@ -194,7 +219,7 @@ namespace Pixiview.Utils }; return TryCount(() => { - using (var request = new HttpRequestMessage(HttpMethod.Get, uri.PathAndQuery) + using (var request = new HttpRequestMessage(post == null ? HttpMethod.Get : HttpMethod.Post, uri.PathAndQuery) { Version = new Version(2, 0) }) @@ -207,6 +232,10 @@ namespace Pixiview.Utils } headers.Add("Accept-Language", Configs.AcceptLanguage); //headers.Add("Accept-Encoding", Configs.AcceptEncoding); + if (post != null) + { + request.Content = post; + } return client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result; } }); diff --git a/Pixiview/Utils/IllustData.cs b/Pixiview/Utils/IllustData.cs index 500a8f0..6334658 100644 --- a/Pixiview/Utils/IllustData.cs +++ b/Pixiview/Utils/IllustData.cs @@ -14,6 +14,12 @@ namespace Pixiview.Utils public T body; } + public class BookmarkResultData + { + public string last_bookmark_id; + public string stacc_status_id; + } + public class Illust { public string illustId; @@ -30,6 +36,7 @@ namespace Pixiview.Utils public int width; public int height; public int pageCount; + public IllustBookmark bookmarkData; public string alt; public IllustUrls urls; public string seriesId; @@ -46,11 +53,19 @@ namespace Pixiview.Utils public string x540; } + public class IllustBookmark + { + public string id; + [JsonProperty("private")] + public bool isPrivate; + } + public IllustItem ConvertToItem(ImageSource image = null) { return new IllustItem { Id = illustId, + BookmarkId = bookmarkData?.id, Title = illustTitle, RankTitle = illustTitle, IllustType = (IllustType)illustType, @@ -167,9 +182,11 @@ namespace Pixiview.Utils public int responseCount; public int viewCount; public bool isOriginal; + public IllustBookmark bookmarkData; public IllustItem CopyToItem(IllustItem item) { + item.BookmarkId = bookmarkData?.id; item.Title = illustTitle; item.RankTitle = illustTitle; item.IllustType = (IllustType)illustType; @@ -194,6 +211,13 @@ namespace Pixiview.Utils [JsonIgnore] public string Url => urls.regular; + public class IllustBookmark + { + public string id; + [JsonProperty("private")] + public bool isPrivate; + } + public class IllustUrls { public string mini; diff --git a/Pixiview/Utils/IllustLegacy.cs b/Pixiview/Utils/IllustLegacy.cs index 1d8033c..88f2ced 100644 --- a/Pixiview/Utils/IllustLegacy.cs +++ b/Pixiview/Utils/IllustLegacy.cs @@ -41,6 +41,8 @@ namespace Pixiview.Utils public string attr; public bool is_bookmarked; public bool bookmarkable; + public string bookmark_id; + public string bookmark_illust_restrict; public class ContentType { @@ -94,6 +96,7 @@ namespace Pixiview.Utils return new IllustItem { Id = illust_id.ToString(), + BookmarkId = bookmark_id, Title = title, RankTitle = $"#{rank} {title}", IllustType = (IllustType)type, diff --git a/Pixiview/Utils/Stores.cs b/Pixiview/Utils/Stores.cs index 6a0123d..3303879 100644 --- a/Pixiview/Utils/Stores.cs +++ b/Pixiview/Utils/Stores.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Text; using Newtonsoft.Json; using Pixiview.Illust; @@ -310,9 +311,75 @@ namespace Pixiview.Utils { App.DebugPrint($"error when load global data, is null"); } + else + { + App.DebugPrint($"current csrf token: {result.token}"); + Configs.CsrfToken = result.token; + } return result; } + public static string AddBookmark(string id) + { + if (string.IsNullOrEmpty(Configs.CsrfToken)) + { + return null; + } + var content = new StringContent( + "{\"illust_id\":\"" + id + "\",\"restrict\":0,\"comment\":\"\",\"tags\":[]}", + Encoding.UTF8, + Configs.AcceptJson); + var result = HttpUtility.LoadObject>( + null, + Configs.BookmarkAdd, + Configs.Referer, + out string error, + force: true, + post: content); + if (error != null) + { + App.DebugPrint($"failed to add bookmark, error: {error}"); + } + else if (result == null || result.error) + { + App.DebugPrint($"failed to add bookmark, message: {result.message}"); + } + App.DebugPrint($"successs, bookmark id: {result.body.last_bookmark_id}, status: {result.body.stacc_status_id}"); + return result.body.last_bookmark_id; + } + + public static bool DeleteBookmark(string id) + { + if (string.IsNullOrEmpty(Configs.CsrfToken)) + { + return false; + } + var content = new StringContent( + "mode=delete_illust_bookmark&bookmark_id=" + id, + Encoding.UTF8, + Configs.AcceptUrlEncoded); + var result = HttpUtility.LoadObject( + null, + Configs.BookmarkRpc, + Configs.Referer, + out string error, + force: true, + nojson: true, + post: content); + if (error != null) + { + App.DebugPrint($"failed to delete bookmark, error: {error}"); + return false; + } + else if (result == null) + { + App.DebugPrint("failed to delete bookmark, result is null"); + return false; + } + App.DebugPrint($"successs, delete bookmark"); + return true; + } + public static IllustPreloadBody LoadIllustPreloadData(string id, bool force = false) { var file = Path.Combine(CacheFolder, preloadsFolder, $"{id}.json"); @@ -512,6 +579,13 @@ namespace Pixiview.Utils } } + public enum SyncType + { + None = 0, + Prompt, + AutoSync + } + public static class Configs { public const string ProfileNameKey = "name"; @@ -520,6 +594,7 @@ namespace Pixiview.Utils public const string CookieKey = "cookies"; public const string UserIdKey = "user_id"; public const string IsOnR18Key = "is_on_r18"; + public const string SyncFavTypeKey = "sync_fav_type"; public const string IsProxiedKey = "is_proxied"; public const string HostKey = "host"; public const string PortKey = "port"; @@ -535,12 +610,14 @@ namespace Pixiview.Utils public const string RefererIllustUser = "https://www.pixiv.net/users/{0}/illustrations"; public static bool IsOnR18; + public static SyncType SyncFavType; public static WebProxy Proxy; public static string Prefix => Proxy == null ? "https://hk.tsanie.us/reverse/" : "https://www.pixiv.net/"; public static string UserId { get; private set; } public static string Cookie { get; private set; } + public static string CsrfToken; public static void SetUserId(string userId, bool save = false) { @@ -613,6 +690,7 @@ namespace Pixiview.Utils public const int SuffixGlobalLength = 32; public const string SuffixPreload = " id=\"meta-preload-data\" content='"; public const int SuffixPreloadLength = 33; // SuffixPreload.Length + public static string UrlIllustList => Prefix + "ajax/top/illust?mode=all&lang=zh"; public static string UrlIllust => Prefix + "artworks/{0}"; public static string UrlIllustRanking => Prefix + "ranking.php?{0}"; @@ -622,9 +700,14 @@ 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 BookmarkAdd => Prefix + "ajax/illusts/bookmarks/add"; + public static string BookmarkRpc => Prefix + "rpc/index.php"; + 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"; + public const string AcceptUrlEncoded = "application/x-www-form-urlencoded"; //public const string AcceptEncoding = "gzip, deflate"; public const string AcceptLanguage = "zh-cn";