diff --git a/src/cljs/airsonic_ui/subs.cljs b/src/cljs/airsonic_ui/subs.cljs index 36048a2..6513cb4 100644 --- a/src/cljs/airsonic_ui/subs.cljs +++ b/src/cljs/airsonic_ui/subs.cljs @@ -1,23 +1,30 @@ (ns airsonic-ui.subs - (:require [re-frame.core :as re-frame])) + (:require [re-frame.core :as re-frame :refer [subscribe]] + [airsonic-ui.utils.api :as api])) ;; can be used to query the user's credentials -;; FIXME: this is used for cover images and it's quite ugly tbh (re-frame/reg-sub - ::login + ::credentials (fn [db _] - (select-keys (:credentials db) [:u :p]))) + (:credentials db))) (re-frame/reg-sub ::user - (fn [{:keys [credentials]} [_]] + (fn [_ _] [(subscribe [::credentials])]) + (fn [[credentials] _] {:name (:u credentials)})) +(defn cover-url + "Provides a convenient way for views to get cover images so they don't have + to build them themselves and can live a simple and happy life." + [[{:keys [server u p]}] [_ song size]] + (api/cover-url server {:u u :p p} song size)) + (re-frame/reg-sub - ::server - (fn [db _] - (get-in db [:credentials :server]))) + ::cover-url + (fn [_ _] [(subscribe [::credentials])]) + cover-url) ;; current hashbang @@ -43,7 +50,7 @@ ::is-playing? (fn [query-v _] [(re-frame/subscribe [::currently-playing])]) - (fn [[currently-playing]] + (fn [[currently-playing] _] (let [status (:status currently-playing)] (and (not (:paused? status)) (not (:ended? status)))))) diff --git a/src/cljs/airsonic_ui/views/bottom_bar.cljs b/src/cljs/airsonic_ui/views/bottom_bar.cljs index bb7f3dc..a9ca588 100644 --- a/src/cljs/airsonic_ui/views/bottom_bar.cljs +++ b/src/cljs/airsonic_ui/views/bottom_bar.cljs @@ -15,7 +15,6 @@ :max (:duration item)}]]) (defn playback-controls [is-playing?] - ;; TODO: Toggle play pause icon based on playback status [:div.field.has-addons (let [buttons [[:media-step-backward ::events/previous-song] [(if is-playing? :media-pause :media-play) ::events/toggle-play-pause] diff --git a/src/cljs/airsonic_ui/views/cover.cljs b/src/cljs/airsonic_ui/views/cover.cljs index 7835978..adbb3ad 100644 --- a/src/cljs/airsonic_ui/views/cover.cljs +++ b/src/cljs/airsonic_ui/views/cover.cljs @@ -3,7 +3,6 @@ [re-frame.core :refer [subscribe]] [reagent.core :as reagent] [airsonic-ui.subs :as subs] - [airsonic-ui.utils.api :as api] ["@hugojosefson/color-hash" :as ColorHash])) (def color-hash (ColorHash.)) @@ -20,8 +19,6 @@ [(mod (+ h (* h 0.3) 10) 360) s l]] (map #(str "hsl(" (str/join "," %) ")"))))) -;; FIXME: The direct dependency on these subs is a bit ugly - (defn generate-cover [canvas item] (let [ctx (.getContext canvas "2d") size (.-clientWidth canvas) @@ -57,13 +54,14 @@ (defn has-cover? [item] (:coverArt item)) +;; FIXME: The direct dependency on these subs is a bit ugly + (defn cover [item size] - (let [server @(subscribe [::subs/server]) - login @(subscribe [::subs/login]) - url (partial api/cover-url server login item)] + (let [original @(subscribe [::subs/cover-url item size]) + retina @(subscribe [::subs/cover-url item (* 2 size)])] [:figure {:class-name (str "image is-" size "x" size)} (if (has-cover? item) - [:img {:src (url size) - :srcSet (str (url size) ", " (url (* 2 size)) " 2x")}] + [:img {:src original + :srcSet (str original ", " retina " 2x")}] [missing-cover item size])])) diff --git a/src/cljs/airsonic_ui/views/song.cljs b/src/cljs/airsonic_ui/views/song.cljs index 98f7f7d..a7a0c2e 100644 --- a/src/cljs/airsonic_ui/views/song.cljs +++ b/src/cljs/airsonic_ui/views/song.cljs @@ -17,13 +17,11 @@ (dispatch [::events/play-songs songs song]))} (:title song)]])) -;; FIXME: This is very similar to album-listing - (defn listing [songs] [:table.table.is-striped.is-hoverable.is-fullwidth>tbody (for [[idx song] (map-indexed vector songs)] ^{:key idx} [:tr - [:td.grow [item songs song]] - ;; FIXME: Not implemented yet - [:td>a {:title "Play next"} [icon :plus]] - [:td>a {:title "Play last"} [icon :arrow-thick-right]]])]) + [:td.grow [item songs song]] + ;; FIXME: Not implemented yet + [:td>a {:title "Play next"} [icon :plus]] + [:td>a {:title "Play last"} [icon :arrow-thick-right]]])]) diff --git a/test/cljs/airsonic_ui/fixtures.cljs b/test/cljs/airsonic_ui/fixtures.cljs index d9d500f..ffc4a42 100644 --- a/test/cljs/airsonic_ui/fixtures.cljs +++ b/test/cljs/airsonic_ui/fixtures.cljs @@ -12,3 +12,26 @@ :version "1.15.0"}} :auth-success {:subsonic-response {:status "ok" :version "1.15.0"}}}) + +(def song + {:artistId 42, + :path "DJ Koze/DJ Koze - Reincarnations Part 2, The Remix Chapter 2009-2014/14. Apparat - Black Water (DJ Koze Remix).mp3", + :suffix "mp3", + :isDir false, + :bitRate 320, + :parent 3556, + :albumId 382, + :type "music", + :created "2017-06-28T19:07:02.000Z", + :duration 317, + :artist "Apparat", + :isVideo false, + :size 12850290, + :title "Black Water (DJ Koze Remix)", + :playCount 0 + :year 2014, + :id 3562, + :coverArt 3556, + :contentType "audio/mpeg", + :album "Reincarnations, Pt. 2 - The Remix Chapter 2009 - 2014", + :track 14}) diff --git a/test/cljs/airsonic_ui/subs_test.cljs b/test/cljs/airsonic_ui/subs_test.cljs new file mode 100644 index 0000000..fed93ff --- /dev/null +++ b/test/cljs/airsonic_ui/subs_test.cljs @@ -0,0 +1,16 @@ +(ns airsonic-ui.subs-test + (:require [cljs.test :refer [deftest testing is]] + [airsonic-ui.fixtures :refer [song]] + [airsonic-ui.utils.api :as api] + [airsonic-ui.subs :as subs])) + +(deftest cover-images + (let [credentials {:server "https://foo.bar" + :u "test-user" + :p "some-random-password"}] + (testing "Should give the correct path once the credentials are set" + (is (= (api/cover-url (:server credentials) + (select-keys credentials [:u :p]) + song + 48) + (subs/cover-url [credentials] [:_ song 48]))))))