feature: loading UI adjustment
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="utf-8"?>
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0.515" package="org.tsanie.pixiview" android:versionCode="5">
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0.516" package="org.tsanie.pixiview" android:versionCode="6">
 | 
				
			||||||
	<uses-sdk android:minSdkVersion="25" android:targetSdkVersion="28" />
 | 
						<uses-sdk android:minSdkVersion="25" android:targetSdkVersion="28" />
 | 
				
			||||||
	<application android:label="Pixiview" android:icon="@mipmap/icon" android:roundIcon="@mipmap/icon_round"></application>
 | 
						<application android:label="Pixiview" android:icon="@mipmap/icon" android:roundIcon="@mipmap/icon_round"></application>
 | 
				
			||||||
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 | 
						<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,8 +29,8 @@
 | 
				
			|||||||
		<string>com.apple.share-services</string>
 | 
							<string>com.apple.share-services</string>
 | 
				
			||||||
	</dict>
 | 
						</dict>
 | 
				
			||||||
	<key>CFBundleShortVersionString</key>
 | 
						<key>CFBundleShortVersionString</key>
 | 
				
			||||||
	<string>1.0.515</string>
 | 
						<string>1.0.516</string>
 | 
				
			||||||
	<key>CFBundleVersion</key>
 | 
						<key>CFBundleVersion</key>
 | 
				
			||||||
	<string>5</string>
 | 
						<string>6</string>
 | 
				
			||||||
</dict>
 | 
					</dict>
 | 
				
			||||||
</plist>
 | 
					</plist>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,8 +79,8 @@
 | 
				
			|||||||
		</dict>
 | 
							</dict>
 | 
				
			||||||
	</array>
 | 
						</array>
 | 
				
			||||||
	<key>CFBundleShortVersionString</key>
 | 
						<key>CFBundleShortVersionString</key>
 | 
				
			||||||
	<string>1.0.515</string>
 | 
						<string>1.0.516</string>
 | 
				
			||||||
	<key>CFBundleVersion</key>
 | 
						<key>CFBundleVersion</key>
 | 
				
			||||||
	<string>5</string>
 | 
						<string>6</string>
 | 
				
			||||||
</dict>
 | 
					</dict>
 | 
				
			||||||
</plist>
 | 
					</plist>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -176,8 +176,7 @@ namespace Pixiview
 | 
				
			|||||||
                                if (result == opReplace)
 | 
					                                if (result == opReplace)
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
                                    // replace favorite file
 | 
					                                    // replace favorite file
 | 
				
			||||||
                                    File.Delete(path);
 | 
					                                    File.Copy(url, path, true);
 | 
				
			||||||
                                    File.Move(url, path);
 | 
					 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                else if (result == opCombine)
 | 
					                                else if (result == opCombine)
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
@@ -191,8 +190,6 @@ namespace Pixiview
 | 
				
			|||||||
                                    Stores.SaveFavoritesIllusts();
 | 
					                                    Stores.SaveFavoritesIllusts();
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                File.Delete(url);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                if (Shell.Current.CurrentState.Location.OriginalString.EndsWith(Routes.Favorites))
 | 
					                                if (Shell.Current.CurrentState.Location.OriginalString.EndsWith(Routes.Favorites))
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
                                    var sc = (IShellSectionController)Shell.Current.CurrentItem.CurrentItem;
 | 
					                                    var sc = (IShellSectionController)Shell.Current.CurrentItem.CurrentItem;
 | 
				
			||||||
@@ -205,7 +202,7 @@ namespace Pixiview
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else
 | 
					                        else
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            File.Move(url, path);
 | 
					                            File.Copy(url, path);
 | 
				
			||||||
                            if (Shell.Current.CurrentState.Location.OriginalString.EndsWith(Routes.Favorites))
 | 
					                            if (Shell.Current.CurrentState.Location.OriginalString.EndsWith(Routes.Favorites))
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                var sc = (IShellSectionController)Shell.Current.CurrentItem.CurrentItem;
 | 
					                                var sc = (IShellSectionController)Shell.Current.CurrentItem.CurrentItem;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,15 +8,24 @@
 | 
				
			|||||||
                                BackgroundColor="{DynamicResource WindowColor}"
 | 
					                                BackgroundColor="{DynamicResource WindowColor}"
 | 
				
			||||||
                                Title="{r:Text Favorites}">
 | 
					                                Title="{r:Text Favorites}">
 | 
				
			||||||
    <ContentPage.ToolbarItems>
 | 
					    <ContentPage.ToolbarItems>
 | 
				
			||||||
 | 
					        <ToolbarItem Order="Primary" Clicked="Refresh_Clicked"
 | 
				
			||||||
 | 
					                     IconImageSource="{DynamicResource FontIconRefresh}"/>
 | 
				
			||||||
        <ToolbarItem Order="Primary" Clicked="ShareFavorites_Clicked"
 | 
					        <ToolbarItem Order="Primary" Clicked="ShareFavorites_Clicked"
 | 
				
			||||||
                     IconImageSource="{DynamicResource FontIconShare}"/>
 | 
					                     IconImageSource="{DynamicResource FontIconShare}"/>
 | 
				
			||||||
    </ContentPage.ToolbarItems>
 | 
					    </ContentPage.ToolbarItems>
 | 
				
			||||||
    <Grid>
 | 
					    <Grid>
 | 
				
			||||||
        <ScrollView HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
					        <ScrollView HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
				
			||||||
            <u:FlowLayout ItemsSource="{Binding Illusts}"
 | 
					            <StackLayout>
 | 
				
			||||||
                          HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
					                <ActivityIndicator x:Name="activityLoading" Margin="0, 16, 0, 0"
 | 
				
			||||||
                          Margin="16" RowSpacing="16" ColumnSpacing="16"
 | 
					                                   HeightRequest="40"
 | 
				
			||||||
                          ItemTemplate="{StaticResource cardView}"/>
 | 
					                                   IsRunning="{Binding IsLoading}"
 | 
				
			||||||
 | 
					                                   IsVisible="{Binding IsLoading}"/>
 | 
				
			||||||
 | 
					                <u:FlowLayout ItemsSource="{Binding Illusts}"
 | 
				
			||||||
 | 
					                              HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
				
			||||||
 | 
					                              Margin="16"
 | 
				
			||||||
 | 
					                              RowSpacing="16" ColumnSpacing="16"
 | 
				
			||||||
 | 
					                              ItemTemplate="{StaticResource cardView}"/>
 | 
				
			||||||
 | 
					            </StackLayout>
 | 
				
			||||||
        </ScrollView>
 | 
					        </ScrollView>
 | 
				
			||||||
    </Grid>
 | 
					    </Grid>
 | 
				
			||||||
