@@ -9,14 +9,95 @@ import qs.Services
99Singleton {
1010 id: root
1111
12- readonly property bool hasAccent: true
13- readonly property color accent: Theme .primary
12+ readonly property bool hasAccent: SettingsData . mediaUseAlbumArtAccent ? _accent !== null : true
13+ readonly property color accent: SettingsData . mediaUseAlbumArtAccent && _accent !== null ? _accent : Theme .primary
1414
15- readonly property color onAccent: Theme .onPrimary
15+ readonly property color onAccent: SettingsData .mediaUseAlbumArtAccent && _accent !== null ? (() => {
16+ const lum = 0.2126 * _accent .r + 0.7152 * _accent .g + 0.0722 * _accent .b ;
17+ return lum > 0.6 ? Qt .rgba (0 , 0 , 0 , 1 ) : Qt .rgba (1 , 1 , 1 , 1 );
18+ })() : Theme .onPrimary
1619
1720 readonly property color accentHover: Theme .withAlpha (accent, 0.12 )
1821 readonly property color accentPressed: Theme .withAlpha (accent, Theme .transparentBlurLayers ? 0.24 : 0.16 )
1922
2023 readonly property color accentTrack: Theme .withAlpha (accent, 0.28 )
2124 readonly property color accentSubtle: Theme .withAlpha (accent, 0.55 )
25+
26+ readonly property string artUrl: {
27+ const resolved = TrackArtService .resolvedArtUrl ;
28+ if (resolved !== " " )
29+ return resolved;
30+ const p = MprisController .activePlayer ;
31+ if (! p)
32+ return " " ;
33+ if (p .trackArtUrl )
34+ return p .trackArtUrl ;
35+ const m = p .metadata ;
36+ return m && m[" mpris:artUrl" ] ? m[" mpris:artUrl" ].toString () : " " ;
37+ }
38+
39+ property var _accent: null
40+
41+ ColorQuantizer {
42+ id: quantizer
43+ source: root .artUrl
44+ depth: 4
45+ rescaleSize: 64
46+ onColorsChanged: {
47+ if (! colors || colors .length === 0 )
48+ return ;
49+ root ._accent = root ._pickAccent (colors);
50+ }
51+ }
52+
53+ function _pickAccent (colors ) {
54+ if (! colors || colors .length === 0 )
55+ return null ;
56+
57+ let best = null ;
58+ let bestScore = - 1 ;
59+ for (let i = 0 ; i < colors .length ; i++ ) {
60+ const c = colors[i];
61+ const s = c .hsvSaturation ;
62+ const v = c .hsvValue ;
63+ if (v < 0.22 || v > 0.96 || s < 0.22 )
64+ continue ;
65+ const score = s * (1 - Math .abs (v - 0.68 ));
66+ if (score > bestScore) {
67+ bestScore = score;
68+ best = c;
69+ }
70+ }
71+
72+ if (best)
73+ return _normalize (best);
74+
75+ return _pickNeutral (colors);
76+ }
77+
78+ function _pickNeutral (colors ) {
79+ let best = null ;
80+ let bestScore = - 1 ;
81+ for (let i = 0 ; i < colors .length ; i++ ) {
82+ const c = colors[i];
83+ const v = c .hsvValue ;
84+ const score = (1 - Math .abs (v - 0.6 )) + c .hsvSaturation * 0.5 ;
85+ if (score > bestScore) {
86+ bestScore = score;
87+ best = c;
88+ }
89+ }
90+
91+ const hue = best .hsvHue < 0 ? 0 : best .hsvHue ;
92+ const s = Math .min (best .hsvSaturation , 0.18 );
93+ const v = Math .min (Math .max (best .hsvValue , 0.6 ), 0.82 );
94+ return Qt .hsva (hue, s, v, 1 );
95+ }
96+
97+ function _normalize (c ) {
98+ const hue = c .hsvHue < 0 ? 0 : c .hsvHue ;
99+ const s = Math .min (1 , c .hsvSaturation * 1.05 );
100+ const v = Math .max (c .hsvValue , 0.62 );
101+ return Qt .hsva (hue, s, v, 1 );
102+ }
22103}
0 commit comments