Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.NET MAUI support #36

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Material.Icons.Maui.Demo/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version = "1.0" encoding = "UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Material.Icons.Maui.Demo"
x:Class="Material.Icons.Maui.Demo.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
10 changes: 10 additions & 0 deletions Material.Icons.Maui.Demo/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Material.Icons.Maui.Demo;

public partial class App {
public App() {
InitializeComponent();

// UserAppTheme = AppTheme.Light;
MainPage = new AppShell();
}
}
15 changes: 15 additions & 0 deletions Material.Icons.Maui.Demo/AppShell.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="Material.Icons.Maui.Demo.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Material.Icons.Maui.Demo"
Shell.FlyoutBehavior="Disabled"
Title="Material.Icons Demo">

<ShellContent
ContentTemplate="{DataTemplate local:MainPage}"
Route="Main">
</ShellContent>

</Shell>
9 changes: 9 additions & 0 deletions Material.Icons.Maui.Demo/AppShell.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Material.Icons.Maui.Demo;

public partial class AppShell {
public AppShell() {
InitializeComponent();

Routing.RegisterRoute("Main/Details", typeof(DetailsPage));
}
}
35 changes: 35 additions & 0 deletions Material.Icons.Maui.Demo/DetailsPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<maui:ReactiveContentPage
x:TypeArguments="demo:DetailsViewModel" xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maui="using:ReactiveUI.Maui"
xmlns:demo="using:Material.Icons.Maui.Demo"
xmlns:material="http://schemas.skproch/material/icons/2024"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="Material.Icons.Maui.Demo.DetailsPage"
x:DataType="demo:DetailsViewModel">
<CarouselView
ItemsSource="{Binding Icons}"
CurrentItem="{Binding SelectedIcon}">
<CarouselView.ItemTemplate>
<DataTemplate x:DataType="demo:PackIconKindGroup">
<toolkit:DockLayout Background="Transparent">

<Label
toolkit:DockLayout.DockPosition="Bottom"
Text="{Binding DisplayName}"
MaxLines="1"
LineBreakMode="TailTruncation"
HorizontalTextAlignment="Center"
Margin="5"
VerticalOptions="Center" />

<material:MaterialIcon
Margin="2"
Kind="{Binding Kind}" />

</toolkit:DockLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</maui:ReactiveContentPage>
8 changes: 8 additions & 0 deletions Material.Icons.Maui.Demo/DetailsPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Material.Icons.Maui.Demo;

[QueryProperty(nameof(ViewModel), "ViewModel")]
public partial class DetailsPage {
public DetailsPage() {
InitializeComponent();
}
}
14 changes: 14 additions & 0 deletions Material.Icons.Maui.Demo/DetailsViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using DynamicData.Binding;

using ReactiveUI;
using ReactiveUI.SourceGenerators;

namespace Material.Icons.Maui.Demo;

public partial class DetailsViewModel : ReactiveObject {
[Reactive]
private PackIconKindGroup? _selectedIcon;

[Reactive]
private ObservableCollectionExtended<PackIconKindGroup> _icons = [];
}
72 changes: 72 additions & 0 deletions Material.Icons.Maui.Demo/MainPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8" ?>
<maui:ReactiveContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
x:TypeArguments="demo:MainViewModel"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:material="http://schemas.skproch/material/icons/2024"
xmlns:maui="clr-namespace:ReactiveUI.Maui;assembly=ReactiveUI.Maui"
xmlns:demo="clr-namespace:Material.Icons.Maui.Demo"
x:Class="Material.Icons.Maui.Demo.MainPage"
x:DataType="demo:MainViewModel">

<Grid>
<Button x:Name="ShowDetails" Text="Details"/>
<!--
<CollectionView
ItemsSource="{Binding Kinds}"
SelectionMode="Single">

<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="12" />
</CollectionView.ItemsLayout>

<CollectionView.ItemTemplate>
<DataTemplate x:DataType="demo:PackIconKindGroup">
<Grid
WidthRequest="64" HeightRequest="64"
HorizontalOptions="Center"
RowDefinitions="32,32"
Background="Transparent">

<material:MaterialIcon
Margin="2"
Grid.Row="0"
Kind="{Binding Kind}" />

<Label
Grid.Row="1"
Text="{Binding DisplayName}"
MaxLines="1"
LineBreakMode="TailTruncation"
HorizontalTextAlignment="Center"
VerticalOptions="Center" />

</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
-->
<!-- <Path Grid.Row="1" Fill="{AppThemeBinding Dark={StaticResource White}, Light={StaticResource Black}}" Data="M17 14V17H14V19H17V22H19V19H22V17H19V14M12 2A2 2 0 0 0 10 4A2 2 0 0 0 10 4.29C7.12 5.14 5 7.82 5 11V17L3 19V20H12.35A6 6 0 0 1 12 18A6 6 0 0 1 18 12A6 6 0 0 1 19 12.09V11C19 7.82 16.88 5.14 14 4.29A2 2 0 0 0 14 4A2 2 0 0 0 12 2M10 21A2 2 0 0 0 12 23A2 2 0 0 0 13.65 22.13A6 6 0 0 1 12.81 21Z" /> -->
<!-- <Path Grid.Row="1" Fill="{AppThemeBinding Dark={StaticResource White}, Light={StaticResource Black}}" Data="M12 2a2 2 0 0 0-2 2 2 2 0 0 0 0 .29" /> -->

