Pixiview/Pixiview/ViewIllustPage.xaml.cs

275 lines
9.3 KiB
C#

using System;
using System.Threading.Tasks;
using Pixiview.Resources;
using Pixiview.UI;
using Pixiview.Utils;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Pixiview
{
public partial class ViewIllustPage : AdaptedPage
{
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 PageTopMarginProperty = BindableProperty.Create(
nameof(PageTopMargin), typeof(Thickness), typeof(ViewIllustPage));
public static readonly BindableProperty IllustItemProperty = BindableProperty.Create(
nameof(IllustItem), typeof(IllustItem), typeof(ViewIllustPage));
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 Thickness PageTopMargin
{
get => (Thickness)GetValue(PageTopMarginProperty);
set => SetValue(PageTopMarginProperty, value);
}
public IllustItem IllustItem
{
get => (IllustItem)GetValue(IllustItemProperty);
private set => SetValue(IllustItemProperty, value);
}
public int CurrentPage { get; private set; }
public ViewIllustPage(IllustItem illust)
{
IllustItem = illust;
BindingContext = this;
InitializeComponent();
}
public override void OnLoad()
{
var illust = IllustItem;
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();
if (i == 0)
{
items[i].Image = illust.Image;
}
}
Illusts = items;
UpdatePageTopMargin(CurrentOrientation);
Task.Run(DoLoadImages);
}
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 Page_OrientationChanged(object sender, OrientationEventArgs e)
{
UpdatePageTopMargin(e.CurrentOrientation);
}
private void UpdatePageTopMargin(Orientation orientation)
{
switch (orientation)
{
case Orientation.Portrait:
PageTopMargin = StyleDefinition.TotalBarOffset;
break;
case Orientation.PortraitUpsideDown:
if (DeviceInfo.Idiom == DeviceIdiom.Phone)
{
PageTopMargin = StyleDefinition.NavigationBarOffset;
}
else
{
PageTopMargin = StyleDefinition.TotalBarOffset;
}
break;
case Orientation.Unknown:
case Orientation.LandscapeLeft:
case Orientation.LandscapeRight:
default:
PageTopMargin = StyleDefinition.NavigationBarOffset;
break;
}
}
private void DoLoadImages()
{
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();
}
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;
}
DoLoadImage(0);
if (items.Length > 1)
{
DoLoadImage(1);
}
}
private void DoLoadImage(int index)
{
var items = Illusts;
if (index < 0 || index >= items.Length)
{
App.DebugPrint($"invalid index: {index}");
return;
}
var item = items[index];
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 async void Download_Clicked(object sender, EventArgs e)
{
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;
}
}
var item = Illusts[CurrentPage];
if (item.Downloading)
{
return;
}
item.Downloading = true;
_ = Task.Run(() => DoLoadOriginalImage(item));
}
private void DoLoadOriginalImage(IllustDetailItem item)
{
var image = Stores.LoadIllustImage(item.OriginalUrl);
if (image != null)
{
Device.BeginInvokeOnMainThread(async () =>
{
var service = DependencyService.Get<IFileStore>();
var result = await service.SaveImageToGalleryAsync(image);
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 PreviewUrl { get; set; }
public string OriginalUrl { get; set; }
}
}