UI adjustment

This commit is contained in:
Tsanie Lily 2020-05-09 08:38:31 +08:00
parent 33cac052f6
commit 8c9f79f06d
19 changed files with 492 additions and 314 deletions

View File

@ -51,6 +51,11 @@ namespace Pixiview.iOS.Renderers
{ {
return new AppShellTabBarAppearanceTracker(); return new AppShellTabBarAppearanceTracker();
} }
protected override void UpdateBackgroundColor()
{
NativeView.BackgroundColor = Color.Transparent.ToUIColor();
}
} }
public class AppShellItemTransition : IShellItemTransition public class AppShellItemTransition : IShellItemTransition

View File

@ -10,7 +10,8 @@
BackgroundColor="{DynamicResource NavColor}" BackgroundColor="{DynamicResource NavColor}"
ForegroundColor="{DynamicResource TintColor}" ForegroundColor="{DynamicResource TintColor}"
TitleColor="{DynamicResource TextColor}" TitleColor="{DynamicResource TextColor}"
UnselectedColor="{DynamicResource SubTextColor}"> UnselectedColor="{DynamicResource SubTextColor}"
FlyoutBackgroundColor="{DynamicResource WindowColor}">
<Shell.FlyoutHeaderTemplate> <Shell.FlyoutHeaderTemplate>
<DataTemplate> <DataTemplate>
<Grid RowSpacing="0" BackgroundColor="{DynamicResource WindowColor}" Padding="20, 0, 0, 20"> <Grid RowSpacing="0" BackgroundColor="{DynamicResource WindowColor}" Padding="20, 0, 0, 20">
@ -35,7 +36,12 @@
<VisualStateManager.VisualStateGroups> <VisualStateManager.VisualStateGroups>
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/> <VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor"
Value="{DynamicResource WindowColor}"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Selected"> <VisualState x:Name="Selected">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="BackgroundColor" <Setter Property="BackgroundColor"
@ -46,13 +52,13 @@
</VisualStateGroupList> </VisualStateGroupList>
</VisualStateManager.VisualStateGroups> </VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/> <ColumnDefinition Width="{x:OnPlatform Android=54, iOS=50}"/>
<ColumnDefinition/> <ColumnDefinition/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image Source="{Binding FlyoutIcon}" <Image Source="{Binding FlyoutIcon}"
HorizontalOptions="Center" VerticalOptions="Center" HorizontalOptions="Center" VerticalOptions="Center"
HeightRequest="22"/> HeightRequest="22"/>
<Label Grid.Column="1" <Label Grid.Column="1" TextColor="{DynamicResource TextColor}"
Text="{Binding Title}" Text="{Binding Title}"
FontSize="{x:OnPlatform Android=14, iOS=Small}" FontSize="{x:OnPlatform Android=14, iOS=Small}"
VerticalTextAlignment="Center"/> VerticalTextAlignment="Center"/>

View File

@ -15,7 +15,7 @@
ItemTemplate="{StaticResource cardView}"/> ItemTemplate="{StaticResource cardView}"/>
</ScrollView> </ScrollView>
<Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8" <Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
IsVisible="{Binding Loading}" IsVisible="{Binding IsLoading}"
HorizontalOptions="Center" VerticalOptions="Center" HorizontalOptions="Center" VerticalOptions="Center"
BackgroundColor="{DynamicResource MaskColor}"> BackgroundColor="{DynamicResource MaskColor}">
<ActivityIndicator IsRunning="True" IsVisible="True" <ActivityIndicator IsRunning="True" IsVisible="True"

View File

