Fabulous icon indicating copy to clipboard operation
Fabulous copied to clipboard

Create iOS extensions with Fabulous

Open bengobeil opened this issue 3 years ago • 5 comments

Hi, I am trying to create a Share Extension for a Fabulous app. The process of creating these extensions are explained here: https://docs.microsoft.com/en-us/xamarin/ios/platform/extensions

I am wondering how to create and call a Fabulous program loop from these extensions. Are there any existing samples of this and/or do we know if this feasible to do with a Fabulous approach vs native or Xamarin.Forms?

Thanks for the help, Ben

bengobeil avatar Aug 17 '20 02:08 bengobeil

Hi Ben,

Fabulous works on top of Xamarin.Forms, so it could theoretically run anywhere XF is supported. After looking at the documentation for XF/Share extensions, it seems to use the integration of Xamarin.Forms into a native view, aka "Native Forms".

Today, Fabulous doesn't support it as the program loop is tied to a Xamarin.Forms.Application instance which a share extension wouldn't have. That said, I have already validated that we can make Fabulous work against any XF control instead of just a Xamarin.Forms.Application. (see https://github.com/fsprojects/Fabulous/issues/738#issuecomment-626354644)

Didn't had time to integrate that new feature for now, but if you want, you can make your own Fabulous Host with a couple lines of code to see if you can write your share extension with Fabulous.

We would gladly accept a PR if that's the case.

For the modification, see this code: https://github.com/fsprojects/Fabulous/blob/dda14abbf1d906de2fe576a4e7940bc94eb4df8c/Fabulous.XamarinForms/src/Fabulous.XamarinForms.Core/Program.fs#L8-L18

Fabulous will consume the IHost interface, so you can implement a XamarinFormsContentPageHost that takes a ContentPage instead of an Application. The GetRootView and SetRootView methods would get/set the Content property.

Then you can write a few functions to be able to write |> Program.runContentPage ... https://github.com/fsprojects/Fabulous/blob/dda14abbf1d906de2fe576a4e7940bc94eb4df8c/Fabulous.XamarinForms/src/Fabulous.XamarinForms.Core/Program.fs#L53-L61

You would write your Fabulous app as usual, except for the App class

module ShareExt =
    type Model = ...
    type Msg = ...

    let init () = ...
    let update msg model = ...

    let view model dispatch =
        View.Grid(...) // Here, make sure you don't use a Page but a Control directly since the parent will be a ContentPage

type MyShareExtContentPage() as this =
    inherit Xamarin.Forms.ContentPage()

    let runner =
        XamarinFormsProgram.mkProgram init update view
        |> XamarinFormsProgram.runContentPage this

Then in your share extension, you can write

member this.ViewDidLoad() =
    global::Xamarin.Forms.Forms.Init()

    let xfPage = new MyShareExtContentPage()
    let newController = xfPage.CreateViewController()
    this.PresentModalViewController(newController, false)

TimLariviere avatar Aug 17 '20 08:08 TimLariviere

Thanks for the incredibly detailed response. I will try it out and submit a PR if it works as well as described.

bengobeil avatar Aug 17 '20 11:08 bengobeil

I suggest having some documentation for running any XF component as a Fabulous program. Seems like a very useful thing to know.

bengobeil avatar Aug 17 '20 11:08 bengobeil

I suggest having some documentation for running any XF component as a Fabulous program. Seems like a very useful thing to know.

It's not an official feature yet. Only something I know is possible for simple use cases. We still need to change a few things inside Fabulous to fully support this. For instance, currently, only one Fabulous program loop can be active at any single time in the whole application, thus preventing having multiple XF components using Fabulous inside a single app.

But it's a planned feature. Once we add it, the documentation will be available as well. :)

TimLariviere avatar Aug 17 '20 12:08 TimLariviere

OK I understand. Well, looks like it works, I haven't done any dynamic views yet but static ones work.

bengobeil avatar Aug 18 '20 10:08 bengobeil