From 66f0c1ba1b3a31a325d18e7f7a4362b7a9f93d40 Mon Sep 17 00:00:00 2001 From: Tsanie Lily <tsorgy@gmail.com> Date: Tue, 5 May 2020 01:53:33 +0800 Subject: [PATCH] * Pixiview/UI/CircleUIs.cs: * Pixiview.iOS/Pixiview.iOS.csproj: * Pixiview.iOS/Renderers/RoundLabelRenderer.cs: * Pixiview.iOS/Renderers/CircleImageRenderer.cs: custom round corner controls * Pixiview/App.xaml: * Pixiview/Utils/Converters.cs: * Pixiview/GlobalSuppressions.cs: * Pixiview/UI/StyleDefinition.cs: * Pixiview/UI/AdaptedPage.cs: * Pixiview.iOS/Renderers/AdaptedPageRenderer.cs: observe orientation * Pixiview/MainPage.xaml: * Pixiview/Utils/Stores.cs: * Pixiview/MainPage.xaml.cs: * Pixiview/Utils/IllustData.cs: data and UI adjust --- Pixiview.iOS/Pixiview.iOS.csproj | 2 + Pixiview.iOS/Renderers/AdaptedPageRenderer.cs | 36 ++++ Pixiview.iOS/Renderers/CircleImageRenderer.cs | 31 ++++ Pixiview.iOS/Renderers/RoundLabelRenderer.cs | 47 ++++++ Pixiview/App.xaml | 1 + Pixiview/GlobalSuppressions.cs | 1 + Pixiview/MainPage.xaml | 59 ++++++- Pixiview/MainPage.xaml.cs | 154 +++++++++++++++++- Pixiview/UI/AdaptedPage.cs | 46 +++++- Pixiview/UI/CircleUIs.cs | 25 +++ Pixiview/UI/StyleDefinition.cs | 79 ++++++++- Pixiview/Utils/Converters.cs | 20 +++ Pixiview/Utils/IllustData.cs | 2 + Pixiview/Utils/Stores.cs | 63 +++++-- 14 files changed, 536 insertions(+), 30 deletions(-) create mode 100644 Pixiview.iOS/Renderers/CircleImageRenderer.cs create mode 100644 Pixiview.iOS/Renderers/RoundLabelRenderer.cs create mode 100644 Pixiview/UI/CircleUIs.cs create mode 100644 Pixiview/Utils/Converters.cs diff --git a/Pixiview.iOS/Pixiview.iOS.csproj b/Pixiview.iOS/Pixiview.iOS.csproj index a297a95..a188d5a 100644 --- a/Pixiview.iOS/Pixiview.iOS.csproj +++ b/Pixiview.iOS/Pixiview.iOS.csproj @@ -70,6 +70,8 @@ <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Renderers\AdaptedPageRenderer.cs" /> <Compile Include="Services\EnvironmentService.cs" /> + <Compile Include="Renderers\CircleImageRenderer.cs" /> + <Compile Include="Renderers\RoundLabelRenderer.cs" /> </ItemGroup> <ItemGroup> <InterfaceDefinition Include="Resources\LaunchScreen.storyboard" /> diff --git a/Pixiview.iOS/Renderers/AdaptedPageRenderer.cs b/Pixiview.iOS/Renderers/AdaptedPageRenderer.cs index 248e127..c06fbd2 100644 --- a/Pixiview.iOS/Renderers/AdaptedPageRenderer.cs +++ b/Pixiview.iOS/Renderers/AdaptedPageRenderer.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using Foundation; using Pixiview.iOS.Renderers; using Pixiview.UI; using Pixiview.Utils; @@ -11,6 +12,9 @@ namespace Pixiview.iOS.Renderers { public class AdaptedPageRenderer : PageRenderer { + UIDeviceOrientation lastOrientation; + NSObject observer; + public override void ViewDidLoad() { base.ViewDidLoad(); @@ -30,6 +34,20 @@ namespace Pixiview.iOS.Renderers { SetStatusBarStyle(style); } + + observer = UIDevice.Notifications.ObserveOrientationDidChange(ChangeOrientation); + ChangeOrientation(null, null); + } + + public override void ViewWillDisappear(bool animated) + { + if (observer != null) + { + observer.Dispose(); + observer = null; + } + + base.ViewWillDisappear(animated); } private void SetStatusBarStyle(UIStatusBarStyle style) @@ -64,5 +82,23 @@ namespace Pixiview.iOS.Renderers return UIStatusBarStyle.Default; } } + + void ChangeOrientation(object sender, NSNotificationEventArgs e) + { + var current = UIDevice.CurrentDevice.Orientation; + if (current == UIDeviceOrientation.FaceUp || current == UIDeviceOrientation.FaceDown) + { + //current = UIDeviceOrientation.Portrait; + return; + } + if (lastOrientation != current) + { + lastOrientation = current; + if (Element is AdaptedPage page) + { + page.OnOrientationChanged((Orientation)lastOrientation); + } + } + } } } diff --git a/Pixiview.iOS/Renderers/CircleImageRenderer.cs b/Pixiview.iOS/Renderers/CircleImageRenderer.cs new file mode 100644 index 0000000..85f77a2 --- /dev/null +++ b/Pixiview.iOS/Renderers/CircleImageRenderer.cs @@ -0,0 +1,31 @@ +using Pixiview.iOS.Renderers; +using Pixiview.UI; +using Xamarin.Forms; +using Xamarin.Forms.Platform.iOS; + +[assembly: ExportRenderer(typeof(CircleImage), typeof(CircleImageRenderer))] +namespace Pixiview.iOS.Renderers +{ + public class CircleImageRenderer : ImageRenderer + { + protected override void OnElementChanged(ElementChangedEventArgs<Image> e) + { + base.OnElementChanged(e); + + if (Control != null) + { + Control.Layer.MasksToBounds = true; + } + } + + public override void LayoutSubviews() + { + base.LayoutSubviews(); + + if (Control != null) + { + Control.Layer.CornerRadius = Control.Frame.Size.Width / 2; + } + } + } +} diff --git a/Pixiview.iOS/Renderers/RoundLabelRenderer.cs b/Pixiview.iOS/Renderers/RoundLabelRenderer.cs new file mode 100644 index 0000000..27f5fae --- /dev/null +++ b/Pixiview.iOS/Renderers/RoundLabelRenderer.cs @@ -0,0 +1,47 @@ +using System.ComponentModel; +using Pixiview.iOS.Renderers; +using Pixiview.UI; +using Xamarin.Forms; +using Xamarin.Forms.Platform.iOS; + +[assembly: ExportRenderer(typeof(RoundLabel), typeof(RoundLabelRenderer))] +namespace Pixiview.iOS.Renderers +{ + public class RoundLabelRenderer : LabelRenderer + { + protected override void OnElementChanged(ElementChangedEventArgs<Label> e) + { + base.OnElementChanged(e); + + if (Control != null && Element is RoundLabel label) + { + int radius = label.CornerRadius; + if (radius > 0) + { + Control.Layer.CornerRadius = radius; + Control.BackgroundColor = label.BackgroundColor.ToUIColor(); + Control.Layer.MasksToBounds = true; + } + } + } + + protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) + { + base.OnElementPropertyChanged(sender, e); + + if (e.PropertyName == RoundLabel.CornerRadiusProperty.PropertyName) + { + if (Control != null && Element is RoundLabel label) + { + int radius = label.CornerRadius; + if (radius > 0) + { + Control.Layer.CornerRadius = radius; + Control.BackgroundColor = label.BackgroundColor.ToUIColor(); + Control.Layer.MasksToBounds = true; + } + } + } + } + } +} diff --git a/Pixiview/App.xaml b/Pixiview/App.xaml index cd3f8d4..0a8bdae 100644 --- a/Pixiview/App.xaml +++ b/Pixiview/App.xaml @@ -8,6 +8,7 @@ <Application.Resources> <Color x:Key="WindowColor">Black</Color> <Color x:Key="TextColor">White</Color> + <Color x:Key="SubTextColor">LightGray</Color> <Color x:Key="MainColor">#333333</Color> <Color x:Key="MainTextColor">White</Color> <Style x:Key="TitleLabel" TargetType="Label"> diff --git a/Pixiview/GlobalSuppressions.cs b/Pixiview/GlobalSuppressions.cs index 6b30c4a..f5c46f7 100644 --- a/Pixiview/GlobalSuppressions.cs +++ b/Pixiview/GlobalSuppressions.cs @@ -6,3 +6,4 @@ using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Style", "IDE0063:Use simple 'using' statement", Justification = "<Pending>")] +[assembly: SuppressMessage("Style", "IDE0066:Convert switch statement to expression", Justification = "<Pending>")] diff --git a/Pixiview/MainPage.xaml b/Pixiview/MainPage.xaml index 7802739..16edc0a 100644 --- a/Pixiview/MainPage.xaml +++ b/Pixiview/MainPage.xaml @@ -5,14 +5,63 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:u="clr-namespace:Pixiview.UI" mc:Ignorable="d" - x:Class="Pixiview.MainPage"> + x:Class="Pixiview.MainPage" + BackgroundColor="{DynamicResource WindowColor}" + OrientationChanged="Page_OrientationChanged"> <NavigationPage.TitleView> - <u:NavigationTitle Title="Startup Name Generator" + <u:NavigationTitle Title="Follow" IsLeftButtonVisible="True" LeftButtonClicked="NavigationTitle_LeftButtonClicked" RightButtonClicked="NavigationTitle_RightButtonClicked"/> </NavigationPage.TitleView> - <Grid> - - </Grid> + <ScrollView HorizontalOptions="Fill" Padding="{Binding StatusBarPadding}"> + <u:FlowLayout ItemsSource="{Binding Illusts}" + HorizontalOptions="Fill" Column="{Binding Columns}" + Margin="16" RowSpacing="16" ColumnSpacing="16"> + <u:FlowLayout.ItemTemplate> + <DataTemplate> + <Frame HasShadow="False" Padding="0" Margin="0" CornerRadius="10" + BackgroundColor="{DynamicResource MainColor}"> + <Grid HorizontalOptions="Fill" Margin="0, -5, 0, 0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="Auto"/> + <RowDefinition Height="Auto"/> + </Grid.RowDefinitions> + <Image BackgroundColor="LightGray" + Source="{Binding Image}" + HorizontalOptions="Fill" + Aspect="AspectFit"/> + <u:RoundLabel Text="R-18" BackgroundColor="#fd4363" Margin="6, 11, 0, 0" + Padding="6, 2" CornerRadius="4" + HorizontalOptions="Start" VerticalOptions="Start" + FontSize="Micro" TextColor="White" + IsVisible="{Binding IsRestrict}"/> + <u:RoundLabel Text="{Binding PageCountText}" + FontFamily="{DynamicResource IconSolidFontFamily}" + BackgroundColor="#50000000" Margin="0, 11, 6, 0" + Padding="6, 4" CornerRadius="6" + HorizontalOptions="End" VerticalOptions="Start" + FontSize="Micro" TextColor="White" + IsVisible="{Binding IsPageVisible}"/> + <Label Grid.Row="1" Text="{Binding Title}" + Padding="8, 2" + TextColor="{DynamicResource TextColor}" + LineBreakMode="TailTruncation" + FontSize="Small"/> + <StackLayout Grid.Row="2" Orientation="Horizontal" Padding="8, 0, 8, 8"> + <u:CircleImage WidthRequest="30" HeightRequest="30" Aspect="AspectFill" + Source="{Binding ProfileImage}"/> + <Label Text="{Binding UserName}" + VerticalOptions="Center" + TextColor="{DynamicResource SubTextColor}" + LineBreakMode="TailTruncation" + FontSize="Micro"/> + </StackLayout> + </Grid> + </Frame> + </DataTemplate> + </u:FlowLayout.ItemTemplate> + </u:FlowLayout> + </ScrollView> </u:AdaptedPage> \ No newline at end of file diff --git a/Pixiview/MainPage.xaml.cs b/Pixiview/MainPage.xaml.cs index 54c18ed..45f6f59 100644 --- a/Pixiview/MainPage.xaml.cs +++ b/Pixiview/MainPage.xaml.cs @@ -1,8 +1,12 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; +using System.Linq; using System.Threading.Tasks; using Pixiview.UI; using Pixiview.Utils; +using Xamarin.Forms; namespace Pixiview { @@ -11,24 +15,115 @@ namespace Pixiview [DesignTimeVisible(false)] public partial class MainPage : AdaptedPage { + public static readonly BindableProperty IllustsProperty = BindableProperty.Create( + nameof(Illusts), typeof(IllustCollection), typeof(MainPage)); + public static readonly BindableProperty ColumnsProperty = BindableProperty.Create( + nameof(Columns), typeof(int), typeof(MainPage), 2); + + public IllustCollection Illusts + { + get => (IllustCollection)GetValue(IllustsProperty); + set => SetValue(IllustsProperty, value); + } + public int Columns + { + get => (int)GetValue(ColumnsProperty); + set => SetValue(ColumnsProperty, value); + } + + private readonly ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Configs.MaxThreads }; + private IllustData illustData; public MainPage() { InitializeComponent(); + BindingContext = this; } public override void OnLoad() { App.DebugPrint($"folder: {Stores.PersonalFolder}"); - Task.Run(async () => + Task.Run(DoLoadIllusts); + } + + async void DoLoadIllusts() + { + illustData = await Stores.LoadIllustData(); + + var data = illustData.body.page.follow.Select(i => { - illustData = await Stores.LoadIllustData(); - App.DebugPrint(illustData.message); + var illust = illustData.body.thumbnails.illust.FirstOrDefault(l => l.illustId == i.ToString()); + if (illust == null) + { + return null; + } + return new IllustItem + { + ImageUrl = illust.urls.x360 ?? illust.url, + Title = illust.illustTitle, + IsRestrict = illust.xRestrict == 1, + ProfileUrl = illust.profileImageUrl, + UserName = illust.userName, + Width = illust.width, + Height = illust.height, + PageCount = illust.pageCount + }; + }).Where(i => i != null); + + var collection = new IllustCollection(data); + Illusts = collection; + + DoLoadImages(collection); + } + + void DoLoadImages(IllustCollection collection) + { + Parallel.ForEach(collection, parallelOptions, illust => + { + if (!collection.Running) + { + return; + } + if (illust.ImageUrl != null) + { + var url = Configs.GetThumbnailUrl(illust.ImageUrl); + var image = Stores.LoadThumbnailImage(url); + if (image != null) + { + illust.Image = image; + } + } + + if (illust.ProfileUrl != null) + { + var userImage = Stores.LoadUserProfileImage(illust.ProfileUrl); + if (userImage != null) + { + illust.ProfileImage = userImage; + } + } }); } + void Page_OrientationChanged(object sender, OrientationEventArgs e) + { + switch (e.CurrentOrientation) + { + case Orientation.Portrait: + Columns = 2; + break; + case Orientation.Unknown: + case Orientation.PortraitUpsideDown: + case Orientation.LandscapeLeft: + case Orientation.LandscapeRight: + default: + Columns = 4; + break; + } + } + void NavigationTitle_RightButtonClicked(object sender, EventArgs e) { } @@ -38,4 +133,57 @@ namespace Pixiview DisplayAlert("title", "message", "Ok"); } } + + public class IllustCollection : ObservableCollection<IllustItem> + { + private static readonly object sync = new object(); + + public IllustCollection(IEnumerable<IllustItem> illusts) : base(illusts) + { + running = true; + } + + private bool running; + public bool Running + { + get => running; + set + { + lock (sync) + { + running = value; + } + } + } + } + + public class IllustItem : BindableObject + { + public static readonly BindableProperty ImageProperty = BindableProperty.Create( + nameof(Image), typeof(ImageSource), typeof(IllustItem)); + public static readonly BindableProperty ProfileImageProperty = BindableProperty.Create( + nameof(ProfileImage), typeof(ImageSource), typeof(IllustItem)); + + public ImageSource Image + { + get => (ImageSource)GetValue(ImageProperty); + set => SetValue(ImageProperty, value); + } + public ImageSource ProfileImage + { + get => (ImageSource)GetValue(ProfileImageProperty); + set => SetValue(ProfileImageProperty, value); + } + + public string ImageUrl { get; set; } + public string Title { get; set; } + public bool IsRestrict { get; set; } + public string ProfileUrl { get; set; } + public string UserName { get; set; } + public int Width { get; set; } + public int Height { get; set; } + public int PageCount { get; set; } + public string PageCountText => $"{StyleDefinition.IconLayer} {PageCount}"; + public bool IsPageVisible => PageCount > 1; + } } diff --git a/Pixiview/UI/AdaptedPage.cs b/Pixiview/UI/AdaptedPage.cs index 1fc6131..f2b6223 100644 --- a/Pixiview/UI/AdaptedPage.cs +++ b/Pixiview/UI/AdaptedPage.cs @@ -5,16 +5,56 @@ namespace Pixiview.UI { public class AdaptedPage : ContentPage { - public event EventHandler Load; + static readonly Thickness LandscapeLeftPadding = new Thickness(34, 0, 0, 0); + static readonly Thickness LandscapeRightPadding = new Thickness(0, 0, 34, 0); - public AdaptedPage() + public static readonly BindableProperty StatusBarPaddingProperty = BindableProperty.Create( + nameof(StatusBarPadding), typeof(Thickness), typeof(AdaptedPage), default(Thickness)); + + public Thickness StatusBarPadding { - SetDynamicResource(BackgroundColorProperty, App.WindowColor); + get => (Thickness)GetValue(StatusBarPaddingProperty); + set => SetValue(StatusBarPaddingProperty, value); } + public event EventHandler Load; + public event EventHandler<OrientationEventArgs> OrientationChanged; + public virtual void OnLoad() { Load?.Invoke(this, EventArgs.Empty); } + + public virtual void OnOrientationChanged(Orientation orientation) + { + if (orientation == Orientation.LandscapeLeft || orientation == Orientation.PortraitUpsideDown) + { + StatusBarPadding = StyleDefinition.IsFullscreenDevice ? LandscapeLeftPadding : default; + } + else if (orientation == Orientation.LandscapeRight) + { + StatusBarPadding = StyleDefinition.IsFullscreenDevice ? LandscapeRightPadding : default; + } + else + { + StatusBarPadding = default; + } + + OrientationChanged?.Invoke(this, new OrientationEventArgs { CurrentOrientation = orientation }); + } + } + + public class OrientationEventArgs : EventArgs + { + public Orientation CurrentOrientation { get; set; } + } + + public enum Orientation + { + Unknown, + Portrait, + PortraitUpsideDown, + LandscapeLeft, + LandscapeRight } } diff --git a/Pixiview/UI/CircleUIs.cs b/Pixiview/UI/CircleUIs.cs new file mode 100644 index 0000000..1906dfc --- /dev/null +++ b/Pixiview/UI/CircleUIs.cs @@ -0,0 +1,25 @@ +using Xamarin.Forms; + +namespace Pixiview.UI +{ + public class CircleImage : Image { } + + public class RoundLabel : Label + { + public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create( + nameof(CornerRadius), typeof(int), typeof(RoundLabel)); + public static new readonly BindableProperty BackgroundColorProperty = BindableProperty.Create( + nameof(BackgroundColor), typeof(Color), typeof(RoundLabel), Color.Transparent); + + public int CornerRadius + { + get => (int)GetValue(CornerRadiusProperty); + set => SetValue(CornerRadiusProperty, value); + } + public new Color BackgroundColor + { + get => (Color)GetValue(BackgroundColorProperty); + set => SetValue(BackgroundColorProperty, value); + } + } +} diff --git a/Pixiview/UI/StyleDefinition.cs b/Pixiview/UI/StyleDefinition.cs index 744af93..bbd2b29 100644 --- a/Pixiview/UI/StyleDefinition.cs +++ b/Pixiview/UI/StyleDefinition.cs @@ -1,13 +1,86 @@ -using Xamarin.Forms; +using System; +using Xamarin.Essentials; +using Xamarin.Forms; namespace Pixiview.UI { public static class StyleDefinition { - public static readonly double FontSizeTitle = 18.0; - public static readonly double FontSizeTitleIcon = 24.0; + public const double FontSizeTitle = 18.0; + public const double FontSizeTitleIcon = 24.0; public static readonly Thickness HorizonLeft10 = new Thickness(10, 0, 0, 0); public static readonly Thickness HorizonRight10 = new Thickness(0, 0, 10, 0); + public static readonly Thickness LeftBottom10 = new Thickness(10, 0, 0, 10); + + public const string IconLayer = "\uf302"; + + private static bool? _isFullscreenDevice; + public static bool IsFullscreenDevice + { + get + { + if (_isFullscreenDevice != null) + { + return _isFullscreenDevice.Value; + } + if (Device.RuntimePlatform == Device.iOS) + { + try + { + var model = DeviceInfo.Model; + if (model == "iPhone10,3") + { + // iPhone X + _isFullscreenDevice = true; + } + else if (model.StartsWith("iPhone")) + { + var vs = model.Substring(6).Split(','); + if (vs.Length == 2 && int.TryParse(vs[0], out int main) && int.TryParse(vs[1], out int sub)) + { + // iPhone X/XS/XR or iPhone 11 + _isFullscreenDevice = (main == 10 && sub >= 6) || (main > 10); + } + else + { + _isFullscreenDevice = false; + } + } + else if (model.StartsWith("iPad8,")) + { + // iPad 11-inch or 12.9-inch (3rd+) + _isFullscreenDevice = true; + } +#if DEBUG + else + { + // iPad or Simulator + var name = DeviceInfo.Name; + _isFullscreenDevice = name.StartsWith("iPhone X") + || name.StartsWith("iPhone 11") + || name.StartsWith("iPad Pro (11-inch)") + || name.StartsWith("iPad Pro (12.9-inch) (3rd generation)") + || name.StartsWith("iPad Pro (12.9-inch) (4th generation)"); + } +#endif + } + catch (Exception ex) + { + App.DebugError("device.get", $"failed to get the device model. {ex.Message}"); + } + } + else + { + // TODO: + _isFullscreenDevice = false; + } + if (_isFullscreenDevice == null) + { + _isFullscreenDevice = false; + } + return _isFullscreenDevice.Value; + } + } } } diff --git a/Pixiview/Utils/Converters.cs b/Pixiview/Utils/Converters.cs new file mode 100644 index 0000000..1dbaeda --- /dev/null +++ b/Pixiview/Utils/Converters.cs @@ -0,0 +1,20 @@ +using System; +using System.Globalization; +using Pixiview.UI; +using Xamarin.Forms; + +namespace Pixiview.Utils +{ + public class PageConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return StyleDefinition.IconLayer + value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Pixiview/Utils/IllustData.cs b/Pixiview/Utils/IllustData.cs index 60ddaef..dbfab17 100644 --- a/Pixiview/Utils/IllustData.cs +++ b/Pixiview/Utils/IllustData.cs @@ -72,11 +72,13 @@ namespace Pixiview.Utils 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 { diff --git a/Pixiview/Utils/Stores.cs b/Pixiview/Utils/Stores.cs index 74d04d4..ca127f3 100644 --- a/Pixiview/Utils/Stores.cs +++ b/Pixiview/Utils/Stores.cs @@ -6,6 +6,7 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; +using Xamarin.Forms; namespace Pixiview.Utils { @@ -14,6 +15,7 @@ namespace Pixiview.Utils public static readonly string PersonalFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); //public static readonly string CacheFolder = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache); private const string imageFolder = "img-master"; + private const string thumbFolder = "img-thumb"; private const string userFolder = "user-profile"; private const string illustFile = "illust.json"; @@ -67,35 +69,46 @@ namespace Pixiview.Utils } } - public static string LoadIllustImage(string url) + public static ImageSource LoadIllustImage(string url) { return LoadImage(url, imageFolder); } - public static string LoadUserProfileImage(string url) + public static ImageSource LoadThumbnailImage(string url) + { + return LoadImage(url, thumbFolder); + } + + public static ImageSource LoadUserProfileImage(string url) { return LoadImage(url, userFolder); } - public static string LoadImage(string url, string folder) + public static ImageSource LoadImage(string url, string folder) { - var file = Path.Combine(PersonalFolder, imageFolder, Path.GetFileName(url)); - if (File.Exists(file)) + var file = Path.Combine(PersonalFolder, folder, Path.GetFileName(url)); + if (!File.Exists(file)) { - return file; + file = DownloadImage(url, folder); } - else + if (file != null) { - file = DownloadImage(url, folder).Result; - return file; + return ImageSource.FromFile(file); } + return null; } - public static async Task<string> DownloadImage(string url, string folder) + public static string DownloadImage(string url, string folder) { try { - var file = Path.Combine(PersonalFolder, folder, Path.GetFileName(url)); + var directory = Path.Combine(PersonalFolder, folder); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + var file = Path.Combine(directory, Path.GetFileName(url)); + App.DebugPrint($"download, url: {url}"); var response = Download(url); if (response == null) { @@ -104,11 +117,11 @@ namespace Pixiview.Utils using (response) using (var fs = File.OpenWrite(file)) { - await response.Content.CopyToAsync(fs); - if (response.Headers.Date != null) - { - File.SetLastWriteTimeUtc(file, response.Headers.Date.Value.UtcDateTime); - } + response.Content.CopyToAsync(fs).Wait(); + //if (response.Headers.Date != null) + //{ + // File.SetLastWriteTimeUtc(file, response.Headers.Date.Value.UtcDateTime); + //} } return file; } @@ -156,6 +169,7 @@ namespace Pixiview.Utils }) { request.Headers.Referrer = referer == null ? Configs.Referer : new Uri(referer); + request.Headers.Add("user-agent", Configs.UserAgent); if (headers != null) { foreach (var (header, value) in headers) @@ -173,6 +187,8 @@ namespace Pixiview.Utils public static readonly WebProxy Proxy = new WebProxy("10.0.10.100", 8088); public static readonly Uri Referer = new Uri("https://www.pixiv.net/"); + public const int MaxThreads = 3; + 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.129 Safari/537.36"; public const string UrlIllust = "https://www.pixiv.net/ajax/top/illust?mode=all&lang=zh"; public const string Cookie = "first_visit_datetime_pc=2019-10-29+22%3A05%3A30; p_ab_id=2; p_ab_id_2=6;" + " p_ab_d_id=1155161977; a_type=0; b_type=1; d_type=2; module_orders_mypage=%5B%7B%22name%22%3A%22s" + @@ -188,5 +204,20 @@ namespace Pixiview.Utils "SID=2603358_VHyGPeRaz7LpeoFkRsHvjXIpApCMb56a; __cfduid=d9fa2d4d1ddd30db85ebb519f9855d256158780674" + "7; privacy_policy_agreement=2"; public const string UserId = "2603358"; + + public static string GetThumbnailUrl(string url) + { + url = url.Replace("/custom-thumb/", "/img-master/"); + var index = url.LastIndexOf("_square1200.jpg"); + if (index < 0) + { + index = url.LastIndexOf("_custom1200.jpg"); + } + if (index >= 0) + { + return url.Substring(0, index) + "_master1200.jpg"; + } + return url; + } } }