Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/eval_in_wasm_build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ jobs:
cache-dependency-path: pnpm-lock.yaml

- name: Install JS dependencies
env:
# Required by tree-sitter native bindings which use C++20 features
# and fail to compile without this flag on the default GCC version in CI.
CXXFLAGS: "-std=c++20"
Comment on lines +59 to +62

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to leave a comment why we need it so we can remove it later if it stops being necessary.

run: pnpm install
working-directory: .

Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/hello_popcorn_build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ jobs:
cache-dependency-path: pnpm-lock.yaml

- name: Install JS dependencies
env:
# Required by tree-sitter native bindings which use C++20 features
# and fail to compile without this flag on the default GCC version in CI.
CXXFLAGS: "-std=c++20"
run: pnpm install
working-directory: .

Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/langtour_e2e_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ jobs:
working-directory: language-tour/elixir_tour

- name: Install pnpm dependencies
env:
# Required by tree-sitter native bindings which use C++20 features
# and fail to compile without this flag on the default GCC version in CI.
CXXFLAGS: "-std=c++20"
run: pnpm install --frozen-lockfile

- name: Build popcorn JS package
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/local_live_view_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ jobs:
cache-dependency-path: pnpm-lock.yaml

- name: Install JS dependencies
env:
# Required by tree-sitter native bindings which use C++20 features
# and fail to compile without this flag on the default GCC version in CI.
CXXFLAGS: "-std=c++20"
run: pnpm install
working-directory: .

Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/otp_js_e2e_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ jobs:
cache-dependency-path: pnpm-lock.yaml

- name: Install JS dependencies
env:
# Required by tree-sitter native bindings which use C++20 features
# and fail to compile without this flag on the default GCC version in CI.
CXXFLAGS: "-std=c++20"
run: pnpm install

- name: Setup Playwright
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/popcorn_build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ jobs:

- name: Install JS dependencies
working-directory: .
env:
# Required by tree-sitter native bindings which use C++20 features
# and fail to compile without this flag on the default GCC version in CI.
CXXFLAGS: "-std=c++20"
run: pnpm install

- name: Setup Playwright
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/popcorn_js_e2e_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ jobs:
cache-dependency-path: pnpm-lock.yaml

- name: Install JS dependencies
env:
# Required by tree-sitter native bindings which use C++20 features
# and fail to compile without this flag on the default GCC version in CI.
CXXFLAGS: "-std=c++20"
run: pnpm install

- name: Build popcorn JS package
Expand Down
2 changes: 1 addition & 1 deletion examples/local-lv-forms/assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
font-size: 15px;
}

