diff --git a/Pixiview.Android/Properties/AndroidManifest.xml b/Pixiview.Android/Properties/AndroidManifest.xml index 34ea860..d9772fa 100644 --- a/Pixiview.Android/Properties/AndroidManifest.xml +++ b/Pixiview.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/Pixiview.iOS.OpenExtension/Info.plist b/Pixiview.iOS.OpenExtension/Info.plist index 08b0851..34ea8b4 100644 --- a/Pixiview.iOS.OpenExtension/Info.plist +++ b/Pixiview.iOS.OpenExtension/Info.plist @@ -29,8 +29,8 @@ com.apple.share-services CFBundleShortVersionString - 1.0.515 + 1.0.516 CFBundleVersion - 5 + 6 diff --git a/Pixiview.iOS/Info.plist b/Pixiview.iOS/Info.plist index 7e87a65..9e6c1d6 100644 --- a/Pixiview.iOS/Info.plist +++ b/Pixiview.iOS/Info.plist @@ -79,8 +79,8 @@ CFBundleShortVersionString - 1.0.515 + 1.0.516 CFBundleVersion - 5 + 6 diff --git a/Pixiview/App.cs b/Pixiview/App.cs index 2fb522e..7ebea65 100644 --- a/Pixiview/App.cs +++ b/Pixiview/App.cs @@ -176,8 +176,7 @@ namespace Pixiview if (result == opReplace) { // replace favorite file - File.Delete(path); - File.Move(url, path); + File.Copy(url, path, true); } else if (result == opCombine) { @@ -191,8 +190,6 @@ namespace Pixiview Stores.SaveFavoritesIllusts(); } - File.Delete(url); - if (Shell.Current.CurrentState.Location.OriginalString.EndsWith(Routes.Favorites)) { var sc = (IShellSectionController)Shell.Current.CurrentItem.CurrentItem; @@ -205,7 +202,7 @@ namespace Pixiview } else { - File.Move(url, path); + File.Copy(url, path); if (Shell.Current.CurrentState.Location.OriginalString.EndsWith(Routes.Favorites)) { var sc = (IShellSectionController)Shell.Current.CurrentItem.CurrentItem; diff --git a/Pixiview/Illust/FavoritesPage.xaml b/Pixiview/Illust/FavoritesPage.xaml index b82fe5e..f59cb82 100644 --- a/Pixiview/Illust/FavoritesPage.xaml +++ b/Pixiview/Illust/FavoritesPage.xaml @@ -8,15 +8,24 @@ BackgroundColor="{DynamicResource WindowColor}" Title="{r:Text Favorites}"> + - + + + + diff --git a/Pixiview/Illust/FavoritesPage.xaml.cs b/Pixiview/Illust/FavoritesPage.xaml.cs index e3673a4..ba39843 100644 --- a/Pixiview/Illust/FavoritesPage.xaml.cs +++ b/Pixiview/Illust/FavoritesPage.xaml.cs @@ -9,6 +9,8 @@ namespace Pixiview.Illust { public partial class FavoritesPage : FavoriteIllustCollectionPage { + private bool flag = false; + public FavoritesPage() { Resources.Add("cardView", GetCardViewTemplate()); @@ -16,16 +18,8 @@ namespace Pixiview.Illust } protected override bool IsFavoriteVisible => false; - - protected override void OnAppearing() - { - //base.OnAppearing(); - Device.StartTimer(TimeSpan.FromMilliseconds(200), () => - { - Reload(); - return false; - }); - } + protected override ActivityIndicator LoadingIndicator => activityLoading; + protected override bool IsDelayLoading => true; protected override IEnumerable DoGetIllustList(IllustItem[] data) { @@ -34,7 +28,8 @@ namespace Pixiview.Illust protected override IllustItem[] DoLoadIllustData(bool force) { - var favorites = Stores.GetFavoriteObject(force); + var favorites = Stores.GetFavoriteObject(flag); + flag = false; if (favorites == null) { return null; @@ -54,9 +49,20 @@ namespace Pixiview.Illust public void Reload(bool force = false) { lastUpdated = default; + if (force) + { + flag = true; + } StartLoad(force); } + private void Refresh_Clicked(object sender, EventArgs e) + { + flag = false; + lastUpdated = default; + StartLoad(true); + } + private async void ShareFavorites_Clicked(object sender, EventArgs e) { var file = Stores.FavoritesPath; diff --git a/Pixiview/Illust/IllustCollectionPage.cs b/Pixiview/Illust/IllustCollectionPage.cs index 557d293..e7e1302 100644 --- a/Pixiview/Illust/IllustCollectionPage.cs +++ b/Pixiview/Illust/IllustCollectionPage.cs @@ -7,7 +7,6 @@ using Pixiview.Resources; using Pixiview.UI; using Pixiview.UI.Theme; using Pixiview.Utils; -using Xamarin.Essentials; using Xamarin.Forms; namespace Pixiview.Illust @@ -24,6 +23,9 @@ namespace Pixiview.Illust } public abstract class IllustCollectionPage : AdaptedPage, IIllustCollectionPage { + protected static readonly Thickness normalMargin = new Thickness(16); + protected static readonly Thickness loadingMargin = new Thickness(16, 46, 0, 0); + #region - Properties - public static readonly BindableProperty IllustsProperty = BindableProperty.Create( @@ -32,6 +34,8 @@ namespace Pixiview.Illust nameof(Columns), typeof(int), typeof(IllustCollectionPage), 2); public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create( nameof(IsLoading), typeof(bool), typeof(IllustCollectionPage), true); + public static readonly BindableProperty IsBottomLoadingProperty = BindableProperty.Create( + nameof(IsBottomLoading), typeof(bool), typeof(IllustCollectionPage), false); public IllustCollection Illusts { @@ -48,6 +52,11 @@ namespace Pixiview.Illust get => (bool)GetValue(IsLoadingProperty); set => SetValue(IsLoadingProperty, value); } + public bool IsBottomLoading + { + get => (bool)GetValue(IsBottomLoadingProperty); + set => SetValue(IsBottomLoadingProperty, value); + } #endregion @@ -56,6 +65,10 @@ namespace Pixiview.Illust public IllustCollection IllustCollection { get; set; } protected virtual bool IsFavoriteVisible => true; + protected virtual ActivityIndicator LoadingIndicator => null; + protected virtual bool IsDelayLoading => false; + protected virtual double IndicatorMarginTop => 16; + protected readonly Command commandIllustImageTapped; protected DateTime lastUpdated; protected double topOffset; @@ -88,15 +101,10 @@ namespace Pixiview.Illust protected override void OnAppearing() { base.OnAppearing(); - Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged; if (lastUpdated != LastUpdated) { - Device.StartTimer(TimeSpan.FromMilliseconds(200), () => - { - StartLoad(); - return false; - }); + StartLoad(); } else if (IsFavoriteVisible && IllustCollection != null) { @@ -108,23 +116,6 @@ namespace Pixiview.Illust } } - protected override void OnDisappearing() - { - Connectivity.ConnectivityChanged -= Connectivity_ConnectivityChanged; - base.OnDisappearing(); - } - - private void Connectivity_ConnectivityChanged(object sender, ConnectivityChangedEventArgs e) - { - if (e.NetworkAccess == NetworkAccess.Internet) - { - if (lastUpdated != LastUpdated) - { - StartLoad(true); - } - } - } - protected override void OnSizeAllocated(double width, double height) { base.OnSizeAllocated(width, height); @@ -188,19 +179,87 @@ namespace Pixiview.Illust var page = new ViewIllustPage(illust, IsFavoriteVisible); Navigation.PushAsync(page); } - protected virtual void DoIllustsLoaded(IllustCollection collection) + protected virtual void DoIllustsLoaded(IllustCollection collection, bool bottom) { IllustCollection = collection; - Illusts = collection; + var indicator = LoadingIndicator; + if (indicator == null) + { + Illusts = collection; + IsLoading = false; + IsBottomLoading = false; + } + else + { + var offset = 16 - IndicatorMarginTop; + indicator.Animate("margin", top => + { + indicator.Margin = new Thickness(0, top, 0, offset); + }, + 16 - offset, -40 - offset, easing: Easing.CubicIn, finished: (v, r) => + { + IsLoading = false; + IsBottomLoading = false; + if (IsDelayLoading) + { + Device.StartTimer(TimeSpan.FromMilliseconds(250), () => + { + Illusts = collection; + return false; + }); + } + else + { + Illusts = collection; + } + }); + } } - protected void StartLoad(bool force = false) + protected virtual void StartLoad(bool force = false, bool isBottom = false) { if (force || lastUpdated != LastUpdated) { lastUpdated = LastUpdated; - IsLoading = true; - Task.Run(() => DoLoadIllusts(force)); + + var indicator = LoadingIndicator; + if (indicator == null) + { + if (isBottom) + { + IsBottomLoading = true; + } + else + { + IsLoading = true; + } + Device.StartTimer(TimeSpan.FromMilliseconds(250), () => + { + Task.Run(() => DoLoadIllusts(force, isBottom)); + return false; + }); + } + else + { + var offset = 16 - IndicatorMarginTop; + indicator.Margin = new Thickness(0, -40 - offset, 0, offset); + if (isBottom) + { + IsBottomLoading = true; + } + else + { + IsLoading = true; + } + indicator.Animate("margin", top => + { + indicator.Margin = new Thickness(0, top, 0, offset); + }, + -40 - offset, 16 - offset, easing: Easing.CubicOut, finished: (v, r) => + { + Task.Run(() => DoLoadIllusts(force, isBottom)); + }); + } } } @@ -425,7 +484,7 @@ namespace Pixiview.Illust #region - Illust Tasks - - protected void DoLoadIllusts(bool force = false) + protected void DoLoadIllusts(bool force = false, bool bottom = false) { App.DebugPrint($"start loading data, force: {force}"); illustData = DoLoadIllustData(force); @@ -433,6 +492,7 @@ namespace Pixiview.Illust { //App.DebugError("illusts.load", "failed to load illusts data."); IsLoading = false; + IsBottomLoading = false; return; } if (force && IsFavoriteVisible) @@ -458,8 +518,7 @@ namespace Pixiview.Illust item.IsFavorite = favorites.Any(i => i.Id == item.Id); } } - DoIllustsLoaded(collection); - IsLoading = false; + DoIllustsLoaded(collection, bottom); DoLoadImages(collection); } @@ -505,9 +564,9 @@ namespace Pixiview.Illust public abstract class IllustScrollableCollectionPage : IllustCollectionPage { protected const int SCROLL_OFFSET = 33; - protected readonly object sync = new object(); private double lastScrollY = double.MinValue; + private double lastRefreshY = double.MinValue; private double offset; protected bool ScrollingDown(double y) @@ -521,19 +580,48 @@ namespace Pixiview.Illust protected abstract bool CheckRefresh(); - protected override void DoIllustsLoaded(IllustCollection collection) + protected override void StartLoad(bool force = false, bool isBottom = false) + { + if (!isBottom) + { + lastRefreshY = double.MinValue; + } + base.StartLoad(force, isBottom); + } + + protected override void DoIllustsLoaded(IllustCollection collection, bool bottom) { var now = IllustCollection; if (now == null) { - IllustCollection = collection; - Illusts = collection; + now = collection; } else { now = new IllustCollection(now.Concat(collection)); - IllustCollection = now; + } + IllustCollection = now; + + var indicator = LoadingIndicator; + if (indicator == null) + { Illusts = now; + IsLoading = false; + IsBottomLoading = false; + } + else + { + var offset = 16 - IndicatorMarginTop; + indicator.Animate("margin", top => + { + indicator.Margin = new Thickness(0, top, 0, offset); + }, + 16 - offset, -40 - offset, easing: Easing.CubicIn, finished: (v, r) => + { + IsLoading = false; + IsBottomLoading = false; + Illusts = now; + }); } } @@ -543,23 +631,19 @@ namespace Pixiview.Illust if (y > 0 && offset > 0 && y - topOffset > offset) { - bool refresh = false; - lock (sync) + if (IsLoading || IsBottomLoading) + { + return; + } + if (y - lastRefreshY > 100) { - if (IsLoading) - { - return; - } if (CheckRefresh()) { - refresh = true; + lastRefreshY = y; + App.DebugPrint("start to load next page"); + StartLoad(true, true); } } - if (refresh) - { - App.DebugPrint("start to load next page"); - StartLoad(true); - } } } } @@ -684,6 +768,8 @@ namespace Pixiview.Illust [JsonProperty] public string Id { get; set; } [JsonProperty] + public DateTime FavoriteDateUtc { get; set; } + [JsonProperty] public string ImageUrl { get; set; } [JsonProperty] public bool IsRestrict { get; set; } diff --git a/Pixiview/Illust/MainPage.xaml b/Pixiview/Illust/MainPage.xaml index b87978c..9b865ee 100644 --- a/Pixiview/Illust/MainPage.xaml +++ b/Pixiview/Illust/MainPage.xaml @@ -14,16 +14,22 @@ - - - - - + + + + + + + + - - - diff --git a/Pixiview/Illust/MainPage.xaml.cs b/Pixiview/Illust/MainPage.xaml.cs index d52de59..c645e23 100644 --- a/Pixiview/Illust/MainPage.xaml.cs +++ b/Pixiview/Illust/MainPage.xaml.cs @@ -35,6 +35,9 @@ namespace Pixiview.Illust #endif } + protected override ActivityIndicator LoadingIndicator => activityLoading; + protected override double IndicatorMarginTop => 66; + protected override IEnumerable DoGetIllustList(IllustData data) { if (data.body == null) diff --git a/Pixiview/Illust/RankingPage.xaml b/Pixiview/Illust/RankingPage.xaml index 3937ff1..712becc 100644 --- a/Pixiview/Illust/RankingPage.xaml +++ b/Pixiview/Illust/RankingPage.xaml @@ -48,10 +48,20 @@ - + + + + + - - - activityLoading; + protected override void OnAppearing() { var r18 = Configs.IsOnR18; @@ -341,12 +343,9 @@ namespace Pixiview.Illust var query = QueryKey; ToggleFilterPanel(false); - lock (sync) + if (IsLoading) { - if (IsLoading) - { - return; - } + return; } //if (lastQueryKey != query) { diff --git a/Pixiview/Illust/RecommendsPage.xaml b/Pixiview/Illust/RecommendsPage.xaml index e9d8789..44d5987 100644 --- a/Pixiview/Illust/RecommendsPage.xaml +++ b/Pixiview/Illust/RecommendsPage.xaml @@ -14,6 +14,10 @@ + - - - diff --git a/Pixiview/Illust/RecommendsPage.xaml.cs b/Pixiview/Illust/RecommendsPage.xaml.cs index 1bdcffc..4b1c570 100644 --- a/Pixiview/Illust/RecommendsPage.xaml.cs +++ b/Pixiview/Illust/RecommendsPage.xaml.cs @@ -36,6 +36,8 @@ namespace Pixiview.Illust private readonly Command commandUserTapped; + private IllustData illustData; + public RecommendsPage() { Resources.Add("cardView", GetCardViewTemplate()); @@ -45,6 +47,8 @@ namespace Pixiview.Illust commandUserTapped = new Command(OnIllustUserItemTapped); } + protected override ActivityIndicator LoadingIndicator => activityLoading; + private void OnIllustUserItemTapped(IllustUserItem item) { Start(async () => @@ -184,9 +188,18 @@ namespace Pixiview.Illust } } - protected override void DoIllustsLoaded(IllustCollection collection) + protected override void DoIllustsLoaded(IllustCollection collection, bool bottom) { - IllustCollection = collection; + //IsLoading = false; + if (illustData != null) + { + IllustCollection = collection; + Task.Run(() => DoLoadUserRecommendsData(illustData)); + } + else + { + base.DoIllustsLoaded(collection, bottom); + } } protected override IEnumerable DoGetIllustList(IllustData data) @@ -201,8 +214,7 @@ namespace Pixiview.Illust protected override IllustData DoLoadIllustData(bool force) { - var illustData = Stores.LoadIllustData(force); - Task.Run(() => DoLoadUserRecommendsData(illustData)); + illustData = Stores.LoadIllustData(force); return illustData; } @@ -259,9 +271,17 @@ namespace Pixiview.Illust }).Where(u => u != null); var list = new List(users); - UserRecommendsVisible = list.Count > 0; - Users = list; - Illusts = IllustCollection; + activityLoading.Animate("margin", top => + { + activityLoading.Margin = new Thickness(0, top, 0, 0); + }, + 16, -40, easing: Easing.CubicIn, finished: (v, r) => + { + IsLoading = false; + UserRecommendsVisible = list.Count > 0; + Users = list; + Illusts = IllustCollection; + }); DoLoadUserRecommendsImages(list); } diff --git a/Pixiview/Illust/RelatedIllustsPage.xaml b/Pixiview/Illust/RelatedIllustsPage.xaml index 58dfbc1..eb77aa8 100644 --- a/Pixiview/Illust/RelatedIllustsPage.xaml +++ b/Pixiview/Illust/RelatedIllustsPage.xaml @@ -14,17 +14,20 @@ - + + + + + - - - diff --git a/Pixiview/Illust/RelatedIllustsPage.xaml.cs b/Pixiview/Illust/RelatedIllustsPage.xaml.cs index e25e031..e96adcd 100644 --- a/Pixiview/Illust/RelatedIllustsPage.xaml.cs +++ b/Pixiview/Illust/RelatedIllustsPage.xaml.cs @@ -27,6 +27,8 @@ namespace Pixiview.Illust nextIndex = 0; } + protected override ActivityIndicator LoadingIndicator => activityLoading; + protected override IEnumerable DoGetIllustList(IllustRecommendsData data) { if (data.body == null) @@ -92,12 +94,13 @@ namespace Pixiview.Illust OnScrolled(y); } - private void Refresh_Clicked(object sender, EventArgs e) + private async void Refresh_Clicked(object sender, EventArgs e) { if (IsLoading) { return; } + await scrollView.ScrollToAsync(0, -topOffset, true); // release var collection = IllustCollection; if (collection != null) diff --git a/Pixiview/Illust/UserIllustPage.xaml b/Pixiview/Illust/UserIllustPage.xaml index 83615b9..eae6f1a 100644 --- a/Pixiview/Illust/UserIllustPage.xaml +++ b/Pixiview/Illust/UserIllustPage.xaml @@ -26,17 +26,20 @@ - + + + + + - - - diff --git a/Pixiview/Illust/UserIllustPage.xaml.cs b/Pixiview/Illust/UserIllustPage.xaml.cs index 07539c7..e3110ec 100644 --- a/Pixiview/Illust/UserIllustPage.xaml.cs +++ b/Pixiview/Illust/UserIllustPage.xaml.cs @@ -38,6 +38,8 @@ namespace Pixiview.Illust nextIndex = 0; } + protected override ActivityIndicator LoadingIndicator => activityLoading; + protected override IEnumerable DoGetIllustList(IllustUserData data) { if (data.body == null) @@ -58,6 +60,7 @@ namespace Pixiview.Illust return null; } illustIds = init.body.illusts.Keys.OrderByDescending(i => i).ToArray(); + App.DebugPrint($"user has ({illustIds.Length}) illusts."); startIndex = 0; } @@ -101,12 +104,13 @@ namespace Pixiview.Illust OnScrolled(y); } - private void Refresh_Clicked(object sender, EventArgs e) + private async void Refresh_Clicked(object sender, EventArgs e) { if (IsLoading) { return; } + await scrollView.ScrollToAsync(0, -topOffset, true); // release var collection = IllustCollection; if (collection != null) diff --git a/Pixiview/Illust/ViewIllustPage.xaml b/Pixiview/Illust/ViewIllustPage.xaml index 7669abe..69e29fa 100644 --- a/Pixiview/Illust/ViewIllustPage.xaml +++ b/Pixiview/Illust/ViewIllustPage.xaml @@ -10,6 +10,8 @@ + diff --git a/Pixiview/Illust/ViewIllustPage.xaml.cs b/Pixiview/Illust/ViewIllustPage.xaml.cs index 817999a..40dfbfe 100644 --- a/Pixiview/Illust/ViewIllustPage.xaml.cs +++ b/Pixiview/Illust/ViewIllustPage.xaml.cs @@ -359,7 +359,7 @@ namespace Pixiview.Illust ParallelTask.Start(0, items.Length, Configs.MaxPageThreads, i => { - DoLoadImage(i, i == 0); + DoLoadImage(i); return true; }); @@ -385,16 +385,16 @@ namespace Pixiview.Illust } var item = items[index]; - if (!force) + if (index > 0) { - if (item.Loading || (index > 0 && item.Image != null)) + 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); + var image = Stores.LoadPreviewImage(item.PreviewUrl, force: force); if (image != null) { item.Image = image; @@ -472,6 +472,7 @@ namespace Pixiview.Illust if (index < 0) { illust.IsFavorite = true; + illust.FavoriteDateUtc = DateTime.UtcNow; favorites.Insert(0, illust); FavoriteIcon = fontIconLove; } @@ -518,6 +519,11 @@ namespace Pixiview.Illust 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; diff --git a/Pixiview/Utils/Stores.cs b/Pixiview/Utils/Stores.cs index c33ea95..b7ad256 100644 --- a/Pixiview/Utils/Stores.cs +++ b/Pixiview/Utils/Stores.cs @@ -382,9 +382,9 @@ namespace Pixiview.Utils return LoadImage(url, PersonalFolder, imageFolder); } - public static ImageSource LoadPreviewImage(string url, bool downloading = true) + public static ImageSource LoadPreviewImage(string url, bool downloading = true, bool force = false) { - return LoadImage(url, PersonalFolder, previewFolder, downloading); + return LoadImage(url, PersonalFolder, previewFolder, downloading, force); } public static ImageSource LoadThumbnailImage(string url) @@ -418,11 +418,11 @@ namespace Pixiview.Utils return null; } - private static ImageSource LoadImage(string url, string working, string folder, bool downloading = true) + private static ImageSource LoadImage(string url, string working, string folder, bool downloading = true, bool force = false) { var file = Path.Combine(working, folder, Path.GetFileName(url)); ImageSource image; - if (File.Exists(file)) + if (!force && File.Exists(file)) { try {