Skip to content

Conversation

@FKubisSWM
Copy link
Contributor

@FKubisSWM FKubisSWM commented Sep 1, 2025

This is a POC of LocalLiveView the LiveView that implements LiveView functionality in the browser using Popcorn.

Right now the functionality is limited to click events and does not support heex template files yet.

@FKubisSWM FKubisSWM changed the title Added render functionality to LocalLiveView. Add render functionality to LocalLiveView. Sep 1, 2025
@FKubisSWM FKubisSWM changed the title Add render functionality to LocalLiveView. LocalLiveView Sep 4, 2025
@FKubisSWM FKubisSWM changed the title LocalLiveView LocalLiveView POC Sep 4, 2025
@FKubisSWM FKubisSWM force-pushed the fkubis/local_live_view branch from 85a5012 to faab7d5 Compare September 18, 2025 08:38
@FKubisSWM FKubisSWM marked this pull request as ready for review September 22, 2025 12:33
Copy link
Contributor

@mat-hek mat-hek left a comment

Choose a reason for hiding this comment

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

TBC

transport_pid: nil,
sticky?: false

# @typedoc "Struct returned when `assigns` is not in the socket."
Copy link
Contributor

Choose a reason for hiding this comment

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

Lot's of commented-out code in here. I don't think we want it to be this way 🤔

@FKubisSWM FKubisSWM force-pushed the fkubis/local_live_view branch from 81bf8ac to cd71ec0 Compare October 2, 2025 06:22
@FKubisSWM FKubisSWM requested review from bblaszkow06 and mat-hek and removed request for mat-hek October 14, 2025 09:13
@FKubisSWM FKubisSWM force-pushed the fkubis/local_live_view branch from 57f5ac6 to ae49fdd Compare October 14, 2025 09:14
Copy link
Contributor

@mat-hek mat-hek left a comment

Choose a reason for hiding this comment

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

  • Compiling local_live_view generates a ton of warnings
  • A brief overview of the architecture would be very useful for someone unfamiliar with LiveView internals

@@ -0,0 +1,176 @@
# defprotocol Phoenix.HTML.Safe do
Copy link
Contributor

Choose a reason for hiding this comment

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

If there are any changes to the copied files, let's tag them and shortly describe their purpose, like we do in the patches


defp f(n, p \\ 2) do
n
|> inspect
Copy link
Contributor

Choose a reason for hiding this comment

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

Please format the code and enforce formatting on the CI in the local live view and all examples

Comment on lines 9 to 11
let elements = document.querySelectorAll('[#{attribute}]');
elements = Array.from(elements)
const found = elements.find((element) => element.getAttribute("#{attribute}") == args.view);
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't something like this work?

Suggested change
let elements = document.querySelectorAll('[#{attribute}]');
elements = Array.from(elements)
const found = elements.find((element) => element.getAttribute("#{attribute}") == args.view);
const element = document.querySelectorAll(`[#{attribute}=${args.view}]`);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok

Comment on lines 10 to 15
```
cd priv/demo_modal_offline
mix popcorn.cook
cd ../..
```
* Run `mix setup` to install and setup dependencies
Copy link
Contributor

Choose a reason for hiding this comment

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

  • mix deps.get is missing
  • Maybe mix setup of the parent project could set up the internal project as well?
  • I don't think the internal project needs to be in priv - it could be just in its directory under the root
  • I'd name the internal project compare_live_views_local and keep it in the local directory
  • After running mix setup I get the following error:
✘ [ERROR] Could not resolve "phoenix-colocated/compare_live_views"

    js/app.js:25:38:
      25 │ ...oks as colocatedHooks} from "phoenix-colocated/compare_live_views"
         ╵                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  You can mark the path "phoenix-colocated/compare_live_views" as external to exclude it from the bundle, which will remove this error and leave the unresolved path in the bundle.

@@ -0,0 +1,21 @@
# LocalThermostat

**TODO: Add description**
Copy link
Contributor

Choose a reason for hiding this comment

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

👀

@FKubisSWM FKubisSWM requested a review from mat-hek October 23, 2025 10:15
Copy link
Contributor

@mat-hek mat-hek left a comment

Choose a reason for hiding this comment

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

Compiling local_live_view still generates warnings

