karaoke-eternal 1.0.0 → 2.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/build/client/447.a51d7d3f87c474adad54.js +1 -0
- package/build/client/715.a51d7d3f87c474adad54.js +1 -0
- package/build/client/718.a51d7d3f87c474adad54.js +1 -0
- package/build/client/851.a51d7d3f87c474adad54.js +1 -0
- package/build/{845.4be526e3a94d53aeceae.css → client/958.a51d7d3f87c474adad54.css} +53 -6
- package/build/client/958.a51d7d3f87c474adad54.js +1 -0
- package/build/{index.html → client/index.html} +1 -1
- package/build/{licenses.txt → client/licenses.txt} +208 -496
- package/build/client/main.a51d7d3f87c474adad54.css +2341 -0
- package/build/client/main.a51d7d3f87c474adad54.js +1 -0
- package/build/server/Library/Library.js +297 -0
- package/build/server/Library/ipc.js +13 -0
- package/build/server/Library/router.js +20 -0
- package/build/server/Library/socket.js +35 -0
- package/build/server/Media/Media.js +170 -0
- package/build/server/Media/fileTypes.js +8 -0
- package/build/server/Media/ipc.js +13 -0
- package/build/server/Media/router.js +97 -0
- package/build/server/Player/socket.js +66 -0
- package/build/server/Prefs/Prefs.js +181 -0
- package/build/server/Prefs/router.js +151 -0
- package/build/server/Prefs/socket.js +52 -0
- package/build/server/Queue/Queue.js +203 -0
- package/build/server/Queue/socket.js +83 -0
- package/build/server/Rooms/Rooms.js +171 -0
- package/build/server/Rooms/router.js +97 -0
- package/build/server/Rooms/socket.js +23 -0
- package/build/server/Scanner/FileScanner/FileScanner.js +166 -0
- package/build/server/Scanner/FileScanner/getConfig.js +32 -0
- package/build/server/Scanner/FileScanner/getFiles.js +61 -0
- package/build/server/Scanner/MetaParser/MetaParser.js +77 -0
- package/build/server/Scanner/MetaParser/defaultMiddleware.js +170 -0
- package/build/server/Scanner/Scanner.js +26 -0
- package/build/server/Scanner/ScannerQueue.js +62 -0
- package/build/server/User/User.js +206 -0
- package/build/server/User/router.js +366 -0
- package/build/server/lib/Database.js +39 -0
- package/build/server/lib/Errors.js +6 -0
- package/build/server/lib/IPCBridge.js +128 -0
- package/build/server/lib/Log.js +31 -0
- package/build/server/lib/accumulatedThrottle.js +16 -0
- package/build/server/lib/bcrypt.js +23 -0
- package/build/server/lib/cli.js +131 -0
- package/build/server/lib/getCdgName.js +18 -0
- package/build/server/lib/getFolders.js +8 -0
- package/build/server/lib/getHotMiddleware.js +22 -0
- package/build/server/lib/getIPAddress.js +14 -0
- package/build/server/lib/getPermutations.js +17 -0
- package/build/server/lib/getWindowsDrives.js +17 -0
- package/build/server/lib/parseCookie.js +13 -0
- package/build/server/lib/pushQueuesAndLibrary.js +22 -0
- package/{server → build/server}/lib/schemas/001-initial-schema.sql +26 -26
- package/build/server/lib/schemas/004-paths-rooms-data.sql +7 -0
- package/build/server/lib/schemas/005-roles.sql +32 -0
- package/build/server/lib/util.js +39 -0
- package/build/server/main.js +124 -0
- package/build/server/scannerWorker.js +59 -0
- package/build/server/serverWorker.js +219 -0
- package/build/server/socket.js +134 -0
- package/build/server/watcherWorker.js +51 -0
- package/build/shared/actionTypes.js +113 -0
- package/build/shared/types.js +1 -0
- package/package.json +111 -86
- package/build/267.4be526e3a94d53aeceae.js +0 -1
- package/build/591.4be526e3a94d53aeceae.js +0 -1
- package/build/598.4be526e3a94d53aeceae.js +0 -1
- package/build/799.4be526e3a94d53aeceae.js +0 -1
- package/build/845.4be526e3a94d53aeceae.js +0 -1
- package/build/main.4be526e3a94d53aeceae.css +0 -2034
- package/build/main.4be526e3a94d53aeceae.js +0 -1
- package/server/Library/Library.js +0 -340
- package/server/Library/index.js +0 -3
- package/server/Library/ipc.js +0 -18
- package/server/Library/router.js +0 -27
- package/server/Library/socket.js +0 -47
- package/server/Media/Media.js +0 -207
- package/server/Media/index.js +0 -3
- package/server/Media/ipc.js +0 -19
- package/server/Media/router.js +0 -99
- package/server/Player/socket.js +0 -78
- package/server/Prefs/Prefs.js +0 -165
- package/server/Prefs/index.js +0 -3
- package/server/Prefs/router.js +0 -124
- package/server/Prefs/socket.js +0 -68
- package/server/Queue/Queue.js +0 -208
- package/server/Queue/index.js +0 -3
- package/server/Queue/socket.js +0 -99
- package/server/Rooms/Rooms.js +0 -114
- package/server/Rooms/index.js +0 -3
- package/server/Rooms/router.js +0 -146
- package/server/Scanner/FileScanner/FileScanner.js +0 -225
- package/server/Scanner/FileScanner/getConfig.js +0 -35
- package/server/Scanner/FileScanner/getFiles.js +0 -63
- package/server/Scanner/FileScanner/index.js +0 -3
- package/server/Scanner/MetaParser/MetaParser.js +0 -49
- package/server/Scanner/MetaParser/defaultMiddleware.js +0 -197
- package/server/Scanner/MetaParser/index.js +0 -3
- package/server/Scanner/Scanner.js +0 -33
- package/server/User/User.js +0 -139
- package/server/User/index.js +0 -3
- package/server/User/router.js +0 -442
- package/server/lib/Database.js +0 -55
- package/server/lib/IPCBridge.js +0 -115
- package/server/lib/Log.js +0 -71
- package/server/lib/bcrypt.js +0 -24
- package/server/lib/cli.js +0 -136
- package/server/lib/electron.js +0 -81
- package/server/lib/getCdgName.js +0 -20
- package/server/lib/getDevMiddleware.js +0 -51
- package/server/lib/getFolders.js +0 -10
- package/server/lib/getHotMiddleware.js +0 -27
- package/server/lib/getIPAddress.js +0 -16
- package/server/lib/getPermutations.js +0 -21
- package/server/lib/getWindowsDrives.js +0 -30
- package/server/lib/parseCookie.js +0 -12
- package/server/lib/pushQueuesAndLibrary.js +0 -29
- package/server/main.js +0 -135
- package/server/scannerWorker.js +0 -58
- package/server/serverWorker.js +0 -242
- package/server/socket.js +0 -173
- package/shared/actionTypes.js +0 -103
- /package/build/{7ce9eb3fe454f54745a4.woff2 → client/7ce9eb3fe454f54745a4.woff2} +0 -0
- /package/build/{598.4be526e3a94d53aeceae.css → client/851.a51d7d3f87c474adad54.css} +0 -0
- /package/build/{a35814dd9eb496e3d7cc.woff2 → client/a35814dd9eb496e3d7cc.woff2} +0 -0
- /package/build/{e419b95dccb58b362811.woff2 → client/e419b95dccb58b362811.woff2} +0 -0
- /package/{server → build/server}/lib/schemas/002-replaygain.sql +0 -0
- /package/{server → build/server}/lib/schemas/003-queue-linked-list.sql +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! See licenses in licenses.txt */(()=>{"use strict";var e,t,a,n,s,r={5668:(e,t,a)=>{a.d(t,{A:()=>i});var n=a(96540),s=a(34164),r=a(80519);const l="qVDsyq0en4mmfO12Q9S6",i=({className:e,dateUpdated:t,userId:a})=>{const[i,o]=(0,n.useState)(!0),[c,d]=(0,n.useState)(!1),u=(0,n.useCallback)(()=>o(!1),[]),m=(0,n.useCallback)(()=>{o(!1),d(!0)},[]);return(0,n.useEffect)(()=>{o(!0),d(!1)},[a,t]),n.createElement("div",{className:(0,s.A)(l,e)},(i||c)&&n.createElement(r.A,{icon:"ACCOUNT"}),!c&&n.createElement("img",{src:`${document.baseURI}api/user/${a}/image?v=${t}`,onLoad:u,onError:m,style:{display:i?"none":"initial"}}))}},8870:(e,t,a)=>{a.d(t,{A:()=>E,D:()=>i});var n=a(15452),s=a(70960),r=a(9934),l=a(42730);const i=(0,n.zD)("userStars/toggleSongStarred",async(e,{dispatch:t,getState:a})=>{(0,r.wd)(a().userStars).starredSongs.includes(e)?t(c(e)):t(o(e))}),o=(0,n.VP)(l.H8,e=>({payload:{songId:e},meta:{isOptimistic:!0}})),c=(0,n.VP)(l.s4,e=>({payload:{songId:e},meta:{isOptimistic:!0}})),d=(0,n.VP)(l.OA),u=(0,n.VP)(l.DN),m=(0,n.VP)(l.bA),p=(0,n.VP)(l.qx),h={userId:null,starredArtists:[],starredSongs:[]},E=(0,n.vy)(h,e=>{e.addCase(o,(e,{payload:t})=>{e.starredSongs.push(t.songId)}).addCase(c,(e,{payload:t})=>{e.starredSongs.splice(e.starredSongs.indexOf(t.songId),1)}).addCase(d,(e,{payload:t})=>{t.userId!==e.userId||e.starredSongs.includes(t.songId)||e.starredSongs.push(t.songId)}).addCase(u,(e,{payload:t})=>{t.userId===e.userId&&e.starredSongs.includes(t.songId)&&e.starredSongs.splice(e.starredSongs.indexOf(t.songId),1)}).addCase(m,(e,{payload:t})=>({...e,...t})).addCase(p,(e,{payload:t})=>{e.userId=t.userId}).addCase(s.r2,(e,{payload:t})=>{"number"==typeof t?.userId&&(e.userId=t.userId)}).addCase(l.T_,()=>({...h})).addCase(l.OL,()=>({...h}))})},32509:(e,t,a)=>{a.d(t,{A:()=>l});var n=a(9934),s=a(25508),r=a(46685);const l=(0,s.Mz)([e=>(0,n.wd)(e.queue).result,e=>(0,n.wd)(e.queue).entities,r.A,e=>e.status.queueId,e=>e.status.nextUserId],(e,t,a,n,s)=>{if(a=a.filter(t=>e.includes(t)),t[n]&&-1===a.lastIndexOf(n)&&a.push(n),null!==s)for(const n of e)if(!a.includes(n)&&!0!==t[n].isOptimistic&&t[n].userId===s){a.push(n);break}const r=new Map,l=[],i=a.map(e=>t[e].userId);for(e.forEach(e=>{if(a.includes(e)||!0===t[e].isOptimistic)return;const n=t[e].userId;r.set(n,r.has(n)?[...r.get(n),e]:[e])});r.size;){let e,t=-1;for(const a of r.keys()){const n=i.lastIndexOf(a),s=-1===n?1/0:i.length-n;s>t&&(t=s,e=a)}const a=r.get(e),n=a.shift();a.length?r.set(e,a):r.delete(e),i.push(e),l.push(n)}return{result:a.concat(l),entities:t}})},32681:(e,t,a)=>{a.d(t,{A:()=>s});var n=a(70960);class s{static init(e,t){return this.instance=(0,n.GM)(e,null,t),this.instance}static get(){if(!this.instance)throw new Error("persistor not initialized");return this.instance}}},33054:(e,t,a)=>{a.d(t,{A:()=>l});var n=a(9934),s=a(25508),r=a(46685);const l=(0,s.Mz)([e=>(0,n.wd)(e.queue).result,e=>(0,n.wd)(e.queue).entities,r.A,e=>e.status.queueId,(e,t)=>t],(e,t,a,n,s)=>e.filter(e=>{const r=t[e];return!0!==r.isOptimistic&&r.userId===s&&e!==n&&!a.includes(e)}))},37655:(e,t,a)=>{a.d(t,{A:()=>N});var n=a(15452),s=a(9934),r=a(42730);const l=(0,n.VP)(r.tA),i=(0,n.vy)({result:[],entities:{}},e=>{e.addCase(l,(e,{payload:t})=>({result:t.artists.result,entities:t.artists.entities}))});var o=a(47768),c=a(99996),d=a(38180),u=a(80470);const m=(0,n.VP)(r.dh),p=(0,n.VP)(r.tA),h=(0,n.vy)({result:[],entities:{}},e=>{e.addCase(p,(e,{payload:t})=>({result:t.songs.result,entities:t.songs.entities})).addCase(m,(e,{payload:t})=>({...e,entities:{...e.entities,...t}}))});var E=a(89853);const g=(0,n.VP)(r.OA),v=(0,n.VP)(r.DN),f=(0,n.VP)(r.Nz),C=(0,n.vy)({artists:{},songs:{},version:0},e=>{e.addCase(g,(e,{payload:t})=>{e.songs[t.songId]=e.songs[t.songId]+1||1}).addCase(v,(e,{payload:t})=>{e.songs[t.songId]=Math.max(e.songs[t.songId]-1,0)}).addCase(f,(e,{payload:t})=>({...t}))});var y=a(88146),b=a(85134),w=a(77759),A=a(8870);const N=(0,n.fP)({artists:i,library:o.Ay,prefs:c.Ay,queue:(0,s.yi)(d.Ay),rooms:u.Ay,songs:h,songInfo:E.Ay,starCounts:C,status:y.Ay,ui:b.Ay,user:w.Ay,userStars:(0,s.yi)(A.A)}).withLazyLoadedSlices()},38180:(e,t,a)=>{a.d(t,{$1:()=>d,Ai:()=>o,Ay:()=>m,Pe:()=>i,t2:()=>u});var n=a(15452),s=a(33054),r=a(42730);const l=(0,n.VP)(r.T_),i=(0,n.VP)(r.Al),o=(0,n.VP)(r.vJ),c=(0,n.VP)(r.bX),d=(0,n.VP)(r.Un,e=>({payload:{songId:e},meta:{isOptimistic:!0}})),u=e=>(t,a)=>{const n=(0,s.A)(a(),e);t(o({queueId:n}))},m=(0,n.vy)({isLoading:!0,result:[],entities:{}},e=>{e.addCase(d,(e,{payload:t})=>{const a=e.result.length?e.result[e.result.length-1]+1:1;e.result.push(a),e.entities[a]={...t,queueId:a,prevQueueId:a-1||null,isOptimistic:!0}}).addCase(c,(e,{payload:t})=>({isLoading:!1,result:t.result,entities:t.entities})).addCase(l,e=>{e.result=[],e.entities={}})})},42730:(e,t,a)=>{a.d(t,{$Q:()=>we,$W:()=>Le,$h:()=>Ne,A2:()=>w,Ac:()=>oe,Ah:()=>ke,Al:()=>v,BD:()=>de,Bw:()=>I,D2:()=>U,DN:()=>m,Df:()=>Re,EA:()=>A,F7:()=>T,Gg:()=>ee,H8:()=>ne,Hz:()=>Ae,Ig:()=>ae,J$:()=>ie,J_:()=>ye,Jc:()=>l,K9:()=>L,NT:()=>le,Nt:()=>S,Nz:()=>p,OA:()=>u,OL:()=>s,P8:()=>X,PQ:()=>z,Pg:()=>Ie,Qp:()=>D,S3:()=>G,SX:()=>Ee,Sz:()=>R,T_:()=>F,Tn:()=>_,U7:()=>he,UD:()=>i,Un:()=>g,VW:()=>Q,Xw:()=>ce,Y2:()=>ge,YM:()=>k,ZC:()=>B,_P:()=>N,ae:()=>Y,bA:()=>re,bX:()=>f,c8:()=>j,cP:()=>x,dh:()=>E,e_:()=>te,fD:()=>Te,fm:()=>o,gD:()=>ve,gU:()=>K,gn:()=>fe,gv:()=>me,gw:()=>O,hC:()=>c,iM:()=>Ce,if:()=>V,jI:()=>J,kW:()=>Pe,kY:()=>ue,lk:()=>$,ln:()=>Z,lq:()=>r,pg:()=>W,qd:()=>P,qx:()=>q,s4:()=>se,sr:()=>pe,tA:()=>h,tB:()=>n,tg:()=>b,tx:()=>Se,v3:()=>be,vD:()=>H,vJ:()=>C,w1:()=>y,xd:()=>d,zF:()=>M});const n="user/SOCKET_REQUEST_CONNECT",s="user/SOCKET_AUTH_ERROR",r="library/FILTER_KEYWORD",l="library/FILTER_KEYWORD_CLEAR",i="library/TOGGLE_FILTER_STARRED",o="library/TOGGLE_ARTIST_EXPANDED",c="library/TOGGLE_ARTIST_RESULT_EXPANDED",d="library/SCROLL_ARTISTS",u="library/SONG_STARRED",m="library/SONG_UNSTARRED",p="library/STAR_COUNTS_PUSH",h="library/PUSH",E="library/PUSH_SONG",g="server/QUEUE_ADD",v="server/QUEUE_MOVE",f="queue/PUSH",C="server/QUEUE_REMOVE",y="player/UPDATE",b="player/CMD_NEXT",w="player/CMD_OPTIONS",A="player/CMD_PAUSE",N="player/CMD_PLAY",S="player/CMD_REPLAY",R="player/CMD_VOLUME",I="server/PLAYER_REQ_NEXT",k="server/PLAYER_REQ_OPTIONS",P="server/PLAYER_REQ_PAUSE",L="server/PLAYER_REQ_PLAY",T="server/PLAYER_REQ_REPLAY",O="server/PLAYER_REQ_VOLUME",M="server/PLAYER_EMIT_STATUS",V="server/PLAYER_EMIT_LEAVE",z="status/PLAYER_STATUS",_="status/PLAYER_ERROR",x="status/PLAYER_LEAVE",H="status/PLAYER_LOAD",U="status/PLAYER_PLAY",D="status/PLAYER_VISUALIZER_ERROR",G="user/LOGIN",F="user/LOGOUT",q="user/ACCOUNT_RECEIVE",B="user/ACCOUNT_CREATE",Y="user/ACCOUNT_UPDATE",j="user/ACCOUNT_REQUEST",W="rooms/RECEIVE",Q="rooms/REQUEST",K="rooms/UPDATE",J="rooms/CREATE",Z="rooms/REMOVE",X="rooms/EDITOR_OPEN",$="rooms/EDITOR_CLOSE",ee="rooms/TOGGLE_SHOW_ALL",te="rooms/ROOM_PREFS_PUSH",ae="server/ROOM_PREFS_PUSH_REQUEST",ne="server/STAR_SONG",se="server/UNSTAR_SONG",re="user/STARS_PUSH",le="prefs/RECEIVE",ie="prefs/REQUEST",oe="server/PREFS_SET",ce="server/PREFS_PATH_SET_PRIORITY",de="prefs/PREFS_PATH_UPDATE",ue="prefs/PREFS_PUSH",me="prefs/REQ_SCANNER_START",pe="prefs/REQ_SCANNER_STOP",he="users/CREATE",Ee="users/EDITOR_OPEN",ge="users/EDITOR_CLOSE",ve="users/FILTER_ONLINE",fe="users/FILTER_ROOM_ID",Ce="users/REMOVE",ye="users/REQUEST",be="users/UPDATE",we="ui/HEADER_HEIGHT_CHANGE",Ae="ui/FOOTER_HEIGHT_CHANGE",Ne="ui/SHOW_ERROR_MESSAGE",Se="ui/CLEAR_ERROR_MESSAGE",Re="ui/WINDOW_RESIZE",Ie="songInfo/SONG_INFO_REQUEST",ke="songInfo/SET_PREFERRED",Pe="songInfo/SONG_INFO_CLOSE",Le="scannerWorker/STATUS",Te="app/REDUX_SLICE_INJECT_NOOP"},46685:(e,t,a)=>{a.d(t,{A:()=>n});const n=(0,a(25508).Mz)([e=>e.status.historyJSON],e=>JSON.parse(e))},47768:(e,t,a)=>{a.d(t,{AR:()=>r,Ay:()=>m,Ic:()=>d,RH:()=>l,lo:()=>c,wk:()=>i,yy:()=>u});var n=a(15452),s=a(42730);const r=(0,n.VP)(s.xd),l=(0,n.VP)(s.fm),i=(0,n.VP)(s.hC),o=(0,n.VP)(s.tA),c=(0,n.VP)(s.Jc),d=(0,n.VP)(s.UD),u=(0,n.VP)(s.lq,e=>({payload:e,meta:{throttle:{wait:350,leading:!1}}})),m=(0,n.vy)({isLoading:!0,version:0,filterStr:"",filterStarred:!1,scrollRow:0,expandedArtists:[],expandedArtistResults:[]},e=>{e.addCase(u,(e,{payload:t})=>{e.filterStr=t}).addCase(c,e=>{e.filterStr=""}).addCase(d,e=>{e.filterStarred=!e.filterStarred}).addCase(r,(e,{payload:t})=>{e.scrollRow=t}).addCase(l,(e,{payload:t})=>{const a=e.expandedArtists.indexOf(t);-1===a?e.expandedArtists.push(t):e.expandedArtists.splice(a,1)}).addCase(i,(e,{payload:t})=>{const a=e.expandedArtistResults.indexOf(t);-1===a?e.expandedArtistResults.push(t):e.expandedArtistResults.splice(a,1)}).addCase(o,(e,{payload:t})=>({...e,isLoading:!1,version:t.version}))})},49905:(e,t,a)=>{a.d(t,{A:()=>n});const n=(0,a(23508).Ay)({autoConnect:!1,path:new URL(document.baseURI).pathname+"socket.io"})},76140:(e,t,a)=>{a.d(t,{G:()=>r,j:()=>s});var n=a(71468);const s=n.wA,r=n.d4},77170:(e,t,a)=>{a.d(t,{A:()=>n});class n{constructor(e=""){this.prefix=e,this.options={credentials:"same-origin"}}put=(e,t={})=>this.request("PUT",e,t);post=(e,t={})=>this.request("POST",e,t);get=(e,t={})=>this.request("GET",e,t);delete=(e,t={})=>this.request("DELETE",e,t);request=async(e,t,a={})=>{const n={...this.options,...a,method:e};"object"!=typeof n.body||n.body instanceof FormData||(n.headers=new Headers({"Content-Type":"application/json"}),n.body=JSON.stringify(n.body));const s=await fetch(`${document.baseURI}api/${this.prefix}${t}`,n);if(s.ok){const e=s.headers.get("Content-Type");return e&&e.includes("application/json")?s.json():s}const r=await s.text();throw new Error(r)}}},77759:(e,t,a)=>{a.d(t,{Ay:()=>S,_m:()=>f,aw:()=>v,cH:()=>w,iD:()=>E,mb:()=>y,z0:()=>C});var n=a(15452),s=a(70960),r=a(69282),l=a(49905),i=a(87161),o=a(77170),c=a(32681),d=a(99996),u=a(42730);const m=new o.A(""),p=new URL(document.baseURI).pathname,h=(0,n.VP)(u.qx),E=(0,n.zD)(u.S3,async(e,t)=>{const a=await m.post("login",{body:e});c.A.get().purge(),t.dispatch(h(a)),t.dispatch((0,d.dJ)()),t.dispatch(w()),l.A.open();const n=new URLSearchParams(window.location.search).get("redirect");n&&i.A.navigate(p.replace(/\/$/,"")+n)}),g=(0,n.VP)(u.T_),v=(0,n.zD)(u.T_,async(e,t)=>{try{await m.get("logout")}catch{}t.dispatch(g()),c.A.get().purge(),l.A.close()}),f=(0,n.zD)(u.ZC,async(e,t)=>{const a=t.getState().prefs.isFirstRun,n=await m.post(a?"setup":"user",{body:e});c.A.get().purge(),t.dispatch(h(n)),t.dispatch((0,d.dJ)()),t.dispatch(w()),l.A.open();const s=new URLSearchParams(window.location.search).get("redirect");s&&i.A.navigate(p.replace(/\/$/,"")+s)}),C=(0,n.zD)(u.ae,async(e,t)=>{const{userId:a}=t.getState().user,n=await m.put(`user/${a}`,{body:e});t.dispatch(h(n)),alert("Account updated successfully.")}),y=(0,n.zD)(u.c8,async(e,t)=>{try{const e=await m.get("user");t.dispatch(h(e))}catch{}}),b=(0,n.VP)(u.tB),w=(0,n.zD)("user/SOCKET_CONNECT",async(e,{dispatch:t,getState:a})=>{const n={library:a().library.version,stars:a().starCounts.version};t(b(n)),l.A.io.opts.query=n}),A={userId:null,username:null,name:null,roomId:null,isAdmin:!1,isGuest:!1,dateCreated:0,dateUpdated:0},N=(0,n.vy)(A,e=>{e.addCase(h,(e,{payload:t})=>({...e,...t})).addCase(u.T_,()=>({...A})).addCase(u.OL,()=>({...A}))}),S=(0,s.rL)({key:"user",storage:r.A},N)},80470:(e,t,a)=>{a.d(t,{$R:()=>p,Ay:()=>f,Mv:()=>h,RM:()=>i,SV:()=>u,ab:()=>c,uE:()=>g,v4:()=>m,x1:()=>o,xX:()=>d});var n=a(15452),s=a(42730);const r=new(a(77170).A)("rooms"),l=(0,n.VP)(s.pg),i=(0,n.zD)(s.VW,async()=>await r.get("")),o=(0,n.zD)(s.VW,async(e,t)=>{const a=t.getState().user.roomId;return"number"!=typeof a?Promise.reject("Please sign into a room"):await r.get(`/${a}`)}),c=(0,n.zD)(s.jI,async(e,t)=>{const a=await r.post("",{body:e});t.dispatch(l(a)),t.dispatch(p())}),d=(0,n.zD)(s.gU,async({roomId:e,data:t},a)=>{const n=await r.put(`/${e}`,{body:t});a.dispatch(l(n)),a.dispatch(p())}),u=(0,n.zD)(s.ln,async(e,t)=>{const a=await r.delete(`/${e}`);t.dispatch(l(a)),t.dispatch(p())}),m=(0,n.VP)(s.P8),p=(0,n.VP)(s.lk),h=(0,n.VP)(s.Gg),E=(0,n.VP)(s.e_);function g(e,t){return a=>{a({type:s.Ig,payload:{roomId:e,prefs:t},meta:{throttle:{wait:200,leading:!0}}})}}const v={result:[],entities:{},filterStatus:"open",isEditorOpen:!1},f=(0,n.vy)(v,e=>{e.addCase(i.fulfilled,(e,{payload:t})=>({...e,...t})).addCase(l,(e,{payload:t})=>({...e,...t})).addCase(m,e=>{e.isEditorOpen=!0}).addCase(p,e=>{e.isEditorOpen=!1}).addCase(h,(e,{payload:t})=>{e.filterStatus=t}).addCase(E,(e,{payload:t})=>{const a=t.roomId;e.entities[a]&&(e.entities[a].prefs=t.prefs)}).addCase(s.T_,()=>({...v}))})},80519:(e,t,a)=>{a.d(t,{A:()=>l});var n=a(58168),s=a(96540);const r={ACCOUNT:{viewBox:"0 0 24 24",d:"M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z"},ACCOUNT_BOX:{viewBox:"0 0 24 24",d:"M6,17C6,15 10,13.9 12,13.9C14,13.9 18,15 18,17V18H6M15,9A3,3 0 0,1 12,12A3,3 0 0,1 9,9A3,3 0 0,1 12,6A3,3 0 0,1 15,9M3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3H5C3.89,3 3,3.9 3,5Z"},ACCOUNT_BOX_OUTLINE:{viewBox:"0 0 24 24",d:"M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M16.5,16.25C16.5,14.75 13.5,14 12,14C10.5,14 7.5,14.75 7.5,16.25V17H16.5M12,12.25A2.25,2.25 0 0,0 14.25,10A2.25,2.25 0 0,0 12,7.75A2.25,2.25 0 0,0 9.75,10A2.25,2.25 0 0,0 12,12.25Z"},ALERT_OUTLINE:{viewBox:"0 0 24 24",d:"M12,2L1,21H23M12,6L19.53,19H4.47M11,10V14H13V10M11,16V18H13V16"},CHEVRON_DOWN:{viewBox:"0 0 24 24",d:"M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z"},CHEVRON_LEFT:{viewBox:"0 0 24 24",d:"M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z"},CHEVRON_RIGHT:{viewBox:"0 0 24 24",d:"M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z"},CHEVRON_UP:{viewBox:"0 0 24 24",d:"M7.41,15.41L12,10.83L16.59,15.41L18,14L12,8L6,14L7.41,15.41Z"},CIRCLE:{viewBox:"0 0 24 24",d:"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z"},CLEAR:{viewBox:"0 0 24 24",d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"},CLOUD:{viewBox:"0 0 24 24",d:"M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z"},DELETE:{viewBox:"0 0 24 24",d:"M14.12 10.47 12 12.59l-2.13-2.12-1.41 1.41L10.59 14l-2.12 2.12 1.41 1.41L12 15.41l2.12 2.12 1.41-1.41L13.41 14l2.12-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4zM6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zM8 9h8v10H8z"},DICE:{viewBox:"0 0 24 24",d:"M19.78,3H11.22C10.55,3 10,3.55 10,4.22V8H16V14H19.78C20.45,14 21,13.45 21,12.78V4.22C21,3.55 20.45,3 19.78,3M12.44,6.67C11.76,6.67 11.21,6.12 11.21,5.44C11.21,4.76 11.76,4.21 12.44,4.21A1.23,1.23 0 0,1 13.67,5.44C13.67,6.12 13.12,6.67 12.44,6.67M18.56,12.78C17.88,12.79 17.33,12.24 17.32,11.56C17.31,10.88 17.86,10.33 18.54,10.32C19.22,10.31 19.77,10.86 19.78,11.56C19.77,12.23 19.23,12.77 18.56,12.78M18.56,6.67C17.88,6.68 17.33,6.13 17.32,5.45C17.31,4.77 17.86,4.22 18.54,4.21C19.22,4.2 19.77,4.75 19.78,5.44C19.78,6.12 19.24,6.66 18.56,6.67M4.22,10H12.78A1.22,1.22 0 0,1 14,11.22V19.78C14,20.45 13.45,21 12.78,21H4.22C3.55,21 3,20.45 3,19.78V11.22C3,10.55 3.55,10 4.22,10M8.5,14.28C7.83,14.28 7.28,14.83 7.28,15.5C7.28,16.17 7.83,16.72 8.5,16.72C9.17,16.72 9.72,16.17 9.72,15.5A1.22,1.22 0 0,0 8.5,14.28M5.44,11.22C4.77,11.22 4.22,11.77 4.22,12.44A1.22,1.22 0 0,0 5.44,13.66C6.11,13.66 6.66,13.11 6.66,12.44V12.44C6.66,11.77 6.11,11.22 5.44,11.22M11.55,17.33C10.88,17.33 10.33,17.88 10.33,18.55C10.33,19.22 10.88,19.77 11.55,19.77A1.22,1.22 0 0,0 12.77,18.55H12.77C12.77,17.88 12.23,17.34 11.56,17.33H11.55Z"},DRAG_INDICATOR:{viewBox:"0 0 24 24",d:"M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"},FLAG:{viewBox:"0 0 24 24",d:"M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"},FOLDER:{viewBox:"0 0 24 24",d:"M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"},FOLDER_MUSIC:{viewBox:"0 0 24 24",d:"M10 4L12 6H20C21.1 6 22 6.89 22 8V18C22 19.1 21.1 20 20 20H4C2.89 20 2 19.1 2 18L2 6C2 4.89 2.89 4 4 4H10M19 9H15.5V13.06L15 13C13.9 13 13 13.9 13 15C13 16.11 13.9 17 15 17C16.11 17 17 16.11 17 15V11H19V9Z"},FULLSCREEN:{viewBox:"0 0 24 24",d:"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"},GITHUB_REPO:{viewBox:"0 0 16 16",d:"M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"},GITHUB_SPONSOR:{viewBox:"0 0 16 16",d:"m8 14.25.345.666a.75.75 0 0 1-.69 0l-.008-.004-.018-.01a7.152 7.152 0 0 1-.31-.17 22.055 22.055 0 0 1-3.434-2.414C2.045 10.731 0 8.35 0 5.5 0 2.836 2.086 1 4.25 1 5.797 1 7.153 1.802 8 3.02 8.847 1.802 10.203 1 11.75 1 13.914 1 16 2.836 16 5.5c0 2.85-2.045 5.231-3.885 6.818a22.066 22.066 0 0 1-3.744 2.584l-.018.01-.006.003h-.002ZM4.25 2.5c-1.336 0-2.75 1.164-2.75 3 0 2.15 1.58 4.144 3.365 5.682A20.58 20.58 0 0 0 8 13.393a20.58 20.58 0 0 0 3.135-2.211C12.92 9.644 14.5 7.65 14.5 5.5c0-1.836-1.414-3-2.75-3-1.373 0-2.609.986-3.029 2.456a.749.749 0 0 1-1.442 0C6.859 3.486 5.623 2.5 4.25 2.5Z"},GITHUB_STAR:{viewBox:"0 0 16 16",d:"M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"},INFO_OUTLINE:{viewBox:"0 0 24 24",d:"M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z"},LABEL:{viewBox:"0 0 24 24",d:"M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"},MAGNIFIER:{viewBox:"0 0 24 24",d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"},MORE_HORIZ:{viewBox:"0 0 24 24",d:"M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"},MOVE_TOP:{viewBox:"0 0 24 24",d:"M5 4v2h14V4H5zm0 10h4v6h6v-6h4l-7-7-7 7z"},NAV_ACCOUNT:{viewBox:"0 0 24 24",d:"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2M12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8m3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5m-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.32-1.45 5.12-3.5h-1.67c-.69 1.19-1.97 2-3.45 2s-2.75-.81-3.45-2H6.88c.8 2.05 2.79 3.5 5.12 3.5"},NAV_ACCOUNT_ACTIVE:{viewBox:"0 0 24 24",d:"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"},NAV_LIBRARY:{viewBox:"0 0 24 24",d:"M20 2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 5h-3v5.5c0 1.38-1.12 2.5-2.5 2.5S10 13.88 10 12.5s1.12-2.5 2.5-2.5c.57 0 1.08.19 1.5.51V5h4v2zM4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6z"},NAV_SUBSCRIPTIONS:{viewBox:"0 0 24 24",d:"M20 8H4V6h16v2zm-2-6H6v2h12V2zm4 10v8c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2v-8c0-1.1.9-2 2-2h16c1.1 0 2 .9 2 2zm-6 4l-6-3.27v6.53L16 16z"},PAUSE:{viewBox:"0 0 24 24",d:"M6 19h4V5H6v14zm8-14v14h4V5h-4z"},PLAY:{viewBox:"0 0 24 24",d:"M8 5v14l11-7z"},PLAY_NEXT:{viewBox:"0 0 24 24",d:"M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"},PLUS:{viewBox:"0 0 24 24",d:"M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z"},PERSON:{viewBox:"0 0 24 24",d:"M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4m0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4"},PHOTO_ADD:{viewBox:"0 0 24 24",d:"M21 6h-3.17L16 4h-6v2h5.12l1.83 2H21v12H5v-9H3v9c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2M8 14c0 2.76 2.24 5 5 5s5-2.24 5-5-2.24-5-5-5-5 2.24-5 5m5-3c1.65 0 3 1.35 3 3s-1.35 3-3 3-3-1.35-3-3 1.35-3 3-3M5 6h3V4H5V1H3v3H0v2h3v3h2z"},QR_CODE:{viewBox:"0 0 24 24",d:"M3 11h8V3H3zm2-6h4v4H5zM3 21h8v-8H3zm2-6h4v4H5zm8-12v8h8V3zm6 6h-4V5h4zm0 10h2v2h-2zm-6-6h2v2h-2zm2 2h2v2h-2zm-2 2h2v2h-2zm2 2h2v2h-2zm2-2h2v2h-2zm0-4h2v2h-2zm2 2h2v2h-2z"},REFRESH:{viewBox:"0 0 24 24",d:"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"},REPLAY:{viewBox:"0 0 24 24",d:"M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8"},STAR_FULL:{viewBox:"0 0 32 32",d:"M32 12.408l-11.056-1.607-4.944-10.018-4.944 10.018-11.056 1.607 8 7.798-1.889 11.011 9.889-5.199 9.889 5.199-1.889-11.011 8-7.798z"},TELEVISION_PLAY:{viewBox:"0 0 24 24",d:"M21,3H3C1.89,3 1,3.89 1,5V17A2,2 0 0,0 3,19H8V21H16V19H21A2,2 0 0,0 23,17V5C23,3.89 22.1,3 21,3M21,17H3V5H21M16,11L9,15V7"},TUNE:{viewBox:"0 0 24 24",d:"M3,17V19H9V17H3M3,5V7H13V5H3M13,21V19H21V17H13V15H11V21H13M7,9V11H3V13H7V15H9V9H7M21,13V11H11V13H21M15,9H17V7H21V5H17V3H15V9Z"},VISIBILITY:{viewBox:"0 0 24 24",d:"M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"},VISIBILITY_OFF:{viewBox:"0 0 24 24",d:"M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"},VOLUME_DOWN:{viewBox:"0 0 24 24",d:"M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z"},VOLUME_MUTE:{viewBox:"0 0 24 24",d:"M7 9v6h4l5 5V4l-5 5H7z"},VOLUME_OFF:{viewBox:"0 0 24 24",d:"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"},VOLUME_UP:{viewBox:"0 0 24 24",d:"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"}},l=e=>{const{size:t,icon:a,...l}=e;return s.createElement("svg",(0,n.A)({height:t?`${t}px`:void 0,viewBox:r[a].viewBox,"aria-hidden":!0},l),s.createElement("path",{fill:"currentColor",d:r[a].d}))}},85134:(e,t,a)=>{a.d(t,{Ay:()=>E,DP:()=>o,Dx:()=>u,L5:()=>d,NJ:()=>c,T6:()=>l,f1:()=>i});var n=a(15452),s=a(42730);let r;const l=(0,n.VP)(s.tx),i=(0,n.VP)(s.$h),o=(0,n.zD)("ui/SET_HEADER_HEIGHT",async(e,{dispatch:t,getState:a})=>{a().ui.headerHeight!==e&&t({type:s.$Q,payload:e??0})}),c=(0,n.zD)("ui/SET_HEADER_HEIGHT",async(e,{dispatch:t,getState:a})=>{a().ui.footerHeight!==e&&t({type:s.Hz,payload:e??0})}),d=(0,n.VP)(s.Df,e=>({payload:e,meta:{throttle:{wait:200,leading:!1}}})),u=e=>{e?(clearTimeout(r),r=null,document.body.classList.add("scroll-lock")):r||(r=setTimeout(()=>{r=null,document.body.classList.remove("scroll-lock")},200))},m=(0,n.VP)(s.Hz),p=(0,n.VP)(s.$Q),h={isErrored:!1,errorMessage:null,footerHeight:0,headerHeight:0,innerWidth:window.innerWidth,innerHeight:window.innerHeight,contentWidth:Math.min(window.innerWidth,768)},E=(0,n.vy)(h,e=>{e.addCase(p,(e,{payload:t})=>{e.headerHeight=t}).addCase(m,(e,{payload:t})=>{e.footerHeight=t}).addCase(i,(e,{payload:t})=>{e.isErrored=!0,e.errorMessage=t}).addCase(l,e=>{e.isErrored=!1}).addCase(d,(e,{payload:t})=>{e.innerWidth=t.innerWidth,e.innerHeight=t.innerHeight,e.contentWidth=Math.min(t.innerWidth,768)}).addMatcher(e=>!!e.error,(e,{error:t})=>{e.isErrored=!0,e.errorMessage=t.message??t})})},85555:(e,t,a)=>{a.d(t,{A:()=>h});var n=a(15452),s=a(37655),r=a(49905),l=a(9934);let i=0;var o=a(44063),c=a(70960),d=a(85134);window.addEventListener("resize",()=>p.dispatch((0,d.L5)({innerWidth:window.innerWidth,innerHeight:window.innerHeight})));const u=(0,o.Ay)(1e3,{leading:!0,trailing:!0}),m=function(e,t){return a=>(e.on("action",e=>a.dispatch(e)),a=>n=>{if(!n.type||!n.type.startsWith(t))return a(n);const s="meta"in n&&(n.meta?.isOptimistic??!1);if(e.emit("action",n,e=>{"object"==typeof e&&"string"==typeof e.type&&(s&&(e.meta={..."meta"in e&&"object"==typeof e.meta?e.meta:{},optimistic:e.error?{type:l.tH,id:i}:{type:l.cJ,id:i}}),a(e))}),!s)return a(n);i++,a({...n,meta:{...n.meta,optimistic:{type:l.Q,id:i}}})})}(r.A,"server/"),p=(0,n.U1)({reducer:s.A,middleware:e=>e({serializableCheck:{ignoredActions:[c.ZM,c.r2,c.Hz,c.DY,c.Cq,c.eY]}}).concat(u,m)});const h=p},87161:(e,t,a)=>{a.d(t,{A:()=>Ks});var n=a(96540),s=a(13937),r=a(71468),l=a(68131),i=a(85555),o=a(32681),c=a(76140),d=a(40936),u=a(58168),m=a(34164),p=a(80519);const h={container:"rYzGz3Rx2eJjMVVhj_lA",default:"BRCYi6lJspftkCxcFdpw",primary:"u4HHBIWYgUhQaG3hu6kB",danger:"X_mi34pYwHmBoHHJS15M"},E=({animateClassName:e,cancelAnimation:t,className:a,children:s,icon:r,onClick:l,size:i,variant:o,as:c,...d})=>{const E=(0,n.useRef)(null),[g,v]=(0,n.useState)(!1),f=c||"button";(0,n.useEffect)(()=>{t&&v(!1)},[t]);const C=(0,n.useCallback)(()=>{v(!1)},[]),y=(0,n.useCallback)(t=>{e&&v(!0),l&&l(t)},[e,l]),b="button"===f?d.type||"button":void 0,w={onClick:y,...e&&g?{className:(0,m.A)(h.container,h[o],a,e),onAnimationEnd:C}:{className:(0,m.A)(h.container,h[o],a)},...d};return"button"===f?n.createElement("button",(0,u.A)({},w,{ref:E,type:b}),r&&n.createElement(p.A,{icon:r,size:i}),s):n.createElement("span",(0,u.A)({},w,{ref:E}),r&&n.createElement(p.A,{icon:r,size:i}),s)},g=n.memo(E);var v=a(25508),f=a(99996),C=a(32509),y=a(46685);const b=(0,v.Mz)([e=>(0,C.A)(e),e=>e.status.queueId,y.A,e=>e.status.position,e=>e.songs],(e,t,a,n,s)=>{const r=e.result.indexOf(t),l={};let i=0,o=0;return e.result.forEach((t,c)=>{const d=e.entities[t].songId;s.entities[d]&&(c===r?-1===a.lastIndexOf(t)&&(o=Math.round(s.entities[d].duration-n)):c>r&&(i+=o,o=s.entities[d].duration),l[t]=i)}),l});var w=a(47768);const A="UIK2HEzG93kJrZg1zrOI",N="PM6oSstQkOr7xx5WXBco",S="jvBgtBq5nhwhgFxDdohV",R="yRcmNgWXHlqworm4xJFy",I="q3cBXbOJzq3CC3galiDw",k="zKCotnvYis3lj_IxNd42",P=()=>{const e=(0,c.j)(),{filterStr:t,filterStarred:a}=(0,c.G)(e=>e.library),s=(0,n.useRef)(null),[r,l]=(0,n.useState)(t),i=()=>{l(""),e((0,w.lo)())};return n.createElement("div",{className:A},n.createElement(g,{className:(0,m.A)(R,t&&N),icon:"MAGNIFIER",onClick:()=>{r.trim()?i():s.current?.focus()}}),n.createElement("input",{type:"search",className:S,placeholder:"search",value:r,onChange:t=>{l(t.target.value),e((0,w.yy)(t.target.value))},ref:s}),t&&n.createElement(g,{icon:"CLEAR",onClick:i,className:(0,m.A)(I,N)}),n.createElement(g,{className:(0,m.A)(k,a&&N),icon:"STAR_FULL",onClick:()=>e((0,w.Ic)())}))};var L=a(45041),T=a(88146),O=a(85134),M=a(11234);const V="DY6_kAr5khzv1QwqLveK",z="X0DCwMUX1tj5tsoGjDFq",_=({"aria-label":e,"aria-labelledby":t,className:a,handle:s,min:r,max:l,onChange:i,step:o,value:c,...d})=>{const[h,E]=(0,n.useState)(null),g=(0,n.useRef)(null),v=(0,n.useCallback)(e=>{g.current&&(clearTimeout(g.current),g.current=null),(0,O.Dx)(!0),E(e),i(e)},[i]),f=(0,n.useCallback)(e=>{(0,O.Dx)(!1),e===c?E(null):g.current=setTimeout(()=>{E(null)},2e3)},[c]),C=(0,n.useCallback)(a=>n.cloneElement(a,{"aria-label":e,"aria-labelledby":t,className:z,onTouchEnd:e=>{e.currentTarget.blur()}},n.createElement(p.A,{icon:"CIRCLE"})),[e,t]);return n.createElement(M.A,(0,u.A)({className:(0,m.A)(V,a),handleRender:s??C,max:l,min:r,onChangeComplete:f,onChange:v,step:o,value:h??c},d))},x="dMo9SQYONtw9WYO5lxiN",H="pMYNwtxIUiwKZSuUB8NQ",U=(e,{value:t})=>{const a=0===t?"VOLUME_OFF":t<.4?"VOLUME_MUTE":t<.7?"VOLUME_DOWN":"VOLUME_UP";return n.cloneElement(e,{"aria-label":"Volume",className:H},n.createElement(p.A,{icon:a}))},D=({volume:e,onVolumeChange:t})=>n.createElement(_,{className:x,handle:U,min:0,max:1,onChange:t,step:.01,value:e}),G="sfr6H9YQSnxNFewvtYb2",F="QYsiKZ5NRjaOsK5iaXfX",q=()=>n.createElement("div",{className:G},n.createElement("p",{className:F},"No player in room (",n.createElement(s.N_,{to:"/player",target:"_blank",replace:!0},"Launch Player"),")")),B="HHYLkEZBcUJPga1se3oQ",Y="pfOAkdcjAgxEaiTckdFA",j="aIGh3kF56tYlTfTCzGuC",W="M1nSLELWzWtg0nMNVAPp",Q="G89xv3BCUffZqoya0LQl",K="nsGMxmc6ZA0V4Fwl17Bf",J=({buttons:e,className:t,children:a,visible:s=!0,onClose:r,scrollable:l,title:i})=>{const o=(0,n.useRef)(null),c=(0,n.useRef)(!1);(0,n.useEffect)(()=>{s&&o.current&&o.current.showModal()},[s]);const d=(0,n.useCallback)(e=>{c.current=e.target===o.current},[]),u=(0,n.useCallback)(e=>{c.current&&e.target===o.current&&r(),c.current=!1},[r]),p=(0,n.useCallback)(e=>{e.preventDefault(),r()},[r]);return s?n.createElement("dialog",{ref:o,className:(0,m.A)(B,t),onMouseDown:d,onMouseUp:u,onCancel:p},n.createElement("div",{className:Y},n.createElement("h1",null,i),n.createElement(g,{icon:"CLEAR",className:j,onClick:r,"aria-label":"Close"})),n.createElement("div",{className:(0,m.A)(W,l&&Q)},a),e&&n.createElement("div",{className:K},e)):null},Z="Fqzbj50Thya7wadiB1RR",X=(0,n.forwardRef)(({label:e,className:t,...a},s)=>n.createElement("label",{className:(0,m.A)(Z,t)},n.createElement("input",(0,u.A)({type:"checkbox",ref:s},a)),e));X.displayName="InputCheckbox";const $=X,ee={modal:"CHH6ukgfI31pNfRWfp2z",container:"xKkwU06MKq2DbjSima4p",section:"eBgZD0SKZoZxdKfDH4T1",visualizer:"PJhDzihe1KxTY9CE2xvq",presetContainer:"hMPTUMcNQY0YeMY1WnWo",presetButtons:"WPJeW28XmDzljHtBz0mq",presetName:"Sx5QwRYN26kPCBm4i6rP",unsupported:"zIEucMK4dBypf03pERBF",slider:"MhuyzAaoykU7XrttP0lt"},te=({cdgAlpha:e,cdgSize:t,isVideoKeyingEnabled:a,isVisualizerEnabled:s,isWebGLSupported:r,mediaType:l="",mp4Alpha:i,sensitivity:o,visualizerPresetName:c,onRequestOptions:d,onClose:u})=>n.createElement(J,{className:ee.modal,onClose:u,title:"Display",buttons:n.createElement(g,{variant:"primary",onClick:u},"Done")},n.createElement("div",{className:ee.container},n.createElement("div",{className:(0,m.A)(ee.section,ee.visualizer)},n.createElement("fieldset",null,n.createElement("legend",null,n.createElement($,{label:"Visualizer",checked:s,disabled:!r,onChange:()=>d({visualizer:{isEnabled:!s}})})),r&&("cdg"===l||a)&&n.createElement(n.Fragment,null,n.createElement("div",{className:ee.presetContainer},n.createElement("div",{className:ee.presetButtons},n.createElement(g,{onClick:()=>d({visualizer:{prevPreset:!0}}),"aria-label":"Previous preset","aria-controls":"visualizer-preset-name"},n.createElement(p.A,{icon:"CHEVRON_LEFT"})),n.createElement(g,{onClick:()=>d({visualizer:{randomPreset:!0}}),"aria-label":"Random preset","aria-controls":"visualizer-preset-name"},n.createElement(p.A,{icon:"DICE"})),n.createElement(g,{onClick:()=>d({visualizer:{nextPreset:!0}}),"aria-label":"Next preset","aria-controls":"visualizer-preset-name"},n.createElement(p.A,{icon:"CHEVRON_RIGHT"}))),n.createElement("p",{id:"visualizer-preset-name",className:ee.presetName,"aria-live":"polite"},c)),n.createElement("div",{className:ee.field},n.createElement("label",{id:"label-visualizer-sensitivity"},"Sensitivity"),n.createElement(_,{min:0,max:2,step:.01,value:o,onChange:e=>d({visualizer:{sensitivity:e}}),className:ee.slider,"aria-labelledby":"label-visualizer-sensitivity"}))),r&&"cdg"!==l&&!a&&n.createElement("p",{className:ee.unsupported},"Not available for this media type"),!r&&n.createElement("p",{className:ee.unsupported},"WebGL not supported"))),n.createElement("div",{className:(0,m.A)(ee.section,ee.lyrics)},n.createElement("fieldset",null,n.createElement("legend",null,n.createElement("label",null,"Lyrics")),"cdg"===l&&n.createElement("div",{className:ee.field},n.createElement("label",{id:"label-lyrics-size"},"Size"),n.createElement(_,{min:.6,max:1,step:.01,value:t,onChange:e=>{d({cdgSize:e})},className:ee.slider,"aria-labelledby":"label-lyrics-size"})),("cdg"===l||a)&&n.createElement("div",{className:ee.field},n.createElement("label",{id:"label-lyrics-background"},"Background"),n.createElement(_,{min:0,max:1,step:.01,value:"cdg"===l?e:i,onChange:e=>{""!==l&&d({[l+"Alpha"]:e})},className:ee.slider,"aria-labelledby":"label-lyrics-background"})),"cdg"!==l&&!a&&n.createElement("p",{className:ee.unsupported},"No options available"))))),ae="s6dMfvg4cHkpBCZwMxlM",ne="utieeUffOQOs5Tb422mr",se="pRlD2sOdoJdRfrjBCylf",re="ffq0SD5gzioIYEcgKgLY",le="pjBKslXw1U349A1rnhe0",ie="tQEHmnxGjJM781oxemUN",oe="fIuT4teYAIcl4oLOLEzJ",ce="HZ7zG9VjL9eCkdQDZGIM",de=()=>{if(L.A.isEnabled){const e=document.getElementById("player-fs-container");L.A.request(e)}},ue=()=>{const[e,t]=(0,n.useState)(!1),a=(0,s.zy)().pathname.replace(/\/$/,"").endsWith("/player"),r=(0,c.G)(e=>e.user.isAdmin),l=(0,c.G)(e=>null!==e.user.roomId),i=(0,c.G)(e=>e.status),o=(0,c.j)(),d=(0,n.useCallback)(e=>o((0,T.ag)(e)),[o]),u=(0,n.useCallback)(()=>o((0,T.wr)()),[o]),p=(0,n.useCallback)(()=>o((0,T.cd)()),[o]),h=(0,n.useCallback)(()=>o((0,T.Lx)()),[o]),E=(0,n.useCallback)(e=>o((0,T.MP)(e)),[o]),v=(0,n.useCallback)(()=>{t(!e)},[e]);return i.isPlayerPresent?n.createElement("div",{className:ae},n.createElement(g,{animateClassName:se,className:(0,m.A)(ne,i.isPlaying?le:re),icon:i.isPlaying?"PAUSE":"PLAY",onClick:i.isPlaying?u:p,"aria-label":i.isPlaying?"Pause":"Play"}),n.createElement(g,{animateClassName:se,className:(0,m.A)(ne,ie),icon:"PLAY_NEXT",onClick:h,"aria-label":"Play Next"}),n.createElement(D,{volume:i.volume,onVolumeChange:E}),n.createElement(g,{className:(0,m.A)(ne,oe),icon:"TUNE",onClick:v,size:48,"aria-label":"Display Options"}),a&&L.A.isEnabled&&n.createElement(g,{className:(0,m.A)(ne,ce),icon:"FULLSCREEN",onClick:de,"aria-label":"Enter Fullscreen"}),e&&n.createElement(te,{cdgAlpha:i.cdgAlpha,cdgSize:i.cdgSize,isVideoKeyingEnabled:i.isVideoKeyingEnabled,isVisualizerEnabled:i.visualizer.isEnabled,isWebGLSupported:i.isWebGLSupported,mediaType:i.mediaType,mp4Alpha:i.mp4Alpha,onClose:v,onRequestOptions:d,sensitivity:i.visualizer.sensitivity,visualizerPresetName:i.visualizer.presetName})):r&&l&&L.A.isEnabled?n.createElement(q,null):null},me="R0tWhGzOMnxRvplqamqt",pe="WxqoYmzzeIRmqDepbVLR",he="iL_22Dl4fbuLsQo42o2o L3KVVs498s_TTzMFHKn5",Ee="rMNneKuTapuKwyse_AMl L3KVVs498s_TTzMFHKn5";class ge extends n.Component{state={isCanceling:!1,isVisible:!1};handleCancelClick=()=>{this.props.isActive&&!this.state.isCanceling?(this.setState({isCanceling:!0}),this.props.onCancel()):this.setState({isVisible:!1})};componentDidUpdate(e){this.props.isActive&&!e.isActive?this.setState({isVisible:!0,isCanceling:!1}):this.state.isCanceling&&this.props.text!==e.text&&this.setState({isCanceling:!1})}render(){const{state:e,props:t}=this;return e.isVisible?n.createElement("div",{className:me,style:{backgroundSize:t.pct+"% 100%"}},n.createElement("p",{className:pe},e.isCanceling?"Stopping...":t.text),n.createElement(g,{className:t.isActive?he:Ee,icon:"CLEAR",onClick:this.handleCancelClick,size:40})):null}}function ve(e){return function(e){return e.toISOString().substring(0,10)}(e)+" "+function(e){let t=e.getHours(),a=e.getMinutes();const n=t>11?"p":"a";return t>12?t-=12:0===t&&(t="12"),a<10&&(a="0"+a),t+":"+a+n}(e)}function fe(e){const t=e%60;return`${Math.floor(e/60)}:${t<10?"0"+t:t}`}function Ce(e,t=!1){if(e>=60&&t)return Math.round(e/60)+"m";const a=Math.floor(e/60),n=e%60;return a?`${a}m ${n}s`:`${n}s`}const ye="PhYxOVpDCwPMJWw0BE6k qdbIg3xgUn4KEomWXd7E",be="C9WuYntlaEVvxRaewY7r qdbIg3xgUn4KEomWXd7E",we="pXcSEQ5RRGogLr2WCFum qdbIg3xgUn4KEomWXd7E",Ae="ZYRIFRvELzaH67PRlPlp",Ne=e=>e.isUpNow?n.createElement("div",{className:be},n.createElement("p",{className:Ae},"You’re up"," ",n.createElement("strong",null,"now"))):e.isUpNext?n.createElement("div",{className:ye},n.createElement("p",{className:Ae},"You’re up"," ",n.createElement("strong",null,"next"),e.wait?` in ${Ce(e.wait,!0)}`:"")):e.wait?n.createElement("div",{className:we},n.createElement("p",{className:Ae},"You’re up in"," ",Ce(e.wait,!0))):null,Se="vreYukSnqUrGi25wejn4",Re=e=>e.status.queueId,Ie=e=>e.user.userId,ke=(0,v.Mz)([C.A,Re,Ie,b],(e,t,a,n)=>{for(let s=e.result.indexOf(t)+1;s<e.result.length;s++)if(e.entities[e.result[s]].userId===a)return n[e.result[s]]}),Pe=(0,v.Mz)([C.A,Re,e=>e.status.isAtQueueEnd,Ie],(e,t,a,n)=>{const{result:s,entities:r}=e,l=s.indexOf(t),i=r[t];return{isUpNext:!!s[l+1]&&r[s[l+1]].userId===n,isUpNow:!!i&&(!a&&i.userId===n)}}),Le=n.forwardRef((e,t)=>{const a=(0,c.G)(e=>e.user.isAdmin),r=(0,c.G)(e=>e.status.isPlayerPresent),l=(0,c.G)(e=>e.prefs.isScanning),i=(0,c.G)(e=>e.prefs.scannerText),o=(0,c.G)(e=>e.prefs.scannerPct),{isUpNext:d,isUpNow:u}=(0,c.G)(Pe),p=(0,c.G)(ke),h=(0,s.zy)().pathname.replace(/\/$/,"").endsWith("/player"),E=(0,c.j)(),g=(0,n.useCallback)(()=>E((0,f.fm)()),[E]);return n.createElement("div",{className:(0,m.A)(Se,"bg-blur"),ref:t},!h&&r&&n.createElement(Ne,{isUpNext:d,isUpNow:u,wait:p}),(u||a)&&n.createElement(ue,null),a&&!h&&n.createElement(ge,{isActive:l,onCancel:g,pct:o,text:i}),n.createElement(s.BV,null,n.createElement(s.qh,{path:"/library",element:n.createElement(P,null)})))});Le.displayName="Header";const Te=Le,Oe="sjMaG58osNAeqXFe4zpO",Me="KFIi1hoqiTVulFtwCOgg",Ve="bx9kUlhkDMmCKpxez9Kn",ze=n.forwardRef((e,t)=>n.createElement("div",{className:(0,m.A)(Oe,"bg-blur"),ref:t},n.createElement(s.k2,{to:"/library",replace:!0,className:({isActive:e})=>(0,m.A)(e&&Me)},({isActive:e})=>n.createElement(g,{icon:"NAV_LIBRARY",as:"span",animateClassName:Ve,cancelAnimation:!e})),n.createElement(s.k2,{to:"/queue",replace:!0,className:({isActive:e})=>(0,m.A)(e&&Me)},({isActive:e})=>n.createElement(g,{icon:"NAV_SUBSCRIPTIONS",as:"span",animateClassName:Ve,cancelAnimation:!e})),n.createElement(s.k2,{to:"/account",replace:!0,className:({isActive:e})=>(0,m.A)(e&&Me)},({isActive:e})=>n.createElement(g,{icon:e?"NAV_ACCOUNT_ACTIVE":"NAV_ACCOUNT",as:"span",animateClassName:Ve,cancelAnimation:!e}))));ze.displayName="Navigation";const _e=ze;var xe=a(89853);const He="AOWDkEJZ7Uh6TMmJSmDN",Ue="Gi_1FjbpZU1FcRC85lBE",De="k8N_J395xr2bblBgwvim",Ge="TSJBvSrnl7BotohIdqrj",Fe=()=>{const{isLoading:e,isVisible:t,songId:a,media:s}=(0,c.G)(e=>e.songInfo),r=(0,c.j)(),l=()=>r((0,xe.ks)()),i=s.result.map(e=>{const t=s.entities[e],l=!!t.isPreferred;return n.createElement("div",{key:t.mediaId,className:De},t.path+(0===t.path.indexOf("/")?"/":"\\")+t.relPath,n.createElement("br",null),n.createElement("span",{className:Ge},"Duration: "),fe(t.duration),n.createElement("br",null),n.createElement("span",{className:Ge},"Media ID: "),e,n.createElement("br",null),n.createElement("span",{className:Ge},"Preferred: "),l&&n.createElement("span",null,n.createElement("strong",null,"Yes")," ",n.createElement("a",{onClick:()=>(e=>r((0,xe.Zi)({songId:a,mediaId:e,isPreferred:!1})))(e)},"(Unset)")),!l&&n.createElement("span",null,"No ",n.createElement("a",{onClick:()=>(e=>r((0,xe.Zi)({songId:a,mediaId:e,isPreferred:!0})))(e)},"(Set)")))});return n.createElement(J,{visible:t,onClose:l,title:"Song Info"},n.createElement("div",{className:He},n.createElement("p",null,n.createElement("span",{className:Ge},"Song ID: "),a,n.createElement("br",null),n.createElement("span",{className:Ge},"Media Files: "),e?"?":s.result.length),n.createElement("div",{className:Ue},e?n.createElement("p",null,"Loading..."):i),n.createElement("div",null,n.createElement(g,{variant:"primary",onClick:l},"Done"))))};var qe=a(77759);const Be="MhLrBfYw2bVvon36GHQg",Ye="MRwxEsiCu74aMC4fJ2yn",je="XrgY7jUteM7yAiFgHV3G",We="opBGPXUVYOwhN4fsI5_5",Qe=e=>n.createElement("div",{className:(0,m.A)(Be,e.className),role:"img","aria-label":"Karaoke Eternal"},n.createElement("span",{className:Ye,"aria-hidden":"true"},"Karaoke",n.createElement("span",{className:je},"Eterna",n.createElement("span",{className:We},"l"))));var Ke=a(58202),Je=a.n(Ke);const Ze="kMVEh9LeEn4g4mp_4CQN",Xe="YA6i4Cl4kAWWDVU3e1xA",$e="s4sM5iEgPiWiNqVuWXXy",et="urwdlhf5zLiQCnkW1lW9",tt=({user:e,onSelect:t})=>{const[a,s]=(0,n.useState)(!0),[r,l]=(0,n.useState)(e&&null!==e.userId?`${document.baseURI}api/user/${e.userId}/image?v=${e.dateUpdated}`:null);(0,n.useEffect)(()=>()=>{r&&URL.revokeObjectURL(r)},[r]);return n.createElement("div",{className:Ze},!r&&n.createElement(p.A,{icon:"PHOTO_ADD",size:48,className:et}),r&&n.createElement("img",{src:r,width:96,height:72,onLoad:()=>{s(!1)},onError:()=>{l(null),s(!1)},alt:"User Profile"}),r&&!a&&n.createElement(g,{className:$e,icon:"CLEAR",onClick:()=>{l(null),t(null)},size:32}),n.createElement("input",{type:"file",accept:"image/*",onChange:e=>{const a=e.target.files?.[0];a&&Je()(a,e=>{if(e instanceof Event)return void alert("The image could not be loaded.");Je().scale(e,{canvas:!0,maxWidth:400,maxHeight:300,crop:!0,downsamplingRatio:.5}).toBlob(e=>{e&&(l(URL.createObjectURL(e)),t(e))},"image/jpeg")},{canvas:!0,aspectRatio:4/3,orientation:!0})},className:Xe,ref:e=>{e&&e.addEventListener("cancel",e=>{e.stopPropagation()})}}))},at="UJP7G5dKPXhMYPVm9lGC",nt="MRv8af4NPh12SLYbjwuA",st=({autoFocus:e,children:t,onDirtyChange:a,onSubmit:s,showRole:r,showUsername:l=!0,showPassword:i=!0,user:o})=>{const c=(0,n.useRef)(null),d=(0,n.useRef)(null),u=(0,n.useRef)(null),m=(0,n.useRef)(null),p=(0,n.useRef)(null),[h,E]=(0,n.useState)({isDirty:!1,isChangingPassword:!o||null===o.userId,userImage:void 0}),g=o&&null!==o.userId;(0,n.useEffect)(()=>{o&&v.current?.dateUpdated!==o.dateUpdated&&E(e=>({...e,isDirty:!1}))},[o]);const v=(0,n.useRef)(void 0),f=(0,n.useRef)(h.isDirty);(0,n.useEffect)(()=>{v.current=o,a&&f.current!==h.isDirty&&a(h.isDirty),f.current=h.isDirty},[o,h.isDirty,a]);const C=()=>{o&&null!==o.userId&&E(e=>({...e,isDirty:!!c.current?.value||!!d.current?.value||m.current?.value!==o.name||p.current&&p.current.value!==(o.isAdmin?"1":"0"),isChangingPassword:!!d.current?.value}))};return n.createElement("form",{className:at,key:o?.dateUpdated,noValidate:!0,onSubmit:e=>{e.preventDefault();const t=new FormData;m.current?.value.trim()&&t.append("name",m.current.value.trim()),c.current?.value.trim()&&t.append("username",c.current.value.trim()),h.isChangingPassword&&(t.append("newPassword",d.current?.value||""),t.append("newPasswordConfirm",u.current?.value||"")),void 0!==h.userImage&&t.append("image",h.userImage),p.current&&t.append("role",p.current.value),s(t)}},l&&n.createElement("input",{type:"email",autoComplete:"off",autoFocus:e,onChange:C,placeholder:g?"change username (optional)":"username or email",ref:t=>{t&&(c.current=t),e&&t?.setAttribute("autofocus","true")}}),i&&n.createElement("input",{type:"password",autoComplete:"new-password",onChange:C,placeholder:g?"change password (optional)":"password",ref:d}),h.isChangingPassword&&n.createElement("input",{type:"password",autoComplete:"new-password",placeholder:g?"new password confirm":"confirm password",ref:u}),n.createElement("div",{className:nt},n.createElement(tt,{user:o,onSelect:e=>{E(t=>({...t,userImage:e,isDirty:!0}))}}),n.createElement("input",{type:"text",defaultValue:g?o.name:"",onChange:C,placeholder:"display name",ref:m})),r&&n.createElement("select",{defaultValue:g&&o.role,onChange:C,ref:p},n.createElement("option",{key:"choose",value:"",disabled:!0},"select role..."),n.createElement("option",{key:"std",value:"standard"},"Standard"),n.createElement("option",{key:"admin",value:"admin"},"Administrator")),t)},rt="IwyJhXcw4stbQluvU1RS",lt="LBGExauA2_9eEf6X1NAw",it=()=>{const e=(0,c.G)(e=>e.ui),t=(0,c.j)(),a=(0,n.useCallback)(e=>{t((0,qe._m)(e))},[t]);return n.createElement("div",{className:rt,style:{maxWidth:Math.max(340,.66*e.contentWidth)}},n.createElement(Qe,{className:lt}),n.createElement("h1",null,"Welcome"),n.createElement("p",null,"Create your"," ",n.createElement("b",null,"admin")," ","account to get started. All data is locally stored and never shared."),n.createElement(st,{onSubmit:a,autoFocus:!0},n.createElement(g,{variant:"primary",type:"submit"},"Create Account")))};var ot=a(37655),ct=a(15452),dt=a(77170),ut=a(42730);const mt=new dt.A(""),pt=(0,ct.zD)(ut.J_,async()=>await mt.get("users")),ht=(0,ct.zD)(ut.U7,async(e,t)=>{await mt.post("user",{body:e}),t.dispatch(pt())}),Et=(0,ct.zD)(ut.v3,async({userId:e,data:t},a)=>{await mt.put(`user/${e}`,{body:t}),a.dispatch(pt())}),gt=(0,ct.zD)(ut.iM,async(e,t)=>{await mt.delete(`user/${e}`),t.dispatch(pt())}),vt=(0,ct.VP)(ut.SX),ft=(0,ct.VP)(ut.Y2),Ct=(0,ct.VP)(ut.gD),yt=(0,ct.VP)(ut.gn),bt=(0,ct.vy)({result:[],entities:{},filterOnline:!0,filterRoomId:null,isEditorOpen:!1},e=>{e.addCase(pt.fulfilled,(e,{payload:t})=>({...e,...t})).addCase(ht.fulfilled,e=>{e.isEditorOpen=!1}).addCase(Et.fulfilled,e=>{e.isEditorOpen=!1}).addCase(gt.fulfilled,e=>{e.isEditorOpen=!1}).addCase(vt,e=>{e.isEditorOpen=!0}).addCase(ft,e=>{e.isEditorOpen=!1}).addCase(Ct,(e,{payload:t})=>({...e,filterOnline:t,filterRoomId:null})).addCase(yt,(e,{payload:t})=>({...e,filterOnline:!1,filterRoomId:t}))}),wt=(0,ct.VP)(ut.fD),At="WUYY8MZhwwhVekAlX5_d",Nt="eP0BAX5ayTg1WGhcfd7y",St="OgJ5EnIwV5jp1GGDcabg",Rt=({children:e,className:t,contentClassName:a,title:s,titleComponent:r})=>n.createElement("div",{className:(0,m.A)(At,t)},n.createElement("div",{className:Nt},n.createElement("h1",null,s),r),n.createElement("div",{className:(0,m.A)(St,a)},e));const It="XIvZjD6Co9DyofyCj0Da",kt="oPMyaF6eFojk2b8ZQKwH",Pt="mFno0FFze3kHGDdbZDBB",Lt="NjmtwxMJxR179Hk2Pomb",Tt="okfIUIOCzr40SucFJR9B",Ot="J1Y6pDd6XtAUjqhW2qIF",Mt="ZKYWLeUdrki571OMgwqw",Vt="z6j4SZzTbavwii_DBoa2",zt=(new Date).getFullYear(),_t=()=>{const[e,t]=(0,n.useState)(!1),a=(0,n.useCallback)(()=>t(e=>!e),[]);return n.createElement(Rt,{title:"About",contentClassName:It},n.createElement(n.Fragment,null,n.createElement("a",{href:"https://www.karaoke-eternal.com",target:"_blank",rel:"noreferrer"},n.createElement(Qe,{className:kt})),n.createElement("p",{className:Pt},"©",`2019-${zt}`," ",n.createElement("a",{href:"https://www.radroot.com",target:"_blank",rel:"noreferrer"},"RadRoot LLC"),n.createElement("br",null),"v","2.0.0-beta.5"),n.createElement("p",null,n.createElement("a",{className:Lt,onClick:a},"Changelog & Sponsors")," ","|"," ",n.createElement("a",{href:"/licenses.txt",target:"_blank"},"Licenses")),n.createElement("div",{className:Ot},n.createElement("div",{className:Mt},n.createElement("a",{href:"https://www.karaoke-eternal.com/repo",target:"_blank",rel:"noreferrer"},n.createElement(p.A,{icon:"GITHUB_REPO",size:16}),"GitHub")),n.createElement("div",{className:Mt},n.createElement("a",{href:"https://www.karaoke-eternal.com/repo",target:"_blank",rel:"noreferrer"},n.createElement(p.A,{icon:"GITHUB_STAR",size:16}),"Star")),n.createElement("div",{className:(0,m.A)(Mt,Vt)},n.createElement("a",{href:"https://www.karaoke-eternal.com/sponsor",target:"_blank",rel:"noreferrer"},n.createElement(p.A,{icon:"GITHUB_SPONSOR",size:16}),"Sponsor"))),e&&n.createElement(J,{title:"Changelog & Sponsors",className:Tt,onClose:a,scrollable:!0,buttons:n.createElement(g,{variant:"primary",onClick:a},"Done")},n.createElement("a",{href:"","aria-hidden":!0}),n.createElement("div",{dangerouslySetInnerHTML:{__html:'<h2 id="v200-beta5">v2.0.0-beta.5</h2> <p><strong>Sponsored by</strong>: <a href="https://github.com/candre23">candre23</a>, <a href="https://github.com/nellisdev">nellisdev</a>, <a href="https://github.com/astrobyte">astrobyte</a>, <a href="https://github.com/jfeldhamer">jfeldhamer</a>, <a href="https://github.com/cubandaddy">cubandaddy</a>, <a href="https://github.com/Backroads4Me">Backroads4Me</a> and other private sponsors. Thank you! If you have fun with it, please consider <a href="https://www.karaoke-eternal.com/sponsor">sponsoring</a>.</p> <h3 id="guest-accounts-and-qr-codes">Guest accounts and QR codes</h3> <p>Joining the party is now faster and easier. The player supports QR codes that link directly to a room, where singers can now (finally!) join as guests. Admins can also choose whether a room allows guests and/or new standard users, or only existing users.</p> <h3 id="videos--visualizer">Videos + visualizer</h3> <p>Visualizations are now supported with video files. By automatically detecting a video's background color and making it transparent, visualizer effects can be displayed behind the lyrics. This works best on videos with solid color backgrounds, and can be enabled by selecting "Allow video background keying" in the media folder's preferences.</p> <h3 id="improved-queue-management">Improved queue management</h3> <p>Enhancements to the queue include:</p> <ul> <li>The queue can be restarted from any previously played song, or the beginning of the current song</li> <li>All upcoming songs for a user can be removed at once by long-pressing the <em>Remove</em> button</li> <li>When a standard user or guest signs out, their upcoming songs are now automatically removed from the queue</li> </ul> <h3 id="metadata-parser-changes">Metadata parser changes</h3> <p>Previously, the metadata parser (which uses filenames or tags to determine artist names and song titles) could be customized via <code>_kes.v1.js</code> files which were essentially arbitrary JavaScript. They were run in a sandbox to limit their functionality, but that sandbox was deprecated, and the overall approach was complex.</p> <p>In v2, the parser instead uses <code>_kes.v2.json</code> files. These JSON files allow the same basic configuration, in addition to simple string replacement and "templating" of artist names and song titles. See the docs for more information. As always, the best approach is to properly name/tag media, but customizing the parser can help in specific cases.</p> <h3 id="other-features-and-fixes">Other features and fixes</h3> <ul> <li>Zipped MP3+G media is now supported</li> <li>Media folders can now be watched for changes, as well as manually scanned individually</li> <li>In the Library view, songs that have already been played in the current session appear greyed</li> <li>In the Library view, tapping a song that is already upcoming no longer queues it again</li> <li>Fixed an error when listing drives on Windows due to removal of <code>wmic</code> (thanks Microsoft! /s)</li> <li>Usernames/emails are no longer case sensitive (thanks <strong>gazugafan</strong>)</li> </ul> <p>This release includes contributions from <a href="https://github.com/gazugafan">gazugafan</a>, (gausie)[<a href="https://github.com/gausie%5D">https://github.com/gausie]</a> and <a href="https://github.com/EffakT">EffakT</a>, as well as testing by <strong>mjmeans</strong>. Thanks!</p> <h2 id="v100-2022-05-17">v1.0.0 (2022-05-17)</h2> <p>Sponsored by: <a href="https://github.com/consolecwby">consolecwby</a>, <a href="https://github.com/vze22jjw">vze22jjw</a>. Thank you! If you have fun with it, please consider <a href="https://www.karaoke-eternal.com/sponsor">sponsoring</a>.</p> <h3 id="new">New</h3> <ul> <li><strong>Name</strong>: Karaoke Forever is now Karaoke Eternal</li> <li><strong>(app)</strong> User management interface</li> <li><strong>(app)</strong> "Make user's next" button for upcoming songs</li> <li><strong>(app)</strong> "Re-queue" button for played songs</li> <li><strong>(app)</strong> Content-aware CD+Graphics backgrounds</li> <li><strong>(app)</strong> Media folders can be prioritized via drag-and-drop</li> <li><strong>(app)</strong> Added ~370 visualizer presets (now 472 total)</li> <li><strong>(app)</strong> Summary is shown following a media scan</li> <li><strong>(server)</strong> Custom URL path (subfolder) support (see <code>--urlPath</code> CLI option)</li> <li><strong>(server)</strong> Custom database file path support (see <code>--data</code> CLI option)</li> <li><strong>(server)</strong> Session key can be rotated on startup (see <code>--rotateKey</code> CLI option)</li> <li><strong>(server)</strong> All CLI options now have equivalent environment variables</li> </ul> <h3 id="changed">Changed</h3> <ul> <li><strong>(app)</strong> Next-up singer's place is now reserved and won't be pre-empted</li> <li><strong>(server)</strong> Uses one less process/helper</li> <li><strong>(server)</strong> Media scanner performance is greatly improved when adding media</li> <li><strong>(server)</strong> Improved client connection speed via library caching</li> <li><strong>(server)</strong> Media scanner process is restricted to read-only database access</li> <li><strong>(server)</strong> Fixed potential error when a non-admin user tries to remove one of their queued songs</li> <li><strong>(server)</strong> Fixed potential SQLITE_BUSY errors while scanning media</li> <li><strong>(server)</strong> Fixed error message when no artist/title delimiter in filename</li> <li><strong>(server)</strong> Idle client socket connections no longer bounce</li> </ul> <h2 id="v080-2020-07-03">v0.8.0 (2020-07-03)</h2> <h3 id="black-lives-matter"><a href="https://blacklivesmatter.com">Black Lives Matter.</a></h3> <h3 id="sponsors">Sponsors</h3> <p>Massive thanks to this release's sponsors: <a href="https://github.com/fulldecent">fulldecent</a>, <a href="https://github.com/vze22jjw">vze22jjw</a>. If you have fun with it, please consider <a href="https://www.karaoke-eternal.com/sponsor">sponsoring</a>.</p> <h3 id="new-1">New</h3> <ul> <li><strong>(app)</strong> <a href="http://www.karaoke-eternal.com/docs/#preferences-admin-only">ReplayGain support</a>. No more scrambling for the volume when a new song starts! With properly tagged media, the player can automatically minimize volume differences between songs.</li> <li><strong>(app)</strong> Rooms can now be password-protected</li> <li><strong>(player)</strong> CD+Graphics now have shadows, can be resized, and use less CPU</li> <li><strong>(player)</strong> <strong>(breaking)</strong> Web Audio API support is now required (only for browsers running the player)</li> <li><strong>(server)</strong> <strong>(breaking)</strong> Database will be migrated and no longer compatible with v0.7.x</li> </ul> <h3 id="changed-1">Changed</h3> <ul> <li><strong>(app)</strong> Reduced motion and improved accessibility of modals</li> <li><strong>(app)</strong> Fixed status not respected when creating a new room</li> <li><strong>(player)</strong> Visualizer sensitivity can now be set up to 200%</li> <li><strong>(player)</strong> Fixed media possibly not (pre)loading in Firefox</li> <li><strong>(server)</strong> Added minimum password length requirement (6) and removed limit</li> <li><strong>(server)</strong> Fixed incorrect queue potentially emitted after setting preferred media</li> <li><strong>(server)</strong> Improved filename parser and renamed config option <code>separator</code> to <code>delimiter</code></li> <li><strong>(server)</strong> Improved logging and made <code>3 (info)</code> the default log file level</li> </ul> <h2 id="v074-2019-12-30">v0.7.4 (2019-12-30)</h2> <ul> <li>Initial release on <a href="https://www.npmjs.com/package/karaoke-eternal">npm</a></li> <li><strong>(app)</strong> Improved sign in/first run form</li> <li><strong>(app)</strong> Added About panel with version and licenses</li> <li><strong>(app)</strong> General style improvements</li> <li><strong>(server)</strong> Improved field validation and error messages</li> <li><strong>(server)</strong> Songs/artists without known media are no longer removed automatically after scan</li> <li><strong>(server)</strong> Media in nonexistent paths are now removed after scan</li> <li><strong>(server)</strong> Replace dep <code>squel</code> with <code>sqlate</code></li> </ul> <h2 id="v073-2019-09-13">v0.7.3 (2019-09-13)</h2> <ul> <li>Initial public release :-D</li> </ul> '}}))))};var xt=a(38180),Ht=a(33054);const Ut="eWB988t3JuRQuM9e6O_N",Dt="lVRxnFYFCfHZHGIPV2QD",Gt="Fj4oA4Er2_057Nqs3d_R",Ft=()=>{const e=(0,c.j)(),t=(0,c.G)(e=>e.user),a=(0,c.G)(e=>(0,Ht.A)(e,t.userId)),s=(0,n.useRef)(null),[r,l]=(0,n.useState)(!1),i=(0,n.useCallback)(()=>{if(!t.isAdmin){const n=a.length>0;let s="";if(t.isGuest&&n?s="Are you sure you want to sign out?\n\nYour upcoming songs will be removed from the queue, and as a guest, you won't be able to sign back into this account.":t.isGuest?s="Are you sure you want to sign out?\n\nAs a guest, you won't be able to sign back into this account.":n&&(s="Are you sure you want to sign out?\n\nYour upcoming songs will be removed from the queue."),s&&!confirm(s))return;n&&e((0,xt.Ai)({queueId:a}))}e((0,qe.aw)())},[e,a,t.isAdmin,t.isGuest]),o=(0,n.useCallback)(a=>{if(!t.isGuest){if(!s.current.value.trim())return alert("Please enter your current password to make changes."),void s.current.focus();a.append("password",s.current.value)}e((0,qe.z0)(a))},[e,t.isGuest]);return n.createElement(Rt,{title:"My Account",contentClassName:Ut},n.createElement(n.Fragment,null,n.createElement("p",null,"Signed in as ",n.createElement("strong",null,t.isGuest?"guest":t.username)),n.createElement(st,{user:t,onDirtyChange:l,onSubmit:o,showUsername:!t.isGuest,showPassword:!t.isGuest},r&&!t.isGuest&&n.createElement("input",{type:"password",autoComplete:"current-password",placeholder:"current password",ref:s}),r&&n.createElement(g,{type:"submit",className:(0,m.A)("primary",Gt),variant:"primary"},"Update Account")),n.createElement(g,{onClick:i,className:Dt,variant:"default"},"Sign Out")))};var qt=a(66248);const Bt="Kyq1e8Js6YODEAIrpuiV",Yt="vrRzBvLX1MqJZgM7p38z",jt="tVJZZisJHykY_Y7qwkKK",Wt=({className:e,children:t,contentClassName:a,headingComponent:s,iconClassName:r,initialExpanded:l=!1})=>{const[i,o]=(0,n.useState)(l),c=(0,n.useId)(),d=(0,n.cloneElement)(s,{children:n.createElement("button",{type:"button",id:`accordion-header-${c}`,"aria-controls":`accordion-panel-${c}`,"aria-expanded":i},s.props.children)});return n.createElement("div",(0,u.A)({className:(0,m.A)(Bt,e)},i&&{"data-expanded":""}),n.createElement("div",{className:(0,m.A)(jt),onClick:()=>{o(!i)}},d,n.createElement(p.A,{icon:"CHEVRON_RIGHT",className:(0,m.A)(Yt,r)})),n.createElement("section",{id:`accordion-panel-${c}`,"aria-labelledby":`accordion-header-${c}`,className:(0,m.A)(a),hidden:!i},t))},Qt="zXRZqy8GypIyzzonhQDj",Kt="nn35PIgJyM8hd_PfVG9P",Jt=e=>n.createElement("div",{className:Qt,onClick:e.onSelect},n.createElement("div",null,n.createElement(p.A,{icon:"FOLDER",size:28})),n.createElement("div",{className:Kt},e.path)),Zt="Z1AkYsOvWFhZrcYR6W9z",Xt="PCD9_JwmkY6aoE1S6ZP_",$t="zuvIYSwYXKYBkknUSBt0",ea="Er04pbLH9MbYq06HYgN2",ta="PQDNPIs88caRIT2AXWfT",aa=new dt.A("prefs/path"),na=({onCancel:e,onChoose:t})=>{const a=(0,n.useRef)(null),[s,r]=(0,n.useState)({current:null,parent:null,children:[]}),l=(0,n.useCallback)(()=>{t(s.current,{})},[t,s]),i=(0,n.useCallback)(async e=>{try{const t=await aa.get(`/ls?dir=${encodeURIComponent(e)}`);r(t)}catch(e){alert(e)}},[]);return(0,n.useEffect)(()=>{i(s.current??".")},[]),(0,n.useEffect)(()=>{a.current&&(a.current.scrollTop=0)},[]),n.createElement(J,{title:"Add Folder",className:Zt,onClose:e,scrollable:!0,buttons:n.createElement("div",{className:ta},n.createElement(g,{onClick:e,variant:"default"},"Cancel"),n.createElement(g,{onClick:l,variant:"primary"},"Add Folder"))},n.createElement("div",{className:Xt},n.createElement("div",{className:$t},s.current||" "),n.createElement("div",{className:ea,ref:a},!1!==s.parent&&n.createElement("strong",null,n.createElement(Jt,{path:"..",onSelect:()=>i(s.parent)})),s.children.map((e,t)=>n.createElement(Jt,{key:t,path:e.label,onSelect:()=>i(e.path)})))))},sa="ATXORF88MX2KCM3GK6PD",ra="J_rtBBS98nuownep8wbe",la="YZaEmIfhPKE_g3gNZwso",ia=({onClose:e,onRemove:t,onUpdate:a,path:s})=>{const r=(0,n.useCallback)(e=>{a(s.pathId,e)},[a,s.pathId]),l=(0,n.useCallback)(()=>t(s.pathId),[t,s.pathId]);return n.createElement(J,{onClose:e,title:"Media Folder",buttons:n.createElement(n.Fragment,null,n.createElement(g,{onClick:l,variant:"danger"},"Remove Folder"),n.createElement(g,{onClick:e,variant:"primary"},"Done"))},n.createElement("div",null,n.createElement("p",{className:sa},s?.path,n.createElement("br",null),n.createElement("span",{className:ra},"pathId: "),s?.pathId),n.createElement("form",{className:la},n.createElement($,{label:"Watch folder",defaultChecked:s?.prefs?.isWatchingEnabled,onChange:e=>r({isWatchingEnabled:e.currentTarget.checked})}),n.createElement($,{label:"Allow video background keying",defaultChecked:s?.prefs?.isVideoKeyingEnabled,onChange:e=>r({isVideoKeyingEnabled:e.currentTarget.checked})}))))},oa="vfEtFMD1PnnZpL7KJi5i",ca="reQxnTVFy0pmOJ_OxHEW",da="cLbX8ACpwjrJHf1i33Kw",ua="mFavmW0ojDDlX4oNvSlc",ma="vKWSaWmD75njSGInSqpQ",pa=({index:e,onInfo:t,onRefresh:a,path:s})=>{const r=(0,n.useCallback)(e=>t(parseInt(e.currentTarget.dataset.pathId)),[t]),l=(0,n.useCallback)(e=>a(parseInt(e.currentTarget.dataset.pathId)),[a]);return n.createElement(qt.sx,{draggableId:`path-${s.pathId}`,index:e},e=>n.createElement("div",(0,u.A)({className:oa,key:s.pathId,ref:e.innerRef,style:e.draggableProps.style},e.draggableProps),n.createElement("div",(0,u.A)({},e.dragHandleProps,{tabIndex:-1}),n.createElement(p.A,{icon:"DRAG_INDICATOR",className:da})),n.createElement("div",{className:ca},s.path),n.createElement(g,{className:ua,"data-path-id":s.pathId,icon:"REFRESH",onClick:l}),n.createElement(g,{className:ma,"data-path-id":s.pathId,icon:"INFO_OUTLINE",onClick:r})))},ha={heading:"IkPiZ7oarPYasin3JcFC",content:"eYUqAJLLPnFSGQfPrwJp",btnContainer:"COsFBSxrE3VeJHh23G5V"},Ea=new dt.A("prefs/path"),ga=()=>{const e=(0,c.G)(e=>e.prefs.paths),[t,a]=(0,n.useState)(!1),[s,r]=(0,n.useState)(null),[l,i]=(0,n.useState)(e.result),o=(0,n.useCallback)(()=>a(!1),[]),d=(0,n.useCallback)(()=>a(!0),[]),m=(0,n.useCallback)(()=>r(null),[]),h=(0,c.j)();(0,n.useEffect)(()=>{i(e.result)},[e]);const E=(0,n.useCallback)(e=>{if(!e.destination)return;const t=l.slice(),[a]=t.splice(e.source.index,1);t.splice(e.destination.index,0,a),i(t),h((0,f.Ah)(t))},[h,l]),v=(0,n.useCallback)((e,t)=>{Ea.post(`/?dir=${encodeURIComponent(e)}`,{body:t}).then(e=>{h((0,f.gL)(e)),a(!1)}).catch(e=>{alert(e)})},[h]),C=(0,n.useCallback)(t=>{confirm(`Remove folder from library?\n\n${e.entities[t].path}`)&&(i(l.filter(e=>e!==t)),r(null),Ea.delete(`/${t}`).then(e=>{h((0,f.gL)(e))}).catch(e=>{alert(e)}))},[h,e,l]),y=(0,n.useCallback)((e,t)=>{h((0,f.yx)({pathId:e,data:t}))},[h]),b=(0,n.useCallback)(t=>r(e.entities[t]),[e]),w=(0,n.useCallback)(e=>h((0,f.PA)(e)),[h]),A=(0,n.useCallback)(()=>h((0,f.mN)()),[h]);return n.createElement(Wt,{headingComponent:n.createElement("div",{className:ha.heading},n.createElement(p.A,{icon:"FOLDER_MUSIC"}),n.createElement("div",{className:ha.title},"Media Folders"))},n.createElement("div",{className:ha.content},0===e.result.length&&n.createElement("p",{style:{marginTop:0}},"Add a media folder to get started."),n.createElement(qt.JY,{onDragEnd:E},n.createElement(qt.gL,{droppableId:"droppable"},t=>n.createElement("div",(0,u.A)({ref:t.innerRef},t.droppableProps),l.map((t,a)=>n.createElement(pa,{index:a,key:t,path:e.entities[t],onInfo:b,onRefresh:w})),t.placeholder))),n.createElement("div",{className:ha.btnContainer},e.result.length>0&&n.createElement(g,{onClick:A,variant:"default"},"Scan Folders"),n.createElement(g,{onClick:d,variant:"primary"},"Add Folder")),t&&n.createElement(na,{onCancel:o,onChoose:v}),!!s&&n.createElement(ia,{onClose:m,onRemove:C,onUpdate:y,path:s})))},va={heading:"iQsmu84S0UOMvskFslib",content:"EsTYWrxvRDwQ5bUKgop3"},fa=()=>{const e=(0,c.G)(e=>e.prefs.isReplayGainEnabled),t=(0,c.j)(),a=(0,n.useCallback)(e=>{t((0,f.I8)({key:e.currentTarget.name,data:e.currentTarget.checked}))},[t]);return n.createElement(Wt,{className:va.container,headingComponent:n.createElement("div",{className:va.heading},n.createElement(p.A,{icon:"TELEVISION_PLAY",size:32,className:va.icon}),n.createElement("div",{className:va.title},"Player"))},n.createElement("div",{className:va.content},n.createElement("label",null,n.createElement("input",{type:"checkbox",checked:e,onChange:a,name:"isReplayGainEnabled"})," ","ReplayGain (clip-safe)")))},Ca="ew2x2VQFG7Hj_ltiyxbF",ya=()=>n.createElement(Rt,{title:"Preferences",contentClassName:Ca},n.createElement(n.Fragment,null,n.createElement(ga,null),n.createElement(fa,null)));var ba=a(80470);const wa={heading:"WI7RHMq3jaNSZwGU2FA6",content:"tW4weGP7ZNHvtdAvHXkQ"},Aa=({onChange:e,prefs:t={}})=>{const a=(0,c.G)(e=>e.prefs.roles),s=(0,n.useCallback)(e=>a.result.find(t=>a.entities[t].name===e),[a.entities,a.result]),r=(0,n.useCallback)(a=>{const{name:n,checked:r}=a.target,l=s(n);l&&e({...t,roles:{...t.roles,[l]:{...t.roles?.[l],allowNew:r}}})},[s,e,t]),l=t.roles?.[s("guest")]?.allowNew??!1,i=t.roles?.[s("standard")]?.allowNew??!1;return n.createElement(Wt,{headingComponent:n.createElement("div",{className:wa.heading},n.createElement(p.A,{icon:"PERSON"}),n.createElement("div",{className:wa.title},"Users"))},n.createElement("div",{className:wa.content},n.createElement("div",{className:wa.field},n.createElement($,{label:"Allow new standard users",name:"standard",checked:i,onChange:r})),n.createElement("div",{className:wa.field},n.createElement($,{label:"Allow new guests",name:"guest",checked:l,onChange:r}))))},Na={heading:"NxVXilqTVRm2Gn61JMnN",slider:"HOcMzCIA0WXMfcLNpS_4",content:"bjETwqGW5QyR3on58pts",hidden:"_zeQjaCY8RxRMtxT2JAF"},Sa=({onChange:e,prefs:t={},roomPassword:a,roomPasswordDirty:s})=>{const[r,l]=(0,n.useState)(!!t?.qr?.password),i=(0,n.useCallback)(a=>{e({...t,...a})},[e,t]);return(0,n.useEffect)(()=>{r&&s&&t?.qr?.password!==a&&i({qr:{...t.qr,password:a}})},[r,i,t,a,s]),n.createElement(Wt,{headingComponent:n.createElement("div",{className:Na.heading},n.createElement(p.A,{icon:"QR_CODE"}),n.createElement("div",{className:Na.title},"QR Code"))},n.createElement("div",{className:Na.content},n.createElement("div",{className:Na.field},n.createElement($,{label:"Show QR code",checked:t?.qr?.isEnabled??!1,onChange:e=>i({qr:{...t.qr,isEnabled:e.currentTarget.checked}})})),t?.qr?.isEnabled&&a&&n.createElement("div",{className:Na.field},n.createElement($,{label:"Include room password",checked:r,onChange:e=>{const a=e.currentTarget.checked;l(a),a||i({qr:{...t.qr,password:""}})}})),r&&!s&&n.createElement("div",{className:Na.field},n.createElement("input",{type:"password",autoComplete:"new-password",value:t?.qr?.password??"",onChange:e=>i({qr:{...t.qr,password:e.target.value}}),onFocus:e=>e.target.select(),placeholder:"re-enter room password"})),n.createElement("div",{className:(0,m.A)(Na.field)},n.createElement("label",{id:"label-qr-size"},"Size"),n.createElement(_,{className:Na.slider,min:0,max:1,step:.05,value:t?.qr?.size??.5,onChange:e=>i({qr:{...t.qr,size:e}}),"aria-labelledby":"label-qr-size"})),n.createElement("div",{className:(0,m.A)(Na.field)},n.createElement("label",{id:"label-qr-opacity"},"Opacity"),n.createElement(_,{className:Na.slider,min:.25,max:1,step:.075,value:t?.qr?.opacity??.625,onChange:e=>i({qr:{...t.qr,opacity:e}}),"aria-labelledby":"label-qr-opacity"}))))},Ra={modal:"Q5T7XWGqm4a5MPArNfUg",fieldContainer:"YSEBZfRCIoJmOplLt9mP",prefsContainer:"a5K1WCxiR97esx_y_2Ex",btnContainer:"uiSOmb44a9pRFxf0NKJc"},Ia=({onClose:e,room:t})=>{const a=(0,n.useRef)(null),[s,r]=(0,n.useState)(t&&t.hasPassword?"*".repeat(32):""),[l,i]=(0,n.useState)(t?.prefs||{}),[o,d]=(0,n.useState)(!1),u=(0,c.j)(),m=(0,n.useCallback)(e=>{e.preventDefault();const n=(e=>{const t={};return e.forEach((e,a)=>{t[a]?t[a]=[].concat(t[a],e):t[a]=e}),t})(new FormData(a.current));n.prefs=l,t?(o||delete n.password,u((0,ba.xX)({roomId:t.roomId,data:n}))):(n.password||delete n.password,u((0,ba.ab)(n)))},[u,l,t,o]),p=(0,n.useCallback)(()=>{t&&confirm(`Remove room "${t.name}" and its queue?`)&&u((0,ba.SV)(t.roomId))},[u,t]),h=(0,n.useCallback)(e=>{i(e),t&&u((0,ba.uE)(t.roomId,e))},[u,t]),E=(0,n.useCallback)(()=>{t&&u((0,ba.uE)(t.roomId,t.prefs)),e()},[u,e,t]),v=(0,n.useCallback)(e=>{d(!0),r(e.target.value)},[]);return(0,n.useEffect)(()=>{t?.prefs&&i(t.prefs)},[t]),n.createElement(J,{className:Ra.modal,onClose:E,title:t?"Edit Room":"Create Room"},n.createElement("form",{onSubmit:m,ref:a,className:Ra.form},n.createElement("div",{className:Ra.fieldContainer},n.createElement("input",{type:"text",autoComplete:"off",defaultValue:t?t.name:"",name:"name",placeholder:"room name",ref:e=>void 0===t?e?.setAttribute("autofocus","true"):void 0}),n.createElement("input",{type:"password",autoComplete:"new-password",value:s,name:"password",onChange:v,onFocus:e=>e.target.select(),placeholder:"room password (optional)"}),n.createElement("select",{name:"status",defaultValue:t?.status??"open"},n.createElement("option",{value:"open"},"Open"),n.createElement("option",{value:"closed"},"Closed"))),n.createElement("div",{className:Ra.prefsContainer},n.createElement(Aa,{prefs:l,onChange:h}),n.createElement(Sa,{prefs:l,onChange:h,roomPassword:s,roomPasswordDirty:o})),n.createElement("div",{className:Ra.btnContainer},n.createElement(g,{type:"submit",variant:"primary",className:Ra.btn},t?"Update Room":"Create Room"),t&&n.createElement(g,{onClick:p,className:Ra.btn,variant:"danger"},"Remove Room"),n.createElement(g,{onClick:E,variant:"default"},"Cancel"))))},ka=(0,v.Mz)([e=>e.rooms.result,e=>e.rooms.entities,e=>e.rooms.filterStatus],(e,t,a)=>({result:e.filter(e=>!1===a||t[e].status===a),entities:t})),Pa="dlkVNG9BLZN9R9HguwLu",La="HAVmLg8TCL18Jeiuo7fX",Ta=()=>{const[e,t]=(0,n.useState)(null),{isEditorOpen:a,filterStatus:s}=(0,c.G)(e=>e.rooms),r=(0,c.G)(ka),l=(0,c.j)(),i=(0,n.useCallback)(()=>l((0,ba.$R)()),[l]),o=(0,n.useCallback)(e=>{"all"===e.currentTarget.value?l((0,ba.Mv)(!1)):l((0,ba.Mv)(e.currentTarget.value))},[l]),d=(0,n.useCallback)(e=>l(yt(parseInt(e.currentTarget.dataset.roomId))),[l]),u=(0,n.useCallback)(e=>{t(r.entities[parseInt(e.currentTarget.dataset.roomId||"0")]),l((0,ba.v4)())},[l,r]);(0,n.useEffect)(()=>{l((0,ba.RM)())},[l]);const m=r.result.map(e=>{const t=r.entities[e];return n.createElement("tr",{key:String(e)},n.createElement("td",null,n.createElement("a",{"data-room-id":e,onClick:u},t.name)),n.createElement("td",null,t.status,t.numUsers>0&&n.createElement(n.Fragment,null," ",n.createElement("a",{"data-room-id":e,onClick:d},"(",t.numUsers,")"))),n.createElement("td",null,ve(new Date(1e3*t.dateCreated))))}),p=n.createElement("select",{className:Pa,onChange:o,value:!1===s?"all":s},n.createElement("option",{key:"all",value:"all"},"All"),n.createElement("option",{key:"open",value:"open"},"Open"),n.createElement("option",{key:"closed",value:"closed"},"Closed"));return n.createElement(Rt,{title:"Rooms",titleComponent:p},n.createElement(n.Fragment,null,n.createElement("table",{className:La},n.createElement("thead",null,n.createElement("tr",null,n.createElement("th",null,"Name"),n.createElement("th",null,"Status"),n.createElement("th",null,"Created"))),n.createElement("tbody",null,m)),n.createElement("br",null),n.createElement(g,{onClick:u,variant:"primary"},"Create Room"),a&&n.createElement(Ia,{onClose:i,room:e})))},Oa={modal:"gqWI3mlnDqWIUNXebNqh",btnContainer:"_UZuyKF0ewftaeFpnDiS",field:"egMKJajhBRVHHcS0ruyV"},Ma=e=>{const t=(0,c.j)(),a=(0,n.useCallback)(a=>{e.user?t(Et({userId:e.user.userId,data:a})):t(ht(a))},[t,e.user]),s=(0,n.useCallback)(()=>{confirm(`Remove user "${e.user.username}"?\n\nTheir queued songs will also be removed.`)&&t(gt(e.user.userId))},[t,e.user]);return n.createElement(J,{className:Oa.modal,onClose:e.onClose,title:e.user?e.user.username:"Create User"},n.createElement(st,{user:e.user,onSubmit:a,showRole:!0,autoFocus:!e.user},n.createElement("div",{className:Oa.btnContainer},!e.user&&n.createElement(g,{type:"submit",className:Oa.btn,variant:"primary"},"Create User"),e.user&&n.createElement(g,{type:"submit",className:Oa.btn,variant:"primary"},"Update User"),e.user&&n.createElement(g,{onClick:s,className:Oa.btn,variant:"danger"},"Remove User"),n.createElement(g,{onClick:e.onClose,variant:"default"},"Cancel"))))},Va=(0,v.Mz)([e=>e.users.result,e=>e.users.entities,e=>e.users.filterOnline,e=>e.users.filterRoomId],(e,t,a,n)=>(a?e=e.filter(e=>t[e].rooms.length):"number"==typeof n&&(e=e.filter(e=>t[e].rooms.includes(n))),{result:e,entities:t})),za="krYGtNnm9wreKzV0sC87",_a="dVtQTutpaei_Zk_0Dmhd",xa=()=>{const[e,t]=(0,n.useState)(null),a=(0,c.G)(e=>e.user.userId),{isEditorOpen:s,filterOnline:r,filterRoomId:l}=(0,c.G)(e=>e.users),i=(0,c.G)(e=>e.rooms),o=(0,c.G)(Va),d=(0,c.j)(),u=(0,n.useCallback)(()=>d(ft()),[d]),m=(0,n.useCallback)(e=>{"all"===e.target.value?d(Ct(!1)):"online"===e.target.value?d(Ct(!0)):d(yt(parseInt(e.target.value,10)))},[d]),p=(0,n.useCallback)(e=>{t(o.entities[parseInt(e.currentTarget.dataset.userId)]),d(vt())},[d,o]);(0,n.useEffect)(()=>{d(pt())},[d]);const h=o.result.map(e=>{const t=o.entities[e];return n.createElement("tr",{key:e},e===a&&n.createElement("td",null,n.createElement("strong",null,t.username)," ","(",t.name,")"),e!==a&&n.createElement("td",null,n.createElement("a",{"data-user-id":e,onClick:p},t.username)," ","(",t.name,")"),n.createElement("td",null,t.role),n.createElement("td",null,ve(new Date(1e3*t.dateCreated))))}),E=i.result.filter(e=>!!i.entities[e].numUsers).map(e=>n.createElement("option",{key:e,value:e},i.entities[e].name)),v=n.createElement("select",{className:za,onChange:m,value:r?"online":l||"all"},n.createElement("option",{key:"all",value:"all"},"All"),n.createElement("option",{key:"online",value:"online"},"Online"),n.createElement("optgroup",{label:"Online in..."},E));return n.createElement(Rt,{title:"Users",titleComponent:v},n.createElement(n.Fragment,null,n.createElement("table",{className:_a},n.createElement("thead",null,n.createElement("tr",null,n.createElement("th",null,"Username"),n.createElement("th",null,"Role"),n.createElement("th",null,"Joined"))),n.createElement("tbody",null,h)),n.createElement("br",null),n.createElement(g,{onClick:p,variant:"primary"},"Create User"),s&&n.createElement(Ma,{onClose:u,user:e})))},Ha=()=>{const{isAdmin:e}=(0,c.G)(e=>e.user),t=!!(0,c.G)(e=>e.users),a=(0,c.j)();return e&&!t&&(ot.A.inject({reducerPath:"users",reducer:bt}),a(wt())),(0,n.useEffect)(()=>{(async()=>{a((0,qe.mb)())})()},[a]),n.createElement(n.Fragment,null,e&&n.createElement(Ta,null),e&&n.createElement(xa,null),e&&n.createElement(ya,null),n.createElement(Ft,null),n.createElement(_t,null))},Ua="Wdz5LHTVlrpDjGYTKK9L",Da=({onChange:e,label:t,className:a,...s})=>n.createElement("label",{className:(0,m.A)(Ua,a)},n.createElement("input",(0,u.A)({type:"radio",onChange:t=>{e&&e(t.target.value)}},s)),t),Ga={container:"MTzbvQ4VAtgPXbJKkrGO",hidden:"X1Pj4fM1xquH4Ymuq0Q5"},Fa=({onRoomSelect:e,onRoomPasswordChange:t,className:a,rooms:s,roomId:r,roomPassword:l,showAllRooms:i})=>{const o=(0,n.useRef)({}),c=e=>t=>{o.current[e]=t},d=t=>{const a=t;Object.entries(o.current).forEach(([e,t])=>{t&&(e===a?(t.classList.remove(Ga.hidden),t.focus()):t.classList.add(Ga.hidden))}),e(parseInt(a))};return n.createElement("div",{className:(0,m.A)(Ga.container,a)},s.result.map(e=>i||e===r?n.createElement("div",{key:`room-${e}`},n.createElement(Da,{name:"roomId",className:(0,m.A)(Ga.option,e===r&&Ga.checked),label:s.entities[e].name,value:e,onChange:d,checked:e===r}),s.entities[e]?.hasPassword&&n.createElement("input",{type:"password",autoComplete:"off",className:(0,m.A)((null===r||e!==r)&&Ga.hidden),onChange:e=>{t(e.target.value)},placeholder:"room password (required)","aria-label":"room password (required)",ref:c(e),value:l})):null))},qa="mlhmoE1JUQKR4Te5DEtv",Ba="glTWFMiUMaerBvhPz8ti",Ya=({guest:e,username:t,password:a,onUsernameChange:s,onPasswordChange:r,onSubmit:l,onFirstFieldRef:i})=>{const[o,c]=(0,n.useState)(""),[d,u]=(0,n.useState)(""),[m,p]=(0,n.useState)(void 0);return n.createElement("form",{className:qa,noValidate:!0,onSubmit:e=>{e.preventDefault(),l({name:o,image:m,passwordConfirm:d})}},!e&&n.createElement(n.Fragment,null,n.createElement("input",{type:"email",autoComplete:"off",value:t,onChange:e=>s(e.target.value),placeholder:"username or email",ref:i}),n.createElement("input",{type:"password",autoComplete:"new-password",value:a,onChange:e=>r(e.target.value),placeholder:"password"}),n.createElement("input",{type:"password",autoComplete:"new-password",placeholder:"confirm password",value:d,onChange:e=>u(e.target.value)})),n.createElement("div",{className:Ba},n.createElement(tt,{onSelect:p}),n.createElement("input",{type:"text",placeholder:"display name",value:o,onChange:e=>c(e.target.value),ref:e?i:void 0})),n.createElement(g,{type:"submit",variant:"primary"},"Join"))},ja="pvyilF8BtiMYHtpXJ_jT",Wa=({username:e,password:t,onUsernameChange:a,onPasswordChange:s,onSubmit:r,onFirstFieldRef:l})=>n.createElement("form",{noValidate:!0,onSubmit:r,className:ja},n.createElement("input",{type:"email",autoComplete:"username",placeholder:"username or email",value:e,onChange:e=>a(e.target.value),ref:l}),n.createElement("input",{type:"password",autoComplete:"current-password",placeholder:"password",value:t,onChange:e=>s(e.target.value)}),n.createElement(g,{type:"submit",variant:"primary"},"Sign In")),Qa="e3jR4OMsV_OIaaAci_hn",Ka="kfaDc9tZA7V0rbLrrQxW",Ja="unPhcciIOQl7IyVNBGQk",Za="cRQaBuJaYH041jNLJIlp",Xa=()=>{const e=(0,n.useRef)(null),t=(0,n.useRef)(null),a=(0,c.G)(e=>e.prefs),s=(0,c.G)(e=>e.rooms),r=(0,c.G)(e=>e.ui),l=(0,c.j)(),[i,o]=(0,n.useState)("returning"),[d,u]=(0,n.useState)(""),[p,h]=(0,n.useState)(""),[E,g]=(0,n.useState)(null),[v,f]=(0,n.useState)(""),[C,y]=(0,n.useState)(!1),[b,w]=(0,n.useState)(!0);(0,n.useEffect)(()=>{l((0,ba.RM)())},[l]),(0,n.useEffect)(()=>{const a=new URLSearchParams(location.search),n=a.get("roomId"),r=n?parseInt(n,10):null,l=a.get("password");r&&s.entities[r]?(g(r),w(!1),e.current.classList.remove(Za),s.entities[r]?.hasPassword?l?(f(atob(l)),y(!1),t.current?.focus()):y(!0):t.current?.focus()):1===s.result.length?(g(s.result[0]),y(s.entities[s.result[0]]?.hasPassword)):y(0!==s.result.length)},[s]);const A=(0,n.useCallback)(a=>{g(a),o("returning"),e.current.classList.remove(Za),s.entities[a]?.hasPassword&&C||(t.current?.focus(),e.current.scrollIntoView({behavior:"smooth",block:"start"}))},[s.entities,C]),N=(0,n.useCallback)(e=>{e&&(t.current=e)},[]),S=(0,n.useCallback)(e=>{e.preventDefault(),l((0,qe.iD)({username:d.trim(),password:p,roomId:E,roomPassword:v}))},[l,p,E,v,d]),R=(0,n.useCallback)(({name:e,image:t,passwordConfirm:a})=>{const n=new FormData;n.append("username",d.trim()),n.append("newPassword",p),n.append("newPasswordConfirm",a),n.append("roomId",String(E)),n.append("roomPassword",p),n.append("name",e.trim()),void 0!==t&&n.append("image",t),"guest"===i&&n.append("role","guest"),l((0,qe._m)(n))},[l,i,p,E,d]);(0,n.useEffect)(()=>{t.current?.focus()},[i]);const I=(0,n.useCallback)(e=>{const t=a.roles.result.find(t=>a.roles.entities[t].name===e);return!!s.entities[E]?.prefs?.roles?.[t]?.allowNew},[a.roles,s.entities,E]),k=I("guest"),P=I("standard"),L=P||k;return n.createElement("div",{className:Qa,style:{maxWidth:Math.max(340,.66*r.contentWidth)}},n.createElement(Qe,{className:Ka}),C&&n.createElement(n.Fragment,null,n.createElement("h1",null,"Join room..."),n.createElement(Fa,{rooms:s,roomId:E,roomPassword:v,showAllRooms:b,onRoomSelect:A,onRoomPasswordChange:f})),n.createElement("div",{ref:e,className:(0,m.A)(s.result.length>1&&Za)},L?n.createElement(n.Fragment,null,n.createElement("h1",null,"Join as..."),n.createElement("div",{className:Ja},n.createElement(Da,{name:"type",value:"returning",checked:"returning"===i,onChange:o,label:"Returning user"}),P&&n.createElement(Da,{name:"type",value:"new",checked:"new"===i,onChange:o,label:"New user"}),k&&n.createElement(Da,{name:"type",value:"guest",checked:"guest"===i,onChange:o,label:"Guest"}))):n.createElement("h1",null,"Sign in"),("returning"===i||!L)&&n.createElement(Wa,{username:d,password:p,onUsernameChange:u,onPasswordChange:h,onSubmit:S,onFirstFieldRef:N}),"returning"!==i&&L&&n.createElement(Ya,{guest:"guest"===i,username:d,password:p,onUsernameChange:u,onPasswordChange:h,onSubmit:R,onFirstFieldRef:N})))},$a="EPw4Q8pC4VCZu_ENeHOh",en=()=>{const e=(0,c.G)(e=>null!==e.user.userId),t=(0,c.G)(e=>!0===e.prefs.isFirstRun),a=(0,c.G)(e=>e.ui),s=(0,c.j)();return(0,n.useEffect)(()=>{s((0,f.dJ)())},[s]),n.createElement("div",{className:$a,style:{paddingTop:a.headerHeight,paddingBottom:a.footerHeight,width:a.contentWidth,height:a.innerHeight}},e&&n.createElement(Ha,null),!t&&!e&&n.createElement(Xa,null),t&&n.createElement(it,null))};var tn=a(9934);const an=(0,v.Mz)([e=>e.artists],e=>{const t={"#":0},a="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");let n=0;return e.result.forEach((s,r)=>{const l=e.entities[s].name[0].toUpperCase(),i=a.indexOf(l)-n;i>=0&&(n+=i,t[a[n]]=r,n++)}),t}),nn=(0,v.Mz)([e=>(0,tn.wd)(e.queue),e=>e.status.isAtQueueEnd?void 0:e.status.queueId,e=>e.status.historyJSON],(e,t,a)=>{const n=JSON.parse(a),s=[],r=[];return e.result.forEach(a=>{n.includes(a)?s.push(e.entities[a].songId):a!==t&&r.push(e.entities[a].songId)}),{played:s,upcoming:r,current:e.entities[t]?.songId}});var sn=a(68853);const rn="JoCtgfMdp4_LkFISBVdL",ln=({numRows:e,onRowsRendered:t,onRef:a,paddingTop:s,paddingRight:r,paddingBottom:l,rowComponent:i,rowHeight:o,rowProps:c={},width:d,height:m})=>{const p=(0,n.useCallback)(e=>{a&&a(e)},[a]),h=(0,n.useCallback)(({index:t,style:a,ariaAttributes:s,...l})=>0===t||t===e+1?n.createElement("div",{key:0===t?"top":"bottom",style:a}):n.createElement(i,(0,u.A)({index:--t,style:{...a,paddingRight:r},ariaAttributes:s},l)),[e,i,r]);return n.createElement(sn.B8,{rowProps:c,rowComponent:h,rowCount:e+2,rowHeight:t=>0===t?s:t===e+1?l:o(t-1),onRowsRendered:t,overscanCount:10,listRef:p,className:rn,style:{width:d,height:m}})},on="vN10Ra6WwFQwsoJD1_3H";class cn extends n.Component{alphabet="#ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");state={isTouchCapable:!1,isTouching:!1,char:null,y:null};render(){return n.createElement("div",{className:on,style:{height:this.props.height,top:this.props.top},onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouch,onTouchEnd:this.handleTouchEnd,onMouseDown:this.handleTouch,onMouseUp:this.handleTouchEnd},this.alphabet.map(e=>n.createElement("div",{key:e,style:{flex:"1 1 auto",minHeight:0}},e)))}handleTouchStart=()=>{(0,O.Dx)(!0),this.setState({isTouchCapable:!0,isTouching:!0})};handleTouch=e=>{if(e.preventDefault(),"mousedown"===e.type&&this.state.isTouchCapable)return;const t="targetTouches"in e?e.targetTouches[0].clientY:e.clientY,a=this.alphabet[Math.floor((t-this.props.top)/this.props.height*this.alphabet.length)];this.setState({char:a,y:t-this.props.top}),a!==this.state.char&&void 0!==a&&this.props.onPick(a)};handleTouchEnd=()=>{(0,O.Dx)(!1),this.setState({isTouching:!1,char:null})}}const dn=cn;var un=a(23257),mn=a.n(un),pn=a(10188);const hn="NLkRlVVNnuiKJMNOXMhe",En="IW53X1CCc5LsUP_viCWs";class gn extends n.Component{render(){let e=0;const t=n.Children.map(this.props.children,t=>{if(n.isValidElement(t))return t.props["data-hide"]&&!this.props.isExpanded?n.cloneElement(t,{className:(0,m.A)(t.props.className,En)}):(e++,t)});return n.createElement("div",{className:(0,m.A)(hn,this.props.className),style:{width:this.props.btnWidth*e}},t)}}class vn extends n.Component{state={animate:!1};componentDidUpdate(e){this.props.toggle!==e.toggle&&this.setState({animate:!0})}render(){return this.state.animate?n.Children.map(this.props.children,e=>{if(n.isValidElement(e))return n.cloneElement(e,{className:(0,m.A)(e.props.className,this.props.className),onAnimationEnd:this.handleAnimationEnd})}):this.props.children}handleAnimationEnd=()=>this.setState({animate:!1})}const fn={container:"Hk5Oiz4LTn0TQU1HJ_4r",withArtist:"otX4OYp4lT3aOtJMqjAT",upcoming:"Ar5Q9JpCbRQjA3OMib2W",title:"oqSOn8U_QmqEzSvyfAw_",played:"iMwtWGP1vWpUXRv3MLTP",starred:"_t4JBPFRguFbumW7x8D6",star:"bfE_vcKGNAy6HuKrhsLQ",starCount:"a2lTNMjjT5QzeuYbGeux",animateGlow:"q8d4R7JJbyKfMfb5qTtn",duration:"hxXzgFhspryRgl6_AkmQ",primary:"z8K08MurHExDsFH50TjN",artist:"INKd0vI4DamezRZUfFHO",btn:"DLgbTdB3hYU0zYVmvotm",info:"IpLs3GshduGnVRAThUSV",animateStar:"r4HcW54ut9T2YXA4ysAf"};let Cn=!1;const yn=({songId:e,artist:t,title:a,duration:s,onSongQueue:r,onSongStarClick:l,onSongInfo:i,isPlayed:o,isStarred:c,isUpcoming:d,isAdmin:h,numStars:E,numMedia:v,filterKeywords:f})=>{const[C,y]=(0,n.useState)(!1),b=(0,n.useCallback)(()=>{Cn?Cn=!1:d||r(e)},[d,r,e]),w=(0,n.useCallback)(()=>i(e),[i,e]),A=(0,n.useCallback)(()=>l(e),[l,e]),N=(0,pn.uh)({onSwipedLeft:(0,n.useCallback)(({event:e})=>{Cn="mouseup"===e.type,y(h)},[h]),onSwipedRight:(0,n.useCallback)(({event:e})=>{Cn="mouseup"===e.type,y(!1)},[]),preventScrollOnSwipe:!0,trackMouse:!0});return n.createElement("div",(0,u.A)({},N,{className:(0,m.A)(fn.container,o&&fn.played,d&&fn.upcoming,c&&fn.starred,C&&fn.expanded,t&&fn.withArtist)}),n.createElement(vn,{toggle:d,className:fn.animateGlow},n.createElement("div",{className:fn.duration},fe(s)),n.createElement("div",{onClick:b,className:fn.primary},n.createElement("div",{className:fn.title},f?.length?n.createElement(mn(),{autoEscape:!0,textToHighlight:a,searchWords:f}):a,h&&v>1&&n.createElement("i",null," ","(",v,")"),t&&n.createElement("div",{className:fn.artist},t)))),n.createElement(gn,{btnWidth:56,isExpanded:C},n.createElement(g,{onClick:A,className:(0,m.A)(fn.btn,fn.star)},n.createElement(vn,{toggle:c,className:fn.animateStar},n.createElement(p.A,{icon:"STAR_FULL"})),n.createElement("div",{className:fn.starCount},E||"")),n.createElement(g,{onClick:w,className:(0,m.A)(fn.btn,fn.info),"data-hide":!0},n.createElement(p.A,{icon:"INFO_OUTLINE"}))))};var bn=a(8870);const wn=e=>{const t=(0,c.j)(),a=(0,c.G)(e=>e.artists.entities),s=(0,c.G)(e=>e.songs.entities),r=(0,c.G)(e=>(0,tn.wd)(e.userStars).starredSongs),l=(0,c.G)(e=>e.starCounts.songs),i=(0,c.G)(e=>e.user.isAdmin),{played:o,upcoming:d,current:m}=(0,c.G)(nn),p=(0,n.useCallback)(e=>t((0,xt.$1)(e)),[t]),h=(0,n.useCallback)(e=>t((0,xe.XH)(e)),[t]),E=(0,n.useCallback)(e=>t((0,bn.D)(e)),[t]);return e.songIds.map(t=>n.createElement(yn,(0,u.A)({},s[t],{artist:e.showArtist?a[s[t].artistId].name:"",filterKeywords:e.filterKeywords,isPlayed:o.includes(t),isUpcoming:d.includes(t)||m===t,isStarred:r.includes(t),isAdmin:i,key:t,numStars:l[t]||0,onSongQueue:p,onSongStarClick:E,onSongInfo:h})))},An="ZQ1vJSuEzaXfK5U2mVy3",Nn="Lo0KOIA2KNbjdkAzONWs",Sn="p93wNKEZo5tcFcoqQsLu",Rn="EDIoZvkx8L71cjC29VBS",In="uK9euOQJZqLMy1JCBauJ",kn="b9LqH0GqWQ8WmCaa4ktx",Pn="HZ0_7hegL7xDvnX1Vw9I",Ln="sfB8p0Y7lGZmslY0UxWw",Tn=({artistSongIds:e,filterKeywords:t,isExpanded:a,name:s,onArtistClick:r,starredSongs:l,style:i,upcomingSongs:o})=>{const c=e.some(e=>o.includes(e)),d=e.some(e=>l.includes(e));return n.createElement("div",{style:i},n.createElement("div",{onClick:r,className:(0,m.A)(An,d&&In)},n.createElement("div",{className:Sn},n.createElement(p.A,{icon:"FOLDER"}),a&&n.createElement("div",{className:Rn},n.createElement(p.A,{icon:"CHEVRON_DOWN"})),!a&&n.createElement("div",{className:kn},e.length)),n.createElement(vn,{toggle:c,className:Pn},n.createElement("div",{className:(0,m.A)(Nn,c&&Ln)},t?.length?n.createElement(mn(),{autoEscape:!0,textToHighlight:s,searchWords:t}):s))),a&&n.createElement(wn,{songIds:e,showArtist:!1,filterKeywords:t}))},On=({index:e,style:t,dispatch:a,artists:s,expandedArtists:r})=>{const l=(0,c.G)(e=>e.starCounts.artists),{starredSongs:i}=(0,c.G)(e=>(0,tn.wd)(e.userStars)),{upcoming:o,current:d}=(0,c.G)(nn),u=s.entities[s.result[e]];return d&&o.push(d),n.createElement(Tn,{artistSongIds:u.songIds,isExpanded:r.includes(u.artistId),key:u.artistId,name:u.name,numStars:l[u.artistId]||0,onArtistClick:()=>a((0,w.RH)(u.artistId)),upcomingSongs:o,starredSongs:i,style:t})},Mn=({ui:e})=>{const t=(0,c.j)(),{expandedArtists:a}=(0,c.G)(e=>e.library),s=(0,c.G)(e=>e.library.scrollRow),r=(0,c.G)(an),l=(0,c.G)(e=>e.artists),i=(0,n.useRef)(s),o=(0,n.useRef)(null);(0,n.useEffect)(()=>()=>{t((0,w.AR)(i.current))},[t]);const d=(0,n.useCallback)(e=>{const t=l.result[e];let n=48;return a.includes(t)&&(n+=56*l.entities[t].songIds.length),n},[l,a]),u=(0,n.useCallback)(({startIndex:e})=>{i.current=e},[]),m=(0,n.useCallback)(e=>{const t=r[e];void 0!==t&&o.current&&o.current.scrollToRow({index:t>0?t-1:t,align:"start"})},[r]),p=(0,n.useCallback)(e=>{e&&(o.current=e,i.current&&o.current.scrollToRow({index:i.current,align:"start",behavior:"instant"}))},[]);return 0===l.result.length?null:n.createElement("div",null,n.createElement(ln,{rowComponent:On,rowProps:{dispatch:t,artists:l,expandedArtists:a},rowHeight:d,numRows:l.result.length,onRowsRendered:u,onRef:p,paddingTop:e.headerHeight,paddingRight:30,paddingBottom:e.footerHeight,width:e.innerWidth,height:e.innerHeight}),n.createElement(dn,{onPick:m,height:e.innerHeight-e.headerHeight-e.footerHeight,top:e.headerHeight}))};var Vn=a(54638);const zn=e=>e.artists,_n=e=>e.songs,xn=e=>e.library.filterStr.trim().toLowerCase(),Hn=e=>e.library.filterStarred,Un=(0,v.Mz)([zn],e=>new Vn.W5(e.result,{keySelector:t=>e.entities[t].name,threshold:.8})),Dn=(0,v.Mz)([_n],e=>new Vn.W5(e.result,{keySelector:t=>e.entities[t].title,threshold:.8})),Gn=(0,v.Mz)([zn,xn,Un],(e,t,a)=>t?a.search(t,{returnMatchData:!0}).map(e=>e.item):e.result),Fn=(0,v.Mz)([_n,xn,Dn],(e,t,a)=>t?a.search(t,{returnMatchData:!0}).map(e=>e.item):e.result),qn=(0,v.Mz)([Gn,Hn,e=>(0,tn.wd)(e.userStars).starredArtists],(e,t,a)=>e.filter(e=>!t||a.includes(e))),Bn=(0,v.Mz)([Fn,Hn,e=>(0,tn.wd)(e.userStars).starredSongs],(e,t,a)=>e.filter(e=>!t||a.includes(e))),Yn=(0,v.Mz)([qn,Bn],(e,t)=>({artistsResult:e,songsResult:t})),jn="FM0NON48tUGevc0Mocok",Wn="CEmdQRH561N9ZZS2sElY",Qn=({index:e,style:t,dispatch:a,artists:s,filterKeywords:r,filterStarred:l,artistsResult:i,songsResult:o,expandedArtistResults:d})=>{const{starredSongs:u}=(0,c.G)(e=>(0,tn.wd)(e.userStars)),{upcoming:m}=(0,c.G)(nn);if(0===e)return n.createElement("div",{key:"artistsHeading",style:t,className:jn},i.length," ",l?"starred ":"",1===i.length?"artist":"artists");if(e>0&&e<i.length+1){const l=i[e-1],o=s.entities[l];return n.createElement(Tn,{artistSongIds:o.songIds,filterKeywords:r,isExpanded:d.includes(l),key:l,name:o.name,numStars:0,onArtistClick:()=>a((0,w.wk)(l)),upcomingSongs:m,starredSongs:u,style:t})}return e===i.length+1?n.createElement("div",{key:"songsHeading",style:t,className:Wn},o.length," ",l?"starred ":"",1===o.length?"song":"songs"):n.createElement("div",{style:t,key:"songs"},n.createElement(wn,{songIds:o,showArtist:!0,filterKeywords:r}))},Kn=({ui:e})=>{const t=(0,c.j)(),a=(0,c.G)(e=>e.artists),s=(0,c.G)(e=>e.library.expandedArtistResults),{filterStr:r,filterStarred:l}=(0,c.G)(e=>e.library),{artistsResult:i,songsResult:o}=(0,c.G)(Yn),d=(0,n.useRef)(null),u=(0,n.useMemo)(()=>r.trim()?r.trim().toLowerCase().split(" "):[],[r]),m=(0,n.useCallback)(e=>{if(0===e)return 24;if(e>0&&e<i.length+1){const t=i[e-1];let n=48;return s.includes(t)&&(n+=56*a.entities[t].songIds.length),n}return e===i.length+1?24:64*o.length},[i,s,a.entities,o.length]),p=(0,n.useCallback)(e=>{e&&(d.current=e)},[]);return n.createElement(ln,{rowComponent:Qn,rowProps:{dispatch:t,artists:a,filterStarred:l,filterKeywords:u,artistsResult:i,songsResult:o,expandedArtistResults:s},rowHeight:m,numRows:i.length+3,paddingTop:e.headerHeight,paddingRight:4,paddingBottom:e.footerHeight,height:e.innerHeight,onRef:p})},Jn="l_cLCw9eRNCSyRKgXWS5",Zn="Fog7IKmx1oVfPd8FU407",Xn=e=>n.createElement("div",{className:Jn},n.createElement("div",{className:(0,m.A)(Zn,e.className)},e.children)),$n="Cy2j9ZX2IZrQWobGUi7X",es="dTWtSURLdyh9OV1LTnaC",ts="L3qh5gTBMbZXjFIzwmUI",as="f7Ry7aQoljxI7zOj18tU",ns="jZojmB6JI3Y1bkX6XnDI",ss="EcvP0cnG_tPw2rSbAdHh",rs=()=>n.createElement("div",{className:$n},n.createElement("div",{className:es}),n.createElement("div",{className:(0,m.A)(es,ts)}),n.createElement("div",{className:(0,m.A)(es,as)}),n.createElement("div",{className:(0,m.A)(es,ns)}),n.createElement("div",{className:(0,m.A)(es,ss)})),ls="bhZWQ2xPWPTNIX6C4F3a",is=()=>{const{isAdmin:e}=(0,c.G)(e=>e.user),{isLoading:t,filterStr:a,filterStarred:r}=(0,c.G)(e=>e.library),l=(0,c.G)(e=>e.songs.result),i=(0,c.G)(e=>e.ui),o=!!a.trim().length||r,d=(0,n.useRef)(i.headerHeight),[u,m]=(0,n.useState)(null);return(0,n.useEffect)(()=>{i.headerHeight>d.current&&m(i.headerHeight)},[i.headerHeight,u]),u?n.createElement(n.Fragment,null,!o&&n.createElement(Mn,{ui:i}),o&&n.createElement(Kn,{ui:i}),t&&n.createElement(rs,null),!t&&0===l.length&&n.createElement(Xn,{className:ls},n.createElement("h1",null,"Library Empty"),e&&n.createElement("p",null,n.createElement(s.N_,{to:"/account"},"Add media folders")," ","to get started."))):null};var os=a(54669),cs=a(5668);const ds="wmZzvQLV8SUXBxloByaI",us="OcXId78BLaxBJIqdYIof",ms="umnUSnD73DO3rWOYPZ9K",ps="GacRKdveAPO6_ywV1_ca",hs="ctOyiO7TWxvaj2cMva6s",Es="pCDYhCexaZe_zujCsnng",gs="nDkBZyovKLxzMG7K_3Tg",vs="Wj7Me9sY8G3TTqTAeAaj",fs="oyozFDwcV8GMOumLs906",Cs="PyOIw1JanvSSiLfkRkZt",ys="HEBTYqqhv5BzgHhWH7vd",bs="_LtmdT6l38fSEjxPLZod",ws="SUdDbZdeZwQPymCmhaMA",As="YmwxQ7Vy9kTAPCo00I2U",Ns="tX8eNQUgD77rREuwXWHO",Ss="gh_SYElq5eTJHE5IZynP",Rs="_gt_BEXlOrYwzEmK6sQ8",Is="ENoEOjlwEk0jBI45f4pk",ks="ZRVZZ_1kYEKO36fznW79",Ps="x1y3JtPFnfVcJSd6mKkB",Ls="pXOty7OejiIGXdAxm6PY",Ts=({artist:e,errorMessage:t,isCurrent:a,isErrored:s,isInfoable:r,isMovable:l,isOwner:i,isPlayed:o,isPlaying:d,isRemovable:p,isReplayable:h,isSkippable:E,isStarred:v,isUpcoming:f,onMoveClick:C,onRemoveUpcoming:y,pctPlayed:b,queueId:w,songId:A,title:N,userDateUpdated:S,userDisplayName:R,userId:I,wait:k})=>{const[P,L]=(0,n.useState)(!1),M=(0,n.useRef)(!1),V=(0,c.j)(),z=(0,n.useCallback)(()=>V((0,O.f1)(t)),[V,t]),_=(0,n.useCallback)(()=>V((0,xe.XH)(A)),[V,A]),x=(0,n.useCallback)(()=>{C(w),L(!1)},[C,w]),H=(0,n.useCallback)(()=>{V((0,T.n3)(w)),L(!1)},[V,w]),U=(0,n.useCallback)(()=>{V((0,xt.$1)(A)),L(!1)},[V,A]),D=(0,n.useCallback)(()=>V((0,xt.Ai)({queueId:w})),[V,w]),G=(0,n.useCallback)(()=>V((0,T.Lx)()),[V]),F=(0,n.useCallback)(()=>V((0,bn.D)(A)),[V,A]),q=(0,pn.uh)({onSwipedLeft:(0,n.useCallback)(()=>{L(s||r||p||E)},[s,r,p,E]),onSwipedRight:(0,n.useCallback)(()=>L(!1),[]),preventScrollOnSwipe:!0,trackMouse:!0}),B=(0,os.HZ)(()=>{const e=i?"Remove all your upcoming songs?":`Remove all upcoming songs for "${R}"?`;M.current=!0,confirm(e)&&y(I)},{threshold:700,cancelOnMovement:!0});return n.createElement("div",(0,u.A)({},q,{className:(0,m.A)(ds,a&&Ps,a&&!d&&Ls),style:{"--progress":(a&&b<2?2:b)+"%"}}),n.createElement("div",{className:us},n.createElement("div",{className:(0,m.A)(ps,o&&ms)},n.createElement(cs.A,{userId:I,dateUpdated:S}),n.createElement("div",{className:hs},f&&n.createElement("div",{className:(0,m.A)(Es,i&&bs)},k))),n.createElement("div",{className:(0,m.A)(gs,o&&ms)},n.createElement("div",{className:vs},n.createElement("div",{className:fs},N),n.createElement("div",{className:Cs},e)),n.createElement("div",{className:(0,m.A)(ys,i&&bs)},R)),n.createElement(gn,{btnWidth:56,isExpanded:P,className:ws},s&&n.createElement(g,{className:Ns,icon:"INFO_OUTLINE",onClick:z}),n.createElement(g,{animateClassName:ks,className:(0,m.A)(v&&As),icon:"STAR_FULL",onClick:F}),h&&n.createElement(g,{className:As,"data-hide":!0,icon:"REPLAY",onClick:H}),o&&n.createElement(g,{className:(0,m.A)(Ss,As),"data-hide":!0,icon:"PLUS",onClick:U}),l&&n.createElement(g,{className:(0,m.A)(Rs,As),"data-hide":!0,icon:"MOVE_TOP",onClick:x}),r&&n.createElement(g,{className:As,"data-hide":!0,icon:"INFO_OUTLINE",onClick:_}),p&&n.createElement(g,(0,u.A)({className:Ns,"data-hide":!0,icon:"DELETE",onTouchEnd:e=>{if(M.current)return e.preventDefault(),e.stopPropagation(),void(M.current=!1)},onClick:()=>{M.current?M.current=!1:D()}},B())),E&&n.createElement(g,{className:(0,m.A)(Is,Ns),"data-hide":!0,icon:"PLAY_NEXT",onClick:G}))))},Os=n.memo(Ts);var Ms=a(40400);const Vs="bbUhdC2XhFqBtedX7G5x",zs="oj9sgd1_DuPZvgyJKc_3",_s=e=>{e.addEventListener("animationend",e=>e.currentTarget.classList.remove(Vs)),e.classList.add(Vs),e.style.removeProperty("opacity")},xs=(e,t,a)=>{e.addEventListener("animationend",a),e.classList.add(zs)},Hs=(e,t)=>t===e,Us=({queueItems:e})=>{const t=(0,c.G)(e=>e.ui.headerHeight),a=n.Children.map(e,e=>n.createElement(Ms.lf,{flipId:e.key,key:e.key,onAppear:_s,onExit:xs,shouldFlip:Hs,translate:!0},n.createElement("div",null,e)));return n.createElement(Ms.ZI,{applyTransformOrigin:!1,decisionData:t,flipKey:e},a)},Ds=()=>{const e=(0,c.G)(e=>e.artists),{errorMessage:t,isAtQueueEnd:a,isErrored:s,isPlaying:r,position:l,queueId:i}=(0,c.G)(e=>e.status),o=(0,c.G)(y.A),d=(0,c.G)(C.A),m=(0,c.G)(e=>e.songs),p=(0,c.G)(e=>(0,tn.wd)(e.userStars).starredSongs),h=(0,c.G)(e=>e.user),E=(0,c.G)(b),g=(0,c.j)(),v=(0,n.useCallback)(e=>{const t=d.entities[e].userId;let a=i;for(let e=d.result.indexOf(i);e>=0;e--)if(d.entities[d.result[e]].userId===t){a=d.result[e];break}g((0,xt.Pe)({queueId:e,prevQueueId:a}))},[g,i,d.entities,d.result]),f=(0,n.useCallback)(e=>{g((0,xt.t2)(e))},[g]),w=d.result.map(c=>{const g=d.entities[c],C=m.entities[g.songId].duration,y=c===i&&!a,b=c!==i&&!o.includes(c),w=g.userId===h.userId;return n.createElement(Os,(0,u.A)({},g,{artist:e.entities[m.entities[g.songId].artistId].name,errorMessage:y&&t?t:"",isCurrent:y,key:c,isErrored:y&&s,isInfoable:h.isAdmin,isMovable:b&&(w||h.isAdmin),isOwner:w,isPlayed:!b&&!y,isPlaying:y&&r,isRemovable:b&&(w||h.isAdmin),isReplayable:(!b||y)&&h.isAdmin,isSkippable:y&&(w||h.isAdmin),isStarred:p.includes(g.songId),isUpcoming:b,pctPlayed:y?l/C*100:0,title:m.entities[g.songId].title,wait:Ce(E[c],!0),onMoveClick:v,onRemoveUpcoming:f}))});return n.createElement(Us,{queueItems:w})},Gs="SF0X5MbNRNL3euuIjCwB",Fs=()=>{const{innerWidth:e,innerHeight:t,headerHeight:a,footerHeight:r}=(0,c.G)(e=>e.ui),l=(0,c.G)(e=>!!e.user.roomId),i=(0,c.G)(e=>(0,tn.wd)(e.queue).isLoading),o=(0,c.G)(C.A),d=(0,c.G)(e=>e.status.queueId),u=(0,n.useRef)(null);return(0,n.useEffect)(()=>{if(u.current){const e=o.result.indexOf(d);u.current.scrollTop=92*e}},[]),n.createElement("div",{className:Gs,ref:u,style:{paddingTop:a,paddingBottom:r,width:e,height:t}},!l&&n.createElement(Xn,null,n.createElement("h1",null,"Get a Room!"),n.createElement("p",null,n.createElement(s.N_,{to:"/account"},"Sign in to a room")," ","to start queueing songs.")),i&&n.createElement(rs,null),!i&&0===o.result.length&&n.createElement(Xn,null,n.createElement("h1",null,"Queue Empty"),n.createElement("p",null,"Tap a song in the"," ",n.createElement(s.N_,{to:"/library"},"library")," ","to queue it.")),n.createElement(Ds,null))},qs=n.lazy(()=>Promise.all([a.e(447),a.e(958)]).then(a.bind(a,13958))),Bs=()=>n.createElement(s.BV,null,n.createElement(s.qh,{path:"/account",element:n.createElement(en,null)}),n.createElement(s.qh,{path:"/library",element:n.createElement(Ys,{path:"/library",redirectTo:"/account"},n.createElement(is,null))}),n.createElement(s.qh,{path:"/queue",element:n.createElement(Ys,{path:"/queue",redirectTo:"/account"},n.createElement(Fs,null))}),n.createElement(s.qh,{path:"/player",element:n.createElement(Ys,{path:"/player",redirectTo:"/account"},n.createElement(qs,null))}),n.createElement(s.qh,{path:"/",element:n.createElement(s.C5,{to:{pathname:"/library",search:window.location.search},replace:!0})})),Ys=({children:e,path:t,redirectTo:a})=>{const{isAdmin:r,userId:l}=(0,c.G)(e=>e.user),i=(0,s.zy)();if("/player"===t&&!r)return n.createElement(s.C5,{to:"/",replace:!0});if(null===l){const e=new URLSearchParams(i.search);return e.set("redirect",t),n.createElement(s.C5,{to:a+"?"+e.toString(),replace:!0})}return e},js=()=>{const e=(0,s.RQ)("/player"),t=(0,c.j)(),a=(0,n.useRef)(null),r=(0,n.useRef)(null);(0,d.A)({onResize:({height:e})=>{t((0,O.DP)(e))},ref:a}),(0,d.A)({onResize:({height:e})=>{t((0,O.NJ)(e))},ref:r});const l=(0,c.G)(e=>e.ui),i=(0,n.useCallback)(()=>t((0,O.T6)()),[t]);return n.createElement(n.Fragment,null,n.createElement(Te,{ref:a}),n.createElement(Bs,null),!e&&n.createElement(_e,{ref:r}),n.createElement(Fe,null),l.isErrored&&n.createElement(J,{title:"Oops...",onClose:i,buttons:n.createElement(g,{variant:"primary",onClick:i},"OK")},n.createElement("p",{style:{WebkitUserSelect:"text",userSelect:"text"}},l.errorMessage)))},Ws=()=>n.createElement(r.Kq,{store:i.A},n.createElement(l.Q,{loading:n.createElement(rs,null),persistor:o.A.get()},n.createElement(n.Suspense,{fallback:n.createElement(rs,null)},n.createElement(js,null)))),Qs=new URL(document.baseURI).pathname,Ks=(0,s.Ys)([{path:"*",element:n.createElement(Ws,null)}],{basename:Qs})},88146:(e,t,a)=>{a.d(t,{Ay:()=>p,Lx:()=>i,MP:()=>u,ag:()=>m,cd:()=>r,n3:()=>d,wr:()=>l});var n=a(15452),s=a(42730);const r=(0,n.VP)(s.K9),l=(0,n.VP)(s.qd),i=(0,n.VP)(s.Bw),o=(0,n.VP)(s.PQ),c=(0,n.VP)(s.cP),d=(0,n.VP)(s.F7,e=>({payload:{queueId:e}})),u=(0,n.VP)(s.gw,e=>({payload:e,meta:{throttle:{wait:200,leading:!1}}})),m=(0,n.VP)(s.YM,e=>({payload:e,meta:{throttle:{wait:200,leading:!0}}})),p=(0,n.vy)({cdgAlpha:0,cdgSize:.8,errorMessage:"",historyJSON:"[]",isAtQueueEnd:!1,isErrored:!1,isPlayerPresent:!1,isPlaying:!1,isVideoKeyingEnabled:!1,isWebGLSupported:!1,mediaType:null,mp4Alpha:1,nextUserId:null,position:0,queueId:-1,visualizer:{},volume:1},e=>{e.addCase(c,e=>{e.isPlayerPresent=!1}).addCase(o,(e,{payload:t})=>({...e,...t,isPlayerPresent:!0}))})},89853:(e,t,a)=>{a.d(t,{Ay:()=>d,XH:()=>i,Zi:()=>c,ks:()=>o});var n=a(15452),s=a(77170),r=a(42730);const l=new s.A,i=(0,n.zD)(r.Pg,async e=>await l.get(`song/${e}`)),o=(0,n.VP)(r.kW),c=(0,n.zD)(r.Ah,async({songId:e,mediaId:t,isPreferred:a},n)=>{await l.request(a?"PUT":"DELETE",`media/${t}/prefer`),n.dispatch(i(e))}),d=(0,n.vy)({isLoading:!1,isVisible:!1,songId:null,media:{result:[],entities:{}}},e=>{e.addCase(i.pending,(e,{meta:t})=>{e.isLoading=!0,e.isVisible=!0,e.songId=t.arg}).addCase(i.fulfilled,(e,{payload:t})=>{e.isLoading=!1,e.media=t}).addCase(i.rejected,e=>{e.isLoading=!1,e.isVisible=!1}).addCase(o,e=>{e.isVisible=!1})})},95099:(e,t,a)=>{var n=a(96540),s=a(5338),r=a(13937),l=a(85555),i=a(49905),o=a(87161),c=a(77759);a(32681).A.init(l.A,()=>{null!==l.A.getState().user.userId&&(l.A.dispatch((0,c.cH)()),i.A.open())}),i.A.on("reconnect_attempt",()=>{l.A.dispatch((0,c.cH)())}),(0,s.H)(document.getElementById("root")).render(n.createElement(n.StrictMode,null,n.createElement(r.pg,{router:o.A})))},99996:(e,t,a)=>{a.d(t,{Ah:()=>c,Ay:()=>v,I8:()=>i,PA:()=>h,dJ:()=>p,fm:()=>g,gL:()=>o,mN:()=>E,yx:()=>m});var n=a(15452),s=a(42730);const r=new(a(77170).A)("prefs"),l=(0,n.VP)(s.T_),i=(0,n.VP)(s.Ac),o=(0,n.VP)(s.NT),c=(0,n.VP)(s.Xw),d=(0,n.VP)(s.kY),u=(0,n.VP)(s.$W),m=(0,n.zD)(s.BD,async({pathId:e,data:t},a)=>{const n=await r.put(`/path/${e}`,{body:t});a.dispatch(o(n))}),p=(0,n.zD)(s.J$,async(e,t)=>{const a=await r.get("");return a.isFirstRun&&null!==t.getState().user.userId&&t.dispatch(l()),a}),h=(0,n.zD)(s.gv,async e=>await r.get(`/path/${e}/scan`)),E=(0,n.zD)(s.gv,async()=>await r.get("/paths/scan")),g=(0,n.zD)(s.sr,async()=>await r.get("/paths/scan/stop")),v=(0,n.vy)({isScanning:!1,isReplayGainEnabled:!1,paths:{result:[],entities:{}},roles:{result:[],entities:{}},scannerPct:0,scannerText:""},e=>{e.addCase(p.fulfilled,(e,{payload:t})=>({...e,...t})).addCase(o,(e,{payload:t})=>({...e,...t})).addCase(d,(e,{payload:t})=>({...e,...t})).addCase(u,(e,{payload:t})=>({...e,isScanning:t.isScanning,scannerPct:t.pct,scannerText:t.text}))})}},l={};function i(e){var t=l[e];if(void 0!==t)return t.exports;var a=l[e]={exports:{}};return r[e].call(a.exports,a,a.exports,i),a.exports}i.m=r,e=[],i.O=(t,a,n,s)=>{if(!a){var r=1/0;for(d=0;d<e.length;d++){for(var[a,n,s]=e[d],l=!0,o=0;o<a.length;o++)(!1&s||r>=s)&&Object.keys(i.O).every(e=>i.O[e](a[o]))?a.splice(o--,1):(l=!1,s<r&&(r=s));if(l){e.splice(d--,1);var c=n();void 0!==c&&(t=c)}}return t}s=s||0;for(var d=e.length;d>0&&e[d-1][2]>s;d--)e[d]=e[d-1];e[d]=[a,n,s]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},a=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,i.t=function(e,n){if(1&n&&(e=this(e)),8&n)return e;if("object"==typeof e&&e){if(4&n&&e.__esModule)return e;if(16&n&&"function"==typeof e.then)return e}var s=Object.create(null);i.r(s);var r={};t=t||[null,a({}),a([]),a(a)];for(var l=2&n&&e;("object"==typeof l||"function"==typeof l)&&!~t.indexOf(l);l=a(l))Object.getOwnPropertyNames(l).forEach(t=>r[t]=()=>e[t]);return r.default=()=>e,i.d(s,r),s},i.d=(e,t)=>{for(var a in t)i.o(t,a)&&!i.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},i.f={},i.e=e=>Promise.all(Object.keys(i.f).reduce((t,a)=>(i.f[a](e,t),t),[])),i.u=e=>e+"."+i.h()+".js",i.miniCssF=e=>e+"."+i.h()+".css",i.h=()=>"a51d7d3f87c474adad54",i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n={},s="karaoke-eternal:",i.l=(e,t,a,r)=>{if(n[e])n[e].push(t);else{var l,o;if(void 0!==a)for(var c=document.getElementsByTagName("script"),d=0;d<c.length;d++){var u=c[d];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==s+a){l=u;break}}l||(o=!0,(l=document.createElement("script")).charset="utf-8",i.nc&&l.setAttribute("nonce",i.nc),l.setAttribute("data-webpack",s+a),l.src=e),n[e]=[t];var m=(t,a)=>{l.onerror=l.onload=null,clearTimeout(p);var s=n[e];if(delete n[e],l.parentNode&&l.parentNode.removeChild(l),s&&s.forEach(e=>e(a)),t)return t(a)},p=setTimeout(m.bind(null,void 0,{type:"timeout",target:l}),12e4);l.onerror=m.bind(null,l.onerror),l.onload=m.bind(null,l.onload),o&&document.head.appendChild(l)}},i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;i.g.importScripts&&(e=i.g.location+"");var t=i.g.document;if(!e&&t&&(t.currentScript&&"SCRIPT"===t.currentScript.tagName.toUpperCase()&&(e=t.currentScript.src),!e)){var a=t.getElementsByTagName("script");if(a.length)for(var n=a.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=a[n--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),i.p=e})(),(()=>{if("undefined"!=typeof document){var e=e=>new Promise((t,a)=>{var n=i.miniCssF(e),s=i.p+n;if(((e,t)=>{for(var a=document.getElementsByTagName("link"),n=0;n<a.length;n++){var s=(l=a[n]).getAttribute("data-href")||l.getAttribute("href");if("stylesheet"===l.rel&&(s===e||s===t))return l}var r=document.getElementsByTagName("style");for(n=0;n<r.length;n++){var l;if((s=(l=r[n]).getAttribute("data-href"))===e||s===t)return l}})(n,s))return t();((e,t,a,n,s)=>{var r=document.createElement("link");r.rel="stylesheet",r.type="text/css",i.nc&&(r.nonce=i.nc),r.onerror=r.onload=a=>{if(r.onerror=r.onload=null,"load"===a.type)n();else{var l=a&&a.type,i=a&&a.target&&a.target.href||t,o=new Error("Loading CSS chunk "+e+" failed.\n("+l+": "+i+")");o.name="ChunkLoadError",o.code="CSS_CHUNK_LOAD_FAILED",o.type=l,o.request=i,r.parentNode&&r.parentNode.removeChild(r),s(o)}},r.href=t,a?a.parentNode.insertBefore(r,a.nextSibling):document.head.appendChild(r)})(e,s,null,t,a)}),t={792:0};i.f.miniCss=(a,n)=>{t[a]?n.push(t[a]):0!==t[a]&&{851:1,958:1}[a]&&n.push(t[a]=e(a).then(()=>{t[a]=0},e=>{throw delete t[a],e}))}}})(),(()=>{var e={792:0};i.f.j=(t,a)=>{var n=i.o(e,t)?e[t]:void 0;if(0!==n)if(n)a.push(n[2]);else{var s=new Promise((a,s)=>n=e[t]=[a,s]);a.push(n[2]=s);var r=i.p+i.u(t),l=new Error;i.l(r,a=>{if(i.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var s=a&&("load"===a.type?"missing":a.type),r=a&&a.target&&a.target.src;l.message="Loading chunk "+t+" failed.\n("+s+": "+r+")",l.name="ChunkLoadError",l.type=s,l.request=r,n[1](l)}},"chunk-"+t,t)}},i.O.j=t=>0===e[t];var t=(t,a)=>{var n,s,[r,l,o]=a,c=0;if(r.some(t=>0!==e[t])){for(n in l)i.o(l,n)&&(i.m[n]=l[n]);if(o)var d=o(i)}for(t&&t(a);c<r.length;c++)s=r[c],i.o(e,s)&&e[s]&&e[s][0](),e[s]=0;return i.O(d)},a=self.webpackChunkkaraoke_eternal=self.webpackChunkkaraoke_eternal||[];a.forEach(t.bind(null,0)),a.push=t.bind(null,a.push.bind(a))})();var o=i.O(void 0,[718],()=>i(95099));o=i.O(o)})();
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import sql from 'sqlate';
|
|
2
|
+
import Database from '../lib/Database.js';
|
|
3
|
+
import getLogger from '../lib/Log.js';
|
|
4
|
+
import { performance } from 'perf_hooks';
|
|
5
|
+
import Media from '../Media/Media.js';
|
|
6
|
+
const log = getLogger('Library');
|
|
7
|
+
const { db } = Database;
|
|
8
|
+
class Library {
|
|
9
|
+
static cache = { version: null };
|
|
10
|
+
static starCountsCache = { version: null };
|
|
11
|
+
/**
|
|
12
|
+
* Get artists and songs in a format suitable for sending to clients.
|
|
13
|
+
* Should not include songs or artists for which there are no media.
|
|
14
|
+
*
|
|
15
|
+
* @return {Promise} Object with artists and songs normalized
|
|
16
|
+
*/
|
|
17
|
+
static async get() {
|
|
18
|
+
// already cached?
|
|
19
|
+
if (this.cache.version)
|
|
20
|
+
return this.cache;
|
|
21
|
+
const startTime = performance.now();
|
|
22
|
+
const SongIdsByArtist = {};
|
|
23
|
+
const artists = {
|
|
24
|
+
result: [],
|
|
25
|
+
entities: {},
|
|
26
|
+
};
|
|
27
|
+
const songs = {
|
|
28
|
+
result: [],
|
|
29
|
+
entities: {},
|
|
30
|
+
};
|
|
31
|
+
// query #1: songs
|
|
32
|
+
{
|
|
33
|
+
const query = sql `
|
|
34
|
+
SELECT duration, songs.artistId AS artistId, songs.songId AS songId, songs.title AS title,
|
|
35
|
+
MAX(isPreferred) AS isPreferred, COUNT(DISTINCT media.mediaId) AS numMedia
|
|
36
|
+
FROM media
|
|
37
|
+
INNER JOIN songs USING (songId)
|
|
38
|
+
INNER JOIN paths USING (pathId)
|
|
39
|
+
GROUP BY songId
|
|
40
|
+
ORDER BY songs.titleNorm, paths.priority ASC
|
|
41
|
+
`;
|
|
42
|
+
const rows = await db.all(String(query), query.parameters);
|
|
43
|
+
for (const row of rows) {
|
|
44
|
+
delete row.isPreferred;
|
|
45
|
+
songs.entities[row.songId] = row;
|
|
46
|
+
songs.result.push(row.songId);
|
|
47
|
+
// add to artist's songIds
|
|
48
|
+
if (typeof SongIdsByArtist[row.artistId] === 'undefined') {
|
|
49
|
+
SongIdsByArtist[row.artistId] = [];
|
|
50
|
+
}
|
|
51
|
+
SongIdsByArtist[row.artistId].push(row.songId);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// query #2: artists
|
|
55
|
+
{
|
|
56
|
+
const query = sql `
|
|
57
|
+
SELECT artistId, name
|
|
58
|
+
FROM artists
|
|
59
|
+
ORDER BY nameNorm ASC
|
|
60
|
+
`;
|
|
61
|
+
const rows = await db.all(String(query), query.parameters);
|
|
62
|
+
for (const row of rows) {
|
|
63
|
+
if (SongIdsByArtist[row.artistId]) {
|
|
64
|
+
artists.result.push(row.artistId);
|
|
65
|
+
artists.entities[row.artistId] = row;
|
|
66
|
+
artists.entities[row.artistId].songIds = SongIdsByArtist[row.artistId];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
log.info('built library cache in %sms', (performance.now() - startTime).toFixed(3));
|
|
71
|
+
// cache result
|
|
72
|
+
this.cache = {
|
|
73
|
+
artists,
|
|
74
|
+
songs,
|
|
75
|
+
version: Date.now(),
|
|
76
|
+
};
|
|
77
|
+
return this.cache;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get single song in format similar to get()
|
|
81
|
+
*
|
|
82
|
+
* @param {number} songId
|
|
83
|
+
* @return {Promise} normalized media entries
|
|
84
|
+
*/
|
|
85
|
+
static async getSong(songId) {
|
|
86
|
+
const { result, entities } = await Media.search({ songId });
|
|
87
|
+
if (!result.length)
|
|
88
|
+
return {};
|
|
89
|
+
// should be in order of path priority...
|
|
90
|
+
let media = entities[result[0]];
|
|
91
|
+
// ...but are any preferred?
|
|
92
|
+
for (const mediaId of result) {
|
|
93
|
+
if (entities[mediaId].isPreferred)
|
|
94
|
+
media = entities[mediaId];
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
[songId]: {
|
|
98
|
+
artistId: media.artistId,
|
|
99
|
+
duration: media.duration,
|
|
100
|
+
songId: media.songId,
|
|
101
|
+
title: media.title,
|
|
102
|
+
numMedia: result.length,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Matches or creates artist and song
|
|
108
|
+
*
|
|
109
|
+
* @param {object} parsed The object returned from MetaParser
|
|
110
|
+
* @return {object} { artistId, songId }
|
|
111
|
+
*/
|
|
112
|
+
static async matchSong(parsed) {
|
|
113
|
+
const match = {};
|
|
114
|
+
// match artist
|
|
115
|
+
{
|
|
116
|
+
const query = sql `
|
|
117
|
+
SELECT *
|
|
118
|
+
FROM artists
|
|
119
|
+
WHERE nameNorm = ${parsed.artistNorm}
|
|
120
|
+
`;
|
|
121
|
+
const row = await db.get(String(query), query.parameters);
|
|
122
|
+
if (row) {
|
|
123
|
+
log.debug('matched artist: %s', row.name);
|
|
124
|
+
match.artistId = row.artistId;
|
|
125
|
+
match.artist = row.name;
|
|
126
|
+
match.artistNorm = row.nameNorm;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
log.debug('new artist: %s', parsed.artist);
|
|
130
|
+
const fields = new Map();
|
|
131
|
+
fields.set('name', parsed.artist);
|
|
132
|
+
fields.set('nameNorm', parsed.artistNorm);
|
|
133
|
+
const query = sql `
|
|
134
|
+
INSERT INTO artists ${sql.tuple(Array.from(fields.keys()).map(sql.column))}
|
|
135
|
+
VALUES ${sql.tuple(Array.from(fields.values()))}
|
|
136
|
+
`;
|
|
137
|
+
const res = await db.run(String(query), query.parameters);
|
|
138
|
+
if (!Number.isInteger(res.lastID)) {
|
|
139
|
+
throw new Error('invalid artistId after insert');
|
|
140
|
+
}
|
|
141
|
+
match.artistId = res.lastID;
|
|
142
|
+
match.artist = parsed.artist;
|
|
143
|
+
match.artistNorm = parsed.artistNorm;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// match song title
|
|
147
|
+
{
|
|
148
|
+
const query = sql `
|
|
149
|
+
SELECT *
|
|
150
|
+
FROM songs
|
|
151
|
+
WHERE artistId = ${match.artistId} AND titleNorm = ${parsed.titleNorm}
|
|
152
|
+
`;
|
|
153
|
+
const row = await db.get(String(query), query.parameters);
|
|
154
|
+
if (row) {
|
|
155
|
+
log.debug('matched song: %s', row.title);
|
|
156
|
+
match.songId = row.songId;
|
|
157
|
+
match.title = row.title;
|
|
158
|
+
match.titleNorm = row.titleNorm;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
log.debug('new song: %s', parsed.title);
|
|
162
|
+
const fields = new Map();
|
|
163
|
+
fields.set('artistId', match.artistId);
|
|
164
|
+
fields.set('title', parsed.title);
|
|
165
|
+
fields.set('titleNorm', parsed.titleNorm);
|
|
166
|
+
const query = sql `
|
|
167
|
+
INSERT INTO songs ${sql.tuple(Array.from(fields.keys()).map(sql.column))}
|
|
168
|
+
VALUES ${sql.tuple(Array.from(fields.values()))}
|
|
169
|
+
`;
|
|
170
|
+
const res = await db.run(String(query), query.parameters);
|
|
171
|
+
if (!Number.isInteger(res.lastID)) {
|
|
172
|
+
throw new Error('invalid songId after insert');
|
|
173
|
+
}
|
|
174
|
+
match.songId = res.lastID;
|
|
175
|
+
match.title = parsed.title;
|
|
176
|
+
match.titleNorm = parsed.titleNorm;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return match;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Gets a user's starred artists and songs
|
|
183
|
+
*
|
|
184
|
+
* @param {Number} userId
|
|
185
|
+
* @return {Object}
|
|
186
|
+
*/
|
|
187
|
+
static async getUserStars(userId) {
|
|
188
|
+
let starredArtists, starredSongs;
|
|
189
|
+
// get starred artists
|
|
190
|
+
{
|
|
191
|
+
const query = sql `
|
|
192
|
+
SELECT artistId
|
|
193
|
+
FROM artistStars
|
|
194
|
+
WHERE userId = ${userId}
|
|
195
|
+
`;
|
|
196
|
+
const rows = await db.all(String(query), query.parameters);
|
|
197
|
+
starredArtists = rows.map(row => row.artistId);
|
|
198
|
+
}
|
|
199
|
+
// get starred songs
|
|
200
|
+
{
|
|
201
|
+
const query = sql `
|
|
202
|
+
SELECT songId
|
|
203
|
+
FROM songStars
|
|
204
|
+
WHERE userId = ${userId}
|
|
205
|
+
`;
|
|
206
|
+
const rows = await db.all(String(query), query.parameters);
|
|
207
|
+
starredSongs = rows.map(row => row.songId);
|
|
208
|
+
}
|
|
209
|
+
return { starredArtists, starredSongs };
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Add a user's star to a song
|
|
213
|
+
*
|
|
214
|
+
* @param {Number} songId
|
|
215
|
+
* @param {Number} userId
|
|
216
|
+
* @return {Promise} Number of rows affected
|
|
217
|
+
*/
|
|
218
|
+
static async starSong(songId, userId) {
|
|
219
|
+
const fields = new Map();
|
|
220
|
+
fields.set('songId', songId);
|
|
221
|
+
fields.set('userId', userId);
|
|
222
|
+
const query = sql `
|
|
223
|
+
INSERT OR IGNORE INTO songStars ${sql.tuple(Array.from(fields.keys()).map(sql.column))}
|
|
224
|
+
VALUES ${sql.tuple(Array.from(fields.values()))}
|
|
225
|
+
`;
|
|
226
|
+
const res = await db.run(String(query), query.parameters);
|
|
227
|
+
if (res.changes) {
|
|
228
|
+
// invalidate cache
|
|
229
|
+
this.starCountsCache.version = null;
|
|
230
|
+
}
|
|
231
|
+
return res.changes;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Remove a user's star from a song
|
|
235
|
+
*
|
|
236
|
+
* @param {Number} songId
|
|
237
|
+
* @param {Number} userId
|
|
238
|
+
* @return {Promise} Number of rows affected
|
|
239
|
+
*/
|
|
240
|
+
static async unstarSong(songId, userId) {
|
|
241
|
+
const query = sql `
|
|
242
|
+
DELETE FROM songStars
|
|
243
|
+
WHERE userId = ${userId} AND songId = ${songId}
|
|
244
|
+
`;
|
|
245
|
+
const res = await db.run(String(query), query.parameters);
|
|
246
|
+
if (res.changes) {
|
|
247
|
+
// invalidate cache
|
|
248
|
+
this.starCountsCache.version = null;
|
|
249
|
+
}
|
|
250
|
+
return res.changes;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Gets artist and song star counts
|
|
254
|
+
*
|
|
255
|
+
* @return {Object}
|
|
256
|
+
*/
|
|
257
|
+
static async getStarCounts() {
|
|
258
|
+
// already cached?
|
|
259
|
+
if (this.starCountsCache.version)
|
|
260
|
+
return this.starCountsCache;
|
|
261
|
+
const startTime = performance.now();
|
|
262
|
+
const artists = {};
|
|
263
|
+
const songs = {};
|
|
264
|
+
// get artist star counts
|
|
265
|
+
{
|
|
266
|
+
const query = sql `
|
|
267
|
+
SELECT artistId, COUNT(userId) AS count
|
|
268
|
+
FROM artistStars
|
|
269
|
+
GROUP BY artistId
|
|
270
|
+
`;
|
|
271
|
+
const rows = await db.all(String(query), query.parameters);
|
|
272
|
+
rows.forEach((row) => {
|
|
273
|
+
artists[row.artistId] = row.count;
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
// get song star counts
|
|
277
|
+
{
|
|
278
|
+
const query = sql `
|
|
279
|
+
SELECT songId, COUNT(userId) AS count
|
|
280
|
+
FROM songStars
|
|
281
|
+
GROUP BY songId
|
|
282
|
+
`;
|
|
283
|
+
const rows = await db.all(String(query), query.parameters);
|
|
284
|
+
rows.forEach((row) => {
|
|
285
|
+
songs[row.songId] = row.count;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
log.info('built star count cache in %sms', (performance.now() - startTime).toFixed(3));
|
|
289
|
+
this.starCountsCache = {
|
|
290
|
+
artists,
|
|
291
|
+
songs,
|
|
292
|
+
version: Date.now(),
|
|
293
|
+
};
|
|
294
|
+
return this.starCountsCache;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
export default Library;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Library from './Library.js';
|
|
2
|
+
import throttle from '@jcoreio/async-throttle';
|
|
3
|
+
import { SCANNER_WORKER_STATUS, LIBRARY_MATCH_SONG } from '../../shared/actionTypes.js';
|
|
4
|
+
/**
|
|
5
|
+
* IPC action handlers
|
|
6
|
+
*/
|
|
7
|
+
export default function (io) {
|
|
8
|
+
const emit = throttle(action => io.emit('action', action), 1000);
|
|
9
|
+
return {
|
|
10
|
+
[LIBRARY_MATCH_SONG]: async ({ payload }) => Library.matchSong(payload),
|
|
11
|
+
[SCANNER_WORKER_STATUS]: action => emit(action),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import KoaRouter from '@koa/router';
|
|
2
|
+
import Media from '../Media/Media.js';
|
|
3
|
+
const router = new KoaRouter({ prefix: '/api' });
|
|
4
|
+
// lists underlying media for a given song
|
|
5
|
+
router.get('/song/:songId', async (ctx) => {
|
|
6
|
+
// must be admin
|
|
7
|
+
if (!ctx.user.isAdmin) {
|
|
8
|
+
ctx.throw(401);
|
|
9
|
+
}
|
|
10
|
+
const songId = parseInt(ctx.params.songId, 10);
|
|
11
|
+
if (Number.isNaN(songId)) {
|
|
12
|
+
ctx.throw(401, 'Invalid songId');
|
|
13
|
+
}
|
|
14
|
+
const res = await Media.search({ songId });
|
|
15
|
+
if (!res.result.length) {
|
|
16
|
+
ctx.throw(404);
|
|
17
|
+
}
|
|
18
|
+
ctx.body = res;
|
|
19
|
+
});
|
|
20
|
+
export default router;
|