Pixiview/Gallery/Illust/RankingPage.xaml.cs
2021-08-04 10:27:41 +08:00

407 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Gallery.Resources;
using Gallery.UI;
using Gallery.Utils;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Gallery.Illust
{
public partial class RankingPage : IllustRankingDataCollectionPage
{
private static readonly string[] segmentDates = { "daily", "weekly", "monthly", "male" };
public static readonly BindableProperty InternalTitleProperty = BindableProperty.Create(
nameof(InternalTitle), typeof(string), typeof(RankingPage));
public string InternalTitle
{
get => (string)GetValue(InternalTitleProperty);
set => SetValue(InternalTitleProperty, value);
}
public static readonly BindableProperty SegmentDateProperty = BindableProperty.Create(
nameof(SegmentDate), typeof(int), typeof(RankingPage), propertyChanged: OnSegmentDatePropertyChanged);
public static readonly BindableProperty SegmentTypeVisibleProperty = BindableProperty.Create(
nameof(SegmentTypeVisible), typeof(bool), typeof(RankingPage));
public static readonly BindableProperty SegmentTypeProperty = BindableProperty.Create(
nameof(SegmentType), typeof(int), typeof(RankingPage), propertyChanged: OnSegmentTypePropertyChanged);
public static readonly BindableProperty MaximumDateProperty = BindableProperty.Create(
nameof(MaximumDate), typeof(DateTime), typeof(RankingPage), DateTime.Today);
public static readonly BindableProperty SelectedDateProperty = BindableProperty.Create(
nameof(SelectedDate), typeof(DateTime), typeof(RankingPage), DateTime.Today);
private static void OnSegmentDatePropertyChanged(BindableObject obj, object old, object @new)
{
var page = (RankingPage)obj;
var index = (int)@new;
if (index == 2)
{
// monthly
var typeIndex = page.SegmentType;
if (typeIndex == 1)
{
// r-18
page.SegmentType = 0;
}
}
}
private static void OnSegmentTypePropertyChanged(BindableObject obj, object old, object @new)
{
var page = (RankingPage)obj;
var index = (int)@new;
if (index == 1)
{
// r-18
var dateIndex = page.SegmentDate;
if (dateIndex == 2)
{
// monthly
page.SegmentDate = 0;
}
}
}
public int SegmentDate
{
get => (int)GetValue(SegmentDateProperty);
set => SetValue(SegmentDateProperty, value);
}
public bool SegmentTypeVisible
{
get => (bool)GetValue(SegmentTypeVisibleProperty);
set => SetValue(SegmentTypeVisibleProperty, value);
}
public int SegmentType
{
get => (int)GetValue(SegmentTypeProperty);
set => SetValue(SegmentTypeProperty, value);
}
public DateTime MaximumDate
{
get => (DateTime)GetValue(MaximumDateProperty);
set => SetValue(MaximumDateProperty, value);
}
public DateTime SelectedDate
{
get => (DateTime)GetValue(SelectedDateProperty);
set => SetValue(SelectedDateProperty, value);
}
public Command<string> ToolbarCommand { get; private set; }
private bool previousEnabled;
private bool dateEnabled;
private bool nextEnabled;
private bool isFilterVisible;
private bool isDatePickerVisible;
private string lastQueryKey;
private string queryDate;
private string previousDate;
private string nextDate;
private int currentPage;
private int nextPage;
private string QueryKey => segmentDates[SegmentDate] + (SegmentType == 1 ? "_r18" : string.Empty);
public RankingPage()
{
Resources.Add("cardView", GetCardViewTemplate(titleBinding: nameof(IllustItem.RankTitle)));
ToolbarCommand = new Command<string>(OnDateTrigger, OnCanDateTrigger);
InitializeComponent();
gridFilter.TranslationY = -100;
panelFilter.TranslationY = -100;
// preferences
SegmentDate = Preferences.Get(Configs.QueryModeKey, 0);
SegmentType = Preferences.Get(Configs.QueryTypeKey, 0);
lastQueryKey = QueryKey;
queryDate = Preferences.Get(Configs.QueryDateKey, null);
currentPage = 1;
datePicker.MinimumDate = new DateTime(2007, 9, 13);
MaximumDate = DateTime.Today.AddDays(-1);
}
protected override ActivityIndicator LoadingIndicator => activityLoading;
protected override void OnAppearing()
{
var r18 = Configs.IsOnR18;
if (!r18)
{
SegmentType = 0;
var query = QueryKey;
if (lastQueryKey != query)
{
ReleaseCollection();
lastQueryKey = query;
}
}
SegmentTypeVisible = r18;
if (currentPage != 1 && Illusts == null)
{
currentPage = 1;
}
base.OnAppearing();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
// saving state
Preferences.Set(Configs.QueryModeKey, SegmentDate);
Preferences.Set(Configs.QueryTypeKey, SegmentType);
if (queryDate != null)
{
Preferences.Set(Configs.QueryDateKey, queryDate);
}
}
protected override IEnumerable<IllustItem> DoGetIllustList(IllustRankingData data, out int tag)
{
tag = currentPage;
if (lastQueryKey != null && lastQueryKey.StartsWith(segmentDates[3]))
{
return data.contents.Where(i => i.illust_type == "0").Select(i => i.ConvertToItem());
}
return data.contents.Select(i => i.ConvertToItem());
}
protected override IllustRankingData DoLoadIllustData(bool force)
{
var data = Stores.LoadIllustRankingData(lastQueryKey, queryDate, currentPage, out lastError, force);
if (data != null)
{
if (int.TryParse(data.next, out int next))
{
nextPage = next;
}
var date = data.date;
DateTime now;
if (date.Length == 8 && int.TryParse(date, out _))
{
queryDate = date;
now = new DateTime(
int.Parse(date.Substring(0, 4)),
int.Parse(date.Substring(4, 2)),
int.Parse(date.Substring(6, 2)));
SelectedDate = now;
//date = now.ToShortDateString();
date = now.ToString("yyyy-MM-dd");
}
else
{
now = default;
}
date = ResourceHelper.GetResource(data.mode, date);
MainThread.BeginInvokeOnMainThread(() => InternalTitle = date);
var prev_date = data.prev_date;
if (int.TryParse(prev_date, out _))
{
previousDate = prev_date;
previousEnabled = true;
}
else
{
previousDate = null;
previousEnabled = false;
}
var next_date = data.next_date;
if (int.TryParse(next_date, out _))
{
nextDate = next_date;
nextEnabled = true;
}
else
{
nextDate = null;
nextEnabled = false;
if (now != default && force)
{
MaximumDate = now;
}
}
}
dateEnabled = true;
MainThread.BeginInvokeOnMainThread(ToolbarCommand.ChangeCanExecute);
return data;
}
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, -100, easing: Easing.CubicIn),
gridFilter.FadeTo(0, easing: Easing.CubicIn),
panelFilter.TranslateTo(0, -100, easing: Easing.CubicIn),
panelFilter.FadeTo(0, easing: Easing.CubicIn)
);
}
}
private async void OnDateTrigger(string action)
{
if (IsLoading)
{
return;
}
if (action == "select")
{
// stop the scrolling
await scrollView.ScrollToAsync(scrollView.ScrollX, scrollView.ScrollY, false);
datePicker.Focus();
}
else
{
var date = action == "prev" ? previousDate : nextDate;
if (date == null)
{
return;
}
if (isFilterVisible)
{
ToggleFilterPanel(false);
}
queryDate = date;
PrepareLoad();
}
}
private bool OnCanDateTrigger(string action)
{
switch (action)
{
case "prev":
return previousEnabled;
case "next":
return nextEnabled;
default:
return dateEnabled;
}
}
private void DatePicker_Focused(object sender, FocusEventArgs e)
{
isDatePickerVisible = e.IsFocused;
}
private void DatePicker_DateSelected(object sender, DateChangedEventArgs e)
{
if (e.OldDate == DateTime.Today || IsLoading)
{
// first load or loading
return;
}
queryDate = e.NewDate.ToString("yyyyMMdd");
PrepareLoad();
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
ToggleFilterPanel(!isFilterVisible);
}
private void FlowLayout_MaxHeightChanged(object sender, HeightEventArgs e)
{
SetOffset(e.ContentHeight - scrollView.Bounds.Height - SCROLL_OFFSET);
}
protected override bool CheckRefresh()
{
if (nextPage == currentPage + 1)
{
currentPage = nextPage;
#if DEBUG
App.DebugPrint($"loading page {nextPage}");
#endif
return true;
}
return false;
}
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
var y = e.ScrollY;
if (IsScrollingDown(y))
{
// down
if (isFilterVisible)
{
ToggleFilterPanel(false);
}
}
if (isDatePickerVisible)
{
isDatePickerVisible = false;
datePicker.Unfocus();
}
OnScrolled(y);
}
private void Filter_Clicked(object sender, EventArgs e)
{
var query = QueryKey;
ToggleFilterPanel(false);
if (IsLoading)
{
return;
}
//if (lastQueryKey != query)
{
// query changed.
lastQueryKey = query;
#if DEBUG
App.DebugPrint($"query changed: {query}");
#endif
PrepareLoad();
}
}
private async void PrepareLoad()
{
await ScrollToTopAsync(scrollView);
// release
currentPage = 1;
previousEnabled = false;
dateEnabled = false;
nextEnabled = false;
ToolbarCommand.ChangeCanExecute();
StartLoad(true);
}
private void ReleaseCollection()
{
currentPage = 1;
InvalidateCollection();
}
}
}