Pixiview/Pixiview/Illust/ViewIllustPage.xaml.cs
Tsanie Lily ba46ba02c4 * Pixiview/Utils/Stores.cs:
* Pixiview/Pixiview.projitems:
* Pixiview/Utils/IllustData.cs:
* Pixiview/Utils/HttpUtility.cs:
* Pixiview/Utils/IllustLegacy.cs:
* Pixiview/Illust/ViewIllustPage.xaml:
* Pixiview/Illust/ViewIllustPage.xaml.cs: feature: view animate

* Pixiview/Illust/FavoritesPage.xaml.cs: lazy load favorites page

* Pixiview/UI/CardView.cs:
* Pixiview/UI/AdaptedPage.cs:
* Pixiview/Utils/Converters.cs:
* Pixiview/UI/StyleDefinition.cs:
* Pixiview/UI/Theme/ThemeBase.cs:
* Pixiview/Illust/RankingPage.xaml:
* Pixiview/Illust/RankingPage.xaml.cs:
* Pixiview/Resources/Languages/zh-CN.xml:
* Pixiview/Illust/IllustCollectionPage.cs:
* Pixiview.iOS/Renderers/SegmentedControlRenderer.cs: feature: filter
  ranking

* Pixiview.iOS/Info.plist:
* Pixiview.iOS/Pixiview.iOS.csproj:
* Pixiview.iOS.OpenExtension/Info.plist:
* Pixiview.Android/Pixiview.Android.csproj:
* Pixiview.Android/Properties/AndroidManifest.xml: version update
2020-05-13 01:18:45 +08:00

