Browse Source
Browser StaticWebAssets sdk support (#14225 )
* Property support StaticWebAssets SDK when it's available
* Fix browser issue with dispatcher used before initialization
* Use RequestAnimationFrame instead of WebEmbeddableControlRoot hack
* Always include both types of assets by default, as I couldn't find a reliable way to detect project capabilities properly
* Remove "WasmRuntimeAssetsLocation" override, instead let users use default value set by .NET SDK
* Revert "Fix browser issue with dispatcher used before initialization"
This reverts commit fc43c7e3d5 .
* Add AvaloniaAllowWebGl2 prop
* What
scroll_transition_repro
Max Katz
2 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with
68 additions and
156 deletions
.gitignore
samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj
samples/ControlCatalog.Browser/ControlCatalog.Browser.csproj
samples/MobileSandbox.Browser/MobileSandbox.Browser.csproj
samples/MobileSandbox.Browser/Roots.xml
src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
src/Browser/Avalonia.Browser/Avalonia.Browser.props
src/Browser/Avalonia.Browser/AvaloniaView.cs
src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
src/Browser/Avalonia.Browser/WebEmbeddableControlRoot.cs
src/Browser/Avalonia.Browser/build/Avalonia.Browser.props
src/Browser/Avalonia.Browser/build/Avalonia.Browser.targets
src/Browser/Avalonia.Browser/build/Microsoft.AspNetCore.StaticWebAssets.props
src/Browser/Avalonia.Browser/build/interop.js
src/Browser/Avalonia.Browser/webapp/build.js
@ -218,3 +218,4 @@ src/Browser/Avalonia.Browser.Blazor/webapp/package-lock.json
src/Browser/Avalonia.Browser.Blazor/wwwroot
src/Browser/Avalonia.Browser/wwwroot
api/diff
src/Browser/Avalonia.Browser/staticwebassets
@ -22,8 +22,8 @@
<Import Project="..\..\build\ReferenceCoreLibraries.props" />
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\src\Browser\Avalonia.Browser\Avalonia.Browser.props" />
<Import Project="..\..\src\Browser\Avalonia.Browser\Avalonia.Browser.targets" />
<Import Project="..\..\src\Browser\Avalonia.Browser\build\ Avalonia.Browser.props" />
<Import Project="..\..\src\Browser\Avalonia.Browser\build\ Avalonia.Browser.targets" />
</Project>
@ -1,6 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../src/Browser/Avalonia.Browser/Avalonia.Browser.props" />
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
@ -8,6 +6,7 @@
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<MSBuildEnableWorkloadResolver>true</MSBuildEnableWorkloadResolver>
<WasmRuntimeAssetsLocation>./</WasmRuntimeAssetsLocation>
</PropertyGroup>
<ItemGroup>
@ -20,5 +19,6 @@
<WasmExtraFilesToDeploy Include="AppBundle/**" />
</ItemGroup>
<Import Project="../../src/Browser/Avalonia.Browser/Avalonia.Browser.targets" />
<Import Project="../../src/Browser/Avalonia.Browser/build/Avalonia.Browser.props" />
<Import Project="../../src/Browser/Avalonia.Browser/build/Avalonia.Browser.targets" />
</Project>
@ -7,25 +7,10 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<MSBuildEnableWorkloadResolver>true</MSBuildEnableWorkloadResolver>
<WasmBuildNative>true</WasmBuildNative>
<EmccFlags>-sVERBOSE -sERROR_ON_UNDEFINED_SYMBOLS=0</EmccFlags >
<WasmRuntimeAssetsLocation>./</WasmRuntimeAssetsLocation >
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<RunAOTCompilation>true</RunAOTCompilation>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
<WasmBuildNative>true</WasmBuildNative>
<InvariantGlobalization>true</InvariantGlobalization>
<EmccCompileOptimizationFlag>-O2</EmccCompileOptimizationFlag>
<EmccLinkOptimizationFlag>-O2</EmccLinkOptimizationFlag>
</PropertyGroup>
<ItemGroup>
<TrimmerRootDescriptor Include="Roots.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\..\src\Browser\Avalonia.Browser\Avalonia.Browser.csproj" />
<ProjectReference Include="..\MobileSandbox\MobileSandbox.csproj" />
</ItemGroup>
@ -38,6 +23,6 @@
<WasmExtraFilesToDeploy Include="app.css" />
</ItemGroup>
<Import Project="..\..\src\Browser\Avalonia.Browser\Avalonia.Browser.props" />
<Import Project="..\..\src\Browser\Avalonia.Browser\Avalonia.Browser.targets" />
<Import Project="..\..\src\Browser\Avalonia.Browser\build\ Avalonia.Browser.props" />
<Import Project="..\..\src\Browser\Avalonia.Browser\build\ Avalonia.Browser.targets" />
</Project>
@ -1,7 +0,0 @@
<linker >
<assembly fullname= "MobileSandbox" preserve= "All" />
<assembly fullname= "MobileSandbox.Browser" preserve= "All" />
<assembly fullname= "Avalonia.Themes.Fluent" preserve= "All" />
<assembly fullname= "Avalonia.Themes.Simple" preserve= "All" />
<assembly fullname= "Avalonia.Controls.ColorPicker" preserve= "All" />
</linker>
@ -1,8 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor ">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ResolveStaticWebAssetsInputsDependsOn>_IncludeGeneratedAvaloniaStaticFiles;$(ResolveStaticWebAssetsInputsDependsOn)</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<ItemGroup>
@ -20,22 +19,4 @@
<ItemGroup>
<ProjectReference Include="../Avalonia.Browser/Avalonia.Browser.csproj" />
</ItemGroup>
<Target Name="_IncludeGeneratedAvaloniaStaticFiles">
<ItemGroup>
<_AvaloniaWebAssets Include="$(MSBuildThisFileDirectory)../Avalonia.Browser/wwwroot/**/*.*" />
</ItemGroup>
<DefineStaticWebAssets SourceId="$(PackageId)"
SourceType="Computed"
AssetKind="All"
AssetRole="Primary"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest"
ContentRoot="$(MSBuildThisFileDirectory)../Avalonia.Browser/wwwroot/"
BasePath="_content/$(PackageId)"
CandidateAssets="@(_AvaloniaWebAssets)"
RelativePathFilter="**.js">
<Output TaskParameter="Assets" ItemName="StaticWebAsset" />
</DefineStaticWebAssets>
</Target>
</Project>
@ -17,9 +17,6 @@ public static class BlazorAppBuilder
/// <param name="options">Browser backend specific options.</param>
public static async Task StartBlazorAppAsync ( this AppBuilder builder , BrowserPlatformOptions ? options = null )
{
options ? ? = new BrowserPlatformOptions ( ) ;
options . FrameworkAssetPathResolver ? ? = filePath = > $"/_content/Avalonia.Browser.Blazor/{filePath}" ;
builder = await BrowserAppBuilder . PreSetupBrowser ( builder , options ) ;
builder . SetupWithLifetime ( new BlazorSingleViewLifetime ( ) ) ;
@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
@ -22,21 +21,26 @@
</ItemGroup>
<ItemGroup>
<Content Include="*.props">
<!-- See https://github.com/dotnet/sdk/blob/9d4d2c4ca35b0856af7df63d6a38b3259aa6917c/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Pack.targets#L64-L66 -->
<Content Include="build\Microsoft.AspNetCore.StaticWebAssets.props">
<Pack>true</Pack>
<PackagePath>build/</PackagePath>
</Content>
<Content Include="*.targets">
<Content Include="build\Avalonia.Browser.props">
<Pack>true</Pack>
<PackagePath>build/;buildTransitive/;buildMultiTargeting/</PackagePath>
</Content>
<Content Include="build\Avalonia.Browser.targets">
<Pack>true</Pack>
<PackagePath>build/;buildTransitive/</PackagePath>
</Content>
<Content Include="interop.js">
<Content Include="build\ interop.js">
<Pack>true</Pack>
<PackagePath>build/interop.js;buildTransitive/interop.js</PackagePath>
</Content>
<Content Include="wwwroot /**/*.*">
<Content Include="staticwebassets /**/*.*">
<Pack>true</Pack>
<PackagePath>build/wwwroot;buildTransitive/wwwroot </PackagePath>
<PackagePath>staticwebassets/ </PackagePath>
</Content>
</ItemGroup>
@ -1,10 +0,0 @@
<Project>
<PropertyGroup>
<ShouldIncludeAvaloniaJavaScript Condition=" '$(ShouldIncludeAvaloniaJavaScript)' == '' ">True</ShouldIncludeAvaloniaJavaScript>
<ShouldIncludeNativeSkiaSharp Condition=" '$(ShouldIncludeNativeSkiaSharp)' == '' ">True</ShouldIncludeNativeSkiaSharp>
<ShouldIncludeNativeHarfBuzzSharp Condition=" '$(ShouldIncludeNativeHarfBuzzSharp)' == '' ">True</ShouldIncludeNativeHarfBuzzSharp>
<!-- .NET 8 changes default location for dotnet script to the "_framework" subfolder, -->
<!-- But this change would introduce a breaking change to Avalonia users, so we revert it back to the .NET 7 state. -->
<WasmRuntimeAssetsLocation Condition="'$(WasmRuntimeAssetsLocation)' == ''">./</WasmRuntimeAssetsLocation>
</PropertyGroup>
</Project>
@ -71,26 +71,18 @@ namespace Avalonia.Browser
_ splash = DomHelper . GetElementById ( "avalonia-splash" ) ;
_ topLevelImpl = new BrowserTopLevelImpl ( this , _ containerElement ) ;
_ topLevel = new WebEmbeddableControlRoot ( _ topLevelImpl , ( ) = >
{
Dispatcher . UIThread . Post ( ( ) = >
{
if ( _ splash ! = null )
{
DomHelper . AddCssClass ( _ splash , "splash-close" ) ;
}
} ) ;
} ) ;
_ topLevelImpl . SetCssCursor = ( cursor ) = >
{
InputHelper . SetCursor ( _ containerElement , cursor ) ;
} ;
_ topLevel = new EmbeddableControlRoot ( _ topLevelImpl ) ;
_ topLevel . Prepare ( ) ;
_ topLevel . Renderer . Start ( ) ;
if ( _ splash ! = null )
{
_ topLevel . RequestAnimationFrame ( _ = > DomHelper . AddCssClass ( _ splash , "splash-close" ) ) ;
}
InputHelper . InitializeBackgroundHandlers ( ) ;
@ -49,5 +49,5 @@ internal class BrowserSingleViewLifetime : ISingleViewApplicationLifetime, IActi
public event EventHandler < ActivatedEventArgs > ? Deactivated ;
public bool TryLeaveBackground ( ) = > false ;
public bool TryEnterBackground ( ) = > tru e;
public bool TryEnterBackground ( ) = > fals e;
}
@ -1,68 +0,0 @@
using System ;
using Avalonia.Controls.Embedding ;
using Avalonia.Media ;
using Avalonia.Platform ;
using Avalonia.Rendering.SceneGraph ;
namespace Avalonia.Browser
{
internal class WebEmbeddableControlRoot : EmbeddableControlRoot
{
class SplashScreenCloseCustomDrawingOperation : ICustomDrawOperation
{
private bool _ hasRendered ;
private Action _ onFirstRender ;
public SplashScreenCloseCustomDrawingOperation ( Action onFirstRender )
{
_ onFirstRender = onFirstRender ;
}
public Rect Bounds = > default ;
public bool HasRendered = > _ hasRendered ;
public void Dispose ( )
{
}
public bool Equals ( ICustomDrawOperation ? other )
{
return false ;
}
public bool HitTest ( Point p )
{
return false ;
}
public void Render ( ImmediateDrawingContext context )
{
_ hasRendered = true ;
_ onFirstRender ( ) ;
}
}
public WebEmbeddableControlRoot ( ITopLevelImpl impl , Action onFirstRender ) : base ( impl )
{
_ splashCloseOp = new SplashScreenCloseCustomDrawingOperation ( ( ) = >
{
_ splashCloseOp = null ;
onFirstRender ( ) ;
} ) ;
}
private SplashScreenCloseCustomDrawingOperation ? _ splashCloseOp ;
public override void Render ( DrawingContext context )
{
base . Render ( context ) ;
if ( _ splashCloseOp ! = null )
{
context . Custom ( _ splashCloseOp ) ;
}
}
}
}
@ -0,0 +1,13 @@
<Project>
<PropertyGroup>
<AvaloniaAllowWebGl2 Condition="'$(AvaloniaAllowWebGl2)' == ''">true</AvaloniaAllowWebGl2>
<ShouldIncludeAvaloniaAssets Condition=" '$(ShouldIncludeAvaloniaAssets)' == '' ">True</ShouldIncludeAvaloniaAssets>
<ShouldIncludeAvaloniaLegacyAssets Condition=" '$(ShouldIncludeAvaloniaLegacyAssets)' == '' AND '$(ShouldIncludeAvaloniaAssets)' == 'True'">True</ShouldIncludeAvaloniaLegacyAssets>
<ShouldIncludeAvaloniaStaticAssets Condition=" '$(ShouldIncludeAvaloniaStaticAssets)' == '' AND '$(ShouldIncludeAvaloniaAssets)' == 'True'">True</ShouldIncludeAvaloniaStaticAssets>
<ShouldIncludeNativeSkiaSharp Condition=" '$(ShouldIncludeNativeSkiaSharp)' == '' ">True</ShouldIncludeNativeSkiaSharp>
<ShouldIncludeNativeHarfBuzzSharp Condition=" '$(ShouldIncludeNativeHarfBuzzSharp)' == '' ">True</ShouldIncludeNativeHarfBuzzSharp>
</PropertyGroup>
<Import Project="$(MSBuildThisFileDirectory)/../build/Microsoft.AspNetCore.StaticWebAssets.props" />
</Project>
@ -1,12 +1,14 @@
<Project>
<PropertyGroup>
<EmccExtraLDFlags>$(EmccExtraLDFlags) --js-library="$(MSBuildThisFileDirectory)/interop.js"</EmccExtraLDFlags>
<EmccFlags>$(EmccExtraLDFlags) -sERROR_ON_UNDEFINED_SYMBOLS=0</EmccFlags>
<EmccFlags>$(EmccFlags) -sERROR_ON_UNDEFINED_SYMBOLS=0</EmccFlags>
<EmccFlags Condition="'$(AvaloniaAllowWebGl2)' == 'true'">$(EmccFlags) -sUSE_WEBGL2=1 -sMAX_WEBGL_VERSION=2 -lGL </EmccFlags>
</PropertyGroup>
<ItemGroup>
<WasmExtraFilesToDeploy Condition="'$(WasmRuntimeAssetsLocation)' == ''" Include="$(MSBuildThisFileDirectory)/wwwroot/**/*.*" />
<WasmExtraFilesToDeploy Condition="'$(WasmRuntimeAssetsLocation)' != ''" Include="$(MSBuildThisFileDirectory)/wwwroot/**/*.*" TargetPath="$(WasmRuntimeAssetsLocation)/%(FileName)%(Extension)" />
<!-- Fallback for applications without StaticWebAssetsEnabled (legacy WASM SDK) -->
<ItemGroup Condition="'$(ShouldIncludeAvaloniaLegacyAssets)' == 'True'">
<WasmExtraFilesToDeploy Condition="'$(WasmRuntimeAssetsLocation)' == ''" Include="$(MSBuildThisFileDirectory)/../staticwebassets/**/*.*" />
<WasmExtraFilesToDeploy Condition="'$(WasmRuntimeAssetsLocation)' != ''" Include="$(MSBuildThisFileDirectory)/../staticwebassets/**/*.*" TargetPath="$(WasmRuntimeAssetsLocation)/%(FileName)%(Extension)" />
</ItemGroup>
<PropertyGroup Condition="'$(ShouldIncludeNativeSkiaSharp)' == 'True' or '$(ShouldIncludeNativeHarfBuzzSharp)' == 'True'">
@ -0,0 +1,22 @@
<Project>
<PropertyGroup>
<_AvaloniaWebAssetsFolder>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)../staticwebassets/))</_AvaloniaWebAssetsFolder>
</PropertyGroup>
<ItemGroup Condition="'$(ShouldIncludeAvaloniaStaticAssets)' == 'True'">
<!-- This file repricates how StaticWebAsset SDK generates static web assets for Blazor nuget packages, which we don't use here. -->
<_AvaloniaWebAssets Include="$(_AvaloniaWebAssetsFolder)**/*.*" />
<StaticWebAsset Include="@(_AvaloniaWebAssets)">
<SourceType>Package</SourceType>
<SourceId>Avalonia.Browser</SourceId>
<ContentRoot>$(_AvaloniaWebAssetsFolder)</ContentRoot>
<BasePath>/</BasePath>
<RelativePath>$(WasmRuntimeAssetsLocation)/%(FileName)%(Extension)</RelativePath>
<AssetKind>All</AssetKind>
<AssetMode>All</AssetMode>
<AssetRole>Primary</AssetRole>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<OriginalItemSpec>$(_AvaloniaWebAssetsFolder)%(FileName)%(Extension)</OriginalItemSpec>
</StaticWebAsset>
</ItemGroup>
</Project>
@ -4,7 +4,7 @@ require("esbuild").build({
"./modules/storage.ts" ,
"./modules/sw.ts"
] ,
outdir : "../wwwroot " ,
outdir : "../staticwebassets " ,
bundle : true ,
minify : true ,
format : "esm" ,