1
1
// Since we declared the script as type=module in the HTML file,
2
- // we can use ES Modules (adapted from the Vue 2 Introduction
3
- // https://vuejs.org/v2/guide/#Declarative-Rendering
2
+ // we can use ES Modules
4
3
5
- // Alternatively, omit the .min from the path for Vue debugging purposes.
6
- import Vue from '../node_modules/vue/dist/vue.esm. browser.min .js' ;
4
+ // Alternatively, omit the .prod from the path for Vue debugging purposes.
5
+ import { createApp } from '../node_modules/vue/dist/vue.esm- browser.prod .js' ;
7
6
8
7
let api = window . muspnpapi ;
9
8
dayjs . extend ( dayjs_plugin_duration ) ;
@@ -22,38 +21,42 @@ function toDuration(strDuration) {
22
21
} ) ;
23
22
}
24
23
25
- window . app = new Vue ( {
26
- el : '#app' ,
27
- data : {
28
- showSpinner : true ,
29
- error : null ,
30
- refreshErrors : 0 ,
31
- libraryObjectsCache : null ,
32
- selectedItem : [ ] ,
33
- playlist : null ,
34
- currentPlayingItem : null ,
35
- currentPositionInfo : null ,
36
- currentMediaServer : '' ,
37
- currentMediaRenderer : '' ,
38
- availableMediaServers : null ,
39
- availableMediaRenderers : null ,
40
- refreshTimer : null ,
41
- transportInfo : null ,
42
- currentVolume : null ,
43
- searchCapabilities : null ,
44
- search : null ,
45
- searchResults : null ,
24
+ window . app = createApp ( {
25
+ data : function ( ) {
26
+ return {
27
+ showSpinner : true ,
28
+ error : null ,
29
+ refreshErrors : 0 ,
30
+ libraryObjectsCache : null ,
31
+ selectedItem : [ ] ,
32
+ playlist : null ,
33
+ currentPlayingItem : null ,
34
+ currentPositionInfo : null ,
35
+ currentMediaServer : '' ,
36
+ currentMediaRenderer : '' ,
37
+ availableMediaServers : null ,
38
+ availableMediaRenderers : null ,
39
+ refreshTimer : null ,
40
+ transportInfo : null ,
41
+ currentVolume : null ,
42
+ searchCapabilities : null ,
43
+ search : null ,
44
+ searchResults : null ,
45
+ }
46
46
} ,
47
47
watch : {
48
48
currentMediaServer : function ( device ) {
49
+ this . showSpinner = true ;
49
50
this . libraryObjectsCache = null ;
50
51
this . selectedItem = [ ] ;
51
- this . showSpinner = true ;
52
+ this . searchCapabilities = null ;
52
53
api . selectServer ( { usn : device . usn } )
53
54
. then ( ( ) => this . browse ( { id : 0 , start : 0 , count : 0 } ) )
54
- . then ( ( ) => api . getSearchCapabilities ( ) )
55
+ . then ( ( ) => api . getSearchCapabilities ( ) . catch ( ( ) => null ) )
55
56
. then ( ( searchCapabilities ) => {
56
- this . searchCapabilities = searchCapabilities . split ( ',' ) . filter ( ( prop ) => [ 'dc:title' , 'upnp:album' , 'upnp:artist' ] . includes ( prop ) )
57
+ if ( searchCapabilities ) {
58
+ this . searchCapabilities = searchCapabilities . split ( ',' ) . filter ( ( prop ) => [ 'dc:title' , 'upnp:album' , 'upnp:artist' ] . includes ( prop ) )
59
+ }
57
60
} )
58
61
. then ( ( ) => this . showSpinner = false )
59
62
. catch ( err => this . error = err ) ;
@@ -82,6 +85,9 @@ window.app = new Vue({
82
85
}
83
86
} ,
84
87
search : function ( search ) {
88
+ if ( ! search ) {
89
+ return ;
90
+ }
85
91
const searchStr = this . searchCapabilities . map ( sc => `${ sc } contains "${ search } "` ) . join ( ' or ' )
86
92
this . searchResults = null ;
87
93
return api
@@ -148,6 +154,9 @@ window.app = new Vue({
148
154
if ( this . _currentPosition_currentPosition == null || this . _currentPosition_duration == null ) {
149
155
return 0 ;
150
156
}
157
+ if ( this . _currentPosition_duration . asSeconds ( ) === 0 ) {
158
+ return 0 ;
159
+ }
151
160
return Math . round ( 100 * this . _currentPosition_currentPosition . asSeconds ( ) / this . _currentPosition_duration . asSeconds ( ) ) ;
152
161
} ,
153
162
currentPositionRemaining : function ( ) {
@@ -186,15 +195,15 @@ window.app = new Vue({
186
195
// Update cache if cache miss or UpdateID changed
187
196
if ( res . UpdateID == null || this . libraryObjectsCache . data ?. [ id ] ?. UpdateID !== res . UpdateID ) {
188
197
// Also freeze res because we don't need reactivity on this potentially big structure
189
- this . $set ( this . libraryObjectsCache . data , id , Object . freeze ( res ) ) ;
198
+ this . libraryObjectsCache . data [ id ] = Object . freeze ( res ) ;
190
199
}
191
200
// Always keep track of effective cache use & remove old entries
192
201
// This is suboptimal because we will fill the fifo with duplicates, but it should work well enough in most cases
193
202
this . libraryObjectsCache . fifo . push ( String ( id ) ) ;
194
203
if ( this . libraryObjectsCache . fifo . length > 20 ) {
195
204
const removeId = this . libraryObjectsCache . fifo . shift ( ) ;
196
205
if ( ! this . libraryObjectsCache . fifo . includes ( removeId ) ) {
197
- this . $ delete( this . libraryObjectsCache . data , removeId ) ;
206
+ delete this . libraryObjectsCache . data [ removeId ]
198
207
}
199
208
}
200
209
} )
@@ -299,9 +308,7 @@ window.app = new Vue({
299
308
const volumePercent = Math . round ( x * e . target . max / e . target . offsetWidth ) ;
300
309
this . currentVolume = volumePercent ;
301
310
api . setVolume ( { desiredVolume : volumePercent } ) ;
302
- }
303
- } ,
304
- filters : {
311
+ } ,
305
312
toIcon : function ( item ) {
306
313
if ( item [ 'upnp:class' ] . startsWith ( 'object.container' ) ) {
307
314
return '📁' ;
@@ -318,5 +325,5 @@ window.app = new Vue({
318
325
return '[]' ;
319
326
}
320
327
}
321
- } )
328
+ } ) . mount ( '#app' )
322
329
0 commit comments