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>
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
The contents of the render function is placed inside a mob.heex file.
home_screen.mob.heex