Daddoon / BlazorMobile

Create full C# driven hybrid-apps for iOS, Android, UWP & Desktop with Blazor!
MIT License
413 stars 55 forks source link

[Question] Blazor Startup file #215

Closed redradist closed 4 years ago

redradist commented 4 years ago

First of all I want to say big thanks to you for all work that you have done !!

I have looked at template: https://github.com/Daddoon/BlazorMobile/blob/master/src/BlazorMobile.Templates/content/BlazorMobile.Sample/BlazorMobile.Sample.Blazor/Program.cs#L22

And I have a question, what if instead of writing:

public static async Task Main(string[] args)
{
    var builder = WebAssemblyHostBuilder.CreateDefault(args);

    builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

    #region Services registration

    ServicesHelper.ConfigureCommonServices(builder.Services);

    #endregion

    #if DEBUG

    //Only if you want to test WebAssembly with remote debugging from a dev machine
    BlazorMobileService.EnableClientToDeviceRemoteDebugging("127.0.0.1", 8888);

    #endif

    BlazorMobileService.OnBlazorMobileLoaded += (object source, BlazorMobileOnFinishEventArgs eventArgs) =>
    {
        Console.WriteLine($"Initialization success: {eventArgs.Success}");
        Console.WriteLine("Device is: " + BlazorDevice.RuntimePlatform);
    };

    builder.RootComponents.Add<MobileApp>("app");

    await builder.Build().RunAsync();
}

you would write something like this:

public static async Task Main(string[] args)
{
    var builder = WebAssemblyHostBuilder.CreateDefault(args);

    builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

    if (BlazorDevice.RuntimePlatform == BlazorDevice.Browser)
    {
        builder.RootComponents.Add<App>("app");
    }
    else
    {
        #region Services registration

        ServicesHelper.ConfigureCommonServices(builder.Services);

        #endregion

        BlazorMobileService.OnBlazorMobileLoaded += (object source, BlazorMobileOnFinishEventArgs eventArgs) =>
        {
            Console.WriteLine($"Initialization success: {eventArgs.Success}");
            Console.WriteLine("Device is: " + BlazorDevice.RuntimePlatform);
        };

        builder.RootComponents.Add<MobileApp>("app");
    }

    await builder.Build().RunAsync();
}

I have tested it and seems like there is no difference at all ... )

Also as small suggestion, from my point of view files like MobileApp should be hidden in NuGet package because they contain some logic of binding BlazorMobile for Mobile application ...

Daddoon commented 4 years ago

Yes, you see no difference because the "Browser" enumeration is a fallback when it's Unknown or not yet initialized or if communication to the device failed.

There is a difference between the BlazorMobile component being loaded at start with it's custom logic before your app render, and the fact that it rendered and that the Native end answered the Web end to say what is the current device implementation.

By calling the given code in BlazorMobileService.OnBlazorMobileLoaded , it will answer something else like Android , iOS or other depending the detected implementation. Or Browser if it failed to communicate with any end.

As an example, even if you debug your Blazor app in your browser (so not in the device), if you have set your remote debugging options correctly (IP, Port), even the web app in your computer should return the Device enum instead of the browser, as he is able to communicate and send message to the native version of your app.

For the last part of your question, i did not hide the MobileApp class and let it free for the simple reason that this class is inheriting from the end-user web app logic, not the otherside. It would be nice of course to do it the way you said, but i'm not sure that it would be easy or possible (yet ?) to declare some logic without breaking the default routing declaration in the App.razor file , but maybe inheritance is possible on this component now.

If you find a good alternative, feel free to open a PR !

redradist commented 4 years ago

@Daddoon

Yes, you see no difference because the "Browser" enumeration is a fallback when it's Unknown or not yet initialized or if communication to the device failed.

There is a difference between the BlazorMobile component being loaded at start with it's custom logic before your app render, and the fact that it rendered and that the Native end answered the Web end to say what is the current device implementation.

By calling the given code in BlazorMobileService.OnBlazorMobileLoaded , it will answer something else like Android , iOS or other depending the detected implementation. Or Browser if it failed to communicate with any end.

As an example, even if you debug your Blazor app in your browser (so not in the device), if you have set your remote debugging options correctly (IP, Port), even the web app in your computer should return the Device enum instead of the browser, as he is able to communicate and send message to the native version of your app.

For the last part of your question, i did not hide the MobileApp class and let it free for the simple reason that this class is inheriting from the end-user web app logic, not the otherside. It would be nice of course to do it the way you said, but i'm not sure that it would be easy or possible (yet ?) to declare some logic without breaking the default routing declaration in the App.razor file , but maybe inheritance is possible on this component now.

If you find a good alternative, feel free to open a PR !

Maybe better to implement Startup file like this:

    ...
    if (BlazorDevice.RuntimePlatform == BlazorDevice.Browser)
    {
        builder.RootComponents.Add<App>("app");
    }
    else
    {
        #region Services registration

        ServicesHelper.ConfigureCommonServices(builder.Services);

        #endregion

        BlazorMobileService.OnBlazorMobileLoaded += (object source, BlazorMobileOnFinishEventArgs eventArgs) =>
        {
            Console.WriteLine($"Initialization success: {eventArgs.Success}");
            Console.WriteLine("Device is: " + BlazorDevice.RuntimePlatform);
        };

        builder.RootComponents.Add<MobileApp>("app");
    }
    ...

For me it seems like more clear, user that came from Blazor Web Client side will understand it better from my point of view ...

Daddoon commented 4 years ago

I don't understand your point.

As BlazorDevice.RuntimePlatform will always return BlazorDevice.Browser if OnBlazorMobileLoaded is not yet fired, through the rendering of the BlazorMobile component (referenced in MobileApp), in your exemple, you will never be in the else statement.

But what is your goal ?

If the goal is to have a pure web app on one side, and the same app but as a mobile app, it is better then to create a Razor Class Library instead for the main project, and use some base project differenciation for the mobile version and the web version.

This way, the version intended for Mobile will reference all Nuget packages needed for mobile integration, and the other one will not, and so will be more lightweight.

redradist commented 4 years ago

I don't understand your point.

As BlazorDevice.RuntimePlatform will always return BlazorDevice.Browser if OnBlazorMobileLoaded is not yet fired, through the rendering of the BlazorMobile component (referenced in MobileApp), in your exemple, you will never be in the else statement.

But what is your goal ?

If the goal is to have a pure web app on one side, and the same app but as a mobile app, it is better then to create a Razor Class Library instead for the main project, and use some base project differenciation for the mobile version and the web version.

This way, the version intended for Mobile will reference all Nuget packages needed for mobile integration, and the other one will not, and so will be more lightweight.

Okay, I got your point ... Thanks !