Browse Source

Add tv support to form factor (#14194)

* add tv support to form factor

* Resolve comments and add chromium book

* Add some documentation

---------

Co-authored-by: Max Katz <maxkatz6@outlook.com>
pull/14226/head
Omid Mafakher 2 years ago
committed by GitHub
parent
commit
a6918116bd
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      samples/ControlCatalog/Pages/PlatformInfoPage.xaml
  2. 2
      src/Android/Avalonia.Android/AndroidPlatform.cs
  3. 52
      src/Android/Avalonia.Android/AndroidRuntimePlatform.cs
  4. 6
      src/Avalonia.Base/Platform/IRuntimePlatform.cs
  5. 6
      src/Browser/Avalonia.Browser/BrowserRuntimePlatform.cs
  6. 5
      src/Browser/Avalonia.Browser/Interop/AvaloniaModule.cs
  7. 4
      src/Browser/Avalonia.Browser/webapp/modules/avalonia/caniuse.ts
  8. 22
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnFormFactorExtension.cs
  9. 7
      src/Tizen/Avalonia.Tizen/TizenApplicationExtensions.cs
  10. 38
      src/Tizen/Avalonia.Tizen/TizenRuntimePlatform.cs

3
samples/ControlCatalog/Pages/PlatformInfoPage.xaml

@ -19,6 +19,9 @@
<Border Height="100" Width="100" Background="{OnFormFactor Gray, Mobile=Green}">
<TextBlock Text="Mobile" />
</Border>
<Border Height="100" Width="100" Background="{OnFormFactor Gray, TV=Green}">
<TextBlock Text="Tv" />
</Border>
</StackPanel>
<WrapPanel>
<Border Height="100" Width="100" Background="{OnPlatform Gray, Windows=Green}">

2
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -20,7 +20,7 @@ namespace Avalonia
public static AppBuilder UseAndroid(this AppBuilder builder)
{
return builder
.UseStandardRuntimePlatformSubsystem()
.UseAndroidRuntimePlatformSubsystem()
.UseWindowingSubsystem(() => AndroidPlatform.Initialize(), "Android")
.UseSkia();
}

52
src/Android/Avalonia.Android/AndroidRuntimePlatform.cs

@ -0,0 +1,52 @@
using System;
using Android.Content.PM;
using Android.Content;
using Avalonia.Platform;
using App = Android.App.Application;
using System.Reflection;
namespace Avalonia
{
internal static class AndroidRuntimePlatformServices
{
public static AppBuilder UseAndroidRuntimePlatformSubsystem(this AppBuilder builder)
{
builder.UseRuntimePlatformSubsystem(() => Register(builder.ApplicationType?.Assembly), nameof(AndroidRuntimePlatform));
return builder;
}
public static void Register(Assembly? assembly = null)
{
AssetLoader.RegisterResUriParsers();
AvaloniaLocator.CurrentMutable
.Bind<IRuntimePlatform>().ToSingleton<AndroidRuntimePlatform>()
.Bind<IAssetLoader>().ToConstant(new StandardAssetLoader(assembly));
}
}
internal class AndroidRuntimePlatform : StandardRuntimePlatform
{
private static readonly Lazy<RuntimePlatformInfo> Info = new(() =>
{
var isDesktop = IsRunningOnDesktop(App.Context);
var isTv = IsRunningOnTv(App.Context);
return new RuntimePlatformInfo
{
IsDesktop = isDesktop,
IsMobile = !isTv && !isDesktop,
IsTV = isTv
};
});
private static bool IsRunningOnDesktop(Context context) =>
context.PackageManager.HasSystemFeature("org.chromium.arc") ||
context.PackageManager.HasSystemFeature("org.chromium.arc.device_management");
private static bool IsRunningOnTv(Context context) =>
context.PackageManager.HasSystemFeature(PackageManager.FeatureLeanback);
public override RuntimePlatformInfo GetRuntimeInfo() => Info.Value;
}
}

6
src/Avalonia.Base/Platform/IRuntimePlatform.cs

@ -13,15 +13,17 @@ namespace Avalonia.Platform
public record struct RuntimePlatformInfo
{
public FormFactorType FormFactor => IsDesktop ? FormFactorType.Desktop :
IsMobile ? FormFactorType.Mobile : FormFactorType.Unknown;
IsMobile ? FormFactorType.Mobile : IsTV ? FormFactorType.TV : FormFactorType.Unknown;
public bool IsDesktop { get; set; }
public bool IsMobile { get; set; }
public bool IsTV { get; set; }
}
public enum FormFactorType
{
Unknown,
Desktop,
Mobile
Mobile,
TV
}
}

6
src/Browser/Avalonia.Browser/BrowserRuntimePlatform.cs

@ -30,10 +30,12 @@ internal class BrowserRuntimePlatform : StandardRuntimePlatform
private static readonly Lazy<RuntimePlatformInfo> Info = new(() =>
{
var isMobile = AvaloniaModule.IsMobile();
var isTv = AvaloniaModule.IsTv();
var result = new RuntimePlatformInfo
{
IsMobile = isMobile,
IsDesktop = !isMobile
IsMobile = isMobile && !isTv,
IsDesktop = !isMobile && !isTv,
IsTV = isTv
};
return result;

5
src/Browser/Avalonia.Browser/Interop/AvaloniaModule.cs

@ -33,7 +33,10 @@ internal static partial class AvaloniaModule
[JSImport("Caniuse.isMobile", AvaloniaModule.MainModuleName)]
public static partial bool IsMobile();
[JSImport("Caniuse.isTv", AvaloniaModule.MainModuleName)]
public static partial bool IsTv();
[JSImport("registerServiceWorker", AvaloniaModule.MainModuleName)]
public static partial void RegisterServiceWorker(string path, string? scope);
}

4
src/Browser/Avalonia.Browser/webapp/modules/avalonia/caniuse.ts

@ -14,4 +14,8 @@ export class Caniuse {
const regex2 = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw(n|u)|c55\/|capi|ccwa|cdm|cell|chtm|cldc|cmd|co(mp|nd)|craw|da(it|ll|ng)|dbte|dcs|devi|dica|dmob|do(c|p)o|ds(12|d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(|_)|g1 u|g560|gene|gf5|gmo|go(\.w|od)|gr(ad|un)|haie|hcit|hd(m|p|t)|hei|hi(pt|ta)|hp( i|ip)|hsc|ht(c(| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i(20|go|ma)|i230|iac( ||\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|[a-w])|libw|lynx|m1w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|mcr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|([1-8]|c))|phil|pire|pl(ay|uc)|pn2|po(ck|rt|se)|prox|psio|ptg|qaa|qc(07|12|21|32|60|[2-7]|i)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h|oo|p)|sdk\/|se(c(|0|1)|47|mc|nd|ri)|sgh|shar|sie(|m)|sk0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h|v|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl|tdg|tel(i|m)|tim|tmo|to(pl|sh)|ts(70|m|m3|m5)|tx9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas|your|zeto|zte/i;
return regex1.test(userAgent) || regex2.test(userAgent.substr(0, 4));
}
public static isTv(): boolean {
return navigator.userAgent.includes("SmartTV");
}
}

22
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnFormFactorExtension.cs

@ -4,6 +4,7 @@ using Avalonia.Platform;
namespace Avalonia.Markup.Xaml.MarkupExtensions;
/// <inheritdoc/>
public sealed class OnFormFactorExtension : OnFormFactorExtensionBase<object, On>
{
public OnFormFactorExtension()
@ -22,6 +23,7 @@ public sealed class OnFormFactorExtension : OnFormFactorExtensionBase<object, On
}
}
/// <inheritdoc/>
public sealed class OnFormFactorExtension<TReturn> : OnFormFactorExtensionBase<TReturn, On<TReturn>>
{
public OnFormFactorExtension()
@ -40,18 +42,38 @@ public sealed class OnFormFactorExtension<TReturn> : OnFormFactorExtensionBase<T
}
}
/// <summary>
/// Provides form factor-specific value for T for the current target device.
/// This extension defines "form-factor" as a "device type" rather than "screen type".
/// </summary>
public abstract class OnFormFactorExtensionBase<TReturn, TOn> : IAddChild<TOn>
where TOn : On<TReturn>
{
/// <summary>
/// Gets or sets the value applied by default.
/// If not set, default(TReturn) is assigned to the value.
/// </summary>
[MarkupExtensionDefaultOption]
public TReturn? Default { get; set; }
/// <summary>
/// Gets or sets the value applied on desktop systems.
/// </summary>
[MarkupExtensionOption(FormFactorType.Desktop)]
public TReturn? Desktop { get; set; }
/// <summary>
/// Gets or sets the value applied on mobile systems.
/// </summary>
[MarkupExtensionOption(FormFactorType.Mobile)]
public TReturn? Mobile { get; set; }
/// <summary>
/// Gets or sets the value applied on TV systems.
/// </summary>
[MarkupExtensionOption(FormFactorType.TV)]
public TReturn? TV { get; set; }
// Required for the compiler, will be replaced with actual method compile time.
public object ProvideValue() { return this; }
void IAddChild<TOn>.AddChild(TOn child) {}

7
src/Tizen/Avalonia.Tizen/TizenApplicationExtensions.cs

@ -1,4 +1,7 @@
namespace Avalonia.Tizen;
using System.Reflection;
using Avalonia.Platform;
namespace Avalonia.Tizen;
/// <summary>
/// Extension to setup app builder with tizen backend
@ -13,8 +16,8 @@ public static class TizenApplicationExtensions
public static AppBuilder UseTizen(this AppBuilder builder)
{
return builder
.UseTizenRuntimePlatformSubsystem()
.UseWindowingSubsystem(TizenPlatform.Initialize, "Tizen")
.UseStandardRuntimePlatformSubsystem()
.UseSkia();
}
}

38
src/Tizen/Avalonia.Tizen/TizenRuntimePlatform.cs

@ -0,0 +1,38 @@
using System.Reflection;
using Avalonia.Platform;
namespace Avalonia.Tizen;
internal static class TizenRuntimePlatformServices
{
public static AppBuilder UseTizenRuntimePlatformSubsystem(this AppBuilder builder)
{
builder.UseRuntimePlatformSubsystem(() => Register(builder.ApplicationType?.Assembly), nameof(TizenRuntimePlatform));
return builder;
}
public static void Register(Assembly? assembly = null)
{
AssetLoader.RegisterResUriParsers();
AvaloniaLocator.CurrentMutable
.Bind<IRuntimePlatform>().ToSingleton<TizenRuntimePlatform>()
.Bind<IAssetLoader>().ToConstant(new StandardAssetLoader(assembly));
}
}
internal class TizenRuntimePlatform : StandardRuntimePlatform
{
private static readonly Lazy<RuntimePlatformInfo> Info = new(() =>
{
global::Tizen.System.Information.TryGetValue("http://tizen.org/feature/profile", out string profile);
return new RuntimePlatformInfo
{
IsMobile = profile.Equals("mobile", StringComparison.OrdinalIgnoreCase),
IsTV = profile.Equals("tv", StringComparison.OrdinalIgnoreCase),
IsDesktop = false
};
});
public override RuntimePlatformInfo GetRuntimeInfo() => Info.Value;
}
Loading…
Cancel
Save