</i:FavoriteIllustCollectionPage>
 | 
					</i:FavoriteIllustCollectionPage>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@ namespace Pixiview.Illust
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public partial class FavoritesPage : FavoriteIllustCollectionPage
 | 
					    public partial class FavoritesPage : FavoriteIllustCollectionPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        private bool flag = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public FavoritesPage()
 | 
					        public FavoritesPage()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Resources.Add("cardView", GetCardViewTemplate());
 | 
					            Resources.Add("cardView", GetCardViewTemplate());
 | 
				
			||||||
@@ -16,16 +18,8 @@ namespace Pixiview.Illust
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override bool IsFavoriteVisible => false;
 | 
					        protected override bool IsFavoriteVisible => false;
 | 
				
			||||||
 | 
					        protected override ActivityIndicator LoadingIndicator => activityLoading;
 | 
				
			||||||
        protected override void OnAppearing()
 | 
					        protected override bool IsDelayLoading => true;
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            //base.OnAppearing();
 | 
					 | 
				
			||||||
            Device.StartTimer(TimeSpan.FromMilliseconds(200), () =>
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                Reload();
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override IEnumerable<IllustItem> DoGetIllustList(IllustItem[] data)
 | 
					        protected override IEnumerable<IllustItem> DoGetIllustList(IllustItem[] data)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -34,7 +28,8 @@ namespace Pixiview.Illust
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        protected override IllustItem[] DoLoadIllustData(bool force)
 | 
					        protected override IllustItem[] DoLoadIllustData(bool force)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var favorites = Stores.GetFavoriteObject(force);
 | 
					            var favorites = Stores.GetFavoriteObject(flag);
 | 
				
			||||||
 | 
					            flag = false;
 | 
				
			||||||
            if (favorites == null)
 | 
					            if (favorites == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return null;
 | 
					                return null;
 | 
				
			||||||
@@ -54,9 +49,20 @@ namespace Pixiview.Illust
 | 
				
			|||||||
        public void Reload(bool force = false)
 | 
					        public void Reload(bool force = false)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            lastUpdated = default;
 | 
					            lastUpdated = default;
 | 
				
			||||||
 | 
					            if (force)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                flag = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            StartLoad(force);
 | 
					            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)
 | 
					        private async void ShareFavorites_Clicked(object sender, EventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var file = Stores.FavoritesPath;
 | 
					            var file = Stores.FavoritesPath;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,6 @@ using Pixiview.Resources;
 | 
				
			|||||||
using Pixiview.UI;
 | 
					using Pixiview.UI;
 | 
				
			||||||
using Pixiview.UI.Theme;
 | 
					using Pixiview.UI.Theme;
 | 
				
			||||||
using Pixiview.Utils;
 | 
					using Pixiview.Utils;
 | 
				
			||||||
using Xamarin.Essentials;
 | 
					 | 
				
			||||||
using Xamarin.Forms;
 | 
					using Xamarin.Forms;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Pixiview.Illust
 | 
					namespace Pixiview.Illust
 | 
				
			||||||
@@ -24,6 +23,9 @@ namespace Pixiview.Illust
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    public abstract class IllustCollectionPage<T> : AdaptedPage, IIllustCollectionPage
 | 
					    public abstract class IllustCollectionPage<T> : AdaptedPage, IIllustCollectionPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        protected static readonly Thickness normalMargin = new Thickness(16);
 | 
				
			||||||
 | 
					        protected static readonly Thickness loadingMargin = new Thickness(16, 46, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region - Properties -
 | 
					        #region - Properties -
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static readonly BindableProperty IllustsProperty = BindableProperty.Create(
 | 
					        public static readonly BindableProperty IllustsProperty = BindableProperty.Create(
 | 
				
			||||||
@@ -32,6 +34,8 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            nameof(Columns), typeof(int), typeof(IllustCollectionPage<T>), 2);
 | 
					            nameof(Columns), typeof(int), typeof(IllustCollectionPage<T>), 2);
 | 
				
			||||||
        public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(
 | 
					        public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(
 | 
				
			||||||
            nameof(IsLoading), typeof(bool), typeof(IllustCollectionPage<T>), true);
 | 
					            nameof(IsLoading), typeof(bool), typeof(IllustCollectionPage<T>), true);
 | 
				
			||||||
 | 
					        public static readonly BindableProperty IsBottomLoadingProperty = BindableProperty.Create(
 | 
				
			||||||
 | 
					            nameof(IsBottomLoading), typeof(bool), typeof(IllustCollectionPage<T>), false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public IllustCollection Illusts
 | 
					        public IllustCollection Illusts
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -48,6 +52,11 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            get => (bool)GetValue(IsLoadingProperty);
 | 
					            get => (bool)GetValue(IsLoadingProperty);
 | 
				
			||||||
            set => SetValue(IsLoadingProperty, value);
 | 
					            set => SetValue(IsLoadingProperty, value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        public bool IsBottomLoading
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get => (bool)GetValue(IsBottomLoadingProperty);
 | 
				
			||||||
 | 
					            set => SetValue(IsBottomLoadingProperty, value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -56,6 +65,10 @@ namespace Pixiview.Illust
 | 
				
			|||||||
        public IllustCollection IllustCollection { get; set; }
 | 
					        public IllustCollection IllustCollection { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual bool IsFavoriteVisible => true;
 | 
					        protected virtual bool IsFavoriteVisible => true;
 | 
				
			||||||
 | 
					        protected virtual ActivityIndicator LoadingIndicator => null;
 | 
				
			||||||
 | 
					        protected virtual bool IsDelayLoading => false;
 | 
				
			||||||
 | 
					        protected virtual double IndicatorMarginTop => 16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected readonly Command<IllustItem> commandIllustImageTapped;
 | 
					        protected readonly Command<IllustItem> commandIllustImageTapped;
 | 
				
			||||||
        protected DateTime lastUpdated;
 | 
					        protected DateTime lastUpdated;
 | 
				
			||||||
        protected double topOffset;
 | 
					        protected double topOffset;
 | 
				
			||||||
@@ -88,15 +101,10 @@ namespace Pixiview.Illust
 | 
				
			|||||||
        protected override void OnAppearing()
 | 
					        protected override void OnAppearing()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            base.OnAppearing();
 | 
					            base.OnAppearing();
 | 
				
			||||||
            Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (lastUpdated != LastUpdated)
 | 
					            if (lastUpdated != LastUpdated)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Device.StartTimer(TimeSpan.FromMilliseconds(200), () =>
 | 
					                StartLoad();
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    StartLoad();
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (IsFavoriteVisible && IllustCollection != null)
 | 
					            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)
 | 
					        protected override void OnSizeAllocated(double width, double height)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            base.OnSizeAllocated(width, height);
 | 
					            base.OnSizeAllocated(width, height);
 | 
				
			||||||
@@ -188,19 +179,87 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            var page = new ViewIllustPage(illust, IsFavoriteVisible);
 | 
					            var page = new ViewIllustPage(illust, IsFavoriteVisible);
 | 
				
			||||||
            Navigation.PushAsync(page);
 | 
					            Navigation.PushAsync(page);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        protected virtual void DoIllustsLoaded(IllustCollection collection)
 | 
					        protected virtual void DoIllustsLoaded(IllustCollection collection, bool bottom)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            IllustCollection = collection;
 | 
					            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)
 | 
					            if (force || lastUpdated != LastUpdated)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                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 -
 | 
					        #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}");
 | 
					            App.DebugPrint($"start loading data, force: {force}");
 | 
				
			||||||
            illustData = DoLoadIllustData(force);
 | 
					            illustData = DoLoadIllustData(force);
 | 
				
			||||||
@@ -433,6 +492,7 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                //App.DebugError("illusts.load", "failed to load illusts data.");
 | 
					                //App.DebugError("illusts.load", "failed to load illusts data.");
 | 
				
			||||||
                IsLoading = false;
 | 
					                IsLoading = false;
 | 
				
			||||||
 | 
					                IsBottomLoading = false;
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (force && IsFavoriteVisible)
 | 
					            if (force && IsFavoriteVisible)
 | 
				
			||||||
@@ -458,8 +518,7 @@ namespace Pixiview.Illust
 | 
				
			|||||||
                    item.IsFavorite = favorites.Any(i => i.Id == item.Id);
 | 
					                    item.IsFavorite = favorites.Any(i => i.Id == item.Id);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            DoIllustsLoaded(collection);
 | 
					            DoIllustsLoaded(collection, bottom);
 | 
				
			||||||
            IsLoading = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            DoLoadImages(collection);
 | 
					            DoLoadImages(collection);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -505,9 +564,9 @@ namespace Pixiview.Illust
 | 
				
			|||||||
    public abstract class IllustScrollableCollectionPage<T> : IllustCollectionPage<T>
 | 
					    public abstract class IllustScrollableCollectionPage<T> : IllustCollectionPage<T>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        protected const int SCROLL_OFFSET = 33;
 | 
					        protected const int SCROLL_OFFSET = 33;
 | 
				
			||||||
        protected readonly object sync = new object();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private double lastScrollY = double.MinValue;
 | 
					        private double lastScrollY = double.MinValue;
 | 
				
			||||||
 | 
					        private double lastRefreshY = double.MinValue;
 | 
				
			||||||
        private double offset;
 | 
					        private double offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected bool ScrollingDown(double y)
 | 
					        protected bool ScrollingDown(double y)
 | 
				
			||||||
@@ -521,19 +580,48 @@ namespace Pixiview.Illust
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        protected abstract bool CheckRefresh();
 | 
					        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;
 | 
					            var now = IllustCollection;
 | 
				
			||||||
            if (now == null)
 | 
					            if (now == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                IllustCollection = collection;
 | 
					                now = collection;
 | 
				
			||||||
                Illusts = collection;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                now = new IllustCollection(now.Concat(collection));
 | 
					                now = new IllustCollection(now.Concat(collection));
 | 
				
			||||||
                IllustCollection = now;
 | 
					            }
 | 
				
			||||||
 | 
					            IllustCollection = now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var indicator = LoadingIndicator;
 | 
				
			||||||
 | 
					            if (indicator == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                Illusts = now;
 | 
					                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)
 | 
					            if (y > 0 && offset > 0 && y - topOffset > offset)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                bool refresh = false;
 | 
					                if (IsLoading || IsBottomLoading)
 | 
				
			||||||
                lock (sync)
 | 
					                {
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (y - lastRefreshY > 100)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (IsLoading)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        return;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    if (CheckRefresh())
 | 
					                    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]
 | 
					        [JsonProperty]
 | 
				
			||||||
        public string Id { get; set; }
 | 
					        public string Id { get; set; }
 | 
				
			||||||
        [JsonProperty]
 | 
					        [JsonProperty]
 | 
				
			||||||
 | 
					        public DateTime FavoriteDateUtc { get; set; }
 | 
				
			||||||
 | 
					        [JsonProperty]
 | 
				
			||||||
        public string ImageUrl { get; set; }
 | 
					        public string ImageUrl { get; set; }
 | 
				
			||||||
        [JsonProperty]
 | 
					        [JsonProperty]
 | 
				
			||||||
        public bool IsRestrict { get; set; }
 | 
					        public bool IsRestrict { get; set; }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,16 +14,22 @@
 | 
				
			|||||||
    <Grid>
 | 
					    <Grid>
 | 
				
			||||||
        <ScrollView HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never"
 | 
					        <ScrollView HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never"
 | 
				
			||||||
                    Scrolled="ScrollView_Scrolled">
 | 
					                    Scrolled="ScrollView_Scrolled">
 | 
				
			||||||
            <u:FlowLayout ItemsSource="{Binding Illusts}"
 | 
					            <StackLayout>
 | 
				
			||||||
                          HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
					                <ActivityIndicator x:Name="activityLoading" Margin="0, 66, 0, 0"
 | 
				
			||||||
                          RowSpacing="16" ColumnSpacing="16"
 | 
					                                   HeightRequest="40"
 | 
				
			||||||
                          ItemTemplate="{StaticResource cardView}">
 | 
					                                   IsRunning="{Binding IsLoading}"
 | 
				
			||||||
                <u:FlowLayout.Margin>
 | 
					                                   IsVisible="{Binding IsLoading}"/>
 | 
				
			||||||
                    <OnPlatform x:TypeArguments="Thickness"
 | 
					                <u:FlowLayout ItemsSource="{Binding Illusts}"
 | 
				
			||||||
                                iOS="16, 66, 16, 16"
 | 
					                              HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
				
			||||||
                                Android="16, 56, 16, 16"/>
 | 
					                              RowSpacing="16" ColumnSpacing="16"
 | 
				
			||||||
                </u:FlowLayout.Margin>
 | 
					                              ItemTemplate="{StaticResource cardView}">
 | 
				
			||||||
            </u:FlowLayout>
 | 
					                    <u:FlowLayout.Margin>
 | 
				
			||||||
 | 
					                        <OnPlatform x:TypeArguments="Thickness"
 | 
				
			||||||
 | 
					                                    iOS="16, 66, 16, 16"
 | 
				
			||||||
 | 
					                                    Android="16, 56, 16, 16"/>
 | 
				
			||||||
 | 
					                    </u:FlowLayout.Margin>
 | 
				
			||||||
 | 
					                </u:FlowLayout>
 | 
				
			||||||
 | 
					            </StackLayout>
 | 
				
			||||||
        </ScrollView>
 | 
					        </ScrollView>
 | 
				
			||||||
        <u:BlurryPanel x:Name="panelBar" VerticalOptions="Start"
 | 
					        <u:BlurryPanel x:Name="panelBar" VerticalOptions="Start"
 | 
				
			||||||
                       HeightRequest="{OnPlatform Android=40, iOS=50}"
 | 
					                       HeightRequest="{OnPlatform Android=40, iOS=50}"
 | 
				
			||||||
@@ -35,12 +41,5 @@
 | 
				
			|||||||
                   CancelButtonColor="{DynamicResource TintColor}"
 | 
					                   CancelButtonColor="{DynamicResource TintColor}"
 | 
				
			||||||
                   Text="{Binding Keywords, Mode=TwoWay}"
 | 
					                   Text="{Binding Keywords, Mode=TwoWay}"
 | 
				
			||||||
                   SearchButtonPressed="SearchBar_SearchButtonPressed"/>
 | 
					                   SearchButtonPressed="SearchBar_SearchButtonPressed"/>
 | 
				
			||||||
        <Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
 | 
					 | 
				
			||||||
               IsVisible="{Binding IsLoading}"
 | 
					 | 
				
			||||||
               HorizontalOptions="Center" VerticalOptions="Center"
 | 
					 | 
				
			||||||
               BackgroundColor="{DynamicResource MaskColor}">
 | 
					 | 
				
			||||||
            <ActivityIndicator IsRunning="True" IsVisible="True"
 | 
					 | 
				
			||||||
                               Color="{DynamicResource WindowColor}"/>
 | 
					 | 
				
			||||||
        </Frame>
 | 
					 | 
				
			||||||
    </Grid>
 | 
					    </Grid>
 | 
				
			||||||
</i:IllustDataCollectionPage>
 | 
					</i:IllustDataCollectionPage>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,9 @@ namespace Pixiview.Illust
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override ActivityIndicator LoadingIndicator => activityLoading;
 | 
				
			||||||
 | 
					        protected override double IndicatorMarginTop => 66;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data)
 | 
					        protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (data.body == null)
 | 
					            if (data.body == null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,10 +48,20 @@
 | 
				
			|||||||
    <Grid>
 | 
					    <Grid>
 | 
				
			||||||
        <ScrollView x:Name="scrollView" Scrolled="ScrollView_Scrolled"
 | 
					        <ScrollView x:Name="scrollView" Scrolled="ScrollView_Scrolled"
 | 
				
			||||||
                    HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
					                    HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
				
			||||||
            <u:FlowLayout ItemsSource="{Binding Illusts}" MaxHeightChanged="FlowLayout_MaxHeightChanged"
 | 
					            <StackLayout>
 | 
				
			||||||
                          HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
					                <ActivityIndicator x:Name="activityLoading" Margin="0, 16, 0, 0"
 | 
				
			||||||
                          Margin="16" RowSpacing="16" ColumnSpacing="16"
 | 
					                                   HeightRequest="40"
 | 
				
			||||||
                          ItemTemplate="{StaticResource cardView}"/>
 | 
					                                   IsRunning="{Binding IsLoading}"
 | 
				
			||||||
 | 
					                                   IsVisible="{Binding IsLoading}"/>
 | 
				
			||||||
 | 
					                <u:FlowLayout ItemsSource="{Binding Illusts}" MaxHeightChanged="FlowLayout_MaxHeightChanged"
 | 
				
			||||||
 | 
					                              HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
				
			||||||
 | 
					                              Margin="16" RowSpacing="16" ColumnSpacing="16"
 | 
				
			||||||
 | 
					                              ItemTemplate="{StaticResource cardView}"/>
 | 
				
			||||||
 | 
					                <ActivityIndicator x:Name="activityBottomLoading" Margin="0, 0, 0, 16"
 | 
				
			||||||
 | 
					                                   HeightRequest="40"
 | 
				
			||||||
 | 
					                                   IsRunning="{Binding IsBottomLoading}"
 | 
				
			||||||
 | 
					                                   IsVisible="{Binding IsBottomLoading}"/>
 | 
				
			||||||
 | 
					            </StackLayout>
 | 
				
			||||||
        </ScrollView>
 | 
					        </ScrollView>
 | 
				
			||||||
        <u:BlurryPanel x:Name="panelFilter" VerticalOptions="Start" Opacity="0"
 | 
					        <u:BlurryPanel x:Name="panelFilter" VerticalOptions="Start" Opacity="0"
 | 
				
			||||||
                       Margin="{Binding PanelTopMargin}"
 | 
					                       Margin="{Binding PanelTopMargin}"
 | 
				
			||||||
@@ -95,13 +105,6 @@
 | 
				
			|||||||
                        Clicked="Filter_Clicked"/>
 | 
					                        Clicked="Filter_Clicked"/>
 | 
				
			||||||
            </Grid>
 | 
					            </Grid>
 | 
				
			||||||
        </Grid>
 | 
					        </Grid>
 | 
				
			||||||
        <Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
 | 
					 | 
				
			||||||
               IsVisible="{Binding IsLoading}"
 | 
					 | 
				
			||||||
               HorizontalOptions="Center" VerticalOptions="Center"
 | 
					 | 
				
			||||||
               BackgroundColor="{DynamicResource MaskColor}">
 | 
					 | 
				
			||||||
            <ActivityIndicator IsRunning="True" IsVisible="True"
 | 
					 | 
				
			||||||
                               Color="{DynamicResource WindowColor}"/>
 | 
					 | 
				
			||||||
        </Frame>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <DatePicker x:Name="datePicker" IsVisible="False"
 | 
					        <DatePicker x:Name="datePicker" IsVisible="False"
 | 
				
			||||||
                    ios:DatePicker.UpdateMode="WhenFinished"
 | 
					                    ios:DatePicker.UpdateMode="WhenFinished"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -115,6 +115,8 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            MaximumDate = DateTime.Today;
 | 
					            MaximumDate = DateTime.Today;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override ActivityIndicator LoadingIndicator => activityLoading;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override void OnAppearing()
 | 
					        protected override void OnAppearing()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var r18 = Configs.IsOnR18;
 | 
					            var r18 = Configs.IsOnR18;
 | 
				
			||||||
@@ -341,12 +343,9 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            var query = QueryKey;
 | 
					            var query = QueryKey;
 | 
				
			||||||
            ToggleFilterPanel(false);
 | 
					            ToggleFilterPanel(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            lock (sync)
 | 
					            if (IsLoading)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (IsLoading)
 | 
					                return;
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    return;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            //if (lastQueryKey != query)
 | 
					            //if (lastQueryKey != query)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,10 @@
 | 
				
			|||||||
    <Grid>
 | 
					    <Grid>
 | 
				
			||||||
        <ScrollView HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
					        <ScrollView HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
				
			||||||
            <StackLayout>
 | 
					            <StackLayout>
 | 
				
			||||||
 | 
					                <ActivityIndicator x:Name="activityLoading" Margin="0, 16, 0, 0"
 | 
				
			||||||
 | 
					                                   HeightRequest="40"
 | 
				
			||||||
 | 
					                                   IsRunning="{Binding IsLoading}"
 | 
				
			||||||
 | 
					                                   IsVisible="{Binding IsLoading}"/>
 | 
				
			||||||
                <u:FlowLayout ItemsSource="{Binding Users}" IsVisible="{Binding UserRecommendsVisible}"
 | 
					                <u:FlowLayout ItemsSource="{Binding Users}" IsVisible="{Binding UserRecommendsVisible}"
 | 
				
			||||||
                              HorizontalOptions="Fill" Column="{Binding UserColumns}"
 | 
					                              HorizontalOptions="Fill" Column="{Binding UserColumns}"
 | 
				
			||||||
                              Margin="16" RowSpacing="16"
 | 
					                              Margin="16" RowSpacing="16"
 | 
				
			||||||
@@ -24,12 +28,5 @@
 | 
				
			|||||||
                              ItemTemplate="{StaticResource cardView}"/>
 | 
					                              ItemTemplate="{StaticResource cardView}"/>
 | 
				
			||||||
            </StackLayout>
 | 
					            </StackLayout>
 | 
				
			||||||
        </ScrollView>
 | 
					        </ScrollView>
 | 
				
			||||||
        <Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
 | 
					 | 
				
			||||||
               IsVisible="{Binding IsLoading}"
 | 
					 | 
				
			||||||
               HorizontalOptions="Center" VerticalOptions="Center"
 | 
					 | 
				
			||||||
               BackgroundColor="{DynamicResource MaskColor}">
 | 
					 | 
				
			||||||
            <ActivityIndicator IsRunning="True" IsVisible="True"
 | 
					 | 
				
			||||||
                               Color="{DynamicResource WindowColor}"/>
 | 
					 | 
				
			||||||
        </Frame>
 | 
					 | 
				
			||||||
    </Grid>
 | 
					    </Grid>
 | 
				
			||||||
</i:IllustDataCollectionPage>
 | 
					</i:IllustDataCollectionPage>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,6 +36,8 @@ namespace Pixiview.Illust
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private readonly Command<IllustUserItem> commandUserTapped;
 | 
					        private readonly Command<IllustUserItem> commandUserTapped;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private IllustData illustData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public RecommendsPage()
 | 
					        public RecommendsPage()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Resources.Add("cardView", GetCardViewTemplate());
 | 
					            Resources.Add("cardView", GetCardViewTemplate());
 | 
				
			||||||
@@ -45,6 +47,8 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            commandUserTapped = new Command<IllustUserItem>(OnIllustUserItemTapped);
 | 
					            commandUserTapped = new Command<IllustUserItem>(OnIllustUserItemTapped);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override ActivityIndicator LoadingIndicator => activityLoading;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void OnIllustUserItemTapped(IllustUserItem item)
 | 
					        private void OnIllustUserItemTapped(IllustUserItem item)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Start(async () =>
 | 
					            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<IllustItem> DoGetIllustList(IllustData data)
 | 
					        protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data)
 | 
				
			||||||
@@ -201,8 +214,7 @@ namespace Pixiview.Illust
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        protected override IllustData DoLoadIllustData(bool force)
 | 
					        protected override IllustData DoLoadIllustData(bool force)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var illustData = Stores.LoadIllustData(force);
 | 
					            illustData = Stores.LoadIllustData(force);
 | 
				
			||||||
            Task.Run(() => DoLoadUserRecommendsData(illustData));
 | 
					 | 
				
			||||||
            return illustData;
 | 
					            return illustData;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -259,9 +271,17 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            }).Where(u => u != null);
 | 
					            }).Where(u => u != null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var list = new List<IllustUserItem>(users);
 | 
					            var list = new List<IllustUserItem>(users);
 | 
				
			||||||
            UserRecommendsVisible = list.Count > 0;
 | 
					            activityLoading.Animate("margin", top =>
 | 
				
			||||||
            Users = list;
 | 
					            {
 | 
				
			||||||
            Illusts = IllustCollection;
 | 
					                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);
 | 
					            DoLoadUserRecommendsImages(list);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,17 +14,20 @@
 | 
				
			|||||||
    <Grid>
 | 
					    <Grid>
 | 
				
			||||||
        <ScrollView x:Name="scrollView" Scrolled="ScrollView_Scrolled"
 | 
					        <ScrollView x:Name="scrollView" Scrolled="ScrollView_Scrolled"
 | 
				
			||||||
                    HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
					                    HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
				
			||||||
            <u:FlowLayout ItemsSource="{Binding Illusts}" MaxHeightChanged="FlowLayout_MaxHeightChanged"
 | 
					            <StackLayout>
 | 
				
			||||||
                          HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
					                <ActivityIndicator x:Name="activityLoading" Margin="0, 16, 0, 0"
 | 
				
			||||||
                          Margin="16" RowSpacing="16" ColumnSpacing="16"
 | 
					                                   HeightRequest="40"
 | 
				
			||||||
                          ItemTemplate="{StaticResource cardView}"/>
 | 
					                                   IsRunning="{Binding IsLoading}"
 | 
				
			||||||
 | 
					                                   IsVisible="{Binding IsLoading}"/>
 | 
				
			||||||
 | 
					                <u:FlowLayout ItemsSource="{Binding Illusts}" MaxHeightChanged="FlowLayout_MaxHeightChanged"
 | 
				
			||||||
 | 
					                              HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
				
			||||||
 | 
					                              Margin="16" RowSpacing="16" ColumnSpacing="16"
 | 
				
			||||||
 | 
					                              ItemTemplate="{StaticResource cardView}"/>
 | 
				
			||||||
 | 
					                <ActivityIndicator x:Name="activityBottomLoading" Margin="0, 0, 0, 16"
 | 
				
			||||||
 | 
					                                   HeightRequest="40"
 | 
				
			||||||
 | 
					                                   IsRunning="{Binding IsBottomLoading}"
 | 
				
			||||||
 | 
					                                   IsVisible="{Binding IsBottomLoading}"/>
 | 
				
			||||||
 | 
					            </StackLayout>
 | 
				
			||||||
        </ScrollView>
 | 
					        </ScrollView>
 | 
				
			||||||
        <Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
 | 
					 | 
				
			||||||
               IsVisible="{Binding IsLoading}"
 | 
					 | 
				
			||||||
               HorizontalOptions="Center" VerticalOptions="Center"
 | 
					 | 
				
			||||||
               BackgroundColor="{DynamicResource MaskColor}">
 | 
					 | 
				
			||||||
            <ActivityIndicator IsRunning="True" IsVisible="True"
 | 
					 | 
				
			||||||
                               Color="{DynamicResource WindowColor}"/>
 | 
					 | 
				
			||||||
        </Frame>
 | 
					 | 
				
			||||||
    </Grid>
 | 
					    </Grid>
 | 
				
			||||||
</i:IllustRecommendsCollectionPage>
 | 
					</i:IllustRecommendsCollectionPage>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,8 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            nextIndex = 0;
 | 
					            nextIndex = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override ActivityIndicator LoadingIndicator => activityLoading;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override IEnumerable<IllustItem> DoGetIllustList(IllustRecommendsData data)
 | 
					        protected override IEnumerable<IllustItem> DoGetIllustList(IllustRecommendsData data)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (data.body == null)
 | 
					            if (data.body == null)
 | 
				
			||||||
@@ -92,12 +94,13 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            OnScrolled(y);
 | 
					            OnScrolled(y);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void Refresh_Clicked(object sender, EventArgs e)
 | 
					        private async void Refresh_Clicked(object sender, EventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (IsLoading)
 | 
					            if (IsLoading)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            await scrollView.ScrollToAsync(0, -topOffset, true);
 | 
				
			||||||
            // release
 | 
					            // release
 | 
				
			||||||
            var collection = IllustCollection;
 | 
					            var collection = IllustCollection;
 | 
				
			||||||
            if (collection != null)
 | 
					            if (collection != null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,17 +26,20 @@
 | 
				
			|||||||
    <Grid>
 | 
					    <Grid>
 | 
				
			||||||
        <ScrollView x:Name="scrollView" Scrolled="ScrollView_Scrolled"
 | 
					        <ScrollView x:Name="scrollView" Scrolled="ScrollView_Scrolled"
 | 
				
			||||||
                    HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
					                    HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
 | 
				
			||||||
            <u:FlowLayout ItemsSource="{Binding Illusts}" MaxHeightChanged="FlowLayout_MaxHeightChanged"
 | 
					            <StackLayout>
 | 
				
			||||||
                          HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
					                <ActivityIndicator x:Name="activityLoading" Margin="0, 16, 0, 0"
 | 
				
			||||||
                          Margin="16" RowSpacing="16" ColumnSpacing="16"
 | 
					                                   HeightRequest="40"
 | 
				
			||||||
                          ItemTemplate="{StaticResource cardView}"/>
 | 
					                                   IsRunning="{Binding IsLoading}"
 | 
				
			||||||
 | 
					                                   IsVisible="{Binding IsLoading}"/>
 | 
				
			||||||
 | 
					                <u:FlowLayout ItemsSource="{Binding Illusts}" MaxHeightChanged="FlowLayout_MaxHeightChanged"
 | 
				
			||||||
 | 
					                              HorizontalOptions="Fill" Column="{Binding Columns}"
 | 
				
			||||||
 | 
					                              Margin="16" RowSpacing="16" ColumnSpacing="16"
 | 
				
			||||||
 | 
					                              ItemTemplate="{StaticResource cardView}"/>
 | 
				
			||||||
 | 
					                <ActivityIndicator x:Name="activityBottomLoading" Margin="0, 0, 0, 16"
 | 
				
			||||||
 | 
					                                   HeightRequest="40"
 | 
				
			||||||
 | 
					                                   IsRunning="{Binding IsBottomLoading}"
 | 
				
			||||||
 | 
					                                   IsVisible="{Binding IsBottomLoading}"/>
 | 
				
			||||||
 | 
					            </StackLayout>
 | 
				
			||||||
        </ScrollView>
 | 
					        </ScrollView>
 | 
				
			||||||
        <Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
 | 
					 | 
				
			||||||
               IsVisible="{Binding IsLoading}"
 | 
					 | 
				
			||||||
               HorizontalOptions="Center" VerticalOptions="Center"
 | 
					 | 
				
			||||||
               BackgroundColor="{DynamicResource MaskColor}">
 | 
					 | 
				
			||||||
            <ActivityIndicator IsRunning="True" IsVisible="True"
 | 
					 | 
				
			||||||
                               Color="{DynamicResource WindowColor}"/>
 | 
					 | 
				
			||||||
        </Frame>
 | 
					 | 
				
			||||||
    </Grid>
 | 
					    </Grid>
 | 
				
			||||||
</i:IllustUserDataCollectionPage>
 | 
					</i:IllustUserDataCollectionPage>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,6 +38,8 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            nextIndex = 0;
 | 
					            nextIndex = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override ActivityIndicator LoadingIndicator => activityLoading;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override IEnumerable<IllustItem> DoGetIllustList(IllustUserData data)
 | 
					        protected override IEnumerable<IllustItem> DoGetIllustList(IllustUserData data)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (data.body == null)
 | 
					            if (data.body == null)
 | 
				
			||||||
@@ -58,6 +60,7 @@ namespace Pixiview.Illust
 | 
				
			|||||||
                    return null;
 | 
					                    return null;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                illustIds = init.body.illusts.Keys.OrderByDescending(i => i).ToArray();
 | 
					                illustIds = init.body.illusts.Keys.OrderByDescending(i => i).ToArray();
 | 
				
			||||||
 | 
					                App.DebugPrint($"user has ({illustIds.Length}) illusts.");
 | 
				
			||||||
                startIndex = 0;
 | 
					                startIndex = 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,12 +104,13 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            OnScrolled(y);
 | 
					            OnScrolled(y);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void Refresh_Clicked(object sender, EventArgs e)
 | 
					        private async void Refresh_Clicked(object sender, EventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (IsLoading)
 | 
					            if (IsLoading)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            await scrollView.ScrollToAsync(0, -topOffset, true);
 | 
				
			||||||
            // release
 | 
					            // release
 | 
				
			||||||
            var collection = IllustCollection;
 | 
					            var collection = IllustCollection;
 | 
				
			||||||
            if (collection != null)
 | 
					            if (collection != null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,8 @@
 | 
				
			|||||||
    <ContentPage.ToolbarItems>
 | 
					    <ContentPage.ToolbarItems>
 | 
				
			||||||
        <ToolbarItem Order="Primary" Clicked="Favorite_Clicked"
 | 
					        <ToolbarItem Order="Primary" Clicked="Favorite_Clicked"
 | 
				
			||||||
                     IconImageSource="{Binding FavoriteIcon}"/>
 | 
					                     IconImageSource="{Binding FavoriteIcon}"/>
 | 
				
			||||||
 | 
					        <ToolbarItem Order="Primary" Clicked="Refresh_Clicked"
 | 
				
			||||||
 | 
					                     IconImageSource="{DynamicResource FontIconRefresh}"/>
 | 
				
			||||||
        <ToolbarItem Order="Primary" Clicked="More_Clicked"
 | 
					        <ToolbarItem Order="Primary" Clicked="More_Clicked"
 | 
				
			||||||
                     IconImageSource="{DynamicResource FontIconMore}"/>
 | 
					                     IconImageSource="{DynamicResource FontIconMore}"/>
 | 
				
			||||||
    </ContentPage.ToolbarItems>
 | 
					    </ContentPage.ToolbarItems>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -359,7 +359,7 @@ namespace Pixiview.Illust
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            ParallelTask.Start(0, items.Length, Configs.MaxPageThreads, i =>
 | 
					            ParallelTask.Start(0, items.Length, Configs.MaxPageThreads, i =>
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                DoLoadImage(i, i == 0);
 | 
					                DoLoadImage(i);
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -385,16 +385,16 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var item = items[index];
 | 
					            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}");
 | 
					                    App.DebugPrint($"skipped, loading or already loaded, index: {index}, loading: {item.Loading}");
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            item.Loading = true;
 | 
					            item.Loading = true;
 | 
				
			||||||
            var image = Stores.LoadPreviewImage(item.PreviewUrl);
 | 
					            var image = Stores.LoadPreviewImage(item.PreviewUrl, force: force);
 | 
				
			||||||
            if (image != null)
 | 
					            if (image != null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                item.Image = image;
 | 
					                item.Image = image;
 | 
				
			||||||
@@ -472,6 +472,7 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            if (index < 0)
 | 
					            if (index < 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                illust.IsFavorite = true;
 | 
					                illust.IsFavorite = true;
 | 
				
			||||||
 | 
					                illust.FavoriteDateUtc = DateTime.UtcNow;
 | 
				
			||||||
                favorites.Insert(0, illust);
 | 
					                favorites.Insert(0, illust);
 | 
				
			||||||
                FavoriteIcon = fontIconLove;
 | 
					                FavoriteIcon = fontIconLove;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -518,6 +519,11 @@ namespace Pixiview.Illust
 | 
				
			|||||||
            CurrentAnimeFrame = e.FrameIndex;
 | 
					            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)
 | 
					        private async void More_Clicked(object sender, EventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            int p = CurrentPage;
 | 
					            int p = CurrentPage;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -382,9 +382,9 @@ namespace Pixiview.Utils
 | 
				
			|||||||
            return LoadImage(url, PersonalFolder, imageFolder);
 | 
					            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)
 | 
					        public static ImageSource LoadThumbnailImage(string url)
 | 
				
			||||||
@@ -418,11 +418,11 @@ namespace Pixiview.Utils
 | 
				
			|||||||
            return null;
 | 
					            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));
 | 
					            var file = Path.Combine(working, folder, Path.GetFileName(url));
 | 
				
			||||||
            ImageSource image;
 | 
					            ImageSource image;
 | 
				
			||||||
            if (File.Exists(file))
 | 
					            if (!force && File.Exists(file))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                try
 | 
					                try
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user