@@ -5,157 +5,161 @@ const formatLongString = (s) => (s.length >= 128 ? `${s.slice(0, 125)}...` : s);
5
5
let programaticPause = false ;
6
6
7
7
function getTrackVibrantColor ( ) {
8
- const sheets = document . styleSheets ;
9
-
10
- for ( let i = 0 ; i < sheets . length ; i ++ ) {
11
- try {
12
- const rules = sheets [ i ] . cssRules ;
13
-
14
- for ( let j = 0 ; j < rules . length ; j ++ ) {
15
- const rule = rules [ j ] ;
16
-
17
- if ( rule . selectorText === ":root" ) {
18
- const styles = rule . style ;
19
- const trackVibrantColor = styles . getPropertyValue (
20
- "--track-vibrant-color"
21
- ) ;
22
- if ( trackVibrantColor ) {
23
- return trackVibrantColor . trim ( ) ;
24
- }
25
- }
26
- }
27
- } catch ( e ) { }
28
- }
29
-
30
- return null ;
8
+ const sheets = document . styleSheets ;
9
+
10
+ for ( let i = 0 ; i < sheets . length ; i ++ ) {
11
+ try {
12
+ const rules = sheets [ i ] . cssRules ;
13
+
14
+ for ( let j = 0 ; j < rules . length ; j ++ ) {
15
+ const rule = rules [ j ] ;
16
+
17
+ if ( rule . selectorText === ":root" ) {
18
+ const styles = rule . style ;
19
+ const trackVibrantColor = styles . getPropertyValue (
20
+ "--track-vibrant-color" ,
21
+ ) ;
22
+ if ( trackVibrantColor ) {
23
+ return trackVibrantColor . trim ( ) ;
24
+ }
25
+ }
26
+ }
27
+ } catch ( e ) { }
28
+ }
29
+
30
+ return null ;
31
31
}
32
32
33
33
class WebSocketTransport {
34
- constructor ( ) {
35
- this . ws = null ;
36
- this . tries = 0 ;
37
- }
38
-
39
- async connect ( ) {
40
- const port = 6463 + ( this . tries % 10 ) ;
41
- this . tries += 1 ;
42
- this . ws = new WebSocket (
43
- `ws://localhost:${ port } /?v=1&client_id=1288341778637918208`
44
- ) ;
45
-
46
- this . ws . onopen = this . onOpen . bind ( this ) ;
47
-
48
- this . ws . onclose = this . onClose . bind ( this ) ;
49
-
50
- this . ws . onerror = this . onError . bind ( this ) ;
51
- }
52
-
53
- onOpen ( ) {
54
- unloadables . push (
55
- neptune . intercept ( "playbackControls/TIME_UPDATE" , ( [ current ] ) => {
56
- if ( programaticPause ) return ;
57
- const { item : currentlyPlaying , type : mediaType } =
58
- neptune . currentMediaItem ;
59
-
60
- // TODO: add video support
61
- if ( mediaType !== "track" ) return ;
62
-
63
- const date = new Date ( ) ;
64
- const now = ( date . getTime ( ) / 1000 ) ;
65
- const remaining = date . setSeconds (
66
- date . getSeconds ( ) + ( currentlyPlaying . duration - current )
67
- ) ;
68
-
69
- const paused =
70
- neptune . store . getState ( ) . playbackControls . playbackState ===
71
- "NOT_PLAYING" ;
72
-
73
- this . ws . readyState === 1 &&
74
- this . send ( {
75
- cmd : "SET_ACTIVITY" ,
76
- args : {
77
- pid : 2094112 ,
78
- activity : {
79
- timestamps : {
80
- ...( paused
81
- ? { }
82
- : {
83
- start : now ,
84
- end : remaining ,
85
- } ) ,
86
- } ,
87
- type : 2 ,
88
- name : formatLongString ( currentlyPlaying . title ) ,
89
- details : formatLongString (
90
- `by ${ currentlyPlaying . artists . map ( ( a ) => a . name ) . join ( ", " ) } `
91
- ) ,
92
- assets : {
93
- large_image : `https://resources.tidal.com/images/${ currentlyPlaying . album . cover
94
- . split ( "-" )
95
- . join ( "/" ) } /80x80.jpg`,
96
- large_text : `on ${ formatLongString (
97
- currentlyPlaying . album . title
98
- ) } `,
99
- small_text :
100
- `${ getTrackVibrantColor ( ) } |${ neptune . currentMediaItem . item . id } ` ,
101
- ...( paused
102
- ? {
103
- small_image : "paused-pause" ,
104
- }
105
- : { } ) ,
106
- } ,
107
- buttons : [ { label : "Play Song" , url : `https://listen.tidal.com/track/${ neptune . currentMediaItem . item . id } ?u` } ] ,
108
- } ,
109
- } ,
110
- } ) ;
111
- } )
112
- ) ;
113
-
114
- programaticPause = true ;
115
- neptune . actions . playbackControls . pause ( ) ;
116
- programaticPause = false ;
117
- }
118
-
119
- onClose ( event ) {
120
- if ( ! event . wasClean ) {
121
- return ;
122
- }
123
- }
124
-
125
- onError ( ) {
126
- for ( const u of unloadables ) {
127
- u ( ) ;
128
- }
129
- try {
130
- this . ws . close ( ) ;
131
- } catch { } // eslint-disable-line no-empty
132
-
133
- setTimeout ( ( ) => {
134
- this . connect ( ) ;
135
- } , 250 ) ;
136
- }
137
-
138
- send ( data ) {
139
- this . ws . send ( JSON . stringify ( data ) ) ;
140
- }
141
-
142
- close ( ) {
143
- this . ws . close ( ) ;
144
- }
34
+ constructor ( ) {
35
+ this . ws = null ;
36
+ this . tries = 0 ;
37
+ }
38
+
39
+ async connect ( ) {
40
+ const port = 6463 + ( this . tries % 10 ) ;
41
+ this . tries += 1 ;
42
+ this . ws = new WebSocket (
43
+ `ws://localhost:${ port } /?v=1&client_id=1288341778637918208` ,
44
+ ) ;
45
+
46
+ this . ws . onopen = this . onOpen . bind ( this ) ;
47
+
48
+ this . ws . onclose = this . onClose . bind ( this ) ;
49
+
50
+ this . ws . onerror = this . onError . bind ( this ) ;
51
+ }
52
+
53
+ onOpen ( ) {
54
+ unloadables . push (
55
+ neptune . intercept ( "playbackControls/TIME_UPDATE" , ( [ current ] ) => {
56
+ if ( programaticPause ) return ;
57
+ const { item : currentlyPlaying , type : mediaType } =
58
+ neptune . currentMediaItem ;
59
+
60
+ // TODO: add video support
61
+ if ( mediaType !== "track" ) return ;
62
+
63
+ const date = new Date ( ) ;
64
+ const now = date . getTime ( ) / 1000 ;
65
+ const remaining = date . setSeconds (
66
+ date . getSeconds ( ) + ( currentlyPlaying . duration - current ) ,
67
+ ) ;
68
+
69
+ const paused =
70
+ neptune . store . getState ( ) . playbackControls . playbackState ===
71
+ "NOT_PLAYING" ;
72
+
73
+ this . ws . readyState === 1 &&
74
+ this . send ( {
75
+ cmd : "SET_ACTIVITY" ,
76
+ args : {
77
+ pid : 2094112 ,
78
+ activity : {
79
+ timestamps : {
80
+ ...( paused
81
+ ? { }
82
+ : {
83
+ start : now ,
84
+ end : remaining ,
85
+ } ) ,
86
+ } ,
87
+ type : 2 ,
88
+ name : formatLongString ( currentlyPlaying . title ) ,
89
+ details : formatLongString (
90
+ `by ${ currentlyPlaying . artists . map ( ( a ) => a . name ) . join ( ", " ) } ` ,
91
+ ) ,
92
+ assets : {
93
+ large_image : `https://resources.tidal.com/images/${ currentlyPlaying . album . cover
94
+ . split ( "-" )
95
+ . join ( "/" ) } /80x80.jpg`,
96
+ large_text : `on ${ formatLongString (
97
+ currentlyPlaying . album . title ,
98
+ ) } `,
99
+ small_text : `${ getTrackVibrantColor ( ) } |${ neptune . currentMediaItem . item . id } ` ,
100
+ ...( paused
101
+ ? {
102
+ small_image : "paused-pause" ,
103
+ }
104
+ : { } ) ,
105
+ } ,
106
+ buttons : [
107
+ {
108
+ label : "Play Song" ,
109
+ url : `https://listen.tidal.com/track/${ neptune . currentMediaItem . item . id } ?u` ,
110
+ } ,
111
+ ] ,
112
+ } ,
113
+ } ,
114
+ } ) ;
115
+ } ) ,
116
+ ) ;
117
+
118
+ programaticPause = true ;
119
+ neptune . actions . playbackControls . pause ( ) ;
120
+ programaticPause = false ;
121
+ }
122
+
123
+ onClose ( event ) {
124
+ if ( ! event . wasClean ) {
125
+ return ;
126
+ }
127
+ }
128
+
129
+ onError ( ) {
130
+ for ( const u of unloadables ) {
131
+ u ( ) ;
132
+ }
133
+ try {
134
+ this . ws . close ( ) ;
135
+ } catch { } // eslint-disable-line no-empty
136
+
137
+ setTimeout ( ( ) => {
138
+ this . connect ( ) ;
139
+ } , 250 ) ;
140
+ }
141
+
142
+ send ( data ) {
143
+ this . ws . send ( JSON . stringify ( data ) ) ;
144
+ }
145
+
146
+ close ( ) {
147
+ this . ws . close ( ) ;
148
+ }
145
149
}
146
150
147
151
const ws = new WebSocketTransport ( ) ;
148
152
149
153
ws . connect ( ) ;
150
154
151
155
export async function onUnload ( ) {
152
- for ( const u of unloadables ) {
153
- u ( ) ;
154
- }
155
-
156
- if ( ws ) {
157
- try {
158
- ws . close ( ) ;
159
- } catch { }
160
- }
161
- }
156
+ for ( const u of unloadables ) {
157
+ u ( ) ;
158
+ }
159
+
160
+ if ( ws ) {
161
+ try {
162
+ ws . close ( ) ;
163
+ } catch { }
164
+ }
165
+ }
0 commit comments