feature: favorites type filter

This commit is contained in:
2020-05-20 01:17:11 +08:00
parent d1ea0243b8
commit 34a8d5f434
6 changed files with 152 additions and 20 deletions

View File

@ -7,6 +7,32 @@
x:Class="Pixiview.Illust.FavoritesPage" x:Class="Pixiview.Illust.FavoritesPage"
BackgroundColor="{DynamicResource WindowColor}" BackgroundColor="{DynamicResource WindowColor}"
Title="{r:Text Favorites}"> Title="{r:Text Favorites}">
<Shell.TitleView>
<Grid VerticalOptions="Fill" ColumnSpacing="6"
HorizontalOptions="{x:OnPlatform Android=Start, iOS=Fill}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{OnPlatform Android=Auto}"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="1" Orientation="Horizontal" Spacing="6">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</StackLayout.GestureRecognizers>
<Label Text="{Binding Title}"
TextColor="{DynamicResource TextColor}"
FontSize="{OnPlatform Android=18}"
LineBreakMode="HeadTruncation"
VerticalTextAlignment="Center" FontAttributes="Bold"/>
<Label x:Name="labelCaret"
Text="{DynamicResource IconCaretDown}"
TextColor="{DynamicResource TextColor}"
FontFamily="{DynamicResource IconSolidFontFamily}"
FontSize="Small"
VerticalTextAlignment="Center"/>
</StackLayout>
</Grid>
</Shell.TitleView>
<ContentPage.ToolbarItems> <ContentPage.ToolbarItems>
<ToolbarItem Order="Primary" Clicked="Refresh_Clicked" <ToolbarItem Order="Primary" Clicked="Refresh_Clicked"
IconImageSource="{DynamicResource FontIconCloudDownload}"/> IconImageSource="{DynamicResource FontIconCloudDownload}"/>
@ -30,5 +56,25 @@
IsVisible="{Binding IsBottomLoading}"/> IsVisible="{Binding IsBottomLoading}"/>
</StackLayout> </StackLayout>
</ScrollView> </ScrollView>
<u:BlurryPanel x:Name="panelFilter" VerticalOptions="Start" Opacity="0"
Margin="{Binding PanelTopMargin}"
BackgroundColor="{DynamicResource WindowColor}"
HeightRequest="{Binding Height, Source={x:Reference gridFilter}}"/>
<Grid x:Name="gridFilter" VerticalOptions="Start" Opacity="0"
Margin="{Binding PageTopMargin}" Padding="10">
<Grid RowSpacing="0" HorizontalOptions="Center">
<u:SegmentedControl Margin="6, 6, 6, 3" VerticalOptions="Center"
SelectedSegmentIndex="{Binding SegmentType, Mode=TwoWay}"
SelectedTextColor="{DynamicResource TextColor}"
TintColor="{DynamicResource CardBackgroundColor}">
<u:SegmentedControl.Children>
<u:SegmentedControlOption Text="{r:Text All}"/>
<u:SegmentedControlOption Text="{r:Text Animation}"/>
<u:SegmentedControlOption Text="{r:Text Online}"/>
</u:SegmentedControl.Children>
</u:SegmentedControl>
</Grid>
</Grid>
</Grid> </Grid>
</i:FavoriteIllustCollectionPage> </i:FavoriteIllustCollectionPage>

View File

@ -14,6 +14,22 @@ namespace Pixiview.Illust
{ {
private const int STEP = 20; private const int STEP = 20;
public static readonly BindableProperty SegmentTypeProperty = BindableProperty.Create(
nameof(SegmentType), typeof(int), typeof(FavoritesPage), propertyChanged: OnSegmentTypePropertyChanged);
private static void OnSegmentTypePropertyChanged(BindableObject obj, object old, object @new)
{
var page = (FavoritesPage)obj;
MainThread.BeginInvokeOnMainThread(page.ChangeFilter);
}
public int SegmentType
{
get => (int)GetValue(SegmentTypeProperty);
set => SetValue(SegmentTypeProperty, value);
}
private bool isFilterVisible;
private int startIndex; private int startIndex;
private int nextIndex; private int nextIndex;
private bool flag = false; private bool flag = false;
@ -22,6 +38,8 @@ namespace Pixiview.Illust
{ {
Resources.Add("cardView", GetCardViewTemplate()); Resources.Add("cardView", GetCardViewTemplate());
InitializeComponent(); InitializeComponent();
gridFilter.TranslationY = -60;
panelFilter.TranslationY = -60;
startIndex = -1; startIndex = -1;
nextIndex = 0; nextIndex = 0;
@ -35,7 +53,6 @@ namespace Pixiview.Illust
if (lastUpdated != LastUpdated) if (lastUpdated != LastUpdated)
{ {
startIndex = -1; startIndex = -1;
nextIndex = 0;
StartLoad(); StartLoad();
} }
else else
@ -45,7 +62,6 @@ namespace Pixiview.Illust
{ {
lastUpdated = default; lastUpdated = default;
startIndex = -1; startIndex = -1;
nextIndex = 0;
StartLoad(); StartLoad();
} }
} }
@ -58,7 +74,7 @@ namespace Pixiview.Illust
protected override IllustItem[] DoLoadIllustData(bool force) protected override IllustItem[] DoLoadIllustData(bool force)
{ {
FavoriteList favs; IEnumerable<IllustItem> favs;
if (startIndex < 0) if (startIndex < 0)
{ {
var favorites = Stores.GetFavoriteObject(flag); var favorites = Stores.GetFavoriteObject(flag);
@ -67,14 +83,22 @@ namespace Pixiview.Illust
{ {
return null; return null;
} }
favs = favorites.Illusts; favs = favorites.Illusts.Reload();
favs.Reload();
startIndex = 0; startIndex = 0;
} }
else else
{ {
favs = Stores.Favorites; favs = Stores.Favorites;
} }
switch (SegmentType)
{
case 1: // animation
favs = favs.Where(f => f.IllustType == IllustType.Anime);
break;
case 2: // online
favs = favs.Where(f => f.BookmarkId != null);
break;
}
var illusts = favs.Skip(startIndex).Take(STEP).ToArray(); var illusts = favs.Skip(startIndex).Take(STEP).ToArray();
nextIndex = startIndex + STEP; nextIndex = startIndex + STEP;
if (illusts.Length == 0 || nextIndex >= Stores.Favorites.Count) if (illusts.Length == 0 || nextIndex >= Stores.Favorites.Count)
@ -85,6 +109,53 @@ namespace Pixiview.Illust
return illusts; return illusts;
} }
private async void ToggleFilterPanel(bool flag)
{
ViewExtensions.CancelAnimations(gridFilter);
ViewExtensions.CancelAnimations(panelFilter);
if (flag)
{
isFilterVisible = true;
if (scrollDirection == ScrollDirection.Down)
{
// stop the scrolling
await scrollView.ScrollToAsync(scrollView.ScrollX, scrollView.ScrollY, false);
}
await Task.WhenAll(
labelCaret.RotateTo(180, easing: Easing.CubicOut),
gridFilter.TranslateTo(0, 0, easing: Easing.CubicOut),
gridFilter.FadeTo(1, easing: Easing.CubicOut),
panelFilter.TranslateTo(0, 0, easing: Easing.CubicOut),
panelFilter.FadeTo(1, easing: Easing.CubicOut)
);
}
else
{
isFilterVisible = false;
await Task.WhenAll(
labelCaret.RotateTo(0, easing: Easing.CubicIn),
gridFilter.TranslateTo(0, -60, easing: Easing.CubicIn),
gridFilter.FadeTo(0, easing: Easing.CubicIn),
panelFilter.TranslateTo(0, -60, easing: Easing.CubicIn),
panelFilter.FadeTo(0, easing: Easing.CubicIn)
);
}
}
private async void ChangeFilter()
{
ToggleFilterPanel(false);
await ScrollToTopAsync(scrollView);
startIndex = 0;
lastUpdated = default;
StartLoad();
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
ToggleFilterPanel(!isFilterVisible);
}
private void FlowLayout_MaxHeightChanged(object sender, HeightEventArgs e) private void FlowLayout_MaxHeightChanged(object sender, HeightEventArgs e)
{ {
SetOffset(e.ContentHeight - scrollView.Bounds.Height - SCROLL_OFFSET); SetOffset(e.ContentHeight - scrollView.Bounds.Height - SCROLL_OFFSET);
@ -103,6 +174,14 @@ namespace Pixiview.Illust
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e) private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{ {
var y = e.ScrollY; var y = e.ScrollY;
if (IsScrollingDown(y))
{
// down
if (isFilterVisible)
{
ToggleFilterPanel(false);
}
}
OnScrolled(y); OnScrolled(y);
} }
@ -114,7 +193,6 @@ namespace Pixiview.Illust
flag = true; flag = true;
} }
startIndex = -1; startIndex = -1;
nextIndex = 0;
StartLoad(force); StartLoad(force);
} }