<!--
<Path Grid.Row="1" Fill="{AppThemeBinding Dark={StaticResource White}, Light={StaticResource Black}}">
<Path.Data>
M 12 2
A 2 2 0 0 0 10 4
A 2 2 0 0 0 10 4.29
</Path.Data>
</Path>
-->
<!--
<Path Grid.Row="1" Fill="{AppThemeBinding Dark={StaticResource White}, Light={StaticResource Black}}">
<Path.Data>
M17 14V17H14V19H17V22H19V19H22V17H19V14
M12 2A2 2 0 0 0 10 4A2 2 0 0 0 10 4.29C7.12 5.14 5 7.82 5 11V17L3 19V20H12.35A6 6 0 0 1 12 18A6 6 0 0 1 18 12A6 6 0 0 1 19 12.09V11C19 7.82 16.88 5.14 14 4.29A2 2 0 0 0 14 4A2 2 0 0 0 12 2
M10 21A2 2 0 0 0 12 23A2 2 0 0 0 13.65 22.13A6 6 0 0 1 12.81 21Z
</Path.Data>
</Path>
-->
</Grid>

</maui:ReactiveContentPage>
21 changes: 21 additions & 0 deletions Material.Icons.Maui.Demo/MainPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using ReactiveUI;

namespace Material.Icons.Maui.Demo;

public partial class MainPage {
public MainPage(MainViewModel viewModel) {
Controls.Init();

BindingContext = viewModel;

InitializeComponent();

this.WhenActivated(d => {
this.BindCommand(
ViewModel,
vm => vm.ShowDetails,
v => v.ShowDetails,
vm => vm.Group);
});
}
}
90 changes: 90 additions & 0 deletions Material.Icons.Maui.Demo/MainViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System.Reactive;
using System.Reactive.Linq;

using DynamicData.Binding;
using DynamicData;

using ReactiveUI;
using ReactiveUI.SourceGenerators;

namespace Material.Icons.Maui.Demo;

public partial class MainViewModel : ReactiveObject {
[Reactive]
private SourceList<PackIconKindGroup> _kindsSource = new();

[Reactive]
private ObservableCollectionExtended<PackIconKindGroup> _kinds = new();

[Reactive]
private string? _searchText;

[Reactive]
private PackIconKindGroup? _group;

[ObservableAsProperty]
private string? _copyText;

public MainViewModel() {
_kindsSource.AddRange(
(from name in Enum.GetNames<MaterialIconKind>()
let kind = Enum.Parse<MaterialIconKind>(name)
let value = (int)kind
let item = (Name: name, Kind: kind, Value: value)
group item by item.Value
into g
select new PackIconKindGroup(g.Select(x => x.Name)))
.OrderBy(x => x.DisplayName));

Group = _kindsSource.Items.FirstOrDefault();

var kindsFilter = this.WhenAnyValue(x => x.SearchText)
.Select(text => string.IsNullOrEmpty(text)
? CreateUnfilteredFilter()
: CreateTextFilter(text))
.Throttle(TimeSpan.FromMilliseconds(250));

_kindsSource
.Connect()
.Filter(kindsFilter)
.Sort(SortExpressionComparer<PackIconKindGroup>.Ascending(p => p.DisplayName))
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(_kinds)
.Subscribe();

_copyTextHelper = this.WhenAnyValue(x => x.Group)
.Select(value => value is null ? null : $"<wpf:MaterialIcon Kind=\"{value.Kind}\" />")
.ToProperty(this, x => x.CopyText);

DetailsViewModel = new DetailsViewModel() {
Icons = _kinds,
SelectedIcon = Group,
};

DetailsViewModel.WhenAnyValue(x => x.SelectedIcon)
.Subscribe(item => Group = item);

var canShowDetails = this.WhenAnyValue(x => x.Group)
.Select(value => value is not null);
ShowDetails = ReactiveCommand.CreateFromTask<PackIconKindGroup>(ShowDetailsAsync, canShowDetails);
}

public DetailsViewModel DetailsViewModel { get; }

public ReactiveCommand<PackIconKindGroup, Unit> ShowDetails { get; }

private static Func<PackIconKindGroup, bool> CreateUnfilteredFilter() {
return _ => true;
}

private static Func<PackIconKindGroup, bool> CreateTextFilter(string searchText) {
return kindGroup => kindGroup.Names.Any(a => a.Contains(searchText, StringComparison.CurrentCultureIgnoreCase));
}

private async Task ShowDetailsAsync(PackIconKindGroup icon, CancellationToken cancellationToken) {
DetailsViewModel.SelectedIcon = icon;
await Shell.Current.GoToAsync("Details", new Dictionary<string, object> {
{ "ViewModel", DetailsViewModel },
});
}
}
74 changes: 74 additions & 0 deletions Material.Icons.Maui.Demo/Material.Icons.Maui.Demo.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->

<!-- Note for MacCatalyst:
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->

<OutputType>Exe</OutputType>
<RootNamespace>Material.Icons.Maui.Demo</RootNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<!-- Display name -->
<ApplicationTitle>Material.Icons Demo</ApplicationTitle>

<!-- App Identifier -->
<ApplicationId>com.companyname.material.icons.maui.demo</ApplicationId>

<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>

<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup>

<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />

<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />

<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />

<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />

<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="CommunityToolkit.Maui" Version="9.0.3" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.82" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.82" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="ReactiveUI.Maui" Version="20.1.1" />
<PackageReference Include="ReactiveUI.SourceGenerators" Version="1.0.3" />
<PackageReference Include="Splat.Microsoft.Extensions.DependencyInjection" Version="15.1.1" />
<PackageReference Include="Splat.Microsoft.Extensions.Logging" Version="15.1.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Material.Icons.Maui\Material.Icons.Maui.csproj" />
</ItemGroup>

</Project>
Loading
Loading