Git Product home page Git Product logo

reactorui-maui's Introduction

MauiReactor

Component-based UI Library built on top of .NET MAUI

Build status Nuget

MauiReactor is .NET library written on top of .NET MAUI that allows you to write applications in pure C# using an MVU approach.

This is the classic Counter app in MauiReactor:

class CounterPageState
{
    public int Counter { get; set; }
}

class CounterPage : Component<CounterPageState>
{
    public override VisualNode Render()
        => ContentPage("Counter Sample",
            VStack(
                Label($"Counter: {State.Counter}"),

                Button("Click To Increment", () =>
                    SetState(s => s.Counter++))
            )
            .Spacing(10)
            .Center()
        );
    
}

Setting up MauiReactor from CLI

  1. Install MauiReactor templates
dotnet new install Reactor.Maui.TemplatePack
  1. Install MauiReactor hot reload console command
dotnet tool install -g Reactor.Maui.HotReload

If you already installed an old version of Reactor.Maui.HotReload you can update it to the latest using this command:

dotnet tool update -g Reactor.Maui.HotReload
  1. Create a sample project
dotnet new maui-reactor-startup -o my-new-project

and move inside the new project folder

cd .\my-new-project\
  1. Build & run the project (emulator or device must be running and configured)
dotnet build -t:Run -f net8.0-android

Under Mac, to target an iOS device/emulator, issue a command like this:

dotnet build -t:Run /p:_DeviceName=:v2:udid=<device_id> -f net8.0-ios

where the device id comes from this list:

xcrun simctl list
  1. Hot-reload console (in a different shell)
dotnet-maui-reactor -f [net8.0-android|net8.0-ios|...]
  1. Edits to code should be hot-reloaded by the application --> Enjoy!

Documentation

Documentation

Videos

All Packages

Introductionary video from Solution1 conference YouTube Video Views

Interview with James Montemagno YouTube Video Views

Getting started video from Gerald Versluis YouTube Video Views

Sample Applications

Main Samples Repository

Rive App

KeeMind App

Samples and test application

How to contribute

  • Star the repository!
  • File an issue (Issues)
  • Fix bugs, add features, or improve the code with PRs
  • Help with the documentation (Documentation Repo)

reactorui-maui's People

Contributors

adospace avatar code-dj avatar fynnschapdick avatar licon4812 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reactorui-maui's Issues

Navigation: set main page?

Hi again @adospace :)

Is there a way to set the application's main page?

Imagine this scenario: I open the app on a loading page that checks authentication, syncs data, and redirects either to the main application screen (if valid user) or the login screen. I usually handle this sort of thing by replacing the application's MainPage (eg Application.Current.MainPage = new LoginPage()) because I don't intend the user to be able to navigate back. I also don't want it to appear as Modal because once login is complete I want to replace the MainPage again with the full application window.

The INavigation abstraction allows me either to push a page to an existing NavigationPage ort to PushModal onto a new modal navigation stack, but there isn't a way to replace the current application root.

Do you think this is a valid use case, or am I doing it all wrong? And if it's valid, is there a way to do it using MauiReactor?

Thanks again

OnRemainingItemsThresholdReached isn't working for CollectionView

public class MainPageState
{
    public IReadonlyList<int> Ints { get; set; } = Enumerable.Range(0,50).ToList();
}
public class MainPage : Component<MainPageState>
{
    public override VisualNode Render()
    {
        return new ContentPage()
        {
            new CollectionView()
                .ItemsSource(State.Ints, i => new Label(i))
                .RemainingItemsThreshold(5)
                .OnRemainingItemsThresholdReached(moreInts)
        };
    }
    
    async void moreInts()
    {
         await Task.Delay(1000);
         SetState(s => s.Ints = Enumerable.Range(0, s.Ints.Count + 50).ToList());
    }
}

Here the ThresholdReached handler never gets called. Is it a bug or I'm doing something wrong? I having this issue on windows platform

How to deal with custom dialogs / popups?

I didn't find any example of dialog / popup implementation in your examples. After reading the documentation, I tried to implement compatibility with third-party libraries (Plugin.Maui.Popup, CommunityToolki.Maui), but I failed. Maybe I was doing it wrong. I would like to have an example of how to do it correctly.

Thanks in advance

Hot reload for windows app

Hi @adospace

This is an awesome library, thanks for putting it out there!

Is hot reload supposed to work for windows apps? I have tested dotnet-maui-reactor for Android in normal and full mode and both work as expected, but when I run under windows I get errors.

Under normal mode:

PS C:\Code\Blauhaus\Blauhaus.Accounts\src\sample\accounts.sample.client.mauireactor> dotnet-maui-reactor -f net7.0-windows10.0.19041.0
MauiReactor Hot-Reload CLI
Version 1.0.116.0
Press Ctrl+C or Ctrl+Break to quit
Setting up build pipeline for Accounts.Sample.Client.MauiReactor project...done.
Monitoring folder 'C:\Code\Blauhaus\Blauhaus.Accounts\src\sample\accounts.sample.client.mauireactor'...
Detected file rename from 'Pages\MainPage.cs' to 'Pages\MainPage.cs~RF16d2c6.TMP'
Detected file rename from 'Pages\hjd5jhbu.dzq~' to 'Pages\MainPage.cs'
Replacing syntax tree for: Pages\MainPage.cs
error CS5001: Program does not contain a static 'Main' method suitable for an entry point
C:\Code\Blauhaus\Blauhaus.Accounts\src\sample\accounts.sample.client.mauireactor\Platforms\Windows\App.xaml.cs(19,18): error CS1061: 'App' does not contain a definition for 'InitializeComponent' and no accessible extension method 'InitializeComponent' accepting a first argument of type 'App' could be found (are you missing a using directive or an assembly reference?)

Under full mode it sometimes works but mostly gets stuck on this:

CSC : error CS2012: Cannot open 'C:\Code\Blauhaus\Blauhaus.Accounts\src\sample\accounts.sample.client.mauireactor\obj\Debug\net7.0-windows10.0.19041.0\win10-x64\Accounts.Sample.Client.MauiReactor.pdb' for writing -- 'The process cannot access the file 'C:\Code\Blauhaus\Blauhaus.Accounts\src\sample\accounts.sample.client.mauireactor\obj\Debug\net7.0-windows10.0.19041.0\win10-x64\Accounts.Sample.Client.MauiReactor.pdb' because it is being used by another process.' [C:\Code\Blauhaus\Blauhaus.Accounts\src\sample\accounts.sample.client.mauireactor\Accounts.Sample.Client.MauiReactor.csproj::TargetFramework=net7.0-windows10.0.19041.0]

If windows is not supported, that's fine, but if it is then let me know if you need any further info.

Apart from the dotnet-maui-reactor tool, Is there anything specific required to get "normal" maui hotreload to work?

Thanks again

dotnet build -t:Run -f net7.0-windows10.0.19041 throws System.DllNotFoundException

I've tried to follow the setup steps in the readme, but it doesn't seem to work if I target Windows. Here's the output for the MauiReactor.TestApp project:

> dotnet build -t:Run -f net7.0-windows10.0.19041
MSBuild version 17.5.1+f6fdcf537 for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
  Unhandled exception. System.DllNotFoundException: Unable to load DLL 'Microsoft.ui.xaml.dll' or one of its dependencies: The specified module could not be found. (0x8007007E)
     at MauiReactor.TestApp.WinUI.Program.XamlCheckProcessRequirements()
     at MauiReactor.TestApp.WinUI.Program.Main(String[] args) in C:\code\reactorui-maui\samples\MauiReactor.TestApp\obj\Debug\net7.0-windows10.0.19041\win10-x64\Platforms\Windows\App.g.i.cs:line 28
C:\Program Files\dotnet\sdk\7.0.203\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.targets(927,5): error MSB3073: The command "C:\code\reactorui-maui\samples\MauiReactor.TestApp\bin\Debug\net7.0-windows10.0.19041\win10-x64\MauiReactor.TestApp.exe " exited with code -5
32462766. [C:\code\reactorui-maui\samples\MauiReactor.TestApp\MauiReactor.TestApp.csproj::TargetFramework=net7.0-windows10.0.19041]

Build FAILED.

C:\Program Files\dotnet\sdk\7.0.203\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.targets(927,5): error MSB3073: The command "C:\code\reactorui-maui\samples\MauiReactor.TestApp\bin\Debug\net7.0-windows10.0.19041\win10-x64\MauiReactor.TestApp.exe " exited with code -5
32462766. [C:\code\reactorui-maui\samples\MauiReactor.TestApp\MauiReactor.TestApp.csproj::TargetFramework=net7.0-windows10.0.19041]
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:00.85

F5 debugging in Visual Studio works though. I assume this is because the project is configured to also deploy on build (in the Configuration Manager).

Reactor.Maui version is 1.0.124.

Component state is not updating

I am trying to create a button component that transitions to an activity indicator when told to do so by its' parent, but when the parent changes the button's state, it does not carry through to the button's Render func.

I would have thought the following would work, but it appears I'm misunderstanding something...

using System;
using MauiReactor;
using MauiReactor.Compatibility;

namespace MyApp.Controls;

class ButtonXState
{
    public bool IsBusy { get; set; } = false;
}

class ButtonX : Component<ButtonXState>
{
    string text = "Button";

    Func<bool> onClicked;

    public override VisualNode Render()
    {
        Console.WriteLine($"Render => IsBusy: {State.IsBusy}"); // Always false

        if (!State.IsBusy)
        {
             return new Button(text).OnClicked(OnClicked);
        }
        else
        {
             return new ActivityIndicator().IsRunning(true);
        }    
    }

    public ButtonX IsBusy(bool isBusy)
    {
        SetState(s => s.IsBusy = isBusy); // This is not reflected in the Render func

        return this;
    }

    public ButtonX Text(string text_)
    {
        text = text_;

        return this;
    }

    public ButtonX OnClicked(Func<bool> func)
    {
        onClicked = func;

        return this;
    }

    private void OnClicked(object sender, EventArgs args)
    {
        onClicked();
    }
}

And in the parent:

new ButtonX()
    .Text("Register") // Sets Correctly
    .OnClicked(Register) // Fires when clicked
    .IsBusy(State.IsSubmitting) // The correct bool is passed in, but it is not reflected in the Render func 

Am I approaching this all wrong? Would you point me in the right direction?

Constructor dependency injection

First of all, great work! I'm exploring other options for Maui development than basic xaml mvvm and this got my attention (currently debating between mauireactor and mobile blazor bindings).

I saw in the docs that for getting services one should use a service locator pattern. What about constructor DI? Is there any reason to not support it? Maybe I'm missing something which prevents this to work.

Thanks for your great work!

Navigation.PushAsync not working

new Button("Open Window") .OnClicked(async() => { await Navigation.PushAsync<FullColorWindow>(); })

I added this code to MainPage (demo) and created a new component named FullColorWindow with its own children items.

Expected behavior
App displays the component named FullColorWindow

What happened
Nothing after clicking on the button multiple times nothing happens
PS: no errors & exception.

Thank you.

How to navigate to another page when not on UI thread?

I asked this on Microsoft Q&A because I thought it was more of a Maui issue but was re-directed here.

I'm building a mobile and desktop app with Maui + MauiReactor that communicates with my server over Websockets. I have this working fine.

My problem is that if I try to Navigate to another page when I receive a Websocket reply with await Navigation.pushAsync<NewPage>(); I get the following error:

UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.

I understand why this happening, just not how best to handle it.

I can display a button after the message has been received, which the user can click to navigate which is obviously performing the navigaton on the UI thread due to the button click, but this feels really clunky. Is it possible to raise the process onto the UI thread so that I can programmatically navigate automatically?

My use case is as follows:

User starts the app, navigates to the sign in page, and enters credentials

Credentials get sent to my server over a websocket

Websocket reply confirms credentials and supplies a session token

Now I need to navigate to another page based on the current state of their profile settings i.e. if incomplete, go to profile page, if complete go back home. I would like this to be automatic without forcing the user to click a button to navigate.

ToolbarItem usage

Hello, I made a method to create a ToolBarItem, but the page does not have a method for adding it, how can I add it to a page?
image

Children not render

Hi, I have a page that can change its own state. Below is an example.
When I click the button, the state changes to the "Loading state" and then it automatically change back, but Children are not displayed.

public class FirstPage : Component
{
    private BasePage _baseRef;

    public override VisualNode Render() => new BasePage(r => _baseRef = r)
    {
        new VStack()
            {
                new Label("First!"),
                new Button("Change view")
                    .OnClicked(() =>
                    {
                        _baseRef.SetIsLoading();
                        Task.Run(async () =>
                        {
                            await Task.Delay(TimeSpan.FromSeconds(2));
                            _baseRef.SetIsSuccess();
                        });
                    })
            }
            .Spacing(20)
            .HCenter()
            .VCenter()
    };
}

public enum PageState
{
    Success = 0,
    Error = 1,
    Loading = 2
}

public class BasePageState
{
    public PageState PageState { get; set; }
}

public class BasePage : Component<BasePageState>
{
    public BasePage(Action<BasePage> func) => func(this);

    public override VisualNode Render()
    {
        return new ContentPage()
        {
            State.PageState == PageState.Loading ? new Label("Loading view") : null,
            State.PageState == PageState.Error ? new Label("Error view") : null,
            State.PageState == PageState.Success ? Children() : null,
        }.Title("Base");
    }

    public void SetIsLoading() => SetState(prev => { prev.PageState = PageState.Loading; });

    public void SetIsError() => SetState(prev => { prev.PageState = PageState.Error; });

    public void SetIsSuccess() => SetState(prev => { prev.PageState = PageState.Success; });
}


public class App : Component
{
    public override VisualNode Render()
    {
        return new NavigationPage()
        {
            new FirstPage()
        }.Set(Microsoft.Maui.Controls.NavigationPage.BarTextColorProperty, Colors.White);
    }
}

Unable to hot reload the application

Followed the readme with net7 and Android. Same on Mac Catalyst. Using macOS Ventura and VS Code.

dmo@Davids-M1 my-new-project % dotnet-maui-reactor -f net7.0-android
MauiReactor Hot-Reload CLI
Version 1.0.72.0
Press Ctrl+C or Ctrl+Break to quit
Setting up build pipeline for my-new-project project...done.
Monitoring folder '/Users/dmo/work/my-new-project'...
Detected changes to 'Pages/MainPage.cs'
Replacing syntax tree for: Pages/MainPage.cs
Connecting to Hot-Reload server (Port: 45820)...Unable to hot reload the application:
System.Net.Sockets.SocketException (61): Connection refused
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
   at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|281_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken)
   at System.Net.Sockets.TcpClient.CompleteConnectAsync(ValueTask task)
   at MauiReactor.HotReloadConsole.HotReloadClient.SendAssemblyFileToServer(MemoryStream stream, MemoryStream pdbStream, CancellationToken cancellationToken) in C:\projects\reactorui-maui\src\MauiReactor.HotReloadConsole\HotReloadClient.cs:line 299
   at MauiReactor.HotReloadConsole.HotReloadClient.ConnectionLoop(CancellationToken cancellationToken) in C:\projects\reactorui-maui\src\MauiReactor.HotReloadConsole\HotReloadClient.cs:line 156

Should this work with Visual Studio's hot reload?

I understand that there is a dotnet tool, dotnet-maui-reactor, which gives us a hot reload dev experience. Visual Studio and the default MAUI template also supports a hot reload dev experience.

I'd like to build a ReactorUI app in Visual Studio using the built-in hot reload experience.

I was wondering if there was anything fundamental to ReactorUI implementation or Visual Studio's implementation of hot reload which would mean this is not possible?

Repro

  1. dotnet new maui-reactor-startup
  2. Open the csproj in Visual Studio
  3. Debug with the Windows Machine profile

Expected

Hot reload works like the default MAUI template.

Actual

Hot reload shows as connected from Visual Studio but not connected from the toolbar inside the Windows app.

Additionally, I see SerializationExceptions in the output window.

System.Runtime.Serialization.SerializationException: 'Element ':item' contains data of the 'http://schemas.datacontract.org/2004/07/Xamarin.HotReload:UpdateDelta' data contract. The deserializer has no knowledge of any type that maps to this contract. Add the type corresponding to 'UpdateDelta' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'

System info

  • ReactorUI.Maui 1.0.108
  • dotnet 7.0.202
  • Visual Studio 17.5.2

CarouselView usage

First of all, thanks for the great project.
I can easily add simple controls into the project, but I have difficulties with controls that require initialization such as CarouselView.
Could you please share sample code for CarouselView?

NotSupportedException when using non-reactorui controls

Hello. Thank you for this library!

I'm trying to use CommunityToolkit views with Reactor.Maui:

class MainPage : Component<MainPageState> {
    public override VisualNode Render() {
        return new ContentPage {
            new ScrollView {
                new VerticalStackLayout {
                    new Button(State.Counter == 0 ? "Click me" : $"Clicked {State.Counter} times!")
                        .OnClicked(()=>SetState(s => s.Counter++))
                        .HCenter(),
                    new AvatarView {
                        Text = "ZS"
                    }
                }
                .VCenter()
                .Spacing(25)
                .Padding(20, 0)
            }
        };
    }
}

But I have a following exception:
Screenshot 2023-05-01 at 12 53 37

Its also happens when using MAUI controls:
Screenshot 2023-05-01 at 12 57 15

Maybe I need to write some kind of wrapper for these classes? For example:

class ReactorUIAvatarView: CommunityToolkit.AvatarView {
    override...
}

About ReactorUI-Maui

Hello, is the implementation of ReactorUI-Maui like flutter? Does the component distinguish whether it is stateful or not?

HotReload console error

Hi, i started testing this package. but i have a problem with the console. Here a quick screenshot of my error. I could not find more in the docs. i suspect my problem is really simple, but i cant figure it out.

image

Is there a GestureRecognizer sample code

Hi Ado, I hope you're doing well. I would like to ask if there are sample code for gesture recognizer (ie. swipe(direction: left; right; top; bottom), drag and drop) in your sample repositories that I can look and try. I think the common use case is swipe to reveal the menu choices for delete or edit. Thank you

How to use DynamicResource and Styles

I've been trying to migrate a C# Markup code to reactorui-maui but there's been no way to use DynamicResource, StaticResource or the the Style method.
I already prepare lot of XAML style i don't want to design controls individually.

Supprot windows development?

Hello. I'm plan to proceed with Windows platform development using maui.
It is currently impossible to proceed.
Do you have a support plan?

Entry with binding to State object doesn't work properly

The entry element doesn't take input. If you write a character on it and it will be automatically deleted.
This code is directly taken from docs

public class MainPage : Component<MainPageState>
{
    public override VisualNode Render()
    {
        return new ContentPage()
        {
            new StackLayout()
            {
                new Entry()
                    .Placeholder("Username")
                    .OnTextChanged((s,e)=> SetState(_ => _.Username = e.NewTextValue)),
                new Entry()
                    .Placeholder("Password")
                    .OnTextChanged((s,e)=> SetState(_ => _.Password = e.NewTextValue)),
                new Button("Login")
                    .IsEnabled(!string.IsNullOrWhiteSpace(State.Username) && !string.IsNullOrWhiteSpace(State.Password))
                    .OnClicked(OnLogin)
            }
            .VCenter()
            .HCenter()
        };
    }

    private void OnLogin()
    {
        //use State.Username and State.Password to login...
    }
}

Typed characters in the TextBox gets automatically deleted.

I modified it to add Text property bind to the Username and Password props

public class MainPageState
{
    public string Username { get; set; }
    public string Password { get; set; }
}

public class MainPage : Component<MainPageState>
{
    public override VisualNode Render()
    {
        return new ContentPage()
        {
            new StackLayout()
            {
                new Entry()
+                  .Text(State.Username)
                    .Placeholder("Username")
                    .OnTextChanged((s,e)=> SetState(_ => _.Username = e.NewTextValue)),
                new Entry()
+                   .Text(State.Password)
                    .Placeholder("Password")
                    .OnTextChanged((s,e)=> SetState(_ => _.Password = e.NewTextValue)),
                new Button("Login")
                    .IsEnabled(!string.IsNullOrWhiteSpace(State.Username) && !string.IsNullOrWhiteSpace(State.Password))
                    .OnClicked(OnLogin)
            }
            .VCenter()
            .HCenter()
        };
    }

    private void OnLogin()
    {
        //use State.Username and State.Password to login...
    }
}

Now it doesn't delete the character but it takes the cursor to the beginning so the next char you type will be added to the left of previous characters.

How to set how HasNavigationBar=false of RxNavigationPage and Third party nuggets integration

First of all Thank you for this amazing library.I really liked it.

I worked on couple of flutter project as well so it seems very similar just need some clarity on few things.
So in flutter every property of widgets are beings passed as a optional parameter inside constructor but it wasn't the case in reactor right so

How to set properties which does not have extension methods

  1. Like HasNavigationBar = false to NaigationPage/RxNavigationPage or want to hide default shell navigation bar from ContentPage as I want to render my own custom navigation bar I couldn't find any way to do hide shell and content page navigation bar

  2. Also can we use any library with reactor-maui like Rg.Plugin.Popup or Library Maintainer need to do some tweaks to support Reactor-MAUI design pattern

How to use the ItemsLayout property with CollectionView and how does Virtualization and mauiReactor caching work ?

Hi @adospace This library is just awesome. Thanks a lot for your work. I've been trying it out and I can't seem to crack how to use use the gridItemslayout with Collection View using MauiReactor. If there is a code sample available please let me know. Thanks.
And I was also wondering how virtualization works if each of the items are rendered every time (forgive me if the question is dumb I haven't got the time to dig deeper). I am really excited about this project and would like to understand it more. Thanks again :)

.WindowTitle has no effect

Hi,

Setting the WindowTitle on the following has no effect, the Window Title remains as the App name, am I missing something?

MainPage.cs

using MauiReactor;

namespace MyApp.Pages;

class MainPageState
{
    public bool IsRegistered { get; set; } = false;
    public string Token { get; set; }
}

class MainPage : Component<MainPageState>
{
    protected override void OnMounted()
    {
        SetState(s =>
            {
                s.IsRegistered = Preferences.Get("isRegistered", false);
                s.Token = Preferences.Get("token", null);
            }
        );

        base.OnMounted();
    }

    public override VisualNode Render()
    {
        bool hasToken = State.Token != null;

        VisualNode page = new RegisterPage();

        if (State.IsRegistered && hasToken)
        {
            page = new NavigationPage()
            {
                new HomePage()
            };
        }
        else if (State.IsRegistered)
        {
            page = new SignInPage();
        }

        return page;
    }
}

RegisterPage.cs

namespace MyApp.Pages;

class RegisterPage : Component
{
    public override VisualNode Render()
    {
        return new ContentPage()
        {
        }
        .WindowTitle("Register")
        ;
    }
}

Do we need to add states to create simple animations such as ScaleTo, FadeTo etc on tap?

In the xaml world I used to create an Animated Tap behavior to add animation and tapgesturerecognizer to any control.
I can simply add the behavior to a control and a visual feedback such as scale in and out can be shown and at the same time tap gesture works too.
Is there simple way to achieve this type of animated tap control in MauiReactor instead of creating a state each time ? From what I've seen you need to change the state to Animate the control

Hot reload fails when using partial class with GeneratedRegex

Hot reload throws an error if GeneratedRegex is used.

To test, add the following class to any project and try using hot reload:

public partial class Test
{
    [System.Text.RegularExpressions.GeneratedRegex("-")]
    private static partial System.Text.RegularExpressions.Regex MyRegex();
}

You will get the following error:

error CS8795: Partial method 'Test.MyRegex()' must have an implementation part because it has accessibility modifiers.

Application lifecycle events

Is there a recommended way to hook into application lifecycle events?

It looks like they're available on ReactorApplication<> if I derive my own application class

protected override void OnStart()
{
_host?.Run();
base.OnStart();
}
protected override void OnResume()
{
//https://github.com/adospace/reactorui-maui/issues/26
//seems like some devices (Android 9.0?) do not send (or Maui app doesn't receive) the resume event
//so for now do not suspend the event loop (actually it's even not required at all to suspend it as the app itself is suspended by the os)
//_host?.Resume();
base.OnResume();
}
protected override void OnSleep()
{
//do not pause the event loop: see OnResume() above
//_host?.Pause();
base.OnSleep();

and instantiate it myself.

public static MauiAppBuilder UseMauiReactorApp<TComponent>(this MauiAppBuilder appBuilder, Action<Application>? configureApplication = null) where TComponent : Component, new()
=> appBuilder.UseMauiApp(sp =>
{
ServiceCollectionProvider.ServiceProvider = sp;
var app = new ReactorApplication<TComponent>();
configureApplication?.Invoke(app);
return app;
});

How to deal with state shared across Components ?

In your samples every component has its own state object. I my case I have more like "application state" that determines state of the components.
To be specific I am trying to control my IOT device and on settings page I want to be able to set visibility of item based on version of connected device (the version is part of application state). This version is also used on other pages.

What is the correct way to handle situations like this ?

Thanks in advance

Handling OnBackButtonPressed in a custom NavigationPage

Hi, I have a custom Navigation Page in my project that inherits from NavigationPage and in it I can override the behavior of pressing the back button. It looks like this

image

image

Every VM of each page can override its behavior of navigation back click.
Inheritance from MauiReactor.NavigationPage does not allow me to override Navigation Back Button Click behavior.

How do I do the same behavior that was when using the MVVM architecture?

Navigating to another page

Hello! Just found out about this great library and giving it a test run, to maybe finally ditch the MVVM (in the future of course!).

Anyways, I have quickly ran into the issue regarding the navigation. In the documentation it appears it is straightforward to navigate to another page so I gave it a try:

Added a button to the existing MainPage:

new Button("Navigate to Another page")
     .OnClicked(HandleNavigateClick)

Defined the click handler like so:

async void HandleNavigateClick()
{
    await Navigation.PushAsync<AnotherPage>(true);
}

And then the second page:

internal class AnotherPage : Component
{
    public override VisualNode Render()
    {
        return new ContentPage
        {
            new VStack
            {
                new Label("This is another page")
            }
        };
    }
}

And well, nothing happens - the method for navigating is called but no navigation happens - no errors or anything out of order. Did I miss something?

Have to say, the developer experience is amazing - being able to constantly run the application and just change things is just crazy good. Not something I can say about the official Hot Reload...

Best regards,
Matej

Hot-reload error when running on ios simulator

The hot reload program tried to load the dll at my-new-project/bin/Debug/net7.0-ios/my-new-project.dll, however the actual build output is my-new-project/bin/Debug/net7.0-ios/iossimulator-x64/my-new-project.dll

Can't start Hot Reload console

I'm trying to use MauiReactor, I just setup the test project.

It compiles fine and I'm running it on the iOS simulator with the following command:

`dotnet build -t:Run /p:_DeviceName=:v2:udid=979A827D-CDC4-4FE4-8244-EA31AB9201AF -f net6.0-ios``

The UDID is needed to start iPhone 13 Pro simulator, otherwise iPad Air 5 was starting (didn't know the background logic of this...)

Anyway, when running, the application starts fine in the simulator but the command doesn't exit... so, I can't launch dotnet-maui-reactor, not in the current console at least.

I tried to open a new macOS terminal and run dotnet-maui-reactor but with no luck:

MauiReactor Hot-Reload CLI
Version 1.0.52.0
Press Ctrl+C or Ctrl+Break to quit
Setting up build pipeline for my-new-project project...done.
Unhandled exception. System.InvalidOperationException: StandardOut has not been redirected or the process hasn't started yet.
   at System.Diagnostics.Process.get_StandardOutput()
   at MauiReactor.HotReloadConsole.HotReloadClient.ExecutePortForwardCommmand() in C:\projects\reactorui-maui\src\MauiReactor.HotReloadConsole\HotReloadClient.cs:line 372
   at MauiReactor.HotReloadConsole.HotReloadClient.Run(CancellationToken cancellationToken) in C:\projects\reactorui-maui\src\MauiReactor.HotReloadConsole\HotReloadClient.cs:line 107
   at MauiReactor.HotReloadConsole.Program.RunMonitorAndConnectionClient(Options options) in C:\projects\reactorui-maui\src\MauiReactor.HotReloadConsole\Program.cs:line 42
   at CommandLine.ParserResultExtensions.WithParsedAsync[T](ParserResult`1 result, Func`2 action)
   at MauiReactor.HotReloadConsole.Program.Main(String[] args) in C:\projects\reactorui-maui\src\MauiReactor.HotReloadConsole\Program.cs:line 20
   at MauiReactor.HotReloadConsole.Program.<Main>(String[] args)
Abort trap: 6```

Reactor.Maui.TemplatePack

The build property on dotnet_bot.svg is not set to MauiImage causing the image not to be displayed.

Reactor.Maui.TemplatePack
      Version: 1.0.103
      Details:
         Author: adospace
         NuGetSource: https://api.nuget.org/v3/index.json
      Templates:
         MauiReactor based app (maui-reactor-startup) C#
      Uninstall Command:
         dotnet new uninstall Reactor.Maui.TemplatePack

Thanks for the awesome work on this.

Help with the Docs?

Hi Ado,

I really like what you are doing with this project, and as a thank you for your help, I'd be happy to help with the docs if that's something that you are up for(?). Initially I'm thinking I could proof read and fix some of the syntax errors that have crept in due to English not being you first language. Later on, as I get to grips with ReactorMaui, I'd be happy to add some code snippet examples for common use cases.

I can't offer to help with the ReactorMaui code, still learning C#, I've spent the last 5 or so years working with Elm (MVU), which is why I was attracted to ReactorMaui, so would be more than happy to help out where I can.

How to navigate to another page when not on UI thread?

I asked this on Microsoft Q&A because I thought it was more of a Maui issue but was re-directed here.


I'm building a mobile and desktop app with Maui + MauiReactor that communicates with my server over Websockets. I have this working fine.

My problem is that if I try to Navigate to another page when I receive a Websocket reply with await Navigation.pushAsync<NewPage>(); I get the following error:

UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.

I understand why this happening, just not how best to handle it.

I can display a button after the message has been received, which the user can click to navigate which is obviously performing the navigaton on the UI thread due to the button click, but this feels really clunky. Is it possible to raise the process onto the UI thread so that I can programmatically navigate automatically?

My use case is as follows:

User starts the app, navigates to the sign in page, and enters credentials

Credentials get sent to my server over a websocket

Websocket reply confirms credentials and supplies a session token

Now I need to navigate to another page based on the current state of their profile settings i.e. if incomplete, go to profile page, if complete go back home. I would like this to be automatic without forcing the user to click a button to navigate.

Unmount page

Hello, I need to call an action for the disappearance of the page, but for some reason the page unmounting is not called. I created a test application with two pages. When I switching from one to the other, the OnMounted method was called once for the first page, and for the second page OnMounted was always called when I switched to it. OnWillUnmount was never called. Why is that?

My test code

public class FirstPage : Component
{
    protected override void OnWillUnmount()
    {
        Debug.WriteLine("OnWillUnmount FirstPage");
    }

    protected override void OnMounted()
    {
        Debug.WriteLine("OnMounted FirstPage");
    }

    public override VisualNode Render()
    {
        return new ContentPage()
        {
            new VStack()
                {
                    new Label("First!"),
                    new Button("Next")
                        .OnClicked(() => { Navigation?.PushAsync<SecondPage>(); })
                }
                .Spacing(20)
                .HCenter()
                .VCenter()
        }.Title("First");
    }
}

public class SecondPage : Component
{
    protected override void OnWillUnmount()
    {
        Debug.WriteLine("OnWillUnmount SecondPage");
    }

    protected override void OnMounted()
    {
        Debug.WriteLine("OnMounted SecondPage");
    }

    public override VisualNode Render()
    {
        return new ContentPage()
            {
                new VStack()
                    {
                        new Label("Second!"),
                        new Button("Back")
                            .OnClicked(() => { Navigation?.PopAsync(); })
                    }
                    .Spacing(20)
                    .HCenter()
                    .VCenter()
            }
            .Title("Second");
    }
}

public class App : Component
{
    public override VisualNode Render()
    {
        return new NavigationPage()
        {
            new FirstPage()
        }.Set(Microsoft.Maui.Controls.NavigationPage.BarTextColorProperty, Colors.White);
    }
}

Set Window size?

Hi Ado,

I've just started looking at Maui Reactor and really like what you're doing ๐Ÿ‘

Is it currently possible to set the window size for a Desktop app? I'm interested in setting the start up size along with minimums and maximums for height and width. I've been through the docs but couldn't find anything and I've seen some examples wrt Maui, but can't figure out how to use those with ReactorUI or if they're even relevant.

(I've just started my .NET journey, so it's all a bit new at the moment...)

Thanks
Paul

Is it possible to animate a strokeshape for border?

I tried to animate the Border corner radius by adding double CornerRadius as a state.

.StrokeShape(new RoundRectangle() .CornerRadius(() => new CornerRadius(State.CornerRadius)))

SetState((s) => { s.CornerRadius = v; },invalidateComponent:true);

  The above code does not animate the corner radius. How can it be achieved ? 

AnimationController question

@Otuyishime
I apologize I couldn't find anywhere else to ask you this question, but Is there a way to smoothly reverse animations with AnimationController? I've playing with it and it seems toggling IsEnabled resets controls to their original position.
You can use this small component as an example. Appreciated.

class AnimatedBoxState
{
public double Translate { get; set; } = 0.0;
public bool ToggleAnimation { get; set; } = false;
}

class AnimatedBox : Component
{
public override VisualNode Render()
{
return new ContentPage("Animated Box")
{
new Grid()
{
new AnimationController
{
new SequenceAnimation
{
new DoubleAnimation()
.StartValue(0)
.TargetValue(50)
.Duration(TimeSpan.FromMilliseconds(600))
.Easing(Easing.SinInOut)
.OnTick(v => SetState(s => s.Translate = v)),
}
.Loop(false)
}
.IsEnabled(State.ToggleAnimation)
.OnIsEnabledChanged(enabled => SetState(s => s.ToggleAnimation = enabled)),
new BoxView()
.GridRow(0)
.HCenter()
.VCenter()
.HeightRequest(80)
.WidthRequest(80)
.CornerRadius(10)
.TranslationX(State.Translate),
new Button("Animate")
.GridRow(1)
.HCenter()
.VCenter()
.WidthRequest(150)
.OnClicked(Toggle)
}
.Rows(new MauiControls.RowDefinitionCollection
{
new MauiControls.RowDefinition(),
new MauiControls.RowDefinition(GridLength.Auto)
})
.Padding(10)
.BackgroundColor(Colors.LightSkyBlue)
};
}

private void Toggle()
{
    SetState(s => s.ToggleAnimation = !s.ToggleAnimation);
}

}

Controls are not showing up inside a Grid.

I basically have a Grid parent with ScrollView
Grid("","")
{
ScrollView
{
Grid("Auto Auto","*")
{
Frame
{
Grid
{
Label(), // not showing up
Label() // not showing up
}
}.GridRow(0),
Frame
{
Grid
{
Label(), // not showing up
Label() // not showing up
}
}.GridRow(1)
}
}
};

here's the link for my repo. Thank you
repo link

Fi4MrAbX0AQ44la

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.