View File

@ -630,6 +630,7 @@ 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 ScrollDirection scrollDirection = ScrollDirection.Stop;
private double lastScrollY = double.MinValue; private double lastScrollY = double.MinValue;
private double lastRefreshY = double.MinValue; private double lastRefreshY = double.MinValue;
@ -637,7 +638,22 @@ namespace Pixiview.Illust
protected bool IsScrollingDown(double y) protected bool IsScrollingDown(double y)
{ {
return y > lastScrollY; if (y > lastScrollY)
{
if (scrollDirection != ScrollDirection.Down)
{
scrollDirection = ScrollDirection.Down;
}
return true;
}
else
{
if (scrollDirection != ScrollDirection.Up)
{
scrollDirection = ScrollDirection.Up;
}
return false;
}
} }
protected void SetOffset(double off) protected void SetOffset(double off)
{ {

View File

@ -86,7 +86,6 @@ namespace Pixiview.Illust
private bool previousEnabled; private bool previousEnabled;
private bool dateEnabled; private bool dateEnabled;
private bool nextEnabled; private bool nextEnabled;
private ScrollDirection scrollDirection = ScrollDirection.Stop;
private bool isFilterVisible; private bool isFilterVisible;
private string lastQueryKey; private string lastQueryKey;
@ -332,23 +331,12 @@ namespace Pixiview.Illust
var y = e.ScrollY; var y = e.ScrollY;
if (IsScrollingDown(y)) if (IsScrollingDown(y))
{ {
if (scrollDirection != ScrollDirection.Down)
{
scrollDirection = ScrollDirection.Down;
}
// down // down
if (isFilterVisible) if (isFilterVisible)
{ {
ToggleFilterPanel(false); ToggleFilterPanel(false);
} }
} }
else
{
if (scrollDirection != ScrollDirection.Up)
{
scrollDirection = ScrollDirection.Up;
}
}
OnScrolled(y); OnScrolled(y);
} }

View File

@ -59,4 +59,7 @@
<FailedResponse>无法获取返回结果。</FailedResponse> <FailedResponse>无法获取返回结果。</FailedResponse>
<ConfirmSyncFavorite>要同步收藏吗?</ConfirmSyncFavorite> <ConfirmSyncFavorite>要同步收藏吗?</ConfirmSyncFavorite>
<ConfirmLogin>当前身份为游客,是否跳转到登录页面?</ConfirmLogin> <ConfirmLogin>当前身份为游客,是否跳转到登录页面?</ConfirmLogin>
<All>所有</All>
<Animation>动画</Animation>
<Online>在线</Online>
</root> </root>

View File

@ -675,9 +675,10 @@ namespace Pixiview.Utils
Changed = true; Changed = true;
} }
public void Reload() public FavoriteList Reload()
{ {
Changed = false; Changed = false;
return this;
} }
} }