rename Pixiview from Gallery

This commit is contained in:
2021-08-05 10:34:39 +08:00
parent c60e3a6445
commit 2985fdb654
206 changed files with 7847 additions and 7847 deletions

View File

@@ -0,0 +1,35 @@
using Foundation;
using UIKit;
namespace Pixiview.iOS
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
#if LOG
App.DebugPrint($"open url: {url}.");
#endif
return App.OpenUrl(url);
}
}
}

View File

@@ -0,0 +1,117 @@
{
"images": [
{
"scale": "2x",
"size": "20x20",
"idiom": "iphone",
"filename": "Icon40.png"
},
{
"scale": "3x",
"size": "20x20",
"idiom": "iphone",
"filename": "Icon60.png"
},
{
"scale": "2x",
"size": "29x29",
"idiom": "iphone",
"filename": "Icon58.png"
},
{
"scale": "3x",
"size": "29x29",
"idiom": "iphone",
"filename": "Icon87.png"
},
{
"scale": "2x",
"size": "40x40",
"idiom": "iphone",
"filename": "Icon80.png"
},
{
"scale": "3x",
"size": "40x40",
"idiom": "iphone",
"filename": "Icon120.png"
},
{
"scale": "2x",
"size": "60x60",
"idiom": "iphone",
"filename": "Icon120.png"
},
{
"scale": "3x",
"size": "60x60",
"idiom": "iphone",
"filename": "Icon180.png"
},
{
"scale": "1x",
"size": "20x20",
"idiom": "ipad",
"filename": "Icon20.png"
},
{
"scale": "2x",
"size": "20x20",
"idiom": "ipad",
"filename": "Icon40.png"
},
{
"scale": "1x",
"size": "29x29",
"idiom": "ipad",
"filename": "Icon29.png"
},
{
"scale": "2x",
"size": "29x29",
"idiom": "ipad",
"filename": "Icon58.png"
},
{
"scale": "1x",
"size": "40x40",
"idiom": "ipad",
"filename": "Icon40.png"
},
{
"scale": "2x",
"size": "40x40",
"idiom": "ipad",
"filename": "Icon80.png"
},
{
"scale": "1x",
"size": "76x76",
"idiom": "ipad",
"filename": "Icon76.png"
},
{
"scale": "2x",
"size": "76x76",
"idiom": "ipad",
"filename": "Icon152.png"
},
{
"scale": "2x",
"size": "83.5x83.5",
"idiom": "ipad",
"filename": "Icon167.png"
},
{
"scale": "1x",
"size": "1024x1024",
"idiom": "ios-marketing",
"filename": "Icon1024.png"
}
],
"properties": {},
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -0,0 +1,23 @@
{
"images": [
{
"filename": "bookmark-solid.png",
"scale": "1x",
"idiom": "universal"
},
{
"filename": "bookmark-solid@2x.png",
"scale": "2x",
"idiom": "universal"
},
{
"filename": "bookmark-solid@3x.png",
"scale": "3x",
"idiom": "universal"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

View File

@@ -0,0 +1,23 @@
{
"images": [
{
"filename": "bookmark-regular.png",
"scale": "1x",
"idiom": "universal"
},
{
"filename": "bookmark-regular@2x.png",
"scale": "2x",
"idiom": "universal"
},
{
"filename": "bookmark-regular@3x.png",
"scale": "3x",
"idiom": "universal"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

View File

@@ -0,0 +1,23 @@
{
"images": [
{
"filename": "sort-size-up-alt-solid.png",
"scale": "1x",
"idiom": "universal"
},
{
"filename": "sort-size-up-alt-solid@2x.png",
"scale": "2x",
"idiom": "universal"
},
{
"filename": "sort-size-up-alt-solid@3x.png",
"scale": "3x",
"idiom": "universal"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

View File

@@ -0,0 +1,23 @@
{
"images": [
{
"filename": "sort-size-up-alt-regular.png",
"scale": "1x",
"idiom": "universal"
},
{
"filename": "sort-size-up-alt-regular@2x.png",
"scale": "2x",
"idiom": "universal"
},
{
"filename": "sort-size-up-alt-regular@3x.png",
"scale": "3x",
"idiom": "universal"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 711 B

View File

@@ -0,0 +1,23 @@
{
"images": [
{
"filename": "sparkles-solid.png",
"scale": "1x",
"idiom": "universal"
},
{
"filename": "sparkles-solid@2x.png",
"scale": "2x",
"idiom": "universal"
},
{
"filename": "sparkles-solid@3x.png",
"scale": "3x",
"idiom": "universal"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

View File

@@ -0,0 +1,23 @@
{
"images": [
{
"filename": "sparkles-regular.png",
"scale": "1x",
"idiom": "universal"
},
{
"filename": "sparkles-regular@2x.png",
"scale": "2x",
"idiom": "universal"
},
{
"filename": "sparkles-regular@3x.png",
"scale": "3x",
"idiom": "universal"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

View File

@@ -0,0 +1,23 @@
{
"images": [
{
"filename": "user-solid.png",
"scale": "1x",
"idiom": "universal"
},
{
"filename": "user-solid@2x.png",
"scale": "2x",
"idiom": "universal"
},
{
"filename": "user-solid@3x.png",
"scale": "3x",
"idiom": "universal"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

View File

@@ -0,0 +1,23 @@
{
"images": [
{
"filename": "user-regular.png",
"scale": "1x",
"idiom": "universal"
},
{
"filename": "user-regular@2x.png",
"scale": "2x",
"idiom": "universal"
},
{
"filename": "user-regular@3x.png",
"scale": "3x",
"idiom": "universal"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,23 @@
{
"images": [
{
"filename": "pixiv.png",
"scale": "1x",
"idiom": "universal"
},
{
"filename": "pixiv@2x.png",
"scale": "2x",
"idiom": "universal"
},
{
"filename": "pixiv@3x.png",
"scale": "3x",
"idiom": "universal"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,57 @@
using Pixiview.iOS.Effects;
using Pixiview.Utils;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ResolutionGroupName("Pixiview")]
[assembly: ExportEffect(typeof(LongPressEffectImplement), "LongPressEffect")]
namespace Pixiview.iOS.Effects
{
public class LongPressEffectImplement : PlatformEffect
{
private bool attached;
private readonly UILongPressGestureRecognizer longPressGesture;
public LongPressEffectImplement()
{
longPressGesture = new UILongPressGestureRecognizer(OnLongPressed);
}
protected override void OnAttached()
{
if (!attached)
{
attached = true;
Container.AddGestureRecognizer(longPressGesture);
}
}
protected override void OnDetached()
{
if (attached)
{
attached = false;
Container.RemoveGestureRecognizer(longPressGesture);
}
}
private void OnLongPressed(UILongPressGestureRecognizer e)
{
if (e.State != UIGestureRecognizerState.Began)
{
return;
}
var element = Element;
if (element != null)
{
var command = LongPressEffect.GetCommand(element);
if (command != null)
{
var o = LongPressEffect.GetCommandParameter(element);
command.Execute(o);
}
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
</dict>
</plist>

View File

@@ -0,0 +1,224 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0CDD279E-3CAB-4CCA-A7C4-BC499724D051}</ProjectGuid>
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TemplateGuid>{6143fdea-f3c2-4a09-aafa-6e230626515e}</TemplateGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Pixiview.iOS</RootNamespace>
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
<AssemblyName>Pixiview.iOS</AssemblyName>
<MtouchEnableSGenConc>true</MtouchEnableSGenConc>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<ProvisioningType>automatic</ProvisioningType>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
<DefineConstants>DEBUG;LOG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<MtouchArch>x86_64</MtouchArch>
<MtouchLink>None</MtouchLink>
<MtouchDebug>true</MtouchDebug>
<CodesignKey>Apple Development: Li Chen (5559SN7Z38)</CodesignKey>
<CodesignProvision>Pixiview.Dev</CodesignProvision>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhoneSimulator\Release</OutputPath>
<DefineConstants>LOG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<MtouchLink>None</MtouchLink>
<MtouchArch>x86_64</MtouchArch>
<CodesignKey>Apple Distribution: Li Chen (7HSM5CKPJ2)</CodesignKey>
<CodesignProvision>Pixiview.Ad-Hoc</CodesignProvision>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\iPhone\Debug</OutputPath>
<DefineConstants>DEBUG;LOG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<MtouchArch>ARM64</MtouchArch>
<CodesignKey>Apple Development: Li Chen (5559SN7Z38)</CodesignKey>
<MtouchDebug>true</MtouchDebug>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<MtouchLink>None</MtouchLink>
<MtouchInterpreter>-all</MtouchInterpreter>
<CodesignProvision>Pixiview.Dev</CodesignProvision>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhone\Release</OutputPath>
<DefineConstants>LOG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<MtouchArch>ARM64</MtouchArch>
<CodesignKey>Apple Distribution: Li Chen (7HSM5CKPJ2)</CodesignKey>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<MtouchUseLlvm>true</MtouchUseLlvm>
<MtouchExtraArgs>--optimize=experimental-xforms-product-type</MtouchExtraArgs>
<MtouchLink>SdkOnly</MtouchLink>
<CodesignProvision>Pixiview.Ad-Hoc</CodesignProvision>
</PropertyGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AppDelegate.cs" />
<None Include="Entitlements.plist" />
<None Include="Info.plist" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Renderers\AdaptedPageRenderer.cs" />
<Compile Include="Renderers\CircleImageRenderer.cs" />
<Compile Include="Renderers\RoundLabelRenderer.cs" />
<Compile Include="Renderers\CardViewRenderer.cs" />
<Compile Include="Renderers\RoundImageRenderer.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="Renderers\AppShellRenderer.cs" />
<Compile Include="Renderers\AppShellSection\AppShellSectionRootHeader.cs" />
<Compile Include="Renderers\SegmentedControlRenderer.cs" />
<Compile Include="Effects\LongPressEffectImplement.cs" />
<Compile Include="Renderers\OptionEntryRenderer.cs" />
<Compile Include="Renderers\AppShellSection\AppAppearanceTracker.cs" />
<Compile Include="Renderers\BlurryPanelRenderer.cs" />
<Compile Include="Renderers\HybridWebViewRenderer.cs" />
<Compile Include="Renderers\OptionPickerRenderer.cs" />
</ItemGroup>
<ItemGroup>
<InterfaceDefinition Include="Resources\LaunchScreen.storyboard" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Contents.json">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon1024.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon180.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon167.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon152.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon120.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon87.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon80.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon76.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon60.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon58.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon40.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon29.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon20.png">
<Visible>false</Visible>
</ImageAsset>
<ImageAsset Include="Assets.xcassets\LauncherLogo.imageset\Contents.json" />
<ImageAsset Include="Assets.xcassets\LauncherLogo.imageset\pixiv.png" />
<ImageAsset Include="Assets.xcassets\LauncherLogo.imageset\pixiv%402x.png" />
<ImageAsset Include="Assets.xcassets\LauncherLogo.imageset\pixiv%403x.png" />
<ImageAsset Include="Assets.xcassets\IconUserRegular.imageset\Contents.json" />
<ImageAsset Include="Assets.xcassets\IconUser.imageset\Contents.json" />
<ImageAsset Include="Assets.xcassets\IconSparklesRegular.imageset\Contents.json" />
<ImageAsset Include="Assets.xcassets\IconSparkles.imageset\Contents.json" />
<ImageAsset Include="Assets.xcassets\IconSortRegular.imageset\Contents.json" />
<ImageAsset Include="Assets.xcassets\IconSort.imageset\Contents.json" />
<ImageAsset Include="Assets.xcassets\IconBookmarkRegular.imageset\Contents.json" />
<ImageAsset Include="Assets.xcassets\IconBookmark.imageset\Contents.json" />
<ImageAsset Include="Assets.xcassets\IconUserRegular.imageset\user-regular.png" />
<ImageAsset Include="Assets.xcassets\IconUserRegular.imageset\user-regular%402x.png" />
<ImageAsset Include="Assets.xcassets\IconUserRegular.imageset\user-regular%403x.png" />
<ImageAsset Include="Assets.xcassets\IconUser.imageset\user-solid.png" />
<ImageAsset Include="Assets.xcassets\IconUser.imageset\user-solid%402x.png" />
<ImageAsset Include="Assets.xcassets\IconUser.imageset\user-solid%403x.png" />
<ImageAsset Include="Assets.xcassets\IconSparkles.imageset\sparkles-solid.png" />
<ImageAsset Include="Assets.xcassets\IconSparkles.imageset\sparkles-solid%402x.png" />
<ImageAsset Include="Assets.xcassets\IconSparkles.imageset\sparkles-solid%403x.png" />
<ImageAsset Include="Assets.xcassets\IconSparklesRegular.imageset\sparkles-regular.png" />
<ImageAsset Include="Assets.xcassets\IconSparklesRegular.imageset\sparkles-regular%402x.png" />
<ImageAsset Include="Assets.xcassets\IconSparklesRegular.imageset\sparkles-regular%403x.png" />
<ImageAsset Include="Assets.xcassets\IconSort.imageset\sort-size-up-alt-solid.png" />
<ImageAsset Include="Assets.xcassets\IconSort.imageset\sort-size-up-alt-solid%402x.png" />
<ImageAsset Include="Assets.xcassets\IconSort.imageset\sort-size-up-alt-solid%403x.png" />
<ImageAsset Include="Assets.xcassets\IconSortRegular.imageset\sort-size-up-alt-regular.png" />
<ImageAsset Include="Assets.xcassets\IconSortRegular.imageset\sort-size-up-alt-regular%402x.png" />
<ImageAsset Include="Assets.xcassets\IconSortRegular.imageset\sort-size-up-alt-regular%403x.png" />
<ImageAsset Include="Assets.xcassets\IconBookmark.imageset\bookmark-solid.png" />
<ImageAsset Include="Assets.xcassets\IconBookmark.imageset\bookmark-solid%402x.png" />
<ImageAsset Include="Assets.xcassets\IconBookmark.imageset\bookmark-solid%403x.png" />
<ImageAsset Include="Assets.xcassets\IconBookmarkRegular.imageset\bookmark-regular.png" />
<ImageAsset Include="Assets.xcassets\IconBookmarkRegular.imageset\bookmark-regular%402x.png" />
<ImageAsset Include="Assets.xcassets\IconBookmarkRegular.imageset\bookmark-regular%403x.png" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="Xamarin.iOS" />
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors" />
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2083" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.0" />
<PackageReference Include="System.Text.Json" Version="5.0.2" />
</ItemGroup>
<Import Project="..\Pixiview\Pixiview.projitems" Label="Shared" Condition="Exists('..\Pixiview\Pixiview.projitems')" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\Pixiview.iOS.OpenExtension\Pixiview.iOS.OpenExtension.csproj">
<IsAppExtension>true</IsAppExtension>
<Project>{618D8350-495C-42D0-9DAC-87ADD36AC727}</Project>
<Name>Pixiview.iOS.OpenExtension</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Renderers\" />
<Folder Include="Renderers\AppShellSection\" />
<Folder Include="Effects\" />
<Folder Include="Assets.xcassets\LauncherLogo.imageset\" />
<Folder Include="Assets.xcassets\IconUserRegular.imageset\" />
<Folder Include="Assets.xcassets\IconUser.imageset\" />
<Folder Include="Assets.xcassets\IconSparklesRegular.imageset\" />
<Folder Include="Assets.xcassets\IconSparkles.imageset\" />
<Folder Include="Assets.xcassets\IconSortRegular.imageset\" />
<Folder Include="Assets.xcassets\IconSort.imageset\" />
<Folder Include="Assets.xcassets\IconBookmarkRegular.imageset\" />
<Folder Include="Assets.xcassets\IconBookmark.imageset\" />
</ItemGroup>
<ItemGroup>
<BundleResource Include="Resources\fa-light-300.ttf" />
<BundleResource Include="Resources\fa-regular-400.ttf" />
<BundleResource Include="Resources\fa-solid-900.ttf" />
<BundleResource Include="Resources\download.png" />
<BundleResource Include="Resources\no_profile.png" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,11 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Style", "IDE0056:Use index operator", Justification = "<Pending>")]
[assembly: SuppressMessage("Style", "IDE0057:Use range operator", Justification = "<Pending>")]
[assembly: SuppressMessage("Style", "IDE0063:Use simple 'using' statement", Justification = "<Pending>")]
[assembly: SuppressMessage("Style", "IDE0066:Convert switch statement to expression", Justification = "<Pending>")]

88
Pixiview.iOS/Info.plist Normal file
View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>MinimumOSVersion</key>
<string>13.0</string>
<key>CFBundleDisplayName</key>
<string>Pixiview</string>
<key>CFBundleIdentifier</key>
<string>org.tsanie.pixiview</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>CFBundleName</key>
<string>Pixiview</string>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/AppIcon.appiconset</string>
<key>UIAppFonts</key>
<array>
<string>fa-light-300.ttf</string>
<string>fa-regular-400.ttf</string>
<string>fa-solid-900.ttf</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDefault</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问您的图片库</string>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLSchemes</key>
<array>
<string>pixiview</string>
</array>
<key>CFBundleURLName</key>
<string>org.tsanie.pixiview</string>
<key>CFBundleURLIconFile</key>
<string>Assets.xcassets/AppIcon.appiconset/Icon58</string>
</dict>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Favorites Json</string>
<key>LSItemContentTypes</key>
<array>
<string>public.text</string>
</array>
<key>CFBundleTypeIconFiles</key>
<array>
<string>Assets.xcassets/AppIcon.appiconset/Icon180</string>
</array>
</dict>
</array>
<key>CFBundleShortVersionString</key>
<string>2.1.805</string>
<key>CFBundleVersion</key>
<string>35</string>
<key>CFBundleDevelopmentRegion</key>
<string>China</string>
</dict>
</plist>

15
Pixiview.iOS/Main.cs Normal file
View File

@@ -0,0 +1,15 @@
using UIKit;
namespace Pixiview.iOS
{
public class Application
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, "AppDelegate");
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Pixiview.iOS")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Pixiview.iOS")]
[assembly: AssemblyCopyright("Copyright © Tsanie.Org 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,107 @@
using Foundation;
using Pixiview.iOS.Renderers;
using Pixiview.UI;
using Pixiview.Utils;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(AdaptedPage), typeof(AdaptedPageRenderer))]
namespace Pixiview.iOS.Renderers
{
public class AdaptedPageRenderer : PageRenderer
{
UIDeviceOrientation lastOrientation;
NSObject observer;
public override void ViewDidLoad()
{
base.ViewDidLoad();
if (Element is AdaptedPage page)
{
//var mode = ForPage.GetLargeTitleDisplay(page);
//NavigationItem.LargeTitleDisplayMode = UINavigationItemLargeTitleDisplayMode.Automatic;
//lastOrientation = UIDevice.CurrentDevice.Orientation;
//var landscape =
// lastOrientation == UIDeviceOrientation.LandscapeLeft ||
// lastOrientation == UIDeviceOrientation.LandscapeRight;
//page.OnOrientationChanged(landscape);
page.OnLoad();
}
}
protected override void Dispose(bool disposing)
{
if (Element is AdaptedPage page)
{
page.OnUnload();
}
base.Dispose(disposing);
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
var element = Element;
if (element != null)
{
var style = EnvironmentService.ConvertStyle(Screen.GetStatusBarStyle(element));
EnvironmentService.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);
}
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 (current == UIDeviceOrientation.Portrait && UIApplication.SharedApplication.StatusBarHidden)
{
var style = EnvironmentService.ConvertStyle(Screen.GetStatusBarStyle(Element));
if (style != UIStatusBarStyle.BlackOpaque)
{
UIApplication.SharedApplication.SetStatusBarHidden(false, true);
}
}
if (Element is AdaptedPage page)
{
AppShell.Current?.SetStatusBarHeight(
NavigationController?.NavigationBar.Frame.Height ?? 0,
UIApplication.SharedApplication.StatusBarFrame.Height);
var landscape =
lastOrientation == UIDeviceOrientation.LandscapeLeft ||
lastOrientation == UIDeviceOrientation.LandscapeRight;
if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
{
landscape |= lastOrientation == UIDeviceOrientation.PortraitUpsideDown;
}
page.OnOrientationChanged(landscape);
}
}
}
}
}

View File

@@ -0,0 +1,93 @@
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Pixiview.iOS.Renderers;
using Pixiview.iOS.Renderers.AppShellSection;
using Pixiview.Utils;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(Shell), typeof(AppShellRenderer))]
namespace Pixiview.iOS.Renderers
{
public class AppShellRenderer : ShellRenderer
{
public override bool PrefersHomeIndicatorAutoHidden => Screen.GetHomeIndicatorAutoHidden(Element);
protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
{
var renderer = base.CreateShellSectionRenderer(shellSection); // new AppShellSectionRenderer(this);
if (renderer is ShellSectionRenderer sr && Element is AppShell shell)
{
shell.SetNavigationBarHeight(sr.NavigationBar.Frame.Height);
shell.SetStatusBarHeight(
sr.NavigationBar.Frame.Height,
UIApplication.SharedApplication.StatusBarFrame.Height);
}
return renderer;
}
protected override IShellItemTransition CreateShellItemTransition()
{
return new AppShellItemTransition();
}
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new AppShellTabBarAppearanceTracker();
}
protected override IShellNavBarAppearanceTracker CreateNavBarAppearanceTracker()
{
return new AppShellNavBarAppearanceTracker();
}
protected override void UpdateBackgroundColor()
{
NativeView.BackgroundColor = Color.Transparent.ToUIColor();
}
}
public class AppShellItemTransition : IShellItemTransition
{
[SuppressMessage("Code Notifications", "XI0001:Notifies you with advices on how to use Apple APIs", Justification = "<Pending>")]
public Task Transition(IShellItemRenderer oldRenderer, IShellItemRenderer newRenderer)
{
var task = new TaskCompletionSource<bool>();
var oldView = oldRenderer.ViewController.View;
var newView = newRenderer.ViewController.View;
newView.Alpha = 0;
newView.Superview.InsertSubviewAbove(newView, oldView);
UIView.Animate(0.2, 0, UIViewAnimationOptions.BeginFromCurrentState, () => newView.Alpha = 1, () => task.TrySetResult(true));
return task.Task;
}
}
public class AppShellSectionRenderer : ShellSectionRenderer
{
public AppShellSectionRenderer(IShellContext context) : base(context)
{
}
protected override IShellSectionRootRenderer CreateShellSectionRootRenderer(ShellSection shellSection, IShellContext shellContext)
{
return new AppShellSectionRootRenderer(shellSection, shellContext);
}
}
public class AppShellSectionRootRenderer : ShellSectionRootRenderer
{
public AppShellSectionRootRenderer(ShellSection shellSection, IShellContext shellContext) : base(shellSection, shellContext)
{
}
protected override IShellSectionRootHeader CreateShellSectionRootHeader(IShellContext shellContext)
{
return new AppShellSectionRootHeader(shellContext);
}
}
}

View File

@@ -0,0 +1,171 @@
using System.Diagnostics.CodeAnalysis;
using CoreGraphics;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
namespace Pixiview.iOS.Renderers.AppShellSection
{
public class AppShellNavBarAppearanceTracker : IShellNavBarAppearanceTracker
{
UIColor _defaultBarTint;
UIColor _defaultTint;
UIStringAttributes _defaultTitleAttributes;
float _shadowOpacity = float.MinValue;
CGColor _shadowColor;
public void ResetAppearance(UINavigationController controller)
{
if (_defaultTint != null)
{
var navBar = controller.NavigationBar;
navBar.TintColor = _defaultBarTint;
navBar.TintColor = _defaultTint;
navBar.TitleTextAttributes = _defaultTitleAttributes;
}
}
public void SetAppearance(UINavigationController controller, ShellAppearance appearance)
{
var background = appearance.BackgroundColor;
var foreground = appearance.ForegroundColor;
var titleColor = appearance.TitleColor;
var navBar = controller.NavigationBar;
if (_defaultTint == null)
{
_defaultBarTint = navBar.BarTintColor;
_defaultTint = navBar.TintColor;
_defaultTitleAttributes = navBar.TitleTextAttributes;
}
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
navBar.TintColor = UIColor.SecondaryLabelColor;
}
else
{
if (!background.IsDefault)
navBar.BarTintColor = background.ToUIColor();
if (!foreground.IsDefault)
navBar.TintColor = foreground.ToUIColor();
if (!titleColor.IsDefault)
{
navBar.TitleTextAttributes = new UIStringAttributes
{
ForegroundColor = titleColor.ToUIColor()
};
}
}
}
public void SetHasShadow(UINavigationController controller, bool hasShadow)
{
var navigationBar = controller.NavigationBar;
if (_shadowOpacity == float.MinValue)
{
// Don't do anything if user hasn't changed the shadow to true
if (!hasShadow)
return;
_shadowOpacity = navigationBar.Layer.ShadowOpacity;
_shadowColor = navigationBar.Layer.ShadowColor;
}
if (hasShadow)
{
navigationBar.Layer.ShadowColor = UIColor.Black.CGColor;
navigationBar.Layer.ShadowOpacity = 1.0f;
}
else
{
navigationBar.Layer.ShadowColor = _shadowColor;
navigationBar.Layer.ShadowOpacity = _shadowOpacity;
}
}
public void Dispose()
{
}
public void UpdateLayout(UINavigationController controller)
{
}
}
public class AppShellTabBarAppearanceTracker : IShellTabBarAppearanceTracker
{
UIColor _defaultBarTint;
UIColor _defaultTint;
UIColor _defaultUnselectedTint;
public void ResetAppearance(UITabBarController controller)
{
if (_defaultTint == null)
return;
var tabBar = controller.TabBar;
tabBar.BarTintColor = _defaultBarTint;
tabBar.TintColor = _defaultTint;
tabBar.UnselectedItemTintColor = _defaultUnselectedTint;
}
public void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
IShellAppearanceElement appearanceElement = appearance;
var backgroundColor = appearanceElement.EffectiveTabBarBackgroundColor;
var unselectedColor = appearanceElement.EffectiveTabBarUnselectedColor;
var tintColor = appearanceElement.EffectiveTabBarForegroundColor; // appearanceElement.EffectiveTabBarTitleColor;
var tabBar = controller.TabBar;
if (_defaultTint == null)
{
_defaultBarTint = tabBar.BarTintColor;
_defaultTint = tabBar.TintColor;
_defaultUnselectedTint = tabBar.UnselectedItemTintColor;
}
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
tabBar.TintColor = UIColor.LabelColor;
//tabBar.UnselectedItemTintColor = UIColor.TertiaryLabelColor;
}
else
{
if (!backgroundColor.IsDefault)
tabBar.BarTintColor = backgroundColor.ToUIColor();
if (!tintColor.IsDefault)
tabBar.TintColor = tintColor.ToUIColor();
if (!unselectedColor.IsDefault)
tabBar.UnselectedItemTintColor = unselectedColor.ToUIColor();
}
}
public void Dispose()
{
}
[SuppressMessage("Code Notifications", "XI0001:Notifies you with advices on how to use Apple APIs", Justification = "<Pending>")]
public void UpdateLayout(UITabBarController controller)
{
var tabBar = controller.TabBar;
if (tabBar != null && tabBar.Items != null && tabBar.Items.Length == 4)
{
var tabUser = tabBar.Items[0];
tabUser.Image = UIImage.FromBundle("IconUserRegular");
tabUser.SelectedImage = UIImage.FromBundle("IconUser");
var tabRecommend = tabBar.Items[1];
tabRecommend.Image = UIImage.FromBundle("IconSparklesRegular");
tabRecommend.SelectedImage = UIImage.FromBundle("IconSparkles");
var tabRank = tabBar.Items[2];
tabRank.Image = UIImage.FromBundle("IconSortRegular");
tabRank.SelectedImage = UIImage.FromBundle("IconSort");
var tabFavorite = tabBar.Items[3];
tabFavorite.Image = UIImage.FromBundle("IconBookmarkRegular");
tabFavorite.SelectedImage = UIImage.FromBundle("IconBookmark");
}
}
}
}

View File

@@ -0,0 +1,325 @@
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using CoreGraphics;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
namespace Pixiview.iOS.Renderers.AppShellSection
{
public class AppShellSectionRootHeader : UICollectionViewController, IAppearanceObserver, IShellSectionRootHeader
{
#region IAppearanceObserver
readonly Color _defaultBackgroundColor = new Color(0.964);
readonly Color _defaultForegroundColor = Color.Black;
readonly Color _defaultUnselectedColor = Color.Black.MultiplyAlpha(0.7);
void IAppearanceObserver.OnAppearanceChanged(ShellAppearance appearance)
{
if (appearance == null)
ResetAppearance();
else
SetAppearance(appearance);
}
protected virtual void ResetAppearance()
{
SetValues(_defaultBackgroundColor, _defaultForegroundColor, _defaultUnselectedColor);
}
protected virtual void SetAppearance(ShellAppearance appearance)
{
SetValues(appearance.BackgroundColor.IsDefault ? _defaultBackgroundColor : appearance.BackgroundColor,
appearance.ForegroundColor.IsDefault ? _defaultForegroundColor : appearance.ForegroundColor,
appearance.UnselectedColor.IsDefault ? _defaultUnselectedColor : appearance.UnselectedColor);
}
void SetValues(Color backgroundColor, Color foregroundColor, Color unselectedColor)
{
CollectionView.BackgroundColor = new Color(backgroundColor.R, backgroundColor.G, backgroundColor.B, .663).ToUIColor();
_bar.BackgroundColor = foregroundColor.ToUIColor();
bool reloadData = _selectedColor != foregroundColor || _unselectedColor != unselectedColor;
_selectedColor = foregroundColor;
_unselectedColor = unselectedColor;
if (reloadData)
CollectionView.ReloadData();
}
#endregion IAppearanceObserver
static readonly NSString CellId = new NSString("HeaderCell");
readonly IShellContext _shellContext;
UIView _bar;
UIView _bottomShadow;
Color _selectedColor;
Color _unselectedColor;
bool _isDisposed;
public AppShellSectionRootHeader(IShellContext shellContext) : base(new UICollectionViewFlowLayout())
{
_shellContext = shellContext;
}
public double SelectedIndex { get; set; }
public ShellSection ShellSection { get; set; }
IShellSectionController ShellSectionController => ShellSection;
public UIViewController ViewController => this;
public override bool CanMoveItem(UICollectionView collectionView, NSIndexPath indexPath)
{
return false;
}
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var reusedCell = (UICollectionViewCell)collectionView.DequeueReusableCell(CellId, indexPath);
if (!(reusedCell is ShellSectionHeaderCell headerCell))
return reusedCell;
var selectedItems = collectionView.GetIndexPathsForSelectedItems();
var shellContent = ShellSectionController.GetItems()[indexPath.Row];
headerCell.Label.Text = shellContent.Title;
headerCell.Label.SetNeedsDisplay();
headerCell.SelectedColor = _selectedColor.ToUIColor();
headerCell.UnSelectedColor = _unselectedColor.ToUIColor();
if (selectedItems.Length > 0 && selectedItems[0].Row == indexPath.Row)
headerCell.Selected = true;
else
headerCell.Selected = false;
return headerCell;
}
public override nint GetItemsCount(UICollectionView collectionView, nint section)
{
return ShellSectionController.GetItems().Count;
}
public override void ItemDeselected(UICollectionView collectionView, NSIndexPath indexPath)
{
if (CollectionView.CellForItem(indexPath) is ShellSectionHeaderCell cell)
cell.Label.TextColor = _unselectedColor.ToUIColor();
}
public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)
{
var row = indexPath.Row;
var item = ShellSectionController.GetItems()[row];
if (item != ShellSection.CurrentItem)
ShellSection.SetValueFromRenderer(ShellSection.CurrentItemProperty, item);
if (CollectionView.CellForItem(indexPath) is ShellSectionHeaderCell cell)
cell.Label.TextColor = _selectedColor.ToUIColor();
}
public override nint NumberOfSections(UICollectionView collectionView)
{
return 1;
}
public override bool ShouldSelectItem(UICollectionView collectionView, NSIndexPath indexPath)
{
var row = indexPath.Row;
var item = ShellSectionController.GetItems()[row];
IShellController shellController = _shellContext.Shell;
if (item == ShellSection.CurrentItem)
return true;
return shellController.ProposeNavigation(ShellNavigationSource.ShellContentChanged, (ShellItem)ShellSection.Parent, ShellSection, item, ShellSection.Stack, true);
}
public override void ViewDidLayoutSubviews()
{
if (_isDisposed)
return;
base.ViewDidLayoutSubviews();
LayoutBar();
_bottomShadow.Frame = new CGRect(0, CollectionView.Frame.Bottom, CollectionView.Frame.Width, 0.5);
}
public override void ViewDidLoad()
{
if (_isDisposed)
return;
base.ViewDidLoad();
CollectionView.ScrollsToTop = false;
CollectionView.Bounces = false;
CollectionView.AlwaysBounceHorizontal = false;
CollectionView.ShowsHorizontalScrollIndicator = false;
CollectionView.ClipsToBounds = false;
_bar = new UIView(new CGRect(0, 0, 20, 20));
_bar.Layer.ZPosition = 9001; //its over 9000!
CollectionView.AddSubview(_bar);
_bottomShadow = new UIView(new CGRect(0, 0, 10, 1))
{
BackgroundColor = Color.Black.MultiplyAlpha(0.3).ToUIColor()
};
_bottomShadow.Layer.ZPosition = 9002;
CollectionView.AddSubview(_bottomShadow);
var flowLayout = Layout as UICollectionViewFlowLayout;
flowLayout.ScrollDirection = UICollectionViewScrollDirection.Horizontal;
flowLayout.MinimumInteritemSpacing = 0;
flowLayout.MinimumLineSpacing = 0;
flowLayout.EstimatedItemSize = new CGSize(70, 35);
CollectionView.RegisterClassForCell(GetCellType(), CellId);
((IShellController)_shellContext.Shell).AddAppearanceObserver(this, ShellSection);
ShellSectionController.ItemsCollectionChanged += OnShellSectionItemsChanged;
UpdateSelectedIndex();
ShellSection.PropertyChanged += OnShellSectionPropertyChanged;
}
protected virtual Type GetCellType()
{
return typeof(ShellSectionHeaderCell);
}
protected override void Dispose(bool disposing)
{
if (_isDisposed)
return;
if (disposing)
{
((IShellController)_shellContext.Shell).RemoveAppearanceObserver(this);
ShellSectionController.ItemsCollectionChanged -= OnShellSectionItemsChanged;
ShellSection.PropertyChanged -= OnShellSectionPropertyChanged;
ShellSection = null;
_bar.RemoveFromSuperview();
RemoveFromParentViewController();
_bar.Dispose();
_bar = null;
}
_isDisposed = true;
base.Dispose(disposing);
}
protected void LayoutBar()
{
if (SelectedIndex < 0)
return;
if (ShellSectionController.GetItems().IndexOf(ShellSection.CurrentItem) != SelectedIndex)
return;
var layout = CollectionView.GetLayoutAttributesForItem(NSIndexPath.FromItemSection((int)SelectedIndex, 0));
if (layout == null)
return;
var frame = layout.Frame;
if (_bar.Frame.Height != 2)
{
_bar.Frame = new CGRect(frame.X, frame.Bottom - 2, frame.Width, 2);
}
else
{
UIView.Animate(.25, () => _bar.Frame = new CGRect(frame.X, frame.Bottom - 2, frame.Width, 2));
}
}
protected virtual void OnShellSectionPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == ShellSection.CurrentItemProperty.PropertyName)
{
UpdateSelectedIndex();
}
}
protected virtual void UpdateSelectedIndex(bool animated = false)
{
if (ShellSection.CurrentItem == null)
return;
SelectedIndex = ShellSectionController.GetItems().IndexOf(ShellSection.CurrentItem);
if (SelectedIndex < 0)
return;
LayoutBar();
CollectionView.SelectItem(NSIndexPath.FromItemSection((int)SelectedIndex, 0), false, UICollectionViewScrollPosition.CenteredHorizontally);
}
void OnShellSectionItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_isDisposed)
return;
CollectionView.ReloadData();
}
public class ShellSectionHeaderCell : UICollectionViewCell
{
public UIColor SelectedColor { get; set; }
public UIColor UnSelectedColor { get; set; }
public ShellSectionHeaderCell()
{
}
[Export("initWithFrame:")]
public ShellSectionHeaderCell(CGRect frame) : base(frame)
{
Label = new UILabel
{
TextAlignment = UITextAlignment.Center,
Font = UIFont.BoldSystemFontOfSize(14)
};
ContentView.AddSubview(Label);
}
public override bool Selected
{
get => base.Selected;
set
{
base.Selected = value;
Label.TextColor = value ? SelectedColor : UnSelectedColor;
}
}
public UILabel Label { get; }
public override void LayoutSubviews()
{
base.LayoutSubviews();
Label.Frame = Bounds;
}
public override CGSize SizeThatFits(CGSize size)
{
return new CGSize(Label.SizeThatFits(size).Width + 30, 35);
}
}
}
}

View File

@@ -0,0 +1,87 @@
using CoreAnimation;
using Pixiview.iOS.Renderers;
using Pixiview.UI;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(BlurryPanel), typeof(BlurryPanelRenderer))]
namespace Pixiview.iOS.Renderers
{
public class BlurryPanelRenderer : ViewRenderer<BlurryPanel, UIVisualEffectView>
{
private UIVisualEffectView nativeControl;
private CALayer bottom;
protected override void OnElementChanged(ElementChangedEventArgs<BlurryPanel> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
if (bottom != null)
{
if (bottom.SuperLayer != null)
{
bottom.RemoveFromSuperLayer();
}
bottom.Dispose();
bottom = null;
}
}
if (e.NewElement != null)
{
e.NewElement.BackgroundColor = Color.Default;
if (Control == null)
{
var blur = UIBlurEffect.FromStyle(UIBlurEffectStyle.SystemMaterial);
nativeControl = new UIVisualEffectView(blur)
{
Frame = Frame
};
SetNativeControl(nativeControl);
}
}
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
if (nativeControl != null)
{
if (bottom == null)
{
bottom = new CALayer
{
BackgroundColor = UIColor.White.CGColor,
ShadowColor = UIColor.Black.CGColor,
ShadowOpacity = 1.0f
};
}
if (bottom.SuperLayer == null)
{
nativeControl.Layer.InsertSublayer(bottom, 0);
}
bottom.Frame = new CoreGraphics.CGRect(0, Frame.Height - 5, Frame.Width, 5);
nativeControl.Frame = Frame;
}
}
protected override void Dispose(bool disposing)
{
if (bottom != null)
{
if (bottom.SuperLayer != null)
{
bottom.RemoveFromSuperLayer();
}
bottom.Dispose();
bottom = null;
}
base.Dispose(disposing);
}
}
}

View File

@@ -0,0 +1,51 @@
using Pixiview.iOS.Renderers;
using Pixiview.UI;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(CardView), typeof(CardViewRenderer))]
namespace Pixiview.iOS.Renderers
{
public class CardViewRenderer : VisualElementRenderer<CardView>
{
protected override void OnElementChanged(ElementChangedEventArgs<CardView> e)
{
base.OnElementChanged(e);
var layer = Layer;
var element = e.NewElement;
if (layer != null && element != null)
{
var cornerRadius = element.CornerRadius;
if (cornerRadius > 0)
{
layer.CornerRadius = cornerRadius;
}
//if (element.BackgroundColor != default)
//{
// layer.BackgroundColor = element.BackgroundColor.ToCGColor();
//}
var shadowColor = element.ShadowColor;
if (shadowColor != default)
{
layer.ShadowColor = shadowColor.ToCGColor();
layer.ShadowOpacity = 1f;
var radius = element.ShadowRadius;
if (radius > 0)
{
layer.ShadowRadius = radius;
}
layer.ShadowOffset = element.ShadowOffset.ToSizeF();
}
else
{
layer.ShadowOpacity = 0f;
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
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);
var layer = Layer;
if (layer != null)
{
layer.MasksToBounds = true;
}
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
var control = Control;
if (control != null)
{
control.Layer.CornerRadius = control.Frame.Size.Width / 2;
}
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using Foundation;
using Pixiview.iOS.Renderers;
using Pixiview.Login;
using Pixiview.Utils;
using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace Pixiview.iOS.Renderers
{
public class HybridWebViewRenderer : WkWebViewRenderer
{
public HybridWebViewRenderer() : this(new WKWebViewConfiguration())
{
}
public HybridWebViewRenderer(WKWebViewConfiguration config) : base(config)
{
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement is HybridWebView webView)
{
string url = webView.Uri;
//Configuration.SetUrlSchemeHandler
CustomUserAgent = webView.UserAgent;
NavigationDelegate = new PixivNavigationDelegate(webView);
LoadRequest(new NSUrlRequest(NSUrl.FromString(url)));
}
}
private class PixivNavigationDelegate : WKNavigationDelegate
{
private readonly HybridWebView hybridWebView;
public PixivNavigationDelegate(HybridWebView hybrid)
{
hybridWebView = hybrid;
}
public override void DecidePolicy(WKWebView webView, WKNavigationResponse navigationResponse, Action<WKNavigationResponsePolicy> decisionHandler)
{
var url = webView.Url;
if (url.Host == "www.pixiv.net" && url.Path == "/")
{
if (navigationResponse.Response is NSHttpUrlResponse response)
{
if (response.AllHeaderFields.TryGetValue(new NSString("x-userid"), out var val))
{
Configs.SetUserId(val.ToString(), true);
}
}
}
decisionHandler(WKNavigationResponsePolicy.Allow);
}
public override async void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
var url = webView.Url;
if (url.Host == "www.pixiv.net" && (url.Path == "/" || url.Path == "/en/"))
{
var store = webView.Configuration.WebsiteDataStore.HttpCookieStore;
var result = await Configs.RequestCookieContainer(store);
if (result && hybridWebView != null)
{
hybridWebView.OnLoginHandle();
}
}
}
}
}
}

View File

@@ -0,0 +1,22 @@
using Pixiview.iOS.Renderers;
using Pixiview.UI;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(OptionEntry), typeof(OptionEntryRenderer))]
namespace Pixiview.iOS.Renderers
{
public class OptionEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
var control = Control;
if (control != null)
{
control.BorderStyle = UIKit.UITextBorderStyle.None;
}
}
}
}

View File

@@ -0,0 +1,22 @@
using Pixiview.iOS.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(Picker), typeof(OptionPickerRenderer))]
namespace Pixiview.iOS.Renderers
{
public class OptionPickerRenderer : PickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
var control = Control;
if (control != null)
{
control.TextAlignment = UIKit.UITextAlignment.Right;
control.BorderStyle = UIKit.UITextBorderStyle.None;
}
}
}
}

View File

@@ -0,0 +1,56 @@
using CoreAnimation;
using Pixiview.iOS.Renderers;
using Pixiview.UI;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(RoundImage), typeof(RoundImageRenderer))]
namespace Pixiview.iOS.Renderers
{
public class RoundImageRenderer : ImageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
var layer = Layer;
if (layer != null && e.NewElement is RoundImage image)
{
bool flag = false;
if (image.CornerRadius > 0)
{
layer.CornerRadius = image.CornerRadius;
flag = true;
}
var mask = image.CornerMasks;
if (mask != CornerMask.None)
{
var m = default(CACornerMask);
if ((mask & CornerMask.LeftTop) == CornerMask.LeftTop)
{
m |= CACornerMask.MinXMinYCorner;
}
if ((mask & CornerMask.RightTop) == CornerMask.RightTop)
{
m |= CACornerMask.MaxXMinYCorner;
}
if ((mask & CornerMask.LeftBottom) == CornerMask.LeftBottom)
{
m |= CACornerMask.MinXMaxYCorner;
}
if ((mask & CornerMask.RightBottom) == CornerMask.RightBottom)
{
m |= CACornerMask.MaxXMaxYCorner;
}
layer.MaskedCorners = m;
flag = true;
}
if (flag)
{
layer.MasksToBounds = true;
}
}
}
}
}

View File

@@ -0,0 +1,56 @@
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);
var layer = Layer;
if (layer != null && e.NewElement is RoundLabel label)
{
var radius = label.CornerRadius;
if (radius > 0)
{
layer.CornerRadius = radius;
//layer.MasksToBounds = true;
}
else
{
layer.CornerRadius = 0;
}
if (layer.BackgroundColor != default)
{
layer.BackgroundColor = label.BackgroundColor.ToCGColor();
}
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == RoundLabel.CornerRadiusProperty.PropertyName)
{
var layer = Layer;
if (layer != null && Element is RoundLabel label)
{
var radius = label.CornerRadius;
if (radius > 0)
{
layer.CornerRadius = radius;
layer.BackgroundColor = label.BackgroundColor.ToCGColor();
//layer.MasksToBounds = true;
}
}
}
}
}
}

View File

@@ -0,0 +1,156 @@
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using Pixiview.iOS.Renderers;
using Pixiview.UI;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(SegmentedControl), typeof(SegmentedControlRenderer))]
namespace Pixiview.iOS.Renderers
{
[SuppressMessage("Code Notifications", "XI0002:Notifies you from using newer Apple APIs when targeting an older OS version", Justification = "<Pending>")]
public class SegmentedControlRenderer : ViewRenderer<SegmentedControl, UISegmentedControl>
{
private UISegmentedControl nativeControl;
protected override void OnElementChanged(ElementChangedEventArgs<SegmentedControl> e)
{
base.OnElementChanged(e);
var element = Element;
if (Control == null && element != null)
{
nativeControl = new UISegmentedControl();
for (var i = 0; i < element.Children.Count; i++)
{
nativeControl.InsertSegment(element.Children[i].Text, i, false);
}
nativeControl.Enabled = element.IsEnabled;
//nativeControl.BackgroundColor = element.BackgroundColor.ToUIColor();
nativeControl.SelectedSegmentTintColor = GetTintColor(element);
SetTextColor();
nativeControl.SelectedSegment = element.SelectedSegmentIndex;
SetNativeControl(nativeControl);
}
if (e.OldElement != null)
{
if (nativeControl != null)
{
nativeControl.ValueChanged -= NativeControl_ValueChanged;
}
}
if (e.NewElement != null)
{
nativeControl.ValueChanged += NativeControl_ValueChanged;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var element = Element;
if (nativeControl == null || element == null)
{
return;
}
switch (e.PropertyName)
{
case "Renderer":
element.SendValueChanged();
break;
//case nameof(element.BackgroundColor):
// nativeControl.BackgroundColor = element.BackgroundColor.ToUIColor();
// break;
case nameof(element.SelectedSegmentIndex):
nativeControl.SelectedSegment = element.SelectedSegmentIndex;
break;
case nameof(element.TintColor):
nativeControl.SelectedSegmentTintColor = GetTintColor(element);
break;
case nameof(element.IsEnabled):
nativeControl.Enabled = element.IsEnabled;
nativeControl.SelectedSegmentTintColor = GetTintColor(element);
break;
case nameof(element.SelectedTextColor):
SetTextColor();
break;
}
}
private void SetTextColor()
{
//var color = Element.SelectedTextColor;
//UIColor c = color == default ? UIColor.LabelColor : color.ToUIColor();
UIColor c = UIColor.LabelColor;
var attribute = new UITextAttributes
{
TextColor = c
};
nativeControl.SetTitleTextAttributes(attribute, UIControlState.Selected);
attribute = new UITextAttributes
{
TextColor = c.ColorWithAlpha(.6f)
};
nativeControl.SetTitleTextAttributes(attribute, UIControlState.Normal);
}
private UIColor GetTintColor(SegmentedControl element)
{
if (element.IsEnabled)
{
//var tintColor = element.TintColor;
//if (tintColor == default)
//{
return UIColor.SystemGray6Color;
//}
//else
//{
// return tintColor.ToUIColor().ColorWithAlpha(.3f);
//}
}
else
{
//var disabledColor = element.DisabledColor;
//if (disabledColor == default)
//{
return UIColor.SecondaryLabelColor;
//}
//else
//{
// return disabledColor.ToUIColor();
//}
}
}
private void NativeControl_ValueChanged(object sender, EventArgs e)
{
Element.SelectedSegmentIndex = (int)nativeControl.SelectedSegment;
}
protected override void Dispose(bool disposing)
{
if (nativeControl != null)
{
nativeControl.ValueChanged -= NativeControl_ValueChanged;
nativeControl.Dispose();
nativeControl = null;
}
base.Dispose(disposing);
}
}
}

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6245" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="X5k-f2-b5h">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6238"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="gAE-YM-kbH">
<objects>
<viewController id="X5k-f2-b5h" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Y8P-hJ-Z43"/>
<viewControllerLayoutGuide type="bottom" id="9ZL-r4-8FZ"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="yd7-JS-zBw">
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" id="197" image="LauncherLogo" translatesAutoresizingMaskIntoConstraints="NO">
<rect key="frame" x="59" y="356" width="256" height="100"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
</accessibility>
<constraints>
<constraint id="399" firstAttribute="height" constant="100"/>
<constraint id="400" firstAttribute="width" constant="256"/>
</constraints>
</imageView>
</subviews>
<constraints>
<constraint id="397" firstItem="197" firstAttribute="centerY" secondItem="yd7-JS-zBw" secondAttribute="centerY"/>
<constraint id="398" firstItem="197" firstAttribute="centerX" secondItem="yd7-JS-zBw" secondAttribute="centerX"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="XAI-xm-WK6" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="349" y="339"/>
</scene>
</scenes>
<resources>
<image name="LauncherLogo" width="256" height="100"/>
</resources>
</document>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB