You've already forked algora-tv
							
							
				mirror of
				https://github.com/algora-io/tv.git
				synced 2025-10-30 23:07:56 +02:00 
			
		
		
		
	intersperse shorts and videos on homepage
This commit is contained in:
		| @@ -191,6 +191,7 @@ defmodule Algora.Library do | ||||
|       limit: ^limit, | ||||
|       where: | ||||
|         v.visibility == :public and | ||||
|           is_nil(v.vertical_thumbnail_url) and | ||||
|           (v.is_live == true or v.duration >= 120 or v.type == :vod), | ||||
|       select_merge: %{channel_name: u.name} | ||||
|     ) | ||||
| @@ -198,6 +199,18 @@ defmodule Algora.Library do | ||||
|     |> Repo.replica().all() | ||||
|   end | ||||
|  | ||||
|   def list_shorts(limit \\ 100) do | ||||
|     from(v in Video, | ||||
|       join: u in User, | ||||
|       on: v.user_id == u.id, | ||||
|       limit: ^limit, | ||||
|       where: v.visibility == :public and not is_nil(v.vertical_thumbnail_url), | ||||
|       select_merge: %{channel_name: u.name} | ||||
|     ) | ||||
|     |> order_by_inserted(:desc) | ||||
|     |> Repo.replica().all() | ||||
|   end | ||||
|  | ||||
|   def list_channel_videos(%Channel{} = channel, limit \\ 100) do | ||||
|     from(v in Video, | ||||
|       limit: ^limit, | ||||
|   | ||||
| @@ -6,7 +6,6 @@ defmodule AlgoraWeb.ChannelLive do | ||||
|   alias AlgoraWeb.{LayoutComponent, Presence} | ||||
|   alias AlgoraWeb.ChannelLive.{StreamFormComponent} | ||||
|  | ||||
|   @impl true | ||||
|   def render(assigns) do | ||||
|     ~H""" | ||||
|     <%!-- <:actions> | ||||
| @@ -205,7 +204,6 @@ defmodule AlgoraWeb.ChannelLive do | ||||
|     """ | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def mount(%{"channel_handle" => channel_handle}, _session, socket) do | ||||
|     %{current_user: current_user} = socket.assigns | ||||
|  | ||||
| @@ -239,13 +237,11 @@ defmodule AlgoraWeb.ChannelLive do | ||||
|     {:ok, socket} | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def handle_params(params, _url, socket) do | ||||
|     LayoutComponent.hide_modal() | ||||
|     {:noreply, socket |> apply_action(socket.assigns.live_action, params)} | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def handle_info({Presence, {:join, presence}}, socket) do | ||||
|     {:noreply, stream_insert(socket, :presences, presence)} | ||||
|   end | ||||
|   | ||||
| @@ -6,29 +6,93 @@ defmodule AlgoraWeb.HomeLive do | ||||
|  | ||||
|   def render(assigns) do | ||||
|     ~H""" | ||||
|     <.playlist id="playlist" videos={@streams.videos} /> | ||||
|     <div class="-mt-16 px-4"> | ||||
|       <div :for={{shorts, videos} <- @sections}> | ||||
|         <div class="pt-16"> | ||||
|           <h2 class="text-white text-xl font-semibold px-8 sr-only"> | ||||
|             Videos | ||||
|           </h2> | ||||
|           <div class="pt-8 gap-8 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3"> | ||||
|             <.video_entry :for={video <- videos} id={"video-#{video.id}"} video={video} /> | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="pt-16"> | ||||
|           <h2 class="text-white text-xl font-bold flex items-center gap-1"> | ||||
|             <svg | ||||
|               xmlns="http://www.w3.org/2000/svg" | ||||
|               class="h-8 w-8" | ||||
|               width="24" | ||||
|               height="24" | ||||
|               viewBox="0 0 24 24" | ||||
|               stroke-width="1.5" | ||||
|               stroke="currentColor" | ||||
|               fill="none" | ||||
|               stroke-linecap="round" | ||||
|               stroke-linejoin="round" | ||||
|             ><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M13 3l0 7l6 0l-8 11l0 -7l-6 0l8 -11" /></svg>Shorts | ||||
|           </h2> | ||||
|           <div class="pt-4 gap-8 grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6"> | ||||
|             <.short_entry :for={video <- shorts} id={"short-#{video.id}"} video={video} /> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|  | ||||
|       <div :if={length(@leftover_videos) > 0} class="pt-16"> | ||||
|         <h2 class="text-white text-xl font-semibold px-8 sr-only"> | ||||
|           Videos | ||||
|         </h2> | ||||
|         <div class="pt-8 gap-8 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3"> | ||||
|           <.video_entry :for={video <- @leftover_videos} id={"video-#{video.id}"} video={video} /> | ||||
|         </div> | ||||
|       </div> | ||||
|  | ||||
|       <div :if={length(@leftover_shorts) > 0} class="pt-16"> | ||||
|         <h2 class="text-white text-xl font-bold flex items-center gap-1"> | ||||
|           <svg | ||||
|             xmlns="http://www.w3.org/2000/svg" | ||||
|             class="h-8 w-8" | ||||
|             width="24" | ||||
|             height="24" | ||||
|             viewBox="0 0 24 24" | ||||
|             stroke-width="1.5" | ||||
|             stroke="currentColor" | ||||
|             fill="none" | ||||
|             stroke-linecap="round" | ||||
|             stroke-linejoin="round" | ||||
|           ><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M13 3l0 7l6 0l-8 11l0 -7l-6 0l8 -11" /></svg>Shorts | ||||
|         </h2> | ||||
|         <div class="pt-4 gap-8 grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6"> | ||||
|           <.short_entry :for={video <- @leftover_shorts} id={"short-#{video.id}"} video={video} /> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     """ | ||||
|   end | ||||
|  | ||||
|   def mount(_map, _session, socket) do | ||||
|     if connected?(socket) do | ||||
|       Library.subscribe_to_livestreams() | ||||
|     end | ||||
|     short_sections = Library.list_shorts(150) |> Enum.chunk_every(6) | ||||
|     video_sections = Library.list_videos(150) |> Enum.chunk_every(6) | ||||
|  | ||||
|     videos = Library.list_videos(150) | ||||
|     num_sections = max(min(length(short_sections), length(video_sections)) - 1, 0) | ||||
|  | ||||
|     {:ok, socket |> stream(:videos, videos)} | ||||
|     {shorts, leftover_shorts} = short_sections |> Enum.split(num_sections) | ||||
|     {videos, leftover_videos} = video_sections |> Enum.split(num_sections) | ||||
|  | ||||
|     sections = Enum.zip(shorts, videos) | ||||
|  | ||||
|     {:ok, | ||||
|      socket | ||||
|      |> assign(sections: sections) | ||||
|      |> assign(leftover_videos: Enum.concat(leftover_videos)) | ||||
|      |> assign(leftover_shorts: Enum.concat(leftover_shorts))} | ||||
|   end | ||||
|  | ||||
|   def handle_params(params, _url, socket) do | ||||
|     {:noreply, socket |> apply_action(socket.assigns.live_action, params)} | ||||
|   end | ||||
|  | ||||
|   def handle_info({Library, _}, socket), do: {:noreply, socket} | ||||
|  | ||||
|   defp apply_action(socket, :show, _params) do | ||||
|     socket | ||||
|     |> assign(:page_title, nil) | ||||
|     |> assign(:video, nil) | ||||
|     socket |> assign(:page_title, nil) | ||||
|   end | ||||
| end | ||||
|   | ||||
		Reference in New Issue
	
	Block a user