Skip to content

Commit 4df46c5

Browse files
authored
Merge pull request #106 from midarrlabs/feature/v1.13.0
v1.13.0
2 parents 19d3d75 + 0457ee9 commit 4df46c5

File tree

13 files changed

+580
-16
lines changed

13 files changed

+580
-16
lines changed

lib/media_server_web/components/nav_component.ex

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,13 @@ defmodule MediaServerWeb.Components.NavComponent do
22
use MediaServerWeb, :live_component
33

44
alias Phoenix.LiveView.JS
5+
6+
@impl true
7+
def handle_event("search", %{"search" => %{"query" => query}}, socket) do
8+
{
9+
:noreply,
10+
socket
11+
|> push_redirect(to: Routes.search_index_path(socket, :index, query: query))
12+
}
13+
end
514
end

lib/media_server_web/components/nav_component.html.heex

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@
2929
</div>
3030
</div>
3131

32-
<div class="flex-none">
32+
<div class="flex space-x-6">
33+
34+
<button phx-click={JS.toggle(to: "#search-command")} type="button" class={"text-base font-medium focus:outline-none focus:ring-2 focus:ring-slate-500 #{ @class }"}>
35+
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
36+
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
37+
</svg>
38+
</button>
39+
3340
<div class="relative">
3441
<button phx-click={JS.toggle(to: "#profile-dropdown")} phx-click-away={JS.hide(to: "#profile-dropdown")} type="button" class="flex text-sm focus:outline-none focus:ring-2 focus:ring-slate-500">
3542
<span class="flex-shrink-0 inline-block relative">
@@ -66,4 +73,21 @@
6673
<%= live_redirect "Continues", to: Routes.continues_index_path(@socket, :index), class: "text-base block px-3 py-2 font-medium #{ @class }" %>
6774
</div>
6875
</div>
76+
77+
<div class="hidden relative z-10" id="search-command">
78+
<div class="fixed inset-0 bg-gray-500 bg-opacity-25 transition-opacity"></div>
79+
80+
<div class="fixed inset-0 z-10 overflow-y-auto p-4 sm:p-6 md:p-20">
81+
<div class="mx-auto max-w-xl transform divide-y divide-gray-100 overflow-hidden rounded-xl bg-white shadow-2xl ring-1 ring-black ring-opacity-5 transition-all">
82+
<div class="relative" phx-click-away={JS.hide(to: "#search-command")}>
83+
<svg class="pointer-events-none absolute top-3.5 left-4 h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
84+
<path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd" />
85+
</svg>
86+
<.form let={f} for={:search} id="search" phx-target={@myself} phx-submit="search">
87+
<%= text_input f, :query, placeholder: "Search...", class: "h-12 w-full border-0 bg-transparent pl-11 pr-4 text-gray-800 placeholder-gray-400 focus:ring-0 sm:text-sm" %>
88+
</.form>
89+
</div>
90+
</div>
91+
</div>
92+
</div>
6993
</nav>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
defmodule MediaServerWeb.Components.SpinnerComponent do
2+
use Phoenix.Component
3+
4+
def render(assigns) do
5+
~H"""
6+
<div class="w-12 h-12 rounded-full animate-spin border-2 border-solid border-slate-500 border-t-transparent"></div>
7+
"""
8+
end
9+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
defmodule MediaServerWeb.ComponentsLive.Index do
2+
use MediaServerWeb, :live_view
3+
4+
@impl true
5+
def mount(_params, _session, socket) do
6+
{
7+
:ok,
8+
socket
9+
|> assign(page_title: "Components")
10+
}
11+
end
12+
13+
@impl true
14+
def handle_params(_params, _url, socket) do
15+
{
16+
:noreply,
17+
socket
18+
}
19+
end
20+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<.live_component module={MediaServerWeb.Components.NavComponent}
2+
id="nav-component"
3+
class="text-slate-600 hover:text-slate-800"
4+
/>
5+
6+
<%= MediaServerWeb.Components.SpinnerComponent.render(%{}) %>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
defmodule MediaServerWeb.SearchLive.Index do
2+
use MediaServerWeb, :live_view
3+
4+
alias MediaServerWeb.Repositories.Movies
5+
alias MediaServerWeb.Repositories.Series
6+
7+
@impl true
8+
def handle_params(%{"query" => query}, _url, socket) do
9+
pid = self()
10+
11+
Task.start(fn ->
12+
send(pid, {:movies, Movies.search(query)})
13+
end)
14+
15+
Task.start(fn ->
16+
send(pid, {:series, Series.search(query)})
17+
end)
18+
19+
{
20+
:noreply,
21+
socket
22+
|> assign(:page_title, query)
23+
}
24+
end
25+
26+
@impl true
27+
def handle_info({:movies, movies}, socket) do
28+
{
29+
:noreply,
30+
socket
31+
|> assign(:movies, movies)
32+
}
33+
end
34+
35+
def handle_info({:series, series}, socket) do
36+
{
37+
:noreply,
38+
socket
39+
|> assign(:series, series)
40+
}
41+
end
42+
end
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<.live_component module={MediaServerWeb.Components.NavComponent}
2+
id="nav-component"
3+
class="text-slate-600 hover:text-slate-800"
4+
/>
5+
6+
<div class="max-w-6xl mx-auto py-6 px-4 sm:py-6 sm:px-6">
7+
8+
<div class="mt-6 grid grid-cols-2 gap-y-10 gap-x-6 sm:grid-cols-2 lg:grid-cols-6 xl:gap-x-8">
9+
10+
<%= if assigns[:movies] && assigns[:series] do %>
11+
<%= for item <- @movies do %>
12+
13+
<%= MediaServerWeb.Components.PosterComponent.render(%{
14+
img_src: MediaServerWeb.Repositories.Movies.get_poster(item),
15+
title: item["title"],
16+
link: Routes.movies_show_path(@socket, :show, item["id"])
17+
}) %>
18+
19+
<% end %>
20+
21+
<%= for item <- @series do %>
22+
23+
<%= MediaServerWeb.Components.PosterComponent.render(%{
24+
img_src: MediaServerWeb.Repositories.Series.get_poster(item),
25+
title: item["title"],
26+
link: Routes.series_show_path(@socket, :show, item["id"])
27+
}) %>
28+
29+
<% end %>
30+
31+
<% else %>
32+
<div class="flex flex-row col-span-2 lg:col-span-6 justify-center mt-56">
33+
<%= MediaServerWeb.Components.SpinnerComponent.render(%{}) %>
34+
</div>
35+
<% end %>
36+
37+
</div>
38+
</div>