.title {
h1 {
padding: 30px 25px;
font-size: 30px;
font-weight: bold;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="page">
<p class="title centered">LocalLiveView & Phoenix Integration: Forms Demo</p>
<h1 class="centered">LocalLiveView & Phoenix Integration: Forms Demo</h1>
<div class="centered-div description">
<p>Explore seamless form handling and LocalLiveView integration.</p>
<p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule FormDemoWeb.FormDemoLive do
<div class="centered-div">
<.local_live_view id={"form-demo-local-#{@socket.id}"} view="FormDemoLocal" />
<div class="bordered">
<h1>[Server Runtime] User List:</h1>
<h2>[Server Runtime] User List:</h2>
<ul>
<%= for user <- @users do %>
<li>Username: {user["username"]}, Email: {user["email"]}</li>
Expand Down
22 changes: 13 additions & 9 deletions examples/local-lv-forms/local/lib/form_demo_local.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,26 @@ defmodule FormDemoLocal do
@impl true
def render(assigns) do
~H"""
<h2 class="header">Add new user</h2>
<div class="bordered">
<.form for={@form} id={@form.id} phx-change="validate" phx-submit="save">
<label>USERNAME</label>
<.input type="text" field={@form[:username]} />
<.input type="text" field={@form[:username]} placeholder="at least 4 characters" />
<label>EMAIL</label>
<.input type="text" field={@form[:email]} />
<div class="centered">
<button class="ghost-button" disabled={@disabled}>SAVE</button>
<.input type="text" field={@form[:email]} placeholder="name@domain.com" />
<div class="buttons">
<button type="submit" class="ghost-button" disabled={@disabled}>SAVE</button>
<button type="button" class="ghost-button" phx-click="generate_random">
GENERATE RANDOM
</button>
</div>
</.form>
<div class="centered">
<button class="ghost-button" phx-click="generate_random">GENERATE RANDOM</button>
</div>
</div>
<div class="bordered">
<h1>[Local Runtime] User List:</h1>
<div class="bordered" data-value="users-list">
<h2 class="title">[Local Runtime] User List:</h2>
<%= if Enum.empty?(@users) do %>
<p>No users yet - save one above</p>
<% end %>
<ul>
<%= for user <- @users do %>
<li>Username: {user.username}, Email: {user.email}</li>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
defmodule FormDemoLocalPresentation do
use LocalLiveView

defdelegate render(assigns), to: FormDemoLocal

def mount(params, session, socket) do
result = FormDemoLocal.mount(params, session, socket)
{:ok, new_socket} = result

Popcorn.Wasm.send_event("llv_presentation", %{
block: nil,
event: "mount",
assigns: presentation_assigns(new_socket)
})

result
end

def handle_event(event, params, socket)
when event in ~w(validate save generate_random) do
# The UI socket lags behind the real state during animation; apply pending
# assigns so the event handler sees up-to-date data.
effective_socket =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is weird:

  1. why the assign starts with underscore?
  2. do we need two versions of socket?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a workaround to keep track of the previous event, allowing the animation to continue when the user spams events and executing the animation with the last pending update value

case socket.assigns[:pending_cur] do
nil -> socket
pending -> assign(socket, Map.to_list(pending))
end

{:noreply, updated} = FormDemoLocal.handle_event(event, params, effective_socket)

Popcorn.Wasm.send_event("llv_presentation", %{
block: event,
event: event,
assigns: presentation_assigns(updated)
})

new_pending = %{
form: updated.assigns.form,
disabled: updated.assigns.disabled,
users: updated.assigns.users
}

{:noreply,
socket
|> assign(:pending_prev, socket.assigns[:pending_cur])
|> assign(:pending_cur, new_pending)}
end

def handle_info({:js_push, "llv_ack", _}, socket) do
case {socket.assigns[:pending_prev], socket.assigns[:pending_cur]} do
{%{form: form, disabled: disabled, users: users}, _} ->
{:noreply, assign(socket, form: form, disabled: disabled, users: users, pending_prev: nil)}

{nil, %{form: form, disabled: disabled, users: users}} ->
{:noreply, assign(socket, form: form, disabled: disabled, users: users, pending_cur: nil)}

_ ->
{:noreply, socket}
end
end

def handle_event(event, params, socket) do
FormDemoLocal.handle_event(event, params, socket)
end

defp presentation_assigns(socket) do
assigns = socket.assigns
form_params = assigns.form.params

%{
username: Map.get(form_params, "username", ""),
email: Map.get(form_params, "email", ""),
disabled: assigns.disabled,
users: length(assigns.users)
}
end
end
12 changes: 12 additions & 0 deletions examples/local-lv-forms/local/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule Local.MixProject do
version: "0.1.0",
elixir: "~> 1.17",
start_permanent: Mix.env() == :prod,
elixirc_paths: elixirc_paths(),
deps: deps(),
compilers: Mix.compilers(),
aliases: aliases()
Expand All @@ -17,6 +18,17 @@ defmodule Local.MixProject do
[default_target: :wasm]
end

# lib_landing contains presentation wrappers that emit WASM events for the
# landing page animation demos. They are compiled only when building for that
# context so normal development builds stay unaffected.
defp elixirc_paths do
if System.get_env("LLV_LANDING_PATCH") == "true" do
["lib", "lib_landing"]
else
["lib"]
end
Comment on lines +25 to +29

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Why we need that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To separate landing page versions that handle event modification from those kept as the normal example

end

def application do
[
extra_applications: [:logger],
Expand Down
4 changes: 2 additions & 2 deletions examples/local-lv-forms/local/mix.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
%{
"decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},
"decimal": {:hex, :decimal, "2.4.1", "6c0fbede12fb122ba685e9ab41c6a40c129e322b3aa192f9e072e61f3a6ffaf2", [:mix], [], "hexpm", "7e618897933a8455f19a727d7c5e50a2c071a544b700e5e724298ecb4340187f"},
"ecto": {:hex, :ecto, "3.13.5", "9d4a69700183f33bf97208294768e561f5c7f1ecf417e0fa1006e4a91713a834", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df9efebf70cf94142739ba357499661ef5dbb559ef902b68ea1f3c1fabce36de"},
"expo": {:hex, :expo, "1.1.1", "4202e1d2ca6e2b3b63e02f69cfe0a404f77702b041d02b58597c00992b601db5", [:mix], [], "hexpm", "5fb308b9cb359ae200b7e23d37c76978673aa1b06e2b3075d814ce12c5811640"},
"file_system": {:hex, :file_system, "1.1.1", "31864f4685b0148f25bd3fbef2b1228457c0c89024ad67f7a81a3ffbc0bbad3a", [:mix], [], "hexpm", "7a15ff97dfe526aeefb090a7a9d3d03aa907e100e262a0f8f7746b78f8f87a5d"},
Expand All @@ -8,7 +8,7 @@
"glob_ex": {:hex, :glob_ex, "0.1.11", "cb50d3f1ef53f6ca04d6252c7fde09fd7a1cf63387714fe96f340a1349e62c93", [:mix], [], "hexpm", "342729363056e3145e61766b416769984c329e4378f1d558b63e341020525de4"},
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
"igniter": {:hex, :igniter, "0.7.9", "8c573440b8127fd80be8220fb197e7422317a81072054fcc0b336029f035a416", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "123513d09f3af149db851aad8492b5b49f861d2c466a72031b2a0cbd9f45526f"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"},
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
"mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
Expand Down
4 changes: 2 additions & 2 deletions examples/local-lv-forms/mix.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%{
"bandit": {:hex, :bandit, "1.10.4", "02b9734c67c5916a008e7eb7e2ba68aaea6f8177094a5f8d95f1fb99069aac17", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "a5faf501042ac1f31d736d9d4a813b3db4ef812e634583b6a457b0928798a51d"},
"cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"},
"decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},
"decimal": {:hex, :decimal, "2.4.1", "6c0fbede12fb122ba685e9ab41c6a40c129e322b3aa192f9e072e61f3a6ffaf2", [:mix], [], "hexpm", "7e618897933a8455f19a727d7c5e50a2c071a544b700e5e724298ecb4340187f"},
"dns_cluster": {:hex, :dns_cluster, "0.2.0", "aa8eb46e3bd0326bd67b84790c561733b25c5ba2fe3c7e36f28e88f384ebcb33", [:mix], [], "hexpm", "ba6f1893411c69c01b9e8e8f772062535a4cf70f3f35bcc964a324078d8c8240"},
"ecto": {:hex, :ecto, "3.13.5", "9d4a69700183f33bf97208294768e561f5c7f1ecf417e0fa1006e4a91713a834", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df9efebf70cf94142739ba357499661ef5dbb559ef902b68ea1f3c1fabce36de"},
"elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
Expand All @@ -16,7 +16,7 @@
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"igniter": {:hex, :igniter, "0.7.9", "8c573440b8127fd80be8220fb197e7422317a81072054fcc0b336029f035a416", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "123513d09f3af149db851aad8492b5b49f861d2c466a72031b2a0cbd9f45526f"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"},
"lazy_html": {:hex, :lazy_html, "0.1.11", "136c8e9cd616b4f4e9c1562daa683880891120b759606dc4c3b6b18058ba5d79", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9.0", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "3b1be592929c31eca1a21673d25696e5c14cddfe922d9d1a3e3b48be4163883b"},
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
"mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"},
Expand Down
27 changes: 13 additions & 14 deletions examples/local-lv-thermostat/local/lib/thermostat_live.ex
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
defmodule ThermostatLive do
use LocalLiveView

@default_temperature 25
@default_country "Poland"

def render(assigns) do
~H"""
<p>Current temperature: {@temperature}°C</p>
<div class="thermostat-controls">
<button phx-click="inc_temperature" class="ghost-button">+</button>
<button phx-click="dec_temperature" class="ghost-button">-</button>
<div class="thermostat-wrapper">
<p class="thermostat-temp-label">Current temperature</p>
<p class="thermostat-temp-value" data-value="temperature">{@temperature}°C</p>
<div class="thermostat-controls">
<button phx-click="inc_temperature" class="ghost-button">+</button>
<button phx-click="dec_temperature" class="ghost-button">-</button>
</div>
<p class="thermostat-country">Country: {@country}</p>
</div>
<p>Country: {@country}</p>
"""
end

def mount(_params, _session, socket) do
temperature = 25
country = "Poland"

socket =
socket
|> assign(:temperature, temperature)
|> assign(:country, country)

{:ok, socket}
{:ok, socket |> assign(:temperature, @default_temperature) |> assign(:country, @default_country)}
end

def handle_event("inc_temperature", _params, socket) do
Expand All @@ -31,4 +29,5 @@ defmodule ThermostatLive do
def handle_event("dec_temperature", _params, socket) do
{:noreply, update(socket, :temperature, &(&1 - 1))}
end

end
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
defmodule ThermostatLivePresentation do
use LocalLiveView

defdelegate render(assigns), to: ThermostatLive

def mount(params, session, socket) do
result = ThermostatLive.mount(params, session, socket)
{:ok, new_socket} = result

Popcorn.Wasm.send_event("llv_presentation", %{
block: nil,
event: "mount",
assigns: presentation_assigns(new_socket)
})

result
end

def handle_event(event, params, socket)
when event in ~w(inc_temperature dec_temperature) do
# The UI socket lags behind the real state during animation; apply pending
# assigns so the event handler sees up-to-date data.
effective_socket =
case socket.assigns[:pending_cur] do
nil -> socket
pending -> assign(socket, Map.to_list(pending))
end

{:noreply, updated} = ThermostatLive.handle_event(event, params, effective_socket)

Popcorn.Wasm.send_event("llv_presentation", %{
block: event,
event: event,
assigns: presentation_assigns(updated)
})

new_pending = %{
temperature: updated.assigns.temperature,
country: updated.assigns.country
}

{:noreply,
socket
|> assign(:pending_prev, socket.assigns[:pending_cur])
|> assign(:pending_cur, new_pending)}
end

def handle_info({:js_push, "llv_ack", _}, socket) do
case {socket.assigns[:pending_prev], socket.assigns[:pending_cur]} do
{%{temperature: t, country: c}, _} ->
{:noreply, assign(socket, temperature: t, country: c, pending_prev: nil)}

{nil, %{temperature: t, country: c}} ->
{:noreply, assign(socket, temperature: t, country: c, pending_cur: nil)}

_ ->
{:noreply, socket}
end
end

def handle_event(event, params, socket) do
ThermostatLive.handle_event(event, params, socket)
end

defp presentation_assigns(socket) do
%{
temperature: socket.assigns.temperature,
country: socket.assigns.country
}
end
end
Loading
Loading