diff --git a/lib/live_beats/media_library.ex b/lib/live_beats/media_library.ex
index 5759b1a..7ae0912 100644
--- a/lib/live_beats/media_library.ex
+++ b/lib/live_beats/media_library.ex
@@ -49,7 +49,7 @@ defmodule LiveBeats.MediaLibrary do
stopped_query =
from s in Song,
- where: s.user_id == ^song.user_id and s.status == :playing,
+ where: s.user_id == ^song.user_id and s.status in [:playing, :paused],
update: [set: [status: :stopped]]
{:ok, %{now_playing: new_song}} =
@@ -89,7 +89,12 @@ defmodule LiveBeats.MediaLibrary do
end
def put_stats(%Ecto.Changeset{} = changeset, %MP3Stat{} = stat) do
- Ecto.Changeset.put_change(changeset, :duration, stat.duration)
+ chset = Song.put_duration(changeset, stat.duration)
+ if error = chset.errors[:duration] do
+ {:error, %{duration: error}}
+ else
+ {:ok, chset}
+ end
end
def import_songs(%Accounts.User{} = user, changesets, consume_file)
diff --git a/lib/live_beats/media_library/song.ex b/lib/live_beats/media_library/song.ex
index 206940b..0780bc2 100644
--- a/lib/live_beats/media_library/song.ex
+++ b/lib/live_beats/media_library/song.ex
@@ -15,6 +15,7 @@ defmodule LiveBeats.MediaLibrary.Song do
field :duration, :integer
field :status, Ecto.Enum, values: [stopped: 1, playing: 2, paused: 3]
field :title, :string
+ field :attribution, :string
field :mp3_url, :string
field :mp3_filepath, :string
field :mp3_filename, :string
@@ -31,15 +32,24 @@ defmodule LiveBeats.MediaLibrary.Song do
@doc false
def changeset(song, attrs) do
song
- |> cast(attrs, [:album_artist, :artist, :title, :date_recorded, :date_released])
+ |> cast(attrs, [:album_artist, :artist, :title, :attribution, :date_recorded, :date_released])
|> validate_required([:artist, :title])
- |> validate_number(:duration, greater_than: 0, less_than: 1200)
end
def put_user(%Ecto.Changeset{} = changeset, %Accounts.User{} = user) do
put_assoc(changeset, :user, user)
end
+ def put_duration(%Ecto.Changeset{} = changeset, duration) when is_integer(duration) do
+ changeset
+ |> Ecto.Changeset.change(%{duration: duration})
+ |> Ecto.Changeset.validate_number(:duration,
+ greater_than: 0,
+ less_than: 1200,
+ message: "must be less than 20 minutes"
+ )
+ end
+
def put_mp3_path(%Ecto.Changeset{} = changeset) do
if changeset.valid? do
filename = Ecto.UUID.generate() <> ".mp3"
diff --git a/lib/live_beats_web/live/live_helpers.ex b/lib/live_beats_web/live/live_helpers.ex
index 4a7daff..1c434ec 100644
--- a/lib/live_beats_web/live/live_helpers.ex
+++ b/lib/live_beats_web/live/live_helpers.ex
@@ -315,7 +315,7 @@ defmodule LiveBeatsWeb.LiveHelpers do
<%= for {row, i} <- Enum.with_index(@rows) do %>
<%= for col <- @col do %>
-
+ |
<%= render_slot(col, row) %>
diff --git a/lib/live_beats_web/live/player_live.ex b/lib/live_beats_web/live/player_live.ex
index cf115e9..1a03f28 100644
--- a/lib/live_beats_web/live/player_live.ex
+++ b/lib/live_beats_web/live/player_live.ex
@@ -16,7 +16,7 @@ defmodule LiveBeatsWeb.PlayerLive do
-
+
<%= if @song, do: @song.title, else: raw(" ") %>
diff --git a/lib/live_beats_web/live/song_live/index.ex b/lib/live_beats_web/live/song_live/index.ex
index f697c81..e8924ca 100644
--- a/lib/live_beats_web/live/song_live/index.ex
+++ b/lib/live_beats_web/live/song_live/index.ex
@@ -33,6 +33,7 @@ defmodule LiveBeatsWeb.SongLive.Index do
>
<:col let={%{song: song}} label="Title"><%= song.title %>
<:col let={%{song: song}} label="Artist"><%= song.artist %>
+ <:col let={%{song: song}} label="Attribution" class="max-w-5xl break-words text-gray-600 font-light"><%= song.attribution %>
<:col let={%{song: song}} label="Duration"><%= MP3Stat.to_mmss(song.duration) %>
<:col let={%{song: song}} label="">
<.link phx-click={show_modal("delete-modal-#{song.id}")} class="inline-flex items-center px-3 py-2 text-sm leading-4 font-medium">
diff --git a/lib/live_beats_web/live/song_live/song_entry_component.ex b/lib/live_beats_web/live/song_live/song_entry_component.ex
index 0d0b010..a2d2d1b 100644
--- a/lib/live_beats_web/live/song_live/song_entry_component.ex
+++ b/lib/live_beats_web/live/song_live/song_entry_component.ex
@@ -33,6 +33,18 @@ defmodule LiveBeatsWeb.SongLive.SongEntryComponent do
<.error input_name={"songs[#{@ref}][title]"} field={:title} errors={@errors} class="-mt-1"/>
<.error input_name={"songs[#{@ref}][artist]"} field={:artist} errors={@errors} class="-mt-1"/>
+
+
+
+
+
+ <.error input_name={"songs[#{@ref}][attribution]"} field={:attribution} errors={@errors} class="-mt-1"/>
+
@@ -51,6 +63,7 @@ defmodule LiveBeatsWeb.SongLive.SongEntryComponent do
|> assign(title: Ecto.Changeset.get_field(changeset, :title))
|> assign(artist: Ecto.Changeset.get_field(changeset, :artist))
|> assign(duration: Ecto.Changeset.get_field(changeset, :duration))
+ |> assign(attribution: Ecto.Changeset.get_field(changeset, :attribution))
|> assign_new(:progress, fn -> 0 end)}
end
end
diff --git a/lib/live_beats_web/live/song_live/song_row_component.ex b/lib/live_beats_web/live/song_live/song_row_component.ex
index 6494e89..5074efb 100644
--- a/lib/live_beats_web/live/song_live/song_row_component.ex
+++ b/lib/live_beats_web/live/song_live/song_row_component.ex
@@ -10,7 +10,7 @@ defmodule LiveBeatsWeb.SongLive.SongRowComponent do
<%= for {col, i} <- Enum.with_index(@col) do %>
diff --git a/lib/live_beats_web/live/song_live/upload_form_component.ex b/lib/live_beats_web/live/song_live/upload_form_component.ex
index 4e10097..c9c1512 100644
--- a/lib/live_beats_web/live/song_live/upload_form_component.ex
+++ b/lib/live_beats_web/live/song_live/upload_form_component.ex
@@ -46,18 +46,26 @@ defmodule LiveBeatsWeb.SongLive.UploadFormComponent do
%{current_user: current_user} = socket.assigns
changesets = socket.assigns.changesets
- case MediaLibrary.import_songs(current_user, changesets, &consume_entry(socket, &1, &2)) do
- {:ok, songs} ->
- {:noreply,
- socket
- |> put_flash(:info, "#{map_size(songs)} song(s) uploaded")
- |> push_redirect(to: Routes.song_index_path(socket, :index))}
+ if pending_stats?(socket) do
+ {:noreply, socket}
+ else
+ case MediaLibrary.import_songs(current_user, changesets, &consume_entry(socket, &1, &2)) do
+ {:ok, songs} ->
+ {:noreply,
+ socket
+ |> put_flash(:info, "#{map_size(songs)} song(s) uploaded")
+ |> push_redirect(to: home_path(socket))}
- {:error, _reason} ->
- {:noreply, socket}
+ {:error, _reason} ->
+ {:noreply, socket}
+ end
end
end
+ defp pending_stats?(socket) do
+ Enum.find(socket.assigns.changesets, fn {_ref, chset} -> !chset.changes[:duration] end)
+ end
+
defp consume_entry(socket, ref, store_func) when is_function(store_func) do
{entries, []} = uploaded_entries(socket, :mp3)
entry = Enum.find(entries, fn entry -> entry.ref == ref end)
@@ -121,6 +129,7 @@ defmodule LiveBeatsWeb.SongLive.UploadFormComponent do
consume_uploaded_entry(socket, entry, fn %{path: path} ->
Task.Supervisor.start_child(LiveBeats.TaskSupervisor, fn ->
+ Process.sleep(5000)
send_update(lv, __MODULE__,
id: socket.assigns.id,
action: {:duration, entry.ref, LiveBeats.MP3Stat.parse(path)}
@@ -136,9 +145,20 @@ defmodule LiveBeatsWeb.SongLive.UploadFormComponent do
defp file_error(%{kind: :not_accepted} = assigns), do: ~H|not a valid MP3 file|
defp file_error(%{kind: :too_many_files} = assigns), do: ~H|too many files|
+ defp file_error(%{kind: {msg, opts}} = assigns) when is_binary(msg) and is_list(opts) do
+ ~H|<%= LiveBeatsWeb.ErrorHelpers.translate_error(@kind) %>|
+ end
+
defp put_stats(socket, entry_ref, %MP3Stat{} = stat) do
if changeset = get_changeset(socket, entry_ref) do
- update_changeset(socket, MediaLibrary.put_stats(changeset, stat), entry_ref)
+ case MediaLibrary.put_stats(changeset, stat) do
+ {:ok, new_changeset} ->
+ update_changeset(socket, new_changeset, entry_ref)
+
+ {:error, %{duration: error}} ->
+ IO.inspect({:duration, error})
+ cancel_changeset_upload(socket, entry_ref, error)
+ end
else
socket
end
diff --git a/lib/live_beats_web/templates/layout/live.html.heex b/lib/live_beats_web/templates/layout/live.html.heex
index 0a5cdae..f0e1fd0 100644
--- a/lib/live_beats_web/templates/layout/live.html.heex
+++ b/lib/live_beats_web/templates/layout/live.html.heex
@@ -1,4 +1,10 @@
+ <.live_component module={LiveBeatsWeb.LayoutComponent} id="layout" />
+
+ <%= if @current_user do %>
+ <%= live_render(@socket, LiveBeatsWeb.PlayerLive, id: "player", session: %{}, sticky: true) %>
+ <% end %>
+
<%= live_flash(@flash, :info) %>
@@ -7,7 +13,5 @@
phx-click="lv:clear-flash"
phx-value-key="error"><%= live_flash(@flash, :error) %>
- <.live_component module={LiveBeatsWeb.LayoutComponent} id="layout" />
-
<%= @inner_content %>
diff --git a/lib/live_beats_web/templates/layout/root.html.heex b/lib/live_beats_web/templates/layout/root.html.heex
index 50f7490..83cb26d 100644
--- a/lib/live_beats_web/templates/layout/root.html.heex
+++ b/lib/live_beats_web/templates/layout/root.html.heex
@@ -301,9 +301,6 @@
- <%= if @current_user do %>
- <%= live_render(@conn, LiveBeatsWeb.PlayerLive, session: %{}) %>
- <% end %>
<%= @inner_content %>
diff --git a/priv/repo/migrations/20211027201102_create_songs.exs b/priv/repo/migrations/20211027201102_create_songs.exs
index 3da4df1..7244dea 100644
--- a/priv/repo/migrations/20211027201102_create_songs.exs
+++ b/priv/repo/migrations/20211027201102_create_songs.exs
@@ -10,6 +10,7 @@ defmodule LiveBeats.Repo.Migrations.CreateSongs do
add :played_at, :utc_datetime
add :paused_at, :utc_datetime
add :title, :string, null: false
+ add :attribution, :string
add :mp3_url, :string, null: false
add :mp3_filename, :string, null: false
add :mp3_filepath, :string, null: false
| |