438 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Pixiview.Resources;
using Pixiview.UI;
using Pixiview.UI.Theme;
using Pixiview.Utils;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Pixiview.Illust
{
[QueryProperty("IllustId", "id")]
public partial class ViewIllustPage : AdaptedPage
{
public static readonly BindableProperty FavoriteIconProperty = BindableProperty.Create(
nameof(FavoriteIcon), typeof(ImageSource), typeof(ViewIllustPage));
public static readonly BindableProperty IllustsProperty = BindableProperty.Create(
nameof(Illusts), typeof(IllustDetailItem[]), typeof(ViewIllustPage));
public static readonly BindableProperty PagePositionTextProperty = BindableProperty.Create(
nameof(PagePositionText), typeof(string), typeof(ViewIllustPage));
public static readonly BindableProperty IsPageVisibleProperty = BindableProperty.Create(
nameof(IsPageVisible), typeof(bool), typeof(ViewIllustPage));
public static readonly BindableProperty IllustItemProperty = BindableProperty.Create(
nameof(IllustItem), typeof(IllustItem), typeof(ViewIllustPage));
public ImageSource FavoriteIcon
{
get => (ImageSource)GetValue(FavoriteIconProperty);
set => SetValue(FavoriteIconProperty, value);
}
public IllustDetailItem[] Illusts
{
get => (IllustDetailItem[])GetValue(IllustsProperty);
set => SetValue(IllustsProperty, value);
}
public string PagePositionText
{
get => (string)GetValue(PagePositionTextProperty);
set => SetValue(PagePositionTextProperty, value);
}
public bool IsPageVisible
{
get => (bool)GetValue(IsPageVisibleProperty);
set => SetValue(IsPageVisibleProperty, value);
}
public IllustItem IllustItem
{
get => (IllustItem)GetValue(IllustItemProperty);
set => SetValue(IllustItemProperty, value);
}
public int CurrentPage { get; private set; }
private readonly bool saveFavorites;
private readonly ICommand longPressed;
private readonly ImageSource fontIconLove;
private readonly ImageSource fontIconNotLove;
private IllustUgoiraData ugoiraData;
private Ugoira ugoira;
public ViewIllustPage(IllustItem illust, bool save)
{
IllustItem = illust;
saveFavorites = save;
longPressed = new Command<IllustDetailItem>(Illust_LongPressed);
BindingContext = this;
fontIconLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconLove];
fontIconNotLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconNotLove];
var favorites = Stores.Favorites;
FavoriteIcon = favorites.Any(i => i.Id == illust.Id)
? fontIconLove
: fontIconNotLove;
InitializeComponent();
if (illust != null)
{
LoadIllust(illust);
}
}
public override void OnLoad()
{
OnOrientationChanged(CurrentOrientation);
}
protected override void OnAppearing()
{
base.OnAppearing();
Screen.SetHomeIndicatorAutoHidden(Shell.Current, true);
}
protected override void OnDisappearing()
{
base.OnDisappearing();
if (ugoira != null)
{
ugoira.TogglePlay(false);
IllustItem.IsPlaying = false;
}
if (saveFavorites)
{
Stores.SaveFavoritesIllusts();
}
Screen.SetHomeIndicatorAutoHidden(Shell.Current, false);
}
private void LoadIllust(IllustItem illust)
{
if (illust == null)
{
return;
}
var items = new IllustDetailItem[illust.PageCount];
if (items.Length > 1)
{
IsPageVisible = true;
PagePositionText = $"1/{items.Length}";
}
else
{
IsPageVisible = false;
}
for (var i = 0; i < items.Length; i++)
{
items[i] = new IllustDetailItem
{
Id = illust.Id,
LongPressed = longPressed
};
if (i == 0)
{
items[i].Loading = true;
items[i].Image = illust.Image;
}
}
Illusts = items;
Task.Run(DoLoadImages);
}
private void DoLoadImages()
{
var illustItem = IllustItem;
var pages = Stores.LoadIllustPageData(illustItem.Id);
if (pages == null)
{
App.DebugError("illustPage.load", $"failed to load illust page data, id: {illustItem.Id}");
return;
}
var items = Illusts;
if (pages.body.Length > items.Length)
{
App.DebugPrint($"local page count ({items.Length}) is not equals the remote one ({pages.body.Length})");
var tmp = new IllustDetailItem[pages.body.Length];
items.CopyTo(items, 0);
for (var i = items.Length; i < tmp.Length; i++)
{
tmp[i] = new IllustDetailItem
{
Id = illustItem.Id,
LongPressed = longPressed
};
}
Illusts = items = tmp;
}
for (var i = 0; i < items.Length; i++)
{
var item = items[i];
var p = pages.body[i];
item.PreviewUrl = p.urls.regular;
item.OriginalUrl = p.urls.original;
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);
if (preload.user.TryGetValue(illust.userId, out var user))
{
illustItem.ProfileUrl = user.image;
}
}
}
}
DoLoadImage(0, true);
var image = items[0].Image;
if (image != null)
{
illustItem.Image = image;
}
if (items.Length > 1)
{
DoLoadImage(1);
}
else if (illustItem.IllustType == IllustType.Anime)
{
// anime
ugoiraData = Stores.LoadIllustUgoiraData(illustItem.Id);
}
}
private void DoLoadImage(int index, bool force = false)
{
var items = Illusts;
if (index < 0 || index >= items.Length)
{
App.DebugPrint($"invalid index: {index}");
return;
}
var item = items[index];
if (!force)
{
if (item.Loading || (index > 0 && item.Image != null))
{
App.DebugPrint($"skipped, loading or already loaded, index: {index}, loading: {item.Loading}");
return;
}
}
item.Loading = true;
var image = Stores.LoadPreviewImage(item.PreviewUrl);
if (image != null)
{
item.Image = image;
}
item.Loading = false;
}
private void CarouselView_PositionChanged(object sender, PositionChangedEventArgs e)
{
var index = e.CurrentPosition;
CurrentPage = index;
var items = Illusts;
var length = items.Length;
PagePositionText = $"{index + 1}/{length}";
var item = items[index];
if (!item.Loading && item.Image == null)
{
Task.Run(() => DoLoadImage(index));
}
if (index < length - 1)
{
item = items[index + 1];
if (!item.Loading && item.Image == null)
{
Task.Run(() => DoLoadImage(index + 1));
}
}
}
private 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)
{
illust.IsFavorite = true;
favorites.Insert(0, illust);
FavoriteIcon = fontIconLove;
}
else
{
illust.IsFavorite = false;
favorites.RemoveAt(index);
FavoriteIcon = fontIconNotLove;
}
}
private void Image_Tapped(object sender, EventArgs e)
{
if (ugoiraData == null)
{
return;
}
var illustItem = IllustItem;
if (ugoira != null)
{
var playing = !ugoira.IsPlaying;
ugoira.TogglePlay(playing);
illustItem.IsPlaying = playing;
}
else if (((Image)sender).BindingContext is IllustDetailItem item)
{
if (illustItem.IsPlaying ||
illustItem.IllustType != IllustType.Anime)
{
return;
}
ugoira = new Ugoira(ugoiraData, item);
ugoira.FrameChanged += OnUgoiraFrameChanged;
illustItem.IsPlaying = true;
ugoira.TogglePlay(true);
}
}
private void OnUgoiraFrameChanged(object sender, UgoiraEventArgs e)
{
e.DetailItem.Image = e.Image;
}
private async void Illust_LongPressed(IllustDetailItem item)
{
List<string> extras = new List<string>();
var share = ResourceHelper.Share;
var preview = Stores.GetPreviewImagePath(item.PreviewUrl);
if (preview != null)
{
extras.Add(share);
}
var saveOriginal = ResourceHelper.SaveOriginal;
var userDetail = ResourceHelper.UserDetail;
extras.Add(userDetail);
var illustItem = IllustItem;
var result = await DisplayActionSheet(
illustItem.Title,
ResourceHelper.Cancel,
saveOriginal,
extras.ToArray());
if (result == saveOriginal)
{
SaveOriginalImage(item);
}
else if (result == share)
{
await Share.RequestAsync(new ShareFileRequest
{
Title = illustItem.Title,
File = new ShareFile(preview)
});
}
else if (result == userDetail)
{
var page = new UserIllustPage(illustItem);
await Navigation.PushAsync(page);
}
}
private async void SaveOriginalImage(IllustDetailItem item)
{
if (Stores.CheckIllustImage(item.OriginalUrl))
{
var flag = await DisplayAlert(ResourceHelper.Operation,
ResourceHelper.AlreadySavedQuestion,
ResourceHelper.Yes,
ResourceHelper.No);
if (!flag)
{
return;
}
}
var status = await Permissions.CheckStatusAsync<Permissions.Photos>();
if (status != PermissionStatus.Granted)
{
status = await Permissions.RequestAsync<Permissions.Photos>();
if (status != PermissionStatus.Granted)
{
App.DebugPrint("access denied to gallery.");
return;
}
}
if (item == null || item.Downloading)
{
return;
}
item.Downloading = true;
_ = Task.Run(() => DoLoadOriginalImage(item));
}
private void DoLoadOriginalImage(IllustDetailItem item)
{
var image = Stores.LoadIllustImage(item.OriginalUrl);
if (image != null)
{
MainThread.BeginInvokeOnMainThread(async () =>
{
var result = await FileStore.SaveImageToGalleryAsync(image, item.OriginalUrl);
string message = result ?? ResourceHelper.SaveSuccess;
await DisplayAlert(ResourceHelper.Title, message, ResourceHelper.Ok);
});
}
item.Downloading = false;
}
}
public class IllustDetailItem : BindableObject
{
public static readonly BindableProperty ImageProperty = BindableProperty.Create(
nameof(Image), typeof(ImageSource), typeof(IllustDetailItem));
public static readonly BindableProperty LoadingProperty = BindableProperty.Create(
nameof(Loading), typeof(bool), typeof(IllustDetailItem));
public static readonly BindableProperty DownloadingProperty = BindableProperty.Create(
nameof(Downloading), typeof(bool), typeof(IllustDetailItem));
public ImageSource Image
{
get => (ImageSource)GetValue(ImageProperty);
set => SetValue(ImageProperty, value);
}
public bool Loading
{
get => (bool)GetValue(LoadingProperty);
set => SetValue(LoadingProperty, value);
}
public bool Downloading
{
get => (bool)GetValue(DownloadingProperty);
set => SetValue(DownloadingProperty, value);
}
public string Id { get; set; }
public ICommand LongPressed { get; set; }
public string PreviewUrl { get; set; }
public string OriginalUrl { get; set; }
}
}