Skip to content

Template collocation #17

@clsource

Description

@clsource

Is possible to have a collocated mob file In the same spirit such as LiveView ?

Example.

Is the same file as the demo, but without the render function.

home_screen.ex

defmodule MiApp.HomeScreen do
  @moduledoc "Landing screen for MiApp."
  use Mob.Screen

  def mount(_params, _session, socket) do
    theme = Mob.State.get(:theme, :obsidian)
    Mob.Theme.set(theme_to_module(theme))
    {:ok, Mob.Socket.assign(socket, :theme, theme)}
  end

  def handle_info({:tap, :open_text}, socket) do
    {:noreply, Mob.Socket.push_screen(socket, MiApp.TextScreen)}
  end

  def handle_info({:tap, :open_list}, socket) do
    {:noreply, Mob.Socket.push_screen(socket, MiApp.ListScreen)}
  end

  def handle_info({:tap, :open_dice}, socket) do
    {:noreply, Mob.Socket.push_screen(socket, MiApp.DiceScreen)}
  end

  def handle_info({:tap, :open_webview}, socket) do
    {:noreply, Mob.Socket.push_screen(socket, MiApp.WebViewScreen)}
  end

  def handle_info({:tap, :open_audio}, socket) do
    {:noreply, Mob.Socket.push_screen(socket, MiApp.AudioScreen)}
  end

  def handle_info({:tap, :open_camera}, socket) do
    {:noreply, Mob.Socket.push_screen(socket, MiApp.CameraScreen)}
  end

  def handle_info({:tap, :open_storage}, socket) do
    {:noreply, Mob.Socket.push_screen(socket, MiApp.StorageScreen)}
  end

  def handle_info({:tap, :theme_obsidian}, socket) do
    Mob.Theme.set(Mob.Theme.Obsidian)
    Mob.State.put(:theme, :obsidian)
    {:noreply, Mob.Socket.assign(socket, :theme, :obsidian)}
  end

  def handle_info({:tap, :theme_citrus}, socket) do
    Mob.Theme.set(Mob.Theme.Citrus)
    Mob.State.put(:theme, :citrus)
    {:noreply, Mob.Socket.assign(socket, :theme, :citrus)}
  end

  def handle_info({:tap, :theme_birch}, socket) do
    Mob.Theme.set(Mob.Theme.Birch)
    Mob.State.put(:theme, :birch)
    {:noreply, Mob.Socket.assign(socket, :theme, :birch)}
  end

  def handle_info(_message, socket), do: {:noreply, socket}

  defp nav_button(label, tag) do
    tap = {self(), tag}
    ~MOB(<Button
  text={label}
  background={:primary}
  text_color={:on_primary}
  text_size={:lg}
  padding={:space_md}
  fill_width={true}
  on_tap={tap}
/>)
  end

  defp theme_tab(label, key, active) do
    {bg, fg} = if key == active, do: {:primary, :on_primary}, else: {:surface, :on_surface}
    tap = {self(), :"theme_#{key}"}
    ~MOB(<Button
  text={label}
  background={bg}
  text_color={fg}
  text_size={:sm}
  padding={:space_sm}
  weight={1}
  on_tap={tap}
/>)
  end

  defp theme_to_module(:citrus), do: Mob.Theme.Citrus
  defp theme_to_module(:birch), do: Mob.Theme.Birch
  defp theme_to_module(_), do: Mob.Theme.Obsidian

  defp logo_src(:birch), do: Path.join(rootdir(), "mob_logo_dark.png")
  defp logo_src(_), do: Path.join(rootdir(), "mob_logo_light.png")

  # ROOTDIR is set by mob_beam (iOS) and mob_beam.c (Android) before erl_start,
  # so this fallback is only exercised in unit tests on the host. Don't put
  # `Path.expand("~/...")` directly in `System.get_env/2`'s default argument —
  # default args evaluate eagerly, and Android's BEAM has no `HOME` env var,
  # so `System.user_home!()` would raise `RuntimeError` and abort the screen
  # before the first render.
  defp rootdir do
    case System.get_env("ROOTDIR") do
      nil -> Path.expand("~/.mob/runtime/ios-sim")
      val -> val
    end
  end
end

The contents of the render function is placed inside a mob.heex file.

home_screen.mob.heex

<Scroll background={:background}>
  <Column background={:background} padding={:space_lg}>
    <Image src={logo_src(assigns.theme)} width={120} height={120} content_mode="fit" />
    <Spacer size={16} />
    <Text text="MiApp" text_size={:xl} text_color={:on_surface} padding={:space_sm} />
    <Text text="BEAM running on device" text_size={:sm} text_color={:primary} padding={4} />
    <Spacer size={40} />
    {nav_button("Text Input",          :open_text)}
    <Spacer size={12} />
    {nav_button("Rock Paper Scissors", :open_list)}
    <Spacer size={12} />
    {nav_button("Roll Dice",           :open_dice)}
    <Spacer size={12} />
    {nav_button("WebView",             :open_webview)}
    <Spacer size={12} />
    {nav_button("Audio",               :open_audio)}
    <Spacer size={12} />
    {nav_button("Camera",              :open_camera)}
    <Spacer size={12} />
    {nav_button("Storage",             :open_storage)}
    <Spacer size={32} />
    <Text text="Theme" text_size={:sm} text_color={:muted} padding={4} />
    <Spacer size={8} />
    <Row fill_width={true}>
      {theme_tab("Obsidian", :obsidian, assigns.theme)}
      <Spacer size={8} />
      {theme_tab("Citrus",   :citrus,   assigns.theme)}
      <Spacer size={8} />
      {theme_tab("Birch",    :birch,    assigns.theme)}
    </Row>
  </Column>
</Scroll>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions