favorite & view page & etc.

This commit is contained in:
2021-08-12 16:27:42 +08:00
parent 3152f47db5
commit fa0b033f2a
33 changed files with 728 additions and 94 deletions

View File

@ -2,11 +2,44 @@
<ui:AdaptedPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:ui="clr-namespace:Gallery.Resources.UI"
x:Class="Gallery.Views.GalleryItemPage"
x:Name="galleryItemPage"
ios:Page.UseSafeArea="False"
Shell.TabBarIsVisible="False"
BindingContext="{x:Reference galleryItemPage}">
<ContentPage.ToolbarItems>
<ToolbarItem Command="{Binding ToolbarCommand}" CommandParameter="favorite"
Order="Primary" IconImageSource="{Binding FavoriteIcon}"/>
<ToolbarItem Command="{Binding ToolbarCommand}" CommandParameter="refresh"
Order="Primary" IconImageSource="{DynamicResource FontIconRefresh}"/>
<ToolbarItem Command="{Binding ToolbarCommand}" CommandParameter="share"
Order="Primary" IconImageSource="{DynamicResource FontIconShare}"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<Grid Padding="{Binding TopMargin}">
<Image HorizontalOptions="Fill"
VerticalOptions="Fill"
Aspect="AspectFit"
Source="{Binding GalleryItem.PreviewImage}"/>
<Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
HorizontalOptions="Center" VerticalOptions="Center"
IsVisible="{Binding IsBusy}"
BackgroundColor="{DynamicResource MaskColor}">
<ActivityIndicator IsVisible="{Binding IsBusy}"
IsRunning="{Binding IsBusy}"
Color="{DynamicResource WindowColor}"/>
</Frame>
<ProgressBar x:Name="progress" IsVisible="{Binding ProgressVisible}"
VerticalOptions="Start">
<ProgressBar.Margin>
<OnPlatform x:TypeArguments="Thickness" Android="0, -6, 0, 0"/>
</ProgressBar.Margin>
</ProgressBar>
</Grid>
</ContentPage.Content>
</ui:AdaptedPage>

View File

@ -1,15 +1,213 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Gallery.Resources.Theme;
using Gallery.Resources.UI;
using Gallery.Services;
using Gallery.Util;
using Gallery.Util.Model;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Gallery.Views
{
[QueryProperty("GalleryId", "id")]
public partial class GalleryItemPage : AdaptedPage
{
public GalleryItemPage()
public static readonly BindableProperty FavoriteIconProperty = BindableProperty.Create(nameof(FavoriteIcon), typeof(ImageSource), typeof(GalleryItemPage));
public static readonly BindableProperty GalleryItemProperty = BindableProperty.Create(nameof(GalleryItem), typeof(GalleryItem), typeof(GalleryItemPage));
public static readonly BindableProperty ProgressVisibleProperty = BindableProperty.Create(nameof(ProgressVisible), typeof(bool), typeof(GalleryItemPage));
public static readonly BindableProperty ToolbarCommandProperty = BindableProperty.Create(nameof(ToolbarCommand), typeof(Command<string>), typeof(GalleryItemPage));
public ImageSource FavoriteIcon
{
get => (ImageSource)GetValue(FavoriteIconProperty);
set => SetValue(FavoriteIconProperty, value);
}
public GalleryItem GalleryItem
{
get => (GalleryItem)GetValue(GalleryItemProperty);
}
public bool ProgressVisible
{
get => (bool)GetValue(ProgressVisibleProperty);
set => SetValue(ProgressVisibleProperty, value);
}
public Command<string> ToolbarCommand
{
get => (Command<string>)GetValue(ToolbarCommandProperty);
}
private readonly ImageSource fontIconLove;
private readonly ImageSource fontIconNotLove;
private bool favoriteChanged;
private bool isLoaded;
public GalleryItemPage(GalleryItem item)
{
SetValue(GalleryItemProperty, item);
SetValue(ToolbarCommandProperty, new Command<string>(HandleCommand, cmd => !IsBusy));
fontIconLove = (ImageSource)Application.Current.Resources[Theme.FontIconLove];
fontIconNotLove = (ImageSource)Application.Current.Resources[Theme.FontIconNotLove];
if (item != null)
{
InitInformation(item);
}
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
Screen.SetHomeIndicatorAutoHidden(Shell.Current, true);
if (!isLoaded)
{
isLoaded = true;
Task.Run(() => LoadImage());
}
}
protected override void OnDisappearing()
{
Screen.SetHomeIndicatorAutoHidden(Shell.Current, false);
base.OnDisappearing();
if (favoriteChanged)
{
Store.SaveFavoriteList();
}
}
private void InitInformation(GalleryItem item)
{
Title = item.TagDescription;
FavoriteIcon = Store.FavoriteList.Any(i => i.SourceEquals(item)) ?
fontIconLove :
fontIconNotLove;
}
private async void LoadImage(bool force = false)
{
IsBusy = true;
MainThread.BeginInvokeOnMainThread(async () =>
{
ToolbarCommand.ChangeCanExecute();
if (force)
{
ProgressVisible = true;
progress.Progress = 0;
await progress.FadeTo(1, easing: Easing.CubicIn);
}
});
var item = GalleryItem;
if (item.IsRawPage)
{
var source = App.GallerySources.FirstOrDefault(s => s.Route == item.Source);
if (source != null)
{
var url = await source.ResolveImageUrl(item);
if (!string.IsNullOrEmpty(url))
{
item.IsRawPage = false;
}
}
}
var image = await Store.LoadRawImage(item, force: force, o =>
{
var val = o.loc / (double)o.size;
if (val > progress.Progress)
{
MainThread.BeginInvokeOnMainThread(async () =>
{
if (!ProgressVisible)
{
ProgressVisible = true;
}
progress.CancelAnimations();
await progress.ProgressTo(val, 250, Easing.CubicIn);
});
}
});
if (image != null)
{
item.PreviewImage = image;
}
IsBusy = false;
MainThread.BeginInvokeOnMainThread(async () =>
{
ToolbarCommand.ChangeCanExecute();
progress.CancelAnimations();
await progress.ProgressTo(1, 250, Easing.CubicIn);
await progress.FadeTo(0, easing: Easing.CubicIn);
ProgressVisible = false;
});
}
private void HandleCommand(string cmd)
{
switch (cmd)
{
case "favorite": Favorite_Clicked(); break;
case "refresh": Refresh_Clicked(); break;
case "share": Share_Clicked(); break;
}
}
private void Favorite_Clicked()
{
if (IsBusy)
{
return;
}
Start(() =>
{
var favorites = Store.FavoriteList;
var item = GalleryItem;
var index = favorites.FindIndex(i => i.SourceEquals(item));
if (index < 0)
{
item.IsFavorite = true;
favorites.Insert(0, item);
FavoriteIcon = fontIconLove;
}
else
{
favorites.RemoveAt(index);
item.IsFavorite = false;
FavoriteIcon = fontIconNotLove;
}
favoriteChanged = true;
});
}
private void Refresh_Clicked()
{
if (IsBusy)
{
return;
}
Start(async () => await Task.Run(() => LoadImage(true)));
}
private void Share_Clicked()
{
if (IsBusy)
{
return;
}
Start(async () =>
{
var item = GalleryItem;
var path = Store.GetRawImagePath(item);
await Share.RequestAsync(new ShareFileRequest
{
Title = item.TagDescription,
File = new ShareFile(path)
});
});
}
}
}