@ -13,14 +13,17 @@ using Xamarin.Forms;
namespace Pixiview.Illust namespace Pixiview.Illust
{ {
public abstract class FavoriteIllustCollectionPage : IllustCollectionPage<IllustItem[]>
{
public override void OnUnload() { }
}
public abstract class IllustDataCollectionPage : IllustCollectionPage<IllustData> { }
public abstract class IllustUserDataCollectionPage : IllustCollectionPage<IllustUserData> { }
public interface IIllustCollectionPage public interface IIllustCollectionPage
{ {
IllustCollection IllustCollection { get; set; } IllustCollection IllustCollection { get; set; }
} }
public abstract class IllustDataCollectionPage : IllustCollectionPage<IllustData> { }
public abstract class FavoriteIllustCollectionPage : IllustCollectionPage<IllustItem[]> { }
public abstract class IllustCollectionPage<T> : AdaptedPage, IIllustCollectionPage public abstract class IllustCollectionPage<T> : AdaptedPage, IIllustCollectionPage
{ {
#region - Properties - #region - Properties -
@ -29,19 +32,8 @@ namespace Pixiview.Illust
nameof(Illusts), typeof(IllustCollection), typeof(IllustCollectionPage<T>)); nameof(Illusts), typeof(IllustCollection), typeof(IllustCollectionPage<T>));
public static readonly BindableProperty ColumnsProperty = BindableProperty.Create( public static readonly BindableProperty ColumnsProperty = BindableProperty.Create(
nameof(Columns), typeof(int), typeof(IllustCollectionPage<T>), 2); nameof(Columns), typeof(int), typeof(IllustCollectionPage<T>), 2);
public static readonly BindableProperty LoadingProperty = BindableProperty.Create( public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(
nameof(Loading), typeof(bool), typeof(IllustCollectionPage<T>), propertyChanged: OnLoadingPropertyChanged); nameof(IsLoading), typeof(bool), typeof(IllustCollectionPage<T>), true);
private static void OnLoadingPropertyChanged(BindableObject obj, object oldValue, object newValue)
{
var page = (IllustCollectionPage<T>)obj;
var now = (bool)newValue;
if (!page.loaded && now && Stores.NetworkAvailable)
{
page.loaded = true;
Task.Run(() => page.DoLoadIllusts());
}
}
public IllustCollection Illusts public IllustCollection Illusts
{ {
@ -53,15 +45,15 @@ namespace Pixiview.Illust
get => (int)GetValue(ColumnsProperty); get => (int)GetValue(ColumnsProperty);
set => SetValue(ColumnsProperty, value); set => SetValue(ColumnsProperty, value);
} }
public bool Loading public bool IsLoading
{ {
get => (bool)GetValue(LoadingProperty); get => (bool)GetValue(IsLoadingProperty);
set => SetValue(LoadingProperty, value); set => SetValue(IsLoadingProperty, value);
} }
#endregion #endregion
protected static bool IsUpdated { get; private set; } = true; protected static bool NeedUpdate { get; private set; } = true;
public IllustCollection IllustCollection { get; set; } public IllustCollection IllustCollection { get; set; }
@ -76,8 +68,8 @@ namespace Pixiview.Illust
public IllustCollectionPage() public IllustCollectionPage()
{ {
BindingContext = this;
commandIllustImageTapped = new Command<IllustItem>(IllustImageTapped); commandIllustImageTapped = new Command<IllustItem>(IllustImageTapped);
BindingContext = this;
} }
private void IllustImageTapped(IllustItem illust) private void IllustImageTapped(IllustItem illust)
@ -87,14 +79,20 @@ namespace Pixiview.Illust
#region - Overrides - #region - Overrides -
public override void OnUnload()
{
Illusts = IllustCollection.Empty;
loaded = false;
}
protected override void OnAppearing() protected override void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();
Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged; Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;
if (IsUpdated || !loaded) if (NeedUpdate || !loaded)
{ {
IsUpdated = false; NeedUpdate = false;
loaded = false; loaded = false;
StartLoad(); StartLoad();
} }
@ -163,21 +161,133 @@ namespace Pixiview.Illust
protected void StartLoad(bool force = false) protected void StartLoad(bool force = false)
{ {
if (force) if (force || !loaded)
{ {
Loading = true; loaded = true;
Task.Run(() => DoLoadIllusts(true)); IsLoading = true;
} Task.Run(() => DoLoadIllusts(force));
else if (!loaded)
{
Loading = true;
} }
} }
protected DataTemplate GetCardViewTemplate() protected DataTemplate GetCardViewTemplate(bool hideUser = false)
{ {
return new DataTemplate(() => return new DataTemplate(() =>
{ {
#region - components -
// image
var image = new RoundImage
{
BackgroundColor = Color.LightGray,
CornerRadius = 10,
CornerMasks = CornerMask.Top,
HorizontalOptions = LayoutOptions.Fill,
Aspect = Aspect.AspectFill,
GestureRecognizers =
{
new TapGestureRecognizer()
.Binding(TapGestureRecognizer.CommandProperty, nameof(IllustItem.IllustTapped))
.Binding(TapGestureRecognizer.CommandParameterProperty, ".")
}
}
.Binding(Image.SourceProperty, nameof(IllustItem.Image));
// label: r-18
var r18 = new RoundLabel
{
Text = ResourceHelper.R18,
BackgroundColor = StyleDefinition.ColorRedBackground,
Margin = new Thickness(6, 6, 0, 0),
Padding = new Thickness(6, 2),
CornerRadius = 4,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Start,
FontSize = StyleDefinition.FontSizeMicro,
TextColor = Color.White
}
.Binding(IsVisibleProperty, nameof(IllustItem.IsRestrict));
// label: pages
var pages = new RoundLabel
{
BackgroundColor = StyleDefinition.ColorDeepShadow,
Margin = new Thickness(0, 6, 6, 0),
Padding = new Thickness(6, 4),
CornerRadius = 6,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Start,
FontSize = StyleDefinition.FontSizeMicro,
TextColor = Color.White
}
.Binding(Label.TextProperty, nameof(IllustItem.PageCountText))
.Binding(IsVisibleProperty, nameof(IllustItem.IsPageVisible))
.DynamicResource(Label.FontFamilyProperty, ThemeBase.IconSolidFontFamily);
// label: title
var title = new Label
{
Padding = new Thickness(8, 2),
HorizontalOptions = LayoutOptions.FillAndExpand,
LineBreakMode = LineBreakMode.TailTruncation,
FontSize = StyleDefinition.FontSizeSmall
}
.Binding(Label.TextProperty, nameof(IllustItem.Title))
.DynamicResource(Label.TextColorProperty, ThemeBase.TextColor);
// label: favorite
var favorite = new Label
{
WidthRequest = 26,
HorizontalOptions = LayoutOptions.End,
HorizontalTextAlignment = TextAlignment.End,
VerticalOptions = LayoutOptions.Center,
FontSize = StyleDefinition.FontSizeSmall,
TextColor = StyleDefinition.ColorRedBackground,
Text = StyleDefinition.IconLove
}
.Binding(IsVisibleProperty, IsFavoriteVisible ? nameof(IllustItem.IsFavorite) : null)
.DynamicResource(Label.FontFamilyProperty, ThemeBase.IconSolidFontFamily);
#endregion
if (hideUser)
{
return new CardView
{
Padding = 0,
Margin = 0,
CornerRadius = 10,
ShadowColor = StyleDefinition.ColorLightShadow,
ShadowOffset = new Size(2, 2),
Content = new Grid
{
HorizontalOptions = LayoutOptions.Fill,
RowDefinitions =
{
new RowDefinition().Binding(RowDefinition.HeightProperty, nameof(IllustItem.ImageHeight)),
new RowDefinition { Height = GridLength.Auto }
},
Children =
{
image,
r18,
pages,
title,
// stacklayout: user
new StackLayout
{
Orientation = StackOrientation.Horizontal,
Padding = new Thickness(0, 0, 8, 0),
Children = { title, favorite }
}
.GridRow(1)
}
}
}
.DynamicResource(BackgroundColorProperty, ThemeBase.CardBackgroundColor);
}
return new CardView return new CardView
{ {
Padding = 0, Padding = 0,
@ -196,65 +306,10 @@ namespace Pixiview.Illust
}, },
Children = Children =
{ {
// image image,
new RoundImage r18,
{ pages,
BackgroundColor = Color.LightGray, title.GridRow(1),
CornerRadius = 10,
CornerMasks = CornerMask.Top,
HorizontalOptions = LayoutOptions.Fill,
Aspect = Aspect.AspectFill,
GestureRecognizers =
{
new TapGestureRecognizer()
.Binding(TapGestureRecognizer.CommandProperty, nameof(IllustItem.IllustTapped))
.Binding(TapGestureRecognizer.CommandParameterProperty, ".")
}
}
.Binding(Image.SourceProperty, nameof(IllustItem.Image)),
// label: r-18
new RoundLabel
{
Text = ResourceHelper.R18,
BackgroundColor = StyleDefinition.ColorRedBackground,
Margin = new Thickness(6, 6, 0, 0),
Padding = new Thickness(6, 2),
CornerRadius = 4,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Start,
FontSize = StyleDefinition.FontSizeMicro,
TextColor = Color.White
}
.Binding(IsVisibleProperty, nameof(IllustItem.IsRestrict)),
// label: pages
new RoundLabel
{
BackgroundColor = StyleDefinition.ColorDeepShadow,
Margin = new Thickness(0, 6, 6, 0),
Padding = new Thickness(6, 4),
CornerRadius = 6,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Start,
FontSize = StyleDefinition.FontSizeMicro,
TextColor = Color.White
}
.Binding(Label.TextProperty, nameof(IllustItem.PageCountText))
.Binding(IsVisibleProperty, nameof(IllustItem.IsPageVisible))
.DynamicResource(Label.FontFamilyProperty, ThemeBase.IconSolidFontFamily),
// label: title
new Label
{
Padding = new Thickness(8, 2),
HorizontalOptions = LayoutOptions.Start,
LineBreakMode = LineBreakMode.TailTruncation,
FontSize = StyleDefinition.FontSizeSmall
}
.Binding(Label.TextProperty, nameof(IllustItem.Title))
.DynamicResource(Label.TextColorProperty, ThemeBase.TextColor)
.GridRow(1),
// stacklayout: user // stacklayout: user
new StackLayout new StackLayout
@ -284,18 +339,7 @@ namespace Pixiview.Illust
.DynamicResource(Label.TextColorProperty, ThemeBase.SubTextColor), .DynamicResource(Label.TextColorProperty, ThemeBase.SubTextColor),
// label: favorite // label: favorite
new Label favorite
{
WidthRequest = 26,
HorizontalOptions = LayoutOptions.End,
HorizontalTextAlignment = TextAlignment.End,
VerticalOptions = LayoutOptions.Center,
FontSize = StyleDefinition.FontSizeSmall,
TextColor = StyleDefinition.ColorRedBackground,
Text = StyleDefinition.IconLove
}
.Binding(IsVisibleProperty, IsFavoriteVisible ? nameof(IllustItem.IsFavorite) : null)
.DynamicResource(Label.FontFamilyProperty, ThemeBase.IconSolidFontFamily)
} }
} }
.GridRow(2) .GridRow(2)
@ -308,18 +352,18 @@ namespace Pixiview.Illust
#region - Illust Tasks - #region - Illust Tasks -
protected void DoLoadIllusts(bool force = false, bool skipImage = false) protected void DoLoadIllusts(bool force = false)
{ {
illustData = DoLoadIllustData(force); illustData = DoLoadIllustData(force);
if (illustData == null) if (illustData == null)
{ {
//App.DebugError("illusts.load", "failed to load illusts data."); //App.DebugError("illusts.load", "failed to load illusts data.");
Loading = false; IsLoading = false;
return; return;
} }
if (force) if (force)
{ {
IsUpdated = true; NeedUpdate = true;
} }
var data = DoGetIllustList(illustData, commandIllustImageTapped).Where(i => i != null); var data = DoGetIllustList(illustData, commandIllustImageTapped).Where(i => i != null);
@ -335,12 +379,9 @@ namespace Pixiview.Illust
} }
IllustCollection = collection; IllustCollection = collection;
Illusts = collection; Illusts = collection;
Loading = false; IsLoading = false;
if (!skipImage) DoLoadImages(collection);
{
DoLoadImages(collection);
}
} }
void DoLoadImages(IllustCollection collection) void DoLoadImages(IllustCollection collection)
@ -354,7 +395,11 @@ namespace Pixiview.Illust
if (illust.ImageUrl != null) if (illust.ImageUrl != null)
{ {
var url = Configs.GetThumbnailUrl(illust.ImageUrl); var url = Configs.GetThumbnailUrl(illust.ImageUrl);
var image = Stores.LoadThumbnailImage(url); var image = Stores.LoadPreviewImage(url, false);
if (image == null)
{
image = Stores.LoadThumbnailImage(url);
}
if (image != null) if (image != null)
{ {
illust.Image = image; illust.Image = image;

View File

@ -19,7 +19,7 @@
ItemTemplate="{StaticResource cardView}"/> ItemTemplate="{StaticResource cardView}"/>
</ScrollView> </ScrollView>
<Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8" <Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
IsVisible="{Binding Loading}" IsVisible="{Binding IsLoading}"
HorizontalOptions="Center" VerticalOptions="Center" HorizontalOptions="Center" VerticalOptions="Center"
BackgroundColor="{DynamicResource MaskColor}"> BackgroundColor="{DynamicResource MaskColor}">
<ActivityIndicator IsRunning="True" IsVisible="True" <ActivityIndicator IsRunning="True" IsVisible="True"

View File

@ -14,12 +14,6 @@ namespace Pixiview.Illust
InitializeComponent(); InitializeComponent();
} }
public override void OnUnload()
{
Illusts = IllustCollection.Empty;
loaded = false;
}
protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data, ICommand command) protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data, ICommand command)
{ {
return data.body.page.follow.Select(i => return data.body.page.follow.Select(i =>
@ -40,7 +34,7 @@ namespace Pixiview.Illust
private void Refresh_Clicked(object sender, EventArgs e) private void Refresh_Clicked(object sender, EventArgs e)
{ {
if (Loading) if (IsLoading)
{ {
return; return;
} }

View File

@ -25,7 +25,7 @@
SearchButtonPressed="SearchBar_SearchButtonPressed" SearchButtonPressed="SearchBar_SearchButtonPressed"
Unfocused="SearchBar_Unfocused"/> Unfocused="SearchBar_Unfocused"/>
<Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8" <Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
IsVisible="{Binding Loading}" IsVisible="{Binding IsLoading}"
HorizontalOptions="Center" VerticalOptions="Center" HorizontalOptions="Center" VerticalOptions="Center"
BackgroundColor="{DynamicResource MaskColor}"> BackgroundColor="{DynamicResource MaskColor}">
<ActivityIndicator IsRunning="True" IsVisible="True" <ActivityIndicator IsRunning="True" IsVisible="True"

View File

@ -28,12 +28,6 @@ namespace Pixiview.Illust
InitializeComponent(); InitializeComponent();
} }
public override void OnUnload()
{
Illusts = IllustCollection.Empty;
loaded = false;
}
public override void OnOrientationChanged(Orientation orientation) public override void OnOrientationChanged(Orientation orientation)
{ {
int columns; int columns;
@ -92,7 +86,7 @@ namespace Pixiview.Illust
private void Refresh_Clicked(object sender, EventArgs e) private void Refresh_Clicked(object sender, EventArgs e)
{ {
if (Loading) if (IsLoading)
{ {
return; return;
} }

View File

@ -32,7 +32,7 @@
</u:SegmentedControl> </u:SegmentedControl>
</Grid> </Grid>
<Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8" <Frame HasShadow="False" Margin="0" Padding="20" CornerRadius="8"
IsVisible="{Binding Loading}" IsVisible="{Binding IsLoading}"
HorizontalOptions="Center" VerticalOptions="Center" HorizontalOptions="Center" VerticalOptions="Center"
BackgroundColor="{DynamicResource MaskColor}"> BackgroundColor="{DynamicResource MaskColor}">
<ActivityIndicator IsRunning="True" IsVisible="True" <ActivityIndicator IsRunning="True" IsVisible="True"

View File

@ -35,12 +35,6 @@ namespace Pixiview.Illust
InitializeComponent(); InitializeComponent();
} }
public override void OnUnload()
{
Illusts = IllustCollection.Empty;
loaded = false;
}
public override void OnOrientationChanged(Orientation orientation) public override void OnOrientationChanged(Orientation orientation)
{ {
int columns; int columns;
@ -108,7 +102,7 @@ namespace Pixiview.Illust
private void Refresh_Clicked(object sender, EventArgs e) private void Refresh_Clicked(object sender, EventArgs e)
{ {
if (Loading) if (IsLoading)
{ {
return; return;
} }

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<i:IllustUserDataCollectionPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:i="clr-namespace:Pixiview.Illust"
xmlns:u="clr-namespace:Pixiview.UI"
x:Class="Pixiview.Illust.UserIllustPage"
BackgroundColor="{DynamicResource WindowColor}">
<Shell.TitleView>
<StackLayout Orientation="Horizontal" Padding="0, 2, 0, 4">
<u:CircleImage Aspect="AspectFill" Source="{Binding UserIcon}"/>
<Label Text="{Binding IllustItem.UserName}" Margin="10, 0, 0, 0"
VerticalOptions="Center" LineBreakMode="TailTruncation"
TextColor="{DynamicResource TextColor}"/>
</StackLayout>
</Shell.TitleView>
<ContentPage.ToolbarItems>
<ToolbarItem Order="Primary" Clicked="Refresh_Clicked"
IconImageSource="{DynamicResource FontIconRefresh}"/>
</ContentPage.ToolbarItems>
<Grid>
<ScrollView HorizontalOptions="Fill">
<u:FlowLayout ItemsSource="{Binding Illusts}"
HorizontalOptions="Fill" Column="{Binding Columns}"
Margin="16" RowSpacing="16" ColumnSpacing="16"
ItemTemplate="{StaticResource cardView}"/>
</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>
</i:IllustUserDataCollectionPage>

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;
using Pixiview.Utils;
using Xamarin.Forms;
namespace Pixiview.Illust
{
public partial class UserIllustPage : IllustUserDataCollectionPage
{
public static readonly BindableProperty UserIconProperty = BindableProperty.Create(
nameof(UserIcon), typeof(ImageSource), typeof(UserIllustPage));
public ImageSource UserIcon
{
get => (ImageSource)GetValue(UserIconProperty);
set => SetValue(UserIconProperty, value);
}
public IllustItem IllustItem { get; }
public UserIllustPage(IllustItem illust)
{
IllustItem = illust;
UserIcon = illust.ProfileImage;
Resources.Add("cardView", GetCardViewTemplate(true));
InitializeComponent();
}
protected override IEnumerable<IllustItem> DoGetIllustList(IllustUserData data, ICommand command)
{
return data.body.works.Select(i =>
{
var item = i.Value?.ConvertToItem();
if (item != null)
{
item.IllustTapped = command;
}
return item;
});
}
protected override IllustUserData DoLoadIllustData(bool force)
{
return Stores.LoadIllustUserData(IllustItem.UserId, force);
}
private void Refresh_Clicked(object sender, EventArgs e)
{
if (IsLoading)
{
return;
}
StartLoad(true);
}
}
}

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
@ -69,12 +70,9 @@ namespace Pixiview.Illust
fontIconLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconLove]; fontIconLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconLove];
fontIconNotLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconNotLove]; fontIconNotLove = (ImageSource)Application.Current.Resources[ThemeBase.FontIconNotLove];
var favorites = Stores.Favorites; var favorites = Stores.Favorites;
if (favorites != null) FavoriteIcon = favorites.Any(i => i.Id == illust.Id)
{ ? fontIconLove
FavoriteIcon = favorites.Any(i => i.Id == illust.Id) : fontIconNotLove;
? fontIconLove
: fontIconNotLove;
}
InitializeComponent(); InitializeComponent();
@ -143,10 +141,11 @@ namespace Pixiview.Illust
private void DoLoadImages() private void DoLoadImages()
{ {
var pages = Stores.LoadIllustPageData(IllustItem.Id); var illustItem = IllustItem;
var pages = Stores.LoadIllustPageData(illustItem.Id);
if (pages == null) if (pages == null)
{ {
App.DebugError("illustPage.load", $"failed to load illust page data, id: {IllustItem.Id}"); App.DebugError("illustPage.load", $"failed to load illust page data, id: {illustItem.Id}");
return; return;
} }
var items = Illusts; var items = Illusts;
@ -174,6 +173,11 @@ namespace Pixiview.Illust
} }
DoLoadImage(0, true); DoLoadImage(0, true);
var image = items[0].Image;
if (image != null)
{
illustItem.Image = image;
}
if (items.Length > 1) if (items.Length > 1)
{ {
DoLoadImage(1); DoLoadImage(1);
@ -233,10 +237,6 @@ namespace Pixiview.Illust
private void Favorite_Clicked(object sender, EventArgs e) private void Favorite_Clicked(object sender, EventArgs e)
{ {
var favorites = Stores.Favorites; var favorites = Stores.Favorites;
if (favorites == null)
{
return;
}
var illust = IllustItem; var illust = IllustItem;
var index = favorites.FindIndex(i => i.Id == illust.Id); var index = favorites.FindIndex(i => i.Id == illust.Id);
if (index < 0) if (index < 0)
@ -255,23 +255,23 @@ namespace Pixiview.Illust
private async void Illust_LongPressed(IllustDetailItem item) private async void Illust_LongPressed(IllustDetailItem item)
{ {
List<string> extras = new List<string>();
var share = ResourceHelper.Share; var share = ResourceHelper.Share;
string[] extras;
var preview = Stores.GetPreviewImagePath(item.PreviewUrl); var preview = Stores.GetPreviewImagePath(item.PreviewUrl);
if (string.IsNullOrEmpty(preview)) if (preview != null)
{ {
extras = new string[0]; extras.Add(share);
}
else
{
extras = new[] { share };
} }
var saveOriginal = ResourceHelper.SaveOriginal; var saveOriginal = ResourceHelper.SaveOriginal;
var userDetail = ResourceHelper.UserDetail;
extras.Add(userDetail);
var illustItem = IllustItem;
var result = await DisplayActionSheet( var result = await DisplayActionSheet(
IllustItem.Title, illustItem.Title,
ResourceHelper.Cancel, ResourceHelper.Cancel,
saveOriginal, saveOriginal,
extras); extras.ToArray());
if (result == saveOriginal) if (result == saveOriginal)
{ {
SaveOriginalImage(item); SaveOriginalImage(item);
@ -280,10 +280,15 @@ namespace Pixiview.Illust
{ {
await Share.RequestAsync(new ShareFileRequest await Share.RequestAsync(new ShareFileRequest
{ {
Title = IllustItem.Title, Title = illustItem.Title,
File = new ShareFile(preview) File = new ShareFile(preview)
}); });
} }
else if (result == userDetail)
{
var page = new UserIllustPage(illustItem);
await Navigation.PushAsync(page);
}
} }
private async void SaveOriginalImage(IllustDetailItem item) private async void SaveOriginalImage(IllustDetailItem item)

View File

@ -17,6 +17,7 @@
<Operation>操作</Operation> <Operation>操作</Operation>
<SaveOriginal>保存原图</SaveOriginal> <SaveOriginal>保存原图</SaveOriginal>
<Share>分享</Share> <Share>分享</Share>
<UserDetail>浏览用户</UserDetail>
<SaveSuccess>成功保存图片到照片库。</SaveSuccess> <SaveSuccess>成功保存图片到照片库。</SaveSuccess>
<AlreadySavedQuestion>原图已保存,是否继续?</AlreadySavedQuestion> <AlreadySavedQuestion>原图已保存,是否继续?</AlreadySavedQuestion>
</root> </root>

View File

@ -19,6 +19,7 @@ namespace Pixiview.Resources
public static string Operation => GetResource(nameof(Operation)); public static string Operation => GetResource(nameof(Operation));
public static string SaveOriginal => GetResource(nameof(SaveOriginal)); public static string SaveOriginal => GetResource(nameof(SaveOriginal));
public static string Share => GetResource(nameof(Share)); public static string Share => GetResource(nameof(Share));
public static string UserDetail => GetResource(nameof(UserDetail));
public static string SaveSuccess => GetResource(nameof(SaveSuccess)); public static string SaveSuccess => GetResource(nameof(SaveSuccess));
public static string AlreadySavedQuestion => GetResource(nameof(AlreadySavedQuestion)); public static string AlreadySavedQuestion => GetResource(nameof(AlreadySavedQuestion));

View File

@ -32,7 +32,7 @@ namespace Pixiview.UI.Theme
Add(TintColor, Color.FromRgb(0x00, 0x96, 0xfa)); // 0x7f, 0x99, 0xc6 Add(TintColor, Color.FromRgb(0x00, 0x96, 0xfa)); // 0x7f, 0x99, 0xc6
Add(TextColor, Color.Black); Add(TextColor, Color.Black);
Add(SubTextColor, Color.DimGray); Add(SubTextColor, Color.DimGray);
Add(CardBackgroundColor, Color.FromRgb(0xfa, 0xfa, 0xf0)); Add(CardBackgroundColor, Color.FromRgb(0xf0, 0xf3, 0xf3));
Add(MaskColor, Color.FromRgba(0, 0, 0, 0x50)); Add(MaskColor, Color.FromRgba(0, 0, 0, 0x50));
Add(NavColor, Color.FromRgb(0xf0, 0xf0, 0xf0)); Add(NavColor, Color.FromRgb(0xf0, 0xf0, 0xf0));
Add(NavSelectedColor, Color.LightGray); Add(NavSelectedColor, Color.LightGray);

View File

@ -2,7 +2,7 @@
namespace Pixiview.UI.Theme namespace Pixiview.UI.Theme
{ {
public class ThemeBase : ResourceDictionary public abstract class ThemeBase : ResourceDictionary
{ {
public const string FontIconUser = nameof(FontIconUser); public const string FontIconUser = nameof(FontIconUser);
public const string FontIconSparkles = nameof(FontIconSparkles); public const string FontIconSparkles = nameof(FontIconSparkles);
@ -55,22 +55,21 @@ namespace Pixiview.UI.Theme
} }
} }
var tintColor = (Color)this[TextColor];
var regularFontFamily = (string)this[IconRegularFontFamily]; var regularFontFamily = (string)this[IconRegularFontFamily];
var solidFontFamily = (string)this[IconSolidFontFamily]; var solidFontFamily = (string)this[IconSolidFontFamily];
Add(FontIconUser, GetSolidIcon(StyleDefinition.IconUser, solidFontFamily, tintColor));
Add(FontIconSparkles, GetSolidIcon(StyleDefinition.IconSparkles, solidFontFamily, tintColor));
Add(FontIconOrder, GetSolidIcon(StyleDefinition.IconOrder, solidFontFamily, tintColor));
Add(FontIconRefresh, GetSolidIcon(StyleDefinition.IconRefresh, solidFontFamily, tintColor));
Add(FontIconLove, GetSolidIcon(StyleDefinition.IconLove, solidFontFamily, StyleDefinition.ColorRedBackground)); Add(FontIconLove, GetSolidIcon(StyleDefinition.IconLove, solidFontFamily, StyleDefinition.ColorRedBackground));
Add(FontIconNotLove, GetSolidIcon(StyleDefinition.IconLove, regularFontFamily, tintColor)); Add(FontIconUser, GetSolidIcon(StyleDefinition.IconUser, solidFontFamily));
Add(FontIconOption, GetSolidIcon(StyleDefinition.IconOption, solidFontFamily, tintColor)); Add(FontIconSparkles, GetSolidIcon(StyleDefinition.IconSparkles, solidFontFamily));
Add(FontIconDownload, GetSolidIcon(StyleDefinition.IconDownload, solidFontFamily, tintColor)); Add(FontIconOrder, GetSolidIcon(StyleDefinition.IconOrder, solidFontFamily));
Add(FontIconFavorite, GetSolidIcon(StyleDefinition.IconFavorite, solidFontFamily, tintColor)); Add(FontIconRefresh, GetSolidIcon(StyleDefinition.IconRefresh, solidFontFamily));
Add(FontIconNotLove, GetSolidIcon(StyleDefinition.IconLove, regularFontFamily));
Add(FontIconOption, GetSolidIcon(StyleDefinition.IconOption, solidFontFamily));
Add(FontIconDownload, GetSolidIcon(StyleDefinition.IconDownload, solidFontFamily));
Add(FontIconFavorite, GetSolidIcon(StyleDefinition.IconFavorite, solidFontFamily));
} }
private FontImageSource GetSolidIcon(string icon, string family, Color color) private FontImageSource GetSolidIcon(string icon, string family, Color color = default)
{ {
return new FontImageSource return new FontImageSource
{ {

View File

@ -1,148 +1,156 @@
using Newtonsoft.Json; using System.Collections.Generic;
using Newtonsoft.Json;
using Pixiview.Illust; using Pixiview.Illust;
namespace Pixiview.Utils namespace Pixiview.Utils
{ {
public class IllustData public class IllustResponse<T>
{ {
public bool error; public bool error;
public string message; public string message;
public Body body; public T body;
}
public class Body public class Illust
{
public string illustId;
public string illustTitle;
public string id;
public string title;
public string url;
public string description;
public string[] tags;
public string userId;
public string userName;
public int width;
public int height;
public int pageCount;
public string alt;
public IllustUrls urls;
public string seriesId;
public string seriesTitle;
public string profileImageUrl;
public int xRestrict;
public class IllustUrls
{ {
public Page page; [JsonProperty("250x250")]
public Thumbnail thumbnails; public string x250;
public User[] users; [JsonProperty("360x360")]
public string x360;
[JsonProperty("540x540")]
public string x540;
}
public class Page public IllustItem ConvertToItem()
{
return new IllustItem
{ {
public int[] follow; Id = illustId,
public string[] recommend; ImageUrl = urls?.x360 ?? url,
public RecommendByTag[] recommendByTags; Title = illustTitle,
public Ranking ranking; IsRestrict = xRestrict == 1,
public RecommendUser[] recommendUser; ProfileUrl = profileImageUrl,
public EditorRecommend[] editorRecommend; UserId = userId,
public string[] newPost; UserName = userName,
Width = width,
public class RecommendByTag Height = height,
{ PageCount = pageCount
public string tag; };
public string[] ids;
}
public class Ranking
{
public RankingItem[] items;
public string date;
public class RankingItem
{
public string rank;
public string id;
}
}
public class RecommendUser
{
public int id;
public string[] illustIds;
}
public class EditorRecommend
{
public string illustId;
public string comment;
}
}
public class Thumbnail
{
public Illust[] illust;
public class Illust
{
public string illustId;
public string illustTitle;
public string id;
public string title;
public string url;
public string description;
public string[] tags;
public string userId;
public string userName;
public int width;
public int height;
public int pageCount;
public string alt;
public IllustUrls urls;
public string seriesId;
public string seriesTitle;
public string profileImageUrl;
public int xRestrict;
public class IllustUrls
{
[JsonProperty("250x250")]
public string x250;
[JsonProperty("360x360")]
public string x360;
[JsonProperty("540x540")]
public string x540;
}
public IllustItem ConvertToItem()
{
return new IllustItem
{
Id = illustId,
ImageUrl = urls.x360 ?? url,
Title = illustTitle,
IsRestrict = xRestrict == 1,
ProfileUrl = profileImageUrl,
UserId = userId,
UserName = userName,
Width = width,
Height = height,
PageCount = pageCount
};
}
}
}
public class User
{
public string userId;
public string name;
public string image;
public string imageBig;
public bool premium;
public bool isFollowed;
public string background;
public int partial;
}
} }
} }
public class IllustPageData public class IllustData : IllustResponse<IllustBody> { }
public class IllustBody
{ {
public bool error; public Page page;
public string message; public Thumbnail thumbnails;
public Body[] body; public User[] users;
public class Body public class Page
{ {
public Urls urls; public int[] follow;
public int width; public string[] recommend;
public int height; public RecommendByTag[] recommendByTags;
public Ranking ranking;
public RecommendUser[] recommendUser;
public EditorRecommend[] editorRecommend;
public string[] newPost;
public class Urls public class RecommendByTag
{ {
public string thumb_mini; public string tag;
public string small; public string[] ids;
public string regular; }
public string original;
public class Ranking
{
public RankingItem[] items;
public string date;
public class RankingItem
{
public string rank;
public string id;
}
}
public class RecommendUser
{
public int id;
public string[] illustIds;
}
public class EditorRecommend
{
public string illustId;
public string comment;
} }
} }
public class Thumbnail
{
public Illust[] illust;
}
public class User
{
public string userId;
public string name;
public string image;
public string imageBig;
public bool premium;
public bool isFollowed;
public string background;
public int partial;
}
}
public class IllustPageData : IllustResponse<IllustPageBody[]> { }
public class IllustPageBody
{
public Urls urls;
public int width;
public int height;
public class Urls
{
public string thumb_mini;
public string small;
public string regular;
public string original;
}
}
public class IllustUserListData : IllustResponse<IllustUserListBody> { }
public class IllustUserListBody
{
public Dictionary<string, object> illusts;
}
public class IllustUserData : IllustResponse<IllustUserBody> { }
public class IllustUserBody
{
public Dictionary<string, Illust> works;
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
@ -58,6 +59,13 @@ namespace Pixiview.Utils
{ {
favoriteObject = favorites; favoriteObject = favorites;
} }
else
{
favoriteObject = new IllustFavorite
{
Illusts = new List<IllustItem>()
};
}
} }
return favoriteObject; return favoriteObject;
} }
@ -89,7 +97,7 @@ namespace Pixiview.Utils
private static T LoadObject<T>(string file, string url, string referer = null, bool force = false) private static T LoadObject<T>(string file, string url, string referer = null, bool force = false)
{ {
string content = null; string content = null;
if (!force && File.Exists(file)) if (!force && file != null && File.Exists(file))
{ {
try try
{ {
@ -117,18 +125,21 @@ namespace Pixiview.Utils
using (response) using (response)
{ {
content = response.Content.ReadAsStringAsync().Result; content = response.Content.ReadAsStringAsync().Result;
try if (file != null)
{ {
var folder = Path.GetDirectoryName(file); try
if (!Directory.Exists(folder))
{ {
Directory.CreateDirectory(folder); var folder = Path.GetDirectoryName(file);
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
File.WriteAllText(file, content, Encoding.UTF8);
}
catch (Exception ex)
{
App.DebugError("save", $"failed to save illust JSON object, error: {ex.Message}");
} }
File.WriteAllText(file, content, Encoding.UTF8);
}
catch (Exception ex)
{
App.DebugError("save", $"failed to save illust JSON object, error: {ex.Message}");
} }
} }
} }
@ -222,14 +233,32 @@ namespace Pixiview.Utils
return result; return result;
} }
public static IllustUserData LoadIllustUserData(string userId, bool force = false)
{
var list = LoadObject<IllustUserListData>(
null,
string.Format(Configs.UrlIllustUserAll, userId),
string.Format(Configs.UrlIllustUser, userId),
force: force);
var ids = string.Join("&ids%5B%5D=", list.body.illusts.Keys.Take(20));
var result = LoadObject<IllustUserData>(
null,
string.Format(Configs.UrlIllustUserArtworks, userId, ids, 1),
string.Format(Configs.UrlIllustUser, userId),
force: force);
return result;
}
public static ImageSource LoadIllustImage(string url) public static ImageSource LoadIllustImage(string url)
{ {
return LoadImage(url, PersonalFolder, imageFolder); return LoadImage(url, PersonalFolder, imageFolder);
} }
public static ImageSource LoadPreviewImage(string url) public static ImageSource LoadPreviewImage(string url, bool downloading = true)
{ {
return LoadImage(url, PersonalFolder, previewFolder); return LoadImage(url, PersonalFolder, previewFolder, downloading);
} }
public static ImageSource LoadThumbnailImage(string url) public static ImageSource LoadThumbnailImage(string url)
@ -258,7 +287,7 @@ namespace Pixiview.Utils
return null; return null;
} }
private static ImageSource LoadImage(string url, string working, string folder) private static ImageSource LoadImage(string url, string working, string folder, bool downloading = true)
{ {
var file = Path.Combine(working, folder, Path.GetFileName(url)); var file = Path.Combine(working, folder, Path.GetFileName(url));
ImageSource image; ImageSource image;
@ -278,7 +307,7 @@ namespace Pixiview.Utils
{ {
image = null; image = null;
} }
if (image == null) if (downloading && image == null)
{ {
file = DownloadImage(url, working, folder); file = DownloadImage(url, working, folder);
if (file != null) if (file != null)
@ -386,6 +415,9 @@ namespace Pixiview.Utils
public const int MaxThreads = 3; public const int MaxThreads = 3;
public const string UrlIllustList = "https://www.pixiv.net/ajax/top/illust?mode=all&lang=zh"; public const string UrlIllustList = "https://www.pixiv.net/ajax/top/illust?mode=all&lang=zh";
public const string UrlIllust = "https://www.pixiv.net/artworks/{0}"; public const string UrlIllust = "https://www.pixiv.net/artworks/{0}";
public const string UrlIllustUserAll = "https://www.pixiv.net/ajax/user/{0}/profile/all?lang=zh";
public const string UrlIllustUserArtworks = "https://www.pixiv.net/ajax/user/{0}/profile/illusts?ids%5B%5D={1}&work_category=illustManga&is_first_page={2}&lang=zh";
public const string UrlIllustUser = "https://www.pixiv.net/users/{0}/artworks";
public const string UrlIllustPage = "https://www.pixiv.net/ajax/illust/{0}/pages?lang=zh"; public const string UrlIllustPage = "https://www.pixiv.net/ajax/illust/{0}/pages?lang=zh";
public const string UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"; public const string UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36";
public const string AcceptImage = "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5"; public const string AcceptImage = "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5";