lib/media_server_web/repositories/movies.ex

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ defmodule MediaServerWeb.Repositories.Movies do
1414
Jason.decode!(body)
1515
end
1616

17-
def handle_response({:error, %HTTPoison.Error{id: nil, reason: :nxdomain}}) do
17+
def handle_response(_) do
1818
[]
1919
end
2020

@@ -66,4 +66,11 @@ defmodule MediaServerWeb.Repositories.Movies do
6666
|> handle_response()
6767
|> Stream.filter(fn item -> item["type"] === "cast" end)
6868
end
69+
70+
def search(query) do
71+
HTTPoison.get("#{get_url("movie/lookup")}&term=#{URI.encode(query)}")
72+
|> handle_response()
73+
|> Stream.filter(fn item -> item["hasFile"] end)
74+
|> Enum.sort_by(& &1["title"], :asc)
75+
end
6976
end

lib/media_server_web/repositories/series.ex

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ defmodule MediaServerWeb.Repositories.Series do
1414
Jason.decode!(body)
1515
end
1616

17-
def handle_response({:error, %HTTPoison.Error{id: nil, reason: :nxdomain}}) do
17+
def handle_response(_) do
1818
[]
1919
end
2020

@@ -47,4 +47,11 @@ defmodule MediaServerWeb.Repositories.Series do
4747
(Stream.filter(serie["images"], fn item -> item["coverType"] === "fanart" end)
4848
|> Enum.at(0))["remoteUrl"]
4949
end
50+
51+
def search(query) do
52+
HTTPoison.get("#{get_url("series/lookup")}&term=#{URI.encode(query)}")
53+
|> handle_response()
54+
|> Stream.filter(fn item -> item["seasonFolder"] end)
55+
|> Enum.sort_by(& &1["title"], :asc)
56+
end
5057
end

lib/media_server_web/router.ex

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ defmodule MediaServerWeb.Router do
3636
live "/episodes/:episode/watch", WatchEpisodeLive.Show, :show
3737
end
3838

39+
live "/search", SearchLive.Index, :index
40+
3941
live "/continues", ContinuesLive.Index, :index
4042
live "/favourites", FavouritesLive.Index, :index
4143

@@ -58,16 +60,18 @@ defmodule MediaServerWeb.Router do
5860
get "/episodes/:episode/stream", StreamEpisodeController, :show
5961
end
6062

61-
# Enables the Swoosh mailbox preview in development.
62-
#
63-
# Note that preview only shows emails that were sent by the same
64-
# node running the Phoenix server.
65-
if Mix.env() == :dev do
63+
if Mix.env() == :dev or Mix.env() == :test do
6664
scope "/dev" do
6765
pipe_through :browser
6866

6967
live_dashboard "/dashboard", metrics: MediaServerWeb.Telemetry
7068

69+
live "/components", MediaServerWeb.ComponentsLive.Index, :index
70+
71+
# Enables the Swoosh mailbox preview in development.
72+
#
73+
# Note that preview only shows emails that were sent by the same
74+
# node running the Phoenix server.
7175
forward "/mailbox", Plug.Swoosh.MailboxPreview
7276
end
7377
end

0 commit comments

Comments
 (0)