feature: login support for Android
feature: display profile information
This commit is contained in:
@ -80,6 +80,7 @@
|
|||||||
<Compile Include="SplashActivity.cs" />
|
<Compile Include="SplashActivity.cs" />
|
||||||
<Compile Include="Renderers\RoundImageRenderer.cs" />
|
<Compile Include="Renderers\RoundImageRenderer.cs" />
|
||||||
<Compile Include="Renderers\AdaptedPageRenderer.cs" />
|
<Compile Include="Renderers\AdaptedPageRenderer.cs" />
|
||||||
|
<Compile Include="Renderers\HybridWebViewRenderer.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Resources\AboutResources.txt" />
|
<None Include="Resources\AboutResources.txt" />
|
||||||
@ -95,10 +96,6 @@
|
|||||||
<SubType></SubType>
|
<SubType></SubType>
|
||||||
<Generator></Generator>
|
<Generator></Generator>
|
||||||
</AndroidResource>
|
</AndroidResource>
|
||||||
<AndroidResource Include="Resources\drawable\userprofile.jpg">
|
|
||||||
<SubType></SubType>
|
|
||||||
<Generator></Generator>
|
|
||||||
</AndroidResource>
|
|
||||||
<AndroidResource Include="Resources\mipmap-xxxhdpi\icon_foreground.png">
|
<AndroidResource Include="Resources\mipmap-xxxhdpi\icon_foreground.png">
|
||||||
<SubType></SubType>
|
<SubType></SubType>
|
||||||
<Generator></Generator>
|
<Generator></Generator>
|
||||||
@ -207,6 +204,10 @@
|
|||||||
<SubType></SubType>
|
<SubType></SubType>
|
||||||
<Generator></Generator>
|
<Generator></Generator>
|
||||||
</AndroidResource>
|
</AndroidResource>
|
||||||
|
<AndroidResource Include="Resources\drawable\no_profile.png">
|
||||||
|
<SubType></SubType>
|
||||||
|
<Generator></Generator>
|
||||||
|
</AndroidResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Resources\drawable\" />
|
<Folder Include="Resources\drawable\" />
|
||||||
|
117
Pixiview.Android/Renderers/HybridWebViewRenderer.cs
Normal file
117
Pixiview.Android/Renderers/HybridWebViewRenderer.cs
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
using Android.Content;
|
||||||
|
using Android.Webkit;
|
||||||
|
using Pixiview.Droid.Renderers;
|
||||||
|
using Pixiview.Login;
|
||||||
|
using Pixiview.Utils;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
using Xamarin.Forms.Platform.Android;
|
||||||
|
|
||||||
|
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
|
||||||
|
namespace Pixiview.Droid.Renderers
|
||||||
|
{
|
||||||
|
public class HybridWebViewRenderer : WebViewRenderer
|
||||||
|
{
|
||||||
|
public HybridWebViewRenderer(Context context) : base(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
|
||||||
|
{
|
||||||
|
base.OnElementChanged(e);
|
||||||
|
|
||||||
|
if (e.NewElement is HybridWebView webView)
|
||||||
|
{
|
||||||
|
Control.SetWebViewClient(new PixivWebViewClient(this));
|
||||||
|
Control.LoadUrl(webView.Uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PixivWebViewClient : FormsWebViewClient
|
||||||
|
{
|
||||||
|
private readonly HybridWebView webView;
|
||||||
|
|
||||||
|
public PixivWebViewClient(HybridWebViewRenderer renderer) : base(renderer)
|
||||||
|
{
|
||||||
|
if (renderer.Element is HybridWebView view)
|
||||||
|
{
|
||||||
|
webView = view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
|
||||||
|
//{
|
||||||
|
// var uri = request.Url;
|
||||||
|
// if (uri.Host == "www.pixiv.net" && uri.Path == "/")
|
||||||
|
// {
|
||||||
|
// var client = new HttpClient(new HttpClientHandler { UseCookies = false })
|
||||||
|
// {
|
||||||
|
// BaseAddress = new Uri($"{uri.Scheme}://{uri.Host}"),
|
||||||
|
// Timeout = TimeSpan.FromSeconds(30)
|
||||||
|
// };
|
||||||
|
// var pathAndQuery = uri.Path;
|
||||||
|
// if (!string.IsNullOrEmpty(uri.Query))
|
||||||
|
// {
|
||||||
|
// pathAndQuery += "?" + uri.EncodedQuery;
|
||||||
|
// }
|
||||||
|
// using (var req = new HttpRequestMessage(
|
||||||
|
// request.Method == "POST" ? HttpMethod.Post : HttpMethod.Get,
|
||||||
|
// pathAndQuery))
|
||||||
|
// {
|
||||||
|
// var headers = req.Headers;
|
||||||
|
// if (request.RequestHeaders != null)
|
||||||
|
// {
|
||||||
|
// foreach (var h in request.RequestHeaders)
|
||||||
|
// {
|
||||||
|
// headers.Add(h.Key, h.Value);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// using (var response = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead).Result)
|
||||||
|
// {
|
||||||
|
// if (response.Headers.TryGetValues("x-userid", out var vals))
|
||||||
|
// {
|
||||||
|
// Configs.SetUserId(string.Join(';', vals), true);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// return base.ShouldOverrideUrlLoading(view, request);
|
||||||
|
//}
|
||||||
|
|
||||||
|
public override void OnPageFinished(Android.Webkit.WebView view, string url)
|
||||||
|
{
|
||||||
|
base.OnPageFinished(view, url);
|
||||||
|
|
||||||
|
if (url == "https://www.pixiv.net/" ||
|
||||||
|
url == "https://www.pixiv.net/en/")
|
||||||
|
{
|
||||||
|
var cookieManager = CookieManager.Instance;
|
||||||
|
var cookie = cookieManager.GetCookie(url);
|
||||||
|
Configs.SetCookie(cookie, true);
|
||||||
|
|
||||||
|
// user-id
|
||||||
|
if (cookie != null)
|
||||||
|
{
|
||||||
|
var index = cookie.IndexOf("PHPSESSID=");
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
var session = cookie.Substring(index + 10);
|
||||||
|
index = session.IndexOf('_');
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
session = session.Substring(0, index);
|
||||||
|
Configs.SetUserId(session, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (webView != null)
|
||||||
|
{
|
||||||
|
webView.OnLoginHandle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
Pixiview.Android/Resources/Resource.designer.cs
generated
44
Pixiview.Android/Resources/Resource.designer.cs
generated
@ -8337,65 +8337,65 @@ namespace Pixiview.Droid
|
|||||||
// aapt resource value: 0x7F070069
|
// aapt resource value: 0x7F070069
|
||||||
public const int navigation_empty_icon = 2131165289;
|
public const int navigation_empty_icon = 2131165289;
|
||||||
|
|
||||||
// aapt resource value: 0x7F07006A
|
|
||||||
public const int notification_action_background = 2131165290;
|
|
||||||
|
|
||||||
// aapt resource value: 0x7F07006B
|
// aapt resource value: 0x7F07006B
|
||||||
public const int notification_bg = 2131165291;
|
public const int notification_action_background = 2131165291;
|
||||||
|
|
||||||
// aapt resource value: 0x7F07006C
|
// aapt resource value: 0x7F07006C
|
||||||
public const int notification_bg_low = 2131165292;
|
public const int notification_bg = 2131165292;
|
||||||
|
|
||||||
// aapt resource value: 0x7F07006D
|
// aapt resource value: 0x7F07006D
|
||||||
public const int notification_bg_low_normal = 2131165293;
|
public const int notification_bg_low = 2131165293;
|
||||||
|
|
||||||
// aapt resource value: 0x7F07006E
|
// aapt resource value: 0x7F07006E
|
||||||
public const int notification_bg_low_pressed = 2131165294;
|
public const int notification_bg_low_normal = 2131165294;
|
||||||
|
|
||||||
// aapt resource value: 0x7F07006F
|
// aapt resource value: 0x7F07006F
|
||||||
public const int notification_bg_normal = 2131165295;
|
public const int notification_bg_low_pressed = 2131165295;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070070
|
// aapt resource value: 0x7F070070
|
||||||
public const int notification_bg_normal_pressed = 2131165296;
|
public const int notification_bg_normal = 2131165296;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070071
|
// aapt resource value: 0x7F070071
|
||||||
public const int notification_icon_background = 2131165297;
|
public const int notification_bg_normal_pressed = 2131165297;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070072
|
// aapt resource value: 0x7F070072
|
||||||
public const int notification_template_icon_bg = 2131165298;
|
public const int notification_icon_background = 2131165298;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070073
|
// aapt resource value: 0x7F070073
|
||||||
public const int notification_template_icon_low_bg = 2131165299;
|
public const int notification_template_icon_bg = 2131165299;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070074
|
// aapt resource value: 0x7F070074
|
||||||
public const int notification_tile_bg = 2131165300;
|
public const int notification_template_icon_low_bg = 2131165300;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070075
|
// aapt resource value: 0x7F070075
|
||||||
public const int notify_panel_notification_icon_bg = 2131165301;
|
public const int notification_tile_bg = 2131165301;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070076
|
// aapt resource value: 0x7F070076
|
||||||
public const int segmented_control_background = 2131165302;
|
public const int notify_panel_notification_icon_bg = 2131165302;
|
||||||
|
|
||||||
|
// aapt resource value: 0x7F07006A
|
||||||
|
public const int no_profile = 2131165290;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070077
|
// aapt resource value: 0x7F070077
|
||||||
public const int segmented_control_first_background = 2131165303;
|
public const int segmented_control_background = 2131165303;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070078
|
// aapt resource value: 0x7F070078
|
||||||
public const int segmented_control_last_background = 2131165304;
|
public const int segmented_control_first_background = 2131165304;
|
||||||
|
|
||||||
// aapt resource value: 0x7F070079
|
// aapt resource value: 0x7F070079
|
||||||
public const int splash_logo = 2131165305;
|
public const int segmented_control_last_background = 2131165305;
|
||||||
|
|
||||||
// aapt resource value: 0x7F07007A
|
// aapt resource value: 0x7F07007A
|
||||||
public const int splash_screen = 2131165306;
|
public const int splash_logo = 2131165306;
|
||||||
|
|
||||||
// aapt resource value: 0x7F07007B
|
// aapt resource value: 0x7F07007B
|
||||||
public const int tooltip_frame_dark = 2131165307;
|
public const int splash_screen = 2131165307;
|
||||||
|
|
||||||
// aapt resource value: 0x7F07007C
|
// aapt resource value: 0x7F07007C
|
||||||
public const int tooltip_frame_light = 2131165308;
|
public const int tooltip_frame_dark = 2131165308;
|
||||||
|
|
||||||
// aapt resource value: 0x7F07007D
|
// aapt resource value: 0x7F07007D
|
||||||
public const int userprofile = 2131165309;
|
public const int tooltip_frame_light = 2131165309;
|
||||||
|
|
||||||
static Drawable()
|
static Drawable()
|
||||||
{
|
{
|
||||||
|
BIN
Pixiview.Android/Resources/drawable/no_profile.png
Normal file
BIN
Pixiview.Android/Resources/drawable/no_profile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
@ -167,7 +167,7 @@
|
|||||||
<BundleResource Include="Resources\fa-light-300.ttf" />
|
<BundleResource Include="Resources\fa-light-300.ttf" />
|
||||||
<BundleResource Include="Resources\fa-regular-400.ttf" />
|
<BundleResource Include="Resources\fa-regular-400.ttf" />
|
||||||
<BundleResource Include="Resources\fa-solid-900.ttf" />
|
<BundleResource Include="Resources\fa-solid-900.ttf" />
|
||||||
<BundleResource Include="Resources\userprofile.jpg" />
|
|
||||||
<BundleResource Include="Resources\download.png" />
|
<BundleResource Include="Resources\download.png" />
|
||||||
|
<BundleResource Include="Resources\no_profile.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -64,7 +64,7 @@ namespace Pixiview.iOS.Renderers
|
|||||||
public override async void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
|
public override async void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
|
||||||
{
|
{
|
||||||
var url = webView.Url;
|
var url = webView.Url;
|
||||||
if (url.Host == "www.pixiv.net" && url.Path == "/")
|
if (url.Host == "www.pixiv.net" && (url.Path == "/" || url.Path == "/en/"))
|
||||||
{
|
{
|
||||||
var store = webView.Configuration.WebsiteDataStore.HttpCookieStore;
|
var store = webView.Configuration.WebsiteDataStore.HttpCookieStore;
|
||||||
var result = await Configs.RequestCookieContainer(store);
|
var result = await Configs.RequestCookieContainer(store);
|
||||||
|
BIN
Pixiview.iOS/Resources/no_profile.png
Normal file
BIN
Pixiview.iOS/Resources/no_profile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
@ -3,6 +3,7 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Pixiview.Illust;
|
using Pixiview.Illust;
|
||||||
using Pixiview.Resources;
|
using Pixiview.Resources;
|
||||||
using Pixiview.UI.Theme;
|
using Pixiview.UI.Theme;
|
||||||
@ -34,6 +35,9 @@ namespace Pixiview
|
|||||||
Configs.SetCookie(Preferences.Get(Configs.CookieKey, null));
|
Configs.SetCookie(Preferences.Get(Configs.CookieKey, null));
|
||||||
Configs.SetUserId(Preferences.Get(Configs.UserIdKey, null));
|
Configs.SetUserId(Preferences.Get(Configs.UserIdKey, null));
|
||||||
|
|
||||||
|
// login info
|
||||||
|
Task.Run(() => AppShell.Current.DoLoginInformation());
|
||||||
|
|
||||||
Configs.IsOnR18 = Preferences.Get(Configs.IsOnR18Key, false);
|
Configs.IsOnR18 = Preferences.Get(Configs.IsOnR18Key, false);
|
||||||
var isProxied = Preferences.Get(Configs.IsProxiedKey, false);
|
var isProxied = Preferences.Get(Configs.IsProxiedKey, false);
|
||||||
if (isProxied)
|
if (isProxied)
|
||||||
|
@ -20,16 +20,16 @@
|
|||||||
</Grid.GestureRecognizers>
|
</Grid.GestureRecognizers>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="80"/>
|
<RowDefinition Height="80"/>
|
||||||
<RowDefinition Height="25"/>
|
<RowDefinition Height="30"/>
|
||||||
<RowDefinition Height="20"/>
|
<RowDefinition Height="20"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<u:CircleImage Aspect="AspectFill" Source="userprofile.jpg"
|
<u:CircleImage Aspect="AspectFill" Source="{Binding UserProfileImage}"
|
||||||
HeightRequest="60" WidthRequest="60"
|
HeightRequest="60" WidthRequest="60"
|
||||||
VerticalOptions="End" HorizontalOptions="Start"/>
|
VerticalOptions="End" HorizontalOptions="Start"/>
|
||||||
<Label Grid.Row="1" VerticalOptions="End" FontAttributes="Bold"
|
<Label Grid.Row="1" VerticalOptions="End" FontAttributes="Bold"
|
||||||
Text="Tsanie" TextColor="{DynamicResource TextColor}"/>
|
Text="{Binding UserProfileName}" TextColor="{DynamicResource TextColor}"/>
|
||||||
<Label Grid.Row="2" VerticalOptions="Center" FontSize="Small"
|
<Label Grid.Row="2" VerticalOptions="Center" FontSize="Small"
|
||||||
Text="@tsanie" TextColor="{DynamicResource SubTextColor}"/>
|
Text="{Binding UserProfileId}" TextColor="{DynamicResource SubTextColor}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</Shell.FlyoutHeaderTemplate>
|
</Shell.FlyoutHeaderTemplate>
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Pixiview.Login;
|
using Pixiview.Login;
|
||||||
|
using Pixiview.Resources;
|
||||||
|
using Pixiview.UI;
|
||||||
using Pixiview.Utils;
|
using Pixiview.Utils;
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
@ -14,11 +17,35 @@ namespace Pixiview
|
|||||||
public static Thickness HalfNavigationBarOffset { get; private set; }
|
public static Thickness HalfNavigationBarOffset { get; private set; }
|
||||||
public static Thickness TotalBarOffset { get; private set; }
|
public static Thickness TotalBarOffset { get; private set; }
|
||||||
|
|
||||||
|
public static readonly BindableProperty UserProfileImageProperty = BindableProperty.Create(
|
||||||
|
nameof(UserProfileImage), typeof(ImageSource), typeof(AppShell), StyleDefinition.ProfileNone);
|
||||||
|
public static readonly BindableProperty UserProfileNameProperty = BindableProperty.Create(
|
||||||
|
nameof(UserProfileName), typeof(string), typeof(AppShell), ResourceHelper.Guest);
|
||||||
|
public static readonly BindableProperty UserProfileIdProperty = BindableProperty.Create(
|
||||||
|
nameof(UserProfileId), typeof(string), typeof(AppShell));
|
||||||
|
|
||||||
|
public ImageSource UserProfileImage
|
||||||
|
{
|
||||||
|
get => (ImageSource)GetValue(UserProfileImageProperty);
|
||||||
|
set => SetValue(UserProfileImageProperty, value);
|
||||||
|
}
|
||||||
|
public string UserProfileName
|
||||||
|
{
|
||||||
|
get => (string)GetValue(UserProfileNameProperty);
|
||||||
|
set => SetValue(UserProfileNameProperty, value);
|
||||||
|
}
|
||||||
|
public string UserProfileId
|
||||||
|
{
|
||||||
|
get => (string)GetValue(UserProfileIdProperty);
|
||||||
|
set => SetValue(UserProfileIdProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public event EventHandler<BarHeightEventArgs> NavigationBarHeightChanged;
|
public event EventHandler<BarHeightEventArgs> NavigationBarHeightChanged;
|
||||||
public event EventHandler<BarHeightEventArgs> StatusBarHeightChanged;
|
public event EventHandler<BarHeightEventArgs> StatusBarHeightChanged;
|
||||||
|
|
||||||
public AppShell()
|
public AppShell()
|
||||||
{
|
{
|
||||||
|
BindingContext = this;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
App.DebugPrint($"folder: {Stores.PersonalFolder}");
|
App.DebugPrint($"folder: {Stores.PersonalFolder}");
|
||||||
@ -47,7 +74,14 @@ namespace Pixiview
|
|||||||
|
|
||||||
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
|
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
PushToLogin(null);
|
if (UserProfileId != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PushToLogin(()=>
|
||||||
|
{
|
||||||
|
Task.Run(() => DoLoginInformation(true));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool isLoginOpened;
|
private bool isLoginOpened;
|
||||||
@ -73,6 +107,38 @@ namespace Pixiview
|
|||||||
await Navigation.PushModalAsync(loginPage);
|
await Navigation.PushModalAsync(loginPage);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DoLoginInformation(bool force = false)
|
||||||
|
{
|
||||||
|
string name = null;
|
||||||
|
string userId = null;
|
||||||
|
string img = null;
|
||||||
|
if (!force)
|
||||||
|
{
|
||||||
|
name = Preferences.Get(Configs.ProfileNameKey, null);
|
||||||
|
userId = Preferences.Get(Configs.ProfileIdKey, null);
|
||||||
|
img = Preferences.Get(Configs.ProfileImageKey, null);
|
||||||
|
}
|
||||||
|
if (name == null || userId == null)
|
||||||
|
{
|
||||||
|
var global = Stores.LoadGlobalData(force);
|
||||||
|
if (global == null || global.userData == null)
|
||||||
|
{
|
||||||
|
App.DebugError("login.info", "user data is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
name = global.userData.name;
|
||||||
|
userId = global.userData.pixivId;
|
||||||
|
img = global.userData.profileImg;
|
||||||
|
Preferences.Set(Configs.ProfileNameKey, name);
|
||||||
|
Preferences.Set(Configs.ProfileIdKey, userId);
|
||||||
|
Preferences.Set(Configs.ProfileImageKey, img);
|
||||||
|
}
|
||||||
|
UserProfileName = name;
|
||||||
|
UserProfileId = $"@{userId}";
|
||||||
|
|
||||||
|
UserProfileImage = Stores.LoadUserProfileImage(img);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BarHeightEventArgs : EventArgs
|
public class BarHeightEventArgs : EventArgs
|
||||||
|
@ -73,9 +73,11 @@ namespace Pixiview.Illust
|
|||||||
protected readonly Command<IllustItem> commandIllustImageTapped;
|
protected readonly Command<IllustItem> commandIllustImageTapped;
|
||||||
protected DateTime lastUpdated;
|
protected DateTime lastUpdated;
|
||||||
protected double topOffset;
|
protected double topOffset;
|
||||||
|
protected string lastError;
|
||||||
|
|
||||||
private T illustData;
|
private T illustData;
|
||||||
private ParallelTask task;
|
private ParallelTask task;
|
||||||
|
private bool isTrying;
|
||||||
|
|
||||||
public IllustCollectionPage()
|
public IllustCollectionPage()
|
||||||
{
|
{
|
||||||
@ -530,15 +532,31 @@ namespace Pixiview.Illust
|
|||||||
illustData = DoLoadIllustData(force);
|
illustData = DoLoadIllustData(force);
|
||||||
if (illustData == null)
|
if (illustData == null)
|
||||||
{
|
{
|
||||||
AppShell.Current.PushToLogin(()=>
|
if (isTrying)
|
||||||
{
|
{
|
||||||
|
MainThread.BeginInvokeOnMainThread(() =>
|
||||||
|
{
|
||||||
|
DisplayAlert(ResourceHelper.Title,
|
||||||
|
ResourceHelper.FailedResponse + "\n" + lastError?.Substring(0, 40),
|
||||||
|
ResourceHelper.Ok);
|
||||||
|
});
|
||||||
|
isTrying = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isTrying = true;
|
||||||
|
AppShell.Current.PushToLogin(() =>
|
||||||
|
{
|
||||||
|
Task.Run(() => AppShell.Current.DoLoginInformation(true));
|
||||||
StartLoad(true);
|
StartLoad(true);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
//App.DebugError("illusts.load", "failed to load illusts data.");
|
//App.DebugError("illusts.load", "failed to load illusts data.");
|
||||||
IsLoading = false;
|
IsLoading = false;
|
||||||
IsBottomLoading = false;
|
IsBottomLoading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
isTrying = false;
|
||||||
if (force && IsFavoriteVisible)
|
if (force && IsFavoriteVisible)
|
||||||
{
|
{
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
|
@ -160,7 +160,7 @@ namespace Pixiview.Illust
|
|||||||
|
|
||||||
protected override IllustRankingData DoLoadIllustData(bool force)
|
protected override IllustRankingData DoLoadIllustData(bool force)
|
||||||
{
|
{
|
||||||
var data = Stores.LoadIllustRankingData(lastQueryKey, queryDate, currentPage, force);
|
var data = Stores.LoadIllustRankingData(lastQueryKey, queryDate, currentPage, out lastError, force);
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
if (int.TryParse(data.next, out int next))
|
if (int.TryParse(data.next, out int next))
|
||||||
|
@ -331,16 +331,23 @@ namespace Pixiview.Illust
|
|||||||
}
|
}
|
||||||
|
|
||||||
Illusts = items;
|
Illusts = items;
|
||||||
Task.Run(DoLoadImages);
|
Task.Run(() => DoLoadImages());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DoLoadImages()
|
private void DoLoadImages(bool force = false)
|
||||||
{
|
{
|
||||||
var illustItem = IllustItem;
|
var illustItem = IllustItem;
|
||||||
var pages = Stores.LoadIllustPageData(illustItem.Id);
|
var pages = Stores.LoadIllustPageData(illustItem.Id, out string error, force);
|
||||||
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}");
|
||||||
|
if (error != null)
|
||||||
|
{
|
||||||
|
MainThread.BeginInvokeOnMainThread(() =>
|
||||||
|
{
|
||||||
|
DisplayAlert(ResourceHelper.Title, error, ResourceHelper.Ok);
|
||||||
|
});
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var items = Illusts;
|
var items = Illusts;
|
||||||
@ -385,9 +392,13 @@ namespace Pixiview.Illust
|
|||||||
var count = illustItem.PageCount;
|
var count = illustItem.PageCount;
|
||||||
pageCount = count;
|
pageCount = count;
|
||||||
Title = illustItem.Title;
|
Title = illustItem.Title;
|
||||||
IsPageVisible = count > 1;
|
|
||||||
IsAnimateSliderVisible = illustItem.IsAnimeVisible;
|
IsAnimateSliderVisible = illustItem.IsAnimeVisible;
|
||||||
ProgressVisible = count > 1;
|
if (count > 1)
|
||||||
|
{
|
||||||
|
IsPageVisible = true;
|
||||||
|
ProgressVisible = true;
|
||||||
|
PagePositionText = $"1/{count}";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (preload.user.TryGetValue(illust.userId, out var user))
|
if (preload.user.TryGetValue(illust.userId, out var user))
|
||||||
{
|
{
|
||||||
@ -423,6 +434,12 @@ namespace Pixiview.Illust
|
|||||||
private void DoLoadImage(int index, bool force = false)
|
private void DoLoadImage(int index, bool force = false)
|
||||||
{
|
{
|
||||||
var items = Illusts;
|
var items = Illusts;
|
||||||
|
if (index == 0 && force)
|
||||||
|
{
|
||||||
|
// error, refresh all
|
||||||
|
Task.Run(() => DoLoadImages(true));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (index < 0 || index >= items.Length)
|
if (index < 0 || index >= items.Length)
|
||||||
{
|
{
|
||||||
App.DebugPrint($"invalid index: {index}");
|
App.DebugPrint($"invalid index: {index}");
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Xamarin.Essentials;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Pixiview.Login
|
namespace Pixiview.Login
|
||||||
@ -29,7 +30,10 @@ namespace Pixiview.Login
|
|||||||
|
|
||||||
public void OnLoginHandle()
|
public void OnLoginHandle()
|
||||||
{
|
{
|
||||||
LoginHandle?.Invoke(this, EventArgs.Empty);
|
if (LoginHandle != null)
|
||||||
|
{
|
||||||
|
MainThread.BeginInvokeOnMainThread(() => LoginHandle(this, EventArgs.Empty));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
xmlns:r="clr-namespace:Pixiview.Resources"
|
xmlns:r="clr-namespace:Pixiview.Resources"
|
||||||
x:Class="Pixiview.OptionPage"
|
x:Class="Pixiview.OptionPage"
|
||||||
Title="{r:Text Option}">
|
Title="{r:Text Option}">
|
||||||
|
<ContentPage.ToolbarItems>
|
||||||
|
<ToolbarItem Order="Primary" Clicked="ShareCookie_Clicked"
|
||||||
|
IconImageSource="{DynamicResource FontIconShare}"/>
|
||||||
|
</ContentPage.ToolbarItems>
|
||||||
<TableView Intent="Settings" VerticalOptions="Start"
|
<TableView Intent="Settings" VerticalOptions="Start"
|
||||||
BackgroundColor="{DynamicResource OptionBackColor}">
|
BackgroundColor="{DynamicResource OptionBackColor}">
|
||||||
<TableRoot>
|
<TableRoot>
|
||||||
@ -24,6 +28,11 @@
|
|||||||
Text="{Binding Port, Mode=TwoWay}"
|
Text="{Binding Port, Mode=TwoWay}"
|
||||||
Keyboard="Numeric" Placeholder="8080"/>
|
Keyboard="Numeric" Placeholder="8080"/>
|
||||||
</TableSection>
|
</TableSection>
|
||||||
|
<TableSection Title="{r:Text Privacy}">
|
||||||
|
<u:OptionEntryCell Title="{r:Text Cookie}"
|
||||||
|
Text="{Binding Cookie, Mode=TwoWay}"
|
||||||
|
Keyboard="Text"/>
|
||||||
|
</TableSection>
|
||||||
</TableRoot>
|
</TableRoot>
|
||||||
</TableView>
|
</TableView>
|
||||||
</u:AdaptedPage>
|
</u:AdaptedPage>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Pixiview.UI;
|
using System;
|
||||||
|
using Pixiview.UI;
|
||||||
using Pixiview.Utils;
|
using Pixiview.Utils;
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
@ -15,6 +16,8 @@ namespace Pixiview
|
|||||||
nameof(Host), typeof(string), typeof(OptionPage));
|
nameof(Host), typeof(string), typeof(OptionPage));
|
||||||
public static readonly BindableProperty PortProperty = BindableProperty.Create(
|
public static readonly BindableProperty PortProperty = BindableProperty.Create(
|
||||||
nameof(Port), typeof(string), typeof(OptionPage));
|
nameof(Port), typeof(string), typeof(OptionPage));
|
||||||
|
public static readonly BindableProperty CookieProperty = BindableProperty.Create(
|
||||||
|
nameof(Cookie), typeof(string), typeof(OptionPage));
|
||||||
|
|
||||||
public bool IsOnR18
|
public bool IsOnR18
|
||||||
{
|
{
|
||||||
@ -36,6 +39,11 @@ namespace Pixiview
|
|||||||
get => (string)GetValue(PortProperty);
|
get => (string)GetValue(PortProperty);
|
||||||
set => SetValue(PortProperty, value);
|
set => SetValue(PortProperty, value);
|
||||||
}
|
}
|
||||||
|
public string Cookie
|
||||||
|
{
|
||||||
|
get => (string)GetValue(CookieProperty);
|
||||||
|
set => SetValue(CookieProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public OptionPage()
|
public OptionPage()
|
||||||
{
|
{
|
||||||
@ -47,14 +55,22 @@ namespace Pixiview
|
|||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
|
||||||
IsOnR18 = Preferences.Get(Configs.IsOnR18Key, false);
|
IsOnR18 = Configs.IsOnR18;
|
||||||
IsProxied = Preferences.Get(Configs.IsProxiedKey, false);
|
var proxy = Configs.Proxy;
|
||||||
Host = Preferences.Get(Configs.HostKey, string.Empty);
|
if (proxy != null)
|
||||||
int pt = Preferences.Get(Configs.PortKey, 0);
|
|
||||||
if (pt > 0)
|
|
||||||
{
|
{
|
||||||
Port = pt.ToString();
|
IsProxied = true;
|
||||||
|
Host = proxy.Address.Host;
|
||||||
|
Port = proxy.Address.Port.ToString();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IsProxied = false;
|
||||||
|
Host = string.Empty;
|
||||||
|
Port = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cookie = Configs.Cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisappearing()
|
protected override void OnDisappearing()
|
||||||
@ -63,30 +79,70 @@ namespace Pixiview
|
|||||||
|
|
||||||
var r18 = IsOnR18;
|
var r18 = IsOnR18;
|
||||||
var proxied = IsProxied;
|
var proxied = IsProxied;
|
||||||
var h = Host?.Trim();
|
|
||||||
|
|
||||||
|
if (Configs.IsOnR18 != r18)
|
||||||
|
{
|
||||||
Preferences.Set(Configs.IsOnR18Key, r18);
|
Preferences.Set(Configs.IsOnR18Key, r18);
|
||||||
Configs.IsOnR18 = r18;
|
Configs.IsOnR18 = r18;
|
||||||
App.DebugPrint($"r-18 filter: {r18}");
|
App.DebugPrint($"r-18 filter: {r18}");
|
||||||
|
}
|
||||||
|
|
||||||
Preferences.Set(Configs.IsProxiedKey, proxied);
|
var proxy = Configs.Proxy;
|
||||||
|
var h = Host?.Trim();
|
||||||
|
_ = int.TryParse(Port, out int pt);
|
||||||
|
if (proxied)
|
||||||
|
{
|
||||||
|
if (proxy == null ||
|
||||||
|
proxy.Address.Host != h ||
|
||||||
|
proxy.Address.Port != pt)
|
||||||
|
{
|
||||||
|
Preferences.Set(Configs.IsProxiedKey, true);
|
||||||
Preferences.Set(Configs.HostKey, h);
|
Preferences.Set(Configs.HostKey, h);
|
||||||
var p = Port;
|
if (pt > 0)
|
||||||
if (int.TryParse(p, out int pt) && pt > 0)
|
|
||||||
{
|
{
|
||||||
Preferences.Set(Configs.PortKey, pt);
|
Preferences.Set(Configs.PortKey, pt);
|
||||||
}
|
}
|
||||||
|
if (!string.IsNullOrEmpty(h) && pt > 0)
|
||||||
if (proxied && !string.IsNullOrEmpty(h) && pt > 0)
|
|
||||||
{
|
{
|
||||||
Configs.Proxy = new System.Net.WebProxy(h, pt);
|
Configs.Proxy = new System.Net.WebProxy(h, pt);
|
||||||
App.DebugPrint($"set proxy to: {h}:{pt}");
|
App.DebugPrint($"set proxy to: {h}:{pt}");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Configs.Proxy = null;
|
|
||||||
App.DebugPrint($"clear proxy");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (proxy != null)
|
||||||
|
{
|
||||||
|
Preferences.Set(Configs.HostKey, false);
|
||||||
|
if (pt > 0)
|
||||||
|
{
|
||||||
|
Preferences.Set(Configs.PortKey, pt);
|
||||||
|
}
|
||||||
|
Configs.Proxy = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cookie = Cookie;
|
||||||
|
if (Configs.Cookie != cookie)
|
||||||
|
{
|
||||||
|
Configs.SetCookie(cookie, true);
|
||||||
|
var index = cookie.IndexOf("PHPSESSID=");
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
var session = cookie.Substring(index + 10);
|
||||||
|
index = session.IndexOf('_');
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
session = session.Substring(0, index);
|
||||||
|
Configs.SetUserId(session, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void ShareCookie_Clicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
await Share.RequestAsync(new ShareTextRequest
|
||||||
|
{
|
||||||
|
Text = Cookie
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<root>
|
<root>
|
||||||
<Title>Pixiview</Title>
|
<Title>Pixiview</Title>
|
||||||
|
<Guest>游客</Guest>
|
||||||
<Ok>OK</Ok>
|
<Ok>OK</Ok>
|
||||||
<Cancel>取消</Cancel>
|
<Cancel>取消</Cancel>
|
||||||
<Yes>是</Yes>
|
<Yes>是</Yes>
|
||||||
@ -12,6 +13,8 @@
|
|||||||
<Enabled>启用</Enabled>
|
<Enabled>启用</Enabled>
|
||||||
<Host>主机</Host>
|
<Host>主机</Host>
|
||||||
<Port>端口</Port>
|
<Port>端口</Port>
|
||||||
|
<Privacy>隐私</Privacy>
|
||||||
|
<Cookie>Cookie</Cookie>
|
||||||
<Daily>今日</Daily>
|
<Daily>今日</Daily>
|
||||||
<Weekly>本周</Weekly>
|
<Weekly>本周</Weekly>
|
||||||
<Monthly>本月</Monthly>
|
<Monthly>本月</Monthly>
|
||||||
@ -49,4 +52,5 @@
|
|||||||
<CantExportVideo>无法导出视频,请先下载完成。</CantExportVideo>
|
<CantExportVideo>无法导出视频,请先下载完成。</CantExportVideo>
|
||||||
<AlreadySavedVideo>视频已保存,是否继续?</AlreadySavedVideo>
|
<AlreadySavedVideo>视频已保存,是否继续?</AlreadySavedVideo>
|
||||||
<ExportSuccess>视频已导出到照片库。</ExportSuccess>
|
<ExportSuccess>视频已导出到照片库。</ExportSuccess>
|
||||||
|
<FailedResponse>无法获取返回结果。</FailedResponse>
|
||||||
</root>
|
</root>
|
@ -11,6 +11,7 @@ namespace Pixiview.Resources
|
|||||||
public class ResourceHelper
|
public class ResourceHelper
|
||||||
{
|
{
|
||||||
public static string Title => GetResource(nameof(Title));
|
public static string Title => GetResource(nameof(Title));
|
||||||
|
public static string Guest => GetResource(nameof(Guest));
|
||||||
public static string Ok => GetResource(nameof(Ok));
|
public static string Ok => GetResource(nameof(Ok));
|
||||||
public static string Cancel => GetResource(nameof(Cancel));
|
public static string Cancel => GetResource(nameof(Cancel));
|
||||||
public static string Yes => GetResource(nameof(Yes));
|
public static string Yes => GetResource(nameof(Yes));
|
||||||
@ -32,6 +33,7 @@ namespace Pixiview.Resources
|
|||||||
public static string CantExportVideo => GetResource(nameof(CantExportVideo));
|
public static string CantExportVideo => GetResource(nameof(CantExportVideo));
|
||||||
public static string AlreadySavedVideo => GetResource(nameof(AlreadySavedVideo));
|
public static string AlreadySavedVideo => GetResource(nameof(AlreadySavedVideo));
|
||||||
public static string ExportSuccess => GetResource(nameof(ExportSuccess));
|
public static string ExportSuccess => GetResource(nameof(ExportSuccess));
|
||||||
|
public static string FailedResponse => GetResource(nameof(FailedResponse));
|
||||||
|
|
||||||
static readonly Dictionary<string, LanguageResource> dict = new Dictionary<string, LanguageResource>();
|
static readonly Dictionary<string, LanguageResource> dict = new Dictionary<string, LanguageResource>();
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ namespace Pixiview.UI
|
|||||||
public static readonly Color ColorRedBackground = Color.FromRgb(0xfd, 0x43, 0x63);
|
public static readonly Color ColorRedBackground = Color.FromRgb(0xfd, 0x43, 0x63);
|
||||||
public static readonly Color ColorDownloadBackground = Color.FromRgb(0xd7, 0xd9, 0xe0);
|
public static readonly Color ColorDownloadBackground = Color.FromRgb(0xd7, 0xd9, 0xe0);
|
||||||
public static readonly ImageSource DownloadBackground = ImageSource.FromFile("download.png");
|
public static readonly ImageSource DownloadBackground = ImageSource.FromFile("download.png");
|
||||||
|
public static readonly ImageSource ProfileNone = ImageSource.FromFile("no_profile.png");
|
||||||
public static readonly double FontSizeMicro = Device.GetNamedSize(NamedSize.Micro, typeof(Label));
|
public static readonly double FontSizeMicro = Device.GetNamedSize(NamedSize.Micro, typeof(Label));
|
||||||
public static readonly double FontSizeSmall = Device.GetNamedSize(NamedSize.Small, typeof(Label));
|
public static readonly double FontSizeSmall = Device.GetNamedSize(NamedSize.Small, typeof(Label));
|
||||||
|
|
||||||
|
@ -97,6 +97,10 @@ namespace Pixiview.Utils
|
|||||||
{
|
{
|
||||||
public static ParallelTask Start(int from, int toExclusive, int maxCount, Predicate<int> action)
|
public static ParallelTask Start(int from, int toExclusive, int maxCount, Predicate<int> action)
|
||||||
{
|
{
|
||||||
|
if (toExclusive <= from)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
var task = new ParallelTask(from, toExclusive, maxCount, action);
|
var task = new ParallelTask(from, toExclusive, maxCount, action);
|
||||||
Task.Run(task.Start);
|
Task.Run(task.Start);
|
||||||
return task;
|
return task;
|
||||||
|
@ -11,7 +11,7 @@ namespace Pixiview.Utils
|
|||||||
{
|
{
|
||||||
public class HttpUtility
|
public class HttpUtility
|
||||||
{
|
{
|
||||||
public static T LoadObject<T>(string file, string url, string referer,
|
public static T LoadObject<T>(string file, string url, string referer, out string error,
|
||||||
bool force = false,
|
bool force = false,
|
||||||
Action<HttpRequestHeaders> header = null,
|
Action<HttpRequestHeaders> header = null,
|
||||||
Func<T, string> namehandler = null,
|
Func<T, string> namehandler = null,
|
||||||
@ -59,6 +59,7 @@ namespace Pixiview.Utils
|
|||||||
});
|
});
|
||||||
if (response == null)
|
if (response == null)
|
||||||
{
|
{
|
||||||
|
error = "response is null";
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
using (response)
|
using (response)
|
||||||
@ -73,7 +74,8 @@ namespace Pixiview.Utils
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
App.DebugError("load.strea", $"failed to read stream, error: {ex.Message}");
|
App.DebugError("load.stream", $"failed to read stream, error: {ex.Message}");
|
||||||
|
error = ex.Message;
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +91,9 @@ namespace Pixiview.Utils
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
App.DebugError("load", $"failed to parse illust JSON object, error: {ex.Message}");
|
App.DebugError("load", $"failed to parse illust JSON object, content: {content}, error: {ex.Message}");
|
||||||
|
error = content;
|
||||||
|
return default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,17 +116,20 @@ namespace Pixiview.Utils
|
|||||||
|
|
||||||
if (rtn)
|
if (rtn)
|
||||||
{
|
{
|
||||||
|
error = null;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
error = null;
|
||||||
return JsonConvert.DeserializeObject<T>(content);
|
return JsonConvert.DeserializeObject<T>(content);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
App.DebugError("load", $"failed to parse illust JSON object, error: {ex.Message}");
|
App.DebugError("load", $"failed to parse illust JSON object, content: {content}, error: {ex.Message}");
|
||||||
|
error = content;
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,4 +115,24 @@ namespace Pixiview.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class IllustGlobalData
|
||||||
|
{
|
||||||
|
public string token;
|
||||||
|
public string oneSignalAppId;
|
||||||
|
public UserData userData;
|
||||||
|
|
||||||
|
public class UserData
|
||||||
|
{
|
||||||
|
public string id;
|
||||||
|
public string pixivId;
|
||||||
|
public string name;
|
||||||
|
public string profileImg;
|
||||||
|
public string profileImgBig;
|
||||||
|
public bool premium;
|
||||||
|
public int xRestrict;
|
||||||
|
public bool adult;
|
||||||
|
public bool safeMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Pixiview.Illust;
|
using Pixiview.Illust;
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
@ -22,6 +21,7 @@ namespace Pixiview.Utils
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private const string favoriteFile = "favorites.json";
|
private const string favoriteFile = "favorites.json";
|
||||||
|
private const string globalFile = "global.json";
|
||||||
private const string imageFolder = "img-original";
|
private const string imageFolder = "img-original";
|
||||||
private const string previewFolder = "img-master";
|
private const string previewFolder = "img-master";
|
||||||
private const string ugoiraFolder = "img-zip-ugoira";
|
private const string ugoiraFolder = "img-zip-ugoira";
|
||||||
@ -199,6 +199,7 @@ namespace Pixiview.Utils
|
|||||||
file,
|
file,
|
||||||
Configs.UrlIllustList,
|
Configs.UrlIllustList,
|
||||||
Configs.Referer,
|
Configs.Referer,
|
||||||
|
out _,
|
||||||
force: force);
|
force: force);
|
||||||
if (result == null || result.error)
|
if (result == null || result.error)
|
||||||
{
|
{
|
||||||
@ -207,7 +208,7 @@ namespace Pixiview.Utils
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IllustRankingData LoadIllustRankingData(string mode, string date, int page, bool force = false)
|
public static IllustRankingData LoadIllustRankingData(string mode, string date, int page, out string error, bool force = false)
|
||||||
{
|
{
|
||||||
var file = Path.Combine(CacheFolder, mode, $"{date}_{page}.json");
|
var file = Path.Combine(CacheFolder, mode, $"{date}_{page}.json");
|
||||||
string query = $"mode={mode}";
|
string query = $"mode={mode}";
|
||||||
@ -229,6 +230,7 @@ namespace Pixiview.Utils
|
|||||||
file,
|
file,
|
||||||
string.Format(Configs.UrlIllustRanking, query),
|
string.Format(Configs.UrlIllustRanking, query),
|
||||||
referer,
|
referer,
|
||||||
|
out error,
|
||||||
namehandler: rst =>
|
namehandler: rst =>
|
||||||
{
|
{
|
||||||
return Path.Combine(CacheFolder, mode, $"{rst.date}_{page}.json");
|
return Path.Combine(CacheFolder, mode, $"{rst.date}_{page}.json");
|
||||||
@ -252,6 +254,7 @@ namespace Pixiview.Utils
|
|||||||
file,
|
file,
|
||||||
string.Format(Configs.UrlIllustRecommendsInit, id),
|
string.Format(Configs.UrlIllustRecommendsInit, id),
|
||||||
string.Format(Configs.RefererIllust, id),
|
string.Format(Configs.RefererIllust, id),
|
||||||
|
out _,
|
||||||
force: force);
|
force: force);
|
||||||
if (result == null || result.error)
|
if (result == null || result.error)
|
||||||
{
|
{
|
||||||
@ -270,7 +273,8 @@ namespace Pixiview.Utils
|
|||||||
var result = HttpUtility.LoadObject<IllustRecommendsData>(
|
var result = HttpUtility.LoadObject<IllustRecommendsData>(
|
||||||
null,
|
null,
|
||||||
string.Format(Configs.UrlIllustRecommendsList, ps),
|
string.Format(Configs.UrlIllustRecommendsList, ps),
|
||||||
string.Format(Configs.RefererIllust, id));
|
string.Format(Configs.RefererIllust, id),
|
||||||
|
out _);
|
||||||
if (result == null || result.error)
|
if (result == null || result.error)
|
||||||
{
|
{
|
||||||
App.DebugPrint($"error when load recommends list data: {result?.message}");
|
App.DebugPrint($"error when load recommends list data: {result?.message}");
|
||||||
@ -278,6 +282,37 @@ namespace Pixiview.Utils
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IllustGlobalData LoadGlobalData(bool force = false)
|
||||||
|
{
|
||||||
|
var file = Path.Combine(PersonalFolder, globalFile);
|
||||||
|
var result = HttpUtility.LoadObject<IllustGlobalData>(
|
||||||
|
file,
|
||||||
|
Configs.Prefix,
|
||||||
|
null,
|
||||||
|
out _,
|
||||||
|
force: force,
|
||||||
|
header: h => { },
|
||||||
|
action: content =>
|
||||||
|
{
|
||||||
|
var index = content.IndexOf(Configs.SuffixGlobal);
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
index += Configs.SuffixGlobalLength;
|
||||||
|
var end = content.IndexOf('\'', index);
|
||||||
|
if (end > index)
|
||||||
|
{
|
||||||
|
content = content.Substring(index, end - index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
});
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
App.DebugPrint($"error when load global data, is null");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static IllustPreloadBody LoadIllustPreloadData(string id, bool force = false)
|
public static IllustPreloadBody LoadIllustPreloadData(string id, bool force = false)
|
||||||
{
|
{
|
||||||
var file = Path.Combine(CacheFolder, preloadsFolder, $"{id}.json");
|
var file = Path.Combine(CacheFolder, preloadsFolder, $"{id}.json");
|
||||||
@ -285,6 +320,7 @@ namespace Pixiview.Utils
|
|||||||
file,
|
file,
|
||||||
string.Format(Configs.UrlIllust, id),
|
string.Format(Configs.UrlIllust, id),
|
||||||
null,
|
null,
|
||||||
|
out _,
|
||||||
force: force,
|
force: force,
|
||||||
action: content =>
|
action: content =>
|
||||||
{
|
{
|
||||||
@ -307,18 +343,22 @@ namespace Pixiview.Utils
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IllustPageData LoadIllustPageData(string id, bool force = false)
|
public static IllustPageData LoadIllustPageData(string id, out string error, bool force = false)
|
||||||
{
|
{
|
||||||
var file = Path.Combine(CacheFolder, pagesFolder, $"{id}.json");
|
var file = Path.Combine(CacheFolder, pagesFolder, $"{id}.json");
|
||||||
var result = HttpUtility.LoadObject<IllustPageData>(
|
var result = HttpUtility.LoadObject<IllustPageData>(
|
||||||
file,
|
file,
|
||||||
string.Format(Configs.UrlIllustPage, id),
|
string.Format(Configs.UrlIllustPage, id),
|
||||||
string.Format(Configs.RefererIllust, id),
|
string.Format(Configs.RefererIllust, id),
|
||||||
|
out _,
|
||||||
force: force);
|
force: force);
|
||||||
if (result == null || result.error)
|
if (result == null || result.error)
|
||||||
{
|
{
|
||||||
App.DebugPrint($"error when load page data: {result?.message}, force({force})");
|
error = result?.message ?? "result is null";
|
||||||
|
App.DebugPrint($"error when load page data: {error}, force({force})");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
error = null;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,6 +369,7 @@ namespace Pixiview.Utils
|
|||||||
file,
|
file,
|
||||||
string.Format(Configs.UrlIllustUgoira, id),
|
string.Format(Configs.UrlIllustUgoira, id),
|
||||||
string.Format(Configs.RefererIllust, id),
|
string.Format(Configs.RefererIllust, id),
|
||||||
|
out _,
|
||||||
force: force);
|
force: force);
|
||||||
if (result == null || result.error)
|
if (result == null || result.error)
|
||||||
{
|
{
|
||||||
@ -342,7 +383,8 @@ namespace Pixiview.Utils
|
|||||||
var list = HttpUtility.LoadObject<IllustUserListData>(
|
var list = HttpUtility.LoadObject<IllustUserListData>(
|
||||||
null,
|
null,
|
||||||
string.Format(Configs.UrlIllustUserAll, userId),
|
string.Format(Configs.UrlIllustUserAll, userId),
|
||||||
string.Format(Configs.RefererIllustUser, userId));
|
string.Format(Configs.RefererIllustUser, userId),
|
||||||
|
out _);
|
||||||
if (list == null || list.error)
|
if (list == null || list.error)
|
||||||
{
|
{
|
||||||
App.DebugPrint($"error when load user data: {list?.message}");
|
App.DebugPrint($"error when load user data: {list?.message}");
|
||||||
@ -360,7 +402,8 @@ namespace Pixiview.Utils
|
|||||||
var result = HttpUtility.LoadObject<IllustUserData>(
|
var result = HttpUtility.LoadObject<IllustUserData>(
|
||||||
null,
|
null,
|
||||||
string.Format(Configs.UrlIllustUserArtworks, userId, ps, firstPage ? 1 : 0),
|
string.Format(Configs.UrlIllustUserArtworks, userId, ps, firstPage ? 1 : 0),
|
||||||
string.Format(Configs.RefererIllustUser, userId));
|
string.Format(Configs.RefererIllustUser, userId),
|
||||||
|
out _);
|
||||||
if (result == null || result.error)
|
if (result == null || result.error)
|
||||||
{
|
{
|
||||||
App.DebugPrint($"error when load user illust data: {result?.message}");
|
App.DebugPrint($"error when load user illust data: {result?.message}");
|
||||||
@ -471,6 +514,9 @@ namespace Pixiview.Utils
|
|||||||
|
|
||||||
public static class Configs
|
public static class Configs
|
||||||
{
|
{
|
||||||
|
public const string ProfileNameKey = "name";
|
||||||
|
public const string ProfileIdKey = "pixiv_id";
|
||||||
|
public const string ProfileImageKey = "profile_img";
|
||||||
public const string CookieKey = "cookies";
|
public const string CookieKey = "cookies";
|
||||||
public const string UserIdKey = "user_id";
|
public const string UserIdKey = "user_id";
|
||||||
public const string IsOnR18Key = "is_on_r18";
|
public const string IsOnR18Key = "is_on_r18";
|
||||||
@ -490,7 +536,7 @@ namespace Pixiview.Utils
|
|||||||
|
|
||||||
public static bool IsOnR18;
|
public static bool IsOnR18;
|
||||||
public static WebProxy Proxy;
|
public static WebProxy Proxy;
|
||||||
private static string Prefix => Proxy == null ?
|
public static string Prefix => Proxy == null ?
|
||||||
"https://hk.tsanie.us/reverse/" :
|
"https://hk.tsanie.us/reverse/" :
|
||||||
"https://www.pixiv.net/";
|
"https://www.pixiv.net/";
|
||||||
public static string UserId { get; private set; }
|
public static string UserId { get; private set; }
|
||||||
@ -513,15 +559,27 @@ namespace Pixiview.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetCookie(string cookie)
|
public static void SetCookie(string cookie, bool save = false)
|
||||||
{
|
{
|
||||||
Cookie = cookie;
|
Cookie = cookie;
|
||||||
|
if (!save)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cookie == null)
|
||||||
|
{
|
||||||
|
Preferences.Remove(CookieKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Preferences.Set(CookieKey, cookie);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __IOS__
|
#if __IOS__
|
||||||
public static Task<bool> RequestCookieContainer(WebKit.WKHttpCookieStore cookieStore)
|
public static System.Threading.Tasks.Task<bool> RequestCookieContainer(WebKit.WKHttpCookieStore cookieStore)
|
||||||
{
|
{
|
||||||
var task = new TaskCompletionSource<bool>();
|
var task = new System.Threading.Tasks.TaskCompletionSource<bool>();
|
||||||
cookieStore.GetAllCookies(cookies =>
|
cookieStore.GetAllCookies(cookies =>
|
||||||
{
|
{
|
||||||
var list = new List<string>();
|
var list = new List<string>();
|
||||||
@ -549,10 +607,10 @@ namespace Pixiview.Utils
|
|||||||
});
|
});
|
||||||
return task.Task;
|
return task.Task;
|
||||||
}
|
}
|
||||||
#elif __ANDROID__
|
|
||||||
task.SetResult(false);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public const string SuffixGlobal = " id=\"meta-global-data\" content='";
|
||||||
|
public const int SuffixGlobalLength = 32;
|
||||||
public const string SuffixPreload = " id=\"meta-preload-data\" content='";
|
public const string SuffixPreload = " id=\"meta-preload-data\" content='";
|
||||||
public const int SuffixPreloadLength = 33; // SuffixPreload.Length
|
public const int SuffixPreloadLength = 33; // SuffixPreload.Length
|
||||||
public static string UrlIllustList => Prefix + "ajax/top/illust?mode=all&lang=zh";
|
public static string UrlIllustList => Prefix + "ajax/top/illust?mode=all&lang=zh";
|
||||||
|
Reference in New Issue
Block a user