mirror of
https://github.com/heyarne/airsonic-ui.git
synced 2026-05-07 02:33:39 +02:00
Add generated covers for items that have none
This commit is contained in:
parent
45d5a4bd04
commit
a0e24f5979
4 changed files with 73 additions and 5 deletions
13
package-lock.json
generated
13
package-lock.json
generated
|
|
@ -4,6 +4,14 @@
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@hugojosefson/color-hash": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@hugojosefson/color-hash/-/color-hash-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-ASaDCIwQmyeH6eXdG1Nf2zMOr85Ljp13/8qBSPtYkY1hAr6URRAPG+15i2ogXh/caSolZ4mGfP7MwHPLm/V2Dw==",
|
||||||
|
"requires": {
|
||||||
|
"string-hash": "^1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"abbrev": {
|
"abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
|
|
@ -5844,6 +5852,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"string-hash": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs="
|
||||||
|
},
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
"url": "git://github.com/heyarne/airsonic-ui.git"
|
"url": "git://github.com/heyarne/airsonic-ui.git"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@hugojosefson/color-hash": "^2.0.3",
|
||||||
"bulma": "^0.7.1",
|
"bulma": "^0.7.1",
|
||||||
"create-react-class": "^15.6.3",
|
"create-react-class": "^15.6.3",
|
||||||
"react": "^16.3.2",
|
"react": "^16.3.2",
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,10 @@
|
||||||
|
|
||||||
(defn sidebar [user]
|
(defn sidebar [user]
|
||||||
[:aside.menu.section
|
[:aside.menu.section
|
||||||
[:p.menu-label (str "User: " (:name user))]
|
[:p.menu-label user]
|
||||||
[:ul.menu-list
|
[:ul.menu-list
|
||||||
[:li [:a "Settings"]]
|
[:li [:a "Settings"]]
|
||||||
|
;; FIXME: Create proper logout event
|
||||||
[:li [:a {:on-click #(dispatch [::events/initialize-db]) :href "#"} "Logout"]]]])
|
[:li [:a {:on-click #(dispatch [::events/initialize-db]) :href "#"} "Logout"]]]])
|
||||||
|
|
||||||
;; putting everything together
|
;; putting everything together
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,68 @@
|
||||||
(ns airsonic-ui.views.cover
|
(ns airsonic-ui.views.cover
|
||||||
(:require [re-frame.core :refer [subscribe]]
|
(:require [clojure.string :as str]
|
||||||
|
[re-frame.core :refer [subscribe]]
|
||||||
|
[reagent.core :as reagent]
|
||||||
[airsonic-ui.subs :as subs]
|
[airsonic-ui.subs :as subs]
|
||||||
[airsonic-ui.utils.api :as api]))
|
[airsonic-ui.utils.api :as api]
|
||||||
|
["@hugojosefson/color-hash" :as ColorHash]))
|
||||||
|
|
||||||
|
(def color-hash (ColorHash.))
|
||||||
|
|
||||||
|
(defn palette
|
||||||
|
"Generate a hsl palette of two colors that's unique for a given item"
|
||||||
|
[item]
|
||||||
|
(let [[h s l] (js->clj (.hsl color-hash (str (:name item) (:artist item))))
|
||||||
|
s (str (* 100 s) "%")
|
||||||
|
l (str (* 100 l) "%")]
|
||||||
|
(->>
|
||||||
|
[[h s l]
|
||||||
|
[(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
|
;; FIXME: The direct dependency on these subs is a bit ugly
|
||||||
|
|
||||||
|
(defn generate-cover [canvas item]
|
||||||
|
(let [ctx (.getContext canvas "2d")
|
||||||
|
size (.-clientWidth canvas)
|
||||||
|
[a b] (palette item)
|
||||||
|
pad (* 0.02 size)
|
||||||
|
gradient (doto (.createLinearGradient ctx pad 0 (- size pad) size)
|
||||||
|
(.addColorStop 0 a)
|
||||||
|
(.addColorStop 1 b))]
|
||||||
|
(set! (.-fillStyle ctx) gradient)
|
||||||
|
(.fillRect ctx 0 0 size size)))
|
||||||
|
|
||||||
|
(defn missing-cover
|
||||||
|
[item size]
|
||||||
|
(let [dom-node (reagent/atom nil)]
|
||||||
|
(reagent/create-class
|
||||||
|
{:component-did-update
|
||||||
|
(fn [this]
|
||||||
|
(let [canvas @dom-node]
|
||||||
|
(set! (.. canvas -style -width) "100%")
|
||||||
|
(set! (. canvas -width) (.-offsetWidth canvas))
|
||||||
|
(set! (. canvas -height) (.-offsetWidth canvas))
|
||||||
|
(generate-cover canvas item)))
|
||||||
|
|
||||||
|
:component-did-mount
|
||||||
|
(fn [this]
|
||||||
|
(reset! dom-node (reagent/dom-node this)))
|
||||||
|
|
||||||
|
:reagent-render
|
||||||
|
(fn []
|
||||||
|
@dom-node
|
||||||
|
[:canvas.missing-cover])})))
|
||||||
|
|
||||||
|
(defn has-cover? [item]
|
||||||
|
(:coverArt item))
|
||||||
|
|
||||||
(defn cover
|
(defn cover
|
||||||
[item size]
|
[item size]
|
||||||
(let [server @(subscribe [::subs/server])
|
(let [server @(subscribe [::subs/server])
|
||||||
login @(subscribe [::subs/login])
|
login @(subscribe [::subs/login])
|
||||||
url (partial api/cover-url server login item)]
|
url (partial api/cover-url server login item)]
|
||||||
[:figure {:class-name (str "image is-" size "x" size)}
|
[:figure {:class-name (str "image is-" size "x" size)}
|
||||||
|
(if (has-cover? item)
|
||||||
[:img {:src (url size)
|
[:img {:src (url size)
|
||||||
:srcset (str (url size) ", " (url (* 2 size)) " 2x")}]]))
|
:srcSet (str (url size) ", " (url (* 2 size)) " 2x")}]
|
||||||
|
[missing-cover item size])]))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue