postland/lib/postland_web/live/timeline_live.ex
2024-11-18 18:27:25 -06:00

157 lines
4.1 KiB
Elixir

defmodule PostlandWeb.TimelineLive do
use PostlandWeb, :live_view
alias Postland.Activities
alias Postland.Objects
def render(assigns) do
~H"""
<div id="timeline">
<.post_form post_content={@post} attachments={@attachments} upload={@uploads.files} cw={@cw} />
<div id="timeline-posts" phx-update="stream">
<div :for={{id, post} <- @streams.posts} id={id} class="mt-10">
<.post_card post={post} post_dom_id={id} />
</div>
</div>
</div>
"""
end
def mount(_params, _session, socket) do
socket =
socket
|> assign(:post, "")
|> assign(:attachments, [])
|> assign(:cw, nil)
|> stream(:posts, Postland.Timeline.timeline())
|> allow_upload(:files,
accept: ["image/*"],
auto_upload: true,
progress: &handle_progress/3
)
{:ok, socket}
end
def handle_event("create_post", %{"post" => post}, socket) do
{:ok, results} =
Postland.Activities.record_markdown_post(
post,
socket.assigns.cw,
socket.assigns.attachments
)
new_posts =
results
|> Enum.filter(fn {_key, value} ->
is_struct(value, Postland.Object)
end)
socket =
socket
|> assign(:post, "")
|> assign(:attachments, [])
|> assign(:cw, nil)
|> then(fn socket ->
Enum.reduce(new_posts, socket, fn {_id, post}, socket ->
stream_insert(socket, :posts, post, at: 0)
end)
end)
{:noreply, socket}
end
def handle_event("delete_post", %{"post-id" => id, "post-dom-id" => dom_id}, socket) do
post = Objects.get_by_id(id)
case Activities.delete_post(post) do
{:ok, _} ->
{:noreply, socket |> stream_delete_by_dom_id(:posts, dom_id)}
_ ->
{:noreply, socket |> put_flash(:error, "An unexpected error has occurred.")}
end
end
def handle_event("like_post", %{"post-id" => id, "post-dom-id" => dom_id}, socket) do
post = Objects.get_by_id(id)
case Activities.like_post(post) do
{:ok, _} ->
post = Objects.get_by_id(id)
{:noreply, socket |> stream_insert(:posts, post)}
_ ->
{:noreply, socket |> put_flash(:error, "An unexpected error has occurred.")}
end
end
def handle_event("unlike_post", %{"post-id" => id, "post-dom-id" => dom_id}, socket) do
post = Objects.get_by_id(id)
case Activities.unlike_post(post) do
{:ok, _} ->
post = Objects.get_by_id(id)
{:noreply, socket |> stream_insert(:posts, post)}
_ ->
{:noreply, socket |> put_flash(:error, "An unexpected error has occurred.")}
end
end
def handle_event("change_post", %{"post" => post} = params, socket) do
cw = Map.get(params, "cw")
{:noreply, socket |> assign(post: post, cw: cw)}
end
def handle_event("remove_attachment", %{"url" => url}, socket) do
attachments =
socket.assigns.attachments
|> Enum.reject(fn %{"url" => attachment_url} -> attachment_url == url end)
{:noreply, assign(socket, attachments: attachments)}
end
def handle_event("change_alt_text", %{"alt" => value, "url" => url}, socket) do
attachments =
socket.assigns.attachments
|> Enum.map(fn
%{"url" => ^url} = attachment ->
Map.put(attachment, "name", value)
other ->
other
end)
{:noreply, assign(socket, attachments: attachments)}
end
def handle_event("add_cw", _, socket) do
{:noreply, assign(socket, cw: "")}
end
def handle_event("remove_cw", _, socket) do
{:noreply, assign(socket, cw: nil)}
end
def handle_progress(:files, entry, socket) do
if entry.done? do
uploaded_file =
consume_uploaded_entry(socket, entry, fn meta ->
Postland.Uploads.handle_upload(entry, meta)
end)
attachment = %{
"type" => "Document",
"mediaType" => entry.client_type,
"url" => unverified_url(PostlandWeb.Endpoint, uploaded_file),
"name" => nil
}
attachments = socket.assigns.attachments ++ [attachment]
{:noreply, assign(socket, attachments: attachments)}
else
{:noreply, socket}
end
end
end