liveview-native / liveview-client-swiftui

MIT License
379 stars 39 forks source link

Slider out of sync with state #1477

Open bcardarella opened 1 month ago

bcardarella commented 1 month ago

I have the following:

<ZStack>
  <Rectangle class="background-black"/>
  <VStack spacing="16">
    <Text class="counter"><%= @counter %></Text>
    <HStack spacing="8">
      <.counter_button class="button-red" value={-10} />
      <.counter_button class="button-orange" value={-1} />
      <.counter_button class="button-green" value={1} />
      <.counter_button class="button-blue" value={10} />
    </HStack>
    <.form id="1">
      <Slider lowerBound={-100} upperBound={100} step={1} name="count" value={@counter} phx-change="count-change" />
    </.form>
  </VStack>
</ZStack>
defmodule CounterWeb.HomeLive do
  use CounterWeb, :live_view
  use CounterNative, :live_view

  @impl true
  def mount(_params, _session, socket) do
    {:ok, assign(socket, :counter, 0)}
  end

  @impl true
  def render(assigns) do
    ~H"""
    <div class="text-center text-9xl"><%= @counter %></div>
    <div class="flex flex-col items-center"><button class="active:bg-blue-300 touch-manipulation bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-5 rounded" phx-click="incr">+1</button></div>
    """
  end

  @impl true
  def handle_event("incr", _params, socket) do
    {:noreply, assign(socket, :counter, socket.assigns.counter + 1)}
  end

  def handle_event("decr", _unsigned_params, socket) do
    {:noreply, assign(socket, :counter, socket.assigns.counter - 1)}
  end

  def handle_event("incr-by", %{"by" => value}, socket) do
    {value, _} = Integer.parse(value)
    {:noreply, assign(socket, :counter, socket.assigns.counter + value)}
  end

  def handle_event("count-change", %{"count" => value}, socket) do
    {value, _} = Integer.parse(value)
    {:noreply, assign(socket, :counter, value)}
  end
end
  ~SHEET"""
  "background-" <> color do
    foregroundStyle(Color.{color})
    ignoresSafeArea(.all)
  end

  "counter" do
    font(.system(size: 300, weight: .regular, design: .monospaced))
    foregroundStyle(
      .linearGradient(
        colors: [.purple, .green],
        startPoint: .top,
        endPoint: .bottom
      )
    )
    minimumScaleFactor(0.5)
    lineLimit(1)
    padding(.bottom, 20)
  end

  "button-border" do
    stroke(.gray, lineWidth: 2)
  end

  "button-" <> color do
    font(.system(size: 16, weight: .bold, design: .monospaced))
    frame(width: 50, height: 50)
    foregroundStyle(
      .linearGradient(
        colors: [.white, .{color}],
        startPoint: .top,
        endPoint: .bottom
      )
    )
    overlay(content: :border)
    background(Color.clear)
    clipShape(.circle)
  end
  """
defmodule CounterWeb.HomeLive.SwiftUI do
  use CounterNative, [:render_component, format: :swiftui]

  def counter_button(assigns) do
    ~LVN"""
    <Button class={@class} phx-click="incr-by" phx-value-by={@value}>
      <Circle class="button-border" template="border" />
      <%= if @value < 0 do %>
        <%= @value %>
      <% else %>
        +<%= @value %>
      <% end %>
    </Button>
    """
  end
end

When I use the buttons to increment the counter, the slider's state always seems to be behind by one action: sliderstate

You will see that when I press +10 the slider's value doesn't change. The counter increases though. If I press +10 again, the slider will change but not to the actual @counter value. If I press -10 the slider will increase but the counter value decreases.