diff --git a/Pixiview.iOS/Effects/LongPressEffectImplement.cs b/Pixiview.iOS/Effects/LongPressEffectImplement.cs
new file mode 100644
index 0000000..00f6ead
--- /dev/null
+++ b/Pixiview.iOS/Effects/LongPressEffectImplement.cs
@@ -0,0 +1,58 @@
+using System.Threading.Tasks;
+using Pixiview.iOS.Effects;
+using Pixiview.Utils;
+using UIKit;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.iOS;
+
+[assembly: ResolutionGroupName("Pixiview")]
+[assembly: ExportEffect(typeof(LongPressEffectImplement), "LongPressEffect")]
+namespace Pixiview.iOS.Effects
+{
+ public class LongPressEffectImplement : PlatformEffect
+ {
+ private bool attached;
+ private readonly UILongPressGestureRecognizer longPressGesture;
+
+ public LongPressEffectImplement()
+ {
+ longPressGesture = new UILongPressGestureRecognizer(OnLongPressed);
+ }
+
+ protected override void OnAttached()
+ {
+ if (!attached)
+ {
+ attached = true;
+ Container.AddGestureRecognizer(longPressGesture);
+ }
+ }
+
+ protected override void OnDetached()
+ {
+ if (attached)
+ {
+ attached = false;
+ Container.RemoveGestureRecognizer(longPressGesture);
+ }
+ }
+
+ private void OnLongPressed(UILongPressGestureRecognizer e)
+ {
+ if (e.State != UIGestureRecognizerState.Began)
+ {
+ return;
+ }
+ var element = Element;
+ if (element != null)
+ {
+ var command = LongPressEffect.GetCommand(element);
+ if (command != null)
+ {
+ var o = LongPressEffect.GetCommandParameter(element);
+ command.Execute(o);
+ }
+ }
+ }
+ }
+}
diff --git a/Pixiview.iOS/Pixiview.iOS.csproj b/Pixiview.iOS/Pixiview.iOS.csproj
index 8b5ff94..e93e687 100644
--- a/Pixiview.iOS/Pixiview.iOS.csproj
+++ b/Pixiview.iOS/Pixiview.iOS.csproj
@@ -79,6 +79,7 @@
+
@@ -148,6 +149,7 @@
+
diff --git a/Pixiview.iOS/Services/EnvironmentService.cs b/Pixiview.iOS/Services/EnvironmentService.cs
index 9588281..307546e 100644
--- a/Pixiview.iOS/Services/EnvironmentService.cs
+++ b/Pixiview.iOS/Services/EnvironmentService.cs
@@ -29,29 +29,28 @@ namespace Pixiview.iOS.Services
#region - Theme -
[SuppressMessage("Code Notifications", "XI0002:Notifies you from using newer Apple APIs when targeting an older OS version", Justification = "")]
- public Theme GetApplicationTheme()
+ public OSAppTheme GetApplicationTheme()
{
if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{
var currentController = Platform.GetCurrentUIViewController();
if (currentController == null)
{
- return Theme.Light;
+ return OSAppTheme.Unspecified;
}
+
var style = currentController.TraitCollection.UserInterfaceStyle;
if (style == UIUserInterfaceStyle.Dark)
{
- return Theme.Dark;
+ return OSAppTheme.Dark;
}
- else
+ else if (style == UIUserInterfaceStyle.Light)
{
- return Theme.Light;
+ return OSAppTheme.Light;
}
}
- else
- {
- return Theme.Light;
- }
+
+ return OSAppTheme.Unspecified;
}
public void SetStatusBarStyle(StatusBarStyles style)
diff --git a/Pixiview/App.cs b/Pixiview/App.cs
index f924c2f..31ab7ed 100644
--- a/Pixiview/App.cs
+++ b/Pixiview/App.cs
@@ -11,7 +11,7 @@ namespace Pixiview
public class App : Application
{
// public properties
- public static Theme CurrentTheme { get; private set; }
+ public static OSAppTheme CurrentTheme { get; private set; }
public static PlatformCulture CurrentCulture { get; private set; }
public static Dictionary ExtraResources { get; private set; }
@@ -39,7 +39,7 @@ namespace Pixiview
CurrentCulture = new PlatformCulture(ci.Name.ToLower());
}
- private void SetTheme(Theme theme, bool force = false)
+ private void SetTheme(OSAppTheme theme, bool force = false)
{
if (force || theme != CurrentTheme)
{
@@ -51,7 +51,7 @@ namespace Pixiview
}
DebugPrint($"application theme: {theme}");
ThemeBase themeInstance;
- if (theme == Theme.Dark)
+ if (theme == OSAppTheme.Dark)
{
themeInstance = DarkTheme.Instance;
}
diff --git a/Pixiview/Illust/IllustCollectionPage.cs b/Pixiview/Illust/IllustCollectionPage.cs
index a0212ec..af674df 100644
--- a/Pixiview/Illust/IllustCollectionPage.cs
+++ b/Pixiview/Illust/IllustCollectionPage.cs
@@ -363,7 +363,6 @@ namespace Pixiview.Illust
public class IllustCollection : List
{
- private static readonly object sync = new object();
private static IllustCollection empty;
public static IllustCollection Empty
@@ -387,7 +386,8 @@ namespace Pixiview.Illust
running = true;
}
- private bool running;
+ private readonly object sync = new object();
+ private volatile bool running;
public bool Running
{
get => running;
diff --git a/Pixiview/Illust/ViewIllustPage.xaml b/Pixiview/Illust/ViewIllustPage.xaml
index 7420cbf..0dd2967 100644
--- a/Pixiview/Illust/ViewIllustPage.xaml
+++ b/Pixiview/Illust/ViewIllustPage.xaml
@@ -3,6 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mdl="clr-namespace:Pixiview.Illust"
xmlns:u="clr-namespace:Pixiview.UI"
+ xmlns:util="clr-namespace:Pixiview.Utils"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
x:Class="Pixiview.Illust.ViewIllustPage"
ios:Page.UseSafeArea="False"
@@ -11,7 +12,7 @@
Title="{Binding IllustItem.Title}">
+ IconImageSource="{Binding FavoriteIcon}"/>
+ Aspect="AspectFit"
+ util:LongPressEffect.Command="{Binding LongPressed}"
+ util:LongPressEffect.CommandParameter="{Binding .}">
+
+
+
+
(ImageSource)GetValue(IsFavoriteProperty);
+ public ImageSource FavoriteIcon
+ {
+ get => (ImageSource)GetValue(FavoriteIconProperty);
+ set => SetValue(FavoriteIconProperty, value);
+ }
public IllustDetailItem[] Illusts
{
@@ -50,22 +55,24 @@ namespace Pixiview.Illust
public int CurrentPage { get; private set; }
private readonly IIllustCollectionPage collectionPage;
- private readonly object fontIconLove;
- private readonly object fontIconNotLove;
+ private readonly ICommand longPressed;
+ private readonly ImageSource fontIconLove;
+ private readonly ImageSource fontIconNotLove;
public ViewIllustPage(IllustItem illust, IIllustCollectionPage page)
{
IllustItem = illust;
collectionPage = page;
+ longPressed = new Command(Illust_LongPressed);
BindingContext = this;
- fontIconLove = Application.Current.Resources[ThemeBase.FontIconLove];
- fontIconNotLove = Application.Current.Resources[ThemeBase.FontIconNotLove];
+ fontIconLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconLove];
+ fontIconNotLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconNotLove];
if (page.Favorites != null)
{
- SetValue(IsFavoriteProperty, page.Favorites.Any(i => i.Id == illust.Id)
+ FavoriteIcon = page.Favorites.Any(i => i.Id == illust.Id)
? fontIconLove
- : fontIconNotLove);
+ : fontIconNotLove;
}
InitializeComponent();
@@ -81,38 +88,6 @@ namespace Pixiview.Illust
OnOrientationChanged(CurrentOrientation);
}
- 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();
- if (i == 0)
- {
- items[i].Loading = true;
- items[i].Image = illust.Image;
- }
- }
-
- Illusts = items;
- Task.Run(DoLoadImages);
- }
-
protected override void OnAppearing()
{
base.OnAppearing();
@@ -135,27 +110,39 @@ namespace Pixiview.Illust
Screen.SetHomeIndicatorAutoHidden(Shell.Current, false);
}
- private void CarouselView_PositionChanged(object sender, PositionChangedEventArgs e)
+ private void LoadIllust(IllustItem illust)
{
- 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)
+ if (illust == null)
{
- Task.Run(() => DoLoadImage(index));
+ return;
}
- if (index < length - 1)
+
+ var items = new IllustDetailItem[illust.PageCount];
+ if (items.Length > 1)
{
- item = items[index + 1];
- if (!item.Loading && item.Image == null)
+ IsPageVisible = true;
+ PagePositionText = $"1/{items.Length}";
+ }
+ else
+ {
+ IsPageVisible = false;
+ }
+
+ for (var i = 0; i < items.Length; i++)
+ {
+ items[i] = new IllustDetailItem
{
- Task.Run(() => DoLoadImage(index + 1));
+ LongPressed = longPressed
+ };
+ if (i == 0)
+ {
+ items[i].Loading = true;
+ items[i].Image = illust.Image;
}
}
+
+ Illusts = items;
+ Task.Run(DoLoadImages);
}
private void DoLoadImages()
@@ -174,7 +161,10 @@ namespace Pixiview.Illust
items.CopyTo(items, 0);
for (var i = items.Length; i < tmp.Length; i++)
{
- tmp[i] = new IllustDetailItem();
+ tmp[i] = new IllustDetailItem
+ {
+ LongPressed = longPressed
+ };
}
items = tmp;
}
@@ -221,6 +211,29 @@ namespace Pixiview.Illust
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)
{
if (collectionPage.Favorites == null)
@@ -232,36 +245,55 @@ namespace Pixiview.Illust
{
collectionPage.Favorites.Insert(0, IllustItem);
IllustItem.IsFavorite = true;
- SetValue(IsFavoriteProperty, fontIconLove);
+ FavoriteIcon = fontIconLove;
}
else
{
collectionPage.Favorites.RemoveAt(index);
IllustItem.IsFavorite = false;
- SetValue(IsFavoriteProperty, fontIconNotLove);
+ FavoriteIcon = fontIconNotLove;
}
}
- private async void Download_Clicked(object sender, EventArgs e)
+ private async void Illust_LongPressed(IllustDetailItem item)
{
- var status = await Permissions.CheckStatusAsync();
- if (status != PermissionStatus.Granted)
+ var saveOriginal = ResourceHelper.SaveOriginal;
+ var result = await DisplayActionSheet(
+ IllustItem.Title,
+ ResourceHelper.Cancel,
+ saveOriginal);
+ if (result == saveOriginal)
{
- status = await Permissions.RequestAsync();
+ 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();
if (status != PermissionStatus.Granted)
{
- App.DebugPrint("access denied to gallery.");
+ status = await Permissions.RequestAsync();
+ if (status != PermissionStatus.Granted)
+ {
+ App.DebugPrint("access denied to gallery.");
+ return;
+ }
+ }
+
+ if (item == null || item.Downloading)
+ {
return;
}
+ item.Downloading = true;
+ _ = Task.Run(() => DoLoadOriginalImage(item));
}
-
- var item = Illusts[CurrentPage];
- if (item.Downloading)
- {
- return;
- }
- item.Downloading = true;
- _ = Task.Run(() => DoLoadOriginalImage(item));
}
private void DoLoadOriginalImage(IllustDetailItem item)
@@ -306,6 +338,7 @@ namespace Pixiview.Illust
get => (bool)GetValue(DownloadingProperty);
set => SetValue(DownloadingProperty, value);
}
+ public ICommand LongPressed { get; set; }
public string PreviewUrl { get; set; }
public string OriginalUrl { get; set; }
}
diff --git a/Pixiview/Resources/Languages/zh-CN.xml b/Pixiview/Resources/Languages/zh-CN.xml
index 7f595a9..5cad518 100644
--- a/Pixiview/Resources/Languages/zh-CN.xml
+++ b/Pixiview/Resources/Languages/zh-CN.xml
@@ -2,6 +2,9 @@
Pixiview
OK
+ 取消
+ 是
+ 否
R-18
已关注
推荐
@@ -11,5 +14,8 @@
收藏夹
预览
+ 操作
+ 保存原图
成功保存图片到照片库。
+ 原图已保存,是否继续?
\ No newline at end of file
diff --git a/Pixiview/Resources/ResourceHelper.cs b/Pixiview/Resources/ResourceHelper.cs
index fa1dc1a..f0722d7 100644
--- a/Pixiview/Resources/ResourceHelper.cs
+++ b/Pixiview/Resources/ResourceHelper.cs
@@ -12,8 +12,14 @@ namespace Pixiview.Resources
{
public static string Title => GetResource(nameof(Title));
public static string Ok => GetResource(nameof(Ok));
+ public static string Cancel => GetResource(nameof(Cancel));
+ public static string Yes => GetResource(nameof(Yes));
+ public static string No => GetResource(nameof(No));
public static string R18 => GetResource(nameof(R18));
+ public static string Operation => GetResource(nameof(Operation));
+ public static string SaveOriginal => GetResource(nameof(SaveOriginal));
public static string SaveSuccess => GetResource(nameof(SaveSuccess));
+ public static string AlreadySavedQuestion => GetResource(nameof(AlreadySavedQuestion));
static readonly Dictionary dict = new Dictionary();
diff --git a/Pixiview/UI/AdaptedPage.cs b/Pixiview/UI/AdaptedPage.cs
index 453cbe5..abae771 100644
--- a/Pixiview/UI/AdaptedPage.cs
+++ b/Pixiview/UI/AdaptedPage.cs
@@ -83,16 +83,12 @@ namespace Pixiview.UI
public static bool IsBusy => _instance?.isBusy == true;
private static readonly object sync = new object();
- private static Tap _instance;
+ private static readonly Tap _instance = new Tap();
private Tap() { }
public static Tap Start()
{
- if (_instance == null)
- {
- _instance = new Tap();
- }
lock (sync)
{
_instance.isBusy = true;
@@ -100,7 +96,7 @@ namespace Pixiview.UI
return _instance;
}
- private bool isBusy = false;
+ private volatile bool isBusy = false;
public void Dispose()
{
diff --git a/Pixiview/Utils/Converters.cs b/Pixiview/Utils/Converters.cs
index b8fe024..1dbaeda 100644
--- a/Pixiview/Utils/Converters.cs
+++ b/Pixiview/Utils/Converters.cs
@@ -1,7 +1,6 @@
using System;
using System.Globalization;
using Pixiview.UI;
-using Pixiview.UI.Theme;
using Xamarin.Forms;
namespace Pixiview.Utils
diff --git a/Pixiview/Utils/IEnvironmentService.cs b/Pixiview/Utils/IEnvironmentService.cs
index 015681b..ea7c9da 100644
--- a/Pixiview/Utils/IEnvironmentService.cs
+++ b/Pixiview/Utils/IEnvironmentService.cs
@@ -7,7 +7,7 @@ namespace Pixiview.Utils
{
EnvironmentParameter GetEnvironment();
- Theme GetApplicationTheme();
+ OSAppTheme GetApplicationTheme();
void SetStatusBarStyle(StatusBarStyles style);
void SetStatusBarColor(Color color);
@@ -22,10 +22,4 @@ namespace Pixiview.Utils
public string IconSolidFontFamily { get; set; }
public string IconLeft { get; set; }
}
-
- public enum Theme
- {
- Light,
- Dark
- }
}
diff --git a/Pixiview/Utils/LongPressEffect.cs b/Pixiview/Utils/LongPressEffect.cs
new file mode 100644
index 0000000..e01c879
--- /dev/null
+++ b/Pixiview/Utils/LongPressEffect.cs
@@ -0,0 +1,26 @@
+using System.Windows.Input;
+using Xamarin.Forms;
+
+namespace Pixiview.Utils
+{
+ public class LongPressEffect : RoutingEffect
+ {
+ private const string Command = nameof(Command);
+ private const string CommandParameter = nameof(CommandParameter);
+
+ public static readonly BindableProperty CommandProperty = BindableProperty.CreateAttached(
+ Command, typeof(ICommand), typeof(LongPressEffect), null);
+ public static readonly BindableProperty CommandParameterProperty = BindableProperty.CreateAttached(
+ CommandParameter, typeof(object), typeof(LongPressEffect), null);
+
+ public static ICommand GetCommand(BindableObject view) => (ICommand)view.GetValue(CommandProperty);
+ public static void SetCommand(BindableObject view, ICommand command) => view.SetValue(CommandProperty, command);
+
+ public static object GetCommandParameter(BindableObject view) => view.GetValue(CommandParameterProperty);
+ public static void SetCommandParameter(BindableObject view, object value) => view.SetValue(CommandParameterProperty, value);
+
+ public LongPressEffect() : base("Pixiview.LongPressEffect")
+ {
+ }
+ }
+}
diff --git a/Pixiview/Utils/Stores.cs b/Pixiview/Utils/Stores.cs
index 6080675..ac7f4d3 100644
--- a/Pixiview/Utils/Stores.cs
+++ b/Pixiview/Utils/Stores.cs
@@ -182,7 +182,10 @@ namespace Pixiview.Utils
public static IllustFavorite LoadFavoritesIllusts()
{
var file = Path.Combine(PersonalFolder, favoriteFile);
- return ReadObject(file);
+ lock (sync)
+ {
+ return ReadObject(file);
+ }
}
public static void SaveFavoritesIllusts(IllustFavorite data)
@@ -214,6 +217,12 @@ namespace Pixiview.Utils
return LoadImage(url, CacheFolder, userFolder);
}
+ public static bool CheckIllustImage(string url)
+ {
+ var file = Path.Combine(PersonalFolder, imageFolder, Path.GetFileName(url));
+ return File.Exists(file);
+ }
+
private static ImageSource LoadImage(string url, string working, string folder)
{
var file = Path.Combine(working, folder, Path.GetFileName(url));