View File

@ -8,6 +8,11 @@
BackgroundColor="{DynamicResource WindowColor}"
BindingContext="{x:Reference yanderePage}"
Title="{Binding Source.Name}">
<ContentPage.ToolbarItems>
<ToolbarItem Order="Primary" Command="{Binding ToolbarCommand}"
IconImageSource="{DynamicResource FontIconRefresh}"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<Grid>
<ScrollView x:Name="scrollView" Scrolled="ScrollView_Scrolled"

View File

@ -4,17 +4,25 @@ using Gallery.Resources.UI;
using Gallery.Util;
using Gallery.Util.Interface;
using Gallery.Util.Model;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Gallery.Views
{
public partial class GalleryPage : GalleryCollectionPage
{
public static readonly BindableProperty ToolbarCommandProperty = BindableProperty.Create(nameof(ToolbarCommand), typeof(Command), typeof(GalleryPage));
public Command ToolbarCommand
{
get => (Command)GetValue(ToolbarCommandProperty);
}
private int currentPage;
public GalleryPage(IGallerySource source) : base(source)
{
Resources.Add("cardView", GetCardViewTemplate());
SetValue(ToolbarCommandProperty, new Command(DoRefresh, () => !IsLoading && !IsBottomLoading));
InitializeComponent();
currentPage = 1;
@ -28,21 +36,62 @@ namespace Gallery.Views
{
currentPage = 1;
}
if (Store.FavoriteList.Changed && Source is Sources.FavoriteGallerySource)
{
Store.FavoriteList.Reload();
LastUpdated = default;
}
base.OnAppearing();
}
protected override async Task<GalleryItem[]> DoloadGalleryData(bool force)
protected override void BeforeLoading()
{
MainThread.BeginInvokeOnMainThread(ToolbarCommand.ChangeCanExecute);
}
protected override void AfterLoaded()
{
MainThread.BeginInvokeOnMainThread(ToolbarCommand.ChangeCanExecute);
}
protected override async Task<IEnumerable<GalleryItem>> DoloadGalleryData(bool force)
{
var result = await Source.GetRecentItemsAsync(currentPage);
return result;
}
protected override IEnumerable<GalleryItem> DoGetGalleryList(GalleryItem[] data, out int tag)
protected override IEnumerable<GalleryItem> DoGetGalleryList(IEnumerable<GalleryItem> data, out int tag)
{
tag = currentPage;
return data;
}
protected override void OnGalleryItemTapped(GalleryItem item)
{
if (item == null)
{
return;
}
Start(async () =>
{
var page = new GalleryItemPage(item);
await Navigation.PushAsync(page);
});
}
private void DoRefresh()
{
if (IsLoading)
{
return;
}
Start(async () =>
{
await ScrollToTopAsync(scrollView);
StartLoading(force: true);
});
}
private void FlowLayout_MaxHeightChanged(object sender, HeightEventArgs e)
{
SetOffset(e.ContentHeight - scrollView.Bounds.Height - SCROLL_OFFSET);
@ -50,6 +99,10 @@ namespace Gallery.Views
protected override bool CheckRefresh()
{
if (!Source.IsScrollable)
{
return false;
}
currentPage++;
#if DEBUG
Log.Print($"loading page: {currentPage}");