1
0
Fork 0
mirror of https://github.com/heyarne/airsonic-ui.git synced 2026-05-07 02:33:39 +02:00

Improvements to currently playing queue (#48)

* First sloppy import of code from heyarne/reagent-movable

* Consistently use "current queue" to avoid confusion

* Update shadow-cljs, re-frame and debux

* Solve styling problem when sorting table rows

* Make sortable component more reusable

* Refactor playlist to use a sorted-map

* Make sure current queue is displayed again

* Fix sorting when converting a shuffled into a linear playlist

* Implement set-current-track

* Implement song-move in playlist

* Add autoprefixer

* Implement drag and drop reordering in current queue

* Fix broken dev sass build

* Bump some dependencies

* Move airsonic-ui.views.icon to bulma.icon

* Implement reusable dropdown in bulma.dropdown

* Immediately render reordered tracks, reimplement actions in album view

* Use new song-table on search result page

* Make song-table more reusable

* Remove current song

* Implement go to source in current queue

* Remove unused song view
This commit is contained in:
heyarne 2019-03-12 15:22:13 +01:00 committed by GitHub
commit 8bf222a6e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1773 additions and 869 deletions

View file

@ -1,31 +1,36 @@
(ns airsonic-ui.components.collection.views
"A collection is a list of audio files that belong together (e.g. an album or
a podcast's overview)"
(:require [airsonic-ui.helpers :refer [format-duration]]
[airsonic-ui.routes :as routes :refer [url-for]]
[airsonic-ui.views.cover :refer [cover card]]
[airsonic-ui.views.icon :refer [icon]]
[airsonic-ui.views.song :as song]))
(:require [re-frame.core :refer [subscribe]]
[bulma.icon :refer [icon]]
[bulma.dropdown.views :refer [dropdown]]
[airsonic-ui.helpers :as h]
[airsonic-ui.routes :as routes]
[airsonic-ui.views.cover :refer [cover card]]))
(defn collection-info [{:keys [songCount duration year]}]
(vec (cond-> [:ul.is-smaller.collection-info
[:li [icon :audio-spectrum] (str songCount (if (= 1 songCount)
" track" " tracks"))]
[:li [icon :clock] (format-duration duration)]]
[:li [icon :clock] (h/format-duration duration)]]
year (conj [:li [icon :calendar] (str "Released in " year)]))))
(defn album-card [album]
(let [{:keys [artist artistId name id]} album]
[card album
:url-fn #(url-for ::routes/album.detail {:id id})
:content [:div
;; link to album
[:div.title.is-5
[:a {:href (url-for ::routes/album.detail {:id id})
:title name} name]]
;; link to artist page
[:div.subtitle.is-6 [:a {:href (url-for ::routes/artist.detail {:id artistId})
:title artist} artist]]]]))
;; TODO: Maybe this view belongs somewhere else?
;; Something like a collection-grid component?
(defn album-card
"A single element in a grid of albums. Shows the cover, artist and album name."
[{:keys [artist artistId name id] :as album}]
[card album
:url-fn #(routes/url-for ::routes/album.detail {:id id})
:content [:div
;; link to album
[:div.title.is-5
[:a {:href (routes/url-for ::routes/album.detail {:id id})
:title name} name]]
;; link to artist page
[:div.subtitle.is-6 [:a {:href (routes/url-for ::routes/artist.detail {:id artistId})
:title artist} artist]]]])
(defn listing [albums]
;; always show 5 in a row
@ -34,8 +39,54 @@
^{:key idx} [:div.column.is-one-fifth-desktop.is-one-quarter-tablet.is-half-mobile
[album-card album]])])
;; TODO: Avoid duplication
(defn artist-link [{id :artistId, artist :artist}]
(if id
[:a {:href (routes/url-for ::routes/artist.detail {:id id})} artist]
artist))
(defn song-link [{:keys [songs song idx]}]
[:a
{:href "#" :on-click (h/muted-dispatch [:audio-player/play-all songs idx] :sync? true)}
(:title song)])
(defn song-actions [song]
[dropdown {:items [{:label "Play next" :event [:audio-player/enqueue-next song]}
{:label "Play last" :event [:audio-player/enqueue-last song]}]}])
(defn default-thead []
[:thead>tr
[:td.is-narrow]
[:td.song-artist "Artist"]
[:td.song-title "Title"]
[:td.song-duration "Duration"]
[:td.is-narrow]])
(defn default-tbody [{:keys [songs current-song]}]
[:tbody
(for [[idx song] (map-indexed vector songs)]
^{:key idx}
[(if (= (:id song) (:id current-song)) :tr.is-playing :tr)
[:td.song-tracknr.is-narrow (:track song)]
[:td.song-artist [artist-link song]]
[:td.song-title [song-link {:songs songs
:song song
:idx idx}]]
[:td.song-duration (h/format-duration (:duration song) :brief? true)]
[:td.song-actions.is-narrow [song-actions song]]])])
(defn song-table [{:keys [songs thead tbody]
:or {thead default-thead, tbody default-tbody}}]
;; we subscribe here instead of one level higher up to make this a more
;; reusable component; this way we can for example get a list of all songs
;; in a search result and easily highlight the currently playing track
(let [current-song @(subscribe [:audio/current-song])]
[:table.song-listing-table.table.is-fullwidth
[thead]
[tbody {:songs songs, :current-song current-song}]]))
(defn detail
"Lists all songs in an album"
"Shows a detail view of a single album, listing all "
[{:keys [album]}]
[:div
[:section.hero.is-small>div.hero-body
@ -46,4 +97,5 @@
[:h2.title (:name album)]
[:h3.subtitle (:artist album)]
[collection-info album]]]]]
[:section.section>div.container [song/listing (:song album)]]])
[:section.section>div.container
[song-table {:songs (:song album)}]]])