diff --git a/lib/music_library/colors.ex b/lib/music_library/colors.ex new file mode 100644 index 00000000..a6b5fd33 --- /dev/null +++ b/lib/music_library/colors.ex @@ -0,0 +1,11 @@ +defmodule MusicLibrary.Colors do + alias MusicLibrary.Colors.{ColorFrequencyExtractor, EdgeWeightedExtractor} + + def extract_colors(image_data, :fast) do + ColorFrequencyExtractor.extract_dominant_colors(image_data) + end + + def extract_colors(image_data, :slow) do + EdgeWeightedExtractor.extract_dominant_colors(image_data) + end +end diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex index 7a950874..25f9f4f3 100644 --- a/lib/music_library/records.ex +++ b/lib/music_library/records.ex @@ -6,7 +6,6 @@ defmodule MusicLibrary.Records do import Ecto.Query, warn: false alias MusicLibrary.Artists - alias MusicLibrary.Colors.EdgeWeightedExtractor alias MusicLibrary.Records.{ArtistRecord, Cover, Record, SearchParser} alias MusicLibrary.{BackgroundRepo, Repo, Worker} @@ -255,18 +254,12 @@ defmodule MusicLibrary.Records do |> BackgroundRepo.insert() end - def generate_dominant_colors(record) do - with {:ok, colors} <- EdgeWeightedExtractor.extract_dominant_colors(record.cover_data) do - update_record(record, %{"dominant_colors" => colors}) - end - end - - def generate_dominant_colors_async(record) do + def extract_colors_async(record, method) do meta = %{title: record.title, artists: Enum.map(record.artists, & &1.name)} - params = %{"id" => record.id} + params = %{"id" => record.id, "method" => method} params - |> Worker.GenerateDominantColors.new(meta: meta) + |> Worker.ExtractColors.new(meta: meta) |> BackgroundRepo.insert() end @@ -329,7 +322,7 @@ defmodule MusicLibrary.Records do def create_record(attrs \\ %{}) do with {:ok, record} <- do_create_record(attrs) do - generate_dominant_colors_async(record) + extract_colors_async(record, :fast) record |> Record.artist_ids() diff --git a/lib/music_library/worker/extract_colors.ex b/lib/music_library/worker/extract_colors.ex new file mode 100644 index 00000000..ed01907e --- /dev/null +++ b/lib/music_library/worker/extract_colors.ex @@ -0,0 +1,16 @@ +defmodule MusicLibrary.Worker.ExtractColors do + use Oban.Worker, queue: :heavy_writes, max_attempts: 3 + + alias MusicLibrary.{Colors, Records} + + @impl Oban.Worker + def perform(%Oban.Job{args: %{"id" => record_id, "method" => method}}) do + record = MusicLibrary.Records.get_record!(record_id) + method = String.to_existing_atom(method) + + with {:ok, colors} <- Colors.extract_colors(record.cover_data, method), + {:ok, updated_record} <- Records.update_record(record, %{dominant_colors: colors}) do + MusicLibrary.Records.notify_update(updated_record) + end + end +end diff --git a/lib/music_library/worker/generate_dominant_colors.ex b/lib/music_library/worker/generate_dominant_colors.ex deleted file mode 100644 index 2de8d913..00000000 --- a/lib/music_library/worker/generate_dominant_colors.ex +++ /dev/null @@ -1,12 +0,0 @@ -defmodule MusicLibrary.Worker.GenerateDominantColors do - use Oban.Worker, queue: :heavy_writes, max_attempts: 3 - - @impl Oban.Worker - def perform(%Oban.Job{args: %{"id" => record_id}}) do - record = MusicLibrary.Records.get_record!(record_id) - - with {:ok, updated_record} <- MusicLibrary.Records.generate_dominant_colors(record) do - MusicLibrary.Records.notify_update(updated_record) - end - end -end diff --git a/lib/music_library_web/live/collection_live/show.ex b/lib/music_library_web/live/collection_live/show.ex index dbf96482..468e52e0 100644 --- a/lib/music_library_web/live/collection_live/show.ex +++ b/lib/music_library_web/live/collection_live/show.ex @@ -116,6 +116,26 @@ defmodule MusicLibraryWeb.CollectionLive.Show do end end + def handle_event("extract_colors", %{"id" => id, "method" => method}, socket) do + record = Records.get_record!(id) + method = String.to_existing_atom(method) + + case Records.extract_colors_async(record, method) do + {:ok, _worker} -> + {:noreply, + socket + |> put_flash(:info, gettext("In progress - record will update automatically"))} + + {:error, reason} -> + {:noreply, + socket + |> put_flash( + :error, + gettext("Error") <> "," <> inspect(reason) + )} + end + end + @impl true def handle_info({MusicLibraryWeb.FormComponent, {:saved, record}}, socket) do {:noreply, assign(socket, :record, record)} diff --git a/lib/music_library_web/live/collection_live/show.html.heex b/lib/music_library_web/live/collection_live/show.html.heex index 36c3c069..5f18b4f2 100644 --- a/lib/music_library_web/live/collection_live/show.html.heex +++ b/lib/music_library_web/live/collection_live/show.html.heex @@ -91,6 +91,38 @@ {gettext("Populate genres")} + <.link + class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700" + role="menuitem" + tabindex="0" + id={"actions-#{@record.id}-extract-colors-fast"} + phx-click={JS.push("extract_colors", value: %{id: @record.id, method: :fast})} + > + <.icon + name="hero-paint-brush" + class="h-4 w-4 mr-1 phx-click-loading:animate-shake" + aria-hidden="true" + data-slot="icon" + /> + {gettext("Extract colors (fast)")} + + + <.link + class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700" + role="menuitem" + tabindex="0" + id={"actions-#{@record.id}-extract-colors-slow"} + phx-click={JS.push("extract_colors", value: %{id: @record.id, method: :slow})} + > + <.icon + name="hero-paint-brush" + class="h-4 w-4 mr-1 phx-click-loading:animate-shake" + aria-hidden="true" + data-slot="icon" + /> + {gettext("Extract colors (slow)")} + + <.link class="block px-3 py-1 text-sm leading-6 text-red-900 hover:bg-red-50 dark:text-red-700 dark:hover:bg-red-900/30 dark:hover:text-red-600" role="menuitem" diff --git a/lib/music_library_web/live/wishlist_live/show.ex b/lib/music_library_web/live/wishlist_live/show.ex index c94b0f96..f11c98ca 100644 --- a/lib/music_library_web/live/wishlist_live/show.ex +++ b/lib/music_library_web/live/wishlist_live/show.ex @@ -117,6 +117,26 @@ defmodule MusicLibraryWeb.WishlistLive.Show do end end + def handle_event("extract_colors", %{"id" => id, "method" => method}, socket) do + record = Records.get_record!(id) + method = String.to_existing_atom(method) + + case Records.extract_colors_async(record, method) do + {:ok, _worker} -> + {:noreply, + socket + |> put_flash(:info, gettext("In progress - record will update automatically"))} + + {:error, reason} -> + {:noreply, + socket + |> put_flash( + :error, + gettext("Error") <> "," <> inspect(reason) + )} + end + end + @impl true def handle_info({MusicLibraryWeb.FormComponent, {:saved, record}}, socket) do {:noreply, assign(socket, :record, record)} diff --git a/lib/music_library_web/live/wishlist_live/show.html.heex b/lib/music_library_web/live/wishlist_live/show.html.heex index 27398236..97fd9a50 100644 --- a/lib/music_library_web/live/wishlist_live/show.html.heex +++ b/lib/music_library_web/live/wishlist_live/show.html.heex @@ -111,6 +111,38 @@ {gettext("Purchased")} + <.link + class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700" + role="menuitem" + tabindex="0" + id={"actions-#{@record.id}-extract-colors-fast"} + phx-click={JS.push("extract_colors", value: %{id: @record.id, method: :fast})} + > + <.icon + name="hero-paint-brush" + class="h-4 w-4 mr-1 phx-click-loading:animate-shake" + aria-hidden="true" + data-slot="icon" + /> + {gettext("Extract colors (fast)")} + + + <.link + class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700" + role="menuitem" + tabindex="0" + id={"actions-#{@record.id}-extract-colors-slow"} + phx-click={JS.push("extract_colors", value: %{id: @record.id, method: :slow})} + > + <.icon + name="hero-paint-brush" + class="h-4 w-4 mr-1 phx-click-loading:animate-shake" + aria-hidden="true" + data-slot="icon" + /> + {gettext("Extract colors (slow)")} + + <.link class="block px-3 py-1 text-sm leading-6 text-red-900 hover:bg-red-50 dark:text-red-700 dark:hover:bg-red-900/30 dark:hover:text-red-600" role="menuitem" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index 4a92f2a1..dfc7e1f5 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -674,6 +674,7 @@ msgid "Meta" msgstr "" #: lib/music_library_web/live/collection_live/show.ex +#: lib/music_library_web/live/wishlist_live/show.ex #, elixir-autogen, elixir-format msgid "Record updated in the background" msgstr "" @@ -854,3 +855,27 @@ msgstr "" #, elixir-autogen, elixir-format msgid "Last listened at" msgstr "" + +#: lib/music_library_web/live/collection_live/show.ex +#: lib/music_library_web/live/wishlist_live/show.ex +#, elixir-autogen, elixir-format +msgid "Error" +msgstr "" + +#: lib/music_library_web/live/collection_live/show.html.heex +#: lib/music_library_web/live/wishlist_live/show.html.heex +#, elixir-autogen, elixir-format +msgid "Extract colors (fast)" +msgstr "" + +#: lib/music_library_web/live/collection_live/show.html.heex +#: lib/music_library_web/live/wishlist_live/show.html.heex +#, elixir-autogen, elixir-format +msgid "Extract colors (slow)" +msgstr "" + +#: lib/music_library_web/live/collection_live/show.ex +#: lib/music_library_web/live/wishlist_live/show.ex +#, elixir-autogen, elixir-format +msgid "In progress - record will update automatically" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index 15e7633a..f7c10f53 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -674,6 +674,7 @@ msgid "Meta" msgstr "" #: lib/music_library_web/live/collection_live/show.ex +#: lib/music_library_web/live/wishlist_live/show.ex #, elixir-autogen, elixir-format msgid "Record updated in the background" msgstr "" @@ -854,3 +855,27 @@ msgstr "" #, elixir-autogen, elixir-format msgid "Last listened at" msgstr "" + +#: lib/music_library_web/live/collection_live/show.ex +#: lib/music_library_web/live/wishlist_live/show.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Error" +msgstr "" + +#: lib/music_library_web/live/collection_live/show.html.heex +#: lib/music_library_web/live/wishlist_live/show.html.heex +#, elixir-autogen, elixir-format +msgid "Extract colors (fast)" +msgstr "" + +#: lib/music_library_web/live/collection_live/show.html.heex +#: lib/music_library_web/live/wishlist_live/show.html.heex +#, elixir-autogen, elixir-format +msgid "Extract colors (slow)" +msgstr "" + +#: lib/music_library_web/live/collection_live/show.ex +#: lib/music_library_web/live/wishlist_live/show.ex +#, elixir-autogen, elixir-format +msgid "In progress - record will update automatically" +msgstr ""