mirror of
https://github.com/heyarne/airsonic-ui.git
synced 2026-05-07 02:33:39 +02:00
Immediately render reordered tracks, reimplement actions in album view
This commit is contained in:
parent
bb700b4b66
commit
21b00dbd6b
5 changed files with 86 additions and 46 deletions
|
|
@ -109,15 +109,6 @@
|
|||
:<- [:audio/summary]
|
||||
current-playlist)
|
||||
|
||||
(defn current-queue
|
||||
[playlist _]
|
||||
(vals (:items playlist)))
|
||||
|
||||
(rf/reg-sub
|
||||
:audio/current-queue
|
||||
:<- [:audio/current-playlist]
|
||||
current-queue)
|
||||
|
||||
(defn current-song
|
||||
"Gives us information about the currently played song as presented by
|
||||
the airsonic api"
|
||||
|
|
|
|||
|
|
@ -1,30 +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]]
|
||||
[bulma.icon :refer [icon]]))
|
||||
(: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
|
||||
|
|
@ -33,8 +39,49 @@
|
|||
^{: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 [song album idx]}]
|
||||
[:a
|
||||
{:href "#" :on-click (h/muted-dispatch [:audio-player/play-all (:song album) idx] :sync? true)}
|
||||
(:title song)])
|
||||
|
||||
(defn song-actions [{:keys [song album idx]}]
|
||||
[dropdown {:items [{:label "Play next" :event [:audio-player/enqueue-next song]}
|
||||
{:label "Play last" :event [:audio-player/enqueue-last song]}]}])
|
||||
|
||||
(defn song-table [{:keys [album]}]
|
||||
;; 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>tr
|
||||
[:td.is-narrow]
|
||||
[:td.song-artist "Artist"]
|
||||
[:td.song-title "Title"]
|
||||
[:td.song-duration "Duration"]
|
||||
[:td.is-narrow]]
|
||||
[:tbody
|
||||
(for [[idx song] (map-indexed vector (:song album))]
|
||||
^{: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 {:album album
|
||||
:song song
|
||||
:idx idx}]]
|
||||
[:td.song-duration (h/format-duration (:duration song) :brief? true)]
|
||||
[:td.song-actions.is-narrow [song-actions {:album album
|
||||
:song song
|
||||
:idx idx}]]])]]))
|
||||
|
||||
(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
|
||||
|
|
@ -45,4 +92,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 {:album album}]]])
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
(ns airsonic-ui.components.current-queue.views
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
(:require [re-frame.core :refer [subscribe dispatch-sync]]
|
||||
[reagent.core :as r]
|
||||
["react-sortable-hoc" :refer [SortableHandle]]
|
||||
[bulma.icon :refer [icon]]
|
||||
|
|
@ -7,6 +7,8 @@
|
|||
[airsonic-ui.helpers :as helpers]
|
||||
[airsonic-ui.components.sortable.views :as sortable]
|
||||
[airsonic-ui.routes :as routes]
|
||||
|
||||
;; ↓ registers subscription handlers ↓
|
||||
[airsonic-ui.components.current-queue.subs]))
|
||||
|
||||
(def SortHandle
|
||||
|
|
@ -60,7 +62,9 @@
|
|||
|
||||
:on-sort-end
|
||||
(fn [{:keys [old-idx new-idx]}]
|
||||
(dispatch [:audio-player/move-song old-idx new-idx]))}]])
|
||||
;; if we don't dispatch-sync, the UI sometimes places the row back and
|
||||
;; resorts it a litle later
|
||||
(dispatch-sync [:audio-player/move-song old-idx new-idx]))}]])
|
||||
|
||||
(defn collection-info [{:keys [playlist-info]}]
|
||||
[:ul.is-smaller.collection-info
|
||||
|
|
|
|||
|
|
@ -5,12 +5,10 @@
|
|||
[bulma.dropdown.events :as ev]
|
||||
[bulma.dropdown.subs :as sub]))
|
||||
|
||||
;; there's "muted-dispatch" in airsonic-ui.helpers which does the same thing
|
||||
;; it's not used here because all the bulma.*-components should work independently
|
||||
|
||||
(defn muted-dispatch [event-vector]
|
||||
(defn choose-action [event-vector]
|
||||
(fn [e]
|
||||
(.preventDefault e)
|
||||
(dispatch [::ev/hide])
|
||||
(dispatch event-vector)))
|
||||
|
||||
(defn generate-id []
|
||||
|
|
@ -42,4 +40,4 @@
|
|||
(for [[idx {:keys [label event]}] (map-indexed vector items)]
|
||||
^{:key (str dropdown-id "-" idx)}
|
||||
[:a.dropdown-item {:href "#"
|
||||
:on-click (muted-dispatch event)} label])]]]))))
|
||||
:on-click (choose-action event)} label])]]]))))
|
||||
|
|
|
|||
|
|
@ -298,17 +298,6 @@
|
|||
margin-right: 1rem
|
||||
margin-bottom: 0
|
||||
|
||||
.collection-info
|
||||
list-style: none
|
||||
|
||||
li
|
||||
display: inline-block
|
||||
margin-left: 0.75rem
|
||||
|
||||
&:first-child
|
||||
margin-left: 0
|
||||
|
||||
|
||||
.song-list
|
||||
counter-reset: track
|
||||
|
||||
|
|
@ -323,6 +312,16 @@
|
|||
display: inline
|
||||
padding-right: 0.375rem
|
||||
|
||||
.collection-info
|
||||
list-style: none
|
||||
|
||||
li
|
||||
display: inline-block
|
||||
margin-left: 0.75rem
|
||||
|
||||
&:first-child
|
||||
margin-left: 0
|
||||
|
||||
.song-listing-table
|
||||
tr.is-playing
|
||||
background-color: $table-row-active-background-color
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue