adospace / reactorui-maui

MauiReactor is a MVU UI framework built on top of .NET MAUI
MIT License
588 stars 49 forks source link

How do I re-render the Flyout Icons on app shell to use State values #241

Closed licon4812 closed 3 months ago

licon4812 commented 3 months ago

I have the following Appshell code


using RandomNumberGenerator.Maui.Pages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MauiReactor;
using UraniumUI.Icons;
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Controls.Xaml;
using Microsoft.Maui.Storage;
using RandomNumberGenerator.Maui.Services;

namespace RandomNumberGenerator.Maui
{
    internal class AppsShellState
    {
        public Color IconsColor { get; set; } = MauiControls.Application.Current!.UserAppTheme switch
        {
            AppTheme.Dark => Colors.White,
            AppTheme.Light => Colors.Black,
            _ => Colors.Black
        };
    }

    internal class AppShell : Component<AppsShellState>
    {
        protected override async void OnMountedOrPropsChanged()
        {
            base.OnMountedOrPropsChanged();
            var savedTheme = await SecureStorage.GetAsync("Theme") ?? "System Default";
            SettingsService.SetTheme(savedTheme);
            MauiControls.Application.Current!.RequestedThemeChanged += (s, e) =>
            {
                var color = e.RequestedTheme switch
                {
                    AppTheme.Dark => Colors.White,
                    AppTheme.Light => Colors.Black,
                    _ => Colors.Black
                };
                SetState(s=>s.IconsColor = color);
                Render();
            };
        }

        public override VisualNode Render()
            => new Shell
            {
                new FlyoutItem("Number Generator")
                {
                    new ShellContent()
                        .Title("Number Generator")
                        .RenderContent(()=>new NumberGeneratorPage())
                }
                    .MaterialIcon(UraniumUI.Icons.MaterialSymbols.MaterialOutlined.Casino,State.IconsColor),
                new FlyoutItem("Decision Maker")
                {
                    new ShellContent()
                        .Title("Decision Maker")
                        .RenderContent(()=>new DecisionMakerPage())
                }
                    .MaterialIcon(UraniumUI.Icons.MaterialSymbols.MaterialOutlined.List_alt, State.IconsColor),
                new FlyoutItem("Email Generator")
                {
                    new ShellContent()
                        .Title("Email Generator")
                        .RenderContent(()=>new EmailGeneratorPage())
                }
                    .MaterialIcon(UraniumUI.Icons.MaterialSymbols.MaterialOutlined.Mail, State.IconsColor),
            }
            .FlyoutFooter(new Label().Text($"Version: {AppInfo.Current.VersionString}")
                .HorizontalTextAlignment(TextAlignment.Center)
            )
            .ItemTemplate(RenderItemTemplate);

        static VisualNode RenderItemTemplate(MauiControls.BaseShellItem item)
            => new Grid("68", "*")
            {
                new HStack()
                    {
                        new Image()
                            .Source(item.FlyoutIcon)
                            .HStart()
                            .Scale(0.5),

                        new Label(item.Title)
                            .VCenter()
                            .Margin(10, 0)
                    }
            };
    }

    public static class FlyoutItemExtensions
    {
        public static T MaterialIcon<T>(this T item, string icon, Color color) where T : FlyoutItem
        {
            item.FlyoutIcon(new MauiControls.FontImageSource
            {
                Glyph = icon,
                FontFamily = "MaterialOutlined",
                Size = 32,
                Color = color
            });
            return item;
        }
    }
}

I have confirmed that the state values are updating correctly, however, the icons aren't being rendered

adospace commented 3 months ago

Hi,

I've created a sample that shows how to achieve what you need: https://github.com/adospace/mauireactor-integration/tree/main/UraniumUI/TestCase241

Generally speaking, you should avoid adding logic to State classes that instead must be just pocos. Also, MauiReactor already offers a streamlined approach to handling theme changes (for example the current component is automatically invalidated as theme changes).

Please look at the above code and let me know if something is unclear.

licon4812 commented 3 months ago

Hi,

I've created a sample that shows how to achieve what you need: https://github.com/adospace/mauireactor-integration/tree/main/UraniumUI/TestCase241

Generally speaking, you should avoid adding logic to State classes that instead must be just pocos. Also, MauiReactor already offers a streamlined approach to handling theme changes (for example the current component is automatically invalidated as theme changes).

Please look at the above code and let me know if something is unclear.

Thank you very much for the assistance 🙂. I was missing the AppTheme custom class and relying only on the Colors.xml and Styles.xml.