Navigate from scrobble search to release-group page

This commit is contained in:
Claudio Ortolina
2026-04-23 14:47:50 +01:00
parent 0dcd6eab83
commit c7c7e1fe4e
4 changed files with 33 additions and 214 deletions
@@ -1,9 +1,9 @@
defmodule MusicLibraryWeb.ScrobbleLive.Index do defmodule MusicLibraryWeb.ScrobbleLive.Index do
use MusicLibraryWeb, :live_view use MusicLibraryWeb, :live_view
import MusicLibraryWeb.RecordComponents, only: [type_label: 1, country_label: 1] import MusicLibraryWeb.RecordComponents, only: [type_label: 1]
alias MusicBrainz.{Release, ReleaseGroupSearchResult} alias MusicBrainz.ReleaseGroupSearchResult
alias MusicLibrary.Records alias MusicLibrary.Records
alias MusicLibrary.ScrobbleActivity alias MusicLibrary.ScrobbleActivity
@@ -25,7 +25,7 @@ defmodule MusicLibraryWeb.ScrobbleLive.Index do
</.button> </.button>
</div> </div>
</header> </header>
<%= if @search_results != [] && @selected_release_group == nil do %> <%= if @search_results != [] do %>
<div class="space-y-3"> <div class="space-y-3">
<h3 class="text-lg font-semibold text-zinc-900 dark:text-zinc-200"> <h3 class="text-lg font-semibold text-zinc-900 dark:text-zinc-200">
{gettext("Release Groups")} {gettext("Release Groups")}
@@ -34,10 +34,9 @@ defmodule MusicLibraryWeb.ScrobbleLive.Index do
"mt-5 divide-y divide-zinc-100 dark:divide-slate-300/30", "mt-5 divide-y divide-zinc-100 dark:divide-slate-300/30",
"max-h-125 overflow-y-auto" "max-h-125 overflow-y-auto"
]}> ]}>
<li <li :for={release_group <- @search_results}>
:for={release_group <- @search_results} <.link
phx-click="select_release_group" navigate={~p"/scrobble/#{release_group.id}"}
phx-value-release_group_id={release_group.id}
class="flex cursor-pointer justify-between gap-x-6 py-5 hover:bg-zinc-100 dark:hover:bg-zinc-700" class="flex cursor-pointer justify-between gap-x-6 py-5 hover:bg-zinc-100 dark:hover:bg-zinc-700"
> >
<div class="flex w-full shrink-0 items-center justify-between px-4"> <div class="flex w-full shrink-0 items-center justify-between px-4">
@@ -61,56 +60,6 @@ defmodule MusicLibraryWeb.ScrobbleLive.Index do
</p> </p>
</div> </div>
</div> </div>
</li>
</ul>
</div>
<% end %>
<%= if @selected_release_group && @releases != [] do %>
<div class="space-y-3">
<div class="flex items-center gap-2">
<.button
variant="ghost"
size="sm"
phx-click="clear_selection"
>
<.icon name="hero-arrow-left" class="icon" aria-hidden="true" data-slot="icon" />
{gettext("Back")}
</.button>
<h3 class="text-lg font-semibold">
{gettext("Releases for \"%{title}\"", title: @selected_release_group.title)}
</h3>
</div>
<ul class="divide-y divide-zinc-100 dark:divide-slate-300/30">
<li :for={release <- @releases}>
<.link
navigate={~p"/scrobble/#{release.id}"}
class="flex items-center gap-x-4 px-4 py-5 transition-colors hover:bg-zinc-100 dark:hover:bg-zinc-700"
>
<img
class="w-20 flex-none rounded-lg"
alt={release.title}
src={Release.thumb_url(release)}
onerror={"this.src = '" <> ~p"/images/cover-not-found.png" <> "';"}
/>
<div class="min-w-0 flex-auto">
<p class="font-medium text-zinc-900 dark:text-zinc-100">
{release.title}
</p>
<div class="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-sm text-zinc-500 dark:text-zinc-400">
<span :if={release.date}>{release.date}</span>
<span :if={release.country}>
{country_label(release.country)}
</span>
<.badge :if={release.catalog_number} variant="soft" size="xs">
{release.catalog_number}
</.badge>
<span :if={release.media != []}>
{ngettext("1 disc", "%{count} discs", Release.media_count(release))}
</span>
</div>
</div>
</.link> </.link>
</li> </li>
</ul> </ul>
@@ -121,11 +70,7 @@ defmodule MusicLibraryWeb.ScrobbleLive.Index do
<div class="py-8 text-center"> <div class="py-8 text-center">
<.loading class="mx-auto size-8 text-zinc-400" /> <.loading class="mx-auto size-8 text-zinc-400" />
<p class="mt-2 text-zinc-600 dark:text-zinc-400"> <p class="mt-2 text-zinc-600 dark:text-zinc-400">
<%= if @selected_release_group do %>
{gettext("Loading releases...")}
<% else %>
{gettext("Searching...")} {gettext("Searching...")}
<% end %>
</p> </p>
</div> </div>
<% end %> <% end %>
@@ -156,8 +101,6 @@ defmodule MusicLibraryWeb.ScrobbleLive.Index do
current_section: :scrobble, current_section: :scrobble,
search_query: "", search_query: "",
search_results: [], search_results: [],
selected_release_group: nil,
releases: [],
loading: false, loading: false,
can_scrobble?: ScrobbleActivity.can_scrobble?() can_scrobble?: ScrobbleActivity.can_scrobble?()
)} )}
@@ -190,9 +133,7 @@ defmodule MusicLibraryWeb.ScrobbleLive.Index do
{:noreply, {:noreply,
assign(socket, assign(socket,
search_query: query, search_query: query,
search_results: [], search_results: []
selected_release_group: nil,
releases: []
)} )}
else else
send(self(), {:perform_search, query}) send(self(), {:perform_search, query})
@@ -200,22 +141,6 @@ defmodule MusicLibraryWeb.ScrobbleLive.Index do
end end
end end
def handle_event("select_release_group", %{"release_group_id" => release_group_id}, socket) do
selected_release_group =
Enum.find(socket.assigns.search_results, &(&1.id == release_group_id))
if selected_release_group do
send(self(), {:fetch_releases, selected_release_group})
{:noreply, assign(socket, selected_release_group: selected_release_group, loading: true)}
else
{:noreply, socket}
end
end
def handle_event("clear_selection", _params, socket) do
{:noreply, assign(socket, selected_release_group: nil, releases: [])}
end
@impl true @impl true
def handle_info({:perform_search, query}, socket) do def handle_info({:perform_search, query}, socket) do
case MusicBrainz.search_release_group(query, limit: 20) do case MusicBrainz.search_release_group(query, limit: 20) do
@@ -223,9 +148,7 @@ defmodule MusicLibraryWeb.ScrobbleLive.Index do
{:noreply, {:noreply,
assign(socket, assign(socket,
search_results: results.release_groups, search_results: results.release_groups,
loading: false, loading: false
selected_release_group: nil,
releases: []
)} )}
{:error, _reason} -> {:error, _reason} ->
@@ -235,21 +158,4 @@ defmodule MusicLibraryWeb.ScrobbleLive.Index do
|> assign(loading: false)} |> assign(loading: false)}
end end
end end
def handle_info({:fetch_releases, release_group}, socket) do
case MusicBrainz.get_releases(release_group.id, limit: 50) do
{:ok, %{"releases" => releases}} ->
releases =
releases
|> Enum.map(&MusicBrainz.Release.from_api_response/1)
{:noreply, assign(socket, releases: releases, loading: false)}
{:error, _reason} ->
{:noreply,
socket
|> put_flash(:error, gettext("Failed to fetch releases for this release group"))
|> assign(loading: false)}
end
end
end end
-21
View File
@@ -1256,11 +1256,6 @@ msgstr ""
msgid "Scrobble" msgid "Scrobble"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format
msgid "Failed to fetch releases for this release group"
msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex #: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Failed to search for release groups" msgid "Failed to search for release groups"
@@ -1271,7 +1266,6 @@ msgstr ""
msgid "Release Groups" msgid "Release Groups"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex
#: lib/music_library_web/live/scrobble_live/release_group_show.ex #: lib/music_library_web/live/scrobble_live/release_group_show.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "1 disc" msgid "1 disc"
@@ -1279,11 +1273,6 @@ msgid_plural "%{count} discs"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format
msgid "Releases for \"%{title}\""
msgstr ""
#: lib/music_library_web/live/scrobble_live/release_show.ex #: lib/music_library_web/live/scrobble_live/release_show.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "You need to connect your Last.fm account to scrobble. Please set up your Last.fm session key in the settings." msgid "You need to connect your Last.fm account to scrobble. Please set up your Last.fm session key in the settings."
@@ -1700,11 +1689,6 @@ msgstr ""
msgid "Search for artist image online" msgid "Search for artist image online"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format
msgid "Back"
msgstr ""
#: lib/music_library_web/live/scrobble_live/release_group_show.ex #: lib/music_library_web/live/scrobble_live/release_group_show.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Back to search" msgid "Back to search"
@@ -1715,11 +1699,6 @@ msgstr ""
msgid "Last.fm not connected" msgid "Last.fm not connected"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format
msgid "Loading releases..."
msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex #: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "No release groups found for \"%{query}\"" msgid "No release groups found for \"%{query}\""
-21
View File
@@ -1256,11 +1256,6 @@ msgstr ""
msgid "Scrobble" msgid "Scrobble"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format
msgid "Failed to fetch releases for this release group"
msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex #: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Failed to search for release groups" msgid "Failed to search for release groups"
@@ -1271,7 +1266,6 @@ msgstr ""
msgid "Release Groups" msgid "Release Groups"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex
#: lib/music_library_web/live/scrobble_live/release_group_show.ex #: lib/music_library_web/live/scrobble_live/release_group_show.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "1 disc" msgid "1 disc"
@@ -1279,11 +1273,6 @@ msgid_plural "%{count} discs"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format
msgid "Releases for \"%{title}\""
msgstr ""
#: lib/music_library_web/live/scrobble_live/release_show.ex #: lib/music_library_web/live/scrobble_live/release_show.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "You need to connect your Last.fm account to scrobble. Please set up your Last.fm session key in the settings." msgid "You need to connect your Last.fm account to scrobble. Please set up your Last.fm session key in the settings."
@@ -1700,11 +1689,6 @@ msgstr ""
msgid "Search for artist image online" msgid "Search for artist image online"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Back"
msgstr ""
#: lib/music_library_web/live/scrobble_live/release_group_show.ex #: lib/music_library_web/live/scrobble_live/release_group_show.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Back to search" msgid "Back to search"
@@ -1715,11 +1699,6 @@ msgstr ""
msgid "Last.fm not connected" msgid "Last.fm not connected"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Loading releases..."
msgstr ""
#: lib/music_library_web/live/scrobble_live/index.ex #: lib/music_library_web/live/scrobble_live/index.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "No release groups found for \"%{query}\"" msgid "No release groups found for \"%{query}\""
@@ -1,7 +1,7 @@
defmodule MusicLibraryWeb.ScrobbleLive.IndexTest do defmodule MusicLibraryWeb.ScrobbleLive.IndexTest do
use MusicLibraryWeb.ConnCase use MusicLibraryWeb.ConnCase
import Phoenix.LiveViewTest, only: [render: 1, render_submit: 1, render_click: 3, form: 3] import Phoenix.LiveViewTest, only: [render: 1, render_submit: 1, form: 3]
alias MusicBrainz.Fixtures.ReleaseGroup alias MusicBrainz.Fixtures.ReleaseGroup
alias Req.Test alias Req.Test
@@ -12,9 +12,6 @@ defmodule MusicLibraryWeb.ScrobbleLive.IndexTest do
"/ws/2/release-group" -> "/ws/2/release-group" ->
Test.json(conn, ReleaseGroup.release_group_search_results()) Test.json(conn, ReleaseGroup.release_group_search_results())
"/ws/2/release" ->
Test.json(conn, ReleaseGroup.release_group_releases(:marbles))
_ -> _ ->
Test.json(conn, %{}) Test.json(conn, %{})
end end
@@ -91,56 +88,14 @@ defmodule MusicLibraryWeb.ScrobbleLive.IndexTest do
|> refute_has("h3", "Release Groups") |> refute_has("h3", "Release Groups")
end end
test "select release group shows releases", %{conn: conn} do test "clicking a release group navigates to /scrobble/:rg_id", %{conn: conn} do
release_group_id = ReleaseGroup.release_group_id(:marbles) release_group_id = ReleaseGroup.release_group_id(:marbles)
session = visit(conn, ~p"/scrobble") session = visit(conn, ~p"/scrobble?#{[query: "marbles"]}")
session session
|> unwrap(fn view -> |> click_link("a[href='/scrobble/#{release_group_id}']", "Marbles")
view |> assert_path(~p"/scrobble/#{release_group_id}")
|> form("form[phx-submit='search']", %{query: "marbles"})
|> render_submit()
render(view)
view
|> render_click("select_release_group", %{
"release_group_id" => release_group_id
})
render(view)
end)
|> assert_has("h3", "Releases for")
|> assert_has("button", "Back")
end
test "clear selection goes back to release groups", %{conn: conn} do
release_group_id = ReleaseGroup.release_group_id(:marbles)
session = visit(conn, ~p"/scrobble")
session
|> unwrap(fn view ->
view
|> form("form[phx-submit='search']", %{query: "marbles"})
|> render_submit()
render(view)
view
|> render_click("select_release_group", %{
"release_group_id" => release_group_id
})
render(view)
# Click back button
view
|> render_click("clear_selection", %{})
end)
|> assert_has("h3", "Release Groups")
|> refute_has("h3", "Releases for")
end end
end end