favorite/online bookmark status in view page

This commit is contained in:
2020-05-20 09:56:58 +08:00
parent 34a8d5f434
commit 67a3995bf2
3 changed files with 106 additions and 76 deletions

View File

@ -146,8 +146,8 @@ namespace Pixiview.Illust
{ {
ToggleFilterPanel(false); ToggleFilterPanel(false);
await ScrollToTopAsync(scrollView); await ScrollToTopAsync(scrollView);
startIndex = 0;
lastUpdated = default; lastUpdated = default;
startIndex = 0;
StartLoad(); StartLoad();
} }
@ -187,11 +187,11 @@ namespace Pixiview.Illust
public void Reload(bool force = false) public void Reload(bool force = false)
{ {
lastUpdated = default;
if (force) if (force)
{ {
flag = true; flag = true;
} }
lastUpdated = default;
startIndex = -1; startIndex = -1;
StartLoad(force); StartLoad(force);
} }
@ -225,7 +225,6 @@ namespace Pixiview.Illust
flag = false; flag = false;
lastUpdated = default; lastUpdated = default;
startIndex = -1; startIndex = -1;
nextIndex = 0;
MainThread.BeginInvokeOnMainThread(() => StartLoad(true)); MainThread.BeginInvokeOnMainThread(() => StartLoad(true));
} }
}); });
@ -336,6 +335,7 @@ namespace Pixiview.Illust
{ {
flag = false; flag = false;
lastUpdated = default; lastUpdated = default;
startIndex = -1;
StartLoad(); StartLoad();
}); });
}); });

View File

@ -14,9 +14,16 @@ namespace Pixiview.Illust
[QueryProperty("IllustId", "id")] [QueryProperty("IllustId", "id")]
public partial class ViewIllustPage : AdaptedPage public partial class ViewIllustPage : AdaptedPage
{ {
#region - Properties -
public static readonly BindableProperty FavoriteIconProperty = BindableProperty.Create( public static readonly BindableProperty FavoriteIconProperty = BindableProperty.Create(
nameof(FavoriteIcon), typeof(ImageSource), typeof(ViewIllustPage)); nameof(FavoriteIcon), typeof(ImageSource), typeof(ViewIllustPage));
public ImageSource FavoriteIcon
{
get => (ImageSource)GetValue(FavoriteIconProperty);
set => SetValue(FavoriteIconProperty, value);
}
public static readonly BindableProperty IllustsProperty = BindableProperty.Create( public static readonly BindableProperty IllustsProperty = BindableProperty.Create(
nameof(Illusts), typeof(IllustDetailItem[]), typeof(ViewIllustPage)); nameof(Illusts), typeof(IllustDetailItem[]), typeof(ViewIllustPage));
public static readonly BindableProperty IsPageVisibleProperty = BindableProperty.Create( public static readonly BindableProperty IsPageVisibleProperty = BindableProperty.Create(
@ -27,43 +34,6 @@ namespace Pixiview.Illust
nameof(CurrentPage), typeof(int), typeof(ViewIllustPage), propertyChanged: OnCurrentPagePropertyChanged); nameof(CurrentPage), typeof(int), typeof(ViewIllustPage), propertyChanged: OnCurrentPagePropertyChanged);
public static readonly BindableProperty IsScrollAnimatedProperty = BindableProperty.Create( public static readonly BindableProperty IsScrollAnimatedProperty = BindableProperty.Create(
nameof(IsScrollAnimated), typeof(bool), typeof(ViewIllustPage), true); nameof(IsScrollAnimated), typeof(bool), typeof(ViewIllustPage), true);
public static readonly BindableProperty AnimeStatusProperty = BindableProperty.Create(
nameof(AnimeStatus), typeof(string), typeof(ViewIllustPage), StyleDefinition.IconPlay);
public static readonly BindableProperty IsAnimateSliderVisibleProperty = BindableProperty.Create(
nameof(IsAnimateSliderVisible), typeof(bool), typeof(ViewIllustPage));
public static readonly BindableProperty IsAnimateSliderEnabledProperty = BindableProperty.Create(
nameof(IsAnimateSliderEnabled), typeof(bool), typeof(ViewIllustPage));
public static readonly BindableProperty CurrentAnimeFrameProperty = BindableProperty.Create(
nameof(CurrentAnimeFrame), typeof(double), typeof(ViewIllustPage), propertyChanged: OnCurrentAnimeFramePropertyChanged);
public static readonly BindableProperty MaximumFrameProperty = BindableProperty.Create(
nameof(MaximumFrame), typeof(double), typeof(ViewIllustPage), 1.0);
public static readonly BindableProperty ProgressVisibleProperty = BindableProperty.Create(
nameof(ProgressVisible), typeof(bool), typeof(ViewIllustPage));
private static void OnCurrentPagePropertyChanged(BindableObject obj, object old, object @new)
{
var page = (ViewIllustPage)obj;
var index = (int)@new;
var items = page.Illusts;
var length = items.Length;
page.PagePositionText = $"{index + 1}/{length}";
}
private static void OnCurrentAnimeFramePropertyChanged(BindableObject obj, object old, object @new)
{
var page = (ViewIllustPage)obj;
if (page.ugoira != null && page.IsAnimateSliderEnabled)
{
var frame = (double)@new;
page.ugoira.ToggleFrame((int)frame);
}
}
public ImageSource FavoriteIcon
{
get => (ImageSource)GetValue(FavoriteIconProperty);
set => SetValue(FavoriteIconProperty, value);
}
public IllustDetailItem[] Illusts public IllustDetailItem[] Illusts
{ {
@ -85,16 +55,47 @@ namespace Pixiview.Illust
get => (int)GetValue(CurrentPageProperty); get => (int)GetValue(CurrentPageProperty);
set => SetValue(CurrentPageProperty, value); set => SetValue(CurrentPageProperty, value);
} }
public string AnimeStatus
{
get => (string)GetValue(AnimeStatusProperty);
set => SetValue(AnimeStatusProperty, value);
}
public bool IsScrollAnimated public bool IsScrollAnimated
{ {
get => (bool)GetValue(IsScrollAnimatedProperty); get => (bool)GetValue(IsScrollAnimatedProperty);
set => SetValue(IsScrollAnimatedProperty, value); set => SetValue(IsScrollAnimatedProperty, value);
} }
private static void OnCurrentPagePropertyChanged(BindableObject obj, object old, object @new)
{
var page = (ViewIllustPage)obj;
var index = (int)@new;
var items = page.Illusts;
var length = items.Length;
page.PagePositionText = $"{index + 1}/{length}";
}
public static readonly BindableProperty AnimeStatusProperty = BindableProperty.Create(
nameof(AnimeStatus), typeof(string), typeof(ViewIllustPage), StyleDefinition.IconPlay);
public static readonly BindableProperty IsAnimateSliderVisibleProperty = BindableProperty.Create(
nameof(IsAnimateSliderVisible), typeof(bool), typeof(ViewIllustPage));
public static readonly BindableProperty IsAnimateSliderEnabledProperty = BindableProperty.Create(
nameof(IsAnimateSliderEnabled), typeof(bool), typeof(ViewIllustPage));
public static readonly BindableProperty CurrentAnimeFrameProperty = BindableProperty.Create(
nameof(CurrentAnimeFrame), typeof(double), typeof(ViewIllustPage), propertyChanged: OnCurrentAnimeFramePropertyChanged);
public static readonly BindableProperty MaximumFrameProperty = BindableProperty.Create(
nameof(MaximumFrame), typeof(double), typeof(ViewIllustPage), 1.0);
private static void OnCurrentAnimeFramePropertyChanged(BindableObject obj, object old, object @new)
{
var page = (ViewIllustPage)obj;
if (page.ugoira != null && page.IsAnimateSliderEnabled)
{
var frame = (double)@new;
page.ugoira.ToggleFrame((int)frame);
}
}
public string AnimeStatus
{
get => (string)GetValue(AnimeStatusProperty);
set => SetValue(AnimeStatusProperty, value);
}
public bool IsAnimateSliderVisible public bool IsAnimateSliderVisible
{ {
get => (bool)GetValue(IsAnimateSliderVisibleProperty); get => (bool)GetValue(IsAnimateSliderVisibleProperty);
@ -115,16 +116,22 @@ namespace Pixiview.Illust
get => (double)GetValue(MaximumFrameProperty); get => (double)GetValue(MaximumFrameProperty);
set => SetValue(MaximumFrameProperty, value); set => SetValue(MaximumFrameProperty, value);
} }
public static readonly BindableProperty ProgressVisibleProperty = BindableProperty.Create(
nameof(ProgressVisible), typeof(bool), typeof(ViewIllustPage));
public bool ProgressVisible public bool ProgressVisible
{ {
get => (bool)GetValue(ProgressVisibleProperty); get => (bool)GetValue(ProgressVisibleProperty);
set => SetValue(ProgressVisibleProperty, value); set => SetValue(ProgressVisibleProperty, value);
} }
#endregion
public IllustItem IllustItem { get; private set; } public IllustItem IllustItem { get; private set; }
private readonly ImageSource fontIconLove; private readonly ImageSource fontIconLove;
private readonly ImageSource fontIconNotLove; private readonly ImageSource fontIconNotLove;
private readonly ImageSource fontIconCircleLove;
private bool favoriteChanged; private bool favoriteChanged;
private IllustUgoiraData ugoiraData; private IllustUgoiraData ugoiraData;
private Ugoira ugoira; private Ugoira ugoira;
@ -138,27 +145,23 @@ namespace Pixiview.Illust
public ViewIllustPage(IllustItem illust) public ViewIllustPage(IllustItem illust)
{ {
IllustItem = illust; IllustItem = illust;
Title = illust.Title;
BindingContext = this;
fontIconLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconLove]; fontIconLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconLove];
fontIconNotLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconNotLove]; fontIconNotLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconNotLove];
FavoriteIcon = Stores.Favorites.Any(i => i.Id == illust.Id) fontIconCircleLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconCircleLove];
? fontIconLove
: fontIconNotLove;
if (illust != null) if (illust != null)
{ {
pageCount = illust.PageCount; pageCount = illust.PageCount;
ProgressVisible = IsPageVisible = pageCount > 1; RefreshInformation(illust, pageCount);
} }
Resources.Add("carouselView", GetCarouseTemplate()); Resources.Add("carouselView", GetCarouseTemplate());
BindingContext = this;
InitializeComponent(); InitializeComponent();
if (illust != null) if (illust != null)
{ {
IsAnimateSliderVisible = illust.IsAnimeVisible;
LoadIllust(illust); LoadIllust(illust);
} }
} }
@ -306,10 +309,6 @@ namespace Pixiview.Illust
} }
var items = new IllustDetailItem[illust.PageCount]; var items = new IllustDetailItem[illust.PageCount];
if (items.Length > 1)
{
PagePositionText = $"1/{items.Length}";
}
#if __IOS__ #if __IOS__
var topMargin = PageTopMargin; var topMargin = PageTopMargin;
@ -351,6 +350,7 @@ namespace Pixiview.Illust
return; return;
} }
var items = Illusts; var items = Illusts;
var reload = false;
if (pages.body.Length > items.Length) if (pages.body.Length > items.Length)
{ {
App.DebugPrint($"local page count ({items.Length}) is not equals the remote one ({pages.body.Length})"); App.DebugPrint($"local page count ({items.Length}) is not equals the remote one ({pages.body.Length})");
@ -371,6 +371,7 @@ namespace Pixiview.Illust
}; };
} }
Illusts = items = tmp; Illusts = items = tmp;
reload = true;
} }
for (var i = 0; i < items.Length; i++) for (var i = 0; i < items.Length; i++)
@ -383,10 +384,15 @@ namespace Pixiview.Illust
if (i == 0 && illustItem.ImageUrl == null) if (i == 0 && illustItem.ImageUrl == null)
{ {
// maybe open from a link // maybe open from a link
DoForcePreload(false); reload = true;
} }
} }
if (reload)
{
DoForcePreload(false);
}
if (task != null) if (task != null)
{ {
task.Dispose(); task.Dispose();
@ -503,7 +509,8 @@ namespace Pixiview.Illust
var favorites = Stores.Favorites; var favorites = Stores.Favorites;
var illust = IllustItem; var illust = IllustItem;
var index = favorites.FindIndex(i => i.Id == illust.Id); var index = favorites.FindIndex(i => i.Id == illust.Id);
bool add = index < 0; var bookmarkId = illust.BookmarkId;
bool add = index < 0 && bookmarkId == null;
if (add) if (add)
{ {
illust.IsFavorite = true; illust.IsFavorite = true;
@ -513,14 +520,20 @@ namespace Pixiview.Illust
} }
else else
{ {
var item = favorites[index]; if (index >= 0)
if (illust.BookmarkId == null && item.BookmarkId != null)
{ {
illust.BookmarkId = item.BookmarkId; var item = favorites[index];
if (bookmarkId == null && item.BookmarkId != null)
{
bookmarkId = item.BookmarkId;
illust.BookmarkId = bookmarkId;
}
favorites.RemoveAt(index);
} }
illust.IsFavorite = false; illust.IsFavorite = false;
favorites.RemoveAt(index); FavoriteIcon = bookmarkId == null ?
FavoriteIcon = fontIconNotLove; fontIconNotLove :
fontIconCircleLove;
} }
favoriteChanged = true; favoriteChanged = true;
@ -528,7 +541,7 @@ namespace Pixiview.Illust
{ {
return; return;
} }
if (!add && string.IsNullOrEmpty(illust.BookmarkId)) if (!add && string.IsNullOrEmpty(bookmarkId))
{ {
return; return;
} }
@ -550,12 +563,18 @@ namespace Pixiview.Illust
var id = await Task.Run(() => Stores.AddBookmark(illust.Id)); var id = await Task.Run(() => Stores.AddBookmark(illust.Id));
if (id != null) if (id != null)
{ {
illust.BookmarkId = id; bookmarkId = id;
illust.BookmarkId = bookmarkId;
FavoriteIcon = fontIconCircleLove;
} }
} }
else else
{ {
_ = Task.Run(() => Stores.DeleteBookmark(illust.BookmarkId)); var result = await Task.Run(() => Stores.DeleteBookmark(bookmarkId));
if (result)
{
FavoriteIcon = fontIconNotLove;
}
} }
// immediately save after changing remote // immediately save after changing remote
@ -600,6 +619,23 @@ namespace Pixiview.Illust
CurrentAnimeFrame = e.FrameIndex; CurrentAnimeFrame = e.FrameIndex;
} }
private void RefreshInformation(IllustItem item, int count)
{
Title = item.Title;
FavoriteIcon = item.BookmarkId != null ?
fontIconCircleLove :
Stores.Favorites.Any(i => i.Id == item.Id) ?
fontIconLove :
fontIconNotLove;
IsAnimateSliderVisible = item.IsAnimeVisible;
if (count > 1)
{
IsPageVisible = true;
ProgressVisible = true;
PagePositionText = $"1/{count}";
}
}
private void DoForcePreload(bool force) private void DoForcePreload(bool force)
{ {
isPreloading = true; isPreloading = true;
@ -609,18 +645,10 @@ namespace Pixiview.Illust
if (preload != null && preload.illust.TryGetValue(illustItem.Id, out var illust)) if (preload != null && preload.illust.TryGetValue(illustItem.Id, out var illust))
{ {
illust.CopyToItem(illustItem); illust.CopyToItem(illustItem);
pageCount = illustItem.PageCount;
MainThread.BeginInvokeOnMainThread(() => MainThread.BeginInvokeOnMainThread(() =>
{ {
var count = illustItem.PageCount; RefreshInformation(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)) if (preload.user.TryGetValue(illust.userId, out var user))
{ {

View File

@ -10,6 +10,7 @@ namespace Pixiview.UI.Theme
public const string FontIconRefresh = nameof(FontIconRefresh); public const string FontIconRefresh = nameof(FontIconRefresh);
public const string FontIconLove = nameof(FontIconLove); public const string FontIconLove = nameof(FontIconLove);
public const string FontIconNotLove = nameof(FontIconNotLove); public const string FontIconNotLove = nameof(FontIconNotLove);
public const string FontIconCircleLove = nameof(FontIconCircleLove);
public const string FontIconOption = nameof(FontIconOption); public const string FontIconOption = nameof(FontIconOption);
public const string FontIconFavorite = nameof(FontIconFavorite); public const string FontIconFavorite = nameof(FontIconFavorite);
public const string FontIconShare = nameof(FontIconShare); public const string FontIconShare = nameof(FontIconShare);
@ -53,6 +54,7 @@ namespace Pixiview.UI.Theme
var solidFontFamily = StyleDefinition.IconSolidFontFamily; var solidFontFamily = StyleDefinition.IconSolidFontFamily;
Add(FontIconLove, GetSolidIcon(StyleDefinition.IconLove, solidFontFamily, StyleDefinition.ColorRedBackground)); Add(FontIconLove, GetSolidIcon(StyleDefinition.IconLove, solidFontFamily, StyleDefinition.ColorRedBackground));
Add(FontIconCircleLove, GetSolidIcon(StyleDefinition.IconCircleLove, solidFontFamily, StyleDefinition.ColorRedBackground));
Add(FontIconUser, GetSolidIcon(StyleDefinition.IconUser, solidFontFamily)); Add(FontIconUser, GetSolidIcon(StyleDefinition.IconUser, solidFontFamily));
Add(FontIconSparkles, GetSolidIcon(StyleDefinition.IconSparkles, solidFontFamily)); Add(FontIconSparkles, GetSolidIcon(StyleDefinition.IconSparkles, solidFontFamily));
Add(FontIconOrder, GetSolidIcon(StyleDefinition.IconOrder, solidFontFamily)); Add(FontIconOrder, GetSolidIcon(StyleDefinition.IconOrder, solidFontFamily));