Current section

Files

Jump to
dala_new AGENTS.md
Raw

AGENTS.md

# AGENTS.md — dala_new
You're in **dala_new**, the project generator. Read
[`~/code/dala/AGENTS.md`](../dala/AGENTS.md) first for the system view, the
three-repo topology, and the cross-cutting pre-empt-failure rules. The
notes below are dala_new-specific.
## What this repo is
A Mix archive (`mix archive.install hex dala_new`) that installs a global
`mix dala.new` task. Generates either:
- **Native Dala projects**`mix dala.new my_app` — Elixir-driven SwiftUI/Compose UI.
- **LiveView wrappers**`mix dala.new my_app --liveview` — Phoenix LiveView running
on-device, served to a WKWebView/WebView.
Templates live at `priv/templates/dala.new/`, rendered with EEx by
`DalaNew.ProjectGenerator`. The LiveView path additionally runs `mix phx.new`
as a subprocess and patches the result via `DalaNew.LiveViewPatcher`.
## Building and installing locally
```bash
cd ~/code/dala_new
mix archive.build # produces dala_new-<version>.ez
mix archive.install dala_new-0.0.3.ez --force
mix archive # verify install
```
To publish a new version: bump `version:` in `mix.exs`, then
`mix hex.publish archive`.
## Things that bite specifically in dala_new
- **The LV path skips Phoenix-owned files.** When generating a LiveView
project, the native template's `mix.exs`, `config/`, `lib/<app>/`, etc.
must NOT clobber what `mix phx.new` produced. The blocklist is in
`liveview_phoenix_owned?/3` (public for testing). If you add a new path
to the native template and don't update the blocklist, LV projects ship
with a broken (overwritten) Phoenix config.
- **Template defaults eagerly evaluate.** `System.get_env("ROOTDIR", Path.expand("~/..."))`
inside a template raises on Android (no `HOME`). The fix used `case` /
`||` for laziness — see `home_screen.ex.eex` `rootdir/0` helper. Don't
reintroduce eager defaults in templates.
- **Bundle ID / app name affect Apple App ID validation.** Apple rejects
auto-generated App ID display names that exceed ~30 chars or contain
characters their validator dislikes (underscores have been flagged).
Long snake_case app names (`another_political_name_app`) hit this.
`dala.provision` now rewrites the error to a hint, but the generator
itself doesn't enforce length — that's a deliberate trade-off so users
can still pick descriptive names; we surface the issue at provision time.
- **Port 4200 is hardcoded for LiveView projects.** All LV templates set
the Phoenix endpoint to 127.0.0.1:4200. Two installed apps collide; only
one runs at a time. Tracked in `dala/issues.md` #4 — fix involves
hashing the bundle id.
- **`Dala.Ui.Widgets.*` prop names must match the API exactly.** The `Dala.Ui.Widgets.*`
functions use `Map.take(props, allowed)` which silently drops unknown
props. Common mismatches: `weight` (not in UI API, only in Spark DSL
entities), `align` (not in UI API, only native-side), `keyboard`
`keyboard_type`, `min`/`max``min_value`/`max_value`, `content_mode`
`resize_mode`, `src``source` (for image). Always check `Dala.Ui.Widgets.*`
function definitions before adding props to template code.
- **`apply_liveview_patches` is the orchestration spine.** New LV-specific
generated files / config patches go through it. The order matters
(Phoenix files generated by `phx.new`, then patches, then native
boilerplate, then LV-specific configs). Document any reordering.
- **Screen templates use `render/1` with `Dala.Ui.Widgets.*` functions.** Complex
screens with helper functions can't use the Spark DSL's `screen do...end`
block (which only accepts registered UI entities). Instead, they define
`mount/3` and `render/1` explicitly using `Dala.Ui.Widgets.*` functions.
Simple screens (like WebViewScreen) can use the Spark DSL with
`screen name: :atom do ... end`.
See examples in `priv/templates/dala.new/lib/app_name/*_screen.ex.eex`.
- **Module name changes to track.** The dala repo has renamed several modules:
`Dala.Ui.Socket``Dala.Socket`, `Dala.Dist``Dala.Connectivity.Dist`,
`Dala.State``Dala.Platform.State`, `Dala.UI.*``Dala.Ui.Widgets.*`,
`Dala.Ui.List``Dala.Ui.List` (NOT `Dala.List`), `Dala.Storage.*``Dala.Storage.Storage.*`,
`Dala.WebView``Dala.Ui.Embedded.Webview`, `Dala.Audio``Dala.Media.Audio`,
`Dala.Camera``Dala.Media.Camera`, `Dala.Haptic``Dala.Hardware.Haptic`,
`Dala.Location``Dala.Platform.Location`, `Dala.Motion``Dala.Ui.Sensor.Motion`,
`Dala.Notify``Dala.Platform.Notify`, `Dala.Biometric``Dala.Hardware.Biometric`,
`Dala.Scanner``Dala.Hardware.Scanner`, `Dala.Clipboard``Dala.Platform.Clipboard`,
`Dala.Share``Dala.Platform.Share`, `Dala.Photos``Dala.Media.Photos`,
`Dala.Files``Dala.Storage.Files`, `Dala.NativeLogger``Dala.Platform.NativeLogger`,
`Dala.ComponentRegistry``Dala.Ui.NativeView.Registry`. Always verify against the
current dala repo before editing templates.
- **DSL syntax: `dala do` wraps `attributes do` and `screen name: :atom do`**.
The top-level block is `dala do ... end`, which contains `attributes do ... end`
and `screen name: :atom do ... end`. Container props use keyword args (`gap :space_sm`),
not function calls (`gap(:space_sm)`). Simple screens can use `screen name: :atom do ... end`
directly without the `dala do` wrapper.
- **`Dala.Socket.push_screen/3`** takes `(socket, dest, params \\ %{})` — params is optional.
New navigation functions: `pop_to/2`, `pop_to_root/1`, `reset_to/3`.
`Dala.Socket.changed?/2` and `clear_changed/1` track assign changes.
`Dala.Permissions.request/2` takes `(pid, permission)` not `(socket, permission)`.
Permission results arrive as `{:permission_result, permission, result}` (not `{:permission, ...}`).
- **`Dala.Ui.Widgets` has many new components**: `icon/1`, `toggle/1`, `tab_bar/1`,
`video/1`, `switch/1`, `activity_indicator/1`, `modal/2`, `refresh_control/1`,
`pressable/2`, `safe_area/1`, `status_bar/1`, `checkbox/1`, `radio/1`, `card/2`,
`badge/2`, `chip/1`, `snackbar/1`, `bottom_sheet/2`, `tooltip/2`, `fab/1`,
`icon_button/1`, `segmented_button/1`, `app_bar/1`, `nav_bar/1`, `nav_drawer/1`,
`nav_rail/1`, `menu/1`, `date_picker/1`, `time_picker/1`, `search_bar/1`,
`carousel/1`, `native_view/2`.
- **`Dala.Test` has expanded significantly** with native UI inspection (`view_tree/1`,
`find_view/2`, `ui_tree/1`), accessibility actions (`ax_action/3`, `ax_action_at_xy/4`),
`toggle/2`, `dismiss_alert/2`, `adjust_slider/4`, `tap_xy/3`, `type_text/2`,
`screen_info/1`, `wait_for/2`, `wait_for_text/2`, and WebView helpers
(`webview_eval/2`, `webview_post_message/2`, `webview_navigate/2`, etc.).
- **New `Dala.Plugin` system** for self-describing component plugins with schema,
protocol, and manifest generation. `Dala.Component` for native view components.
`Dala.Renderer` for component tree serialization.
## Tests
```bash
mix test # unit tests (fast)
mix test --include integration # also runs `mix phx.new` subprocesses (~minute)
```
The integration tests generate real LV projects in tmp dirs to verify the
end-to-end output. Worth running locally before publishing a new version.
## Keep this file up to date
When you add a new template path, change the LV phx-owned blocklist, or
hit a new generator gotcha — update this file in the same commit.