diff --git a/Pixiview/Illust/ViewIllustPage.xaml b/Pixiview/Illust/ViewIllustPage.xaml
index cbc3c19..2849fba 100644
--- a/Pixiview/Illust/ViewIllustPage.xaml
+++ b/Pixiview/Illust/ViewIllustPage.xaml
@@ -1,9 +1,7 @@
+
+
+
+
+
-
+
+
diff --git a/Pixiview/Illust/ViewIllustPage.xaml.cs b/Pixiview/Illust/ViewIllustPage.xaml.cs
index d9016f3..6d551f2 100644
--- a/Pixiview/Illust/ViewIllustPage.xaml.cs
+++ b/Pixiview/Illust/ViewIllustPage.xaml.cs
@@ -2,7 +2,6 @@
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;
@@ -22,10 +21,51 @@ namespace Pixiview.Illust
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 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 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 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}";
+
+ var item = items[index];
+ if (!item.Loading && item.Image == null)
+ {
+ Task.Run(() => page.DoLoadImage(index));
+ }
+ if (index < length - 1)
+ {
+ item = items[index + 1];
+ if (!item.Loading && item.Image == null)
+ {
+ Task.Run(() => page.DoLoadImage(index + 1));
+ }
+ }
+ }
+
+ 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
{
@@ -43,21 +83,41 @@ namespace Pixiview.Illust
get => (string)GetValue(PagePositionTextProperty);
set => SetValue(PagePositionTextProperty, value);
}
- public bool IsPageVisible
+ public int CurrentPage
{
- get => (bool)GetValue(IsPageVisibleProperty);
- set => SetValue(IsPageVisibleProperty, value);
+ get => (int)GetValue(CurrentPageProperty);
+ private set => SetValue(CurrentPageProperty, value);
}
- public IllustItem IllustItem
+ public bool IsScrollAnimated
{
- get => (IllustItem)GetValue(IllustItemProperty);
- set => SetValue(IllustItemProperty, value);
+ 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 int CurrentPage { get; private set; }
+ public IllustItem IllustItem { get; private set; }
+ public bool IsPageVisible { get; private set; }
private readonly bool saveFavorites;
- private readonly ICommand longPressed;
private readonly ImageSource fontIconLove;
private readonly ImageSource fontIconNotLove;
private IllustUgoiraData ugoiraData;
@@ -67,7 +127,6 @@ namespace Pixiview.Illust
{
IllustItem = illust;
saveFavorites = save;
- longPressed = new Command(Illust_LongPressed);
BindingContext = this;
fontIconLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconLove];
@@ -77,7 +136,9 @@ namespace Pixiview.Illust
? fontIconLove
: fontIconNotLove;
- Resources.Add("carouselView", GetCarouseTemplate());
+ var pageVisible = illust != null && illust.PageCount > 1;
+ IsPageVisible = pageVisible;
+ Resources.Add("carouselView", GetCarouseTemplate(pageVisible));
InitializeComponent();
@@ -115,65 +176,111 @@ namespace Pixiview.Illust
Screen.SetHomeIndicatorAutoHidden(Shell.Current, false);
}
- private DataTemplate GetCarouseTemplate()
+ private DataTemplate GetCarouseTemplate(bool multiPages)
{
- var isAnime = IllustItem.IllustType == IllustType.Anime;
var tap = new TapGestureRecognizer();
tap.Tapped += Image_Tapped;
return new DataTemplate(() =>
{
+ // image
var image = new Image
{
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill,
- Aspect = Aspect.AspectFit
+ Aspect = Aspect.AspectFit,
+ GestureRecognizers = { tap }
}
.Binding(Image.SourceProperty, nameof(IllustDetailItem.Image));
- if (isAnime)
+
+ // downloading
+ var downloading = new Frame
{
- image.GestureRecognizers.Add(tap);
+ HasShadow = false,
+ Margin = default,
+ Padding = new Thickness(20),
+ CornerRadius = 8,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center,
+ Content = new ActivityIndicator
+ {
+ IsRunning = true,
+ IsVisible = true
+ }
+ .DynamicResource(ActivityIndicator.ColorProperty, ThemeBase.WindowColor)
}
- else
+ .Binding(IsVisibleProperty, nameof(IllustDetailItem.Loading))
+ .DynamicResource(BackgroundColorProperty, ThemeBase.MaskColor);
+
+ // loading original
+ var original = new ActivityIndicator
{
- image.SetBinding(LongPressEffect.CommandProperty, nameof(IllustDetailItem.LongPressed));
- image.SetBinding(LongPressEffect.CommandParameterProperty, ".");
- image.Effects.Add(new LongPressEffect());
+ IsRunning = true,
+ Margin = new Thickness(10),
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Start
+ }
+ .Binding(IsVisibleProperty, nameof(IllustDetailItem.Downloading))
+ .DynamicResource(ActivityIndicator.ColorProperty, ThemeBase.TextColor);
+
+ if (multiPages)
+ {
+ var tapPrevious = new TapGestureRecognizer();
+ tapPrevious.Tapped += TapPrevious_Tapped;
+ var tapNext = new TapGestureRecognizer();
+ tapNext.Tapped += TapNext_Tapped;
+
+ return new Grid
+ {
+ Children =
+ {
+ // image
+ image,
+
+ // tap holder
+ new Grid
+ {
+ RowDefinitions =
+ {
+ new RowDefinition(),
+ new RowDefinition(),
+ new RowDefinition()
+ },
+ Children =
+ {
+ new Label
+ {
+ GestureRecognizers = { tapPrevious }
+ },
+ new Label
+ {
+ GestureRecognizers = { tapNext }
+ }
+ .GridRow(2)
+ }
+ },
+
+ // downloading
+ downloading,
+
+ // loading original
+ original
+ }
+ };
}
return new Grid
{
Children =
{
+ // image
image,
- new Frame
- {
- HasShadow = false,
- Margin = default,
- Padding = new Thickness(20),
- CornerRadius = 8,
- HorizontalOptions = LayoutOptions.Center,
- VerticalOptions = LayoutOptions.Center,
- Content = new ActivityIndicator
- {
- IsRunning = true,
- IsVisible = true
- }
- .DynamicResource(ActivityIndicator.ColorProperty, ThemeBase.WindowColor)
- }
- .Binding(IsVisibleProperty, nameof(IllustDetailItem.Loading))
- .DynamicResource(BackgroundColorProperty, ThemeBase.MaskColor),
+ // downloading
+ downloading,
- new ActivityIndicator
- {
- IsRunning = true,
- Margin = new Thickness(10),
- HorizontalOptions = LayoutOptions.Start,
- VerticalOptions = LayoutOptions.Start
- }
- .Binding(IsVisibleProperty, nameof(IllustDetailItem.Downloading))
- .DynamicResource(ActivityIndicator.ColorProperty, ThemeBase.TextColor)
+ // loading original
+ original
}
};
});
@@ -189,20 +296,14 @@ namespace Pixiview.Illust
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
+ Id = illust.Id
};
if (i == 0)
{
@@ -234,8 +335,7 @@ namespace Pixiview.Illust
{
tmp[i] = new IllustDetailItem
{
- Id = illustItem.Id,
- LongPressed = longPressed
+ Id = illustItem.Id
};
}
Illusts = items = tmp;
@@ -277,6 +377,12 @@ namespace Pixiview.Illust
{
// anime
ugoiraData = Stores.LoadIllustUgoiraData(illustItem.Id);
+ if (ugoiraData != null && ugoiraData.body != null)
+ {
+ var length = ugoiraData.body.frames.Length;
+ MaximumFrame = length > 0 ? length : 1;
+ IsAnimateSliderVisible = true;
+ }
}
}
@@ -309,24 +415,29 @@ namespace Pixiview.Illust
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}";
+ CurrentPage = e.CurrentPosition;
+ }
- var item = items[index];
- if (!item.Loading && item.Image == null)
+ private void TapPrevious_Tapped(object sender, EventArgs e)
+ {
+ var index = CurrentPage;
+ if (index > 0)
{
- Task.Run(() => DoLoadImage(index));
+ IsScrollAnimated = false;
+ CurrentPage = index - 1;
+ IsScrollAnimated = true;
}
- if (index < length - 1)
+ }
+
+ private void TapNext_Tapped(object sender, EventArgs e)
+ {
+ var index = CurrentPage;
+ var illusts = Illusts;
+ if (illusts != null && index < illusts.Length - 1)
{
- item = items[index + 1];
- if (!item.Loading && item.Image == null)
- {
- Task.Run(() => DoLoadImage(index + 1));
- }
+ IsScrollAnimated = false;
+ CurrentPage = index + 1;
+ IsScrollAnimated = true;
}
}
@@ -360,6 +471,7 @@ namespace Pixiview.Illust
if (ugoira != null)
{
var playing = !ugoira.IsPlaying;
+ IsAnimateSliderEnabled = !playing;
ugoira.TogglePlay(playing);
illustItem.IsPlaying = playing;
}
@@ -381,10 +493,20 @@ namespace Pixiview.Illust
private void OnUgoiraFrameChanged(object sender, UgoiraEventArgs e)
{
e.DetailItem.Image = e.Image;
+ CurrentAnimeFrame = e.FrameIndex;
}
- private async void Illust_LongPressed(IllustDetailItem item)
+ 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 extras = new List();
var share = ResourceHelper.Share;
var preview = Stores.GetPreviewImagePath(item.PreviewUrl);
@@ -496,7 +618,6 @@ namespace Pixiview.Illust
set => SetValue(DownloadingProperty, value);
}
public string Id { get; set; }
- public ICommand LongPressed { get; set; }
public string PreviewUrl { get; set; }
public string OriginalUrl { get; set; }
}
diff --git a/Pixiview/Utils/HttpUtility.cs b/Pixiview/Utils/HttpUtility.cs
index c2c02b5..f22e1ec 100644
--- a/Pixiview/Utils/HttpUtility.cs
+++ b/Pixiview/Utils/HttpUtility.cs
@@ -302,6 +302,7 @@ namespace Pixiview.Utils
private int index = 0;
public bool IsPlaying { get; private set; }
+ public readonly int FrameCount;
public event EventHandler FrameChanged;
public Ugoira(IllustUgoiraData illust, IllustDetailItem item)
@@ -309,6 +310,7 @@ namespace Pixiview.Utils
ugoira = illust.body;
detailItem = item;
frames = new ImageSource[ugoira.frames.Length];
+ FrameCount = frames.Length;
timer = new Timer(OnTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
Task.Run(LoadFrames);
@@ -332,6 +334,30 @@ namespace Pixiview.Utils
}
}
+ public void ToggleFrame(int frame)
+ {
+ if (IsPlaying)
+ {
+ // TODO: doesn't support change current frame when playing
+ return;
+ }
+ if (frame < 0 || frame >= frames.Length)
+ {
+ return;
+ }
+ var image = frames[frame];
+ if (image != null)
+ {
+ index = frame;
+ FrameChanged?.Invoke(this, new UgoiraEventArgs
+ {
+ DetailItem = detailItem,
+ Image = image,
+ FrameIndex = frame
+ });
+ }
+ }
+
private void OnTimerCallback(object state)
{
if (!IsPlaying)
@@ -350,7 +376,8 @@ namespace Pixiview.Utils
FrameChanged?.Invoke(this, new UgoiraEventArgs
{
DetailItem = detailItem,
- Image = frame
+ Image = frame,
+ FrameIndex = i
});
i++;
if (i >= frames.Length)
@@ -498,5 +525,6 @@ namespace Pixiview.Utils
{
public IllustDetailItem DetailItem { get; set; }
public ImageSource Image { get; set; }
+ public int FrameIndex { get; set; }
}
}