Skip to content

Commit

Permalink
https://github.com/bonfire-networks/bonfire-app/issues/1043
Browse files Browse the repository at this point in the history
  • Loading branch information
mayel committed Oct 8, 2024
1 parent b35cdf1 commit a1093dd
Show file tree
Hide file tree
Showing 8 changed files with 449 additions and 338 deletions.
98 changes: 52 additions & 46 deletions lib/components/core_components.swiftui.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
if Code.ensure_loaded?(LiveViewNative.Component) do

defmodule Bonfire.UI.Common.CoreComponents.SwiftUI do
@moduledoc """
Provides core UI components built for SwiftUI.
Expand All @@ -23,57 +22,64 @@ if Code.ensure_loaded?(LiveViewNative.Component) do

import LiveViewNative.LiveForm.Component


@doc """
A special component that allows users to inject dynamic live components
"""
attr :module, :atom, required: true
attr :id, :string, required: true
attr :function, :atom, default: :render
slot :default
def stateful_component(assigns) do
# TEMP: until LVN supports live components
stateless_component(with true <- module_enabled?(assigns[:module]),
{:ok, assigns} <- assigns
|> assign(module_default_assigns(assigns[:module]))
|> assign(assigns) # again so we override defaults
|> assign_new(:myself, fn -> nil end)
|> assign_new(:streams, fn -> nil end)
|> apply(assigns[:module], :mount, [...]),
{:ok, assigns} <- apply(assigns[:module], :update, [assigns, assigns]) do
assign_new(assigns, :function, fn -> :render end)
|> debug("assi")
else e ->
@doc """
A special component that allows users to inject dynamic live components
"""
attr :module, :atom, required: true
attr :id, :string, required: true
attr :function, :atom, default: :render
slot :default

def stateful_component(assigns) do
# TEMP: until LVN supports live components
stateless_component(
with true <- module_enabled?(assigns[:module]),
{:ok, assigns} <-
assigns
|> assign(module_default_assigns(assigns[:module]))
# again so we override defaults
|> assign(assigns)
|> assign_new(:myself, fn -> nil end)
|> assign_new(:streams, fn -> nil end)
|> apply(assigns[:module], :mount, [...]),
{:ok, assigns} <- apply(assigns[:module], :update, [assigns, assigns]) do
assign_new(assigns, :function, fn -> :render end)
|> debug("assi")
else
e ->
error(e)

assigns
|> debug("erssi")
|> assign(:module, __MODULE__)
|> assign(:function, :error_msg)
|> assign(:text, "Could not render component")
end
)
# TODO: when LVN supports live components
# ~LVN"""
# <Phoenix.Component.live_component module={@module} id={@id}><%= render_slot(@default) %></Phoenix.Component.live_component>
# """
end

@doc """
A special component that allows users to inject dynamic function components
"""
attr :module, :atom, default: nil
attr :function, :atom, default: :render
attr :id, :string, default: nil
slot :default
def stateless_component(assigns) do
~LVN"""
<%= Phoenix.LiveView.TagEngine.component(
&apply(@module || __MODULE__, @function || :render, [&1]),
assigns,
{__ENV__.module, __ENV__.function, __ENV__.file, __ENV__.line}
) %>
"""
end
end
)

# TODO: when LVN supports live components
# ~LVN"""
# <Phoenix.Component.live_component module={@module} id={@id}><%= render_slot(@default) %></Phoenix.Component.live_component>
# """
end

@doc """
A special component that allows users to inject dynamic function components
"""
attr :module, :atom, default: nil
attr :function, :atom, default: :render
attr :id, :string, default: nil
slot :default

def stateless_component(assigns) do
~LVN"""
<%= Phoenix.LiveView.TagEngine.component(
&apply(@module || __MODULE__, @function || :render, [&1]),
assigns,
{__ENV__.module, __ENV__.function, __ENV__.file, __ENV__.line}
) %>
"""
end

@doc """
Renders an input with label and error messages.
Expand Down
2 changes: 1 addition & 1 deletion lib/layout/layout_view.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Bonfire.UI.Common.LayoutView do
use Bonfire.UI.Common.Web, :layout

embed_templates "*.html"
use_if_enabled(Bonfire.UI.Common.Web.Native, :layout)

# def render("live.html", assigns) do
# Bonfire.UI.Common.LayoutLive.render(assigns)
Expand Down
2 changes: 1 addition & 1 deletion lib/static_generator/static_generator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ defmodule Bonfire.UI.Common.StaticGenerator do

urls
|> Enum.reject(fn url ->
full_path = Path.join([dest, url, "index.html"])
full_path = Path.join([dest, url, "index.#{opts[:ext] || "html"}"])
file_exists_not_expired(full_path)
end)
|> debug("expired or doesn't exist")
Expand Down
114 changes: 57 additions & 57 deletions lib/themes/default/app.swiftui.ex
Original file line number Diff line number Diff line change
@@ -1,70 +1,70 @@
defmodule Bonfire.UI.Common.Themes.Default.App.SwiftUI do
use LiveViewNative.Stylesheet, :swiftui
if Bonfire.Common.Extend.module_enabled?(LiveViewNative) do
defmodule Bonfire.UI.Common.Themes.Default.App.SwiftUI do
use LiveViewNative.Stylesheet, :swiftui

# Add your styles here
# Refer to your client's documentation on what the proper syntax
# is for defining rules within classes
~SHEET"""
"""
# Add your styles here
# Refer to your client's documentation on what the proper syntax
# is for defining rules within classes
~SHEET"""
def class("main_header") do
~RULES"""
toolbar(content: :toolbar)
navigationTitle(:title)
toolbarTitleMenu(content: :content)
navigationBarTitleDisplayMode(.inline)
toolbarBackgroundVisibility(.visible, for: .navigationBar)
toolbarBackground(.ultraThinMaterial, for: .navigationBar)
"""
end

def class("simple_header") do
~RULES"""
toolbar(content: :toolbar)
navigationTitle(:title)
navigationBarTitleDisplayMode(.inline)
"""
end
def class("main_header") do
~RULES"""
toolbar(content: :toolbar)
navigationTitle(:title)
toolbarTitleMenu(content: :content)
navigationBarTitleDisplayMode(.inline)
toolbarBackgroundVisibility(.visible, for: .navigationBar)
toolbarBackground(.ultraThinMaterial, for: .navigationBar)
"""
end

def class("detents:" <> props) do
[height, size] = String.split(props, ":")
def class("simple_header") do
~RULES"""
toolbar(content: :toolbar)
navigationTitle(:title)
navigationBarTitleDisplayMode(.inline)
"""
end

# {height, _} = Integer.parse(height)
def class("detents:" <> props) do
[height, size] = String.split(props, ":")

~RULES"""
presentationDetents([.{height}, .{size}])
"""
end
# {height, _} = Integer.parse(height)

def class("dragindicator:" <> props) do

~RULES"""
presentationDragIndicator(.{props})
"""
end
~RULES"""
presentationDetents([.{height}, .{size}])
"""
end

def class("dragindicator:" <> props) do
~RULES"""
presentationDragIndicator(.{props})
"""
end

def class("ultrathinmaterial") do
~RULES"""
presentationBackground(.ultraThinMaterial)
"""
end
def class("ultrathinmaterial") do
~RULES"""
presentationBackground(.ultraThinMaterial)
"""
end

# If you need to have greater control over how your style rules are created
# you can use the function defintion style which is more verbose but allows
# for more fine-grained controled
#
# This example shows what is not possible within the more concise ~SHEET
# use `<Text class="frame:w100:h200" />` allows for a setting
# of both the `width` and `height` values.
# If you need to have greater control over how your style rules are created
# you can use the function defintion style which is more verbose but allows
# for more fine-grained controled
#
# This example shows what is not possible within the more concise ~SHEET
# use `<Text class="frame:w100:h200" />` allows for a setting
# of both the `width` and `height` values.

# def class("frame:" <> dims) do
# [width] = Regex.run(~r/w(\d+)/, dims, capture: :all_but_first)
# [height] = Regex.run(~r/h(\d+)/, dims, capture: :all_but_first)
# def class("frame:" <> dims) do
# [width] = Regex.run(~r/w(\d+)/, dims, capture: :all_but_first)
# [height] = Regex.run(~r/h(\d+)/, dims, capture: :all_but_first)

# ~RULES"""
# frame(width: {width}, height: {height})
# """
# end
end
# ~RULES"""
# frame(width: {width}, height: {height})
# """
# end
end
end
10 changes: 7 additions & 3 deletions lib/ui_common.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1334,7 +1334,8 @@ defmodule Bonfire.UI.Common do
Inserts one or many items in an existing stream.
See `Phoenix.LiveView.stream_insert/4` for opts.
"""
def maybe_stream_insert(%{assigns: %{streams: streams}} = socket, name, items, _opts) when is_nil(streams) or streams==%{} do
def maybe_stream_insert(%{assigns: %{streams: streams}} = socket, name, items, _opts)
when is_nil(streams) or streams == %{} do
error(
assigns(socket),
"Invalid stream '#{name}' to render data in. Will set as regular assign instead"
Expand Down Expand Up @@ -1438,17 +1439,20 @@ defmodule Bonfire.UI.Common do
def component_props(module) do
component_attr(module, :prop)
end

def component_data(module) do
component_attr(module, :data)
end

defp component_attr(module, key) do
apply(Bonfire.UI.Social.FeedLive, :__info__, [:attributes])
|> Keyword.get_values(key)
|> Enum.flat_map(&(&1))
|> Enum.flat_map(& &1)
end

def module_default_assigns(module) do
for %{name: name, opts: opts} <- component_props(module) ++ component_data(module), Keyword.has_key?(opts, :default) do
for %{name: name, opts: opts} <- component_props(module) ++ component_data(module),
Keyword.has_key?(opts, :default) do
{name, opts[:default]}
end
end
Expand Down
Loading

0 comments on commit a1093dd

Please sign in to comment.