defmodule AlgoraWeb.ChannelLive do use AlgoraWeb, :live_view require Logger alias Algora.{Accounts, Library, Storage} alias AlgoraWeb.{LayoutComponent, Presence} alias AlgoraWeb.ChannelLive.StreamFormComponent def render(assigns) do ~H""" <%!-- <:actions> <.button :if={@owns_channel? && not @channel.is_live} id="stream-btn" primary patch={channel_stream_path(@current_user)} > Start streaming! --%>

<%= @channel.tagline %>

{@channel.handle}
LIVE
<%= @channel.name %>
  1. <%= lang.name %>

@<%= @channel.handle %>
Watching now
<%= metas |> Enum.filter(fn meta -> meta.id != @channel.handle end) |> length() %>
Bounties collected
<%= @channel.bounties_count %>
0}>
OSS projects contributed

Library

<.playlist id="playlist" videos={@streams.videos} />
""" end def mount(%{"channel_handle" => channel_handle}, _session, socket) do %{current_user: current_user} = socket.assigns channel = Accounts.get_user_by!(handle: channel_handle) |> Library.get_channel!() if connected?(socket) do Library.subscribe_to_livestreams() Library.subscribe_to_channel(channel) Presence.track_user(channel_handle, %{ id: if(current_user, do: current_user.handle, else: "") }) Presence.subscribe(channel_handle) end videos = Library.list_channel_videos(channel, 50) socket = socket |> assign( channel: channel, owns_channel?: current_user && Library.owns_channel?(current_user, channel), videos_count: Enum.count(videos) ) |> stream(:videos, videos) |> stream(:presences, Presence.list_online_users(channel_handle)) {:ok, socket} end def handle_params(params, _url, socket) do LayoutComponent.hide_modal() {:noreply, socket |> apply_action(socket.assigns.live_action, params)} end def handle_info({Presence, {:join, presence}}, socket) do {:noreply, stream_insert(socket, :presences, presence)} end def handle_info({Presence, {:leave, presence}}, socket) do if presence.metas == [] do {:noreply, stream_delete(socket, :presences, presence)} else {:noreply, stream_insert(socket, :presences, presence)} end end def handle_info( {Storage, %Library.Events.ThumbnailsGenerated{video: video}}, socket ) do {:noreply, if video.user_id == socket.assigns.channel.user_id do socket |> stream_insert(:videos, video, at: 0) else socket end} end def handle_info( {Library, %Library.Events.LivestreamStarted{video: video}}, socket ) do %{channel: channel} = socket.assigns {:noreply, if video.user_id == channel.user_id do socket |> assign(channel: %{channel | is_live: true}) |> stream_insert(:videos, video, at: 0) else socket end} end def handle_info( {Library, %Library.Events.LivestreamEnded{video: video}}, socket ) do %{channel: channel} = socket.assigns {:noreply, if video.user_id == channel.user_id do socket |> assign(channel: %{channel | is_live: false}) |> stream_insert(:videos, video) else socket end} end def handle_info({Library, _}, socket), do: {:noreply, socket} defp apply_action(socket, :stream, _params) do if socket.assigns.owns_channel? do socket |> assign(:page_title, "Start streaming") |> show_stream_modal() else socket |> put_flash(:error, "You can't do that") |> redirect(to: channel_path(socket.assigns.current_user)) end end defp apply_action(socket, :show, params) do socket |> assign(:page_title, socket.assigns.channel.name || params["channel_handle"]) |> assign(:channel_handle, socket.assigns.channel.handle) |> assign(:channel_name, socket.assigns.channel.name) |> assign(:channel_tagline, socket.assigns.channel.tagline) end defp show_stream_modal(socket) do LayoutComponent.show_modal(StreamFormComponent, %{ id: :stream, confirm: {"Save", type: "submit", form: "stream-form"}, patch: channel_path(socket.assigns.current_user), video: socket.assigns.video, title: socket.assigns.page_title, current_user: socket.assigns.current_user, changeset: Accounts.change_settings(socket.assigns.current_user, %{}) }) socket end end