762 lines
27 KiB
C#
762 lines
27 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
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 IsPageVisibleProperty = BindableProperty.Create(
|
|
nameof(IsPageVisible), typeof(bool), typeof(ViewIllustPage));
|
|
public static readonly BindableProperty PagePositionTextProperty = BindableProperty.Create(
|
|
nameof(PagePositionText), typeof(string), typeof(ViewIllustPage));
|
|
public static readonly BindableProperty CurrentPageProperty = BindableProperty.Create(
|
|
nameof(CurrentPage), typeof(int), typeof(ViewIllustPage), propertyChanged: OnCurrentPagePropertyChanged);
|
|
public static readonly BindableProperty IsScrollAnimatedProperty = BindableProperty.Create(
|
|
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
|
|
{
|
|
get => (IllustDetailItem[])GetValue(IllustsProperty);
|
|
set => SetValue(IllustsProperty, value);
|
|
}
|
|
public bool IsPageVisible
|
|
{
|
|
get => (bool)GetValue(IsPageVisibleProperty);
|
|
set => SetValue(IsPageVisibleProperty, value);
|
|
}
|
|
public string PagePositionText
|
|
{
|
|
get => (string)GetValue(PagePositionTextProperty);
|
|
set => SetValue(PagePositionTextProperty, value);
|
|
}
|
|
public int CurrentPage
|
|
{
|
|
get => (int)GetValue(CurrentPageProperty);
|
|
set => SetValue(CurrentPageProperty, value);
|
|
}
|
|
public string AnimeStatus
|
|
{
|
|
get => (string)GetValue(AnimeStatusProperty);
|
|
set => SetValue(AnimeStatusProperty, value);
|
|
}
|
|
public bool IsScrollAnimated
|
|
{
|
|
get => (bool)GetValue(IsScrollAnimatedProperty);
|
|
set => SetValue(IsScrollAnimatedProperty, value);
|
|
}
|
|
public bool IsAnimateSliderVisible
|
|
{
|
|
get => (bool)GetValue(IsAnimateSliderVisibleProperty);
|
|
set => SetValue(IsAnimateSliderVisibleProperty, value);
|
|
}
|
|
public bool IsAnimateSliderEnabled
|
|
{
|
|
get => (bool)GetValue(IsAnimateSliderEnabledProperty);
|
|
set => SetValue(IsAnimateSliderEnabledProperty, value);
|
|
}
|
|
public double CurrentAnimeFrame
|
|
{
|
|
get => (double)GetValue(CurrentAnimeFrameProperty);
|
|
set => SetValue(CurrentAnimeFrameProperty, value);
|
|
}
|
|
public double MaximumFrame
|
|
{
|
|
get => (double)GetValue(MaximumFrameProperty);
|
|
set => SetValue(MaximumFrameProperty, value);
|
|
}
|
|
public bool ProgressVisible
|
|
{
|
|
get => (bool)GetValue(ProgressVisibleProperty);
|
|
set => SetValue(ProgressVisibleProperty, value);
|
|
}
|
|
|
|
public IllustItem IllustItem { get; private set; }
|
|
|
|
private readonly bool saveFavorites;
|
|
private readonly ImageSource fontIconLove;
|
|
private readonly ImageSource fontIconNotLove;
|
|
private IllustUgoiraData ugoiraData;
|
|
private Ugoira ugoira;
|
|
|
|
private readonly object sync = new object();
|
|
private int downloaded = 0;
|
|
private int pageCount;
|
|
|
|
public ViewIllustPage(IllustItem illust, bool save)
|
|
{
|
|
IllustItem = illust;
|
|
Title = illust.Title;
|
|
saveFavorites = save;
|
|
BindingContext = this;
|
|
|
|
fontIconLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconLove];
|
|
fontIconNotLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconNotLove];
|
|
FavoriteIcon = Stores.Favorites.Any(i => i.Id == illust.Id)
|
|
? fontIconLove
|
|
: fontIconNotLove;
|
|
|
|
if (illust != null)
|
|
{
|
|
pageCount = illust.PageCount;
|
|
ProgressVisible = IsPageVisible = pageCount > 1;
|
|
}
|
|
Resources.Add("carouselView", GetCarouseTemplate());
|
|
|
|
InitializeComponent();
|
|
|
|
if (illust != null)
|
|
{
|
|
IsAnimateSliderVisible = illust.IsAnimeVisible;
|
|
LoadIllust(illust);
|
|
}
|
|
}
|
|
|
|
protected override void OnAppearing()
|
|
{
|
|
base.OnAppearing();
|
|
Screen.SetHomeIndicatorAutoHidden(Shell.Current, true);
|
|
}
|
|
|
|
protected override void OnDisappearing()
|
|
{
|
|
Screen.SetHomeIndicatorAutoHidden(Shell.Current, false);
|
|
base.OnDisappearing();
|
|
|
|
if (ugoira != null)
|
|
{
|
|
IllustItem.IsPlaying = false;
|
|
ugoira.FrameChanged -= OnUgoiraFrameChanged;
|
|
ugoira.TogglePlay(false);
|
|
ugoira.Dispose();
|
|
ugoira = null;
|
|
}
|
|
|
|
if (saveFavorites)
|
|
{
|
|
Stores.SaveFavoritesIllusts();
|
|
}
|
|
}
|
|
|
|
#if __IOS__
|
|
protected override void OnPageTopMarginChanged(Thickness old, Thickness @new)
|
|
{
|
|
var illusts = Illusts;
|
|
if (illusts != null)
|
|
{
|
|
for (var i = 0; i < illusts.Length; i++)
|
|
{
|
|
illusts[i].TopPadding = @new;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
private DataTemplate GetCarouseTemplate()
|
|
{
|
|
return new DataTemplate(() =>
|
|
{
|
|
// image
|
|
var image = new Image
|
|
{
|
|
HorizontalOptions = LayoutOptions.Fill,
|
|
VerticalOptions = LayoutOptions.Fill,
|
|
Aspect = Aspect.AspectFit
|
|
}
|
|
.Binding(Image.SourceProperty, nameof(IllustDetailItem.Image));
|
|
|
|
// downloading
|
|
var downloading = new Frame
|
|
{
|
|
HasShadow = false,
|
|
Margin = default,
|
|
Padding = new Thickness(20),
|
|
CornerRadius = 8,
|
|
HorizontalOptions = LayoutOptions.Center,
|
|
VerticalOptions = LayoutOptions.Center,
|
|
Content = new ActivityIndicator()
|
|
.Binding(IsVisibleProperty, nameof(IllustDetailItem.Loading))
|
|
.Binding(ActivityIndicator.IsRunningProperty, nameof(IllustDetailItem.Loading))
|
|
.DynamicResource(ActivityIndicator.ColorProperty, ThemeBase.WindowColor)
|
|
}
|
|
.Binding(IsVisibleProperty, nameof(IllustDetailItem.Loading))
|
|
.DynamicResource(BackgroundColorProperty, ThemeBase.MaskColor);
|
|
|
|
// loading original
|
|
var original = new ActivityIndicator
|
|
{
|
|
Margin = new Thickness(10),
|
|
HorizontalOptions = LayoutOptions.Start,
|
|
VerticalOptions = LayoutOptions.Start
|
|
}
|
|
.Binding(IsVisibleProperty, nameof(IllustDetailItem.Downloading))
|
|
.Binding(ActivityIndicator.IsRunningProperty, nameof(IllustDetailItem.Downloading))
|
|
.DynamicResource(ActivityIndicator.ColorProperty, ThemeBase.TextColor);
|
|
|
|
var tap = new TapGestureRecognizer();
|
|
tap.Tapped += Image_Tapped;
|
|
var tapPrevious = new TapGestureRecognizer();
|
|
tapPrevious.Tapped += TapPrevious_Tapped;
|
|
var tapNext = new TapGestureRecognizer();
|
|
tapNext.Tapped += TapNext_Tapped;
|
|
|
|
var grid = new Grid
|
|
{
|
|
Children =
|
|
{
|
|
// image
|
|
image,
|
|
|
|
// tap holder
|
|
new Grid
|
|
{
|
|
RowDefinitions =
|
|
{
|
|
new RowDefinition { Height = new GridLength(.3, GridUnitType.Star) },
|
|
new RowDefinition { Height = new GridLength(.4, GridUnitType.Star) },
|
|
new RowDefinition { Height = new GridLength(.3, GridUnitType.Star) }
|
|
},
|
|
Children =
|
|
{
|
|
new Label { GestureRecognizers = { tapPrevious } },
|
|
new Label { GestureRecognizers = { tap } }.GridRow(1),
|
|
new Label { GestureRecognizers = { tapNext } }.GridRow(2)
|
|
}
|
|
},
|
|
|
|
// downloading
|
|
downloading,
|
|
|
|
// loading original
|
|
original
|
|
}
|
|
};
|
|
#if __IOS__
|
|
grid.SetBinding(Xamarin.Forms.Layout.PaddingProperty, nameof(IllustDetailItem.TopPadding));
|
|
#endif
|
|
return grid;
|
|
});
|
|
}
|
|
|
|
private void LoadIllust(IllustItem illust)
|
|
{
|
|
if (illust == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var items = new IllustDetailItem[illust.PageCount];
|
|
if (items.Length > 1)
|
|
{
|
|
PagePositionText = $"1/{items.Length}";
|
|
}
|
|
|
|
#if __IOS__
|
|
var topMargin = PageTopMargin;
|
|
#endif
|
|
for (var i = 0; i < items.Length; i++)
|
|
{
|
|
items[i] = new IllustDetailItem
|
|
{
|
|
#if __IOS__
|
|
TopPadding = topMargin,
|
|
#endif
|
|
Id = illust.Id
|
|
};
|
|
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);
|
|
#if __IOS__
|
|
var topMargin = PageTopMargin;
|
|
#endif
|
|
for (var i = items.Length; i < tmp.Length; i++)
|
|
{
|
|
tmp[i] = new IllustDetailItem
|
|
{
|
|
Id = illustItem.Id,
|
|
#if __IOS__
|
|
TopPadding = topMargin,
|
|
#endif
|
|
Loading = i == 0
|
|
};
|
|
}
|
|
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);
|
|
MainThread.BeginInvokeOnMainThread(() =>
|
|
{
|
|
var count = illustItem.PageCount;
|
|
pageCount = count;
|
|
Title = illustItem.Title;
|
|
IsPageVisible = count > 1;
|
|
IsAnimateSliderVisible = illustItem.IsAnimeVisible;
|
|
ProgressVisible = count > 1;
|
|
});
|
|
if (preload.user.TryGetValue(illust.userId, out var user))
|
|
{
|
|
illustItem.ProfileUrl = user.image;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ParallelTask.Start(0, items.Length, Configs.MaxPageThreads, i =>
|
|
{
|
|
DoLoadImage(i);
|
|
return true;
|
|
});
|
|
|
|
if (illustItem.IsAnimeVisible)
|
|
{
|
|
// anime
|
|
ugoiraData = Stores.LoadIllustUgoiraData(illustItem.Id);
|
|
if (ugoiraData != null && ugoiraData.body != null)
|
|
{
|
|
var length = ugoiraData.body.frames.Length;
|
|
MaximumFrame = length > 0 ? length : 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
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 (index > 0 && !force)
|
|
{
|
|
if (item.Loading || 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, force: force);
|
|
if (image != null)
|
|
{
|
|
item.Image = image;
|
|
if(index == 0)
|
|
{
|
|
IllustItem.Image = image;
|
|
}
|
|
}
|
|
item.Loading = false;
|
|
RefreshProgress();
|
|
}
|
|
|
|
private void RefreshProgress()
|
|
{
|
|
if (pageCount <= 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lock (sync)
|
|
{
|
|
downloaded++;
|
|
}
|
|
if (downloaded >= pageCount)
|
|
{
|
|
MainThread.BeginInvokeOnMainThread(async () =>
|
|
{
|
|
ViewExtensions.CancelAnimations(progress);
|
|
await progress.ProgressTo(1, 250, Easing.CubicIn);
|
|
await progress.FadeTo(0, easing: Easing.CubicIn);
|
|
ProgressVisible = false;
|
|
});
|
|
}
|
|
else
|
|
{
|
|
var val = downloaded / (float)pageCount;
|
|
App.DebugPrint($"download progress: {val}");
|
|
MainThread.BeginInvokeOnMainThread(() =>
|
|
{
|
|
ViewExtensions.CancelAnimations(progress);
|
|
progress.ProgressTo(val, 250, Easing.CubicIn);
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
private void TapPrevious_Tapped(object sender, EventArgs e)
|
|
{
|
|
var index = CurrentPage;
|
|
if (index > 0)
|
|
{
|
|
IsScrollAnimated = false;
|
|
CurrentPage = index - 1;
|
|
IsScrollAnimated = true;
|
|
}
|
|
}
|
|
|
|
private void TapNext_Tapped(object sender, EventArgs e)
|
|
{
|
|
var index = CurrentPage;
|
|
var illusts = Illusts;
|
|
if (illusts != null && index < illusts.Length - 1)
|
|
{
|
|
IsScrollAnimated = false;
|
|
CurrentPage = index + 1;
|
|
IsScrollAnimated = true;
|
|
}
|
|
}
|
|
|
|
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;
|
|
illust.FavoriteDateUtc = DateTime.UtcNow;
|
|
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;
|
|
AnimeStatus = playing ? StyleDefinition.IconPause : StyleDefinition.IconPlay;
|
|
IsAnimateSliderEnabled = !playing;
|
|
ugoira.TogglePlay(playing);
|
|
illustItem.IsPlaying = playing;
|
|
}
|
|
else if (((VisualElement)sender).BindingContext is IllustDetailItem item)
|
|
{
|
|
if (illustItem.IsPlaying || !illustItem.IsAnimeVisible)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ugoira = new Ugoira(ugoiraData, item);
|
|
ugoira.FrameChanged += OnUgoiraFrameChanged;
|
|
AnimeStatus = StyleDefinition.IconPause;
|
|
illustItem.IsPlaying = true;
|
|
ugoira.TogglePlay(true);
|
|
}
|
|
}
|
|
|
|
private void OnUgoiraFrameChanged(object sender, UgoiraEventArgs e)
|
|
{
|
|
e.DetailItem.Image = e.Image;
|
|
CurrentAnimeFrame = e.FrameIndex;
|
|
}
|
|
|
|
private void Refresh_Clicked(object sender, EventArgs e)
|
|
{
|
|
Task.Run(() => DoLoadImage(CurrentPage, true));
|
|
}
|
|
|
|
private async void More_Clicked(object sender, EventArgs e)
|
|
{
|
|
int p = CurrentPage;
|
|
var illusts = Illusts;
|
|
if (illusts == null || p < 0 || p >= illusts.Length)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var item = illusts[p];
|
|
List<string> extras = new List<string>();
|
|
|
|
var share = ResourceHelper.Share;
|
|
var preview = Stores.GetPreviewImagePath(item.PreviewUrl);
|
|
if (preview != null)
|
|
{
|
|
extras.Add(share);
|
|
}
|
|
|
|
var userDetail = ResourceHelper.UserDetail;
|
|
extras.Add(userDetail);
|
|
|
|
var related = ResourceHelper.RelatedIllusts;
|
|
extras.Add(related);
|
|
|
|
#if __IOS__
|
|
var exportVideo = ResourceHelper.ExportVideo;
|
|
if (IsAnimateSliderVisible)
|
|
{
|
|
extras.Add(exportVideo);
|
|
}
|
|
#endif
|
|
|
|
var saveOriginal = ResourceHelper.SaveOriginal;
|
|
var illustItem = IllustItem;
|
|
var result = await DisplayActionSheet(
|
|
$"{illustItem.Title} (id: {illustItem.Id})",
|
|
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);
|
|
}
|
|
else if (result == related)
|
|
{
|
|
var page = new RelatedIllustsPage(illustItem);
|
|
await Navigation.PushAsync(page);
|
|
}
|
|
#if __IOS__
|
|
else if (result == exportVideo)
|
|
{
|
|
ExportVideo();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if __IOS__
|
|
private async void ExportVideo()
|
|
{
|
|
string msg = ResourceHelper.CantExportVideo;
|
|
|
|
if (ugoira != null && ugoiraData != null && ugoiraData.body != null)
|
|
{
|
|
if (Stores.CheckUgoiraVideo(ugoiraData.body.originalSrc))
|
|
{
|
|
var flag = await DisplayAlert(ResourceHelper.Operation,
|
|
ResourceHelper.AlreadySavedVideo,
|
|
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;
|
|
}
|
|
}
|
|
|
|
var success = await Task.Run(ugoira.ExportVideo); // ugoira.ExportGif
|
|
if (success != null)
|
|
{
|
|
var result = await FileStore.SaveVideoToGalleryAsync(success);
|
|
|
|
msg = result ?? ResourceHelper.ExportSuccess;
|
|
}
|
|
}
|
|
|
|
await DisplayAlert(ResourceHelper.Title, msg, ResourceHelper.Ok);
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
|
|
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));
|
|
#if __IOS__
|
|
public static readonly BindableProperty TopPaddingProperty = BindableProperty.Create(
|
|
nameof(TopPadding), typeof(Thickness), typeof(IllustDetailItem));
|
|
|
|
public Thickness TopPadding
|
|
{
|
|
get => (Thickness)GetValue(TopPaddingProperty);
|
|
set => SetValue(TopPaddingProperty, value);
|
|
}
|
|
#endif
|
|
|
|
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 string PreviewUrl { get; set; }
|
|
public string OriginalUrl { get; set; }
|
|
}
|
|
}
|