mirror of
https://github.com/algora-io/tv.git
synced 2025-02-14 01:59:50 +02:00
Choose thumbnail UI (#108)
This commit is contained in:
parent
dace52a204
commit
e363662880
@ -435,6 +435,11 @@ defmodule Algora.Library do
|
||||
Phoenix.PubSub.unsubscribe(@pubsub, topic(channel.user_id))
|
||||
end
|
||||
|
||||
def get_thumbnails_for_video(%Video{} = video) do
|
||||
Repo.all(from vt in VideoThumbnail,
|
||||
where: vt.video_id == ^video.id, order_by: vt.minutes)
|
||||
end
|
||||
|
||||
defp create_thumbnail_from_file(%Video{} = video, src_path, marker, opts \\ []) do
|
||||
dst_path = Path.join(System.tmp_dir!(), "#{video.uuid}-#{marker.minutes}.jpeg")
|
||||
|
||||
@ -454,7 +459,7 @@ defmodule Algora.Library do
|
||||
end
|
||||
|
||||
def store_thumbnail_from_file(%Video{} = video, src_path, marker \\ %{ minutes: 0 }, opts \\ []) do
|
||||
with {:ok, thumbnail} <- create_thumbnail_from_file(video, src_path, opts),
|
||||
with {:ok, thumbnail} <- create_thumbnail_from_file(video, src_path, marker, opts),
|
||||
{:ok, _} <-
|
||||
Storage.upload(thumbnail, "#{video.uuid}/#{thumbnail_filename(marker.minutes)}",
|
||||
content_type: "image/jpeg"
|
||||
|
@ -60,6 +60,12 @@ defmodule Algora.Library.Video do
|
||||
|> validate_required([:title])
|
||||
end
|
||||
|
||||
def change_thumbnail(video, thumbnail_url \\ "") do
|
||||
video
|
||||
|> change()
|
||||
|> put_change(:thumbnail_url, thumbnail_url)
|
||||
end
|
||||
|
||||
def put_user(%Ecto.Changeset{} = changeset, %User{} = user) do
|
||||
put_assoc(changeset, :user, user)
|
||||
end
|
||||
|
@ -1,7 +1,6 @@
|
||||
defmodule Algora.Library.VideoThumbnail do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
import Ecto.Query
|
||||
|
||||
alias Algora.Library.Video
|
||||
|
||||
|
@ -493,7 +493,7 @@ defmodule AlgoraWeb.CoreComponents do
|
||||
id={@id}
|
||||
phx-mounted={@show && show_modal(@id)}
|
||||
phx-remove={hide_modal(@id)}
|
||||
class="relative z-50 hidden"
|
||||
class="relative z-[1001] hidden"
|
||||
>
|
||||
<div
|
||||
id={"#{@id}-bg"}
|
||||
@ -795,6 +795,30 @@ defmodule AlgoraWeb.CoreComponents do
|
||||
"""
|
||||
end
|
||||
|
||||
def input(%{type: "radio", value: value} = assigns) do
|
||||
assigns =
|
||||
assign_new(assigns, :checked, fn -> Phoenix.HTML.Form.normalize_value("radio", value) end)
|
||||
|
||||
~H"""
|
||||
<div phx-feedback-for={@name}>
|
||||
<label class="flex items-center gap-4 text-sm leading-6 text-gray-300">
|
||||
<input
|
||||
type="radio"
|
||||
id={@id || @name}
|
||||
name={@name}
|
||||
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
|
||||
checked={@checked}
|
||||
class="rounded-full border-gray-600 text-gray-500 focus:ring-gray-50 sr-only peer"
|
||||
{@rest}
|
||||
/>
|
||||
<%= @label %>
|
||||
<%= render_slot(@inner_block) %>
|
||||
</label>
|
||||
<.error :for={msg <- @errors}><%= msg %></.error>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
def input(%{type: "select"} = assigns) do
|
||||
~H"""
|
||||
<div phx-feedback-for={@name}>
|
||||
|
@ -9,6 +9,7 @@ defmodule AlgoraWeb.VideoLive do
|
||||
alias Algora.Events.Event
|
||||
|
||||
alias AlgoraWeb.{
|
||||
CoreComponents,
|
||||
LayoutComponent,
|
||||
Presence,
|
||||
RTMPDestinationIconComponent,
|
||||
@ -22,6 +23,31 @@ defmodule AlgoraWeb.VideoLive do
|
||||
~H"""
|
||||
<div class="lg:mr-[24rem]">
|
||||
<.pwa_install_prompt />
|
||||
<.modal id="choose_thumbnail">
|
||||
<:title>
|
||||
Choose thumbnail
|
||||
</:title>
|
||||
<:subtitle>
|
||||
New thumbnails are added periodically
|
||||
</:subtitle>
|
||||
<.simple_form for={assigns.thumbnail_form} phx-submit="save_thumbnail">
|
||||
<div class="mt-4 grid-cols-2 grid gap-8">
|
||||
<label :for={video_thumbnail <- assigns.video_thumbnails} class="flex items-center">
|
||||
<.input
|
||||
field={assigns.thumbnail_form[:thumbnail_url]}
|
||||
type="radio"
|
||||
value={video_thumbnail.thumbnail_url}
|
||||
checked={assigns.thumbnail_form[:thumbnail_url].value == video_thumbnail.thumbnail_url}
|
||||
>
|
||||
<img src={video_thumbnail.thumbnail_url} class="border-2 rounded-lg opacity-50 peer-checked:opacity-100 peer-checked:border-white" />
|
||||
</.input>
|
||||
</label>
|
||||
</div>
|
||||
<:actions>
|
||||
<.button phx-click={CoreComponents.hide_modal("choose_thumbnail")}>Save</.button>
|
||||
</:actions>
|
||||
</.simple_form>
|
||||
</.modal>
|
||||
<div class="px-4" id="video-player-container" phx-update="ignore">
|
||||
<.live_component module={PlayerComponent} id="video-player" />
|
||||
</div>
|
||||
@ -49,18 +75,25 @@ defmodule AlgoraWeb.VideoLive do
|
||||
]}>
|
||||
<p><%= @video.title %></p>
|
||||
</blockquote>
|
||||
<.button :if={@current_user} phx-click="toggle_subscription">
|
||||
<%= if @subscribed? do %>
|
||||
Unsubscribe
|
||||
<% else %>
|
||||
Subscribe
|
||||
<div class="flex items-center gap-2 whitespace-nowrap">
|
||||
<%= if @current_user && (@video.user_id == @current_user.id || Accounts.admin?(@current_user)) && @has_many_thumbnails? do %>
|
||||
<.button phx-click={CoreComponents.show_modal("choose_thumbnail")}>
|
||||
Choose thumbnail
|
||||
</.button>
|
||||
<% end %>
|
||||
</.button>
|
||||
<.button :if={!@current_user && @authorize_url}>
|
||||
<.link navigate={@authorize_url}>
|
||||
Subscribe
|
||||
</.link>
|
||||
</.button>
|
||||
<.button :if={@current_user} phx-click="toggle_subscription">
|
||||
<%= if @subscribed? do %>
|
||||
Unsubscribe
|
||||
<% else %>
|
||||
Subscribe
|
||||
<% end %>
|
||||
</.button>
|
||||
<.button :if={!@current_user && @authorize_url}>
|
||||
<.link navigate={@authorize_url}>
|
||||
Subscribe
|
||||
</.link>
|
||||
</.button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:if={@channel.solving_challenge}
|
||||
@ -594,6 +627,7 @@ defmodule AlgoraWeb.VideoLive do
|
||||
|> Ecto.Changeset.cast(%{subtitles: encoded_subtitles}, Map.keys(types))
|
||||
|
||||
tabs = [:chat] |> append_if(length(subtitles) > 0, :transcript)
|
||||
video_thumbnails = Library.get_thumbnails_for_video(video)
|
||||
|
||||
socket =
|
||||
socket
|
||||
@ -609,7 +643,10 @@ defmodule AlgoraWeb.VideoLive do
|
||||
can_edit: false,
|
||||
subscribed?: subscribed?(current_user, video),
|
||||
transcript_form: to_form(transcript_changeset, as: :data),
|
||||
chat_form: to_form(Chat.change_message(%Chat.Message{}))
|
||||
chat_form: to_form(Chat.change_message(%Chat.Message{})),
|
||||
video_thumbnails: video_thumbnails,
|
||||
has_many_thumbnails?: length(video_thumbnails) > 1,
|
||||
thumbnail_form: to_form(Library.Video.change_thumbnail(video, video.thumbnail_url))
|
||||
)
|
||||
|> stream(:videos, videos)
|
||||
|> stream(:messages, Chat.list_messages(video))
|
||||
@ -787,6 +824,12 @@ defmodule AlgoraWeb.VideoLive do
|
||||
{:noreply, socket |> assign(subscribed?: !socket.assigns.subscribed?)}
|
||||
end
|
||||
|
||||
def handle_event("save_thumbnail", params, socket) do
|
||||
Library.Video.change_thumbnail(socket.assigns.video, params["video"]["thumbnail_url"])
|
||||
|> Repo.update()
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
# TODO: move into events context
|
||||
defp toggle_subscription_event(user, video) do
|
||||
name = if subscribed?(user, video), do: :unsubscribed, else: :subscribed
|
||||
|
Loading…
x
Reference in New Issue
Block a user