LocalLiveView should be used exactly like its Phoenix equivalent:
defmodule MyAppWeb.DemoLive do
use Phoenix.LiveView
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
use Phoenix.LiveView
use LocalLiveView


defmodule LocalLiveView.Server do
@moduledoc false
# A LocalLiveView is a process that receives events, updates
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
# A LocalLiveView is a process that receives events, updates
# A LocalLiveView.Server is a process that receives events, updates

Comment on lines 13 to 21
- "!examples/**"
- "!misc/**"
- "!.github/**"
- ".github/workflows/popcorn_build_test.yml"
pull_request:
branches: ["**"]
paths:
- "**"
- "!examples/**"
Copy link
Contributor

@mat-hek mat-hek Oct 23, 2025

Choose a reason for hiding this comment

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

These changes will trigger Popcorn build & test when an example changes. What's the point? Instead, I'd add an action that checks if local_live_view and the dependent examples compile successfully and without warnings

Comment on lines 9 to 12
cd local/compare_live_views_local
mix deps.get
mix popcorn.cook
cd ../..
Copy link
Contributor

Choose a reason for hiding this comment

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

This is already done by mix setup


defp build_local(_) do
Mix.shell().cmd("""
cd local/compare_live_views_local
Copy link
Contributor

Choose a reason for hiding this comment

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

I meant just to put it in the local dir

Suggested change
cd local/compare_live_views_local
cd local


This is a demo project that illustrates the differences between Popcorn's Local Live View and Phoenix Live View behaviors.

The page is split into two halves, each covered by a modal. One modal is implemented using Local LiveView and the other with Phoenix LiveView.
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bit sad that you can only close the modal :P Let's at least add a button to show the modal again

@@ -0,0 +1,25 @@
# CompareLiveViews

This is a demo project that illustrates the differences between Popcorn's Local Live View and Phoenix Live View behaviors.
Copy link
Contributor

Choose a reason for hiding this comment

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

When I run it I see no difference at all :D Let's add an option to configure simulated latency using LiveView APIs for that

@@ -0,0 +1,18 @@
defmodule LocalLiveView.JS do
Copy link
Contributor

Choose a reason for hiding this comment

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

Either add moduledoc or @moduledoc false. Generally, generate documentation and see how it looks like

Copy link
Contributor

Choose a reason for hiding this comment

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

let's remove this

@jgonet jgonet removed their request for review October 30, 2025 12:58
@FKubisSWM FKubisSWM removed the request for review from bblaszkow06 October 30, 2025 13:02
@FKubisSWM FKubisSWM requested a review from mat-hek October 30, 2025 14:55
Comment on lines 42 to 46
attr :id, :string, doc: "the optional id of flash container"
attr :flash, :map, default: %{}, doc: "the map of flash messages to display"
attr :title, :string, default: nil
attr :kind, :atom, values: [:info, :error], doc: "used for styling and flash lookup"
attr :rest, :global, doc: "the arbitrary HTML attributes to add to the flash container"
attr(:id, :string, doc: "the optional id of flash container")
attr(:flash, :map, default: %{}, doc: "the map of flash messages to display")
attr(:title, :string, default: nil)
attr(:kind, :atom, values: [:info, :error], doc: "used for styling and flash lookup")
attr(:rest, :global, doc: "the arbitrary HTML attributes to add to the flash container")
Copy link
Contributor

Choose a reason for hiding this comment

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

seems like something went wrong with the formatting

Copy link
Contributor Author

@FKubisSWM FKubisSWM Nov 5, 2025

Choose a reason for hiding this comment

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

I reverted those changes.

Comment on lines 90 to 94
Mix.shell().cmd("""
cd local
mix deps.get
mix compile
""")
Copy link
Contributor

@mat-hek mat-hek Nov 3, 2025

Choose a reason for hiding this comment

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

This way there's a risk that the working directory stays changed and messes something. It's better to do this:

Suggested change
Mix.shell().cmd("""
cd local
mix deps.get
mix compile
""")
Mix.shell().cmd("""
mix deps.get
mix compile
""", cd: "local")

Copy link
Contributor

Choose a reason for hiding this comment

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

leftover?

defmodule LocalLiveView.JS do
def rerender(rendered, view, attribute \\ "data-pop-view") do
@moduledoc """
Module responsible for running JS in the browser.
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't it rather about rendering a local live view in DOM? Perhaps the module name could be better too 🤔

Comment on lines 7 to 20
defmodule MyAppWeb.DemoLive do
use LocalLiveView
def render(assigns) do
~H"""
Hello world!
"""
end
end
The LocalLiveView can be added to a page with:
```
<div data-pop-view="DemoLive"></div>
```
Copy link
Contributor

Choose a reason for hiding this comment

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

Either use backticks or indent

Copy link
Contributor

Choose a reason for hiding this comment

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

Files in the wasm directory should be gitignored

Copy link
Contributor

Choose a reason for hiding this comment

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

If this file is copied automatically, it should be gitignored

Copy link
Contributor

Choose a reason for hiding this comment

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

This looks nice, but I'm worried about duplication with readme. WDYT about putting this into readme and adding readme as a main page in the docs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think thats a good idea.

Comment on lines 2 to 8
@moduledoc """
This process dispatches events to different LocalLiveViews present on the page.
It uses Popcorn API and registers as a main process to handle wasm messages inside Popcorn runtime.
Uses GenServer.
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I understand, there's no need for the user to call dispatcher in any way, so it shouldn't be in the API. Actually, the only module that the user needs is LocalLiveView, so all the rest should be a private API (i.e. moduledoc -> moduledoc false & comment)


Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.

_The project enables Phoenix LiveView latency simulation by using_ `liveSocket.enableLatencySim(1000)` _to show response time difference between the LiveViews._
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd mention this on the demo page too, with a notice you can change it by calling liveSocket.enableLatencySim in the console

...
defp deps do
[
{:local_live_view, path: path_to_popcorn <> "/examples/local_live_view"}
Copy link
Contributor

@mat-hek mat-hek Nov 3, 2025

Choose a reason for hiding this comment

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

Suggested change
{:local_live_view, path: path_to_popcorn <> "/examples/local_live_view"}
{:local_live_view, github: "software-mansion/popcorn", sparse: "examples/local_live_view"}

@FKubisSWM FKubisSWM requested a review from mat-hek November 6, 2025 12:46
Comment on lines 7 to 15
The local part of the project is located in `local` directory.

The most important files to look at are:

```compare_live_views/lib/compare_live_views_web/live/demo_modal_online.ex``` - Phoenix LiveView that represents online part of the demo and is rendered on the left side of the page.

```compare_live_views/local/lib/demo_modal_offline.ex``` - LocalLiveView that represents offline part of the demo and is rendered on the right side of the page.

```compare_live_views/lib/compare_live_views_web/controllers/page_html/home.html.heex``` - home page that renders both views.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The local part of the project is located in `local` directory.
The most important files to look at are:
```compare_live_views/lib/compare_live_views_web/live/demo_modal_online.ex``` - Phoenix LiveView that represents online part of the demo and is rendered on the left side of the page.
```compare_live_views/local/lib/demo_modal_offline.ex``` - LocalLiveView that represents offline part of the demo and is rendered on the right side of the page.
```compare_live_views/lib/compare_live_views_web/controllers/page_html/home.html.heex``` - home page that renders both views.
The local part of the project is located in the `local` directory.
The most important files to look at are:
`compare_live_views/lib/compare_live_views_web/live/demo_modal_online.ex` - Phoenix LiveView that represents online part of the demo and is rendered on the left side of the page.
`compare_live_views/local/lib/demo_modal_offline.ex` - LocalLiveView that represents offline part of the demo and is rendered on the right side of the page.
`compare_live_views/lib/compare_live_views_web/controllers/page_html/home.html.heex` - home page that renders both views.

Comment on lines 37 to 40
plug Phoenix.LiveReloader
plug Phoenix.CodeReloader
socket("/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket)
plug(Phoenix.LiveReloader)
plug(Phoenix.CodeReloader)
Copy link
Contributor

Choose a reason for hiding this comment

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

Formatting still messed up

@FKubisSWM FKubisSWM merged commit 9c1a847 into main Nov 7, 2025
2 checks passed
@FKubisSWM FKubisSWM deleted the fkubis/local_live_view branch November 7, 2025 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants