Subscribe now

Preparing for Fuse Native Apps [04.12.2017]

This week we're going to look at building cross-platform mobile apps with Fuse. It's a declarative take on native apps, which appeals to me. Let's go ahead and install the toolkit and build and modify a basic app.

Project

We'll start off by installing Fuse. On their website there's a Get Fuse now button that links to the downloads page. Right now you have to sign up for their open beta to get access. I've already done that, so I can just click the download link, but it's fast if you haven't as well.

Once you install it, you can just open it up and get started.

Building a basic project

Let's build a basic project. We'll open up Fuse and click on New Project. It'll use the Fuse Project template and we'll tell it to put it in ~/fuse and give it a name: Basic.

Now we can launch a preview. I'll start by launching a local preview. It builds for a while. Once it finally launches we have...a blank screen! Let's look at the code.

cd ~/fuse/Basic
vim MainView.ux
<App>
</App>

Well, that sure looks like a blank project. There was also a Basic.unoproj file created - let's look there:

{
  "RootNamespace":"",
  "Packages": [
    "Fuse",
    "FuseJS"
  ],
  "Includes": [
    "*"
  ]
}

Nothing important to discuss about this yet, just wanted to show that it was a thing. Next, let's look at the examples on the Fuse site and see if we can get something more interesting going. I think Tabs using LayoutMaster looks interesting, so let's look at it and start playing. We won't necessarily duplicate it exactly, but it's got some nice stuff to learn from.

First, we see that we can set the background color of our App node. Let's do that, using the DailyDrip blue:

<App Background="#4a90e2">
</App>

We can already see something awesome - at least for the local preview, we can see changes take place immediately. We can also use it in splitscreen mode, which isn't something you can do with the iOS simulator, so that makes me extra happy.

Now let's just put some text on the page.

<App Background="#4a90e2">
  <Text Value="Hello Potato!" />
</App>

If you test this on a device, the text will be covered up by the status bar. We can fix that by wrapping it in a ClientPanel node:

<App Background="#4a90e2">
  <ClientPanel>
    <Text Value="Hello Potato!" />
  </ClientPanel>
</App>

It doesn't make a difference when not testing on a device, but you want to do this. This still isn't amazing. It's hard to read. Let's change the color of the text and make it larger:

<App Background="#4a90e2">
  <ClientPanel>
    <Text Value="Hello Potato!" Color="#ffffff" FontSize=40 />
  </ClientPanel>
</App>

OK, so now we have some large text. Let's look at what it would take to create some tabs above the text, cribbing from the example. They use a Panel for each tab. A panel just gives its children all available space.

<App Background="#4a90e2">
  <ClientPanel>
    <Panel Color="#ffffff">
      <Text Value="Tab 1" Color="#00000" />
    </Panel>
    <Text Value="Hello Potato!" Color="#ffffff" FontSize=40 />
  </ClientPanel>
</App>

This isn't working out of the gate but I have no idea why. Let's kill the preview and start it using the command line tools.

fuse preview
Fuse 0.36.1 (build 12010)
Build started: FullCompile
Configuring
MainView.ux(4): E8001: Cannot parse '#00000' as 'float4': 'Invalid hex-code for 4-component vector, expected 3, 4, 6 or 8 digits'
/Users/jadams/fuse/Basic/MainView.ux(4,1): Error E8001: Cannot parse '#00000' as 'float4': 'Invalid hex-code for 4-component vector, expected 3, 4, 6 or 8 digits'

Build completed in 2.65 seconds
    1 error
Build ended
fuse: Failed to compile project

Oops. I left a 0 out of my hex code. Without running the preview myself I'm not sure where I would have seen that error log. Let's fix that.

Now we have our tab, sort of, but it's completely covering our background and other text content. Let's give it a height:

<App Background="#4a90e2">
  <ClientPanel>
    <Panel Color="#ffffff" Height=50>
      <Text Value="Tab 1" Color="#000000" />
    </Panel>
    <Text Value="Hello Potato!" Color="#ffffff" FontSize=40 />
  </ClientPanel>
</App>

Now it's the right height but it's centered. The ClientPanel is really just a DockPanel. That means we can dock things to its top and bottom. Let's dock the tab to the top:

<App Background="#4a90e2">
  <ClientPanel>
    <Panel Color="#ffffff" Height=50 Dock="Top">
      <Text Value="Tab 1" Color="#000000" />
    </Panel>
    <Text Value="Hello Potato!" Color="#ffffff" FontSize=40 />
  </ClientPanel>
</App>

Now this is starting to look alright. Next we'll use a Grid to add a second tab.

<App Background="#4a90e2">
  <ClientPanel>
    <Grid Height=50 Dock="Top" ColumnCount="2">
      <Panel Color="#ffffff">
        <Text Value="Tab 1" Color="#000000" />
      </Panel>
      <Panel Color="#ffffff">
        <Text Value="Tab 2" Color="#000000" />
      </Panel>
    </Grid>
    <Text Value="Hello Potato!" Color="#ffffff" FontSize=40 />
  </ClientPanel>
</App>

Let's center the text in these tabs:

    <Grid Height=50 Dock="Top" ColumnCount="2">
      <Panel Color="#ffffff">
        <Text Value="Tab 1" Color="#000000" Alignment="Center" />
      </Panel>
      <Panel Color="#ffffff">
        <Text Value="Tab 2" Color="#000000" Alignment="Center" />
      </Panel>
    </Grid>

It's kind of terrible that we had to do that twice. All of these elements are Classes. We can define our own class, so let's do that for tabs:

<App Background="#4a90e2">
  <Panel ux:Class="Tab" Color="#ffffff">
    <Text Value="Tab 1" Color="#000000" Alignment="Center" />
  </Panel>
  <ClientPanel>
    <Grid Height=50 Dock="Top" ColumnCount="2">
      <Tab />
      <Tab />
    </Grid>
    <Text Value="Hello Potato!" Color="#ffffff" FontSize=40 />
  </ClientPanel>
</App>

Of course now they both say the same thing. We can define a property that will be used for the text of each instance of the class:

<App Background="#4a90e2">
  <Panel ux:Class="Tab" Color="#ffffff">
    <string ux:Property="Text" />
    <Text Value="{ReadProperty Text}" Color="#000000" Alignment="Center" />
  </Panel>
  <ClientPanel>
    <Grid Height=50 Dock="Top" ColumnCount="2">
      <Tab Text="Tab 1" />
      <Tab Text="Tab 2" />
    </Grid>
    <Text Value="Hello Potato!" Color="#ffffff" FontSize=40 />
  </ClientPanel>
</App>

Neat!

Summary

That's all we have time for today. Tomorrow we'll look at elm-fuse. It's an elm interface for building Fuse apps. We'll keep building this app, adding navigation between tabs. If you look at the example code we were basing this episode on, you can perhaps figure out how navigation between pages works.

I hope you enjoyed this introduction to Fuse. See you soon!

Resources

Bonus

To handle Fuse in neovim I added this autocmd block:

augroup fuse
  autocmd!
  autocmd BufNewFile,BufRead *.ux setlocal filetype=xml
  autocmd BufNewFile,BufRead *.unoproj setlocal filetype=json
augroup END

However, I quickly moved on to this vim-fuse plugin.

Plug 'BeeWarloc/vim-fuse'