diff --git a/.config/spicetify/.github/README.md b/.config/spicetify/.github/README.md deleted file mode 100644 index affa9d51..00000000 --- a/.config/spicetify/.github/README.md +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/.config/spicetify/.github/title.png b/.config/spicetify/.github/title.png deleted file mode 100644 index c36a790b..00000000 Binary files a/.config/spicetify/.github/title.png and /dev/null differ diff --git a/.config/spicetify/CustomApps/better-local-files/README.md b/.config/spicetify/CustomApps/better-local-files/README.md new file mode 100644 index 00000000..672d3dd6 --- /dev/null +++ b/.config/spicetify/CustomApps/better-local-files/README.md @@ -0,0 +1,84 @@ +# Better local files + +View your local songs, albums and artists. + +![preview](https://raw.githubusercontent.com/Pithaya/spicetify-apps/main/custom-apps/better-local-files/preview.png) + +> **Note** +> There is a specific way to format artists so that the custom app recognizes them correctly: see [limitations](#limitations). +> +> If you have an issue with albums with the same name being merged, see [Albums with the same name from different artists](#albums-with-the-same-name-from-different-artists). + +## Features + +- Tracks, albums, and artists views +- Supports filtering and sorting +- Supports all languages available in Spotify. + +![preview](https://raw.githubusercontent.com/Pithaya/spicetify-apps/main/custom-apps/better-local-files/docs/tracks.png) + +## Installation + +1. Run `spicetify config-dir` to open the spicetify folder. +2. Go to the `CustomApps` folder. +3. Create a `better-local-files` folder. +4. Download the custom app files as a zip from [here](https://github.com/Pithaya/spicetify-apps-dist/archive/refs/heads/dist/better-local-files.zip). +5. Extract the zip and put the files inside the folder you created in step 3. + +Then, run the following commands: + +```sh +spicetify config custom_apps better-local-files +spicetify apply +``` + +## Limitations + +### Song artists + +Spotify doesn't seem to recognize separate artist tags on songs as different artists, and will instead use the concatenation of the artist's names. So a track with artists 'A' and 'B' will be considered as having a single artist: 'A, B'. +The custom app parses these strings with the following delimiters: ', ' and '; '. You should use this format to get artists recognized properly. +**Note**: This means that artists with the same name will be **considered the same artist**. + +### Album artists + +Album artists tags are not recognized, so the custom app will use the list of all artists from the album's tracks as the album's artists. + +### Artist images + +As artist images are not available, the artist's first album's image will be used instead. + +## Albums with the same name from different artists + +To identify an album, Spotify uses the current track's artist(s) name and the album name. This means that albums with tracks from different artists will be considered separate albums. +To fix this, the custom app groups albums by name. +This means that albums with the same name will be **considered the same album**. + +If you find that you have albums with the same name that are being merged when they shouldn't, you can use the **settings menu** to **rebuild the local album cache**. This will try to group tracks that share the same album name correctly by comparing the album covers. + +Note that for performance reasons this behaviour is **not enabled by default**. If you add new albums that have the same issue later on, you will need to **rebuild the cache manually again**. + +![preview](https://raw.githubusercontent.com/Pithaya/spicetify-apps/main/custom-apps/better-local-files/docs/build-cache.PNG) + +The cache can take some time to be built depending on how many tracks you have and how large the cover images are. + +The **clear album cache** menu item allows you to clear the cache and go back to the default behavior. + +## Upcoming features + +- Artist's album list +- Multi track selection +- Keep search, sort, and scroll information on navigation + +## Uninstall + +1. Run `spicetify config-dir` to open the spicetify folder +2. Go to the `CustomApps` folder +3. Delete the `better-local-files` folder + +Then, run the following commands: + +```sh +spicetify config custom_apps better-local-files- +spicetify apply +``` diff --git a/.config/spicetify/CustomApps/better-local-files/extension.js b/.config/spicetify/CustomApps/better-local-files/extension.js new file mode 100644 index 00000000..26b2b5f6 --- /dev/null +++ b/.config/spicetify/CustomApps/better-local-files/extension.js @@ -0,0 +1 @@ +!async function(){for(;!Spicetify.React||!Spicetify.ReactDOM;)await new Promise(t=>setTimeout(t,10));var t,e,D,a,F,c,U,R,r,$,o,i,n,H,s,J,u,l,g,L,B,K,V,h,f,Y,p,d,W,m,X,q,G,Q,Z,b,tt,et,rt,it,nt,ot,y,v,w,S,st,at;D=Object.create,a=Object.defineProperty,F=Object.getOwnPropertyDescriptor,c=Object.getOwnPropertyNames,U=Object.getPrototypeOf,R=Object.prototype.hasOwnProperty,t={"../../node_modules/pixelmatch/index.js"(t,e){"use strict";var m={threshold:.1,includeAA:!(e.exports=function(r,i,n,o,s,a){if(!b(r)||!b(i)||n&&!b(n))throw new Error("Image data: Uint8Array, Uint8ClampedArray or Buffer expected.");if(r.length!==i.length||n&&n.length!==r.length)throw new Error("Image sizes do not match.");if(r.length!==o*s*4)throw new Error("Image data size does not match width/height.");a=Object.assign({},m,a);var e=o*s,c=new Uint32Array(r.buffer,r.byteOffset,e),u=new Uint32Array(i.buffer,i.byteOffset,e);let l=!0;for(let t=0;th?a.includeAA||!y(r,t,e,o,s,i)&&!y(i,t,e,o,s,r)?(n&&v(n,p,...d<0&&a.diffColorAlt||a.diffColor),f++):n&&!a.diffMask&&v(n,p,...a.aaColor):n&&!a.diffMask&&S(r,p,a.alpha,n)}return f}),alpha:.1,aaColor:[255,255,0],diffColor:[255,0,0],diffColorAlt:null,diffMask:!1};function b(t){return ArrayBuffer.isView(t)&&1===t.constructor.BYTES_PER_ELEMENT}function y(r,i,n,o,t,e){var s=Math.max(i-1,0),a=Math.max(n-1,0),c=Math.min(i+1,o-1),u=Math.min(n+1,t-1),l=4*(n*o+i);let h=i===s||i===c||n===a||n===u?1:0,f=0,p=0,d,m,b,y;for(let e=s;e<=c;e++)for(let t=a;t<=u;t++)if(e!==i||t!==n){var v=w(r,r,l,4*(t*o+e),!0);if(0===v){if(2<++h)return}else vp&&(p=v,b=e,y=t)}return 0!==f&&0!==p&&(g(r,d,m,o,t)&&g(e,d,m,o,t)||g(r,b,y,o,t)&&g(e,b,y,o,t))}function g(r,i,n,o,t){var s=Math.max(i-1,0),a=Math.max(n-1,0),c=Math.min(i+1,o-1),u=Math.min(n+1,t-1),l=4*(n*o+i);let h=i===s||i===c||n===a||n===u?1:0;for(let e=s;e<=c;e++)for(let t=a;t<=u;t++)if(e!==i||t!==n){var f=4*(t*o+e);if(r[l]===r[f]&&r[1+l]===r[1+f]&&r[2+l]===r[2+f]&&r[3+l]===r[3+f]&&h++,2=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,o=t=>{if("string"!=typeof t)throw new TypeError("Invalid argument expected string");var e=t.match($);if(e)return e.shift(),e;throw new Error(`Invalid argument not valid semver ('${t}' received)`)},i=t=>"*"===t||"x"===t||"X"===t,n=t=>{var e=parseInt(t,10);return isNaN(e)?t:e},H=(t,e)=>{return i(t)||i(e)?0:([t,e]=(t=n(t),e=n(e),typeof t!=typeof e?[String(t),String(e)]:[t,e]),e{for(let t=0;t{var i=r;if("string"!=typeof i)throw new TypeError("Invalid operator type, expected string but got "+typeof i);if(-1===l.indexOf(i))throw new Error("Invalid operator, expected one of "+l.join("|"));i=e,e=o(e=t),i=o(i),t=e.pop(),n=i.pop();var n,i=0!==(e=s(e,i))?e:t&&n?s(t.split("."),n.split(".")):t||n?t?-1:1:0;return u[r].includes(i)},u={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1],"!=":[-1,1]},l=Object.keys(u),g=class{constructor(t,e,r){this.uri=t,this.name=e,this.image=r,this.artists=[],this.discs=new Map}artists;discs;getTracks(){const r=[];return this.discs.forEach((t,e)=>r.push(...t)),r}getDuration(){return this.getTracks().map(t=>t.duration).reduce((t,e)=>t+e)}},L=class{constructor(t,e){this.name=t,this.image=e,this.uri="spotify:local:"+t}uri},B=class{constructor(t,e,r){this.localTrack=t,this.album=e,this.artists=r}get addedAt(){return this.localTrack.addedAt}get uri(){return this.localTrack.uri}get name(){return this.localTrack.name}get duration(){return this.localTrack.duration.milliseconds}get discNumber(){return this.localTrack.discNumber}get trackNumber(){return this.localTrack.trackNumber}},K=((t,e,r)=>{r=null!=t?D(U(t)):{};var i=!e&&t&&t.__esModule?r:a(r,"default",{value:t,enumerable:!0}),n=t,o=void 0,s=void 0;if(n&&"object"==typeof n||"function"==typeof n)for(let t of c(n))R.call(i,t)||t===o||a(i,t,{get:()=>n[t],enumerable:!(s=F(n,t))||s.enumerable});return i})(r()),V=function(t,e){return(V=Object.setPrototypeOf||({__proto__:[]}instanceof Array?function(t,e){t.__proto__=e}:function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])}))(t,e)},h=ft(function(e){return function(t){e(this),this.message=t?t.length+" errors occurred during unsubscription:\n"+t.map(function(t,e){return e+1+") "+t.toString()}).join("\n "):"",this.name="UnsubscriptionError",this.errors=t}}),I.prototype.unsubscribe=function(){var e,t,r;if(!this.closed){this.closed=!0;var i=this._parentage;if(i)if(this._parentage=null,Array.isArray(i))try{for(var n=ht(i),o=n.next();!o.done;o=n.next())o.value.remove(this)}catch(t){a={error:t}}finally{try{o&&!o.done&&(s=n.return)&&s.call(n)}finally{if(a)throw a.error}}else i.remove(this);var s=this.initialTeardown;if(T(s))try{s()}catch(t){r=t instanceof h?t.errors:[t]}var a=this._finalizers;if(a){this._finalizers=null;try{for(var c=ht(a),u=c.next();!u.done;u=c.next()){var l=u.value;try{mt(l)}catch(t){r=null!=r?r:[],t instanceof h?r=O(O([],k(r)),k(t.errors)):r.push(t)}}}catch(t){e={error:t}}finally{try{u&&!u.done&&(t=c.return)&&t.call(c)}finally{if(e)throw e.error}}}if(r)throw new h(r)}},I.prototype.add=function(t){var e;if(t&&t!==this)if(this.closed)mt(t);else{if(t instanceof I){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=null!=(e=this._finalizers)?e:[]).push(t)}},I.prototype._hasParent=function(t){var e=this._parentage;return e===t||Array.isArray(e)&&e.includes(t)},I.prototype._addParent=function(t){var e=this._parentage;this._parentage=Array.isArray(e)?(e.push(t),e):e?[e,t]:t},I.prototype._removeParent=function(t){var e=this._parentage;e===t?this._parentage=null:Array.isArray(e)&&pt(e,t)},I.prototype.remove=function(t){var e=this._finalizers;e&&pt(e,t),t instanceof I&&t._removeParent(this)},I.EMPTY=((r=new I).closed=!0,r),Y=(f=I).EMPTY,p={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1},d={setTimeout:function(t,e){for(var r=[],i=2;it.artists.some(t=>t.uri===e)).sort((t,e)=>_(t.album.name,e.album.name,"ascending")||_(t.discNumber,e.discNumber,"ascending")||_(t.trackNumber,e.trackNumber,"ascending"))}getDisplayName(t){return""===t?"Untitled":t}albumKeyFromName(t){return"spotify:uri:"+t.toLowerCase().replace(/\s/g,"+")}async clearCache(){this.isInitializedSubject.next(!1),this.storageService.cache=[],this.storageService.hasCache=!0,await this.init()}async reset(){this.isInitializedSubject.next(!1),this.storageService.cache=[],this.storageService.hasCache=!1,await this.init()}async init(){if(!this.isReady&&!this.isInitializing){this.isInitializing=!0,this.tracks=new Map,this.albums=new Map,this.artists=new Map;try{await this.processLocalTracks(),await this.postProcessAlbums()}catch(t){console.error("Error while processing",t);let e="Error while processing local files; clearing the cache";t instanceof Error&&(e+=": "+t.message),Spicetify.showNotification(e,!0,5e3),this.storageService.cache=[],this.storageService.hasCache=!0}this.isInitializedSubject.next(!0),this.isInitializing=!1}}async processLocalTracks(){for(const i of await(await ut("LocalFilesAPI")).getTracks()){let e;var t=this.getDisplayName(i.album.name),r=this.albumKeyFromName(t),t=(this.albums.has(r)?e=this.albums.get(r):(e=new g(r,t,this.getImageUrlFromAlbum(i.album)),this.albums.set(r,e)),i.artists.flatMap(t=>this.getArtistsFromString(t.name,e.image)));for(const n of t)this.artists.has(n.uri)||this.artists.set(n.uri,n),e.artists.some(t=>t.uri===n.uri)||e.artists.push(n);r=new B(i,e,t);this.tracks.set(r.uri,r),e.discs.has(i.discNumber)||e.discs.set(i.discNumber,[]),e.discs.get(i.discNumber)?.push(r)}}async postProcessAlbums(){var t,e,r=this.storageService.hasCache,i=[],n=[],o=[];this.albumCountSubject.next(this.albums.size);let s=0;for([t,e]of this.albums.entries()){this.processedAlbumsSubject.next(s+1),s++;var a=await this.postProcessAlbum(t,e);if(!(a.length<=1)){n.push(t);for(var[c,u]of a.entries())if(0!==u.tracks.length){var l=u.tracks[0],c=this.albumKeyFromName(e.name+" "+c),h=new g(c,e.name,this.getImageUrlFromAlbum(l.localTrack.album));for(const d of l.artists)h.artists.some(t=>t.uri===d.uri)||h.artists.push(d);for(const m of u.tracks)(m.album=h).discs.has(m.localTrack.discNumber)||h.discs.set(m.localTrack.discNumber,[]),h.discs.get(m.localTrack.discNumber)?.push(m);o.push(h)}i.push({uri:t,tracks:a.map(t=>t.tracks.map(t=>t.uri))})}}r||(this.storageService.cache=i,this.storageService.hasCache=!0);for(const b of n)this.albums.delete(b);for(const y of o)this.albums.set(y.uri,y);for(const v of this.albums.values())for(var[f,p]of v.discs.entries())v.discs.set(f,p.toSorted((t,e)=>_(t.trackNumber,e.trackNumber,"ascending")))}async postProcessAlbum(e,t){var r=this.storageService.hasCache,i=this.storageService.cache;let n=[];if(r){r=i.find(t=>t.uri===e);void 0!==r&&(n=r.tracks.map(t=>({cover:null,tracks:t.filter(t=>this.tracks.has(t)).map(t=>this.tracks.get(t))})))}else{if(t.artists.length<=1)return[];i=t.getTracks();if(i.length<=1)return[];var o=new Map;for(const c of i){var s=c.artists.map(t=>t.name).join(", ");o.has(s)?o.get(s)?.push(c):o.set(s,[c])}if(1===o.size)return[];for(const u of o.values()){var a=this.getImageUrlFromAlbum(u[0].localTrack.album);let t;try{t=await this.getImage(a)}catch(t){console.error(`Couldn't load image "${a}"`,t),n.push({tracks:u,cover:null});continue}const l=this.getImageDataFromCanvas(t);a=n.find(t=>0===this.getImageDifferenceWithPixelMatch(t.cover,l));void 0===a?n.push({tracks:u,cover:l}):a.tracks.push(...u)}}return n}getArtistsFromString(t,e){return t.split(/[;,]/).map(t=>new L(this.getDisplayName(t.trim()),e))}async getImage(i){return new Promise((t,e)=>{const r=new Image;r.onload=()=>{t(r)},r.onerror=t=>{e(t)},r.src=i})}getImageDataFromCanvas(t){var e=document.createElement("canvas"),e=(e.width=50,e.height=50,e.style.width="50px",e.style.height="50px",e.getContext("2d"));return e.drawImage(t,0,0,t.width,t.height,0,0,50,50),e.getImageData(0,0,50,50)}getImageDifferenceWithPixelMatch(t,e){return(0,K.default)(t.data,e.data,null,t.width,t.height,{threshold:.1})}getImageUrlFromAlbum(t){return 0===t.images.length?"":t.images[0].url}},(async()=>{for(window.localTracksService=new at;!Spicetify?.Platform;)await new Promise(t=>setTimeout(t,100));await 0;var t=await ut("History");const e=new Spicetify.Menu.Item("Rebuild local album cache",!1,async()=>{await window.localTracksService.reset()}),r=new Spicetify.Menu.Item("Clear local album cache",!1,async()=>{await window.localTracksService.clearCache()}),i=t=>{t.includes("better-local-files")?(e.register(),r.register()):(e.deregister(),r.deregister())};i(t.location.pathname),t.listen(t=>{i(t.pathname)}),async function(t,r){var i=await ut("History");const n=async()=>{await lt(t,r)||Spicetify.showNotification("📢 A new version of the custom app is available.",!1,5e3)};if(i.location.pathname==="/"+r)await n();else{let e=null;e=i.listen(async t=>{t.pathname==="/"+r&&(await n(),e?.())})}}("2.0.2","better-local-files")})();function ct(t){return Spicetify.Platform?.[t]}async function ut(t){return async function(t){let e=t();for(;void 0===e;)await new Promise(t=>setTimeout(t,100)),e=t();return e}(()=>ct(t))}async function lt(t,e){e=await(await(await fetch(`https://raw.githubusercontent.com/Pithaya/spicetify-apps/main/custom-apps/${e}/package.json`)).json()).version;return J(t,e,">=")}function _(t,e,r){r="descending"===r?-1:1;return e=t.length?void 0:t)&&t[i++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function k(t,e){var r="function"==typeof Symbol&&t[Symbol.iterator];if(!r)return t;var i,n,o=r.call(t),s=[];try{for(;(void 0===e||0{var z,P=Object.create,H=Object.defineProperty,B=Object.getOwnPropertyDescriptor,$=Object.getOwnPropertyNames,G=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty,e=(e,t)=>function(){return t||(0,e[$(e)[0]])((t={exports:{}}).exports,t),t.exports},j=(t,a,r,n)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let e of $(a))F.call(t,e)||e===r||H(t,e,{get:()=>a[e],enumerable:!(n=B(a,e))||n.enumerable});return t},t=(e,t,a)=>(a=null!=e?P(G(e)):{},j(!t&&e&&e.__esModule?a:H(a,"default",{value:e,enumerable:!0}),e)),r=e({"external-global-plugin:react"(e,t){t.exports=Spicetify.React}}),U=e({"external-global-plugin:react-dom"(e,t){t.exports=Spicetify.ReactDOM}}),X=e({"../../node_modules/spcr-whats-new/node_modules/semver/internal/debug.js"(e,t){var a="object"==typeof process&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...e)=>console.error("SEMVER",...e):()=>{};t.exports=a}}),W=e({"../../node_modules/spcr-whats-new/node_modules/semver/internal/constants.js"(e,t){var a=Number.MAX_SAFE_INTEGER||9007199254740991;t.exports={MAX_LENGTH:256,MAX_SAFE_COMPONENT_LENGTH:16,MAX_SAFE_BUILD_LENGTH:250,MAX_SAFE_INTEGER:a,RELEASE_TYPES:["major","premajor","minor","preminor","patch","prepatch","prerelease"],SEMVER_SPEC_VERSION:"2.0.0",FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}}}),J=e({"../../node_modules/spcr-whats-new/node_modules/semver/internal/re.js"(e,t){var{MAX_SAFE_COMPONENT_LENGTH:a,MAX_SAFE_BUILD_LENGTH:r,MAX_LENGTH:n}=W(),i=X(),l=(e=t.exports={}).re=[],o=e.safeRe=[],c=e.src=[],s=e.t={},u=0,t="[a-zA-Z0-9-]",d=[["\\s",1],["\\d",n],[t,r]],n=(e,t,a)=>{var r=(e=>{for(var[t,a]of d)e=e.split(t+"*").join(`${t}{0,${a}}`).split(t+"+").join(`${t}{1,${a}}`);return e})(t),n=u++;i(e,n,t),s[e]=n,c[n]=t,l[n]=new RegExp(t,a?"g":void 0),o[n]=new RegExp(r,a?"g":void 0)};n("NUMERICIDENTIFIER","0|[1-9]\\d*"),n("NUMERICIDENTIFIERLOOSE","\\d+"),n("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${t}*`),n("MAINVERSION",`(${c[s.NUMERICIDENTIFIER]})\\.(${c[s.NUMERICIDENTIFIER]})\\.(${c[s.NUMERICIDENTIFIER]})`),n("MAINVERSIONLOOSE",`(${c[s.NUMERICIDENTIFIERLOOSE]})\\.(${c[s.NUMERICIDENTIFIERLOOSE]})\\.(${c[s.NUMERICIDENTIFIERLOOSE]})`),n("PRERELEASEIDENTIFIER",`(?:${c[s.NUMERICIDENTIFIER]}|${c[s.NONNUMERICIDENTIFIER]})`),n("PRERELEASEIDENTIFIERLOOSE",`(?:${c[s.NUMERICIDENTIFIERLOOSE]}|${c[s.NONNUMERICIDENTIFIER]})`),n("PRERELEASE",`(?:-(${c[s.PRERELEASEIDENTIFIER]}(?:\\.${c[s.PRERELEASEIDENTIFIER]})*))`),n("PRERELEASELOOSE",`(?:-?(${c[s.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${c[s.PRERELEASEIDENTIFIERLOOSE]})*))`),n("BUILDIDENTIFIER",t+"+"),n("BUILD",`(?:\\+(${c[s.BUILDIDENTIFIER]}(?:\\.${c[s.BUILDIDENTIFIER]})*))`),n("FULLPLAIN",`v?${c[s.MAINVERSION]}${c[s.PRERELEASE]}?${c[s.BUILD]}?`),n("FULL",`^${c[s.FULLPLAIN]}$`),n("LOOSEPLAIN",`[v=\\s]*${c[s.MAINVERSIONLOOSE]}${c[s.PRERELEASELOOSE]}?${c[s.BUILD]}?`),n("LOOSE",`^${c[s.LOOSEPLAIN]}$`),n("GTLT","((?:<|>)?=?)"),n("XRANGEIDENTIFIERLOOSE",c[s.NUMERICIDENTIFIERLOOSE]+"|x|X|\\*"),n("XRANGEIDENTIFIER",c[s.NUMERICIDENTIFIER]+"|x|X|\\*"),n("XRANGEPLAIN",`[v=\\s]*(${c[s.XRANGEIDENTIFIER]})(?:\\.(${c[s.XRANGEIDENTIFIER]})(?:\\.(${c[s.XRANGEIDENTIFIER]})(?:${c[s.PRERELEASE]})?${c[s.BUILD]}?)?)?`),n("XRANGEPLAINLOOSE",`[v=\\s]*(${c[s.XRANGEIDENTIFIERLOOSE]})(?:\\.(${c[s.XRANGEIDENTIFIERLOOSE]})(?:\\.(${c[s.XRANGEIDENTIFIERLOOSE]})(?:${c[s.PRERELEASELOOSE]})?${c[s.BUILD]}?)?)?`),n("XRANGE",`^${c[s.GTLT]}\\s*${c[s.XRANGEPLAIN]}$`),n("XRANGELOOSE",`^${c[s.GTLT]}\\s*${c[s.XRANGEPLAINLOOSE]}$`),n("COERCE",`(^|[^\\d])(\\d{1,${a}})(?:\\.(\\d{1,${a}}))?(?:\\.(\\d{1,${a}}))?(?:$|[^\\d])`),n("COERCERTL",c[s.COERCE],!0),n("LONETILDE","(?:~>?)"),n("TILDETRIM",`(\\s*)${c[s.LONETILDE]}\\s+`,!0),e.tildeTrimReplace="$1~",n("TILDE",`^${c[s.LONETILDE]}${c[s.XRANGEPLAIN]}$`),n("TILDELOOSE",`^${c[s.LONETILDE]}${c[s.XRANGEPLAINLOOSE]}$`),n("LONECARET","(?:\\^)"),n("CARETTRIM",`(\\s*)${c[s.LONECARET]}\\s+`,!0),e.caretTrimReplace="$1^",n("CARET",`^${c[s.LONECARET]}${c[s.XRANGEPLAIN]}$`),n("CARETLOOSE",`^${c[s.LONECARET]}${c[s.XRANGEPLAINLOOSE]}$`),n("COMPARATORLOOSE",`^${c[s.GTLT]}\\s*(${c[s.LOOSEPLAIN]})$|^$`),n("COMPARATOR",`^${c[s.GTLT]}\\s*(${c[s.FULLPLAIN]})$|^$`),n("COMPARATORTRIM",`(\\s*)${c[s.GTLT]}\\s*(${c[s.LOOSEPLAIN]}|${c[s.XRANGEPLAIN]})`,!0),e.comparatorTrimReplace="$1$2$3",n("HYPHENRANGE",`^\\s*(${c[s.XRANGEPLAIN]})\\s+-\\s+(${c[s.XRANGEPLAIN]})\\s*$`),n("HYPHENRANGELOOSE",`^\\s*(${c[s.XRANGEPLAINLOOSE]})\\s+-\\s+(${c[s.XRANGEPLAINLOOSE]})\\s*$`),n("STAR","(<|>)?=?\\s*\\*"),n("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$"),n("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")}}),V=e({"../../node_modules/spcr-whats-new/node_modules/semver/internal/parse-options.js"(e,t){var a=Object.freeze({loose:!0}),r=Object.freeze({});t.exports=e=>e?"object"!=typeof e?a:e:r}}),Z=e({"../../node_modules/spcr-whats-new/node_modules/semver/internal/identifiers.js"(e,t){var n=/^[0-9]+$/,a=(e,t)=>{var a=n.test(e),r=n.test(t);return a&&r&&(e=+e,t=+t),e===t?0:a&&!r||(!r||a)&&ea(t,e)}}}),K=e({"../../node_modules/spcr-whats-new/node_modules/semver/classes/semver.js"(e,t){var n=X(),{MAX_LENGTH:a,MAX_SAFE_INTEGER:r}=W(),{safeRe:i,t:l}=J(),o=V(),c=Z()["compareIdentifiers"],s=class{constructor(e,t){if(t=o(t),e instanceof s){if(e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease)return e;e=e.version}else if("string"!=typeof e)throw new TypeError(`Invalid version. Must be a string. Got type "${typeof e}".`);if(e.length>a)throw new TypeError(`version is longer than ${a} characters`);n("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;t=e.trim().match(t.loose?i[l.LOOSE]:i[l.FULL]);if(!t)throw new TypeError("Invalid Version: "+e);if(this.raw=e,this.major=+t[1],this.minor=+t[2],this.patch=+t[3],this.major>r||this.major<0)throw new TypeError("Invalid major version");if(this.minor>r||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>r||this.patch<0)throw new TypeError("Invalid patch version");t[4]?this.prerelease=t[4].split(".").map(e=>{if(/^[0-9]+$/.test(e)){var t=+e;if(0<=t&&tnew r(e,a).compare(new r(t,a))}}),a=e({"../../node_modules/spcr-whats-new/node_modules/semver/functions/gt.js"(e,t){var r=Y();t.exports=(e,t,a)=>0s.current.offsetHeight||s.current.scrollWidth>s.current.offsetWidth),t=bfunction(){return ur.default.createElement(sr,null)}};for(z in te)H(ee,z,{get:te[z],enumerable:!0});function ae(e){return Spicetify.Platform?.[e]}function p(e){var t=ae(e);if(void 0===t)throw new Error(`Platform API "${e}" is not available`);return t}var o=t(r()),re=t(U()),ne=t(a()),ie=t(U());var le=async function(t,a,e){for(;!Spicetify?.PopupModal||!Spicetify?.LocalStorage;)await new Promise(e=>setTimeout(e,100));var r,t=`spcr-whats-new_${t}-version`,n=Spicetify.LocalStorage.get(t)??"";try{(0,ne.default)(a,n)&&(Spicetify.LocalStorage.set(t,a),r={...e,content:function(e){var t=document.createElement("div"),a=(t.setAttribute("id","whats-new-content-wrapper"),document.createElement("style"));return a.textContent=` + #whats-new-content-wrapper ul, #whats-new-content-wrapper ol { + list-style: inherit; + margin-left: 1em; + } + `,ie.default.render(e,t),t.appendChild(a),t}(e.content)},Spicetify.PopupModal.display(r))}catch(e){Spicetify.LocalStorage.set(t,a)}},oe="2.0.2",ce=["Fix the app crashing on load"],n=t(r());function l(e,t=null){var a=p("History");null===t?a.push(e):a.push({pathname:e,state:{uri:t},hash:"",key:"",search:""})}var c=t(r());function se(t,e){0!==e.length&&e.some(e=>e.uri===t)&&Spicetify.Player.origin.play({uri:"spotify:internal:local-files",pages:[{items:e}]},{},{skipTo:{uri:t}})}function ue(e){0!==e.length&&Spicetify.Player.origin.play({uri:"spotify:internal:local-files",pages:[{items:e}]},{},{})}var de=t(r());function f(e,...a){let t=p("Translations");for(const n of e)t=t[n];let r=t;return a.forEach((e,t)=>{r=r.replace(`{${t}}`,a[t])}),r}var me=t(r());function _(e){return e.icon?me.default.createElement(Spicetify.ReactComponent.IconComponent,{iconSize:e.iconSize,semanticColor:e.semanticColor,dangerouslySetInnerHTML:{__html:Spicetify.SVGIcons[e.icon]},viewBox:"0 0 16 16"}):e.iconPath?me.default.createElement(Spicetify.ReactComponent.IconComponent,{iconSize:e.iconSize,semanticColor:e.semanticColor,dangerouslySetInnerHTML:{__html:e.iconPath},viewBox:"0 0 16 16"}):me.default.createElement(me.default.Fragment,null)}function pe(t){return de.default.createElement(Spicetify.ReactComponent.ButtonPrimary,{"aria-label":f(["play"]),buttonSize:t.size,onClick:e=>{e.stopPropagation(),t.onClick()},iconOnly:()=>de.default.createElement(_,{icon:"play"})})}var fe="app-module__display-list___8BLJG_betterDlocalDfiles",_e="app-module__display-list-compact___sbWJt_betterDlocalDfiles",s=t(r()),h=t(r()),he=t(r());function be(t){const[e,a]=(0,he.useState)(!1);return(0,he.useEffect)(()=>{const e=new IntersectionObserver((e,t)=>{a(e.some(e=>e.isIntersecting))},{rootMargin:"0px",threshold:0});return e.observe(t.current),()=>{e.disconnect()}},[t]),e}var i=t(r()),ve=t(r());function ye(e){var t=Spicetify.ReactDOMServer.renderToString(ve.default.createElement(Spicetify.ReactComponent.MenuItem,{leadingIcon:e.leadingIcon,trailingIcon:ve.default.createElement("svg",{height:"16",width:"16","aria-hidden":"true",className:"main-contextMenu-subMenuIcon",viewBox:"0 0 16 16",fill:"currentColor"},ve.default.createElement("path",{d:"M14 10 8 4l-6 6h12z"}))},ve.default.createElement("span",null,e.label)));return ve.default.createElement(Spicetify.ReactComponent.ContextMenu,{trigger:"click",action:"toggle",placement:"right-end",renderInline:!0,menu:e.submenu},ve.default.createElement("div",{onMouseEnter:e=>{e.currentTarget.click()},dangerouslySetInnerHTML:{__html:t}}))}var a="/better-local-files",Ee=a+"/album",ge=a+"/albums",u=a+"/artist",De=a+"/artists",ke=a,we=[{key:"Tracks",href:ke,label:f(["search.title.tracks"])},{key:"Albums",href:ge,label:f(["search.title.albums"])},{key:"Artists",href:De,label:f(["search.title.artists"])}],Se="encore-dark-theme main-contextMenu-menu",Ie=t(r());function xe(e){return Ie.default.createElement(Spicetify.ReactComponent.Menu,{className:Se},e.artists.map(e=>Ie.default.createElement(Spicetify.ReactComponent.MenuItem,{onClick:()=>{l(u,e.uri)},key:e.uri},Ie.default.createElement("span",null,e.name))))}var Ne=t(r());function Ce(a){const r=p("PlaylistAPI"),n=p("RootlistAPI"),i=p("UserAPI"),[e,l]=(0,Ne.useState)([]);return(0,Ne.useEffect)(()=>{!async function(){var e=await n.getContents();const t=await i.getUser();e=e.items.flatMap(e=>"playlist"===e.type?e:e.items).filter(e=>"playlist"===e.type).filter(e=>e.owner.uri===t.uri),l(e)}()},[]),Ne.default.createElement(Spicetify.ReactComponent.Menu,{className:Se},e.map(t=>Ne.default.createElement(Spicetify.ReactComponent.MenuItem,{onClick:async()=>{var e;e=t.uri,await r.add(e,a.tracksUri,{after:"end"})},key:t.uri},Ne.default.createElement("span",null,t.name))))}var Re='',Le=t(r());function Te(e){const t=p("LibraryAPI"),[a,r]=(0,Le.useState)(t.containsSync(e));return(0,Le.useEffect)(()=>{void 0===a&&t.contains(e).then(e=>{r(e[0])}).catch(console.error)},[e]),[a,r]}function Oe(e){var[t]=Te(e.track.uri);let a;switch(t){case!0:a=i.default.createElement(Spicetify.ReactComponent.MenuItem,{onClick:async function(){await p("LibraryAPI").remove({uris:[e.track.uri]})},leadingIcon:i.default.createElement(_,{icon:"check-alt-fill",iconSize:16,semanticColor:"essentialBrightAccent"})},i.default.createElement("span",null,f(["remove_from_your_liked_songs"])));break;case!1:a=i.default.createElement(Spicetify.ReactComponent.MenuItem,{onClick:async function(){await p("LibraryAPI").add({uris:[e.track.uri]})},leadingIcon:i.default.createElement(_,{icon:"plus-alt",iconSize:16})},i.default.createElement("span",null,f(["save_to_your_liked_songs"])));break;default:a=i.default.createElement(Spicetify.ReactComponent.MenuItem,null,i.default.createElement("span",null,"..."))}return i.default.createElement(Spicetify.ReactComponent.Menu,{className:Se},i.default.createElement(ye,{label:f(["contextmenu.add-to-playlist"]),submenu:i.default.createElement(Ce,{tracksUri:[e.track.uri]}),leadingIcon:i.default.createElement(_,{icon:"plus2px",iconSize:16})}),a,i.default.createElement(Spicetify.ReactComponent.MenuItem,{divider:"after",onClick:async function(){await p("PlayerAPI").addToQueue([{uri:e.track.uri}])},leadingIcon:i.default.createElement(_,{iconPath:Re,iconSize:16})},i.default.createElement("span",null,f(["contextmenu.add-to-queue"]))),1===e.track.artists.length?i.default.createElement(Spicetify.ReactComponent.MenuItem,{onClick:()=>{l(u,e.track.artists[0].uri)},leadingIcon:i.default.createElement(_,{icon:"artist",iconSize:16})},i.default.createElement("span",null,f(["contextmenu.go-to-artist"]))):i.default.createElement(ye,{label:f(["contextmenu.go-to-artist"]),submenu:i.default.createElement(xe,{artists:e.track.artists}),leadingIcon:i.default.createElement(_,{icon:"artist",iconSize:16})}),i.default.createElement(Spicetify.ReactComponent.MenuItem,{onClick:()=>{l(Ee,e.track.album.uri)},leadingIcon:i.default.createElement(_,{icon:"album",iconSize:16})},i.default.createElement("span",null,f(["contextmenu.go-to-album"]))))}var Ae=t(r());function b(e){const{elementType:t="span",children:a,...r}=e;let n;switch(t){case"h1":n=Spicetify.ReactComponent.TextComponent.h1;break;case"h2":n=Spicetify.ReactComponent.TextComponent.h2;break;case"h3":n=Spicetify.ReactComponent.TextComponent.h3;break;case"h4":n=Spicetify.ReactComponent.TextComponent.h4;break;case"h5":n=Spicetify.ReactComponent.TextComponent.h5;break;case"h6":n=Spicetify.ReactComponent.TextComponent.h6;break;case"li":n=Spicetify.ReactComponent.TextComponent.li;break;case"p":n=Spicetify.ReactComponent.TextComponent.p;break;case"small":n=Spicetify.ReactComponent.TextComponent.small;break;case"span":n=Spicetify.ReactComponent.TextComponent.span;break;default:n=Spicetify.ReactComponent.TextComponent}return Ae.default.createElement(n,{...r,style:e.style},a)}function Me(t){var e=(0,h.useRef)(null);const a=be(e),[r,n]=(0,h.useState)(!1),[i,l]=Te(t.track.uri),o=p("LibraryAPI");(0,h.useEffect)(()=>{if(a){const e=e=>{e.data.uris.some(e=>e===t.track.uri)&&("add"===e.data.operation?l(!0):"remove"===e.data.operation&&l(!1))};return o.getEvents().addListener("operation_complete",e),()=>{o.getEvents().removeListener("operation_complete",e)}}},[a,t.track.uri]);var c=h.default.createElement("div",{style:{height:"compact"===t.displayType?"32px":"54px"}}),s=h.default.createElement(Spicetify.ReactComponent.TooltipWrapper,{label:f(["save_to_your_liked_songs"]),showDelay:100},h.default.createElement(Spicetify.ReactComponent.ButtonTertiary,{"aria-label":f(["save_to_your_liked_songs"]),iconOnly:()=>h.default.createElement(_,{icon:"plus-alt",iconSize:16}),buttonSize:"sm",style:{padding:0,visibility:r?void 0:"hidden"},onClick:async function(){await o.add({uris:[t.track.uri]})}})),u=h.default.createElement(Spicetify.ReactComponent.TooltipWrapper,{label:f(["remove_from_your_liked_songs"]),showDelay:100},h.default.createElement(Spicetify.ReactComponent.ButtonTertiary,{"aria-label":f(["remove_from_your_liked_songs"]),iconOnly:()=>h.default.createElement(_,{icon:"check-alt-fill",iconSize:16}),buttonSize:"sm",style:{padding:0},onClick:async function(){await o.remove({uris:[t.track.uri]})},semanticColor:"essentialBrightAccent"})),d=h.default.createElement(Spicetify.ReactComponent.ButtonTertiary,{iconOnly:()=>h.default.createElement(h.default.Fragment,null),buttonSize:"sm",style:{padding:0,visibility:r?void 0:"hidden"}});let m;switch(i){case!0:m=u;break;case!1:m=s;break;default:m=d}return h.default.createElement("div",{ref:e,onMouseEnter:()=>{n(!0)},onMouseLeave:()=>{n(!1)}},a?h.default.createElement(Spicetify.ReactComponent.RightClickMenu,{menu:h.default.createElement(Oe,{track:t.track})},h.default.createElement("div",{"aria-selected":t.selected,onClick:t.onClick,onDoubleClick:t.onDoubleClick,draggable:"true",onDragStart:t.dragHandler},h.default.createElement("div",{className:`main-trackList-trackListRow main-trackList-trackListRowGrid ${t.active?"main-trackList-active":""} ${t.selected?"main-trackList-selected":""} `+("compact"===t.displayType?"main-trackList-rowCompactMode":"")},h.default.createElement("div",{className:"main-trackList-rowSectionIndex","aria-colindex":1,tabIndex:-1},h.default.createElement("div",{className:"main-trackList-rowMarker"},t.playing?h.default.createElement(h.default.Fragment,null,h.default.createElement("img",{className:"main-trackList-playingIcon",width:"14",height:"14",alt:"",src:"/images/equaliser-animated-green.gif"}),h.default.createElement(Spicetify.ReactComponent.TooltipWrapper,{label:f(["playback-control.pause"]),showDelay:200},h.default.createElement("button",{className:"main-trackList-rowImagePlayButton","aria-label":f(["playback-control.pause"]),tabIndex:0,"aria-expanded":"false",onClick:()=>{Spicetify.Player.pause()}},h.default.createElement("svg",{height:"24",width:"24","aria-hidden":"true",fill:"currentColor",className:"main-trackList-rowPlayPauseIcon",viewBox:"0 0 24 24"},h.default.createElement("path",{d:"M5.7 3a.7.7 0 0 0-.7.7v16.6a.7.7 0 0 0 .7.7h2.6a.7.7 0 0 0 .7-.7V3.7a.7.7 0 0 0-.7-.7H5.7zm10 0a.7.7 0 0 0-.7.7v16.6a.7.7 0 0 0 .7.7h2.6a.7.7 0 0 0 .7-.7V3.7a.7.7 0 0 0-.7-.7h-2.6z"}))))):h.default.createElement(h.default.Fragment,null,h.default.createElement("span",{className:"main-trackList-number"},t.index),h.default.createElement(Spicetify.ReactComponent.TooltipWrapper,{label:f(["tracklist.a11y.play"],t.track.name,t.track.artists.map(e=>e.name).join(", ")),showDelay:200},h.default.createElement("button",{className:"main-trackList-rowImagePlayButton","aria-label":f(["tracklist.a11y.play"],t.track.name,t.track.artists.map(e=>e.name).join(", ")),onClick:()=>{t.active?Spicetify.Player.play():t.onDoubleClick()},tabIndex:-1},h.default.createElement("svg",{height:"24",width:"24","aria-hidden":"true",className:"main-trackList-rowPlayPauseIcon",viewBox:"0 0 24 24","data-encore-id":"icon",fill:"currentColor"},h.default.createElement("path",{d:"M7.05 3.606l13.49 7.788a.7.7 0 010 1.212L7.05 20.394A.7.7 0 016 19.788V4.212a.7.7 0 011.05-.606z"}))))))),t.children&&h.Children.map(t.children,(e,t)=>h.default.createElement("div",{className:0===t?"main-trackList-rowSectionStart":"main-trackList-rowSectionVariable","aria-colindex":t+2,tabIndex:-1},e)),h.default.createElement("div",{className:"main-trackList-rowSectionEnd","aria-colindex":h.Children.count(t.children)+2,tabIndex:-1},m,h.default.createElement(b,{variant:"mesto",semanticColor:"textSubdued",className:"main-trackList-rowDuration"},Spicetify.Player.formatTime(t.track.duration)),h.default.createElement(Spicetify.ReactComponent.TooltipWrapper,{label:f(["more.label.track"],t.track.name,t.track.artists.map(e=>e.name).join(", ")),showDelay:100},h.default.createElement("div",null,h.default.createElement(Spicetify.ReactComponent.ContextMenu,{trigger:"click",action:"toggle",menu:h.default.createElement(Oe,{track:t.track})},h.default.createElement(Spicetify.ReactComponent.ButtonTertiary,{"aria-label":f(["more.label.track"],t.track.name,t.track.artists.map(e=>e.name).join(", ")),"aria-haspopup":"menu",iconOnly:()=>h.default.createElement(_,{icon:"more",iconSize:16}),buttonSize:"sm",style:{padding:0,visibility:r?void 0:"hidden"}})))))))):c)}var d=t(r()),ze=t(r());function Pe(e){return ze.default.createElement("svg",{height:"16",width:"16",viewBox:"0 0 16 16",fill:"var(--text-bright-accent)",className:e.className},ze.default.createElement("path",{d:"M14 10L8 4l-6 6h12z"}))}var He=t(r());function Be(e){return He.default.createElement("svg",{height:"16",width:"16",viewBox:"0 0 16 16",fill:"var(--text-bright-accent)",className:e.className},He.default.createElement("path",{d:"M14 6l-6 6-6-6h12z"}))}function $e(a){function r(){return void 0===a.sortedHeader?d.default.createElement(d.default.Fragment,null):"ascending"===a.sortedHeader.order?d.default.createElement(Pe,{className:"main-trackList-arrow"}):d.default.createElement(Be,{className:"main-trackList-arrow"})}const n=void 0!==a.sortedHeader?"main-trackList-sortable":"";return d.default.createElement("div",{className:"main-trackList-trackListHeader"},d.default.createElement("div",{className:"main-trackList-trackListHeaderRow main-trackList-trackListRowGrid","aria-rowindex":1},d.default.createElement("div",{className:"main-trackList-rowSectionIndex","aria-colindex":1,"aria-sort":"none",tabIndex:-1},"#"),a.headers.map((e,t)=>d.default.createElement("div",{key:e.key,className:0===t?"main-trackList-rowSectionStart":"main-trackList-rowSectionVariable","aria-colindex":t+2,"aria-sort":a.sortedHeader&&a.sortedHeader.key===e.key?a.sortedHeader.order:"none",tabIndex:-1},d.default.createElement("button",{className:"main-trackList-column "+n,tabIndex:-1,onClick:()=>{a.onHeaderClicked?.(e.key)}},d.default.createElement(b,{variant:"mesto"},e.label),a.sortedHeader&&a.sortedHeader.key===e.key&&r()))),d.default.createElement("div",{className:"main-trackList-rowSectionEnd","aria-colindex":a.headers.length+2,"aria-sort":"none",tabIndex:-1},d.default.createElement("button",{"aria-label":f(["tracklist.header.duration"]),className:"main-trackList-column main-trackList-durationHeader "+n,onClick:()=>{a.onHeaderClicked?.("duration")}},d.default.createElement("svg",{height:"16",width:"16","aria-hidden":"true",viewBox:"0 0 16 16",fill:"currentColor"},d.default.createElement("path",{d:"M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z"}),d.default.createElement("path",{d:"M8 3.25a.75.75 0 01.75.75v3.25H11a.75.75 0 010 1.5H7.25V4A.75.75 0 018 3.25z"}))),a.sortedHeader&&"duration"===a.sortedHeader.key&&r())))}var Ge=t(r());var Fe=t(r());function je(a){const r=function(){const[e,t]=(0,Ge.useState)(Spicetify.Player?.data?.item?.uri??"");return(0,Ge.useEffect)(()=>{function e(e){t((e?.data).item?.uri??"")}return Spicetify.Player.addEventListener("songchange",e),()=>{Spicetify.Player.removeEventListener("songchange",e)}}),e}(),n=function(){const[e,t]=(0,Fe.useState)(Spicetify.Player?.data?.isPaused?"pause":"play");return(0,Fe.useEffect)(()=>{function e(e){t((e?.data).isPaused?"pause":"play")}return Spicetify.Player.addEventListener("onplaypause",e),()=>{Spicetify.Player.removeEventListener("onplaypause",e)}}),e}(),[i,l]=(0,s.useState)(new Map),o=(0,s.useMemo)(()=>{var e=Array.from(i.entries());return 0===e.length?Spicetify.ReactHook.DragHandler({itemUris:[],dragLabelText:""}):Spicetify.ReactHook.DragHandler({itemUris:e.map(e=>e[0]),dragLabelText:1s.default.createElement(Me,{key:t.uri,track:t,index:a.useTrackNumber?t.trackNumber:e+1,selected:i.has(t.uri),active:r===t.uri,playing:r===t.uri&&"play"===n,onClick:e=>{c(e,t)},onDoubleClick:()=>{a.onPlayTrack(t.uri)},dragHandler:o,displayType:a.displayType},a.getRowContent(t))),a.subtracks.map(e=>s.default.createElement(s.default.Fragment,null,e.headerRow,e.tracks.map((t,e)=>s.default.createElement(Me,{key:t.uri,track:t,index:a.useTrackNumber?t.trackNumber:e+1,selected:i.has(t.uri),active:r===t.uri,playing:r===t.uri&&"play"===n,onClick:e=>{c(e,t)},onDoubleClick:()=>{a.onPlayTrack(t.uri)},dragHandler:o,displayType:a.displayType},a.getRowContent(t))))))))}var Ue=t(r());function Xe(e){return Ue.default.createElement("div",{className:"main-trackList-rowMainContent"},Ue.default.createElement(b,{className:"main-trackList-rowTitle standalone-ellipsis-one-line",variant:"ballad",semanticColor:"textBase"},e.track.name),e.withArtists&&Ue.default.createElement(b,{className:"main-trackList-rowSubTitle standalone-ellipsis-one-line",variant:"mesto",semanticColor:"textSubdued"},e.track.artists.map(e=>Ue.default.createElement("a",{dir:"auto",href:"#",tabIndex:-1,onClick:()=>{l(u,e.uri)},key:e.uri},e.name)).reduce((e,t)=>null===e?[t]:[...e,Ue.default.createElement(Ue.default.Fragment,null,", "),t],null)))}var m=t(r());function We(e){return m.default.createElement("div",{className:"main-trackList-trackListRowGrid main-trackList-discRow"},m.default.createElement("div",{className:"main-trackList-rowSectionIndex","aria-colindex":1,tabIndex:-1},m.default.createElement("div",{className:"main-trackList-rowMarker"},m.default.createElement("span",{className:"main-trackList-icon"},m.default.createElement("svg",{height:"16",width:"16","aria-hidden":"true",viewBox:"0 0 16 16",fill:"currentColor"},m.default.createElement("path",{d:"M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zM0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8z"}),m.default.createElement("path",{d:"M8 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zM5 8a3 3 0 1 1 6 0 3 3 0 0 1-6 0z"}))))),m.default.createElement("div",{className:"main-trackList-rowSectionStart","aria-colindex":2,tabIndex:-1},m.default.createElement("div",{className:"main-trackList-rowMainContent"},m.default.createElement("div",{dir:"auto",className:"main-trackList-rowTitle main-trackList-discTitle standalone-ellipsis-one-line"},f(["tracklist.disc-sperator.title"],e.discNumber)))))}var Je="app-module__flex-centered___5gRmM_betterDlocalDfiles",Ve=t(r());function Ze(e){return Ve.default.createElement(Spicetify.ReactComponent.TooltipWrapper,{label:e.label,showDelay:100},Ve.default.createElement("div",{className:""+Je},Ve.default.createElement(Spicetify.ReactComponent.ContextMenu,{trigger:"click",action:"toggle",menu:e.menu},Ve.default.createElement(Spicetify.ReactComponent.ButtonTertiary,{"aria-label":e.label,"aria-haspopup":"menu",iconOnly:()=>Ve.default.createElement(_,{icon:"more"})}))))}var Ke=t(r());function Ye(e){return Ke.default.createElement(Spicetify.ReactComponent.Menu,{className:Se},Ke.default.createElement(ye,{label:f(["contextmenu.add-to-playlist"]),submenu:Ke.default.createElement(Ce,{tracksUri:e.tracks.map(e=>e.uri)}),leadingIcon:Ke.default.createElement(_,{icon:"plus2px",iconSize:16})}),Ke.default.createElement(Spicetify.ReactComponent.MenuItem,{onClick:async function(){await p("PlayerAPI").addToQueue(e.tracks.map(e=>({uri:e.uri})))},leadingIcon:Ke.default.createElement(_,{iconPath:Re,iconSize:16})},Ke.default.createElement("span",null,f(["contextmenu.add-to-queue"]))))}function qe(e){var t=[],a=[];const r=Array.from(e.discs.values()).flat();if(1===e.discs.size)t.push(...r);else for(var[n,i]of e.discs.entries())a.push({headerRow:c.default.createElement(We,{discNumber:n}),tracks:i});var l=[{key:"title",label:f(["sort.title"])}];return c.default.createElement(c.default.Fragment,null,c.default.createElement("div",{className:"main-actionBar-ActionBar contentSpacing"},c.default.createElement("div",{className:"main-actionBar-ActionBarRow"},c.default.createElement("div",{className:"main-playButton-PlayButton"},c.default.createElement(pe,{size:"lg",onClick:()=>{ue(r.map(e=>e.localTrack))}})),c.default.createElement(Ze,{label:f(["more.label.context"],r[0].album.name),menu:c.default.createElement(Ye,{tracks:r})}))),c.default.createElement(je,{tracks:t,subtracks:a,gridLabel:e.albumName,useTrackNumber:!0,onPlayTrack:e=>{se(e,r.map(e=>e.localTrack))},headers:l,getRowContent:e=>[c.default.createElement(Xe,{key:e.uri,track:e,withArtists:!0})],displayType:"list"}))}var v=t(r()),Qe=t(e());function et(e){return v.default.createElement("img",{src:e.imageSrc,className:"main-image-image main-entityHeader-image main-entityHeader-shadow main-entityHeader-newEntityHeaders main-image-loaded",onError:e=>e.currentTarget.outerHTML=` +
+ + + + + +
`})}function tt(e){var{fontSize:t,ref:a}=(0,Qe.default)();return v.default.createElement("div",{className:"contentSpacing main-entityHeader-container main-entityHeader-nonWrapped main-entityHeader-newEntityHeaders"},v.default.createElement("div",{className:"main-entityHeader-backgroundColor"}),v.default.createElement("div",{className:"main-entityHeader-backgroundColor main-entityHeader-overlay"}),v.default.createElement("div",null),v.default.createElement("div",{className:"main-entityHeader-imageContainer main-entityHeader-imageContainerNew"},v.default.createElement("div",{className:"main-entityHeader-image"},e.image)),v.default.createElement("div",{className:"main-entityHeader-headerText"},e.subtitle&&v.default.createElement(b,{variant:"mesto",className:"main-entityHeader-pretitle"},e.subtitle),v.default.createElement("div",{dir:"auto",className:"main-entityHeader-title",style:{maxHeight:"135px",fontSize:"6rem"},ref:a},v.default.createElement(b,{variant:"bass",semanticColor:"textBase",elementType:"h1",style:{fontSize:t}},e.title)),e.metadata&&v.default.createElement("div",{className:"main-entityHeader-metaData",style:{maxHeight:"66px"}},e.metadata)))}function at(e){return n.default.createElement(tt,{image:n.default.createElement(et,{imageSrc:e.album.image}),subtitle:f(["album"]),title:e.album.name,metadata:n.default.createElement(n.default.Fragment,null,e.album.artists.map(e=>n.default.createElement(b,{variant:"mestoBold",key:e.uri},n.default.createElement("a",{href:"#",draggable:"false",onClick:()=>{l(u,e.uri)}},e.name))).reduce((e,t,a)=>null===e?[t]:[...e,n.default.createElement("span",{key:a,className:"main-entityHeader-divider"}),t],null),n.default.createElement(b,{variant:"mesto",className:"main-entityHeader-metaDataText"},f(["tracklist-header.songs-counter",1===e.album.getTracks().length?"one":"other"],e.album.getTracks().length)),n.default.createElement(b,{variant:"mesto",className:"main-entityHeader-metaDataText"},(e=e.album.getDuration(),t=Math.floor(e/1e3%60),a=Math.floor(e/1e3/60%60),e=Math.floor(e/1e3/60/60%24),r=[],0!==e&&r.push(f(["time.hours.short",1===e?"one":"other"],e)),0!==a&&r.push(f(["time.minutes.short",1===a?"one":"other"],a)),0===e&&0!==t&&r.push(f(["time.seconds.short",1===t?"one":"other"],t)),r.join(" "))))});var t,a,r}function rt(){var e=p("History"),t=e.location.state.uri??null;return null===t?(e.replace(ge),n.default.createElement(n.default.Fragment,null)):(e=window.localTracksService.getAlbums()).has(t)?(e=e.get(t),n.default.createElement(n.default.Fragment,null,null!==e&&n.default.createElement(n.default.Fragment,null,n.default.createElement(at,{album:e}),n.default.createElement(qe,{albumName:e.name,discs:e.discs})))):(l(ge),n.default.createElement(n.default.Fragment,null))}var y=t(r()),nt={"stretch-container":"app-module__stretch-container___SIzsh_betterDlocalDfiles","center-container":"app-module__center-container___LG8O4_betterDlocalDfiles","full-size-container":"app-module__full-size-container___XoGtP_betterDlocalDfiles","pad-top":"app-module__pad-top___8OIp9_betterDlocalDfiles",tabBar:"app-module__tabBar___EngzO_betterDlocalDfiles",active:"app-module__active___JYUKA_betterDlocalDfiles","album-grid":"app-module__album-grid___JeelH_betterDlocalDfiles","main-card-card":"app-module__main-card-card___E9Zy2_betterDlocalDfiles","text-subdued":"app-module__text-subdued___7rYtR_betterDlocalDfiles","album-header":"app-module__album-header___J1nVK_betterDlocalDfiles","search-container":"app-module__search-container___SlAU8_betterDlocalDfiles","search-icon":"app-module__search-icon___-9z2r_betterDlocalDfiles","clear-icon":"app-module__clear-icon___pSLvx_betterDlocalDfiles",controls:"app-module__controls___ZDW-X_betterDlocalDfiles","flex-centered":"app-module__flex-centered___5gRmM_betterDlocalDfiles","display-list":"app-module__display-list___8BLJG_betterDlocalDfiles","display-list-compact":"app-module__display-list-compact___sbWJt_betterDlocalDfiles","limit-lines-2":"app-module__limit-lines-2___GyZCj_betterDlocalDfiles","text-full-centered":"app-module__text-full-centered___xI2eE_betterDlocalDfiles"},E=t(r()),it={"stretch-container":"app-module__stretch-container___SIzsh_betterDlocalDfiles","center-container":"app-module__center-container___LG8O4_betterDlocalDfiles","full-size-container":"app-module__full-size-container___XoGtP_betterDlocalDfiles","pad-top":"app-module__pad-top___8OIp9_betterDlocalDfiles",tabBar:"app-module__tabBar___EngzO_betterDlocalDfiles",active:"app-module__active___JYUKA_betterDlocalDfiles","album-grid":"app-module__album-grid___JeelH_betterDlocalDfiles","main-card-card":"app-module__main-card-card___E9Zy2_betterDlocalDfiles","text-subdued":"app-module__text-subdued___7rYtR_betterDlocalDfiles","album-header":"app-module__album-header___J1nVK_betterDlocalDfiles","search-container":"app-module__search-container___SlAU8_betterDlocalDfiles","search-icon":"app-module__search-icon___-9z2r_betterDlocalDfiles","clear-icon":"app-module__clear-icon___pSLvx_betterDlocalDfiles",controls:"app-module__controls___ZDW-X_betterDlocalDfiles","flex-centered":"app-module__flex-centered___5gRmM_betterDlocalDfiles","display-list":"app-module__display-list___8BLJG_betterDlocalDfiles","display-list-compact":"app-module__display-list-compact___sbWJt_betterDlocalDfiles","limit-lines-2":"app-module__limit-lines-2___GyZCj_betterDlocalDfiles","text-full-centered":"app-module__text-full-centered___xI2eE_betterDlocalDfiles"};function lt(e){var t=(0,E.useRef)(null),a=be(t),r=Spicetify.ReactHook.DragHandler({itemUris:e.album.getTracks().map(e=>e.uri),dragLabelText:e.album.name,contextUri:e.album.uri}),n=E.default.createElement("div",{style:{height:"250px"}});const i=` +
+ + + + + +
`;r=E.default.createElement("div",{className:it["main-card-card"]+" main-card-card",draggable:!0,onClick:()=>{l(Ee,e.album.uri)},onDragStart:r},E.default.createElement("div",{className:"main-card-draggable"},E.default.createElement("div",{className:"main-card-imageContainer main-card-imageContainerOld"},E.default.createElement("div",{className:"main-cardImage-imageWrapper"},E.default.createElement("img",{"aria-hidden":"false",draggable:"false",loading:"lazy",src:e.album.image,alt:"album image",className:"main-image-image main-cardImage-image main-image-loading main-image-loaded",onError:e=>e.currentTarget.outerHTML=i})),E.default.createElement("div",{className:"main-card-PlayButtonContainer"},E.default.createElement("div",{className:"main-playButton-PlayButton"},E.default.createElement(pe,{size:"md",onClick:()=>{e.onPlayClicked(e.album)}})))),E.default.createElement("div",{className:"main-card-cardMetadata"},E.default.createElement(b,{className:"main-cardHeader-link main-cardHeader-text",variant:"balladBold",semanticColor:"textBase",paddingBottom:"4px"},e.album.name),E.default.createElement(b,{className:"main-cardSubHeader-root "+it["limit-lines-2"],variant:"mesto",semanticColor:"textSubdued"},e.album.artists.map(t=>E.default.createElement("span",{key:t.uri},E.default.createElement("a",{href:"#",draggable:"false",onClick:e=>{e.stopPropagation(),l(u,t.uri)}},t.name))).reduce((e,t)=>null===e?[t]:[...e,E.default.createElement(E.default.Fragment,null,", "),t],null)))));return E.default.createElement("div",{ref:t},a?E.default.createElement(Spicetify.ReactComponent.RightClickMenu,{menu:E.default.createElement(Ye,{tracks:e.album.getTracks()})},r):n)}var ot=t(r()),ct={"stretch-container":"app-module__stretch-container___SIzsh_betterDlocalDfiles","center-container":"app-module__center-container___LG8O4_betterDlocalDfiles","full-size-container":"app-module__full-size-container___XoGtP_betterDlocalDfiles","pad-top":"app-module__pad-top___8OIp9_betterDlocalDfiles",tabBar:"app-module__tabBar___EngzO_betterDlocalDfiles",active:"app-module__active___JYUKA_betterDlocalDfiles","album-grid":"app-module__album-grid___JeelH_betterDlocalDfiles","main-card-card":"app-module__main-card-card___E9Zy2_betterDlocalDfiles","text-subdued":"app-module__text-subdued___7rYtR_betterDlocalDfiles","album-header":"app-module__album-header___J1nVK_betterDlocalDfiles","search-container":"app-module__search-container___SlAU8_betterDlocalDfiles","search-icon":"app-module__search-icon___-9z2r_betterDlocalDfiles","clear-icon":"app-module__clear-icon___pSLvx_betterDlocalDfiles",controls:"app-module__controls___ZDW-X_betterDlocalDfiles","flex-centered":"app-module__flex-centered___5gRmM_betterDlocalDfiles","display-list":"app-module__display-list___8BLJG_betterDlocalDfiles","display-list-compact":"app-module__display-list-compact___sbWJt_betterDlocalDfiles","limit-lines-2":"app-module__limit-lines-2___GyZCj_betterDlocalDfiles","text-full-centered":"app-module__text-full-centered___xI2eE_betterDlocalDfiles"},st=function(e,t){return(st=Object.setPrototypeOf||({__proto__:[]}instanceof Array?function(e,t){e.__proto__=t}:function(e,t){for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a])}))(e,t)};function g(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function a(){this.constructor=e}st(e,t),e.prototype=null===t?Object.create(t):(a.prototype=t.prototype,new a)}function ut(e){var t="function"==typeof Symbol&&Symbol.iterator,a=t&&e[t],r=0;if(a)return a.call(e);if(e&&"number"==typeof e.length)return{next:function(){return{value:(e=e&&r>=e.length?void 0:e)&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function dt(e,t){var a="function"==typeof Symbol&&e[Symbol.iterator];if(!a)return e;var r,n,i=a.call(e),l=[];try{for(;(void 0===t||0{var e=(0,pa.forwardRef)(({color:e="currentColor",size:t=24,strokeWidth:a=2,absoluteStrokeWidth:r,className:n="",children:i,...l},o)=>(0,pa.createElement)("svg",{ref:o,...fa,width:t,height:t,stroke:e,strokeWidth:r?24*Number(a)/Number(t):a,className:["lucide","lucide-"+c.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase().trim(),n].join(" "),...l},[...s.map(([e,t])=>(0,pa.createElement)(e,t)),...Array.isArray(i)?i:[i]]));return e.displayName=""+c,e},_a=e("ArrowDown",[["path",{d:"M12 5v14",key:"s699le"}],["path",{d:"m19 12-7 7-7-7",key:"1idqje"}]]),ha=e("ArrowUp",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]),ba=e("Folder",[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]]),va=e("Search",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]]),x=t(r(),1),ya=e=>e+1|0,Ea=()=>{const e=(0,x.useState)(0)[1];return(0,x.useRef)(()=>e(ya)).current},ga=(()=>"undefined"==typeof window?x.useEffect:x.useLayoutEffect)(),Da=e=>e[1]?.next?e[1]:{next:e[1],error:e[2],complete:e[3]};function ka(e,t,a,r){{var n=x.useEffect,i=[e,t,a,r];const l=(0,x.useRef)(i),o=(0,x.useRef)(),c=(0,x.useRef)();ga(()=>{l.current=i,o.current=Da(i)}),n(()=>{const t=l.current[0],e=(o.current||(o.current=Da(l.current)),t.subscribe({next:e=>{t===l.current[0]&&o.current.next?.(e)},error:e=>{t===l.current[0]&&(o.current.error?o.current:console).error(e)},complete:()=>{t===l.current[0]&&o.current.complete?.()}}));return c.current=e,()=>{e.unsubscribe()}},[i[0]]),c}}function wa(e){const r=Ea(),n=(0,x.useRef)(e),i=(0,x.useRef)(),l=(0,x.useRef)(!1),a=(0,x.useRef)(!1),[o,c]=(0,x.useState)(()=>{let t;return e.subscribe({next:e=>{a.current=!0,t=e},error:e=>{i.current=e}}).unsubscribe(),t});if(ga(()=>{n.current=e}),(0,x.useEffect)(()=>{i.current=null;const t=n.current;let a=o;const e=t.subscribe({next:e=>{t===n.current&&(l.current?c(e):a=e)},error:e=>{t===n.current&&(i.current=e,r())}});return l.current||a!==o&&c(a),l.current=!0,()=>{e.unsubscribe()}},[e]),i.current)throw i.current;if(a.current)return(0,x.useDebugValue)(o),o;throw new Error("Observable did not synchronously emit a value.")}function Sa(t){const[a,e]=function(e){const[t]=(0,x.useState)(()=>new Qt(e));var[a]=(0,x.useState)(()=>({get current(){return t.value},set current(e){t.next(e)}}));return[a,t]}(t.search);var i,l,o,c;function r(e){a.current=e,t.setSearch(e)}return ka(e.pipe((o=400,void 0===c&&(c=da),Ft(function(e,a){var r=null,t=null,n=null,i=function(){var e;r&&(r.unsubscribe(),e=t,t=r=null,a.next(e))};function l(){var e=n+o,t=c.now();t{r(e.target.value)}}),ot.default.createElement(Spicetify.ReactComponent.ButtonTertiary,{iconOnly:()=>ot.default.createElement(_,{icon:"x",iconSize:16}),buttonSize:"sm",className:ct["clear-icon"],onClick:()=>{r("")},style:{visibility:t.search?"visible":"hidden"}}))}var N=t(r()),Ia={list:"list-view",compact:"menu",grid:"grid-view"},xa=t(r());function Na(e){return xa.default.createElement("li",null,xa.default.createElement(b,{className:"main-contextMenu-menuHeading ellipsis-one-line",variant:"finaleBold"},e.children))}var Ca=t(r());function Ra(e){return Ca.default.createElement(b,{className:"main-contextMenu-menuItemLabel ellipsis-one-line",variant:"mesto"},e.children)}function La(t){var e=N.default.createElement(N.default.Fragment,null,N.default.createElement(Na,null,f(["drop_down.sort_by"])),t.sortOptions.map(e=>N.default.createElement(Spicetify.ReactComponent.MenuItem,{key:e.key,onClick:()=>{t.setSelectedSortOption(e.key)},role:"menuitemradio","aria-checked":t.selectedSortOption.key===e.key,CheckedIcon:()=>"ascending"===t.selectedSortOption.order?N.default.createElement(ha,null):N.default.createElement(_a,null)},N.default.createElement(Ra,null,e.label)))),a=N.default.createElement(N.default.Fragment,null,N.default.createElement(Na,null,f(["web-player.your-library-x.sort-and-view-picker.view-as"])),t.displayTypes.map(e=>N.default.createElement(Spicetify.ReactComponent.MenuItem,{key:e,onClick:()=>{t.setSelectedDisplayType(e)},leadingIcon:N.default.createElement(_,{icon:Ia[e],iconSize:16}),role:"menuitemradio","aria-checked":t.selectedDisplayType===e},N.default.createElement(Ra,null,f(["web-player.your-library-x.sort-and-view-picker."+e]))))),e=N.default.createElement(Spicetify.ReactComponent.Menu,{className:Se},0e.key===t.selectedSortOption.key)?.label??""),N.default.createElement(_,{icon:Ia[t.selectedDisplayType],iconSize:16})))}function Ta(e,t,a){a="descending"===a?-1:1;return te);const l=(0,y.useMemo)(()=>{return e=i,""===(t=a)?e:e.filter(e=>e.name.toLowerCase().includes(t.toLowerCase())||e.artists.some(e=>e.name.toLowerCase().includes(t.toLowerCase())));var e,t},[i,a]),[o,c]=(0,y.useState)({...n[0],order:"ascending"});var s=(0,y.useMemo)(()=>{return[...(e=l,"title"===(a=o).key?e.sort((e,t)=>Ta(e.name,t.name,a.order)):e)];var e,a},[l,o]);function u(e){ue(e.getTracks().map(e=>e.localTrack))}return y.default.createElement("div",{className:"contentSpacing"},y.default.createElement("div",{className:nt["album-header"]+" "+nt["pad-top"]},y.default.createElement("h1",null,f(["albums"])),y.default.createElement("div",{className:nt.controls},y.default.createElement(Sa,{search:e,setSearch:t,setDebouncedSearch:r}),y.default.createElement(La,{sortOptions:n,selectedSortOption:o,setSelectedSortOption:function(t){c(e=>{return{key:t,order:e.key===t&&"ascending"===e.order?"descending":"ascending"}})},displayTypes:["grid"],selectedDisplayType:"grid",setSelectedDisplayType:()=>{}}))),y.default.createElement("div",{className:nt["album-grid"]+" main-gridContainer-gridContainer main-gridContainer-fixedWidth"},s.map(e=>y.default.createElement(lt,{key:e.uri,album:e,onPlayClicked:u}))))}var C=t(r()),R=t(r()),Aa=t(r());function Ma(e){const t=` +
+ +
`;return Aa.default.createElement(Aa.default.Fragment,null,Aa.default.createElement("img",{loading:"eager",src:e.track.localTrack.album.images[0]?.url??t,className:"main-image-image main-trackList-rowImage main-image-loaded",width:"40",height:"40",onError:e=>e.currentTarget.outerHTML=t}),Aa.default.createElement(Xe,{track:e.track,withArtists:e.withArtists}))}var za=t(r());function Pa(e){return za.default.createElement(b,{variant:"mesto"},za.default.createElement("a",{className:"standalone-ellipsis-one-line",dir:"auto",href:"#",tabIndex:-1,onClick:()=>{l(Ee,e.track.album.uri)}},e.track.album.name))}function Ha(t){var e=[{key:"title",label:f(["sort.title"])},{key:"album",label:f(["sort.album"])}];return R.default.createElement(R.default.Fragment,null,R.default.createElement("div",{className:"main-actionBar-ActionBar contentSpacing"},R.default.createElement("div",{className:"main-actionBar-ActionBarRow"},R.default.createElement("div",{className:"main-playButton-PlayButton"},R.default.createElement(pe,{size:"lg",onClick:()=>{ue(t.tracks.map(e=>e.localTrack))}})),R.default.createElement(Ze,{label:f(["more.label.context"],t.artist.name),menu:R.default.createElement(Ye,{tracks:t.tracks})}))),R.default.createElement(je,{tracks:t.tracks,subtracks:[],gridLabel:t.artist.name,useTrackNumber:!1,onPlayTrack:e=>{se(e,t.tracks.map(e=>e.localTrack))},headers:e,getRowContent:e=>[R.default.createElement(Ma,{key:e.uri,track:e,withArtists:!1}),R.default.createElement(Pa,{key:e.uri,track:e})],displayType:"list"}))}function Ba(e){return C.default.createElement(tt,{image:C.default.createElement(et,{imageSrc:e.artist.image}),subtitle:f(["artist"]),title:e.artist.name})}function $a(){var e=p("History"),t=e.location.state.uri??null;return null===t?(e.replace(De),C.default.createElement(C.default.Fragment,null)):(e=window.localTracksService.getArtists()).has(t)?(e=e.get(t),t=window.localTracksService.getArtistTracks(e.uri),C.default.createElement(C.default.Fragment,null,null!==e&&C.default.createElement(C.default.Fragment,null,C.default.createElement(Ba,{artist:e}),C.default.createElement(Ha,{tracks:t,artist:e})))):(l(De),C.default.createElement(C.default.Fragment,null))}var L=t(r()),Ga={"stretch-container":"app-module__stretch-container___SIzsh_betterDlocalDfiles","center-container":"app-module__center-container___LG8O4_betterDlocalDfiles","full-size-container":"app-module__full-size-container___XoGtP_betterDlocalDfiles","pad-top":"app-module__pad-top___8OIp9_betterDlocalDfiles",tabBar:"app-module__tabBar___EngzO_betterDlocalDfiles",active:"app-module__active___JYUKA_betterDlocalDfiles","album-grid":"app-module__album-grid___JeelH_betterDlocalDfiles","main-card-card":"app-module__main-card-card___E9Zy2_betterDlocalDfiles","text-subdued":"app-module__text-subdued___7rYtR_betterDlocalDfiles","album-header":"app-module__album-header___J1nVK_betterDlocalDfiles","search-container":"app-module__search-container___SlAU8_betterDlocalDfiles","search-icon":"app-module__search-icon___-9z2r_betterDlocalDfiles","clear-icon":"app-module__clear-icon___pSLvx_betterDlocalDfiles",controls:"app-module__controls___ZDW-X_betterDlocalDfiles","flex-centered":"app-module__flex-centered___5gRmM_betterDlocalDfiles","display-list":"app-module__display-list___8BLJG_betterDlocalDfiles","display-list-compact":"app-module__display-list-compact___sbWJt_betterDlocalDfiles","limit-lines-2":"app-module__limit-lines-2___GyZCj_betterDlocalDfiles","text-full-centered":"app-module__text-full-centered___xI2eE_betterDlocalDfiles"},T=t(r()),Fa={"stretch-container":"app-module__stretch-container___SIzsh_betterDlocalDfiles","center-container":"app-module__center-container___LG8O4_betterDlocalDfiles","full-size-container":"app-module__full-size-container___XoGtP_betterDlocalDfiles","pad-top":"app-module__pad-top___8OIp9_betterDlocalDfiles",tabBar:"app-module__tabBar___EngzO_betterDlocalDfiles",active:"app-module__active___JYUKA_betterDlocalDfiles","album-grid":"app-module__album-grid___JeelH_betterDlocalDfiles","main-card-card":"app-module__main-card-card___E9Zy2_betterDlocalDfiles","text-subdued":"app-module__text-subdued___7rYtR_betterDlocalDfiles","album-header":"app-module__album-header___J1nVK_betterDlocalDfiles","search-container":"app-module__search-container___SlAU8_betterDlocalDfiles","search-icon":"app-module__search-icon___-9z2r_betterDlocalDfiles","clear-icon":"app-module__clear-icon___pSLvx_betterDlocalDfiles",controls:"app-module__controls___ZDW-X_betterDlocalDfiles","flex-centered":"app-module__flex-centered___5gRmM_betterDlocalDfiles","display-list":"app-module__display-list___8BLJG_betterDlocalDfiles","display-list-compact":"app-module__display-list-compact___sbWJt_betterDlocalDfiles","limit-lines-2":"app-module__limit-lines-2___GyZCj_betterDlocalDfiles","text-full-centered":"app-module__text-full-centered___xI2eE_betterDlocalDfiles"};function ja(e){var t=(0,T.useRef)(null),a=be(t),r=T.default.createElement("div",{style:{height:"260px"}});const n=` +
+ + + + + +
`;return T.default.createElement("div",{ref:t},a?T.default.createElement(Spicetify.ReactComponent.RightClickMenu,{menu:T.default.createElement(Ye,{tracks:window.localTracksService.getArtistTracks(e.artist.uri)})},T.default.createElement("div",{className:Fa["main-card-card"]+" main-card-card",onClick:()=>{l(u,e.artist.uri)}},T.default.createElement("div",{draggable:"true",className:"main-card-draggable"},T.default.createElement("div",{className:"main-card-imageContainer main-card-imageContainerOld"},T.default.createElement("div",{className:"main-cardImage-imageWrapper main-cardImage-circular"},T.default.createElement("img",{"aria-hidden":"false",draggable:"false",loading:"lazy",src:e.artist.image,alt:"artist image",className:"main-image-image main-cardImage-image main-cardImage-circular main-image-loading main-image-loaded",onError:e=>e.currentTarget.outerHTML=n})),T.default.createElement("div",{className:"main-card-PlayButtonContainer"},T.default.createElement("div",{className:"main-playButton-PlayButton"},T.default.createElement(pe,{size:"md",onClick:()=>{e.onPlayClicked(e.artist)}})))),T.default.createElement("div",{className:"main-card-cardMetadata"},T.default.createElement(b,{className:"main-cardHeader-link main-cardHeader-text "+Fa["text-full-centered"],variant:"balladBold",semanticColor:"textBase",paddingBottom:"4px"},e.artist.name))))):r)}function Ua(){var[e,t]=(0,L.useState)("");const[a,r]=(0,L.useState)("");var n=[{key:"title",label:f(["collection.sort.alphabetical"])}];const i=Array.from(window.localTracksService.getArtists()).map(([,e])=>e);const l=(0,L.useMemo)(()=>{return e=i,""===(t=a)?e:e.filter(e=>e.name.toLowerCase().includes(t.toLowerCase()));var e,t},[i,a]),[o,c]=(0,L.useState)({...n[0],order:"ascending"});var s=(0,L.useMemo)(()=>{return[...(e=l,"title"===(a=o).key?e.sort((e,t)=>Ta(e.name,t.name,a.order)):e)];var e,a},[l,o]);function u(e){ue(window.localTracksService.getArtistTracks(e.uri).map(e=>e.localTrack))}return L.default.createElement("div",{className:"contentSpacing"},L.default.createElement("div",{className:Ga["album-header"]+" "+Ga["pad-top"]},L.default.createElement("h1",null,f(["artists"])),L.default.createElement("div",{className:Ga.controls},L.default.createElement(Sa,{search:e,setSearch:t,setDebouncedSearch:r}),L.default.createElement(La,{sortOptions:n,selectedSortOption:o,setSelectedSortOption:function(t){c(e=>{return{key:t,order:e.key===t&&"ascending"===e.order?"descending":"ascending"}})},displayTypes:["grid"],selectedDisplayType:"grid",setSelectedDisplayType:()=>{}}))),L.default.createElement("div",{className:Ga["album-grid"]+" main-gridContainer-gridContainer main-gridContainer-fixedWidth"},s.map(e=>L.default.createElement(ja,{key:e.uri,artist:e,onPlayClicked:u}))))}var Xa=t(r());function Wa(){return Xa.default.createElement("svg",{width:"100px",height:"100px",viewBox:"0 0 100 100",preserveAspectRatio:"xMidYMid"},Xa.default.createElement("circle",{cx:"50",cy:"50",r:"0",fill:"none",stroke:"currentColor",strokeWidth:"2"},Xa.default.createElement("animate",{attributeName:"r",repeatCount:"indefinite",dur:"1s",values:"0;40",keyTimes:"0;1",keySplines:"0 0.2 0.8 1",calcMode:"spline",begin:"0s"}),Xa.default.createElement("animate",{attributeName:"opacity",repeatCount:"indefinite",dur:"1s",values:"1;0",keyTimes:"0;1",keySplines:"0.2 0 0.8 1",calcMode:"spline",begin:"0s"})),Xa.default.createElement("circle",{cx:"50",cy:"50",r:"0",fill:"none",stroke:"currentColor",strokeWidth:"2"},Xa.default.createElement("animate",{attributeName:"r",repeatCount:"indefinite",dur:"1s",values:"0;40",keyTimes:"0;1",keySplines:"0 0.2 0.8 1",calcMode:"spline",begin:"-0.5s"}),Xa.default.createElement("animate",{attributeName:"opacity",repeatCount:"indefinite",dur:"1s",values:"1;0",keyTimes:"0;1",keySplines:"0.2 0 0.8 1",calcMode:"spline",begin:"-0.5s"})))}var Ja=t(r()),O=t(r()),Va=t(r()),Za="app-module__active___JYUKA_betterDlocalDfiles";function Ka(e){return Va.default.createElement("li",{"data-tab":e.item.key,onClick:()=>{e.onItemClicked(e.item)}},Va.default.createElement("button",{className:e.active?Za:"",draggable:"false"},Va.default.createElement(b,{variant:"mestoBold"},e.item.label)))}var Ya=t(r());function qa(a){var e={width:a.size+"px"};return Ya.default.createElement("li",{id:"more-button",style:e},Ya.default.createElement(Spicetify.ReactComponent.Dropdown,{value:a.activeItem.key,disabled:!1,onSelect:t=>{var e=a.items.find(e=>e.key===t);e&&a.onClick(e)}},a.items.map(e=>Ya.default.createElement("option",{key:e.key,value:e.key},e.label))))}var Qa={"stretch-container":"app-module__stretch-container___SIzsh_betterDlocalDfiles","center-container":"app-module__center-container___LG8O4_betterDlocalDfiles","full-size-container":"app-module__full-size-container___XoGtP_betterDlocalDfiles","pad-top":"app-module__pad-top___8OIp9_betterDlocalDfiles",tabBar:"app-module__tabBar___EngzO_betterDlocalDfiles",active:"app-module__active___JYUKA_betterDlocalDfiles","album-grid":"app-module__album-grid___JeelH_betterDlocalDfiles","main-card-card":"app-module__main-card-card___E9Zy2_betterDlocalDfiles","text-subdued":"app-module__text-subdued___7rYtR_betterDlocalDfiles","album-header":"app-module__album-header___J1nVK_betterDlocalDfiles","search-container":"app-module__search-container___SlAU8_betterDlocalDfiles","search-icon":"app-module__search-icon___-9z2r_betterDlocalDfiles","clear-icon":"app-module__clear-icon___pSLvx_betterDlocalDfiles",controls:"app-module__controls___ZDW-X_betterDlocalDfiles","flex-centered":"app-module__flex-centered___5gRmM_betterDlocalDfiles","display-list":"app-module__display-list___8BLJG_betterDlocalDfiles","display-list-compact":"app-module__display-list-compact___sbWJt_betterDlocalDfiles","limit-lines-2":"app-module__limit-lines-2___GyZCj_betterDlocalDfiles","text-full-centered":"app-module__text-full-centered___xI2eE_betterDlocalDfiles"};function er(a){const t=O.default.useRef(null),[n,r]=(0,O.useState)([]),[i,e]=(0,O.useState)(0),[l,o]=(0,O.useState)([]),[c,s]=(0,O.useState)(0);return(0,O.useEffect)(()=>{t.current&&e(t.current.clientWidth)},[a.windowSize]),(0,O.useEffect)(()=>{var e;t.current&&(e=Array.from(t.current.children).filter(e=>"more-button"!==e.id).map(e=>e.clientWidth),r(e))},[a.items]),(0,O.useEffect)(()=>{if(t.current)if(n.reduce((e,t)=>e+t,0)<=i)o([]);else{var e=Math.max(...n)+32;const r=[];let a=e;n.forEach((e,t)=>{i>=a+e?a+=e:r.push(t)}),o(r),s(e)}},[i,n]),O.default.createElement("nav",{className:Qa.tabBar},O.default.createElement("ul",{ref:t},a.items.filter((e,t)=>!l.includes(t)).map(e=>O.default.createElement(Ka,{key:e.key,item:e,active:a.activeItem.key===e.key,onItemClicked:a.onItemClicked})),l.length||0===n.length?O.default.createElement(qa,{items:a.items.filter((e,t)=>l.includes(t)||e.key===a.activeItem.key),activeItem:a.activeItem,onClick:a.onItemClicked,size:c}):null))}function tr(e){const t=document.querySelector(".Root__main-view .os-resize-observer-host")??document.querySelector(".Root__main-view .os-size-observer");if(!t)throw new Error("Could not find resize host");const[a,r]=(0,Ja.useState)(t.clientWidth),n=()=>{r(t.clientWidth)};return(0,Ja.useEffect)(()=>{const e=new ResizeObserver(n);return e.observe(t),()=>{e.disconnect()}},[]),Ja.default.createElement(er,{windowSize:a,items:e.items,activeItem:e.activeItem,onItemClicked:e.onItemClicked})}var A=t(r()),ar={"stretch-container":"app-module__stretch-container___SIzsh_betterDlocalDfiles","center-container":"app-module__center-container___LG8O4_betterDlocalDfiles","full-size-container":"app-module__full-size-container___XoGtP_betterDlocalDfiles","pad-top":"app-module__pad-top___8OIp9_betterDlocalDfiles",tabBar:"app-module__tabBar___EngzO_betterDlocalDfiles",active:"app-module__active___JYUKA_betterDlocalDfiles","album-grid":"app-module__album-grid___JeelH_betterDlocalDfiles","main-card-card":"app-module__main-card-card___E9Zy2_betterDlocalDfiles","text-subdued":"app-module__text-subdued___7rYtR_betterDlocalDfiles","album-header":"app-module__album-header___J1nVK_betterDlocalDfiles","search-container":"app-module__search-container___SlAU8_betterDlocalDfiles","search-icon":"app-module__search-icon___-9z2r_betterDlocalDfiles","clear-icon":"app-module__clear-icon___pSLvx_betterDlocalDfiles",controls:"app-module__controls___ZDW-X_betterDlocalDfiles","flex-centered":"app-module__flex-centered___5gRmM_betterDlocalDfiles","display-list":"app-module__display-list___8BLJG_betterDlocalDfiles","display-list-compact":"app-module__display-list-compact___sbWJt_betterDlocalDfiles","limit-lines-2":"app-module__limit-lines-2___GyZCj_betterDlocalDfiles","text-full-centered":"app-module__text-full-centered___xI2eE_betterDlocalDfiles"},M=t(r()),rr=t(r());function nr(e){return rr.default.createElement(b,{className:"standalone-ellipsis-one-line",variant:"mesto"},e.track.artists.map(e=>rr.default.createElement("a",{dir:"auto",href:"#",tabIndex:-1,onClick:()=>{l(u,e.uri)},key:e.uri},e.name)).reduce((e,t)=>null===e?[t]:[...e,rr.default.createElement(rr.default.Fragment,null,", "),t],null))}function ir(a){var[e,t]=(0,M.useState)("");const[r,n]=(0,M.useState)("");var i=[{key:"date",label:f(["sort.date-added"])},{key:"title",label:f(["sort.title"])},{key:"artist",label:f(["sort.artist"])},{key:"album",label:f(["sort.album"])},{key:"duration",label:f(["sort.duration"])}];const[l,o]=(0,M.useState)({...i[0],order:"ascending"}),[c,s]=(0,M.useState)("list");var u=[];"list"===c?u.push("artist"===l.key?{key:"artist",label:f(["artist"])}:{key:"title",label:f(["tracklist.header.title"])}):u.push({key:"title",label:f(["tracklist.header.title"])},{key:"artist",label:f(["artist"])}),u.push({key:"album",label:f(["tracklist.header.album"])},{key:"date",label:f(["tracklist.header.date-added"])});const d=(0,M.useMemo)(()=>{return e=a.tracks,""===(t=r)?e:e.filter(e=>e.name.toLowerCase().includes(t.toLowerCase())||e.album.name.toLowerCase().includes(t.toLowerCase())||e.artists.some(e=>e.name.toLowerCase().includes(t.toLowerCase())));var e,t},[a.tracks,r]),m=(0,M.useMemo)(()=>[...function(e,a){switch(a.key){case"date":return e.sort((e,t)=>Ta(e.addedAt,t.addedAt,a.order));case"title":return e.sort((e,t)=>Ta(e.name,t.name,a.order));case"artist":return e.sort((e,t)=>Ta(e.artists.map(e=>e.name).join(", "),t.artists.map(e=>e.name).join(", "),a.order));case"album":return e.sort((e,t)=>Ta(e.album.name,t.album.name,a.order));case"duration":return e.sort((e,t)=>Ta(e.duration,t.duration,a.order));default:return e}}(d,l)],[d,l]);function p(r,n){o(e=>{let t,a;return a=n||"title"!==r||"descending"!==l.order||"compact"===c?n||"artist"!==r||"descending"!==l.order||"compact"===c?(t=r,e.key===r&&"ascending"===e.order?"descending":"ascending"):(t="title","ascending"):(t="artist","ascending"),{key:t,order:a}})}return M.default.createElement(M.default.Fragment,null,M.default.createElement("div",{className:"main-actionBar-ActionBar contentSpacing"},M.default.createElement("div",{className:"main-actionBar-ActionBarRow"},M.default.createElement("div",{className:"main-playButton-PlayButton"},M.default.createElement(pe,{size:"lg",onClick:()=>{ue(m.map(e=>e.localTrack))}})),M.default.createElement("div",{className:""+ar.controls},M.default.createElement(Sa,{search:e,setSearch:t,setDebouncedSearch:n}),M.default.createElement(La,{sortOptions:i,selectedSortOption:l,setSelectedSortOption:e=>{p(e,!0)},displayTypes:["list","compact"],selectedDisplayType:c,setSelectedDisplayType:s})))),M.default.createElement(je,{tracks:m,subtracks:[],gridLabel:f(["local-files"]),useTrackNumber:!1,onPlayTrack:e=>{se(e,m.map(e=>e.localTrack))},headers:u,onHeaderClicked:e=>{p(e,!1)},sortedHeader:l,getRowContent:e=>{var t=["compact"===c?M.default.createElement(b,{className:"main-trackList-rowTitle standalone-ellipsis-one-line",variant:"ballad",semanticColor:"textBase",key:e.uri},e.name):M.default.createElement(Ma,{track:e,withArtists:!0,key:e.uri})];return"compact"===c&&t.push(M.default.createElement(nr,{track:e,key:e.uri})),t.push(M.default.createElement(Pa,{track:e,key:e.uri}),M.default.createElement(b,{variant:"mesto",semanticColor:"textSubdued",key:e.uri},e.addedAt.toLocaleDateString())),t},displayType:c}))}var lr={"stretch-container":"app-module__stretch-container___SIzsh_betterDlocalDfiles","center-container":"app-module__center-container___LG8O4_betterDlocalDfiles","full-size-container":"app-module__full-size-container___XoGtP_betterDlocalDfiles","pad-top":"app-module__pad-top___8OIp9_betterDlocalDfiles",tabBar:"app-module__tabBar___EngzO_betterDlocalDfiles",active:"app-module__active___JYUKA_betterDlocalDfiles","album-grid":"app-module__album-grid___JeelH_betterDlocalDfiles","main-card-card":"app-module__main-card-card___E9Zy2_betterDlocalDfiles","text-subdued":"app-module__text-subdued___7rYtR_betterDlocalDfiles","album-header":"app-module__album-header___J1nVK_betterDlocalDfiles","search-container":"app-module__search-container___SlAU8_betterDlocalDfiles","search-icon":"app-module__search-icon___-9z2r_betterDlocalDfiles","clear-icon":"app-module__clear-icon___pSLvx_betterDlocalDfiles",controls:"app-module__controls___ZDW-X_betterDlocalDfiles","flex-centered":"app-module__flex-centered___5gRmM_betterDlocalDfiles","display-list":"app-module__display-list___8BLJG_betterDlocalDfiles","display-list-compact":"app-module__display-list-compact___sbWJt_betterDlocalDfiles","limit-lines-2":"app-module__limit-lines-2___GyZCj_betterDlocalDfiles","text-full-centered":"app-module__text-full-centered___xI2eE_betterDlocalDfiles"};function or(){var e=Array.from(window.localTracksService.getTracks().values());return A.default.createElement(A.default.Fragment,null,A.default.createElement(tt,{image:A.default.createElement("div",{className:""+lr["center-container"],style:{background:"linear-gradient(126deg, rgba(69,8,245,1) 0%, rgba(111,86,235,1) 27%, rgba(151,159,225,1) 67%, rgba(189,228,217,1) 100%)",borderRadius:"4px"}},A.default.createElement(ba,{fill:"var(--spice-text)",size:100})),title:f(["local-files"]),titleFontSize:"6rem",metadata:A.default.createElement(A.default.Fragment,null,A.default.createElement(b,{variant:"mesto",className:"main-entityHeader-metaDataText"},f(["local-files.description"])),A.default.createElement(b,{variant:"mesto",className:"main-entityHeader-metaDataText"},f(["tracklist-header.songs-counter",1===e.length?"one":"other"],e.length)))}),A.default.createElement(ir,{tracks:e}))}var cr={"stretch-container":"app-module__stretch-container___SIzsh_betterDlocalDfiles","center-container":"app-module__center-container___LG8O4_betterDlocalDfiles","full-size-container":"app-module__full-size-container___XoGtP_betterDlocalDfiles","pad-top":"app-module__pad-top___8OIp9_betterDlocalDfiles",tabBar:"app-module__tabBar___EngzO_betterDlocalDfiles",active:"app-module__active___JYUKA_betterDlocalDfiles","album-grid":"app-module__album-grid___JeelH_betterDlocalDfiles","main-card-card":"app-module__main-card-card___E9Zy2_betterDlocalDfiles","text-subdued":"app-module__text-subdued___7rYtR_betterDlocalDfiles","album-header":"app-module__album-header___J1nVK_betterDlocalDfiles","search-container":"app-module__search-container___SlAU8_betterDlocalDfiles","search-icon":"app-module__search-icon___-9z2r_betterDlocalDfiles","clear-icon":"app-module__clear-icon___pSLvx_betterDlocalDfiles",controls:"app-module__controls___ZDW-X_betterDlocalDfiles","flex-centered":"app-module__flex-centered___5gRmM_betterDlocalDfiles","display-list":"app-module__display-list___8BLJG_betterDlocalDfiles","display-list-compact":"app-module__display-list-compact___sbWJt_betterDlocalDfiles","limit-lines-2":"app-module__limit-lines-2___GyZCj_betterDlocalDfiles","text-full-centered":"app-module__text-full-centered___xI2eE_betterDlocalDfiles"};var sr=function(){var e=wa(window.localTracksService.isReady$),t=wa(window.localTracksService.processedAlbums$),a=wa(window.localTracksService.albumCount$);(0,o.useEffect)(()=>{!async function(){await window.localTracksService.init(),await le("better-local-files",oe,{title:"New in v"+oe,content:o.default.createElement("p",null,o.default.createElement("ul",null,ce.map(e=>o.default.createElement("li",{key:e},e)))),isLarge:!0})}()},[]);const r=p("History"),n=r.location;let i=o.default.createElement(o.default.Fragment,null);switch(n.pathname){case ke:i=o.default.createElement(or,null);break;case Ee:i=o.default.createElement(rt,null);break;case ge:i=o.default.createElement(Oa,null);break;case u:i=o.default.createElement($a,null);break;case De:i=o.default.createElement(Ua,null);break;default:r.replace(ke)}var l=document.querySelector(".main-topBar-topbarContentWrapper");return o.default.createElement(o.default.Fragment,null,o.default.createElement("div",{className:cr["full-size-container"]},e?o.default.createElement("div",{className:cr["stretch-container"]+" "+cr.padded},i):o.default.createElement("div",{className:cr["center-container"]+" "+cr.padded},o.default.createElement(Wa,null),0===a&&o.default.createElement("p",null,"Processing tracks..."),0{r.push(e.href)},items:we,activeItem:we.find(e=>e.href.startsWith(n.pathname))??we[0]}),l))},ur=t(r());return U=Q,j(H({},"__esModule",{value:!0}),U)})();const render=()=>betterDlocalDfiles.default(); \ No newline at end of file diff --git a/.config/spicetify/CustomApps/better-local-files/manifest.json b/.config/spicetify/CustomApps/better-local-files/manifest.json new file mode 100644 index 00000000..ccfde349 --- /dev/null +++ b/.config/spicetify/CustomApps/better-local-files/manifest.json @@ -0,0 +1,9 @@ +{ + "name": "Local Files", + "icon": "", + "active-icon": "", + "subfiles": [], + "subfiles_extension": [ + "extension.js" + ] +} \ No newline at end of file diff --git a/.config/spicetify/CustomApps/better-local-files/preview.png b/.config/spicetify/CustomApps/better-local-files/preview.png new file mode 100644 index 00000000..f87bcac8 Binary files /dev/null and b/.config/spicetify/CustomApps/better-local-files/preview.png differ diff --git a/.config/spicetify/CustomApps/better-local-files/style.css b/.config/spicetify/CustomApps/better-local-files/style.css new file mode 100644 index 00000000..492e566d --- /dev/null +++ b/.config/spicetify/CustomApps/better-local-files/style.css @@ -0,0 +1 @@ +.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%}.app-module__center-container___LG8O4_betterDlocalDfiles,.app-module__stretch-container___SIzsh_betterDlocalDfiles{display:flex;flex-direction:column;height:100%}.app-module__stretch-container___SIzsh_betterDlocalDfiles{justify-content:stretch;align-items:stretch}.app-module__center-container___LG8O4_betterDlocalDfiles{justify-content:center;align-items:center}.app-module__full-size-container___XoGtP_betterDlocalDfiles{position:absolute;left:0;right:0;top:0;bottom:0}.app-module__pad-top___8OIp9_betterDlocalDfiles{padding-top:64px}.app-module__tabBar___EngzO_betterDlocalDfiles ul{display:flex;flex-direction:row;align-items:stretch}.app-module__tabBar___EngzO_betterDlocalDfiles ul li{pointer-events:all}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button{border-radius:4px;border-style:none;color:var(--spice-text);background-color:transparent;margin:0 8px 0 0;padding:8px 16px;cursor:pointer}.app-module__tabBar___EngzO_betterDlocalDfiles ul li button.app-module__active___JYUKA_betterDlocalDfiles{background-color:var(--spice-tab-active);border-radius:4px}.app-module__tabBar___EngzO_betterDlocalDfiles ul select{height:100%}.app-module__album-grid___JeelH_betterDlocalDfiles{--minimumColumnWidth:180px;--column-width:minmax(var(--minimumColumnWidth), 1fr);--column-count:auto-fill;--grid-gap:24px}.app-module__album-grid___JeelH_betterDlocalDfiles .app-module__main-card-card___E9Zy2_betterDlocalDfiles{cursor:pointer;height:100%;border-radius:6.3px}.app-module__text-subdued___7rYtR_betterDlocalDfiles{color:var(--text-subdued)}.app-module__album-header___J1nVK_betterDlocalDfiles{align-items:center;color:var(--spice-text);display:flex;justify-content:space-between;margin-bottom:16px}.app-module__album-header___J1nVK_betterDlocalDfiles h1{margin-top:0;font-size:1.5rem;font-weight:700}.app-module__search-container___SlAU8_betterDlocalDfiles{display:flex;align-items:center;background-color:rgba(var(--spice-rgb-selected-row),.1);border-radius:4px}.app-module__search-container___SlAU8_betterDlocalDfiles input{border-style:none;background-color:transparent;color:var(--spice-text)!important}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__search-icon___-9z2r_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;margin-left:8px;margin-top:4px;margin-right:8px;display:inline-block}.app-module__search-container___SlAU8_betterDlocalDfiles .app-module__clear-icon___pSLvx_betterDlocalDfiles{color:var(--spice-text);background-color:transparent;display:inline-block}.app-module__controls___ZDW-X_betterDlocalDfiles{-webkit-box-flex:1;-webkit-box-pack:end;-ms-flex-pack:end;display:flex;flex:1;gap:8px;justify-content:flex-end}.app-module__flex-centered___5gRmM_betterDlocalDfiles{display:flex;align-items:center}.app-module__display-list___8BLJG_betterDlocalDfiles{--row-height:56px}.app-module__display-list-compact___sbWJt_betterDlocalDfiles{--row-height:32px}.app-module__limit-lines-2___GyZCj_betterDlocalDfiles{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.app-module__text-full-centered___xI2eE_betterDlocalDfiles{text-align:center;width:100%} \ No newline at end of file diff --git a/.config/spicetify/CustomApps/library/collection_wrapper.js b/.config/spicetify/CustomApps/library/collection_wrapper.js new file mode 100644 index 00000000..4d78490d --- /dev/null +++ b/.config/spicetify/CustomApps/library/collection_wrapper.js @@ -0,0 +1,156 @@ +(async function() { + while (!Spicetify.React || !Spicetify.ReactDOM) { + await new Promise(resolve => setTimeout(resolve, 10)); + } + "use strict"; +var library = (() => { + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // src/extensions/collection_wrapper.tsx + var collection_wrapper_exports = {}; + __export(collection_wrapper_exports, { + default: () => collection_wrapper_default + }); + + // node_modules/uuid/dist/esm-browser/rng.js + var getRandomValues; + var rnds8 = new Uint8Array(16); + function rng() { + if (!getRandomValues) { + getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto); + if (!getRandomValues) { + throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported"); + } + } + return getRandomValues(rnds8); + } + + // node_modules/uuid/dist/esm-browser/stringify.js + var byteToHex = []; + for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 256).toString(16).slice(1)); + } + function unsafeStringify(arr, offset = 0) { + return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]; + } + + // node_modules/uuid/dist/esm-browser/native.js + var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto); + var native_default = { + randomUUID + }; + + // node_modules/uuid/dist/esm-browser/v4.js + function v4(options, buf, offset) { + if (native_default.randomUUID && !buf && !options) { + return native_default.randomUUID(); + } + options = options || {}; + const rnds = options.random || (options.rng || rng)(); + rnds[6] = rnds[6] & 15 | 64; + rnds[8] = rnds[8] & 63 | 128; + if (buf) { + offset = offset || 0; + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + return buf; + } + return unsafeStringify(rnds); + } + var v4_default = v4; + + // src/extensions/collection_wrapper.tsx + var CollectionWrapper = class { + constructor() { + this.getCollections = () => { + return this._collections; + }; + this.createCollection = (name) => { + const collection = { + id: v4_default(), + name, + items: [] + }; + this._collections.push(collection); + this.saveCollections(); + Spicetify.showNotification("Collection Created"); + return collection; + }; + this.deleteCollection = (collectionID) => { + this._collections = this._collections.filter((collection) => collection.id !== collectionID); + this.saveCollections(); + Spicetify.showNotification("Collection Deleted"); + }; + this.getCollection = (collectionID) => { + return this._collections.find((collection) => collection.id === collectionID); + }; + this.renameCollection = (collectionID, name) => { + const collection = this.getCollection(collectionID); + if (!collection) + throw new Error("Collection is not defined"); + collection.name = name; + this.saveCollections(); + Spicetify.showNotification("Collection Renamed"); + }; + this.addToCollection = (collectionID, albumURI) => { + const collection = this.getCollection(collectionID); + if (!collection) + throw new Error("Collection is not defined"); + Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.getAlbum, { + uri: albumURI, + locale: "en", + offset: 0, + limit: 1 + }).then((res) => { + var _a, _b, _c, _d, _e, _f, _g; + const data = res.data.albumUnion; + const albumItem = { + uri: data.uri, + name: data.name, + artist: (_d = (_c = (_b = (_a = data.artists) == null ? void 0 : _a.items) == null ? void 0 : _b[0]) == null ? void 0 : _c.profile) == null ? void 0 : _d.name, + image: ((_g = (_f = (_e = data.coverArt) == null ? void 0 : _e.sources) == null ? void 0 : _f[0]) == null ? void 0 : _g.url) || "" + }; + collection.items.push(albumItem); + this.saveCollections(); + }); + Spicetify.showNotification("Item Added to Collection"); + }; + this.removeFromCollection = (collectionID, albumURI) => { + const collection = this.getCollection(collectionID); + if (!collection) + throw new Error("Collection is not defined"); + collection.items = collection.items.filter((album) => album.uri !== albumURI); + this.saveCollections(); + Spicetify.showNotification("Item Removed from Collection"); + }; + this.getCollectionForItem = (albumURI) => { + return this._collections.filter((collection) => collection.items.some((item) => item.uri === albumURI)); + }; + this.saveCollections = () => { + localStorage.setItem("library:collections", JSON.stringify(this._collections)); + }; + this._collections = JSON.parse(localStorage.getItem("library:collections") || "[]"); + } + }; + var collection_wrapper_default = CollectionWrapper; + return __toCommonJS(collection_wrapper_exports); +})(); + + })(); \ No newline at end of file diff --git a/.config/spicetify/CustomApps/library/collections_wrapper.js b/.config/spicetify/CustomApps/library/collections_wrapper.js new file mode 100644 index 00000000..a4175d9d --- /dev/null +++ b/.config/spicetify/CustomApps/library/collections_wrapper.js @@ -0,0 +1,218 @@ +(async function() { + while (!Spicetify.React || !Spicetify.ReactDOM) { + await new Promise(resolve => setTimeout(resolve, 10)); + } + "use strict"; +var library = (() => { + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // src/extensions/collections_wrapper.ts + var collections_wrapper_exports = {}; + __export(collections_wrapper_exports, { + default: () => collections_wrapper_default + }); + + // ../node_modules/uuid/dist/esm-browser/rng.js + var getRandomValues; + var rnds8 = new Uint8Array(16); + function rng() { + if (!getRandomValues) { + getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto); + if (!getRandomValues) { + throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported"); + } + } + return getRandomValues(rnds8); + } + + // ../node_modules/uuid/dist/esm-browser/stringify.js + var byteToHex = []; + for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 256).toString(16).slice(1)); + } + function unsafeStringify(arr, offset = 0) { + return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]; + } + + // ../node_modules/uuid/dist/esm-browser/native.js + var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto); + var native_default = { + randomUUID + }; + + // ../node_modules/uuid/dist/esm-browser/v4.js + function v4(options, buf, offset) { + if (native_default.randomUUID && !buf && !options) { + return native_default.randomUUID(); + } + options = options || {}; + const rnds = options.random || (options.rng || rng)(); + rnds[6] = rnds[6] & 15 | 64; + rnds[8] = rnds[8] & 63 | 128; + if (buf) { + offset = offset || 0; + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + return buf; + } + return unsafeStringify(rnds); + } + var v4_default = v4; + + // src/extensions/collections_wrapper.ts + var CollectionWrapper = class extends EventTarget { + _collections; + constructor() { + super(); + this._collections = JSON.parse(localStorage.getItem("library:collections") || "[]"); + } + saveCollections() { + localStorage.setItem("library:collections", JSON.stringify(this._collections)); + this.dispatchEvent(new CustomEvent("update", { detail: this._collections })); + } + getCollection(uri) { + return this._collections.find((collection) => collection.uri === uri); + } + async requestAlbums({ sortOrder, textFilter }) { + const albums = await Spicetify.Platform.LibraryAPI.getContents({ + filters: ["0"], + sortOrder, + textFilter, + offset: 0, + limit: 9999 + }); + return albums; + } + async getCollectionItems(props) { + const { collectionUri, textFilter, sortOrder, rootlist, limit = 9999, offset = 0 } = props; + let collectionItems = this._collections; + let albumItems = []; + let unfilteredLength = this._collections.length; + let openedCollection = ""; + if (collectionUri) { + const collection = this.getCollection(collectionUri); + const res = await this.requestAlbums({ sortOrder, textFilter }); + const collectionSet = new Set(collection.items); + const commonElements = res.items.filter((item) => collectionSet.has(item.uri)); + const collections = this._collections.filter((collection2) => collection2.parentCollection === collectionUri); + openedCollection = collection.name; + collectionItems = collections; + albumItems = commonElements; + unfilteredLength = collection.totalLength; + } + if (textFilter) { + let regex = new RegExp("\\b" + textFilter, "i"); + collectionItems = collectionItems.filter((item) => { + return regex.test(item.name); + }); + } + if (rootlist && !collectionUri) { + const res = await this.requestAlbums({ sortOrder, textFilter }); + albumItems = res.items; + if (!textFilter) { + const collectionSet = new Set(this._collections.map((collection) => collection.items).flat()); + const uncommonElements = res.items.filter((item) => !collectionSet.has(item.uri)); + collectionItems = this._collections.filter((collection) => !collection.parentCollection); + albumItems = uncommonElements; + unfilteredLength = this._collections.length + uncommonElements.length; + } + } + if (offset > 0) + collectionItems = []; + return { + openedCollection, + items: [...collectionItems, ...albumItems.slice(offset, offset + limit)], + totalLength: albumItems.length + collectionItems.length, + unfilteredLength + }; + } + createCollection(name, parentCollection = "") { + const uri = v4_default(); + const collection = { + type: "collection", + uri, + name, + items: [], + totalLength: 0, + imgUrl: "", + parentCollection + }; + this._collections.push(collection); + this.saveCollections(); + Spicetify.showNotification("Collection created"); + } + deleteCollection(uri) { + this._collections = this._collections.filter((collection) => collection.uri !== uri); + this.saveCollections(); + Spicetify.showNotification("Collection deleted"); + } + async addAlbumToCollection(collectionUri, albumUri) { + const collection = this.getCollection(collectionUri); + if (!collection) + return; + collection.items.push(albumUri); + collection.totalLength++; + this.saveCollections(); + Spicetify.showNotification("Album added to collection"); + } + removeAlbumFromCollection(collectionUri, albumUri) { + const collection = this.getCollection(collectionUri); + if (!collection) + return; + collection.items = collection.items.filter((item) => item !== albumUri); + collection.totalLength--; + this.saveCollections(); + Spicetify.showNotification("Album removed from collection"); + } + getCollectionsWithAlbum(albumUri) { + return this._collections.filter((collection) => { + return collection.items.some((item) => item === albumUri); + }); + } + renameCollection(uri, newName) { + const collection = this.getCollection(uri); + if (!collection) + return; + collection.name = newName; + this.saveCollections(); + Spicetify.showNotification("Collection renamed"); + } + setCollectionImage(uri, imgUrl) { + const collection = this.getCollection(uri); + if (!collection) + return; + collection.imgUrl = imgUrl; + this.saveCollections(); + Spicetify.showNotification("Collection image set"); + } + removeCollectionImage(uri) { + const collection = this.getCollection(uri); + if (!collection) + return; + collection.imgUrl = ""; + this.saveCollections(); + Spicetify.showNotification("Collection image removed"); + } + }; + var collections_wrapper_default = CollectionWrapper; + return __toCommonJS(collections_wrapper_exports); +})(); + + })(); \ No newline at end of file diff --git a/.config/spicetify/CustomApps/library/config_loader.js b/.config/spicetify/CustomApps/library/config_loader.js new file mode 100644 index 00000000..ee9608dd --- /dev/null +++ b/.config/spicetify/CustomApps/library/config_loader.js @@ -0,0 +1,280 @@ +(async function() { + while (!Spicetify.React || !Spicetify.ReactDOM) { + await new Promise(resolve => setTimeout(resolve, 10)); + } + "use strict"; +var library = (() => { + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getOwnPropSymbols = Object.getOwnPropertySymbols; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __propIsEnum = Object.prototype.propertyIsEnumerable; + var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; + var __spreadValues = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + if (__getOwnPropSymbols) + for (var prop of __getOwnPropSymbols(b)) { + if (__propIsEnum.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + } + return a; + }; + var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + }; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod + )); + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // external-global-plugin:react + var require_react = __commonJS({ + "external-global-plugin:react"(exports, module) { + module.exports = Spicetify.React; + } + }); + + // src/extensions/config_loader.tsx + var config_loader_exports = {}; + __export(config_loader_exports, { + default: () => config_loader_default + }); + + // src/components/settings_modal.tsx + var import_react = __toESM(require_react()); + var TextInput = (props) => { + const textId = `text-input:${props.storageKey}`; + return /* @__PURE__ */ import_react.default.createElement("label", { + className: "text-input-wrapper" + }, /* @__PURE__ */ import_react.default.createElement("input", { + className: "text-input", + type: "text", + value: props.value || "", + "data-storage-key": props.storageKey, + placeholder: props.placeholder, + id: textId, + title: `Text input for ${props.storageKey}`, + onChange: props.onChange + })); + }; + var Dropdown = (props) => { + const dropdownId = `dropdown:${props.storageKey}`; + return /* @__PURE__ */ import_react.default.createElement("label", { + className: "dropdown-wrapper" + }, /* @__PURE__ */ import_react.default.createElement("select", { + className: "dropdown-input", + value: props.value, + "data-storage-key": props.storageKey, + id: dropdownId, + title: `Dropdown for ${props.storageKey}`, + onChange: props.onChange + }, props.options.map((option, index) => /* @__PURE__ */ import_react.default.createElement("option", { + key: index, + value: option + }, option)))); + }; + var TooltipIcon = () => { + return /* @__PURE__ */ import_react.default.createElement("svg", { + role: "img", + height: "16", + width: "16", + className: "Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4", + viewBox: "0 0 16 16" + }, /* @__PURE__ */ import_react.default.createElement("path", { + d: "M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z" + }), /* @__PURE__ */ import_react.default.createElement("path", { + d: "M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z" + })); + }; + var ConfigRow = (props) => { + console.log(props); + const enabled = !!props.modalConfig[props.storageKey]; + const value = props.modalConfig[props.storageKey]; + const updateItem = (storageKey, state) => { + props.modalConfig[storageKey] = state; + console.debug(`toggling ${storageKey} to ${state}`); + localStorage.setItem(`library:config:${storageKey}`, String(state)); + props.updateConfig(props.modalConfig); + }; + const settingsToggleChange = (newValue, storageKey) => { + updateItem(storageKey, newValue); + if (props.callback) + props.callback(newValue); + }; + const settingsTextChange = (event) => { + console.log("yoohoo"); + updateItem(event.target.dataset.storageKey, event.target.value); + console.log(props.callback); + if (props.callback) + props.callback(event.target.value); + }; + const settingsDropdownChange = (event) => { + updateItem(event.target.dataset.storageKey, event.target.value); + if (props.callback) + props.callback(event.target.value); + }; + const element = () => { + switch (props.type) { + case "dropdown": + return /* @__PURE__ */ import_react.default.createElement(Dropdown, { + name: props.name, + storageKey: props.storageKey, + value, + options: props.options || [], + onChange: settingsDropdownChange + }); + case "text": + return /* @__PURE__ */ import_react.default.createElement(TextInput, { + name: props.name, + storageKey: props.storageKey, + value, + placeholder: props.placeholder, + onChange: settingsTextChange + }); + default: + return /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.Toggle, { + id: `toggle:${props.storageKey}`, + value: enabled, + onSelected: (newValue) => { + settingsToggleChange(newValue, props.storageKey); + } + }); + } + }; + return /* @__PURE__ */ import_react.default.createElement("div", { + className: "setting-row" + }, /* @__PURE__ */ import_react.default.createElement("label", { + className: "col description" + }, props.name, props.desc && /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + label: /* @__PURE__ */ import_react.default.createElement("div", { + dangerouslySetInnerHTML: { __html: props.desc } + }), + renderInline: true, + showDelay: 10, + placement: "top", + labelClassName: "tooltip", + disabled: false + }, /* @__PURE__ */ import_react.default.createElement("div", { + className: "tooltip-icon" + }, /* @__PURE__ */ import_react.default.createElement(TooltipIcon, null)))), /* @__PURE__ */ import_react.default.createElement("div", { + className: "col action" + }, element())); + }; + var SettingsModal = ({ CONFIG, settings, updateAppConfig }) => { + const [modalConfig, setModalConfig] = import_react.default.useState(__spreadValues({}, CONFIG)); + const updateConfig = (CONFIG2) => { + updateAppConfig(__spreadValues({}, CONFIG2)); + setModalConfig(__spreadValues({}, CONFIG2)); + }; + const configRows = settings.map((setting, index) => { + console.log(setting); + if (setting.sectionHeader) { + return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, index != 0 ? /* @__PURE__ */ import_react.default.createElement("br", null) : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null), /* @__PURE__ */ import_react.default.createElement("h2", { + className: "section-header" + }, setting.sectionHeader), /* @__PURE__ */ import_react.default.createElement(ConfigRow, { + name: setting.name, + storageKey: setting.key, + type: setting.type, + options: setting.options, + placeholder: setting.placeholder, + desc: setting.desc, + modalConfig, + updateConfig, + callback: setting.callback + })); + } + return /* @__PURE__ */ import_react.default.createElement(ConfigRow, { + name: setting.name, + storageKey: setting.key, + type: setting.type, + options: setting.options, + placeholder: setting.placeholder, + desc: setting.desc, + modalConfig, + updateConfig, + callback: setting.callback + }); + }); + return /* @__PURE__ */ import_react.default.createElement("div", { + id: "stats-config-container" + }, configRows); + }; + var settings_modal_default = SettingsModal; + + // src/extensions/config_loader.tsx + var import_react2 = __toESM(require_react()); + var getLocalStorageDataFromKey = (key, fallback) => { + const data = localStorage.getItem(key); + if (data) { + try { + return JSON.parse(data); + } catch (err) { + return data; + } + } else { + return fallback; + } + }; + (function wait() { + const { LocalStorageAPI } = Spicetify == null ? void 0 : Spicetify.Platform; + if (!LocalStorageAPI) { + setTimeout(wait, 100); + return; + } + })(); + async function loadConfig(configSettings) { + const { PopupModal } = Spicetify; + await new Promise((resolve) => { + (function checkPopupModal() { + if (PopupModal) { + resolve(void 0); + } else { + setTimeout(checkPopupModal, 100); + } + })(); + }); + const settingsArray = configSettings.map((setting) => { + return { [setting.key]: getLocalStorageDataFromKey(`library:config:${setting.key}`, setting.def) }; + }); + let CONFIG = window.CONFIG = Object.assign({}, ...settingsArray); + const updateConfig = (config) => { + window.CONFIG = __spreadValues({}, config); + console.log("updated config", config); + }; + const launchModal = window.launchModal = () => { + console.log(settingsArray); + PopupModal.display({ + title: "Library Settings", + content: /* @__PURE__ */ import_react2.default.createElement(settings_modal_default, { + CONFIG, + settings: configSettings, + updateAppConfig: updateConfig + }), + isLarge: true + }); + }; + return { CONFIG, launchModal }; + } + var config_loader_default = loadConfig; + return __toCommonJS(config_loader_exports); +})(); + + })(); \ No newline at end of file diff --git a/.config/spicetify/CustomApps/library/config_wrapper.js b/.config/spicetify/CustomApps/library/config_wrapper.js new file mode 100644 index 00000000..6e0bdc0f --- /dev/null +++ b/.config/spicetify/CustomApps/library/config_wrapper.js @@ -0,0 +1,269 @@ +(async function() { + while (!Spicetify.React || !Spicetify.ReactDOM) { + await new Promise(resolve => setTimeout(resolve, 10)); + } + "use strict"; +var library = (() => { + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getOwnPropSymbols = Object.getOwnPropertySymbols; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __propIsEnum = Object.prototype.propertyIsEnumerable; + var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; + var __spreadValues = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + if (__getOwnPropSymbols) + for (var prop of __getOwnPropSymbols(b)) { + if (__propIsEnum.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + } + return a; + }; + var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + }; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod + )); + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // external-global-plugin:react + var require_react = __commonJS({ + "external-global-plugin:react"(exports, module) { + module.exports = Spicetify.React; + } + }); + + // src/extensions/config_wrapper.tsx + var config_wrapper_exports = {}; + __export(config_wrapper_exports, { + default: () => config_wrapper_default + }); + var import_react2 = __toESM(require_react()); + + // src/components/config/config_modal.tsx + var import_react = __toESM(require_react()); + var TextInput = (props) => { + const handleTextChange = (event) => { + props.callback(event.target.value); + }; + return /* @__PURE__ */ import_react.default.createElement("label", { + className: "text-input-wrapper" + }, /* @__PURE__ */ import_react.default.createElement("input", { + className: "text-input", + type: "text", + value: props.value || "", + "data-storage-key": props.storageKey, + placeholder: props.placeholder, + id: `text-input:${props.storageKey}`, + title: `Text input for ${props.storageKey}`, + onChange: handleTextChange + })); + }; + var Dropdown = (props) => { + const handleDropdownChange = (event) => { + props.callback(event.target.value); + }; + return /* @__PURE__ */ import_react.default.createElement("label", { + className: "dropdown-wrapper" + }, /* @__PURE__ */ import_react.default.createElement("select", { + className: "dropdown-input", + value: props.value, + "data-storage-key": props.storageKey, + id: `dropdown:${props.storageKey}`, + title: `Dropdown for ${props.storageKey}`, + onChange: handleDropdownChange + }, props.options.map((option, index) => /* @__PURE__ */ import_react.default.createElement("option", { + key: index, + value: option + }, option)))); + }; + var ToggleInput = (props) => { + const { Toggle } = Spicetify.ReactComponent; + const handleToggleChange = (newValue) => { + props.callback(newValue); + }; + return /* @__PURE__ */ import_react.default.createElement(Toggle, { + id: `toggle:${props.storageKey}`, + value: props.value, + onSelected: (newValue) => handleToggleChange(newValue) + }); + }; + var SliderInput = (props) => { + const { Slider } = Spicetify.ReactComponent; + const handleSliderChange = (newValue) => { + const calculatedValue = props.min + newValue * (props.max - props.min); + props.callback(calculatedValue); + }; + const value = (props.value - props.min) / (props.max - props.min); + return /* @__PURE__ */ import_react.default.createElement(Slider, { + id: `slider:${props.storageKey}`, + value, + min: 0, + max: 1, + step: 0.1, + onDragMove: (newValue) => handleSliderChange(newValue), + onDragStart: () => { + }, + onDragEnd: () => { + } + }); + }; + var TooltipIcon = () => { + return /* @__PURE__ */ import_react.default.createElement("svg", { + role: "img", + height: "16", + width: "16", + className: "Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4", + viewBox: "0 0 16 16" + }, /* @__PURE__ */ import_react.default.createElement("path", { + d: "M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z" + }), /* @__PURE__ */ import_react.default.createElement("path", { + d: "M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z" + })); + }; + var ConfigRow = (props) => { + return /* @__PURE__ */ import_react.default.createElement("div", { + className: "setting-row" + }, /* @__PURE__ */ import_react.default.createElement("label", { + className: "col description" + }, props.name, props.desc && /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + label: /* @__PURE__ */ import_react.default.createElement("div", { + dangerouslySetInnerHTML: { __html: props.desc } + }), + renderInline: true, + showDelay: 10, + placement: "top", + labelClassName: "tooltip", + disabled: false + }, /* @__PURE__ */ import_react.default.createElement("div", { + className: "tooltip-icon" + }, /* @__PURE__ */ import_react.default.createElement(TooltipIcon, null)))), /* @__PURE__ */ import_react.default.createElement("div", { + className: "col action" + }, props.children)); + }; + var ConfigModal = (props) => { + const { config, structure, updateAppConfig } = props; + const [modalConfig, setModalConfig] = import_react.default.useState(__spreadValues({}, config)); + const modalRows = structure.map((modalRow, index) => { + const key = modalRow.key; + const currentValue = modalConfig[key]; + const updateItem = (state) => { + console.debug(`toggling ${key} to ${state}`); + localStorage.setItem(`library:config:${key}`, String(state)); + if (modalRow.callback) + modalRow.callback(state); + const newConfig = __spreadValues({}, modalConfig); + newConfig[key] = state; + updateAppConfig(newConfig); + setModalConfig(newConfig); + }; + const header = modalRow.sectionHeader; + const element = () => { + switch (modalRow.type) { + case "toggle": + return /* @__PURE__ */ import_react.default.createElement(ToggleInput, { + storageKey: key, + value: currentValue, + callback: updateItem + }); + case "text": + return /* @__PURE__ */ import_react.default.createElement(TextInput, { + storageKey: key, + value: currentValue, + callback: updateItem + }); + case "dropdown": + return /* @__PURE__ */ import_react.default.createElement(Dropdown, { + storageKey: key, + value: currentValue, + options: modalRow.options, + callback: updateItem + }); + case "slider": + return /* @__PURE__ */ import_react.default.createElement(SliderInput, { + storageKey: key, + value: currentValue, + min: modalRow.min, + max: modalRow.max, + step: modalRow.step, + callback: updateItem + }); + } + }; + return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, header && index !== 0 && /* @__PURE__ */ import_react.default.createElement("br", null), header && /* @__PURE__ */ import_react.default.createElement("h2", { + className: "section-header" + }, modalRow.sectionHeader), /* @__PURE__ */ import_react.default.createElement(ConfigRow, { + name: modalRow.name, + desc: modalRow.desc + }, element())); + }); + return /* @__PURE__ */ import_react.default.createElement("div", { + id: "library-config-container" + }, modalRows); + }; + var config_modal_default = ConfigModal; + + // src/extensions/config_wrapper.tsx + var _ConfigWrapper = class { + constructor(modalStructure) { + const config = modalStructure.map((modalStructureRow) => { + var _a; + const value = _ConfigWrapper.getLocalStorageDataFromKey(`library:config:${modalStructureRow.key}`, modalStructureRow.def); + (_a = modalStructureRow.callback) == null ? void 0 : _a.call(modalStructureRow, value); + return { [modalStructureRow.key]: value }; + }); + this.Config = Object.assign({}, ...config); + this.launchModal = (callback) => { + const updateConfig = (config2) => { + this.Config = __spreadValues({}, config2); + callback == null ? void 0 : callback(config2); + }; + Spicetify.PopupModal.display({ + title: "Library Settings", + content: /* @__PURE__ */ import_react2.default.createElement(config_modal_default, { + config: this.Config, + structure: modalStructure, + updateAppConfig: updateConfig + }), + isLarge: true + }); + }; + } + }; + var ConfigWrapper = _ConfigWrapper; + ConfigWrapper.getLocalStorageDataFromKey = (key, fallback) => { + const data = localStorage.getItem(key); + if (data) { + try { + return JSON.parse(data); + } catch (err) { + return data; + } + } else { + return fallback; + } + }; + var config_wrapper_default = ConfigWrapper; + return __toCommonJS(config_wrapper_exports); +})(); + + })(); \ No newline at end of file diff --git a/.config/spicetify/CustomApps/library/context_menu_handler.js b/.config/spicetify/CustomApps/library/context_menu_handler.js new file mode 100644 index 00000000..04dfac26 --- /dev/null +++ b/.config/spicetify/CustomApps/library/context_menu_handler.js @@ -0,0 +1,19 @@ +(async function() { + while (!Spicetify.React || !Spicetify.ReactDOM) { + await new Promise(resolve => setTimeout(resolve, 10)); + } + "use strict"; +var library = (() => { + // src/extensions/context_menu_handler.tsx + var observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.addedNodes.length) { + const node = mutation.addedNodes[0]; + console.log(node); + } + }); + }); + observer.observe(document.body, { childList: true, subtree: false }); +})(); + + })(); \ No newline at end of file diff --git a/.config/spicetify/CustomApps/library/extension.js b/.config/spicetify/CustomApps/library/extension.js new file mode 100644 index 00000000..55f750cc --- /dev/null +++ b/.config/spicetify/CustomApps/library/extension.js @@ -0,0 +1,926 @@ +(async function() { + while (!Spicetify.React || !Spicetify.ReactDOM) { + await new Promise(resolve => setTimeout(resolve, 10)); + } + "use strict"; +var library = (() => { + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; + var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod + )); + var __publicField = (obj, key, value) => { + __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + return value; + }; + + // external-global-plugin:react + var require_react = __commonJS({ + "external-global-plugin:react"(exports, module) { + module.exports = Spicetify.React; + } + }); + + // external-global-plugin:react-dom + var require_react_dom = __commonJS({ + "external-global-plugin:react-dom"(exports, module) { + module.exports = Spicetify.ReactDOM; + } + }); + + // ../shared/config/config_wrapper.tsx + var import_react2 = __toESM(require_react()); + + // ../shared/config/config_modal.tsx + var import_react = __toESM(require_react()); + var TextInput = (props) => { + const handleTextChange = (event) => { + props.callback(event.target.value); + }; + return /* @__PURE__ */ import_react.default.createElement("label", { + className: "text-input-wrapper" + }, /* @__PURE__ */ import_react.default.createElement("input", { + className: "text-input", + type: "text", + value: props.value || "", + "data-storage-key": props.storageKey, + placeholder: props.placeholder, + id: `text-input:${props.storageKey}`, + title: `Text input for ${props.storageKey}`, + onChange: handleTextChange + })); + }; + var Dropdown = (props) => { + const handleDropdownChange = (event) => { + props.callback(event.target.value); + }; + return /* @__PURE__ */ import_react.default.createElement("label", { + className: "dropdown-wrapper" + }, /* @__PURE__ */ import_react.default.createElement("select", { + className: "dropdown-input", + value: props.value, + "data-storage-key": props.storageKey, + id: `dropdown:${props.storageKey}`, + title: `Dropdown for ${props.storageKey}`, + onChange: handleDropdownChange + }, props.options.map((option, index) => /* @__PURE__ */ import_react.default.createElement("option", { + key: index, + value: option + }, option)))); + }; + var ToggleInput = (props) => { + const { Toggle } = Spicetify.ReactComponent; + const handleToggleChange = (newValue) => { + props.callback(newValue); + }; + return /* @__PURE__ */ import_react.default.createElement(Toggle, { + id: `toggle:${props.storageKey}`, + value: props.value, + onSelected: (newValue) => handleToggleChange(newValue) + }); + }; + var SliderInput = (props) => { + const { Slider } = Spicetify.ReactComponent; + const handleSliderChange = (newValue) => { + const calculatedValue = props.min + newValue * (props.max - props.min); + props.callback(calculatedValue); + }; + const value = (props.value - props.min) / (props.max - props.min); + return /* @__PURE__ */ import_react.default.createElement(Slider, { + id: `slider:${props.storageKey}`, + value, + min: 0, + max: 1, + step: 0.1, + onDragMove: (newValue) => handleSliderChange(newValue), + onDragStart: () => { + }, + onDragEnd: () => { + } + }); + }; + var TooltipIcon = () => { + return /* @__PURE__ */ import_react.default.createElement("svg", { + role: "img", + height: "16", + width: "16", + className: "Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4", + viewBox: "0 0 16 16" + }, /* @__PURE__ */ import_react.default.createElement("path", { + d: "M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z" + }), /* @__PURE__ */ import_react.default.createElement("path", { + d: "M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z" + })); + }; + var ConfigRow = (props) => { + return /* @__PURE__ */ import_react.default.createElement("div", { + className: "setting-row" + }, /* @__PURE__ */ import_react.default.createElement("label", { + className: "col description" + }, props.name, props.desc && /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + label: /* @__PURE__ */ import_react.default.createElement("div", { + dangerouslySetInnerHTML: { __html: props.desc } + }), + renderInline: true, + showDelay: 10, + placement: "top", + labelClassName: "tooltip", + disabled: false + }, /* @__PURE__ */ import_react.default.createElement("div", { + className: "tooltip-icon" + }, /* @__PURE__ */ import_react.default.createElement(TooltipIcon, null)))), /* @__PURE__ */ import_react.default.createElement("div", { + className: "col action" + }, props.children)); + }; + var ConfigModal = (props) => { + const { config, structure, appKey, updateAppConfig } = props; + const [modalConfig, setModalConfig] = import_react.default.useState({ ...config }); + const modalRows = structure.map((modalRow, index) => { + const key = modalRow.key; + const currentValue = modalConfig[key]; + const updateItem = (state) => { + console.debug(`toggling ${key} to ${state}`); + localStorage.setItem(`${appKey}:config:${key}`, String(state)); + if (modalRow.callback) + modalRow.callback(state); + const newConfig = { ...modalConfig }; + newConfig[key] = state; + updateAppConfig(newConfig); + setModalConfig(newConfig); + }; + const header = modalRow.sectionHeader; + const element = () => { + switch (modalRow.type) { + case "toggle": + return /* @__PURE__ */ import_react.default.createElement(ToggleInput, { + storageKey: key, + value: currentValue, + callback: updateItem + }); + case "text": + return /* @__PURE__ */ import_react.default.createElement(TextInput, { + storageKey: key, + value: currentValue, + callback: updateItem + }); + case "dropdown": + return /* @__PURE__ */ import_react.default.createElement(Dropdown, { + storageKey: key, + value: currentValue, + options: modalRow.options, + callback: updateItem + }); + case "slider": + return /* @__PURE__ */ import_react.default.createElement(SliderInput, { + storageKey: key, + value: currentValue, + min: modalRow.min, + max: modalRow.max, + step: modalRow.step, + callback: updateItem + }); + } + }; + return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, header && index !== 0 && /* @__PURE__ */ import_react.default.createElement("br", null), header && /* @__PURE__ */ import_react.default.createElement("h2", { + className: "section-header" + }, modalRow.sectionHeader), /* @__PURE__ */ import_react.default.createElement(ConfigRow, { + name: modalRow.name, + desc: modalRow.desc + }, element())); + }); + return /* @__PURE__ */ import_react.default.createElement("div", { + className: "config-container" + }, modalRows); + }; + var config_modal_default = ConfigModal; + + // ../shared/config/config_wrapper.tsx + var _ConfigWrapper = class { + Config; + launchModal; + constructor(modalStructure, key) { + const config = modalStructure.map((modalStructureRow) => { + const value = _ConfigWrapper.getLocalStorageDataFromKey( + `${key}:config:${modalStructureRow.key}`, + modalStructureRow.def + ); + modalStructureRow.callback?.(value); + return { [modalStructureRow.key]: value }; + }); + this.Config = Object.assign({}, ...config); + this.launchModal = (callback) => { + const updateConfig = (config2) => { + this.Config = { ...config2 }; + callback?.(config2); + }; + Spicetify.PopupModal.display({ + title: `${key.charAt(0).toUpperCase() + key.slice(1)} Settings`, + content: /* @__PURE__ */ import_react2.default.createElement(config_modal_default, { + config: this.Config, + structure: modalStructure, + appKey: key, + updateAppConfig: updateConfig + }), + isLarge: true + }); + }; + } + }; + var ConfigWrapper = _ConfigWrapper; + __publicField(ConfigWrapper, "getLocalStorageDataFromKey", (key, fallback) => { + const data = localStorage.getItem(key); + if (data) { + try { + return JSON.parse(data); + } catch (err) { + return data; + } + } else { + return fallback; + } + }); + var config_wrapper_default = ConfigWrapper; + + // src/extensions/extension.tsx + var import_react10 = __toESM(require_react()); + var import_react_dom = __toESM(require_react_dom()); + + // src/components/toggle_filters.tsx + var import_react3 = __toESM(require_react()); + var UpIcon = () => { + const { IconComponent } = Spicetify.ReactComponent; + return /* @__PURE__ */ import_react3.default.createElement(IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: '' + }, + iconSize: 16 + }); + }; + var DownIcon = () => { + const { IconComponent } = Spicetify.ReactComponent; + return /* @__PURE__ */ import_react3.default.createElement(IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: '' + }, + iconSize: 16 + }); + }; + var ToggleFiltersButton = () => { + const [direction, setDirection] = import_react3.default.useState(document.body.classList.contains("show-ylx-filters") ? "up" : "down"); + const { ButtonTertiary } = Spicetify.ReactComponent; + const toggleDirection = () => { + if (direction === "down") { + document.body.classList.add("show-ylx-filters"); + setDirection("up"); + } else { + setDirection("down"); + document.body.classList.remove("show-ylx-filters"); + } + }; + const Icon = direction === "down" ? DownIcon : UpIcon; + return /* @__PURE__ */ import_react3.default.createElement(ButtonTertiary, { + buttonSize: "sm", + "aria-label": "Show Filters", + iconOnly: Icon, + onClick: toggleDirection + }); + }; + var toggle_filters_default = ToggleFiltersButton; + + // src/components/collapse_button.tsx + var import_react4 = __toESM(require_react()); + var collapseLibrary = () => { + Spicetify.Platform.LocalStorageAPI.setItem("ylx-sidebar-state", 1); + }; + var CollapseIcon = () => { + const { IconComponent } = Spicetify.ReactComponent; + return /* @__PURE__ */ import_react4.default.createElement(IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: '' + }, + iconSize: 16 + }); + }; + var CollapseButton = () => { + const { ButtonTertiary } = Spicetify.ReactComponent; + return /* @__PURE__ */ import_react4.default.createElement(ButtonTertiary, { + buttonSize: "sm", + "aria-label": "Show Filters", + iconOnly: CollapseIcon, + onClick: collapseLibrary + }); + }; + var collapse_button_default = CollapseButton; + + // src/components/expand_button.tsx + var import_react5 = __toESM(require_react()); + var expandLibrary = () => { + Spicetify.Platform.LocalStorageAPI.setItem("ylx-sidebar-state", 0); + }; + var ExpandIcon = () => { + const { IconComponent } = Spicetify.ReactComponent; + return /* @__PURE__ */ import_react5.default.createElement(IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: '' + }, + iconSize: 16 + }); + }; + var ExpandButton = () => { + const { ButtonTertiary } = Spicetify.ReactComponent; + return /* @__PURE__ */ import_react5.default.createElement(ButtonTertiary, { + buttonSize: "sm", + "aria-label": "Show Filters", + iconOnly: ExpandIcon, + onClick: expandLibrary + }); + }; + var expand_button_default = ExpandButton; + + // ../node_modules/uuid/dist/esm-browser/rng.js + var getRandomValues; + var rnds8 = new Uint8Array(16); + function rng() { + if (!getRandomValues) { + getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto); + if (!getRandomValues) { + throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported"); + } + } + return getRandomValues(rnds8); + } + + // ../node_modules/uuid/dist/esm-browser/stringify.js + var byteToHex = []; + for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 256).toString(16).slice(1)); + } + function unsafeStringify(arr, offset = 0) { + return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]; + } + + // ../node_modules/uuid/dist/esm-browser/native.js + var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto); + var native_default = { + randomUUID + }; + + // ../node_modules/uuid/dist/esm-browser/v4.js + function v4(options, buf, offset) { + if (native_default.randomUUID && !buf && !options) { + return native_default.randomUUID(); + } + options = options || {}; + const rnds = options.random || (options.rng || rng)(); + rnds[6] = rnds[6] & 15 | 64; + rnds[8] = rnds[8] & 63 | 128; + if (buf) { + offset = offset || 0; + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + return buf; + } + return unsafeStringify(rnds); + } + var v4_default = v4; + + // src/extensions/collections_wrapper.ts + var CollectionWrapper = class extends EventTarget { + _collections; + constructor() { + super(); + this._collections = JSON.parse(localStorage.getItem("library:collections") || "[]"); + } + saveCollections() { + localStorage.setItem("library:collections", JSON.stringify(this._collections)); + this.dispatchEvent(new CustomEvent("update", { detail: this._collections })); + } + getCollection(uri) { + return this._collections.find((collection) => collection.uri === uri); + } + async requestAlbums({ sortOrder, textFilter }) { + const albums = await Spicetify.Platform.LibraryAPI.getContents({ + filters: ["0"], + sortOrder, + textFilter, + offset: 0, + limit: 9999 + }); + return albums; + } + async getCollectionItems(props) { + const { collectionUri, textFilter, sortOrder, rootlist, limit = 9999, offset = 0 } = props; + let collectionItems = this._collections; + let albumItems = []; + let unfilteredLength = this._collections.length; + let openedCollection = ""; + if (collectionUri) { + const collection = this.getCollection(collectionUri); + const res = await this.requestAlbums({ sortOrder, textFilter }); + const collectionSet = new Set(collection.items); + const commonElements = res.items.filter((item) => collectionSet.has(item.uri)); + const collections = this._collections.filter((collection2) => collection2.parentCollection === collectionUri); + openedCollection = collection.name; + collectionItems = collections; + albumItems = commonElements; + unfilteredLength = collection.totalLength; + } + if (textFilter) { + let regex = new RegExp("\\b" + textFilter, "i"); + collectionItems = collectionItems.filter((item) => { + return regex.test(item.name); + }); + } + if (rootlist && !collectionUri) { + const res = await this.requestAlbums({ sortOrder, textFilter }); + albumItems = res.items; + if (!textFilter) { + const collectionSet = new Set(this._collections.map((collection) => collection.items).flat()); + const uncommonElements = res.items.filter((item) => !collectionSet.has(item.uri)); + collectionItems = this._collections.filter((collection) => !collection.parentCollection); + albumItems = uncommonElements; + unfilteredLength = this._collections.length + uncommonElements.length; + } + } + if (offset > 0) + collectionItems = []; + return { + openedCollection, + items: [...collectionItems, ...albumItems.slice(offset, offset + limit)], + totalLength: albumItems.length + collectionItems.length, + unfilteredLength + }; + } + createCollection(name, parentCollection = "") { + const uri = v4_default(); + const collection = { + type: "collection", + uri, + name, + items: [], + totalLength: 0, + imgUrl: "", + parentCollection + }; + this._collections.push(collection); + this.saveCollections(); + Spicetify.showNotification("Collection created"); + } + deleteCollection(uri) { + this._collections = this._collections.filter((collection) => collection.uri !== uri); + this.saveCollections(); + Spicetify.showNotification("Collection deleted"); + } + async addAlbumToCollection(collectionUri, albumUri) { + const collection = this.getCollection(collectionUri); + if (!collection) + return; + collection.items.push(albumUri); + collection.totalLength++; + this.saveCollections(); + Spicetify.showNotification("Album added to collection"); + } + removeAlbumFromCollection(collectionUri, albumUri) { + const collection = this.getCollection(collectionUri); + if (!collection) + return; + collection.items = collection.items.filter((item) => item !== albumUri); + collection.totalLength--; + this.saveCollections(); + Spicetify.showNotification("Album removed from collection"); + } + getCollectionsWithAlbum(albumUri) { + return this._collections.filter((collection) => { + return collection.items.some((item) => item === albumUri); + }); + } + renameCollection(uri, newName) { + const collection = this.getCollection(uri); + if (!collection) + return; + collection.name = newName; + this.saveCollections(); + Spicetify.showNotification("Collection renamed"); + } + setCollectionImage(uri, imgUrl) { + const collection = this.getCollection(uri); + if (!collection) + return; + collection.imgUrl = imgUrl; + this.saveCollections(); + Spicetify.showNotification("Collection image set"); + } + removeCollectionImage(uri) { + const collection = this.getCollection(uri); + if (!collection) + return; + collection.imgUrl = ""; + this.saveCollections(); + Spicetify.showNotification("Collection image removed"); + } + }; + var collections_wrapper_default = CollectionWrapper; + + // src/components/album_menu_item.tsx + var import_react9 = __toESM(require_react()); + + // src/components/leading_icon.tsx + var import_react6 = __toESM(require_react()); + var LeadingIcon = ({ path }) => { + return /* @__PURE__ */ import_react6.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: `${path}` + }, + iconSize: 16 + }); + }; + var leading_icon_default = LeadingIcon; + + // src/components/text_input_dialog.tsx + var import_react7 = __toESM(require_react()); + var TextInputDialog = (props) => { + const { ButtonPrimary } = Spicetify.ReactComponent; + const { def, placeholder, onSave } = props; + const [value, setValue] = import_react7.default.useState(def); + const onSubmit = (e) => { + e.preventDefault(); + Spicetify.PopupModal.hide(); + onSave(value); + }; + return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement("form", { + className: "text-input-form", + onSubmit + }, /* @__PURE__ */ import_react7.default.createElement("label", { + className: "text-input-wrapper" + }, /* @__PURE__ */ import_react7.default.createElement("input", { + className: "text-input", + type: "text", + value, + placeholder, + onChange: (e) => setValue(e.target.value) + })), /* @__PURE__ */ import_react7.default.createElement("button", { + type: "submit", + "data-encore-id": "buttonPrimary", + className: "Button-sc-qlcn5g-0 Button-small-buttonPrimary" + }, /* @__PURE__ */ import_react7.default.createElement("span", { + className: "ButtonInner-sc-14ud5tc-0 ButtonInner-small encore-bright-accent-set" + }, "Save")))); + }; + var text_input_dialog_default = TextInputDialog; + + // src/components/searchbar.tsx + var import_react8 = __toESM(require_react()); + var SearchBar = (props) => { + const { setSearch, placeholder } = props; + const handleChange = (e) => { + setSearch(e.target.value); + }; + return /* @__PURE__ */ import_react8.default.createElement("div", { + className: "x-filterBox-filterInputContainer x-filterBox-expandedOrHasFilter", + role: "search" + }, /* @__PURE__ */ import_react8.default.createElement("input", { + type: "text", + className: "x-filterBox-filterInput", + role: "searchbox", + maxLength: 80, + autoCorrect: "off", + autoCapitalize: "off", + spellCheck: "false", + placeholder: `Search ${placeholder}`, + "aria-hidden": "false", + onChange: handleChange + }), /* @__PURE__ */ import_react8.default.createElement("div", { + className: "x-filterBox-overlay" + }, /* @__PURE__ */ import_react8.default.createElement("span", { + className: "x-filterBox-searchIconContainer" + }, /* @__PURE__ */ import_react8.default.createElement("svg", { + "data-encore-id": "icon", + role: "img", + "aria-hidden": "true", + className: "Svg-sc-ytk21e-0 Svg-img-icon-small x-filterBox-searchIcon", + viewBox: "0 0 16 16" + }, /* @__PURE__ */ import_react8.default.createElement("path", { + d: "M7 1.75a5.25 5.25 0 1 0 0 10.5 5.25 5.25 0 0 0 0-10.5zM.25 7a6.75 6.75 0 1 1 12.096 4.12l3.184 3.185a.75.75 0 1 1-1.06 1.06L11.304 12.2A6.75 6.75 0 0 1 .25 7z" + })))), /* @__PURE__ */ import_react8.default.createElement("button", { + className: "x-filterBox-expandButton", + "aria-hidden": "false", + "aria-label": "Search Playlists" + }, /* @__PURE__ */ import_react8.default.createElement("svg", { + "data-encore-id": "icon", + role: "img", + "aria-hidden": "true", + className: "Svg-sc-ytk21e-0 Svg-img-icon-small x-filterBox-searchIcon", + viewBox: "0 0 16 16" + }, /* @__PURE__ */ import_react8.default.createElement("path", { + d: "M7 1.75a5.25 5.25 0 1 0 0 10.5 5.25 5.25 0 0 0 0-10.5zM.25 7a6.75 6.75 0 1 1 12.096 4.12l3.184 3.185a.75.75 0 1 1-1.06 1.06L11.304 12.2A6.75 6.75 0 0 1 .25 7z" + })))); + }; + var searchbar_default = SearchBar; + + // src/components/album_menu_item.tsx + var createCollection = () => { + const onSave = (value) => { + SpicetifyLibrary.CollectionWrapper.createCollection(value); + }; + Spicetify.PopupModal.display({ + title: "Create Collection", + content: /* @__PURE__ */ import_react9.default.createElement(text_input_dialog_default, { + def: "New Collection", + placeholder: "Collection Name", + onSave + }) + }); + }; + var CollectionSearchMenu = () => { + const { MenuItem } = Spicetify.ReactComponent; + const { SVGIcons } = Spicetify; + const [textFilter, setTextFilter] = import_react9.default.useState(""); + const [collections, setCollections] = import_react9.default.useState(null); + const context = import_react9.default.useContext(Spicetify.ContextMenuV2._context); + const uri = context?.props?.uri; + import_react9.default.useEffect(() => { + const fetchCollections = async () => { + const res = await SpicetifyLibrary.CollectionWrapper.getCollectionItems({ textFilter }); + setCollections(res); + }; + fetchCollections(); + }, [textFilter]); + if (!collections) + return /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null); + const addToCollection = (collectionUri) => { + SpicetifyLibrary.CollectionWrapper.addAlbumToCollection(collectionUri, uri); + }; + const activeCollections = SpicetifyLibrary.CollectionWrapper.getCollectionsWithAlbum(uri); + const hasCollections = activeCollections.length > 0; + const removeFromCollections = () => { + activeCollections.forEach((collection) => { + SpicetifyLibrary.CollectionWrapper.removeAlbumFromCollection(collection.uri, uri); + }); + }; + const allCollectionsLength = collections.unfilteredLength; + const menuItems = collections.items.map((collection, index) => { + return /* @__PURE__ */ import_react9.default.createElement(MenuItem, { + key: collection.uri, + onClick: () => { + addToCollection(collection.uri); + }, + divider: index === 0 ? "before" : void 0 + }, collection.name); + }); + const menuLength = allCollectionsLength + (hasCollections ? 1 : 0); + return /* @__PURE__ */ import_react9.default.createElement("div", { + className: "main-contextMenu-filterPlaylistSearchContainer", + style: { "--context-menu-submenu-length": `${menuLength}` } + }, /* @__PURE__ */ import_react9.default.createElement("li", { + role: "presentation", + className: "main-contextMenu-filterPlaylistSearch" + }, /* @__PURE__ */ import_react9.default.createElement("div", { + role: "menuitem" + }, /* @__PURE__ */ import_react9.default.createElement(searchbar_default, { + setSearch: setTextFilter, + placeholder: "collections" + }))), /* @__PURE__ */ import_react9.default.createElement(MenuItem, { + key: "new-collection", + leadingIcon: /* @__PURE__ */ import_react9.default.createElement(leading_icon_default, { + path: SVGIcons["plus2px"] + }), + onClick: createCollection + }, "Create collection"), hasCollections && /* @__PURE__ */ import_react9.default.createElement(MenuItem, { + key: "remove-collection", + leadingIcon: /* @__PURE__ */ import_react9.default.createElement(leading_icon_default, { + path: SVGIcons["minus"] + }), + onClick: removeFromCollections + }, "Remove from all"), menuItems); + }; + var AlbumMenuItem = () => { + const { MenuSubMenuItem } = Spicetify.ReactComponent; + const { SVGIcons } = Spicetify; + return /* @__PURE__ */ import_react9.default.createElement(MenuSubMenuItem, { + displayText: "Add to collection", + divider: "after", + leadingIcon: /* @__PURE__ */ import_react9.default.createElement(leading_icon_default, { + path: SVGIcons["plus2px"] + }) + }, /* @__PURE__ */ import_react9.default.createElement(CollectionSearchMenu, null)); + }; + var album_menu_item_default = AlbumMenuItem; + + // src/extensions/folder_image_wrapper.ts + var FolderImageWrapper = class extends EventTarget { + _folderImages; + constructor() { + super(); + this._folderImages = JSON.parse(localStorage.getItem("library:folderImages") || "{}"); + } + getFolderImage(uri) { + return this._folderImages[uri]; + } + getFolderImages() { + return this._folderImages; + } + setFolderImage({ uri, url }) { + this._folderImages[uri] = url; + this.saveFolderImages(); + Spicetify.showNotification("Folder image updated"); + } + removeFolderImage(uri) { + delete this._folderImages[uri]; + this.saveFolderImages(); + Spicetify.showNotification("Folder image removed"); + } + saveFolderImages() { + this.dispatchEvent(new CustomEvent("update", { detail: this._folderImages })); + localStorage.setItem("library:folderImages", JSON.stringify(this._folderImages)); + } + }; + var folder_image_wrapper_default = FolderImageWrapper; + + // src/extensions/extension.tsx + var styleLink = document.createElement("link"); + styleLink.rel = "stylesheet"; + styleLink.href = "/spicetify-routes-library.css"; + document.head.appendChild(styleLink); + var setCardSize = (size) => { + document.documentElement.style.setProperty("--library-card-size", `${size}px`); + }; + var setSearchBarSize = (enlarged) => { + const size = enlarged ? 300 : 200; + document.documentElement.style.setProperty("--library-searchbar-size", `${size}px`); + }; + var FolderImage = ({ url }) => { + return /* @__PURE__ */ import_react10.default.createElement("img", { + "aria-hidden": "true", + draggable: "false", + loading: "eager", + src: url, + className: "main-image-image x-entityImage-image main-image-loading main-image-loaded" + }); + }; + var FolderPlaceholder = () => { + return /* @__PURE__ */ import_react10.default.createElement("div", { + className: "x-entityImage-imagePlaceholder" + }, /* @__PURE__ */ import_react10.default.createElement("svg", { + "data-encore-id": "icon", + role: "img", + "aria-hidden": "true", + className: "Svg-sc-ytk21e-0 Svg-img-icon-medium", + viewBox: "0 0 24 24" + }, /* @__PURE__ */ import_react10.default.createElement("path", { + d: "M1 4a2 2 0 0 1 2-2h5.155a3 3 0 0 1 2.598 1.5l.866 1.5H21a2 2 0 0 1 2 2v13a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V4zm7.155 0H3v16h18V7H10.464L9.021 4.5a1 1 0 0 0-.866-.5z" + }))); + }; + var SpicetifyLibrary2 = class { + ConfigWrapper = new config_wrapper_default( + [ + { + name: "Card Size", + key: "cardSize", + type: "slider", + min: 100, + max: 200, + step: 0.05, + def: 180, + callback: setCardSize + }, + { + name: "Extend Search Bar", + key: "extendSearchBar", + type: "toggle", + def: false, + callback: setSearchBarSize + } + ], + "library" + ); + CollectionWrapper = new collections_wrapper_default(); + FolderImageWrapper = new folder_image_wrapper_default(); + }; + window.SpicetifyLibrary = new SpicetifyLibrary2(); + (function wait() { + const { LocalStorageAPI } = Spicetify?.Platform; + if (!LocalStorageAPI) { + setTimeout(wait, 100); + return; + } + main(LocalStorageAPI); + })(); + function main(LocalStorageAPI) { + const isAlbum = (props) => { + return props.uri?.includes("album"); + }; + Spicetify.ContextMenuV2.registerItem(/* @__PURE__ */ import_react10.default.createElement(album_menu_item_default, null), isAlbum); + function injectFolderImages() { + const rootlist = document.querySelector(".main-rootlist-wrapper > div:nth-child(2)"); + if (!rootlist) + return setTimeout(injectFolderImages, 100); + setTimeout(() => { + Array.from(rootlist.children).forEach((el) => { + const uri = el.querySelector(".main-yourLibraryX-listItemGroup")?.getAttribute("aria-labelledby")?.slice(14); + if (uri?.includes("folder")) { + const imageBox = el.querySelector(".x-entityImage-imageContainer"); + if (!imageBox) + return; + const imageUrl = window.SpicetifyLibrary.FolderImageWrapper.getFolderImage(uri); + if (!imageUrl) + import_react_dom.default.render(/* @__PURE__ */ import_react10.default.createElement(FolderPlaceholder, null), imageBox); + else + import_react_dom.default.render(/* @__PURE__ */ import_react10.default.createElement(FolderImage, { + url: imageUrl + }), imageBox); + } + }); + }, 500); + } + injectFolderImages(); + window.SpicetifyLibrary.FolderImageWrapper.addEventListener("update", () => { + injectFolderImages(); + }); + function injectYLXButtons() { + const ylx_filter = document.querySelector( + ".main-yourLibraryX-libraryRootlist > .main-yourLibraryX-libraryFilter" + ); + if (!ylx_filter) { + return setTimeout(injectYLXButtons, 100); + } + injectFiltersButton(ylx_filter); + injectCollapseButton(ylx_filter); + } + function injectFiltersButton(ylx_filter) { + const toggleFiltersButton = document.createElement("span"); + toggleFiltersButton.classList.add("toggle-filters-button"); + ylx_filter.appendChild(toggleFiltersButton); + import_react_dom.default.render(/* @__PURE__ */ import_react10.default.createElement(toggle_filters_default, null), toggleFiltersButton); + } + function injectCollapseButton(ylx_filter) { + const collapseButton = document.createElement("span"); + collapseButton.classList.add("collapse-button"); + ylx_filter.appendChild(collapseButton); + import_react_dom.default.render( + /* @__PURE__ */ import_react10.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + label: "Collapse Sidebar", + placement: "top" + }, /* @__PURE__ */ import_react10.default.createElement(collapse_button_default, null)), + collapseButton + ); + } + function injectExpandButton() { + const sidebarHeader = document.querySelector("li.main-yourLibraryX-navItem[data-id='/library']"); + if (!sidebarHeader) { + return setTimeout(injectExpandButton, 100); + } + const expandButton = document.createElement("span"); + expandButton.classList.add("expand-button"); + sidebarHeader.appendChild(expandButton); + import_react_dom.default.render(/* @__PURE__ */ import_react10.default.createElement(expand_button_default, null), expandButton); + } + function removeExpandButton() { + const expandButton = document.querySelector(".expand-button"); + if (expandButton) + expandButton.remove(); + } + const state = LocalStorageAPI.getItem("ylx-sidebar-state"); + if (state === 0) { + injectYLXButtons(); + } else if (state === 1) { + injectExpandButton(); + } + LocalStorageAPI.getEvents()._emitter.addListener("update", (e) => { + const { key, value } = e.data; + if (key === "ylx-sidebar-state" && value === 0) { + injectFolderImages(); + injectYLXButtons(); + removeExpandButton(); + } + if (key === "ylx-sidebar-state" && value === 1) { + injectFolderImages(); + injectExpandButton(); + } + }); + } +})(); + + })(); \ No newline at end of file diff --git a/.config/spicetify/CustomApps/library/folder_image_wrapper.js b/.config/spicetify/CustomApps/library/folder_image_wrapper.js new file mode 100644 index 00000000..57f0f545 --- /dev/null +++ b/.config/spicetify/CustomApps/library/folder_image_wrapper.js @@ -0,0 +1,61 @@ +(async function() { + while (!Spicetify.React || !Spicetify.ReactDOM) { + await new Promise(resolve => setTimeout(resolve, 10)); + } + "use strict"; +var library = (() => { + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // src/extensions/folder_image_wrapper.ts + var folder_image_wrapper_exports = {}; + __export(folder_image_wrapper_exports, { + default: () => folder_image_wrapper_default + }); + var FolderImageWrapper = class extends EventTarget { + _folderImages; + constructor() { + super(); + this._folderImages = JSON.parse(localStorage.getItem("library:folderImages") || "{}"); + } + getFolderImage(uri) { + return this._folderImages[uri]; + } + getFolderImages() { + return this._folderImages; + } + setFolderImage({ uri, url }) { + this._folderImages[uri] = url; + this.saveFolderImages(); + Spicetify.showNotification("Folder image updated"); + } + removeFolderImage(uri) { + delete this._folderImages[uri]; + this.saveFolderImages(); + Spicetify.showNotification("Folder image removed"); + } + saveFolderImages() { + this.dispatchEvent(new CustomEvent("update", { detail: this._folderImages })); + localStorage.setItem("library:folderImages", JSON.stringify(this._folderImages)); + } + }; + var folder_image_wrapper_default = FolderImageWrapper; + return __toCommonJS(folder_image_wrapper_exports); +})(); + + })(); \ No newline at end of file diff --git a/.config/spicetify/CustomApps/library/index.js b/.config/spicetify/CustomApps/library/index.js new file mode 100644 index 00000000..326195fd --- /dev/null +++ b/.config/spicetify/CustomApps/library/index.js @@ -0,0 +1,1461 @@ +var library = (() => { + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + }; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod + )); + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // external-global-plugin:react + var require_react = __commonJS({ + "external-global-plugin:react"(exports, module) { + module.exports = Spicetify.React; + } + }); + + // external-global-plugin:react-dom + var require_react_dom = __commonJS({ + "external-global-plugin:react-dom"(exports, module) { + module.exports = Spicetify.ReactDOM; + } + }); + + // ../../../AppData/Local/Temp/spicetify-creator/index.jsx + var spicetify_creator_exports = {}; + __export(spicetify_creator_exports, { + default: () => render + }); + + // src/app.tsx + var import_react23 = __toESM(require_react()); + + // ../node_modules/spcr-navigation-bar/useNavigationBar.tsx + var import_react3 = __toESM(require_react()); + + // ../node_modules/spcr-navigation-bar/navBar.tsx + var import_react2 = __toESM(require_react()); + var import_react_dom = __toESM(require_react_dom()); + + // ../node_modules/spcr-navigation-bar/optionsMenu.tsx + var import_react = __toESM(require_react()); + var OptionsMenuItemIcon = /* @__PURE__ */ import_react.default.createElement("svg", { + width: 16, + height: 16, + viewBox: "0 0 16 16", + fill: "currentColor" + }, /* @__PURE__ */ import_react.default.createElement("path", { + d: "M13.985 2.383L5.127 12.754 1.388 8.375l-.658.77 4.397 5.149 9.618-11.262z" + })); + var OptionsMenuItem = import_react.default.memo((props) => { + return /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.MenuItem, { + onClick: props.onSelect, + icon: props.isSelected ? OptionsMenuItemIcon : null + }, props.value); + }); + var OptionsMenu = import_react.default.memo((props) => { + const menuRef = import_react.default.useRef(null); + const menu = /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.Menu, null, props.options.map( + (option) => /* @__PURE__ */ import_react.default.createElement(OptionsMenuItem, { + value: option.link, + isSelected: option.isActive, + onSelect: () => { + props.onSelect(option.link); + menuRef.current?.click(); + } + }) + )); + return /* @__PURE__ */ import_react.default.createElement(Spicetify.ReactComponent.ContextMenu, { + menu, + trigger: "click", + action: "toggle", + renderInLine: true + }, /* @__PURE__ */ import_react.default.createElement("button", { + className: navBar_module_default.optionsMenuDropBox, + ref: menuRef + }, /* @__PURE__ */ import_react.default.createElement("span", { + className: props.bold ? "main-type-mestoBold" : "main-type-mesto" + }, props.options.find((o) => o.isActive)?.link || props.defaultValue), /* @__PURE__ */ import_react.default.createElement("svg", { + width: 16, + height: 16, + viewBox: "0 0 16 16", + fill: "currentColor" + }, /* @__PURE__ */ import_react.default.createElement("path", { + d: "M3 6l5 5.794L13 6z" + })))); + }); + var optionsMenu_default = OptionsMenu; + + // postcss-module:C:\Users\user\AppData\Local\Temp\tmp-5152-1Ex7Bvh4Tu6u\18f3cb8bc8b4\navBar.module.css + var navBar_module_default = { "topBarHeaderItem": "navBar-module__topBarHeaderItem___piw4C_library", "topBarHeaderItemLink": "navBar-module__topBarHeaderItemLink___xA4uv_library", "topBarActive": "navBar-module__topBarActive___XhWpm_library", "topBarNav": "navBar-module__topBarNav___qWGeZ_library", "optionsMenuDropBox": "navBar-module__optionsMenuDropBox___pzfNI_library" }; + + // ../node_modules/spcr-navigation-bar/navBar.tsx + var NavbarItem2 = class { + constructor(link, isActive) { + this.link = link; + this.isActive = isActive; + } + }; + var NavbarItemComponent = (props) => { + return /* @__PURE__ */ import_react2.default.createElement("li", { + className: navBar_module_default.topBarHeaderItem, + onClick: (e) => { + e.preventDefault(); + props.switchTo(props.item.link); + } + }, /* @__PURE__ */ import_react2.default.createElement("a", { + className: `${navBar_module_default.topBarHeaderItemLink} ${props.item.isActive ? navBar_module_default.topBarActive : ""}`, + "aria-current": "page", + draggable: false, + href: "" + }, /* @__PURE__ */ import_react2.default.createElement("span", { + className: "main-type-mestoBold" + }, props.item.link))); + }; + var NavbarMore = import_react2.default.memo(({ items, switchTo }) => { + return /* @__PURE__ */ import_react2.default.createElement("li", { + className: `${navBar_module_default.topBarHeaderItem} ${items.find((item) => item.isActive) ? navBar_module_default.topBarActive : ""}` + }, /* @__PURE__ */ import_react2.default.createElement(optionsMenu_default, { + options: items, + onSelect: switchTo, + defaultValue: "More", + bold: true + })); + }); + var NavbarContent = (props) => { + const resizeHost = document.querySelector(".Root__main-view .os-resize-observer-host") ?? document.querySelector(".Root__main-view .os-size-observer"); + const [windowSize, setWindowSize] = (0, import_react2.useState)(resizeHost.clientWidth); + const resizeHandler = () => setWindowSize(resizeHost.clientWidth); + (0, import_react2.useEffect)(() => { + const observer = new ResizeObserver(resizeHandler); + observer.observe(resizeHost); + return () => { + observer.disconnect(); + }; + }, [resizeHandler]); + return /* @__PURE__ */ import_react2.default.createElement(NavbarContext, null, /* @__PURE__ */ import_react2.default.createElement(Navbar, { + ...props, + windowSize + })); + }; + var NavbarContext = (props) => { + return import_react_dom.default.createPortal( + /* @__PURE__ */ import_react2.default.createElement("div", { + className: "main-topbar-topbarContent" + }, props.children), + document.querySelector(".main-topBar-topbarContentWrapper") + ); + }; + var Navbar = (props) => { + const navBarListRef = import_react2.default.useRef(null); + const [childrenSizes, setChildrenSizes] = (0, import_react2.useState)([]); + const [availableSpace, setAvailableSpace] = (0, import_react2.useState)(0); + const [outOfRangeItemIndexes, setOutOfRangeItemIndexes] = (0, import_react2.useState)([]); + let items = props.links.map((link) => new NavbarItem2(link, link === props.activeLink)); + (0, import_react2.useEffect)(() => { + if (!navBarListRef.current) + return; + const children = Array.from(navBarListRef.current.children); + const navBarItemSizes = children.map((child) => child.clientWidth); + setChildrenSizes(navBarItemSizes); + }, []); + (0, import_react2.useEffect)(() => { + if (!navBarListRef.current) + return; + setAvailableSpace(navBarListRef.current.clientWidth); + }, [props.windowSize]); + (0, import_react2.useEffect)(() => { + if (!navBarListRef.current) + return; + let totalSize = childrenSizes.reduce((a, b) => a + b, 0); + if (totalSize <= availableSpace) { + setOutOfRangeItemIndexes([]); + return; + } + const viewMoreButtonSize = Math.max(...childrenSizes); + const itemsToHide = []; + let stopWidth = viewMoreButtonSize; + childrenSizes.forEach((childWidth, i) => { + if (availableSpace >= stopWidth + childWidth) { + stopWidth += childWidth; + } else if (i !== items.length) { + itemsToHide.push(i); + } + }); + setOutOfRangeItemIndexes(itemsToHide); + }, [availableSpace, childrenSizes]); + return /* @__PURE__ */ import_react2.default.createElement("nav", { + className: navBar_module_default.topBarNav + }, /* @__PURE__ */ import_react2.default.createElement("ul", { + className: navBar_module_default.topBarHeader, + ref: navBarListRef + }, items.filter((_, id) => !outOfRangeItemIndexes.includes(id)).map( + (item) => /* @__PURE__ */ import_react2.default.createElement(NavbarItemComponent, { + item, + switchTo: props.switchCallback + }) + ), outOfRangeItemIndexes.length ? /* @__PURE__ */ import_react2.default.createElement(NavbarMore, { + items: outOfRangeItemIndexes.map((i) => items[i]), + switchTo: props.switchCallback + }) : null)); + }; + var navBar_default = NavbarContent; + + // ../node_modules/spcr-navigation-bar/useNavigationBar.tsx + var useNavigationBar = (links) => { + const [activeLink, setActiveLink] = (0, import_react3.useState)(links[0]); + const navbar = /* @__PURE__ */ import_react3.default.createElement(navBar_default, { + links, + activeLink, + switchCallback: (link) => setActiveLink(link) + }); + return [navbar, activeLink, setActiveLink]; + }; + var useNavigationBar_default = useNavigationBar; + + // src/pages/albums.tsx + var import_react19 = __toESM(require_react()); + + // src/components/searchbar.tsx + var import_react4 = __toESM(require_react()); + var SearchBar = (props) => { + const { setSearch, placeholder } = props; + const handleChange = (e) => { + setSearch(e.target.value); + }; + return /* @__PURE__ */ import_react4.default.createElement("div", { + className: "x-filterBox-filterInputContainer x-filterBox-expandedOrHasFilter", + role: "search" + }, /* @__PURE__ */ import_react4.default.createElement("input", { + type: "text", + className: "x-filterBox-filterInput", + role: "searchbox", + maxLength: 80, + autoCorrect: "off", + autoCapitalize: "off", + spellCheck: "false", + placeholder: `Search ${placeholder}`, + "aria-hidden": "false", + onChange: handleChange + }), /* @__PURE__ */ import_react4.default.createElement("div", { + className: "x-filterBox-overlay" + }, /* @__PURE__ */ import_react4.default.createElement("span", { + className: "x-filterBox-searchIconContainer" + }, /* @__PURE__ */ import_react4.default.createElement("svg", { + "data-encore-id": "icon", + role: "img", + "aria-hidden": "true", + className: "Svg-sc-ytk21e-0 Svg-img-icon-small x-filterBox-searchIcon", + viewBox: "0 0 16 16" + }, /* @__PURE__ */ import_react4.default.createElement("path", { + d: "M7 1.75a5.25 5.25 0 1 0 0 10.5 5.25 5.25 0 0 0 0-10.5zM.25 7a6.75 6.75 0 1 1 12.096 4.12l3.184 3.185a.75.75 0 1 1-1.06 1.06L11.304 12.2A6.75 6.75 0 0 1 .25 7z" + })))), /* @__PURE__ */ import_react4.default.createElement("button", { + className: "x-filterBox-expandButton", + "aria-hidden": "false", + "aria-label": "Search Playlists" + }, /* @__PURE__ */ import_react4.default.createElement("svg", { + "data-encore-id": "icon", + role: "img", + "aria-hidden": "true", + className: "Svg-sc-ytk21e-0 Svg-img-icon-small x-filterBox-searchIcon", + viewBox: "0 0 16 16" + }, /* @__PURE__ */ import_react4.default.createElement("path", { + d: "M7 1.75a5.25 5.25 0 1 0 0 10.5 5.25 5.25 0 0 0 0-10.5zM.25 7a6.75 6.75 0 1 1 12.096 4.12l3.184 3.185a.75.75 0 1 1-1.06 1.06L11.304 12.2A6.75 6.75 0 0 1 .25 7z" + })))); + }; + var searchbar_default = SearchBar; + + // ../shared/components/settings_button.tsx + var import_react5 = __toESM(require_react()); + function SettingsIcon() { + return /* @__PURE__ */ import_react5.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: '' + }, + iconSize: 16 + }); + } + function SettingsButton(props) { + const { TooltipWrapper, ButtonTertiary } = Spicetify.ReactComponent; + const { configWrapper } = props; + return /* @__PURE__ */ import_react5.default.createElement(TooltipWrapper, { + label: "Settings", + renderInline: true, + placement: "top" + }, /* @__PURE__ */ import_react5.default.createElement(ButtonTertiary, { + buttonSize: "sm", + onClick: configWrapper.launchModal, + "aria-label": "Settings", + iconOnly: SettingsIcon + })); + } + var settings_button_default = SettingsButton; + + // ../shared/dropdown/useDropdownMenu.tsx + var import_react7 = __toESM(require_react()); + + // ../shared/dropdown/dropdown.tsx + var import_react6 = __toESM(require_react()); + function CheckIcon() { + return /* @__PURE__ */ import_react6.default.createElement(Spicetify.ReactComponent.IconComponent, { + iconSize: 16, + semanticColor: "textBase", + dangerouslySetInnerHTML: { + __html: '' + } + }); + } + var MenuItem = (props) => { + const { ReactComponent } = Spicetify; + const { option, isActive, switchCallback } = props; + const activeStyle = { + backgroundColor: "rgba(var(--spice-rgb-selected-row),.1)" + }; + return /* @__PURE__ */ import_react6.default.createElement(ReactComponent.MenuItem, { + trigger: "click", + onClick: () => switchCallback(option), + "data-checked": isActive, + trailingIcon: isActive ? /* @__PURE__ */ import_react6.default.createElement(CheckIcon, null) : void 0, + style: isActive ? activeStyle : void 0 + }, option.name); + }; + var DropdownMenu = (props) => { + const { ContextMenu, Menu, TextComponent } = Spicetify.ReactComponent; + const { options, activeOption, switchCallback } = props; + const optionItems = options.map((option) => { + return /* @__PURE__ */ import_react6.default.createElement(MenuItem, { + option, + isActive: option === activeOption, + switchCallback + }); + }); + const MenuWrapper = (props2) => { + return /* @__PURE__ */ import_react6.default.createElement(Menu, { + ...props2 + }, optionItems); + }; + return /* @__PURE__ */ import_react6.default.createElement(ContextMenu, { + menu: /* @__PURE__ */ import_react6.default.createElement(MenuWrapper, null), + trigger: "click" + }, /* @__PURE__ */ import_react6.default.createElement("button", { + className: "x-sortBox-sortDropdown", + type: "button", + role: "combobox", + "aria-expanded": "false" + }, /* @__PURE__ */ import_react6.default.createElement(TextComponent, { + variant: "mesto", + semanticColor: "textSubdued" + }, activeOption.name), /* @__PURE__ */ import_react6.default.createElement("svg", { + role: "img", + height: "16", + width: "16", + "aria-hidden": "true", + className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small", + viewBox: "0 0 16 16", + "data-encore-id": "icon" + }, /* @__PURE__ */ import_react6.default.createElement("path", { + d: "m14 6-6 6-6-6h12z" + })))); + }; + var dropdown_default = DropdownMenu; + + // ../shared/dropdown/useDropdownMenu.tsx + var useDropdownMenu = (options, storageVariable) => { + const initialOptionID = storageVariable && Spicetify.LocalStorage.get(`${storageVariable}:active-option`); + const initialOption = initialOptionID && options.find((e) => e.id === initialOptionID); + const [activeOption, setActiveOption] = (0, import_react7.useState)(initialOption || options[0]); + const [availableOptions, setAvailableOptions] = (0, import_react7.useState)(options); + const dropdown = /* @__PURE__ */ import_react7.default.createElement(dropdown_default, { + options: availableOptions, + activeOption, + switchCallback: (option) => { + setActiveOption(option); + if (storageVariable) + Spicetify.LocalStorage.set(`${storageVariable}:active-option`, option.id); + } + }); + return [dropdown, activeOption, setActiveOption, setAvailableOptions]; + }; + var useDropdownMenu_default = useDropdownMenu; + + // ../shared/components/page_container.tsx + var import_react9 = __toESM(require_react()); + + // ../stats/src/components/buttons/create_playlist_button.tsx + var import_react8 = __toESM(require_react()); + async function createPlaylistAsync(infoToCreatePlaylist) { + const { Platform, showNotification } = Spicetify; + const { RootlistAPI, PlaylistAPI } = Platform; + try { + const { playlistName, itemsUris } = infoToCreatePlaylist; + const playlistUri = await RootlistAPI.createPlaylist(playlistName, { before: "start" }); + await PlaylistAPI.add(playlistUri, itemsUris, { before: "start" }); + } catch (error) { + console.error(error); + showNotification("Failed to create playlist", true, 1e3); + } + } + function CreatePlaylistButton(props) { + const { TooltipWrapper, ButtonSecondary } = Spicetify.ReactComponent; + const { infoToCreatePlaylist } = props; + return /* @__PURE__ */ import_react8.default.createElement(TooltipWrapper, { + label: "Turn Into Playlist", + renderInline: true, + placement: "top" + }, /* @__PURE__ */ import_react8.default.createElement(ButtonSecondary, { + "aria-label": "Turn Into Playlist", + children: "Turn Into Playlist", + semanticColor: "textBase", + buttonSize: "sm", + onClick: () => createPlaylistAsync(infoToCreatePlaylist), + className: "stats-make-playlist-button" + })); + } + var create_playlist_button_default = CreatePlaylistButton; + + // ../shared/components/page_container.tsx + var PageContainer = (props) => { + const { title, infoToCreatePlaylist, headerEls, children } = props; + const { TextComponent } = Spicetify.ReactComponent; + return /* @__PURE__ */ import_react9.default.createElement("section", { + className: "contentSpacing" + }, /* @__PURE__ */ import_react9.default.createElement("div", { + className: "page-header" + }, /* @__PURE__ */ import_react9.default.createElement("div", { + className: "header-left" + }, /* @__PURE__ */ import_react9.default.createElement(TextComponent, { + children: title, + as: "h1", + variant: "canon", + semanticColor: "textBase" + }), infoToCreatePlaylist ? /* @__PURE__ */ import_react9.default.createElement(create_playlist_button_default, { + infoToCreatePlaylist + }) : null), /* @__PURE__ */ import_react9.default.createElement("div", { + className: "header-right" + }, headerEls)), /* @__PURE__ */ import_react9.default.createElement("div", { + className: "page-content" + }, children)); + }; + var page_container_default = PageContainer; + + // ../shared/components/status.tsx + var import_react10 = __toESM(require_react()); + var ErrorIcon = () => { + return /* @__PURE__ */ import_react10.default.createElement("svg", { + "data-encore-id": "icon", + role: "img", + "aria-hidden": "true", + viewBox: "0 0 24 24", + className: "status-icon" + }, /* @__PURE__ */ import_react10.default.createElement("path", { + d: "M11 18v-2h2v2h-2zm0-4V6h2v8h-2z" + }), /* @__PURE__ */ import_react10.default.createElement("path", { + d: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12z" + })); + }; + var LibraryIcon = () => { + return /* @__PURE__ */ import_react10.default.createElement("svg", { + role: "img", + height: "46", + width: "46", + "aria-hidden": "true", + viewBox: "0 0 24 24", + "data-encore-id": "icon", + className: "status-icon" + }, /* @__PURE__ */ import_react10.default.createElement("path", { + d: "M14.5 2.134a1 1 0 0 1 1 0l6 3.464a1 1 0 0 1 .5.866V21a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1V3a1 1 0 0 1 .5-.866zM16 4.732V20h4V7.041l-4-2.309zM3 22a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1zm6 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1z" + })); + }; + var Status = (props) => { + const [isVisible, setIsVisible] = import_react10.default.useState(false); + import_react10.default.useEffect(() => { + const to = setTimeout(() => { + setIsVisible(true); + }, 500); + return () => clearTimeout(to); + }, []); + return isVisible ? /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("div", { + className: "loadingWrapper" + }, props.icon === "error" ? /* @__PURE__ */ import_react10.default.createElement(ErrorIcon, null) : /* @__PURE__ */ import_react10.default.createElement(LibraryIcon, null), /* @__PURE__ */ import_react10.default.createElement("h1", null, props.heading), /* @__PURE__ */ import_react10.default.createElement("h3", null, props.subheading))) : /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null); + }; + var status_default = Status; + + // src/components/collection_menu.tsx + var import_react13 = __toESM(require_react()); + + // src/components/text_input_dialog.tsx + var import_react11 = __toESM(require_react()); + var TextInputDialog = (props) => { + const { ButtonPrimary } = Spicetify.ReactComponent; + const { def, placeholder, onSave } = props; + const [value, setValue] = import_react11.default.useState(def); + const onSubmit = (e) => { + e.preventDefault(); + Spicetify.PopupModal.hide(); + onSave(value); + }; + return /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, /* @__PURE__ */ import_react11.default.createElement("form", { + className: "text-input-form", + onSubmit + }, /* @__PURE__ */ import_react11.default.createElement("label", { + className: "text-input-wrapper" + }, /* @__PURE__ */ import_react11.default.createElement("input", { + className: "text-input", + type: "text", + value, + placeholder, + onChange: (e) => setValue(e.target.value) + })), /* @__PURE__ */ import_react11.default.createElement("button", { + type: "submit", + "data-encore-id": "buttonPrimary", + className: "Button-sc-qlcn5g-0 Button-small-buttonPrimary" + }, /* @__PURE__ */ import_react11.default.createElement("span", { + className: "ButtonInner-sc-14ud5tc-0 ButtonInner-small encore-bright-accent-set" + }, "Save")))); + }; + var text_input_dialog_default = TextInputDialog; + + // src/components/leading_icon.tsx + var import_react12 = __toESM(require_react()); + var LeadingIcon = ({ path }) => { + return /* @__PURE__ */ import_react12.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: `${path}` + }, + iconSize: 16 + }); + }; + var leading_icon_default = LeadingIcon; + + // src/components/collection_menu.tsx + var editIconPath = ''; + var deleteIconPath = ''; + var CollectionMenu = ({ id }) => { + const { Menu, MenuItem: MenuItem2 } = Spicetify.ReactComponent; + const deleteCollection = () => { + SpicetifyLibrary.CollectionWrapper.deleteCollection(id); + }; + const renameCollection = () => { + const name = SpicetifyLibrary.CollectionWrapper.getCollection(id).name; + const rename = (newName) => { + SpicetifyLibrary.CollectionWrapper.renameCollection(id, newName); + }; + Spicetify.PopupModal.display({ + title: "Rename Collection", + content: /* @__PURE__ */ import_react13.default.createElement(text_input_dialog_default, { + def: name, + onSave: rename + }) + }); + }; + const image = SpicetifyLibrary.CollectionWrapper.getCollection(id).imgUrl; + const setCollectionImage = () => { + const setImg = (imgUrl) => { + SpicetifyLibrary.CollectionWrapper.setCollectionImage(id, imgUrl); + }; + Spicetify.PopupModal.display({ + title: "Set Collection Image", + content: /* @__PURE__ */ import_react13.default.createElement(text_input_dialog_default, { + def: image, + placeholder: "Image URL", + onSave: setImg + }) + }); + }; + const removeImage = () => { + SpicetifyLibrary.CollectionWrapper.removeCollectionImage(id); + }; + return /* @__PURE__ */ import_react13.default.createElement(Menu, null, /* @__PURE__ */ import_react13.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react13.default.createElement(leading_icon_default, { + path: editIconPath + }), + onClick: renameCollection + }, "Rename"), /* @__PURE__ */ import_react13.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react13.default.createElement(leading_icon_default, { + path: deleteIconPath + }), + onClick: deleteCollection + }, "Delete"), /* @__PURE__ */ import_react13.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react13.default.createElement(leading_icon_default, { + path: editIconPath + }), + onClick: setCollectionImage + }, "Set Collection Image"), image && /* @__PURE__ */ import_react13.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react13.default.createElement(leading_icon_default, { + path: deleteIconPath + }), + onClick: removeImage + }, "Remove Collection Image")); + }; + var collection_menu_default = CollectionMenu; + + // src/components/folder_menu.tsx + var import_react14 = __toESM(require_react()); + var editIconPath2 = ''; + var deleteIconPath2 = ''; + var FolderMenu = ({ uri }) => { + const { MenuItem: MenuItem2, Menu } = Spicetify.ReactComponent; + const image = SpicetifyLibrary.FolderImageWrapper.getFolderImage(uri); + const setImage = () => { + const setNewImage = (newUrl) => { + SpicetifyLibrary.FolderImageWrapper.setFolderImage({ uri, url: newUrl }); + }; + Spicetify.PopupModal.display({ + title: "Set Folder Image", + content: /* @__PURE__ */ import_react14.default.createElement(text_input_dialog_default, { + def: image, + onSave: setNewImage + }) + }); + }; + const removeImage = () => { + SpicetifyLibrary.FolderImageWrapper.removeFolderImage(uri); + }; + return /* @__PURE__ */ import_react14.default.createElement(Menu, null, /* @__PURE__ */ import_react14.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react14.default.createElement(leading_icon_default, { + path: editIconPath2 + }), + onClick: setImage + }, "Set Folder Image"), image && /* @__PURE__ */ import_react14.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react14.default.createElement(leading_icon_default, { + path: deleteIconPath2 + }), + onClick: removeImage + }, "Remove Folder Image")); + }; + var folder_menu_default = FolderMenu; + + // ../shared/components/spotify_card.tsx + var import_react16 = __toESM(require_react()); + + // ../shared/components/folder_fallback.tsx + var import_react15 = __toESM(require_react()); + var FolderSVG = (e) => { + return /* @__PURE__ */ import_react15.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + viewBox: "0 0 24 24", + size: "xxlarge", + dangerouslySetInnerHTML: { + __html: '' + }, + ...e + }); + }; + var folder_fallback_default = FolderSVG; + + // ../shared/components/spotify_card.tsx + function SpotifyCard(props) { + const { Cards, TextComponent, ArtistMenu, AlbumMenu, PodcastShowMenu, PlaylistMenu, ContextMenu } = Spicetify.ReactComponent; + const { FeatureCard: Card, CardImage } = Cards; + const { createHref, push } = Spicetify.Platform.History; + const { type, header, uri, imageUrl, subheader, artistUri } = props; + const backupImageUrl = type === "folder" || type === "collection" ? "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/folder_placeholder.png" : "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/def_placeholder.png"; + const Menu = () => { + switch (type) { + case "artist": + return /* @__PURE__ */ import_react16.default.createElement(ArtistMenu, { + uri + }); + case "album": + return /* @__PURE__ */ import_react16.default.createElement(AlbumMenu, { + uri, + artistUri, + canRemove: true + }); + case "playlist": + return /* @__PURE__ */ import_react16.default.createElement(PlaylistMenu, { + uri + }); + case "show": + return /* @__PURE__ */ import_react16.default.createElement(PodcastShowMenu, { + uri + }); + case "collection": + return /* @__PURE__ */ import_react16.default.createElement(collection_menu_default, { + id: uri + }); + case "folder": + return /* @__PURE__ */ import_react16.default.createElement(folder_menu_default, { + uri + }); + default: + return /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null); + } + }; + const lastfmProps = type === "lastfm" ? { onClick: () => window.open(uri, "_blank"), isPlayable: false, delegateNavigation: true } : {}; + const folderProps = type === "folder" ? { + delegateNavigation: true, + onClick: () => { + createHref({ pathname: `/library/folder/${uri}` }); + push({ pathname: `/library/folder/${uri}` }); + } + } : {}; + const collectionProps = type === "collection" ? { + delegateNavigation: true, + onClick: () => { + createHref({ pathname: `/library/collection/${uri}` }); + push({ pathname: `/library/collection/${uri}` }); + } + } : {}; + return /* @__PURE__ */ import_react16.default.createElement(ContextMenu, { + menu: Menu(), + trigger: "right-click" + }, /* @__PURE__ */ import_react16.default.createElement(Card, { + featureIdentifier: type, + headerText: header, + renderCardImage: () => /* @__PURE__ */ import_react16.default.createElement(CardImage, { + images: [ + { + height: 640, + url: imageUrl, + width: 640 + } + ], + isCircular: type === "artist", + FallbackComponent: folder_fallback_default + }), + renderSubHeaderContent: () => /* @__PURE__ */ import_react16.default.createElement(TextComponent, { + as: "div", + variant: "mesto", + semanticColor: "textSubdued", + children: subheader + }), + uri, + ...lastfmProps, + ...folderProps, + ...collectionProps + })); + } + var spotify_card_default = SpotifyCard; + + // src/components/load_more_card.tsx + var import_react17 = __toESM(require_react()); + var LoadMoreCard = (props) => { + const { callback } = props; + return /* @__PURE__ */ import_react17.default.createElement("div", { + onClick: callback, + className: "load-more-card main-card-card" + }, /* @__PURE__ */ import_react17.default.createElement("div", { + className: "svg-placeholder" + }, /* @__PURE__ */ import_react17.default.createElement("svg", { + viewBox: "0 8 24 8", + xmlns: "http://www.w3.org/2000/svg" + }, /* @__PURE__ */ import_react17.default.createElement("circle", { + cx: "17.5", + cy: "12", + r: "1.5" + }), /* @__PURE__ */ import_react17.default.createElement("circle", { + cx: "12", + cy: "12", + r: "1.5" + }), /* @__PURE__ */ import_react17.default.createElement("circle", { + cx: "6.5", + cy: "12", + r: "1.5" + }))), /* @__PURE__ */ import_react17.default.createElement(Spicetify.ReactComponent.TextComponent, { + as: "div", + variant: "violaBold", + semanticColor: "textBase", + weight: "bold", + children: "Load More" + })); + }; + var load_more_card_default = LoadMoreCard; + + // src/components/add_button.tsx + var import_react18 = __toESM(require_react()); + function AddIcon() { + return /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: '' + }, + iconSize: 16 + }); + } + function AddButton(props) { + const { ReactComponent } = Spicetify; + const { TooltipWrapper, ButtonTertiary, ContextMenu } = ReactComponent; + const { Menu } = props; + return /* @__PURE__ */ import_react18.default.createElement(TooltipWrapper, { + label: "Add", + placement: "top" + }, /* @__PURE__ */ import_react18.default.createElement("span", null, /* @__PURE__ */ import_react18.default.createElement(ContextMenu, { + trigger: "click", + menu: Menu + }, /* @__PURE__ */ import_react18.default.createElement(ButtonTertiary, { + buttonSize: "sm", + "aria-label": "Add", + iconOnly: AddIcon + })))); + } + var add_button_default = AddButton; + + // src/pages/albums.tsx + var sortOptions = [ + { id: "0", name: "Name" }, + { id: "1", name: "Date Added" }, + { id: "2", name: "Artist Name" }, + { id: "6", name: "Recents" } + ]; + var AddMenu = ({ collection }) => { + const { MenuItem: MenuItem2, Menu } = Spicetify.ReactComponent; + const { SVGIcons } = Spicetify; + const createCollection = () => { + const onSave = (value) => { + SpicetifyLibrary.CollectionWrapper.createCollection(value, collection); + }; + Spicetify.PopupModal.display({ + title: "Create Collection", + content: /* @__PURE__ */ import_react19.default.createElement(text_input_dialog_default, { + def: "New Collection", + placeholder: "Collection Name", + onSave + }) + }); + }; + const addAlbum = () => { + const onSave = (value) => { + if (collection) + SpicetifyLibrary.CollectionWrapper.addAlbumToCollection(collection, value); + Spicetify.Platform.LibraryAPI.add({ uris: [value] }); + }; + Spicetify.PopupModal.display({ + title: "Add Album", + content: /* @__PURE__ */ import_react19.default.createElement(text_input_dialog_default, { + def: "", + placeholder: "Album URI", + onSave + }) + }); + }; + return /* @__PURE__ */ import_react19.default.createElement(Menu, null, /* @__PURE__ */ import_react19.default.createElement(MenuItem2, { + onClick: createCollection, + leadingIcon: /* @__PURE__ */ import_react19.default.createElement(leading_icon_default, { + path: SVGIcons["playlist-folder"] + }) + }, "Create Collection"), /* @__PURE__ */ import_react19.default.createElement(MenuItem2, { + onClick: addAlbum, + leadingIcon: /* @__PURE__ */ import_react19.default.createElement(leading_icon_default, { + path: SVGIcons["album"] + }) + }, "Add Album")); + }; + var AlbumsPage = ({ configWrapper, collection }) => { + const [dropdown, sortOption] = useDropdownMenu_default(sortOptions, "library:albums"); + const [textFilter, setTextFilter] = import_react19.default.useState(""); + const { useInfiniteQuery } = Spicetify.ReactQuery; + const limit = 200; + const fetchRootlist = async ({ pageParam }) => { + const collections = await SpicetifyLibrary.CollectionWrapper.getCollectionItems({ + collectionUri: collection, + textFilter, + sortOrder: sortOption.id, + limit, + offset: pageParam, + rootlist: true + }); + return collections; + }; + const { data, status, hasNextPage, fetchNextPage, refetch } = useInfiniteQuery({ + queryKey: ["library:albums", sortOption.id, textFilter, collection], + queryFn: fetchRootlist, + initialPageParam: 0, + getNextPageParam: (lastPage, _allPages, lastPageParam) => { + return lastPage.totalLength > lastPageParam + limit ? lastPageParam + limit : void 0; + }, + structuralSharing: false + }); + import_react19.default.useEffect(() => { + const onUpdate = (e) => { + refetch(); + }; + Spicetify.Platform.LibraryAPI.getEvents()._emitter.addListener("update", onUpdate); + SpicetifyLibrary.CollectionWrapper.addEventListener("update", onUpdate); + return () => { + Spicetify.Platform.LibraryAPI.getEvents()._emitter.removeListener("update", onUpdate); + SpicetifyLibrary.CollectionWrapper.removeEventListener("update", onUpdate); + }; + }, []); + const props = { + title: data?.pages[0].openedCollection || "Albums", + headerEls: [ + /* @__PURE__ */ import_react19.default.createElement(add_button_default, { + Menu: /* @__PURE__ */ import_react19.default.createElement(AddMenu, { + collection + }) + }), + dropdown, + /* @__PURE__ */ import_react19.default.createElement(searchbar_default, { + setSearch: setTextFilter, + placeholder: "Albums" + }), + /* @__PURE__ */ import_react19.default.createElement(settings_button_default, { + configWrapper + }) + ] + }; + if (status === "pending") { + return /* @__PURE__ */ import_react19.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react19.default.createElement(status_default, { + icon: "library", + heading: "Loading", + subheading: "Fetching your albums" + })); + } else if (status === "error") { + return /* @__PURE__ */ import_react19.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react19.default.createElement(status_default, { + icon: "error", + heading: "Error", + subheading: "Failed to load your albums" + })); + } else if (!data.pages[0].items.length) { + return /* @__PURE__ */ import_react19.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react19.default.createElement(status_default, { + icon: "library", + heading: "Nothing Here", + subheading: "You don't have any albums saved" + })); + } + const rootlistItems = data.pages.map((page) => page.items).flat(); + const rootlistCards = rootlistItems.map((item) => { + const isAlbum = item.type === "album"; + return /* @__PURE__ */ import_react19.default.createElement(spotify_card_default, { + type: item.type, + uri: item.uri, + header: item.name, + subheader: isAlbum ? item.artists?.[0]?.name : "Collection", + imageUrl: isAlbum ? item.images?.[0]?.url : item.imgUrl, + artistUri: isAlbum ? item.artists?.[0]?.uri : void 0 + }); + }); + if (hasNextPage) + rootlistCards.push(/* @__PURE__ */ import_react19.default.createElement(load_more_card_default, { + callback: fetchNextPage + })); + return /* @__PURE__ */ import_react19.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react19.default.createElement("div", { + className: `main-gridContainer-gridContainer grid` + }, rootlistCards)); + }; + var albums_default = AlbumsPage; + + // src/pages/artists.tsx + var import_react20 = __toESM(require_react()); + var sortOptions2 = [ + { id: "0", name: "Name" }, + { id: "1", name: "Date Added" } + ]; + var AddMenu2 = () => { + const { MenuItem: MenuItem2, Menu } = Spicetify.ReactComponent; + const { SVGIcons } = Spicetify; + const addAlbum = () => { + const onSave = (value) => { + Spicetify.Platform.LibraryAPI.add({ uris: [value] }); + }; + Spicetify.PopupModal.display({ + title: "Add Artist", + content: /* @__PURE__ */ import_react20.default.createElement(text_input_dialog_default, { + def: "", + placeholder: "Artist URI", + onSave + }) + }); + }; + return /* @__PURE__ */ import_react20.default.createElement(Menu, null, /* @__PURE__ */ import_react20.default.createElement(MenuItem2, { + onClick: addAlbum, + leadingIcon: /* @__PURE__ */ import_react20.default.createElement(leading_icon_default, { + path: SVGIcons["artist"] + }) + }, "Add Artist")); + }; + var ArtistsPage = ({ configWrapper }) => { + const [dropdown, sortOption] = useDropdownMenu_default(sortOptions2, "library:artists"); + const [textFilter, setTextFilter] = import_react20.default.useState(""); + const { useInfiniteQuery } = Spicetify.ReactQuery; + const limit = 200; + const fetchArtists = async ({ pageParam }) => { + const res = await Spicetify.Platform.LibraryAPI.getContents({ + filters: ["1"], + sortOrder: sortOption.id, + textFilter, + offset: pageParam, + limit + }); + return res; + }; + const { data, status, hasNextPage, fetchNextPage, refetch } = useInfiniteQuery({ + queryKey: ["library:artists", sortOption.id, textFilter], + queryFn: fetchArtists, + initialPageParam: 0, + getNextPageParam: (lastPage, _allPages, lastPageParam) => { + return lastPage.totalLength > lastPageParam + limit ? lastPageParam + limit : void 0; + } + }); + import_react20.default.useEffect(() => { + const onUpdate = (e) => refetch(); + Spicetify.Platform.LibraryAPI.getEvents()._emitter.addListener("update", onUpdate); + return () => Spicetify.Platform.LibraryAPI.getEvents()._emitter.removeListener("update", onUpdate); + }, []); + const props = { + title: "Artists", + headerEls: [ + /* @__PURE__ */ import_react20.default.createElement(add_button_default, { + Menu: /* @__PURE__ */ import_react20.default.createElement(AddMenu2, null) + }), + dropdown, + /* @__PURE__ */ import_react20.default.createElement(searchbar_default, { + setSearch: setTextFilter, + placeholder: "Artists" + }), + /* @__PURE__ */ import_react20.default.createElement(settings_button_default, { + configWrapper + }) + ] + }; + if (status === "pending") { + return /* @__PURE__ */ import_react20.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react20.default.createElement(status_default, { + icon: "library", + heading: "Loading", + subheading: "Fetching your artists" + })); + } else if (status === "error") { + return /* @__PURE__ */ import_react20.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react20.default.createElement(status_default, { + icon: "error", + heading: "Error", + subheading: "Failed to load your artists" + })); + } else if (!data.pages[0].items.length) { + return /* @__PURE__ */ import_react20.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react20.default.createElement(status_default, { + icon: "library", + heading: "Nothing Here", + subheading: "You don't have any artists saved" + })); + } + const artists = data.pages.map((page) => page.items).flat(); + const artistCards = artists.map((artist) => { + return /* @__PURE__ */ import_react20.default.createElement(spotify_card_default, { + type: "artist", + uri: artist.uri, + header: artist.name, + subheader: "Artist", + imageUrl: artist.images?.[0]?.url || "" + }); + }); + if (hasNextPage) + artistCards.push(/* @__PURE__ */ import_react20.default.createElement(load_more_card_default, { + callback: fetchNextPage + })); + return /* @__PURE__ */ import_react20.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react20.default.createElement("div", { + className: `main-gridContainer-gridContainer grid` + }, artistCards)); + }; + var artists_default = ArtistsPage; + + // src/pages/shows.tsx + var import_react21 = __toESM(require_react()); + var sortOptions3 = [ + { id: "0", name: "Name" }, + { id: "1", name: "Date Added" } + ]; + var AddMenu3 = () => { + const { MenuItem: MenuItem2, Menu } = Spicetify.ReactComponent; + const { SVGIcons } = Spicetify; + const addAlbum = () => { + const onSave = (value) => { + Spicetify.Platform.LibraryAPI.add({ uris: [value] }); + }; + Spicetify.PopupModal.display({ + title: "Add Show", + content: /* @__PURE__ */ import_react21.default.createElement(text_input_dialog_default, { + def: "", + placeholder: "Show URI", + onSave + }) + }); + }; + return /* @__PURE__ */ import_react21.default.createElement(Menu, null, /* @__PURE__ */ import_react21.default.createElement(MenuItem2, { + onClick: addAlbum, + leadingIcon: /* @__PURE__ */ import_react21.default.createElement(leading_icon_default, { + path: SVGIcons["podcasts"] + }) + }, "Add Show")); + }; + var ShowsPage = ({ configWrapper }) => { + const [dropdown, sortOption] = useDropdownMenu_default(sortOptions3, "library:shows"); + const [textFilter, setTextFilter] = import_react21.default.useState(""); + const { useInfiniteQuery } = Spicetify.ReactQuery; + const limit = 200; + const fetchShows = async ({ pageParam }) => { + const res = await Spicetify.Platform.LibraryAPI.getContents({ + filters: ["3"], + sortOrder: sortOption.id, + textFilter, + offset: pageParam, + limit + }); + return res; + }; + const { data, status, hasNextPage, fetchNextPage, refetch } = useInfiniteQuery({ + queryKey: ["library:shows", sortOption.id, textFilter], + queryFn: fetchShows, + initialPageParam: 0, + getNextPageParam: (lastPage, _allPages, lastPageParam) => { + return lastPage.totalLength > lastPageParam + limit ? lastPageParam + limit : void 0; + } + }); + import_react21.default.useEffect(() => { + const onUpdate = (e) => refetch(); + Spicetify.Platform.LibraryAPI.getEvents()._emitter.addListener("update", onUpdate); + return () => Spicetify.Platform.LibraryAPI.getEvents()._emitter.removeListener("update", onUpdate); + }, []); + const props = { + title: "Shows", + headerEls: [ + /* @__PURE__ */ import_react21.default.createElement(add_button_default, { + Menu: /* @__PURE__ */ import_react21.default.createElement(AddMenu3, null) + }), + dropdown, + /* @__PURE__ */ import_react21.default.createElement(searchbar_default, { + setSearch: setTextFilter, + placeholder: "Shows" + }), + /* @__PURE__ */ import_react21.default.createElement(settings_button_default, { + configWrapper + }) + ] + }; + if (status === "pending") { + return /* @__PURE__ */ import_react21.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react21.default.createElement(status_default, { + icon: "library", + heading: "Loading", + subheading: "Fetching your shows" + })); + } else if (status === "error") { + return /* @__PURE__ */ import_react21.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react21.default.createElement(status_default, { + icon: "error", + heading: "Error", + subheading: "Failed to load your shows" + })); + } else if (!data.pages[0].items.length) { + return /* @__PURE__ */ import_react21.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react21.default.createElement(status_default, { + icon: "library", + heading: "Nothing Here", + subheading: "You don't have any shows saved" + })); + } + const shows = data.pages.map((page) => page.items).flat(); + const showCards = shows.map((show) => { + return /* @__PURE__ */ import_react21.default.createElement(spotify_card_default, { + type: "show", + uri: show.uri, + header: show.name, + subheader: show.publisher, + imageUrl: show.images?.[0]?.url || "" + }); + }); + if (hasNextPage) + showCards.push(/* @__PURE__ */ import_react21.default.createElement(load_more_card_default, { + callback: fetchNextPage + })); + return /* @__PURE__ */ import_react21.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react21.default.createElement("div", { + className: `main-gridContainer-gridContainer grid` + }, showCards)); + }; + var shows_default = ShowsPage; + + // src/pages/playlists.tsx + var import_react22 = __toESM(require_react()); + var dropdownOptions = [ + { id: "0", name: "Name" }, + { id: "1", name: "Date Added" }, + { id: "2", name: "Creator" }, + { id: "4", name: "Custom Order" }, + { id: "6", name: "Recents" } + ]; + var filterOptions = [ + { id: "all", name: "All" }, + { id: "100", name: "Downloaded" }, + { id: "102", name: "By You" }, + { id: "103", name: "By Spotify" } + ]; + var AddMenu4 = ({ folder }) => { + const { MenuItem: MenuItem2, Menu } = Spicetify.ReactComponent; + const { RootlistAPI } = Spicetify.Platform; + const { SVGIcons } = Spicetify; + const insertLocation = folder ? { uri: folder } : "start"; + const createFolder = () => { + const onSave = (value) => { + RootlistAPI.createFolder(value || "New Folder", { after: insertLocation }); + }; + Spicetify.PopupModal.display({ + title: "Create Folder", + content: /* @__PURE__ */ import_react22.default.createElement(text_input_dialog_default, { + def: "New Folder", + placeholder: "Folder Name", + onSave + }) + }); + }; + const createPlaylist = () => { + const onSave = (value) => { + RootlistAPI.createPlaylist(value || "New Playlist", { after: insertLocation }); + }; + Spicetify.PopupModal.display({ + title: "Create Playlist", + content: /* @__PURE__ */ import_react22.default.createElement(text_input_dialog_default, { + def: "New Playlist", + placeholder: "Playlist Name", + onSave + }) + }); + }; + return /* @__PURE__ */ import_react22.default.createElement(Menu, null, /* @__PURE__ */ import_react22.default.createElement(MenuItem2, { + onClick: createFolder, + leadingIcon: /* @__PURE__ */ import_react22.default.createElement(leading_icon_default, { + path: SVGIcons["playlist-folder"] + }) + }, "Create Folder"), /* @__PURE__ */ import_react22.default.createElement(MenuItem2, { + onClick: createPlaylist, + leadingIcon: /* @__PURE__ */ import_react22.default.createElement(leading_icon_default, { + path: SVGIcons["playlist"] + }) + }, "Create Playlist")); + }; + var PlaylistsPage = ({ folder, configWrapper }) => { + const [sortDropdown, sortOption] = useDropdownMenu_default(dropdownOptions, "library:playlists-sort"); + const [filterDropdown, filterOption, setFilterOption, setAvailableOptions] = useDropdownMenu_default(filterOptions); + const [textFilter, setTextFilter] = import_react22.default.useState(""); + const [images, setImages] = import_react22.default.useState({ ...SpicetifyLibrary.FolderImageWrapper.getFolderImages() }); + const { useInfiniteQuery } = Spicetify.ReactQuery; + const limit = 200; + const fetchRootlist = async ({ pageParam }) => { + const filters = filterOption.id === "all" ? ["2"] : ["2", filterOption.id]; + const res = await Spicetify.Platform.LibraryAPI.getContents({ + filters, + sortOrder: sortOption.id, + folderUri: folder, + textFilter, + offset: pageParam, + limit + }); + return res; + }; + const { data, status, hasNextPage, fetchNextPage, refetch } = useInfiniteQuery({ + queryKey: ["library:playlists", sortOption.id, filterOption.id, textFilter, folder], + queryFn: fetchRootlist, + initialPageParam: 0, + getNextPageParam: (lastPage, _allPages, lastPageParam) => { + return lastPage.totalLength > lastPageParam + limit ? lastPageParam + limit : void 0; + } + }); + import_react22.default.useEffect(() => { + const onUpdate = (e) => refetch(); + const onImageUpdate = (e) => setImages({ ...e.detail }); + Spicetify.Platform.RootlistAPI.getEvents().addListener("update", onUpdate); + SpicetifyLibrary.FolderImageWrapper.addEventListener("update", onImageUpdate); + return () => { + Spicetify.Platform.RootlistAPI.getEvents().removeListener("update", onUpdate); + SpicetifyLibrary.FolderImageWrapper.removeEventListener("update", onImageUpdate); + }; + }, []); + const props = { + title: data?.pages[0].openedFolderName || "Playlists", + headerEls: [ + /* @__PURE__ */ import_react22.default.createElement(add_button_default, { + Menu: /* @__PURE__ */ import_react22.default.createElement(AddMenu4, { + folder + }) + }), + sortDropdown, + filterDropdown, + /* @__PURE__ */ import_react22.default.createElement(searchbar_default, { + setSearch: setTextFilter, + placeholder: "Playlists" + }), + /* @__PURE__ */ import_react22.default.createElement(settings_button_default, { + configWrapper + }) + ] + }; + if (status === "pending") { + return /* @__PURE__ */ import_react22.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react22.default.createElement(status_default, { + icon: "library", + heading: "Loading", + subheading: "Fetching your playlists" + })); + } else if (status === "error") { + return /* @__PURE__ */ import_react22.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react22.default.createElement(status_default, { + icon: "error", + heading: "Error", + subheading: "Failed to load your playlists" + })); + } else if (!data.pages[0].items.length) { + return /* @__PURE__ */ import_react22.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react22.default.createElement(status_default, { + icon: "library", + heading: "Nothing Here", + subheading: "You don't have any playlists saved" + })); + } + const rootlistItems = data.pages.map((page) => page.items).flat(); + const rootlistCards = rootlistItems.map((playlist) => { + return /* @__PURE__ */ import_react22.default.createElement(spotify_card_default, { + type: playlist.type, + uri: playlist.uri, + header: playlist.name, + subheader: playlist.owner?.name || "Folder", + imageUrl: playlist.images?.[0]?.url || images[playlist.uri] || "" + }); + }); + if (hasNextPage) + rootlistCards.push(/* @__PURE__ */ import_react22.default.createElement(load_more_card_default, { + callback: fetchNextPage + })); + return /* @__PURE__ */ import_react22.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react22.default.createElement("div", { + className: `main-gridContainer-gridContainer grid` + }, rootlistCards)); + }; + var playlists_default = PlaylistsPage; + + // package.json + var version = "0.1.1"; + + // src/app.tsx + var tabPages = ["Playlists", "Albums", "Artists", "Shows"]; + var checkForUpdates = (setNewUpdate) => { + fetch("https://api.github.com/repos/harbassan/spicetify-apps/releases").then((res) => res.json()).then( + (result) => { + const releases = result.filter((release) => release.name.startsWith("library")); + setNewUpdate(releases[0].name.slice(9) !== version); + }, + (error) => { + console.log("Failed to check for updates", error); + } + ); + }; + var NavbarContainer = ({ configWrapper }) => { + const pages = { + ["Artists"]: /* @__PURE__ */ import_react23.default.createElement(artists_default, { + configWrapper + }), + ["Albums"]: /* @__PURE__ */ import_react23.default.createElement(albums_default, { + configWrapper + }), + ["Shows"]: /* @__PURE__ */ import_react23.default.createElement(shows_default, { + configWrapper + }), + ["Playlists"]: /* @__PURE__ */ import_react23.default.createElement(playlists_default, { + configWrapper + }) + }; + const [navBar, activeLink, setActiveLink] = useNavigationBar_default(tabPages); + const [firstUpdate, setFirstUpdate] = import_react23.default.useState(true); + const [newUpdate, setNewUpdate] = import_react23.default.useState(false); + import_react23.default.useEffect(() => { + setActiveLink(Spicetify.LocalStorage.get("library:active-link") || "Playlists"); + checkForUpdates(setNewUpdate); + setFirstUpdate(false); + }, []); + import_react23.default.useEffect(() => { + Spicetify.LocalStorage.set("library:active-link", activeLink); + }, [activeLink]); + if (firstUpdate) + return /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null); + return /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, navBar, newUpdate && /* @__PURE__ */ import_react23.default.createElement("div", { + className: "new-update" + }, "New app update available! Visit", " ", /* @__PURE__ */ import_react23.default.createElement("a", { + href: "https://github.com/harbassan/spicetify-apps/releases" + }, "harbassan/spicetify-apps"), " to install."), pages[activeLink]); + }; + var App = () => { + const [config, setConfig] = import_react23.default.useState({ ...SpicetifyLibrary.ConfigWrapper.Config }); + const launchModal = () => { + SpicetifyLibrary.ConfigWrapper.launchModal(setConfig); + }; + const configWrapper = { + config, + launchModal + }; + const { pathname } = Spicetify.Platform.History.location; + const route = pathname.slice(8); + if (/^\/folder\/.+/.test(route)) { + return /* @__PURE__ */ import_react23.default.createElement("div", { + id: "library-app" + }, /* @__PURE__ */ import_react23.default.createElement(playlists_default, { + folder: route.split("/").pop(), + configWrapper + })); + } + if (/^\/collection\/.+/.test(route)) { + return /* @__PURE__ */ import_react23.default.createElement("div", { + id: "library-app" + }, /* @__PURE__ */ import_react23.default.createElement(albums_default, { + collection: route.split("/").pop(), + configWrapper + })); + } + return /* @__PURE__ */ import_react23.default.createElement("div", { + id: "library-app" + }, /* @__PURE__ */ import_react23.default.createElement(NavbarContainer, { + configWrapper + })); + }; + var app_default = App; + + // ../../../AppData/Local/Temp/spicetify-creator/index.jsx + var import_react24 = __toESM(require_react()); + function render() { + return /* @__PURE__ */ import_react24.default.createElement(app_default, null); + } + return __toCommonJS(spicetify_creator_exports); +})(); +const render=()=>library.default(); diff --git a/.config/spicetify/CustomApps/library/manifest.json b/.config/spicetify/CustomApps/library/manifest.json new file mode 100644 index 00000000..b234e30d --- /dev/null +++ b/.config/spicetify/CustomApps/library/manifest.json @@ -0,0 +1,11 @@ +{ + "name": "Your Library", + "icon": "\r\n\r\n\r\n", + "active-icon": "\r\n\r\n", + "subfiles": [], + "subfiles_extension": [ + "collections_wrapper.js", + "extension.js", + "folder_image_wrapper.js" + ] +} \ No newline at end of file diff --git a/.config/spicetify/CustomApps/library/style.css b/.config/spicetify/CustomApps/library/style.css new file mode 100644 index 00000000..9a15dd6c --- /dev/null +++ b/.config/spicetify/CustomApps/library/style.css @@ -0,0 +1,356 @@ +/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8bc8b4/navBar.module.css */ +.navBar-module__topBarHeaderItem___piw4C_library { + -webkit-app-region: no-drag; + display: inline-block; + pointer-events: auto; +} +.navBar-module__topBarHeaderItemLink___xA4uv_library { + margin: 0 8px 0 0; +} +.navBar-module__topBarActive___XhWpm_library { + background-color: var(--spice-tab-active); + border-radius: 4px; +} +.navBar-module__topBarHeaderItemLink___xA4uv_library { + border-radius: 4px; + color: var(--spice-text); + display: inline-block; + margin: 0 8px; + padding: 8px 16px; + position: relative; + text-decoration: none !important; + cursor: pointer; +} +.navBar-module__topBarNav___qWGeZ_library { + -webkit-app-region: drag; + pointer-events: none; + width: 100%; +} +.navBar-module__topBarHeaderItem___piw4C_library .navBar-module__optionsMenuDropBox___pzfNI_library { + color: var(--spice-text); + border: 0; + max-width: 150px; + height: 42px; + padding: 0 30px 0 12px; + background-color: initial; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.navBar-module__topBarHeaderItem___piw4C_library .navBar-module__optionsMenuDropBox___pzfNI_library svg { + position: absolute; + margin-left: 8px; +} +div.navBar-module__topBarHeaderItemLink___xA4uv_library { + padding: 0; +} + +/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8baff0/app.css */ +:root { + --library-card-size: 180px; + --library-searchbar-size: 200px; +} +#library-app .header-right .x-filterBox-expandedOrHasFilter .x-filterBox-filterInput { + width: var(--library-searchbar-size); +} +#library-app .grid { + grid-template-columns: repeat(auto-fill, minmax(var(--library-card-size), 1fr)) !important; +} +#library-app .load-more-card { + display: flex; + gap: 10px; + flex-direction: column; + justify-content: center; +} +#library-app .load-more-card div:nth-child(2) { + text-align: center; + font-size: var(--encore-text-size-base); +} +#library-app .load-more-card div:first-child { + fill: var(--text-subdued); + width: 80%; + margin: 0 auto; +} +#library-app .load-more-card:hover { + cursor: pointer; +} +.text-input-form { + display: flex; + flex-direction: column; + gap: 18px; +} +.text-input-form .text-input { + background: rgba(var(--spice-rgb-selected-row), 0.1); + border: 1px solid transparent; + border-radius: 4px; + color: var(--spice-text); + font-family: inherit; + font-size: 14px; + height: 32px; + padding: 0 12px; + width: 100%; +} +.text-input-form .text-input:focus { + background-color: var(--spice-tab-active); + border: 1px solid var(--spice-button-disabled); + outline: none; +} +.text-input-form button { + align-self: end; +} + +/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8bc361/external.css */ +body:not(.show-ylx-filters) .main-yourLibraryX-filterArea:not(:has(> .main-yourLibraryX-libraryFilter)), +.main-yourLibraryX-header:not(:has(> .main-yourLibraryX-headerContent > .main-yourLibraryX-collapseButton > button:nth-child(2))), +.main-yourLibraryX-collapseButton > button:first-child, +.main-yourLibraryX-headerContent > button { + display: none; +} +.main-yourLibraryX-library { + padding-top: 8px; +} +.main-yourLibraryX-header { + margin-top: -8px; +} +.main-yourLibraryX-librarySortWrapper button span:first-child { + display: none; +} +.main-yourLibraryX-librarySortWrapper { + margin-left: auto; +} +.toggle-filters-button > button:after, +.collapse-button > button:after, +.expand-button > button:after { + display: none; +} +.expand-button { + display: flex; + align-items: center; + z-index: 1; + margin-left: 5px; +} +.expand-button > button { + visibility: hidden; + margin: 0 5px; +} +li.main-yourLibraryX-navItem[data-id="/library"] { + display: flex; +} +li.main-yourLibraryX-navItem[data-id="/library"] > a { + flex-grow: 1; +} +.toggle-filters-button > button, +.collapse-button > button, +.main-yourLibraryX-librarySortWrapper > button { + padding: 0; +} +.toggle-filters-button, +.collapse-button, +.main-yourLibraryX-librarySortWrapper { + display: flex; + flex-basis: 32px; + justify-content: center; + min-width: 24px; + flex-shrink: 10; +} +.main-yourLibraryX-librarySortWrapper > button > span:nth-child(2) { + margin: 0; +} +.LayoutResizer__resize-bar { + opacity: 0 !important; +} +.Root__nav-bar .x-filterBox-expandedOrHasFilter .x-filterBox-filterInput { + width: 100%; +} +.Root__nav-bar .x-filterBox-expandedOrHasFilter { + flex-grow: 1; + margin-right: 5px; +} +.Root__nav-bar:has(> .LayoutResizer__resize-bar:hover) .expand-button > button, +.Root__nav-bar .expand-button:hover > button { + visibility: visible; + height: 32px; + background-color: black; +} +.text-input-form .Button-small-buttonPrimary { + box-sizing: border-box; + -webkit-tap-highlight-color: transparent; + font-size: 0.875rem; + font-weight: 700; + font-family: var(--font-family, CircularSp, CircularSp-Arab, CircularSp-Hebr, CircularSp-Cyrl, CircularSp-Grek, CircularSp-Deva, var(--fallback-fonts, sans-serif)); + background-color: transparent; + border: 0px; + border-radius: 9999px; + cursor: pointer; + display: inline-block; + position: relative; + text-align: center; + text-decoration: none; + text-transform: none; + touch-action: manipulation; + transition-duration: 33ms; + transition-property: + background-color, + border-color, + color, + box-shadow, + filter, + transform; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + vertical-align: middle; + transform: translate3d(0px, 0px, 0px); + padding: 0px; + min-inline-size: 0px; +} +.text-input-form .ButtonInner-small { + box-sizing: border-box; + -webkit-tap-highlight-color: transparent; + position: relative; + background-color: var(--background-base, #1ed760); + color: var(--text-base, #000000); + display: flex; + border-radius: 9999px; + font-size: inherit; + min-block-size: var(--encore-control-size-smaller, 32px); + align-items: center; + justify-content: center; + padding-block-start: var(--encore-spacing-tighter-4, 4px); + padding-block-end: var(--encore-spacing-tighter-4, 4px); + padding-inline-start: var(--encore-spacing-base, 16px); + padding-inline-end: var(--encore-spacing-base, 16px); +} +.text-input-form .Button-small-buttonPrimary:hover .ButtonInner-sc-14ud5tc-0, +.text-input-form .Button-small-buttonPrimary:hover .ButtonFocus-sc-2hq6ey-0 { + transform: scale(1.04); +} + +/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8bc5f2/config_modal.css */ +.config-container { + gap: 10px; + display: flex; + flex-direction: column; +} +.config-container .section-header { + box-sizing: border-box; + -webkit-tap-highlight-color: transparent; + margin-block: 0px; + font-size: 1.125rem; + font-weight: 700; + color: var(--spice-text); +} +.config-container .col.description { + box-sizing: border-box; + -webkit-tap-highlight-color: transparent; + margin-block: 0px; + font-size: 0.875rem; + font-weight: 400; + color: var(--spice-subtext); +} +.config-container .disabled { + opacity: 0; + pointer-events: none; +} +.config-container .text-input { + background: rgba(var(--spice-rgb-selected-row), 0.1); + border: 1px solid transparent; + border-radius: 4px; + color: var(--spice-text); + font-family: inherit; + font-size: 14px; + height: 32px; + padding: 0 12px; + width: 100%; +} +.config-container .text-input:focus { + background-color: var(--spice-tab-active); + border: 1px solid var(--spice-button-disabled); + outline: none; +} +.config-container .dropdown-input { + background-color: var(--spice-tab-active); + border: 0; + border-radius: 4px; + color: rgba(var(--spice-rgb-selected-row), 0.7); + font-size: 14px; + font-weight: 400; + height: 32px; + letter-spacing: 0.24px; + line-height: 20px; + padding: 0 32px 0 12px; + width: 100%; +} +.config-container .tooltip-icon { + float: right; + margin-left: 10px; + display: flex; + align-items: center; + height: 22px; + fill: var(--spice-subtext); +} +.config-container .tooltip-icon:hover { + fill: var(--spice-text); +} +.config-container .tooltip { + text-align: center; +} +.config-container .setting-row { + display: flex; + justify-content: space-between; +} +.config-container .playback-progressbar { + width: 200px; +} + +/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8bc713/shared.css */ +.grid { + --grid-gap: 24px; + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)) !important; +} +.loadingWrapper { + display: flex; + justify-content: center; + align-items: center; + min-height: 60vh; + flex-direction: column; + gap: 16px; +} +.loadingWrapper .status-icon { + width: 40px; + height: 40px; + fill: currentColor; +} +.page-content { + display: flex; + flex-direction: column; + gap: 24px; +} +.page-header { + align-content: space-between; + align-items: center; + display: flex; + justify-content: space-between; + margin: 16px 0; +} +.page-header .header-right, +.page-header .header-left { + display: flex; + align-items: center; + gap: 8px; +} +.page-header .header-right { + justify-content: flex-end; +} +.page-header .header-left { + justify-content: flex-start; +} +.new-update { + background-color: var(--spice-player); + color: var(--spice-text); + border-radius: 8px; + padding: 2px 12px; + margin: 0 24px; + border: 0px; +} diff --git a/.config/spicetify/CustomApps/marketplace/extension.js b/.config/spicetify/CustomApps/marketplace/extension.js index 20bd442c..cc6abe57 100644 --- a/.config/spicetify/CustomApps/marketplace/extension.js +++ b/.config/spicetify/CustomApps/marketplace/extension.js @@ -1,10 +1,10 @@ -!async function(){for(;!Spicetify.React||!Spicetify.ReactDOM;)await new Promise(e=>setTimeout(e,10));var e,t,i,l,_,u,F,U,T,D,r,c,n,V,B,q,z,f,h,o,C,p,K,H,J,W,a,G,Y,X,Z,s,d,g,b,m,v,Q,y,ee,te,w,re,ne,ae,k,x,oe,S,se;i=Object.create,l=Object.defineProperty,_=Object.getOwnPropertyDescriptor,u=Object.getOwnPropertyNames,F=Object.getPrototypeOf,U=Object.prototype.hasOwnProperty,e={"node_modules/.pnpm/chroma-js@2.4.2/node_modules/chroma-js/chroma.js"(e,t){var r;r=function(){"use strict";for(var e=function(e,t,r){return void 0===r&&(r=1),e<(t=void 0===t?0:t)?t:r>16,t>>8&255,255&t,1];if(e.match(tt))return 4===(e=5!==e.length&&9!==e.length?e:e.substr(1)).length&&(e=(e=e.split(""))[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]),[(t=parseInt(e,16))>>24&255,t>>16&255,t>>8&255,Math.round((255&t)/255*100)/100];throw new Error("unknown hex color: "+e)}function Ne(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r,n,a,o=(e=ct(e,"hsi"))[0],s=e[1],i=e[2];return isNaN(o)&&(o=0),isNaN(s)&&(s=0),360g.t1?e*e*e:g.t2*(e-g.t0)}function Me(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r=(e=$t(e,"lab"))[0],n=e[1],a=e[2],r=(r+16)/116,n=isNaN(n)?r:r+n/500,a=isNaN(a)?r:r-a/200;return r=g.Yn*je(r),n=g.Xn*je(n),a=g.Zn*je(a),[Pe(3.2404542*n-1.5371385*r-.4985314*a),Pe(-.969266*n+1.8760108*r+.041556*a),Pe(.0556434*n-.2040259*r+1.0572252*a),3>16,e>>8&255,255&e,1];throw new Error("unknown num color: "+e)}function Fe(e){var t,r,n=(e=e/100)<66?(t=255,r=e<6?0:-155.25485562709179-.44596950469579133*(r=e-2)+104.49216199393888*w(r),e<20?0:.8274096064007395*(n=e-10)-254.76935184120902+115.67994401066147*w(n)):(t=351.97690566805693+.114206453784165*(t=e-55)-40.25366309332127*w(t),r=325.4494125711974+.07943456536662342*(r=e-50)-28.0852963507957*w(r),255);return[t,r,n,1]}function Ue(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r=(a=Sr(e,"rgb"))[0],n=a[1],a=a[2],r=[Rr(r/255),Rr(n/255),Rr(a/255)],o=Lr(.4122214708*(n=r[0])+.5363325363*(a=r[1])+.0514459929*(r=r[2])),s=Lr(.2119034982*n+.6806995451*a+.1073969566*r),n=Lr(.0883024619*n+.2817188376*a+.6299787005*r);return[.2104542553*o+.793617785*s-.0040720468*n,1.9779984951*o-2.428592205*s+.4505937099*n,.0259040371*o+.7827717662*s-.808675766*n]}var u=l,Te=s,c=o,De=e.type,Ve=q,Be=K,qe=(Te.prototype.css=function(e){return Ve(this._rgb,e)},u.css=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(Te,[null].concat(e,["css"])))},c.format.css=Be,c.autodetect.push({p:5,test:function(e){for(var t=[],r=arguments.length-1;0d.t3?Mt(e,1/3):e/d.t2+d.t0},g=c,$t=e.unpack,At=Math.pow,_t=e.unpack,Ft=e.type,u=l,Ut=s,b=o,Tt=Ce,Dt=(Ut.prototype.lab=function(){return Tt(this._rgb)},u.lab=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(Ut,[null].concat(e,["lab"])))},b.format.lab=Me,b.autodetect.push({p:2,test:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];if(e=_t(e,"lab"),"array"===Ft(e)&&3===e.length)return"lab"}}),e.unpack),Vt=e.RAD2DEG,Bt=Math.sqrt,qt=Math.atan2,zt=Math.round,Kt=e.unpack,Ht=Ce,Jt=Ee,Wt=e.unpack,Gt=e.DEG2RAD,Yt=Math.sin,Xt=Math.cos,Zt=e.unpack,Qt=Ie,er=Me,tr=e.unpack,rr=$e,nr=e.unpack,ar=e.type,u=l,m=s,or=o,sr=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r=Kt(e,"rgb"),n=r[0],a=r[1],r=r[2],n=Ht(n,a,r),a=n[0],r=n[1],n=n[2];return Jt(a,r,n)},b=(m.prototype.lch=function(){return sr(this._rgb)},m.prototype.hcl=function(){return sr(this._rgb).reverse()},u.lch=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(m,[null].concat(e,["lch"])))},u.hcl=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(m,[null].concat(e,["hcl"])))},or.format.lch=$e,or.format.hcl=Ae,["lch","hcl"].forEach(function(r){return or.autodetect.push({p:2,test:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];if(e=nr(e,r),"array"===ar(e)&&3===e.length)return r}})}),{aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflower:"#6495ed",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"}),u=s,v=o,ir=e.type,y=b,lr=Oe,ur=Le,cr=(u.prototype.name=function(){for(var e=ur(this._rgb,"rgb"),t=0,r=Object.keys(y);t=a/n?s=i:o=i}return kr(i)},Sr=(k.prototype.temp=k.prototype.kelvin=k.prototype.temperature=function(){return xr(this._rgb)},u.temp=u.kelvin=u.temperature=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(k,[null].concat(e,["temp"])))},v.format.temp=v.format.kelvin=v.format.temperature=Fe,e.unpack),Lr=Math.cbrt,Or=Math.pow,Nr=Math.sign;function Rr(e){var t=Math.abs(e);return t<.04045?e/12.92:(Nr(e)||1)*Or((t+.055)/1.055,2.4)}function Cr(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r=(e=Pr(e,"lab"))[0],n=e[1],a=e[2],o=x(r+.3963377774*n+.2158037573*a,3),s=x(r-.1055613458*n-.0638541728*a,3),r=x(r-.0894841775*n-1.291485548*a,3);return[255*Mr(4.0767416621*o-3.3077115913*s+.2309699292*r),255*Mr(-1.2684380046*o+2.6097574011*s-.3413193965*r),255*Mr(-.0041960863*o-.7034186147*s+1.707614701*r),3=d[r];)r++;return r-1},x=function(e){return e},S=function(e){return e};return r(u),f.classes=function(e){var t;return null!=e?("array"===P(e)?h=[(d=e)[0],e[e.length-1]]:(t=C.analyze(h),d=0===e?[t.min,t.max]:C.limits(t,"e",e)),f):d},f.domain=function(r){if(!arguments.length)return h;b=r[0],m=r[r.length-1],l=[];var e=g.length;if(r.length===e&&b!==m)for(var t=0,n=Array.from(r);t=s[t+1];)t++;var r=(e-s[t])/(s[t+1]-s[t]);return o[t]+r*(o[t+1]-o[t])}))}return h=[b,m],f},f.mode=function(e){return arguments.length?(s=e,n(),f):s},f.range=function(e,t){return r(e),f},f.out=function(e){return a=e,f},f.spread=function(e){return arguments.length?(t=e,f):t},f.correctLightness=function(e){return n(),x=(e=null==e?!0:e)?function(e){for(var t=c(0,!0).lab()[0],r=c(1,!0).lab()[0],n=r 0");var l=Math.LOG10E*Wn(n),_=Math.LOG10E*Wn(a);s.push(n);for(var u=1;u.9999999)l[3]=1;return new On(Nn(l))}for(var h,p=e.shift(),d=p.get(o),g=[],b=0,m=0,v=0;v{this.observers[e]||(this.observers[e]=new Map);var t=this.observers[e].get(r)||0;this.observers[e].set(r,t+1)}),this}off(e,t){this.observers[e]&&(t?this.observers[e].delete(t):delete this.observers[e])}emit(n){for(var e=arguments.length,a=new Array(1{var[t,r]=e;for(let e=0;e{var[t,r]=e;for(let e=0;e":">",'"':""","'":"'","/":"/"},q=[" ",",","?","!",";"],z=new class{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){var t=this.regExpMap.get(e);return void 0!==t||(t=new RegExp(e),this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,t),this.regExpQueue.push(e)),t}}(20),f=class extends n{constructor(e){var t=1t[e]&&0{this.processors[e]&&(t=this.processors[e].process(t,r,n,a))}),t}},o={},C=class extends n{constructor(e){var t=1{r=x&&r!==c?r:O;this.options.missingKeyHandler?this.options.missingKeyHandler(e,i,t,r,N,n):this.backendConnector&&this.backendConnector.saveMissing&&this.backendConnector.saveMissing(e,i,t,r,N,n),this.emit("missingKey",e,i,t,c)};this.options.saveMissing&&(this.options.saveMissingPlurals&&b?t.forEach(t=>{var e=this.pluralResolver.getSuffixes(t,n);S&&n[`defaultValue${this.options.pluralSeparator}zero`]&&e.indexOf(this.options.pluralSeparator+"zero")<0&&e.push(this.options.pluralSeparator+"zero"),e.forEach(e=>{R([t],s+e,n["defaultValue"+e]||L)})}):R(t,s,L))}c=this.extendTranslation(c,r,n,u,a),t&&c===s&&this.options.appendNamespaceToMissingKey&&(c=i+":"+s),(t||e)&&this.options.parseMissingKeyHandler&&(c="v1"!==this.options.compatibilityAPI?this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?i+":"+s:s,e?c:void 0):this.options.parseMissingKeyHandler(c))}return e?(u.res=c,u.usedParams=this.getUsedParamsDetails(n),u):c}extendTranslation(r,n,a,o,s){var i=this;if(this.i18nFormat&&this.i18nFormat.parse)r=this.i18nFormat.parse(r,{...this.options.interpolation.defaultVariables,...a},a.lng||this.language||o.usedLng,o.usedNS,o.usedKey,{resolved:o});else if(!a.skipInterpolation){a.interpolation&&this.interpolator.init({...a,interpolation:{...this.options.interpolation,...a.interpolation}});var l="string"==typeof r&&(a&&a.interpolation&&void 0!==a.interpolation.skipOnVariables?a:this.options).interpolation.skipOnVariables;let e,t=(l&&(u=r.match(this.interpolator.nestingRegexp),e=u&&u.length),a.replace&&"string"!=typeof a.replace?a.replace:a);this.options.interpolation.defaultVariables&&(t={...this.options.interpolation.defaultVariables,...t}),r=this.interpolator.interpolate(r,t,a.lng||this.language,a),l&&(l=(u=r.match(this.interpolator.nestingRegexp))&&u.length,e{if(!this.isValidLookup(h)){t=this.extractFromKey(t,f);const i=t.key;n=i;let e=t.namespaces;this.options.fallbackNS&&(e=e.concat(this.options.fallbackNS));const l=void 0!==f.count&&"string"!=typeof f.count,u=l&&!f.ordinal&&0===f.count&&this.pluralResolver.shouldUseIntlApi(),c=void 0!==f.context&&("string"==typeof f.context||"number"==typeof f.context)&&""!==f.context,r=f.lngs||this.languageUtils.toResolveHierarchy(f.lng||this.language,f.fallbackLng);e.forEach(s=>{this.isValidLookup(h)||(a=s,!o[r[0]+"-"+s]&&this.utils&&this.utils.hasLoadedNamespace&&!this.utils.hasLoadedNamespace(a)&&(o[r[0]+"-"+s]=!0,this.logger.warn(`key "${n}" for languages "${r.join(", ")}" won't get resolved as namespace "${a}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!")),r.forEach(t=>{if(!this.isValidLookup(h)){d=t;var e,r=[i];if(this.i18nFormat&&this.i18nFormat.addLookupKeys)this.i18nFormat.addLookupKeys(r,i,t,s,f);else{let e;l&&(e=this.pluralResolver.getSuffix(t,f.count,f));var n,a=this.options.pluralSeparator+"zero",o=this.options.pluralSeparator+"ordinal"+this.options.pluralSeparator;l&&(r.push(i+e),f.ordinal&&0===e.indexOf(o)&&r.push(i+e.replace(o,this.options.pluralSeparator)),u)&&r.push(i+a),c&&(n=""+i+this.options.contextSeparator+f.context,r.push(n),l)&&(r.push(n+e),f.ordinal&&0===e.indexOf(o)&&r.push(n+e.replace(o,this.options.pluralSeparator)),u)&&r.push(n+a)}for(;e=r.pop();)this.isValidLookup(h)||(p=e,h=this.getResource(t,s,e,f))}}))})}}),{res:h,usedKey:n,exactUsedKey:p,usedLng:d,usedNS:a}}isValidLookup(e){return!(void 0===e||!this.options.returnNull&&null===e||!this.options.returnEmptyString&&""===e)}getResource(e,t,r){var n=3e.toLowerCase()):2===e.length?(e[0]=e[0].toLowerCase(),e[1]=e[1].toUpperCase(),-1{r||(e=this.formatLanguageCode(e),this.options.supportedLngs&&!this.isSupportedCode(e))||(r=e)}),!r&&this.options.supportedLngs&&e.forEach(e=>{if(!r){const t=this.getLanguagePartFromCode(e);if(this.isSupportedCode(t))return r=t;r=this.options.supportedLngs.find(e=>e===t||!(e.indexOf("-")<0&&t.indexOf("-")<0)&&(0{e&&(this.isSupportedCode(e)?r.push(e):this.logger.warn("rejecting language code not found in supportedLngs: "+e))};return"string"==typeof e&&(-1{r.indexOf(e)<0&&n(this.formatLanguageCode(e))}),r}},K=[{lngs:["ach","ak","am","arn","br","fil","gun","ln","mfe","mg","mi","oc","pt","pt-BR","tg","tl","ti","tr","uz","wa"],nr:[1,2],fc:1},{lngs:["af","an","ast","az","bg","bn","ca","da","de","dev","el","en","eo","es","et","eu","fi","fo","fur","fy","gl","gu","ha","hi","hu","hy","ia","it","kk","kn","ku","lb","mai","ml","mn","mr","nah","nap","nb","ne","nl","nn","no","nso","pa","pap","pms","ps","pt-PT","rm","sco","se","si","so","son","sq","sv","sw","ta","te","tk","ur","yo"],nr:[1,2],fc:2},{lngs:["ay","bo","cgg","fa","ht","id","ja","jbo","ka","km","ko","ky","lo","ms","sah","su","th","tt","ug","vi","wo","zh"],nr:[1],fc:3},{lngs:["be","bs","cnr","dz","hr","ru","sr","uk"],nr:[1,2,5],fc:4},{lngs:["ar"],nr:[0,1,2,3,11,100],fc:5},{lngs:["cs","sk"],nr:[1,2,5],fc:6},{lngs:["csb","pl"],nr:[1,2,5],fc:7},{lngs:["cy"],nr:[1,2,3,8],fc:8},{lngs:["fr"],nr:[1,2],fc:9},{lngs:["ga"],nr:[1,2,3,7,11],fc:10},{lngs:["gd"],nr:[1,2,3,20],fc:11},{lngs:["is"],nr:[1,2],fc:12},{lngs:["jv"],nr:[0,1],fc:13},{lngs:["kw"],nr:[1,2,3,4],fc:14},{lngs:["lt"],nr:[1,2,10],fc:15},{lngs:["lv"],nr:[1,2,0],fc:16},{lngs:["mk"],nr:[1,2],fc:17},{lngs:["mnk"],nr:[0,1,2],fc:18},{lngs:["mt"],nr:[1,2,11,20],fc:19},{lngs:["or"],nr:[2,1],fc:2},{lngs:["ro"],nr:[1,2,20],fc:20},{lngs:["sl"],nr:[5,1,2,3],fc:21},{lngs:["he","iw"],nr:[1,2,20,21],fc:22}],H={1:function(e){return Number(1""+t+e)}getSuffixes(t){let r=1a[e]-a[t]).map(e=>""+this.options.prepend+(r.ordinal?"ordinal"+this.options.prepend:"")+e):e.numbers.map(e=>this.getSuffix(t,e,r)):[]}getSuffix(e,t){var r=2this.options.prepend&&r.toString()?this.options.prepend+r.toString():r.toString();return"v1"===this.options.compatibilityJSON?1===r?"":"number"==typeof r?"_plural_"+r.toString():n():"v2"===this.options.compatibilityJSON||this.options.simplifyPluralSuffix&&2===e.numbers.length&&1===e.numbers[0]?n():this.options.prepend&&t.toString()?this.options.prepend+t.toString():t.toString()}shouldUseIntlApi(){return!J.includes(this.options.compatibilityJSON)}},Y=class{constructor(){var e=0e),this.init(e)}init(){var e=0e&&e.source===t?(e.lastIndex=0,e):new RegExp(t,"g");this.regexp=e(this.regexp,this.prefix+"(.+?)"+this.suffix),this.regexpUnescape=e(this.regexpUnescape,""+this.prefix+this.unescapePrefix+"(.+?)"+this.unescapeSuffix+this.suffix),this.nestingRegexp=e(this.nestingRegexp,this.nestingPrefix+"(.+?)"+this.nestingSuffix)}interpolate(n,r,a,o){let s,i,l;const u=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{};function t(e){return e.replace(/\$/g,"$$$$")}const c=e=>{var t;return e.indexOf(this.formatSeparator)<0?(t=ge(r,u,e,this.options.keySeparator,this.options.ignoreJSONStructure),this.alwaysFormat?this.format(t,void 0,a,{...o,...r,interpolationkey:e}):t):(e=(t=e.split(this.formatSeparator)).shift().trim(),t=t.join(this.formatSeparator).trim(),this.format(ge(r,u,e,this.options.keySeparator,this.options.ignoreJSONStructure),t,a,{...o,...r,interpolationkey:e}))},f=(this.resetRegExp(),o&&o.missingInterpolationHandler||this.options.missingInterpolationHandler),h=(o&&o.interpolation&&void 0!==o.interpolation.skipOnVariables?o:this.options).interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:e=>t(e)},{regex:this.regexp,safeValue:e=>this.escapeValue?t(this.escape(e)):t(e)}].forEach(e=>{for(l=0;s=e.regex.exec(n);){var t=s[1].trim();if(void 0===(i=c(t)))if("function"==typeof f){var r=f(n,s,o);i="string"==typeof r?r:""}else{if(!o||!Object.prototype.hasOwnProperty.call(o,t)){if(h){i=s[0];continue}this.logger.warn(`missed to pass in variable ${t} for interpolating `+n)}i=""}else"string"==typeof i||this.useRawValueToEscape||(i=ie(i));r=e.safeValue(i);if(n=n.replace(s[0],r),h?(e.regex.lastIndex+=i.length,e.regex.lastIndex-=s[0].length):e.regex.lastIndex=0,++l>=this.maxReplaces)break}}),n}nest(r,n){let a=2e.trim()),o[1]=u.shift(),e=u,t=!0),(s=n(l.call(this,o[1].trim(),i),i))&&o[0]===r&&"string"!=typeof s)return s;(s="string"!=typeof s?ie(s):s)||(this.logger.warn(`missed to resolve ${o[1]} for nesting `+r),s=""),t&&(s=e.reduce((e,t)=>this.format(e,t,a.lng,{...a,interpolationkey:o[1].trim()}),s.trim())),r=r.replace(o[0],s),this.regexp.lastIndex=0}return r}},X=class{constructor(){var e=0{const r=new Intl.NumberFormat(e,{...t});return e=>r.format(e)}),currency:E((e,t)=>{const r=new Intl.NumberFormat(e,{...t,style:"currency"});return e=>r.format(e)}),datetime:E((e,t)=>{const r=new Intl.DateTimeFormat(e,{...t});return e=>r.format(e)}),relativetime:E((e,t)=>{const r=new Intl.RelativeTimeFormat(e,{...t});return e=>r.format(e,t.range||"day")}),list:E((e,t)=>{const r=new Intl.ListFormat(e,{...t});return e=>r.format(e)})},this.init(e)}init(e){var t=(1{var{formatName:r,formatOptions:n}=be(r);if(this.formats[r]){let e=t;try{var a=i&&i.formatParams&&i.formatParams[i.interpolationkey]||{},o=a.locale||a.lng||i.locale||i.lng||s;e=this.formats[r](t,o,{...n,...i,...a})}catch(e){this.logger.warn(e)}return e}return this.logger.warn("there was no format function for "+r),t},e)}},Z=class extends n{constructor(e,t,r){var n=3{let n=!0;t.forEach(e=>{var t=r+"|"+e;!a.reload&&this.store.hasResourceBundle(r,e)?this.state[t]=2:this.state[t]<0||(1===this.state[t]?void 0===s[t]&&(s[t]=!0):(this.state[t]=1,n=!1,void 0===s[t]&&(s[t]=!0),void 0===o[t]&&(o[t]=!0),void 0===l[e]&&(l[e]=!0)))}),n||(i[r]=!0)}),(Object.keys(o).length||Object.keys(s).length)&&this.queue.push({pending:s,pendingCount:Object.keys(s).length,loaded:{},errors:[],callback:r}),{toLoad:Object.keys(o),pending:Object.keys(s),toLoadLanguages:Object.keys(i),toLoadNamespaces:Object.keys(l)}}loaded(e,t,r){var n=e.split("|");const a=n[0],o=n[1],s=(t&&this.emit("failedLoading",a,o,t),r&&this.store.addResourceBundle(a,o,r,void 0,void 0,{skipCopy:!0}),this.state[e]=t?-1:2,{});this.queue.forEach(r=>{ce(r.loaded,[a],o),me(r,e),t&&r.errors.push(t),0!==r.pendingCount||r.done||(Object.keys(r.loaded).forEach(t=>{s[t]||(s[t]={});var e=r.loaded[t];e.length&&e.forEach(e=>{void 0===s[t][e]&&(s[t][e]=!0)})}),r.done=!0,r.errors.length?r.callback(r.errors):r.callback())}),this.emit("loaded",s),this.queue=this.queue.filter(e=>!e.done)}read(n,a,o){let s=3=this.maxParallelReads)this.waitingReads.push({lng:n,ns:a,fcName:o,tried:s,wait:i,callback:l});else{this.readingCalls++;const r=(e,t)=>{var r;this.readingCalls--,0{this.read.call(this,n,a,o,s+1,2*i,l)},i):l(e,t)};var e=this.backend[o].bind(this.backend);if(2!==e.length)return e(n,a,r);try{var t=e(n,a);t&&"function"==typeof t.then?t.then(e=>r(null,e)).catch(r):r(null,t)}catch(e){r(e)}}}prepareLoading(e,t){var r=2{this.loadOne(e)})}load(e,t,r){this.prepareLoading(e,t,{},r)}reload(e,t,r){this.prepareLoading(e,t,{reload:!0},r)}loadOne(r){let n=1{e&&this.logger.warn(`${n}loading namespace ${o} for language ${a} failed`,e),!e&&t&&this.logger.log(`${n}loaded namespace ${o} for language `+a,t),this.loaded(r,e,t)})}saveMissing(t,r,n,a,o){var s=5{};if(this.services.utils&&this.services.utils.hasLoadedNamespace&&!this.services.utils.hasLoadedNamespace(r))this.logger.warn(`did not save key "${n}" as the namespace "${r}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");else if(null!=n&&""!==n){if(this.backend&&this.backend.create){s={...s,isUpdate:o},o=this.backend.create.bind(this.backend);if(o.length<6)try{let e;(e=5===o.length?o(t,r,n,a,s):o(t,r,n,a))&&"function"==typeof e.then?e.then(e=>i(null,e)).catch(i):i(null,e)}catch(e){i(e)}else o(t,r,n,a,i,s)}t&&t[0]&&this.store.addResource(t[0],r,n,a)}}},s=class extends n{constructor(){let e=0{this.init(e,t)},0)}}init(){var a=this;let e=0{e.init&&e.init(this)})}this.format=this.options.interpolation.format,r=r||I,!this.options.fallbackLng||this.services.languageDetector||this.options.lng||0<(o=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng)).length&&"dev"!==o[0]&&(this.options.lng=o[0]),this.services.languageDetector||this.options.lng||this.logger.warn("init: no languageDetector is used and no lng is defined");["getResource","hasResourceBundle","getResourceBundle","getDataByLanguage"].forEach(e=>{this[e]=function(){return a.store[e](...arguments)}});["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(e=>{this[e]=function(){return a.store[e](...arguments),a}});const i=L();t=()=>{var e=(e,t)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn("init: i18next is already initialized. You should call init just once!"),this.isInitialized=!0,this.options.isClone||this.logger.log("initialized",this.options),this.emit("initialized",this.options),i.resolve(t),r(e,t)};if(this.languages&&"v1"!==this.options.compatibilityAPI&&!this.isInitialized)return e(null,this.t.bind(this));this.changeLanguage(this.options.lng,e)};return this.options.resources||!this.options.initImmediate?t():setTimeout(t,0),i}loadResources(e){let t=1{e&&"cimode"!==e&&this.services.languageUtils.toResolveHierarchy(e).forEach(e=>{"cimode"!==e&&n.indexOf(e)<0&&n.push(e)})};r?a(r):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(e=>a(e)),this.options.preload&&this.options.preload.forEach(e=>a(e)),this.services.backendConnector.load(n,this.options.ns,e=>{e||this.resolvedLanguage||!this.language||this.setResolvedLanguage(this.language),t(e)})}else t(null)}reloadResources(e,t,r){const n=L();return e=e||this.languages,t=t||this.options.ns,r=r||I,this.services.backendConnector.reload(e,t,e=>{n.resolve(),r(e)}),n}use(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(e.type)return"backend"===e.type&&(this.modules.backend=e),("logger"===e.type||e.log&&e.warn&&e.error)&&(this.modules.logger=e),"languageDetector"===e.type&&(this.modules.languageDetector=e),"i18nFormat"===e.type&&(this.modules.i18nFormat=e),"postProcessor"===e.type&&h.addPostProcessor(e),"formatter"===e.type&&(this.modules.formatter=e),"3rdParty"===e.type&&this.modules.external.push(e),this;throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()")}setResolvedLanguage(e){if(e&&this.languages&&!(-1<["cimode","dev"].indexOf(e)))for(let e=0;e{this.language=e,this.languages=this.services.languageUtils.toResolveHierarchy(e),this.resolvedLanguage=void 0,this.setResolvedLanguage(e)}),i=(e,t)=>{t?(s(t),this.translator.changeLanguage(t),this.isLanguageChangingTo=void 0,this.emit("languageChanged",t),this.logger.log("languageChanged",t)):this.isLanguageChangingTo=void 0,o.resolve(function(){return a.t(...arguments)}),n&&n(e,function(){return a.t(...arguments)})};var e=e=>{const t="string"==typeof(e=r||e||!this.services.languageDetector?e:[])?e:this.services.languageUtils.getBestMatchFromCodes(e);t&&(this.language||s(t),this.translator.language||this.translator.changeLanguage(t),this.services.languageDetector)&&this.services.languageDetector.cacheUserLanguage&&this.services.languageDetector.cacheUserLanguage(t),this.loadResources(t,e=>{i(e,t)})};return r||!this.services.languageDetector||this.services.languageDetector.async?!r&&this.services.languageDetector&&this.services.languageDetector.async?0===this.services.languageDetector.detect.length?this.services.languageDetector.detect().then(e):this.services.languageDetector.detect(e):e(r):e(this.services.languageDetector.detect()),o}getFixedT(e,t,l){var u=this;function c(e,t){let r;if("object"!=typeof t){for(var n=arguments.length,a=new Array(2""+r.keyPrefix+s+e):r.keyPrefix?""+r.keyPrefix+s+e:e,u.t(i,r)}return"string"==typeof e?c.lng=e:c.lngs=e,c.ns=t,c.keyPrefix=l,c}t(){return this.translator&&this.translator.translate(...arguments)}exists(){return this.translator&&this.translator.exists(...arguments)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e){var t=1{e=this.services.backendConnector.state[e+"|"+t];return-1===e||2===e};if(t.precheck){t=t.precheck(this,o);if(void 0!==t)return t}return!!this.hasResourceBundle(r,e)||!(this.services.backendConnector.backend&&(!this.options.resources||this.options.partialBundledLanguages)&&(!o(r,e)||n&&!o(a,e)))}loadNamespaces(e,t){const r=L();return this.options.ns?((e="string"==typeof e?[e]:e).forEach(e=>{this.options.ns.indexOf(e)<0&&this.options.ns.push(e)}),this.loadResources(e=>{r.resolve(),t&&t(e)}),r):(t&&t(),Promise.resolve())}loadLanguages(e,t){const r=L(),n=this.options.preload||[];e=(e="string"==typeof e?[e]:e).filter(e=>n.indexOf(e)<0);return e.length?(this.options.preload=n.concat(e),this.loadResources(e=>{r.resolve(),t&&t(e)}),r):(t&&t(),Promise.resolve())}dir(e){var t;return!(e=e||this.resolvedLanguage||(this.languages&&0{a[e]=this[e]}),a.services={...this.services},a.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},r&&(a.store=new f(this.store.data,n),a.services.resourceStore=a.store),a.translator=new C(a.services,n),a.translator.on("*",function(e){for(var t=arguments.length,r=new Array(1{r=null!=e?i(F(e)):{};var n=!t&&e&&e.__esModule?r:l(r,"default",{value:e,enumerable:!0}),a=e,o=void 0,s=void 0;if(a&&"object"==typeof a||"function"==typeof a)for(let e of u(a))U.call(n,e)||e===o||l(n,e,{get:()=>a[e],enumerable:!(s=_(a,e))||s.enumerable});return n})(T()),v=(t,e)=>{t=localStorage.getItem(t);if(!t)return e;try{return JSON.parse(t)}catch(e){return t}},Q=e=>{if(3===e.length)e=e.split("").map(e=>e+e).join("");else{if(6!=e.length)throw"Only 3- or 6-digit hex colours are allowed.";if(e.match(/[^0-9a-f]/i))throw"Only hex colours are allowed."}e=e.match(/.{1,2}/g);if(e&&3===e.length)return[parseInt(e[0],16),parseInt(e[1],16),parseInt(e[2],16)];throw"Could not parse hex colour."},y=(e,t)=>{let r=[];return e&&0({name:e.name,url:oe(e.url)})):r.push({name:t,url:"https://github.com/"+t}),r},ee=(...e)=>{console.debug("Resetting Marketplace");const t=[];0===e.length&&Object.keys(localStorage).forEach(e=>{e.startsWith("marketplace:")&&t.push(e)}),e.forEach(e=>{switch(e){case"extensions":t.push(...v(g.installedExtensions,[])),t.push(g.installedExtensions);break;case"snippets":t.push(...v(g.installedSnippets,[])),t.push(g.installedSnippets);break;case"theme":t.push(...v(g.installedThemes,[])),t.push(g.installedThemes),t.push(g.themeInstalled);break;default:console.error("Unknown category: "+e)}}),t.forEach(e=>{localStorage.removeItem(e),console.debug("Removed "+e)}),console.debug("Marketplace has been reset"),location.reload()},te=()=>{const t={};return Object.keys(localStorage).forEach(e=>{e.startsWith("marketplace:")&&(t[e]=localStorage.getItem(e))}),t},w=r=>{var e=document.querySelector("style.marketplaceCSS.marketplaceScheme");if(e&&e.remove(),r){e=document.createElement("style");e.classList.add("marketplaceCSS"),e.classList.add("marketplaceScheme");let t=":root {";Object.keys(r).forEach(e=>{t=(t+=`--spice-${e}: #${r[e]};`)+`--spice-rgb-${e}: ${Q(r[e])};`}),t+="}",e.innerHTML=t,document.body.appendChild(e)}},re=async e=>{let t=v(g.albumArtBasedColorVibrancy);return t=t.replace(/([A-Z])/g,"_$1").toUpperCase(),(await Spicetify.colorExtractor(e))[t].substring(1)},ne=async(e,t)=>{var r=v(g.albumArtBasedColorMode).replace(/([A-Z])/g,"-$1").toLowerCase();return(await fetch(`https://www.thecolorapi.com/scheme?hex=${e}&mode=${r}&count=`+t).then(e=>e.json())).colors.map(e=>e.hex.value.substring(1))},ae=h=>{Spicetify.Player.addEventListener("songchange",async()=>{var t;t=1e3,await new Promise(e=>setTimeout(e,t));let r=Spicetify.Player.data?.item?.metadata?.image_xlarge_url;if(r=null==r?await new Promise(t=>{setInterval(()=>{var e=Spicetify.Player.data?.item?.metadata?.image_xlarge_url;e&&t(e)},50)}):r){var n,a,o=new Set(Object.values(h)).size,s=await re(r),i=await ne(s,o);let e=new Map;for([n,a]of Object.entries(h))e.has(a)?e.get(a).push(n):e.set(a,[n]);var l,s=new Map([...e.entries()].sort((e,t)=>{e=(0,m.default)(e[0]),t=(0,m.default)(t[0]);return e.get("lab.l")-t.get("lab.l")})),u={};for([,l]of(e=s).entries()){var c=i.shift();if(c)for(const f of l)u[f]=c}w(u)}})},k=e=>{e=new URL(e);return e.host,"raw.githubusercontent.com"===e.host},x=e=>{e=e.match(/https:\/\/raw\.githubusercontent\.com\/(?[^/]+)\/(?[^/]+)\/(?[^/]+)\/(?.+$)/);return{user:e?e.groups?.user:null,repo:e?e.groups?.repo:null,branch:e?e.groups?.branch:null,filePath:e?e.groups?.filePath:null}},oe=e=>{var t=decodeURI(e).trim().toLowerCase();return t.startsWith("javascript:")||t.startsWith("data:")||t.startsWith("vbscript:")?"about:blank":e},S=e=>{e&&(e=e.split("/").pop())&&-1===Spicetify.Config.extensions.indexOf(e)&&Spicetify.Config.extensions.push(e)},n=new Blob([` +!async function(){for(;!Spicetify.React||!Spicetify.ReactDOM;)await new Promise(e=>setTimeout(e,10));var e,t,i,l,_,u,F,U,T,D,r,c,n,V,B,q,z,f,h,o,C,p,K,H,J,W,a,G,Y,X,Z,s,d,g,b,m,v,Q,y,ee,te,w,re,ne,ae,k,x,oe,S,se;i=Object.create,l=Object.defineProperty,_=Object.getOwnPropertyDescriptor,u=Object.getOwnPropertyNames,F=Object.getPrototypeOf,U=Object.prototype.hasOwnProperty,e={"node_modules/.pnpm/chroma-js@2.4.2/node_modules/chroma-js/chroma.js"(e,t){var r;r=function(){"use strict";for(var e=function(e,t,r){return void 0===r&&(r=1),e<(t=void 0===t?0:t)?t:r>16,t>>8&255,255&t,1];if(e.match(tt))return 4===(e=5!==e.length&&9!==e.length?e:e.substr(1)).length&&(e=(e=e.split(""))[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]),[(t=parseInt(e,16))>>24&255,t>>16&255,t>>8&255,Math.round((255&t)/255*100)/100];throw new Error("unknown hex color: "+e)}function Ne(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r,n,a,o=(e=ct(e,"hsi"))[0],s=e[1],i=e[2];return isNaN(o)&&(o=0),isNaN(s)&&(s=0),360g.t1?e*e*e:g.t2*(e-g.t0)}function Me(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r=(e=$t(e,"lab"))[0],n=e[1],a=e[2],r=(r+16)/116,n=isNaN(n)?r:r+n/500,a=isNaN(a)?r:r-a/200;return r=g.Yn*je(r),n=g.Xn*je(n),a=g.Zn*je(a),[Pe(3.2404542*n-1.5371385*r-.4985314*a),Pe(-.969266*n+1.8760108*r+.041556*a),Pe(.0556434*n-.2040259*r+1.0572252*a),3>16,e>>8&255,255&e,1];throw new Error("unknown num color: "+e)}function Fe(e){var t,r,n=(e=e/100)<66?(t=255,r=e<6?0:-155.25485562709179-.44596950469579133*(r=e-2)+104.49216199393888*w(r),e<20?0:.8274096064007395*(n=e-10)-254.76935184120902+115.67994401066147*w(n)):(t=351.97690566805693+.114206453784165*(t=e-55)-40.25366309332127*w(t),r=325.4494125711974+.07943456536662342*(r=e-50)-28.0852963507957*w(r),255);return[t,r,n,1]}function Ue(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r=(a=Sr(e,"rgb"))[0],n=a[1],a=a[2],r=[Rr(r/255),Rr(n/255),Rr(a/255)],o=Lr(.4122214708*(n=r[0])+.5363325363*(a=r[1])+.0514459929*(r=r[2])),s=Lr(.2119034982*n+.6806995451*a+.1073969566*r),n=Lr(.0883024619*n+.2817188376*a+.6299787005*r);return[.2104542553*o+.793617785*s-.0040720468*n,1.9779984951*o-2.428592205*s+.4505937099*n,.0259040371*o+.7827717662*s-.808675766*n]}var u=l,Te=s,c=o,De=e.type,Ve=q,Be=K,qe=(Te.prototype.css=function(e){return Ve(this._rgb,e)},u.css=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(Te,[null].concat(e,["css"])))},c.format.css=Be,c.autodetect.push({p:5,test:function(e){for(var t=[],r=arguments.length-1;0d.t3?Mt(e,1/3):e/d.t2+d.t0},g=c,$t=e.unpack,At=Math.pow,_t=e.unpack,Ft=e.type,u=l,Ut=s,b=o,Tt=Ce,Dt=(Ut.prototype.lab=function(){return Tt(this._rgb)},u.lab=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(Ut,[null].concat(e,["lab"])))},b.format.lab=Me,b.autodetect.push({p:2,test:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];if(e=_t(e,"lab"),"array"===Ft(e)&&3===e.length)return"lab"}}),e.unpack),Vt=e.RAD2DEG,Bt=Math.sqrt,qt=Math.atan2,zt=Math.round,Kt=e.unpack,Ht=Ce,Jt=Ee,Wt=e.unpack,Gt=e.DEG2RAD,Yt=Math.sin,Xt=Math.cos,Zt=e.unpack,Qt=Ie,er=Me,tr=e.unpack,rr=$e,nr=e.unpack,ar=e.type,u=l,m=s,or=o,sr=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r=Kt(e,"rgb"),n=r[0],a=r[1],r=r[2],n=Ht(n,a,r),a=n[0],r=n[1],n=n[2];return Jt(a,r,n)},b=(m.prototype.lch=function(){return sr(this._rgb)},m.prototype.hcl=function(){return sr(this._rgb).reverse()},u.lch=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(m,[null].concat(e,["lch"])))},u.hcl=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(m,[null].concat(e,["hcl"])))},or.format.lch=$e,or.format.hcl=Ae,["lch","hcl"].forEach(function(r){return or.autodetect.push({p:2,test:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];if(e=nr(e,r),"array"===ar(e)&&3===e.length)return r}})}),{aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflower:"#6495ed",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"}),u=s,v=o,ir=e.type,y=b,lr=Oe,ur=Le,cr=(u.prototype.name=function(){for(var e=ur(this._rgb,"rgb"),t=0,r=Object.keys(y);t=a/n?s=i:o=i}return kr(i)},Sr=(k.prototype.temp=k.prototype.kelvin=k.prototype.temperature=function(){return xr(this._rgb)},u.temp=u.kelvin=u.temperature=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(k,[null].concat(e,["temp"])))},v.format.temp=v.format.kelvin=v.format.temperature=Fe,e.unpack),Lr=Math.cbrt,Or=Math.pow,Nr=Math.sign;function Rr(e){var t=Math.abs(e);return t<.04045?e/12.92:(Nr(e)||1)*Or((t+.055)/1.055,2.4)}function Cr(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var r=(e=Pr(e,"lab"))[0],n=e[1],a=e[2],o=x(r+.3963377774*n+.2158037573*a,3),s=x(r-.1055613458*n-.0638541728*a,3),r=x(r-.0894841775*n-1.291485548*a,3);return[255*Mr(4.0767416621*o-3.3077115913*s+.2309699292*r),255*Mr(-1.2684380046*o+2.6097574011*s-.3413193965*r),255*Mr(-.0041960863*o-.7034186147*s+1.707614701*r),3=d[r];)r++;return r-1},x=function(e){return e},S=function(e){return e};return r(u),f.classes=function(e){var t;return null!=e?("array"===P(e)?h=[(d=e)[0],e[e.length-1]]:(t=C.analyze(h),d=0===e?[t.min,t.max]:C.limits(t,"e",e)),f):d},f.domain=function(r){if(!arguments.length)return h;b=r[0],m=r[r.length-1],l=[];var e=g.length;if(r.length===e&&b!==m)for(var t=0,n=Array.from(r);t=s[t+1];)t++;var r=(e-s[t])/(s[t+1]-s[t]);return o[t]+r*(o[t+1]-o[t])}))}return h=[b,m],f},f.mode=function(e){return arguments.length?(s=e,n(),f):s},f.range=function(e,t){return r(e),f},f.out=function(e){return a=e,f},f.spread=function(e){return arguments.length?(t=e,f):t},f.correctLightness=function(e){return n(),x=(e=null==e?!0:e)?function(e){for(var t=c(0,!0).lab()[0],r=c(1,!0).lab()[0],n=r 0");var l=Math.LOG10E*Wn(n),_=Math.LOG10E*Wn(a);s.push(n);for(var u=1;u.9999999)l[3]=1;return new On(Nn(l))}for(var h,p=e.shift(),d=p.get(o),g=[],b=0,m=0,v=0;v{this.observers[e]||(this.observers[e]=new Map);var t=this.observers[e].get(r)||0;this.observers[e].set(r,t+1)}),this}off(e,t){this.observers[e]&&(t?this.observers[e].delete(t):delete this.observers[e])}emit(n){for(var e=arguments.length,a=new Array(1{var[t,r]=e;for(let e=0;e{var[t,r]=e;for(let e=0;e":">",'"':""","'":"'","/":"/"},q=[" ",",","?","!",";"],z=new class{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){var t=this.regExpMap.get(e);return void 0!==t||(t=new RegExp(e),this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,t),this.regExpQueue.push(e)),t}}(20),f=class extends n{constructor(e){var t=1t[e]&&0{this.processors[e]&&(t=this.processors[e].process(t,r,n,a))}),t}},o={},C=class extends n{constructor(e){var t=1{r=x&&r!==c?r:O;this.options.missingKeyHandler?this.options.missingKeyHandler(e,i,t,r,N,n):this.backendConnector&&this.backendConnector.saveMissing&&this.backendConnector.saveMissing(e,i,t,r,N,n),this.emit("missingKey",e,i,t,c)};this.options.saveMissing&&(this.options.saveMissingPlurals&&b?t.forEach(t=>{var e=this.pluralResolver.getSuffixes(t,n);S&&n[`defaultValue${this.options.pluralSeparator}zero`]&&e.indexOf(this.options.pluralSeparator+"zero")<0&&e.push(this.options.pluralSeparator+"zero"),e.forEach(e=>{R([t],s+e,n["defaultValue"+e]||L)})}):R(t,s,L))}c=this.extendTranslation(c,r,n,u,a),t&&c===s&&this.options.appendNamespaceToMissingKey&&(c=i+":"+s),(t||e)&&this.options.parseMissingKeyHandler&&(c="v1"!==this.options.compatibilityAPI?this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?i+":"+s:s,e?c:void 0):this.options.parseMissingKeyHandler(c))}return e?(u.res=c,u.usedParams=this.getUsedParamsDetails(n),u):c}extendTranslation(r,n,a,o,s){var i=this;if(this.i18nFormat&&this.i18nFormat.parse)r=this.i18nFormat.parse(r,{...this.options.interpolation.defaultVariables,...a},a.lng||this.language||o.usedLng,o.usedNS,o.usedKey,{resolved:o});else if(!a.skipInterpolation){a.interpolation&&this.interpolator.init({...a,interpolation:{...this.options.interpolation,...a.interpolation}});var l="string"==typeof r&&(a&&a.interpolation&&void 0!==a.interpolation.skipOnVariables?a:this.options).interpolation.skipOnVariables;let e,t=(l&&(u=r.match(this.interpolator.nestingRegexp),e=u&&u.length),a.replace&&"string"!=typeof a.replace?a.replace:a);this.options.interpolation.defaultVariables&&(t={...this.options.interpolation.defaultVariables,...t}),r=this.interpolator.interpolate(r,t,a.lng||this.language,a),l&&(l=(u=r.match(this.interpolator.nestingRegexp))&&u.length,e{if(!this.isValidLookup(h)){t=this.extractFromKey(t,f);const i=t.key;n=i;let e=t.namespaces;this.options.fallbackNS&&(e=e.concat(this.options.fallbackNS));const l=void 0!==f.count&&"string"!=typeof f.count,u=l&&!f.ordinal&&0===f.count&&this.pluralResolver.shouldUseIntlApi(),c=void 0!==f.context&&("string"==typeof f.context||"number"==typeof f.context)&&""!==f.context,r=f.lngs||this.languageUtils.toResolveHierarchy(f.lng||this.language,f.fallbackLng);e.forEach(s=>{this.isValidLookup(h)||(a=s,!o[r[0]+"-"+s]&&this.utils&&this.utils.hasLoadedNamespace&&!this.utils.hasLoadedNamespace(a)&&(o[r[0]+"-"+s]=!0,this.logger.warn(`key "${n}" for languages "${r.join(", ")}" won't get resolved as namespace "${a}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!")),r.forEach(t=>{if(!this.isValidLookup(h)){d=t;var e,r=[i];if(this.i18nFormat&&this.i18nFormat.addLookupKeys)this.i18nFormat.addLookupKeys(r,i,t,s,f);else{let e;l&&(e=this.pluralResolver.getSuffix(t,f.count,f));var n,a=this.options.pluralSeparator+"zero",o=this.options.pluralSeparator+"ordinal"+this.options.pluralSeparator;l&&(r.push(i+e),f.ordinal&&0===e.indexOf(o)&&r.push(i+e.replace(o,this.options.pluralSeparator)),u)&&r.push(i+a),c&&(n=""+i+this.options.contextSeparator+f.context,r.push(n),l)&&(r.push(n+e),f.ordinal&&0===e.indexOf(o)&&r.push(n+e.replace(o,this.options.pluralSeparator)),u)&&r.push(n+a)}for(;e=r.pop();)this.isValidLookup(h)||(p=e,h=this.getResource(t,s,e,f))}}))})}}),{res:h,usedKey:n,exactUsedKey:p,usedLng:d,usedNS:a}}isValidLookup(e){return!(void 0===e||!this.options.returnNull&&null===e||!this.options.returnEmptyString&&""===e)}getResource(e,t,r){var n=3e.toLowerCase()):2===e.length?(e[0]=e[0].toLowerCase(),e[1]=e[1].toUpperCase(),-1{r||(e=this.formatLanguageCode(e),this.options.supportedLngs&&!this.isSupportedCode(e))||(r=e)}),!r&&this.options.supportedLngs&&e.forEach(e=>{if(!r){const t=this.getLanguagePartFromCode(e);if(this.isSupportedCode(t))return r=t;r=this.options.supportedLngs.find(e=>e===t||!(e.indexOf("-")<0&&t.indexOf("-")<0)&&(0{e&&(this.isSupportedCode(e)?r.push(e):this.logger.warn("rejecting language code not found in supportedLngs: "+e))};return"string"==typeof e&&(-1{r.indexOf(e)<0&&n(this.formatLanguageCode(e))}),r}},K=[{lngs:["ach","ak","am","arn","br","fil","gun","ln","mfe","mg","mi","oc","pt","pt-BR","tg","tl","ti","tr","uz","wa"],nr:[1,2],fc:1},{lngs:["af","an","ast","az","bg","bn","ca","da","de","dev","el","en","eo","es","et","eu","fi","fo","fur","fy","gl","gu","ha","hi","hu","hy","ia","it","kk","kn","ku","lb","mai","ml","mn","mr","nah","nap","nb","ne","nl","nn","no","nso","pa","pap","pms","ps","pt-PT","rm","sco","se","si","so","son","sq","sv","sw","ta","te","tk","ur","yo"],nr:[1,2],fc:2},{lngs:["ay","bo","cgg","fa","ht","id","ja","jbo","ka","km","ko","ky","lo","ms","sah","su","th","tt","ug","vi","wo","zh"],nr:[1],fc:3},{lngs:["be","bs","cnr","dz","hr","ru","sr","uk"],nr:[1,2,5],fc:4},{lngs:["ar"],nr:[0,1,2,3,11,100],fc:5},{lngs:["cs","sk"],nr:[1,2,5],fc:6},{lngs:["csb","pl"],nr:[1,2,5],fc:7},{lngs:["cy"],nr:[1,2,3,8],fc:8},{lngs:["fr"],nr:[1,2],fc:9},{lngs:["ga"],nr:[1,2,3,7,11],fc:10},{lngs:["gd"],nr:[1,2,3,20],fc:11},{lngs:["is"],nr:[1,2],fc:12},{lngs:["jv"],nr:[0,1],fc:13},{lngs:["kw"],nr:[1,2,3,4],fc:14},{lngs:["lt"],nr:[1,2,10],fc:15},{lngs:["lv"],nr:[1,2,0],fc:16},{lngs:["mk"],nr:[1,2],fc:17},{lngs:["mnk"],nr:[0,1,2],fc:18},{lngs:["mt"],nr:[1,2,11,20],fc:19},{lngs:["or"],nr:[2,1],fc:2},{lngs:["ro"],nr:[1,2,20],fc:20},{lngs:["sl"],nr:[5,1,2,3],fc:21},{lngs:["he","iw"],nr:[1,2,20,21],fc:22}],H={1:function(e){return Number(1""+t+e)}getSuffixes(t){let r=1a[e]-a[t]).map(e=>""+this.options.prepend+(r.ordinal?"ordinal"+this.options.prepend:"")+e):e.numbers.map(e=>this.getSuffix(t,e,r)):[]}getSuffix(e,t){var r=2this.options.prepend&&r.toString()?this.options.prepend+r.toString():r.toString();return"v1"===this.options.compatibilityJSON?1===r?"":"number"==typeof r?"_plural_"+r.toString():n():"v2"===this.options.compatibilityJSON||this.options.simplifyPluralSuffix&&2===e.numbers.length&&1===e.numbers[0]?n():this.options.prepend&&t.toString()?this.options.prepend+t.toString():t.toString()}shouldUseIntlApi(){return!J.includes(this.options.compatibilityJSON)}},Y=class{constructor(){var e=0e),this.init(e)}init(){var e=0e&&e.source===t?(e.lastIndex=0,e):new RegExp(t,"g");this.regexp=e(this.regexp,this.prefix+"(.+?)"+this.suffix),this.regexpUnescape=e(this.regexpUnescape,""+this.prefix+this.unescapePrefix+"(.+?)"+this.unescapeSuffix+this.suffix),this.nestingRegexp=e(this.nestingRegexp,this.nestingPrefix+"(.+?)"+this.nestingSuffix)}interpolate(n,r,a,o){let s,i,l;const u=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{};function t(e){return e.replace(/\$/g,"$$$$")}const c=e=>{var t;return e.indexOf(this.formatSeparator)<0?(t=ge(r,u,e,this.options.keySeparator,this.options.ignoreJSONStructure),this.alwaysFormat?this.format(t,void 0,a,{...o,...r,interpolationkey:e}):t):(e=(t=e.split(this.formatSeparator)).shift().trim(),t=t.join(this.formatSeparator).trim(),this.format(ge(r,u,e,this.options.keySeparator,this.options.ignoreJSONStructure),t,a,{...o,...r,interpolationkey:e}))},f=(this.resetRegExp(),o&&o.missingInterpolationHandler||this.options.missingInterpolationHandler),h=(o&&o.interpolation&&void 0!==o.interpolation.skipOnVariables?o:this.options).interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:e=>t(e)},{regex:this.regexp,safeValue:e=>this.escapeValue?t(this.escape(e)):t(e)}].forEach(e=>{for(l=0;s=e.regex.exec(n);){var t=s[1].trim();if(void 0===(i=c(t)))if("function"==typeof f){var r=f(n,s,o);i="string"==typeof r?r:""}else{if(!o||!Object.prototype.hasOwnProperty.call(o,t)){if(h){i=s[0];continue}this.logger.warn(`missed to pass in variable ${t} for interpolating `+n)}i=""}else"string"==typeof i||this.useRawValueToEscape||(i=ie(i));r=e.safeValue(i);if(n=n.replace(s[0],r),h?(e.regex.lastIndex+=i.length,e.regex.lastIndex-=s[0].length):e.regex.lastIndex=0,++l>=this.maxReplaces)break}}),n}nest(r,n){let a=2e.trim()),o[1]=u.shift(),e=u,t=!0),(s=n(l.call(this,o[1].trim(),i),i))&&o[0]===r&&"string"!=typeof s)return s;(s="string"!=typeof s?ie(s):s)||(this.logger.warn(`missed to resolve ${o[1]} for nesting `+r),s=""),t&&(s=e.reduce((e,t)=>this.format(e,t,a.lng,{...a,interpolationkey:o[1].trim()}),s.trim())),r=r.replace(o[0],s),this.regexp.lastIndex=0}return r}},X=class{constructor(){var e=0{const r=new Intl.NumberFormat(e,{...t});return e=>r.format(e)}),currency:E((e,t)=>{const r=new Intl.NumberFormat(e,{...t,style:"currency"});return e=>r.format(e)}),datetime:E((e,t)=>{const r=new Intl.DateTimeFormat(e,{...t});return e=>r.format(e)}),relativetime:E((e,t)=>{const r=new Intl.RelativeTimeFormat(e,{...t});return e=>r.format(e,t.range||"day")}),list:E((e,t)=>{const r=new Intl.ListFormat(e,{...t});return e=>r.format(e)})},this.init(e)}init(e){var t=(1{var{formatName:r,formatOptions:n}=be(r);if(this.formats[r]){let e=t;try{var a=i&&i.formatParams&&i.formatParams[i.interpolationkey]||{},o=a.locale||a.lng||i.locale||i.lng||s;e=this.formats[r](t,o,{...n,...i,...a})}catch(e){this.logger.warn(e)}return e}return this.logger.warn("there was no format function for "+r),t},e)}},Z=class extends n{constructor(e,t,r){var n=3{let n=!0;t.forEach(e=>{var t=r+"|"+e;!a.reload&&this.store.hasResourceBundle(r,e)?this.state[t]=2:this.state[t]<0||(1===this.state[t]?void 0===s[t]&&(s[t]=!0):(this.state[t]=1,n=!1,void 0===s[t]&&(s[t]=!0),void 0===o[t]&&(o[t]=!0),void 0===l[e]&&(l[e]=!0)))}),n||(i[r]=!0)}),(Object.keys(o).length||Object.keys(s).length)&&this.queue.push({pending:s,pendingCount:Object.keys(s).length,loaded:{},errors:[],callback:r}),{toLoad:Object.keys(o),pending:Object.keys(s),toLoadLanguages:Object.keys(i),toLoadNamespaces:Object.keys(l)}}loaded(e,t,r){var n=e.split("|");const a=n[0],o=n[1],s=(t&&this.emit("failedLoading",a,o,t),r&&this.store.addResourceBundle(a,o,r,void 0,void 0,{skipCopy:!0}),this.state[e]=t?-1:2,{});this.queue.forEach(r=>{ce(r.loaded,[a],o),me(r,e),t&&r.errors.push(t),0!==r.pendingCount||r.done||(Object.keys(r.loaded).forEach(t=>{s[t]||(s[t]={});var e=r.loaded[t];e.length&&e.forEach(e=>{void 0===s[t][e]&&(s[t][e]=!0)})}),r.done=!0,r.errors.length?r.callback(r.errors):r.callback())}),this.emit("loaded",s),this.queue=this.queue.filter(e=>!e.done)}read(n,a,o){let s=3=this.maxParallelReads)this.waitingReads.push({lng:n,ns:a,fcName:o,tried:s,wait:i,callback:l});else{this.readingCalls++;const r=(e,t)=>{var r;this.readingCalls--,0{this.read.call(this,n,a,o,s+1,2*i,l)},i):l(e,t)};var e=this.backend[o].bind(this.backend);if(2!==e.length)return e(n,a,r);try{var t=e(n,a);t&&"function"==typeof t.then?t.then(e=>r(null,e)).catch(r):r(null,t)}catch(e){r(e)}}}prepareLoading(e,t){var r=2{this.loadOne(e)})}load(e,t,r){this.prepareLoading(e,t,{},r)}reload(e,t,r){this.prepareLoading(e,t,{reload:!0},r)}loadOne(r){let n=1{e&&this.logger.warn(`${n}loading namespace ${o} for language ${a} failed`,e),!e&&t&&this.logger.log(`${n}loaded namespace ${o} for language `+a,t),this.loaded(r,e,t)})}saveMissing(t,r,n,a,o){var s=5{};if(this.services.utils&&this.services.utils.hasLoadedNamespace&&!this.services.utils.hasLoadedNamespace(r))this.logger.warn(`did not save key "${n}" as the namespace "${r}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");else if(null!=n&&""!==n){if(this.backend&&this.backend.create){s={...s,isUpdate:o},o=this.backend.create.bind(this.backend);if(o.length<6)try{let e;(e=5===o.length?o(t,r,n,a,s):o(t,r,n,a))&&"function"==typeof e.then?e.then(e=>i(null,e)).catch(i):i(null,e)}catch(e){i(e)}else o(t,r,n,a,i,s)}t&&t[0]&&this.store.addResource(t[0],r,n,a)}}},s=class extends n{constructor(){let e=0{this.init(e,t)},0)}}init(){var a=this;let e=0{e.init&&e.init(this)})}this.format=this.options.interpolation.format,r=r||I,!this.options.fallbackLng||this.services.languageDetector||this.options.lng||0<(o=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng)).length&&"dev"!==o[0]&&(this.options.lng=o[0]),this.services.languageDetector||this.options.lng||this.logger.warn("init: no languageDetector is used and no lng is defined");["getResource","hasResourceBundle","getResourceBundle","getDataByLanguage"].forEach(e=>{this[e]=function(){return a.store[e](...arguments)}});["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(e=>{this[e]=function(){return a.store[e](...arguments),a}});const i=L();t=()=>{var e=(e,t)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn("init: i18next is already initialized. You should call init just once!"),this.isInitialized=!0,this.options.isClone||this.logger.log("initialized",this.options),this.emit("initialized",this.options),i.resolve(t),r(e,t)};if(this.languages&&"v1"!==this.options.compatibilityAPI&&!this.isInitialized)return e(null,this.t.bind(this));this.changeLanguage(this.options.lng,e)};return this.options.resources||!this.options.initImmediate?t():setTimeout(t,0),i}loadResources(e){let t=1{e&&"cimode"!==e&&this.services.languageUtils.toResolveHierarchy(e).forEach(e=>{"cimode"!==e&&n.indexOf(e)<0&&n.push(e)})};r?a(r):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(e=>a(e)),this.options.preload&&this.options.preload.forEach(e=>a(e)),this.services.backendConnector.load(n,this.options.ns,e=>{e||this.resolvedLanguage||!this.language||this.setResolvedLanguage(this.language),t(e)})}else t(null)}reloadResources(e,t,r){const n=L();return e=e||this.languages,t=t||this.options.ns,r=r||I,this.services.backendConnector.reload(e,t,e=>{n.resolve(),r(e)}),n}use(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(e.type)return"backend"===e.type&&(this.modules.backend=e),("logger"===e.type||e.log&&e.warn&&e.error)&&(this.modules.logger=e),"languageDetector"===e.type&&(this.modules.languageDetector=e),"i18nFormat"===e.type&&(this.modules.i18nFormat=e),"postProcessor"===e.type&&h.addPostProcessor(e),"formatter"===e.type&&(this.modules.formatter=e),"3rdParty"===e.type&&this.modules.external.push(e),this;throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()")}setResolvedLanguage(e){if(e&&this.languages&&!(-1<["cimode","dev"].indexOf(e)))for(let e=0;e{this.language=e,this.languages=this.services.languageUtils.toResolveHierarchy(e),this.resolvedLanguage=void 0,this.setResolvedLanguage(e)}),i=(e,t)=>{t?(s(t),this.translator.changeLanguage(t),this.isLanguageChangingTo=void 0,this.emit("languageChanged",t),this.logger.log("languageChanged",t)):this.isLanguageChangingTo=void 0,o.resolve(function(){return a.t(...arguments)}),n&&n(e,function(){return a.t(...arguments)})};var e=e=>{const t="string"==typeof(e=r||e||!this.services.languageDetector?e:[])?e:this.services.languageUtils.getBestMatchFromCodes(e);t&&(this.language||s(t),this.translator.language||this.translator.changeLanguage(t),this.services.languageDetector)&&this.services.languageDetector.cacheUserLanguage&&this.services.languageDetector.cacheUserLanguage(t),this.loadResources(t,e=>{i(e,t)})};return r||!this.services.languageDetector||this.services.languageDetector.async?!r&&this.services.languageDetector&&this.services.languageDetector.async?0===this.services.languageDetector.detect.length?this.services.languageDetector.detect().then(e):this.services.languageDetector.detect(e):e(r):e(this.services.languageDetector.detect()),o}getFixedT(e,t,l){var u=this;function c(e,t){let r;if("object"!=typeof t){for(var n=arguments.length,a=new Array(2""+r.keyPrefix+s+e):r.keyPrefix?""+r.keyPrefix+s+e:e,u.t(i,r)}return"string"==typeof e?c.lng=e:c.lngs=e,c.ns=t,c.keyPrefix=l,c}t(){return this.translator&&this.translator.translate(...arguments)}exists(){return this.translator&&this.translator.exists(...arguments)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e){var t=1{e=this.services.backendConnector.state[e+"|"+t];return-1===e||2===e};if(t.precheck){t=t.precheck(this,o);if(void 0!==t)return t}return!!this.hasResourceBundle(r,e)||!(this.services.backendConnector.backend&&(!this.options.resources||this.options.partialBundledLanguages)&&(!o(r,e)||n&&!o(a,e)))}loadNamespaces(e,t){const r=L();return this.options.ns?((e="string"==typeof e?[e]:e).forEach(e=>{this.options.ns.indexOf(e)<0&&this.options.ns.push(e)}),this.loadResources(e=>{r.resolve(),t&&t(e)}),r):(t&&t(),Promise.resolve())}loadLanguages(e,t){const r=L(),n=this.options.preload||[];e=(e="string"==typeof e?[e]:e).filter(e=>n.indexOf(e)<0&&this.services.languageUtils.isSupportedCode(e));return e.length?(this.options.preload=n.concat(e),this.loadResources(e=>{r.resolve(),t&&t(e)}),r):(t&&t(),Promise.resolve())}dir(e){var t;return!(e=e||this.resolvedLanguage||(this.languages&&0{a[e]=this[e]}),a.services={...this.services},a.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},r&&(a.store=new f(this.store.data,n),a.services.resourceStore=a.store),a.translator=new C(a.services,n),a.translator.on("*",function(e){for(var t=arguments.length,r=new Array(1{r=null!=e?i(F(e)):{};var n=!t&&e&&e.__esModule?r:l(r,"default",{value:e,enumerable:!0}),a=e,o=void 0,s=void 0;if(a&&"object"==typeof a||"function"==typeof a)for(let e of u(a))U.call(n,e)||e===o||l(n,e,{get:()=>a[e],enumerable:!(s=_(a,e))||s.enumerable});return n})(T()),v=(t,e)=>{t=localStorage.getItem(t);if(!t)return e;try{return JSON.parse(t)}catch(e){return t}},Q=e=>{if(3===e.length)e=e.split("").map(e=>e+e).join("");else{if(6!=e.length)throw"Only 3- or 6-digit hex colours are allowed.";if(e.match(/[^0-9a-f]/i))throw"Only hex colours are allowed."}e=e.match(/.{1,2}/g);if(e&&3===e.length)return[parseInt(e[0],16),parseInt(e[1],16),parseInt(e[2],16)];throw"Could not parse hex colour."},y=(e,t)=>{let r=[];return e&&0({name:e.name,url:oe(e.url)})):r.push({name:t,url:"https://github.com/"+t}),r},ee=(...e)=>{console.debug("Resetting Marketplace");const t=[];0===e.length&&Object.keys(localStorage).forEach(e=>{e.startsWith("marketplace:")&&t.push(e)}),e.forEach(e=>{switch(e){case"extensions":t.push(...v(g.installedExtensions,[])),t.push(g.installedExtensions);break;case"snippets":t.push(...v(g.installedSnippets,[])),t.push(g.installedSnippets);break;case"theme":t.push(...v(g.installedThemes,[])),t.push(g.installedThemes),t.push(g.themeInstalled);break;default:console.error("Unknown category: "+e)}}),t.forEach(e=>{localStorage.removeItem(e),console.debug("Removed "+e)}),console.debug("Marketplace has been reset"),location.reload()},te=()=>{const t={};return Object.keys(localStorage).forEach(e=>{e.startsWith("marketplace:")&&(t[e]=localStorage.getItem(e))}),t},w=r=>{var e=document.querySelector("style.marketplaceCSS.marketplaceScheme");if(e&&e.remove(),r){e=document.createElement("style");e.classList.add("marketplaceCSS"),e.classList.add("marketplaceScheme");let t=":root {";Object.keys(r).forEach(e=>{t=(t+=`--spice-${e}: #${r[e]};`)+`--spice-rgb-${e}: ${Q(r[e])};`}),t+="}",e.innerHTML=t,document.body.appendChild(e)}},re=async e=>{let t=v(g.albumArtBasedColorVibrancy);return t=t.replace(/([A-Z])/g,"_$1").toUpperCase(),(await Spicetify.colorExtractor(e))[t].substring(1)},ne=async(e,t)=>{var r=v(g.albumArtBasedColorMode).replace(/([A-Z])/g,"-$1").toLowerCase();return(await fetch(`https://www.thecolorapi.com/scheme?hex=${e}&mode=${r}&count=`+t).then(e=>e.json())).colors.map(e=>e.hex.value.substring(1))},ae=h=>{Spicetify.Player.addEventListener("songchange",async()=>{var t;t=1e3,await new Promise(e=>setTimeout(e,t));let r=Spicetify.Player.data?.item?.metadata?.image_xlarge_url;if(r=null==r?await new Promise(t=>{setInterval(()=>{var e=Spicetify.Player.data?.item?.metadata?.image_xlarge_url;e&&t(e)},50)}):r){var n,a,o=new Set(Object.values(h)).size,s=await re(r),i=await ne(s,o);let e=new Map;for([n,a]of Object.entries(h))e.has(a)?e.get(a).push(n):e.set(a,[n]);var l,s=new Map([...e.entries()].sort((e,t)=>{e=(0,m.default)(e[0]),t=(0,m.default)(t[0]);return e.get("lab.l")-t.get("lab.l")})),u={};for([,l]of(e=s).entries()){var c=i.shift();if(c)for(const f of l)u[f]=c}w(u)}})},k=e=>{e=new URL(e);return e.host,"raw.githubusercontent.com"===e.host},x=e=>{e=e.match(/https:\/\/raw\.githubusercontent\.com\/(?[^/]+)\/(?[^/]+)\/(?[^/]+)\/(?.+$)/);return{user:e?e.groups?.user:null,repo:e?e.groups?.repo:null,branch:e?e.groups?.branch:null,filePath:e?e.groups?.filePath:null}},oe=e=>{var t=decodeURI(e).trim().toLowerCase();return t.startsWith("javascript:")||t.startsWith("data:")||t.startsWith("vbscript:")?"about:blank":e},S=e=>{e&&(e=e.split("/").pop())&&-1===Spicetify.Config.extensions.indexOf(e)&&Spicetify.Config.extensions.push(e)},n=new Blob([` self.addEventListener('message', async (event) => { const url = event.data; const response = await fetch(url); const data = await response.json().catch(() => null); self.postMessage(data); }); -`],{type:"application/javascript"}),se=URL.createObjectURL(n),async function e(){if(Spicetify.LocalStorage&&Spicetify.showNotification){var t=document.createElement("script");t.innerHTML="const global = globalThis;",document.body.appendChild(t),console.log("Initializing Spicetify Marketplace v1.0.1"),window.Marketplace={reset:ee,export:te,version:"1.0.1"};const l=await xe();t=async t=>{t=v(t);if(t){if(console.debug("Initializing theme: ",t),t.schemes){var e=t.schemes[t.activeScheme];if(w(e),Spicetify.Config.color_scheme=t.activeScheme,"true"===localStorage.getItem(g.albumArtBasedColor))ae(e);else if("true"===localStorage.getItem(g.colorShift)){var r=t.schemes;let e=0;const i=Object.keys(r).length;setInterval(()=>{e%=i,w(Object.values(r)[e]),e++},6e4)}}else console.warn("No schemes found for theme");e=document.querySelector("link.marketplaceCSS"),e=(e&&e.remove(),await(async(e,t)=>{if(!e.cssURL)throw new Error("No CSS URL provided");t||=await xe();var t=k(e.cssURL)?`https://cdn.jsdelivr.${t}/gh/${e.user}/${e.repo}@${e.branch}/`+e.manifest.usercss:e.cssURL,r=t.replace("/user.css","/assets/");console.debug("Parsing CSS: ",t);let n=await fetch(t+"?time="+Date.now()).then(e=>e.text());for(const s of n.matchAll(/url\(['|"](?.+?)['|"]\)/gm)||[]){var a,o=s?.groups?.path;!o||o.startsWith("http")||o.startsWith("data")||(a=r+o.replace(/\.\//g,""),n=n.replace(o,a))}return n})(t,l));try{var n,a,o=document.querySelector("link[href='user.css']"),s=(o&&o.remove(),document.querySelector("style.marketplaceCSS.marketplaceUserCSS"));s&&s.remove(),e?((n=document.createElement("style")).classList.add("marketplaceCSS"),n.classList.add("marketplaceUserCSS"),n.innerHTML=e,document.body.appendChild(n)):((a=document.createElement("link")).setAttribute("rel","stylesheet"),a.setAttribute("href","user.css"),a.classList.add("userCSS"),document.body.appendChild(a))}catch(e){console.warn(e)}Spicetify.Config.current_theme=t.manifest?.name,t.include&&t.include.length&&t.include.forEach(e=>{var t=document.createElement("script");let r=e;if(k(e)){var{user:n,repo:a,branch:o,filePath:s}=x(e);if(!(n&&a&&o&&s))return;r=`https://cdn.jsdelivr.${l}/gh/${n}/${a}@${o}/`+s,s.endsWith(".mjs")&&(t.type="module")}t.src=r+"?time="+Date.now(),t.classList.add("marketplaceScript"),document.body.appendChild(t),S(e)})}else console.debug("No theme manifest found")};console.log("Loaded Marketplace extension");var r,n=v(g.installedSnippets,[]).map(e=>v(e));n=n,(r=document.querySelector("style.marketplaceSnippets"))&&r.remove(),r=document.createElement("style"),n=n.reduce((e,t)=>e=(e+=`/* ${t.title} - ${t.description} */ +`],{type:"application/javascript"}),se=URL.createObjectURL(n),async function e(){if(Spicetify.LocalStorage&&Spicetify.showNotification){var t=document.createElement("script");t.innerHTML="const global = globalThis;",document.body.appendChild(t),console.log("Initializing Spicetify Marketplace v1.0.2"),window.Marketplace={reset:ee,export:te,version:"1.0.2"};const l=await xe();t=async t=>{t=v(t);if(t){if(console.debug("Initializing theme: ",t),t.schemes){var e=t.schemes[t.activeScheme];if(w(e),Spicetify.Config.color_scheme=t.activeScheme,"true"===localStorage.getItem(g.albumArtBasedColor))ae(e);else if("true"===localStorage.getItem(g.colorShift)){var r=t.schemes;let e=0;const i=Object.keys(r).length;setInterval(()=>{e%=i,w(Object.values(r)[e]),e++},6e4)}}else console.warn("No schemes found for theme");e=document.querySelector("link.marketplaceCSS"),e=(e&&e.remove(),await(async(e,t)=>{if(!e.cssURL)throw new Error("No CSS URL provided");t||=await xe();var t=k(e.cssURL)?`https://cdn.jsdelivr.${t}/gh/${e.user}/${e.repo}@${e.branch}/`+e.manifest.usercss:e.cssURL,r=t.replace("/user.css","/assets/");console.debug("Parsing CSS: ",t);let n=await fetch(t+"?time="+Date.now()).then(e=>e.text());for(const s of n.matchAll(/url\(['|"](?.+?)['|"]\)/gm)||[]){var a,o=s?.groups?.path;!o||o.startsWith("http")||o.startsWith("data")||(a=r+o.replace(/\.\//g,""),n=n.replace(o,a))}return n})(t,l));try{var n,a,o=document.querySelector("link[href='user.css']"),s=(o&&o.remove(),document.querySelector("style.marketplaceCSS.marketplaceUserCSS"));s&&s.remove(),e?((n=document.createElement("style")).classList.add("marketplaceCSS"),n.classList.add("marketplaceUserCSS"),n.innerHTML=e,document.body.appendChild(n)):((a=document.createElement("link")).setAttribute("rel","stylesheet"),a.setAttribute("href","user.css"),a.classList.add("userCSS"),document.body.appendChild(a))}catch(e){console.warn(e)}Spicetify.Config.current_theme=t.manifest?.name,t.include&&t.include.length&&t.include.forEach(e=>{var t=document.createElement("script");let r=e;if(k(e)){var{user:n,repo:a,branch:o,filePath:s}=x(e);if(!(n&&a&&o&&s))return;r=`https://cdn.jsdelivr.${l}/gh/${n}/${a}@${o}/`+s,s.endsWith(".mjs")&&(t.type="module")}t.src=r+"?time="+Date.now(),t.classList.add("marketplaceScript"),document.body.appendChild(t),S(e)})}else console.debug("No theme manifest found")};console.log("Loaded Marketplace extension");var r,n=v(g.installedSnippets,[]).map(e=>v(e));n=n,(r=document.querySelector("style.marketplaceSnippets"))&&r.remove(),r=document.createElement("style"),n=n.reduce((e,t)=>e=(e+=`/* ${t.title} - ${t.description} */ `)+t.code+` `,""),r.innerHTML=n,r.classList.add("marketplaceSnippets"),document.body.appendChild(r),l?(window.sessionStorage.setItem("marketplace-request-tld",l),n=(v(g.installedExtensions,[]).forEach(e=>{if((e=v(e))&&e.extensionURL){console.debug("Initializing extension: ",e);var t=document.createElement("script");if(t.defer=!0,t.src=e.extensionURL,k(t.src)){var{user:r,repo:n,branch:a,filePath:o}=x(e.extensionURL);if(!(r&&n&&a&&o))return;t.src=`https://cdn.jsdelivr.${l}/gh/${r}/${n}@${a}/`+o,o.endsWith(".mjs")&&(t.type="module")}t.src=t.src+"?time="+Date.now(),document.body.appendChild(t),S(e.manifest?.main)}}),Spicetify.Config)["current_theme"],localStorage.setItem(g.localTheme,n),(r=localStorage.getItem(g.themeInstalled))&&("marketplace"!==n.toLocaleLowerCase()?Spicetify.showNotification(d("notifications.wrongLocalTheme"),!0,5e3):t(r))):window.navigator.onLine?(console.error(new Error("Unable to connect to the CDN, please check your Internet configuration.")),Spicetify.showNotification(d("notifications.noCdnConnection"),!0,5e3)):window.addEventListener("online",e,{once:!0})}else setTimeout(e,100)}(),async function(){console.debug("Preloading extensions and themes..."),window.sessionStorage.clear();var e=await(await fetch("https://raw.githubusercontent.com/spicetify/spicetify-marketplace/main/resources/blacklist.json").then(e=>e.json()).catch(()=>({}))).repos;window.sessionStorage.setItem("marketplace:blacklist",JSON.stringify(e)),await Promise.all([A("extension",0),A("theme",0),A("app",0)])}();function L(){let r,n;var e=new Promise((e,t)=>{r=e,n=t});return e.resolve=r,e.reject=n,e}function ie(e){return null==e?"":""+e}function le(e,t,r){e.forEach(e=>{t[e]&&(r[e]=t[e])})}function O(e,t,r){function n(e){return e&&-1"'\/]/g,e=>B[e]):e}function pe(e,t,r){t=t||"",r=r||"";var n=q.filter(e=>t.indexOf(e)<0&&r.indexOf(e)<0);if(0===n.length)return 1;var a,n=z.getRegExp(`(${n.map(e=>"?"===e?"\\?":e).join("|")})`);let o=!n.test(e);return o||0<(a=e.indexOf(r))&&!n.test(e.substring(0,a))&&(o=!0),o}function P(e,t,r){var o=2{t.lngs.forEach(e=>{r[e]={numbers:t.nr,plurals:H[t.fc]}})}),r}function ge(e,t,r,n,a){var o,s,i,l=3{var t;e&&([e,...t]=e.split(":"),t=t.join(":").trim().replace(/^'+|'+$/g,""),r[e.trim()]||(r[e.trim()]=t),"false"===t&&(r[e.trim()]=!1),"true"===t&&(r[e.trim()]=!0),isNaN(t)||(r[e.trim()]=parseInt(t,10)))})),{formatName:t,formatOptions:r}}function E(o){const s={};return function(e,t,r){var n=t+JSON.stringify(r);let a=s[n];return a||(a=o(j(t),r),s[n]=a),a(e)}}function me(e,t){void 0!==e.pending[t]&&(delete e.pending[t],e.pendingCount--)}function ve(){return{debug:!1,initImmediate:!0,ns:["translation"],defaultNS:["translation"],fallbackLng:["dev"],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:"all",preload:!1,simplifyPluralSuffix:!0,keySeparator:".",nsSeparator:":",pluralSeparator:"_",contextSeparator:"_",partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:"fallback",saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:function(e){let t={};if("object"==typeof e[1]&&(t=e[1]),"string"==typeof e[1]&&(t.defaultValue=e[1]),"string"==typeof e[2]&&(t.tDescription=e[2]),"object"==typeof e[2]||"object"==typeof e[3]){const r=e[3]||e[2];Object.keys(r).forEach(e=>{t[e]=r[e]})}return t},interpolation:{escapeValue:!0,format:e=>e,prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!0}}}function ye(e){return"string"==typeof e.ns&&(e.ns=[e.ns]),"string"==typeof e.fallbackLng&&(e.fallbackLng=[e.fallbackLng]),"string"==typeof e.fallbackNS&&(e.fallbackNS=[e.fallbackNS]),e.supportedLngs&&e.supportedLngs.indexOf("cimode")<0&&(e.supportedLngs=e.supportedLngs.concat(["cimode"])),e}function I(){}function we(t){Object.getOwnPropertyNames(Object.getPrototypeOf(t)).forEach(e=>{"function"==typeof t[e]&&(t[e]=t[e].bind(t))})}function ke(e,n){e&&e.forEach(e=>{var t=n||e.user+"-"+e.repo,r=window.sessionStorage.getItem(t),r=r?JSON.parse(r):[];r.push(e),window.sessionStorage.setItem(t,JSON.stringify(r))})}async function xe(){for(const e of["net","xyz"])try{if("opaqueredirect"===(await fetch("https://cdn.jsdelivr."+e,{redirect:"manual",cache:"no-cache"})).type)return e}catch(e){console.error(e);continue}}async function $(e,t,r){var n=e+"-"+t,a=window.sessionStorage.getItem(n),o=JSON.parse(window.sessionStorage.getItem("noManifests")||"[]");if(a)return JSON.parse(a);a=`https://raw.githubusercontent.com/${e}/${t}/${r}/manifest.json`;if(o.includes(a))return null;let s=await async function(e){const n=new Worker(se);return new Promise(t=>{const r=e=>{n.terminate(),t(e)};n.postMessage(e),n.addEventListener("message",e=>r(e.data),{once:!0}),n.addEventListener("error",()=>r(null),{once:!0})})}(a);return s?(ke(s=Array.isArray(s)?s:[s],n),s):ke([a],"noManifests")}async function A(e,t){var r=await async function(e,t=1){const r=window.sessionStorage.getItem("marketplace:blacklist");let n=`https://api.github.com/search/repositories?per_page=${b}&q=`+encodeURIComponent(`topic:spicetify-${e}s`);t&&(n+="&page="+t);var a=JSON.parse(window.sessionStorage.getItem(`spicetify-${e}s-page-`+t)||"null")||await fetch(n).then(e=>e.json()).catch(()=>null);return a?.items?(window.sessionStorage.setItem(`spicetify-${e}s-page-`+t,JSON.stringify(a)),{...a,page_count:a.items.length,items:a.items.filter(e=>!r?.includes(e.html_url))}):(Spicetify.showNotification(d("notifications.tooManyRequests"),!0,5e3),{items:[]})}(e,t),n=(!async function(e,t){for(const r of e.items)"theme"===t?await async function(e,n,a){try{var t=e.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/);if(!t||!t.groups)return;const{user:o,repo:s}=t.groups;return(await $(o,s,n)).reduce((e,t)=>{var r=t.branch||n,r={manifest:t,title:t.name,subtitle:t.description,authors:y(t.authors,o),user:o,repo:s,branch:r,imageURL:t.preview&&t.preview.startsWith("http")?t.preview:`https://raw.githubusercontent.com/${o}/${s}/${r}/`+t.preview,readmeURL:t.readme&&t.readme.startsWith("http")?t.readme:`https://raw.githubusercontent.com/${o}/${s}/${r}/`+t.readme,stars:a,tags:t.tags,cssURL:t.usercss.startsWith("http")?t.usercss:`https://raw.githubusercontent.com/${o}/${s}/${r}/`+t.usercss,schemesURL:t.schemes?t.schemes.startsWith("http")?t.schemes:`https://raw.githubusercontent.com/${o}/${s}/${r}/`+t.schemes:null,include:t.include};return t?.name&&t?.usercss&&t?.description&&e.push(r),e},[])}catch{return}}(r.contents_url,r.default_branch,r.stargazers_count):"extension"===t?await async function(e,n,a,o=!1){try{var t=e.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/);if(!t||!t.groups)return;const{user:s,repo:i}=t.groups;return(await $(s,i,n)).reduce((e,t)=>{var r=t.branch||n,r={manifest:t,title:t.name,subtitle:t.description,authors:y(t.authors,s),user:s,repo:i,branch:r,imageURL:t.preview&&t.preview.startsWith("http")?t.preview:`https://raw.githubusercontent.com/${s}/${i}/${r}/`+t.preview,extensionURL:t.main.startsWith("http")?t.main:`https://raw.githubusercontent.com/${s}/${i}/${r}/`+t.main,readmeURL:t.readme&&t.readme.startsWith("http")?t.readme:`https://raw.githubusercontent.com/${s}/${i}/${r}/`+t.readme,stars:a,tags:t.tags};return t&&t.name&&t.description&&t.main&&(o&&localStorage.getItem(`marketplace:installed:${s}/${i}/`+t.main)||e.push(r)),e},[])}catch{return}}(r.contents_url,r.default_branch,r.stargazers_count):"app"===t&&await async function(e,n,a){try{var t=e.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/);if(!t||!t.groups)return;const{user:o,repo:s}=t.groups;return(await $(o,s,n)).reduce((e,t)=>{var r=t.branch||n,r={manifest:t,title:t.name,subtitle:t.description,authors:y(t.authors,o),user:o,repo:s,branch:r,imageURL:t.preview&&t.preview.startsWith("http")?t.preview:`https://raw.githubusercontent.com/${o}/${s}/${r}/`+t.preview,readmeURL:t.readme&&t.readme.startsWith("http")?t.readme:`https://raw.githubusercontent.com/${o}/${s}/${r}/`+t.readme,stars:a,tags:t.tags};return t&&t.name&&t.description&&e.push(r),e},[])}catch{return}}(r.contents_url,r.default_branch,r.stargazers_count)}(r,e),b*t+r.page_count),a=(console.debug({pageOfRepos:r}),r.total_count-n);if(console.debug(`Parsed ${n}/${r.total_count} ${e}s`),0{var A,P=Object.create,_=Object.defineProperty,R=Object.getOwnPropertyDescriptor,M=Object.getOwnPropertyNames,j=Object.getPrototypeOf,$=Object.prototype.hasOwnProperty,e=(e,t)=>function(){return t||(0,e[M(e)[0]])((t={exports:{}}).exports,t),t.exports},D=(t,a,r,n)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let e of M(a))$.call(t,e)||e===r||_(t,e,{get:()=>a[e],enumerable:!(n=R(a,e))||n.enumerable});return t},t=(e,t,a)=>(a=null!=e?P(j(e)):{},D(!t&&e&&e.__esModule?a:_(a,"default",{value:e,enumerable:!0}),e)),b=e({"external-global-plugin:react"(e,t){t.exports=Spicetify.React}}),z=e({"node_modules/.pnpm/void-elements@3.1.0/node_modules/void-elements/index.js"(e,t){t.exports={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0}}}),J=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/constants.js"(e,t){var a=Number.MAX_SAFE_INTEGER||9007199254740991;t.exports={MAX_LENGTH:256,MAX_SAFE_COMPONENT_LENGTH:16,MAX_SAFE_BUILD_LENGTH:250,MAX_SAFE_INTEGER:a,RELEASE_TYPES:["major","premajor","minor","preminor","patch","prepatch","prerelease"],SEMVER_SPEC_VERSION:"2.0.0",FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}}}),U=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/debug.js"(e,t){var a="object"==typeof process&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...e)=>console.error("SEMVER",...e):()=>{};t.exports=a}}),V=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/re.js"(e,t){var{MAX_SAFE_COMPONENT_LENGTH:a,MAX_SAFE_BUILD_LENGTH:r,MAX_LENGTH:n}=J(),o=U(),i=(e=t.exports={}).re=[],s=e.safeRe=[],l=e.src=[],c=e.t={},u=0,t="[a-zA-Z0-9-]",d=[["\\s",1],["\\d",n],[t,r]],n=(e,t,a)=>{var r=(e=>{for(var[t,a]of d)e=e.split(t+"*").join(`${t}{0,${a}}`).split(t+"+").join(`${t}{1,${a}}`);return e})(t),n=u++;o(e,n,t),c[e]=n,l[n]=t,i[n]=new RegExp(t,a?"g":void 0),s[n]=new RegExp(r,a?"g":void 0)};n("NUMERICIDENTIFIER","0|[1-9]\\d*"),n("NUMERICIDENTIFIERLOOSE","\\d+"),n("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${t}*`),n("MAINVERSION",`(${l[c.NUMERICIDENTIFIER]})\\.(${l[c.NUMERICIDENTIFIER]})\\.(${l[c.NUMERICIDENTIFIER]})`),n("MAINVERSIONLOOSE",`(${l[c.NUMERICIDENTIFIERLOOSE]})\\.(${l[c.NUMERICIDENTIFIERLOOSE]})\\.(${l[c.NUMERICIDENTIFIERLOOSE]})`),n("PRERELEASEIDENTIFIER",`(?:${l[c.NUMERICIDENTIFIER]}|${l[c.NONNUMERICIDENTIFIER]})`),n("PRERELEASEIDENTIFIERLOOSE",`(?:${l[c.NUMERICIDENTIFIERLOOSE]}|${l[c.NONNUMERICIDENTIFIER]})`),n("PRERELEASE",`(?:-(${l[c.PRERELEASEIDENTIFIER]}(?:\\.${l[c.PRERELEASEIDENTIFIER]})*))`),n("PRERELEASELOOSE",`(?:-?(${l[c.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${l[c.PRERELEASEIDENTIFIERLOOSE]})*))`),n("BUILDIDENTIFIER",t+"+"),n("BUILD",`(?:\\+(${l[c.BUILDIDENTIFIER]}(?:\\.${l[c.BUILDIDENTIFIER]})*))`),n("FULLPLAIN",`v?${l[c.MAINVERSION]}${l[c.PRERELEASE]}?${l[c.BUILD]}?`),n("FULL",`^${l[c.FULLPLAIN]}$`),n("LOOSEPLAIN",`[v=\\s]*${l[c.MAINVERSIONLOOSE]}${l[c.PRERELEASELOOSE]}?${l[c.BUILD]}?`),n("LOOSE",`^${l[c.LOOSEPLAIN]}$`),n("GTLT","((?:<|>)?=?)"),n("XRANGEIDENTIFIERLOOSE",l[c.NUMERICIDENTIFIERLOOSE]+"|x|X|\\*"),n("XRANGEIDENTIFIER",l[c.NUMERICIDENTIFIER]+"|x|X|\\*"),n("XRANGEPLAIN",`[v=\\s]*(${l[c.XRANGEIDENTIFIER]})(?:\\.(${l[c.XRANGEIDENTIFIER]})(?:\\.(${l[c.XRANGEIDENTIFIER]})(?:${l[c.PRERELEASE]})?${l[c.BUILD]}?)?)?`),n("XRANGEPLAINLOOSE",`[v=\\s]*(${l[c.XRANGEIDENTIFIERLOOSE]})(?:\\.(${l[c.XRANGEIDENTIFIERLOOSE]})(?:\\.(${l[c.XRANGEIDENTIFIERLOOSE]})(?:${l[c.PRERELEASELOOSE]})?${l[c.BUILD]}?)?)?`),n("XRANGE",`^${l[c.GTLT]}\\s*${l[c.XRANGEPLAIN]}$`),n("XRANGELOOSE",`^${l[c.GTLT]}\\s*${l[c.XRANGEPLAINLOOSE]}$`),n("COERCEPLAIN",`(^|[^\\d])(\\d{1,${a}})(?:\\.(\\d{1,${a}}))?(?:\\.(\\d{1,${a}}))?`),n("COERCE",l[c.COERCEPLAIN]+"(?:$|[^\\d])"),n("COERCEFULL",l[c.COERCEPLAIN]+`(?:${l[c.PRERELEASE]})?(?:${l[c.BUILD]})?(?:$|[^\\d])`),n("COERCERTL",l[c.COERCE],!0),n("COERCERTLFULL",l[c.COERCEFULL],!0),n("LONETILDE","(?:~>?)"),n("TILDETRIM",`(\\s*)${l[c.LONETILDE]}\\s+`,!0),e.tildeTrimReplace="$1~",n("TILDE",`^${l[c.LONETILDE]}${l[c.XRANGEPLAIN]}$`),n("TILDELOOSE",`^${l[c.LONETILDE]}${l[c.XRANGEPLAINLOOSE]}$`),n("LONECARET","(?:\\^)"),n("CARETTRIM",`(\\s*)${l[c.LONECARET]}\\s+`,!0),e.caretTrimReplace="$1^",n("CARET",`^${l[c.LONECARET]}${l[c.XRANGEPLAIN]}$`),n("CARETLOOSE",`^${l[c.LONECARET]}${l[c.XRANGEPLAINLOOSE]}$`),n("COMPARATORLOOSE",`^${l[c.GTLT]}\\s*(${l[c.LOOSEPLAIN]})$|^$`),n("COMPARATOR",`^${l[c.GTLT]}\\s*(${l[c.FULLPLAIN]})$|^$`),n("COMPARATORTRIM",`(\\s*)${l[c.GTLT]}\\s*(${l[c.LOOSEPLAIN]}|${l[c.XRANGEPLAIN]})`,!0),e.comparatorTrimReplace="$1$2$3",n("HYPHENRANGE",`^\\s*(${l[c.XRANGEPLAIN]})\\s+-\\s+(${l[c.XRANGEPLAIN]})\\s*$`),n("HYPHENRANGELOOSE",`^\\s*(${l[c.XRANGEPLAINLOOSE]})\\s+-\\s+(${l[c.XRANGEPLAINLOOSE]})\\s*$`),n("STAR","(<|>)?=?\\s*\\*"),n("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$"),n("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")}}),F=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/parse-options.js"(e,t){var a=Object.freeze({loose:!0}),r=Object.freeze({});t.exports=e=>e?"object"!=typeof e?a:e:r}}),W=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/identifiers.js"(e,t){var n=/^[0-9]+$/,a=(e,t)=>{var a=n.test(e),r=n.test(t);return a&&r&&(e=+e,t=+t),e===t?0:a&&!r||(!r||a)&&ea(t,e)}}}),H=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/classes/semver.js"(e,t){var n=U(),{MAX_LENGTH:a,MAX_SAFE_INTEGER:r}=J(),{safeRe:o,t:i}=V(),s=F(),l=W()["compareIdentifiers"],c=class{constructor(e,t){if(t=s(t),e instanceof c){if(e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease)return e;e=e.version}else if("string"!=typeof e)throw new TypeError(`Invalid version. Must be a string. Got type "${typeof e}".`);if(e.length>a)throw new TypeError(`version is longer than ${a} characters`);n("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;t=e.trim().match(t.loose?o[i.LOOSE]:o[i.FULL]);if(!t)throw new TypeError("Invalid Version: "+e);if(this.raw=e,this.major=+t[1],this.minor=+t[2],this.patch=+t[3],this.major>r||this.major<0)throw new TypeError("Invalid major version");if(this.minor>r||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>r||this.patch<0)throw new TypeError("Invalid patch version");t[4]?this.prerelease=t[4].split(".").map(e=>{if(/^[0-9]+$/.test(e)){var t=+e;if(0<=t&&t{if(e instanceof r)return e;try{return new r(e,t)}catch(e){if(a)throw e;return null}}}}),X=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/valid.js"(e,t){var a=q();t.exports=(e,t)=>{e=a(e,t);return e?e.version:null}}}),Z=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/clean.js"(e,t){var a=q();t.exports=(e,t)=>{e=a(e.trim().replace(/^[=v]+/,""),t);return e?e.version:null}}}),Y=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/inc.js"(e,t){var o=H();t.exports=(e,t,a,r,n)=>{"string"==typeof a&&(n=r,r=a,a=void 0);try{return new o(e instanceof o?e.version:e,a).inc(t,r,n).version}catch(e){return null}}}}),Q=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/diff.js"(e,t){var o=q();t.exports=(e,t)=>{var a,r,e=o(e,null,!0),t=o(t,null,!0),n=e.compare(t);return 0===n?null:(r=!!(a=(n=0new a(e,t).major}}),te=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/minor.js"(e,t){var a=H();t.exports=(e,t)=>new a(e,t).minor}}),ae=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/patch.js"(e,t){var a=H();t.exports=(e,t)=>new a(e,t).patch}}),re=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/prerelease.js"(e,t){var a=q();t.exports=(e,t)=>{e=a(e,t);return e&&e.prerelease.length?e.prerelease:null}}}),G=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/compare.js"(e,t){var r=H();t.exports=(e,t,a)=>new r(e,a).compare(new r(t,a))}}),ne=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/rcompare.js"(e,t){var r=G();t.exports=(e,t,a)=>r(t,e,a)}}),oe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/compare-loose.js"(e,t){var a=G();t.exports=(e,t)=>a(e,t,!0)}}),ie=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/compare-build.js"(e,t){var r=H();t.exports=(e,t,a)=>{e=new r(e,a),t=new r(t,a);return e.compare(t)||e.compareBuild(t)}}}),se=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/sort.js"(e,t){var r=ie();t.exports=(e,a)=>e.sort((e,t)=>r(e,t,a))}}),le=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/rsort.js"(e,t){var r=ie();t.exports=(e,a)=>e.sort((e,t)=>r(t,e,a))}}),ce=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/gt.js"(e,t){var r=G();t.exports=(e,t,a)=>0r(e,t,a)<0}}),de=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/eq.js"(e,t){var r=G();t.exports=(e,t,a)=>0===r(e,t,a)}}),pe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/neq.js"(e,t){var r=G();t.exports=(e,t,a)=>0!==r(e,t,a)}}),he=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/gte.js"(e,t){var r=G();t.exports=(e,t,a)=>0<=r(e,t,a)}}),me=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/lte.js"(e,t){var r=G();t.exports=(e,t,a)=>r(e,t,a)<=0}}),fe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/cmp.js"(e,t){var n=de(),o=pe(),i=ce(),s=he(),l=ue(),c=me();t.exports=(e,t,a,r)=>{switch(t){case"===":return(e="object"==typeof e?e.version:e)===(a="object"==typeof a?a.version:a);case"!==":return(e="object"==typeof e?e.version:e)!==(a="object"==typeof a?a.version:a);case"":case"=":case"==":return n(e,a,r);case"!=":return o(e,a,r);case">":return i(e,a,r);case">=":return s(e,a,r);case"<":return l(e,a,r);case"<=":return c(e,a,r);default:throw new TypeError("Invalid operator: "+t)}}}}),ge=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/coerce.js"(e,t){var u=H(),d=q(),{safeRe:p,t:h}=V();t.exports=(e,t)=>{if(e instanceof u)return e;if("string"!=typeof(e="number"==typeof e?String(e):e))return null;let a=null;if((t=t||{}).rtl){for(var r,n=t.includePrerelease?p[h.COERCERTLFULL]:p[h.COERCERTL];(r=n.exec(e))&&(!a||a.index+a[0].length!==e.length);)a&&r.index+r[0].length===a.index+a[0].length||(a=r),n.lastIndex=r.index+r[1].length+r[2].length;n.lastIndex=-1}else a=e.match(t.includePrerelease?p[h.COERCEFULL]:p[h.COERCE]);var o,i,s,l,c;return null===a?null:(o=a[2],i=a[3]||"0",s=a[4]||"0",l=t.includePrerelease&&a[5]?"-"+a[5]:"",c=t.includePrerelease&&a[6]?"+"+a[6]:"",d(o+`.${i}.`+s+l+c,t))}}}),B=e({"node_modules/.pnpm/yallist@4.0.0/node_modules/yallist/iterator.js"(e,t){"use strict";t.exports=function(e){e.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}}}),ve=e({"node_modules/.pnpm/yallist@4.0.0/node_modules/yallist/yallist.js"(e,t){"use strict";function o(e){var t=this;if((t=t instanceof o?t:new o).tail=null,t.head=null,t.length=0,e&&"function"==typeof e.forEach)e.forEach(function(e){t.push(e)});else if(0this.length&&(t=this.length);for(var r=0,n=this.head;null!==n&&rthis.length&&(t=this.length);for(var r=this.length,n=this.tail;null!==n&&tthis.length?this.length-1:e)<0&&(e=this.length+e);for(var r=0,n=this.head;null!==n&&r1,m=(e,t,a)=>{t=e[h].get(t);if(t){var r=t.value;if(f(e,r)){if(v(e,t),!e[o])return}else a&&(e[n]&&(t.value.now=Date.now()),e[p].unshiftNode(t));return r.value}},f=(e,t)=>{var a;return!(!t||!t.maxAge&&!e[c])&&(a=Date.now()-t.now,t.maxAge?a>t.maxAge:e[c]&&a>e[c])},g=t=>{if(t[s]>t[i])for(let e=t[p].tail;t[s]>t[i]&&null!==e;){var a=e.prev;v(t,e),e=a}},v=(e,t)=>{var a;t&&(a=t.value,e[u]&&e[u](a.key,a.value),e[s]-=a.length,e[h].delete(a.key),e[p].removeNode(t))},b=class{constructor(e,t,a,r,n){this.key=e,this.value=t,this.length=a,this.now=r,this.maxAge=n||0}},y=(e,t,a,r)=>{let n=a.value;f(e,n)&&(v(e,a),e[o]||(n=void 0)),n&&t.call(r,n.value,n.key,e)};t.exports=class{constructor(e){if((e=(e="number"==typeof e?{max:e}:e)||{}).max&&("number"!=typeof e.max||e.max<0))throw new TypeError("max must be a non-negative number");this[i]=e.max||1/0;var t=e.length||r;if(this[l]="function"!=typeof t?r:t,this[o]=e.stale||!1,e.maxAge&&"number"!=typeof e.maxAge)throw new TypeError("maxAge must be a number");this[c]=e.maxAge||0,this[u]=e.dispose,this[d]=e.noDisposeOnSet||!1,this[n]=e.updateAgeOnGet||!1,this.reset()}set max(e){if("number"!=typeof e||e<0)throw new TypeError("max must be a non-negative number");this[i]=e||1/0,g(this)}get max(){return this[i]}set allowStale(e){this[o]=!!e}get allowStale(){return this[o]}set maxAge(e){if("number"!=typeof e)throw new TypeError("maxAge must be a non-negative number");this[c]=e,g(this)}get maxAge(){return this[c]}set lengthCalculator(e){(e="function"!=typeof e?r:e)!==this[l]&&(this[l]=e,this[s]=0,this[p].forEach(e=>{e.length=this[l](e.value,e.key),this[s]+=e.length})),g(this)}get lengthCalculator(){return this[l]}get length(){return this[s]}get itemCount(){return this[p].length}rforEach(t,a){a=a||this;for(let e=this[p].tail;null!==e;){var r=e.prev;y(this,t,e,a),e=r}}forEach(t,a){a=a||this;for(let e=this[p].head;null!==e;){var r=e.next;y(this,t,e,a),e=r}}keys(){return this[p].toArray().map(e=>e.key)}values(){return this[p].toArray().map(e=>e.value)}reset(){this[u]&&this[p]&&this[p].length&&this[p].forEach(e=>this[u](e.key,e.value)),this[h]=new Map,this[p]=new a,this[s]=0}dump(){return this[p].map(e=>!f(this,e)&&{k:e.key,v:e.value,e:e.now+(e.maxAge||0)}).toArray().filter(e=>e)}dumpLru(){return this[p]}set(e,t,a){if((a=a||this[c])&&"number"!=typeof a)throw new TypeError("maxAge must be a number");var r,n=a?Date.now():0,o=this[l](t,e);return this[h].has(e)?o>this[i]?(v(this,this[h].get(e)),!1):(r=this[h].get(e).value,this[u]&&!this[d]&&this[u](e,r.value),r.now=n,r.maxAge=a,r.value=t,this[s]+=o-r.length,r.length=o,this.get(e),g(this),!0):(r=new b(e,t,o,n,a)).length>this[i]?(this[u]&&this[u](e,t),!1):(this[s]+=r.length,this[p].unshift(r),this[h].set(e,this[p].head),g(this),!0)}has(e){return!!this[h].has(e)&&(e=this[h].get(e).value,!f(this,e))}get(e){return m(this,e,!0)}peek(e){return m(this,e,!1)}pop(){var e=this[p].tail;return e?(v(this,e),e.value):null}del(e){v(this,this[h].get(e))}load(t){this.reset();var a=Date.now();for(let e=t.length-1;0<=e;e--){var r=t[e],n=r.e||0;0===n?this.set(r.k,r.v):0<(n=n-a)&&this.set(r.k,r.v,n)}}prune(){this[h].forEach((e,t)=>m(this,t,!1))}}}}),K=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/classes/range.js"(e,t){var r=class{constructor(e,t){if(t=n(t),e instanceof r)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new r(e.raw,t);if(e instanceof l)return this.raw=e.value,this.set=[[e]],this.format(),this;if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e.trim().split(/\s+/).join(" "),this.set=this.raw.split("||").map(e=>this.parseRange(e.trim())).filter(e=>e.length),!this.set.length)throw new TypeError("Invalid SemVer Range: "+this.raw);if(1!v(e[0])),0===this.set.length)this.set=[t];else if(1e.join(" ").trim()).join("||").trim(),this.range}toString(){return this.range}parseRange(e){var t=((this.options.includePrerelease&&f)|(this.options.loose&&g))+":"+e,a=s.get(t);if(a)return a;var a=this.options.loose,r=a?p[h.HYPHENRANGELOOSE]:p[h.HYPHENRANGE];e=e.replace(r,L(this.options.includePrerelease)),d("hyphen replace",e),e=e.replace(p[h.COMPARATORTRIM],c),d("comparator trim",e),e=e.replace(p[h.TILDETRIM],u),d("tilde trim",e),e=e.replace(p[h.CARETTRIM],m),d("caret trim",e);let n=e.split(" ").map(e=>b(e,this.options)).join(" ").split(/\s+/).map(e=>I(e,this.options));a&&(n=n.filter(e=>(d("loose invalid filter",e,this.options),!!e.match(p[h.COMPARATORLOOSE])))),d("range list",n);var o=new Map;for(const i of n.map(e=>new l(e,this.options))){if(v(i))return[i];o.set(i.value,i)}1i(t,a)&&e.set.some(e=>i(e,a)&&t.every(t=>e.every(e=>t.intersects(e,a)))));throw new TypeError("a Range is required")}test(t){if(t){if("string"==typeof t)try{t=new a(t,this.options)}catch(e){return!1}for(let e=0;e"<0.0.0-0"===e.value,o=e=>""===e.value,i=(e,t)=>{let a=!0;var r=e.slice();let n=r.pop();for(;a&&r.length;)a=r.every(e=>n.intersects(e,t)),n=r.pop();return a},b=(e,t)=>(d("comp",e,t),e=w(e,t),d("caret",e),e=S(e,t),d("tildes",e),e=C(e,t),d("xrange",e),e=x(e,t),d("stars",e),e),y=e=>!e||"x"===e.toLowerCase()||"*"===e,S=(e,t)=>e.trim().split(/\s+/).map(e=>k(e,t)).join(" "),k=(i,e)=>{e=e.loose?p[h.TILDELOOSE]:p[h.TILDE];return i.replace(e,(e,t,a,r,n)=>{d("tilde",i,e,t,a,r,n);let o;return o=y(t)?"":y(a)?`>=${t}.0.0 <${+t+1}.0.0-0`:y(r)?`>=${t}.${a}.0 <${t}.${+a+1}.0-0`:n?(d("replaceTilde pr",n),`>=${t}.${a}.${r}-${n} <${t}.${+a+1}.0-0`):`>=${t}.${a}.${r} <${t}.${+a+1}.0-0`,d("tilde return",o),o})},w=(e,t)=>e.trim().split(/\s+/).map(e=>E(e,t)).join(" "),E=(i,e)=>{d("caret",i,e);var t=e.loose?p[h.CARETLOOSE]:p[h.CARET];const s=e.includePrerelease?"-0":"";return i.replace(t,(e,t,a,r,n)=>{d("caret",i,e,t,a,r,n);let o;return o=y(t)?"":y(a)?`>=${t}.0.0${s} <${+t+1}.0.0-0`:y(r)?"0"===t?`>=${t}.${a}.0${s} <${t}.${+a+1}.0-0`:`>=${t}.${a}.0${s} <${+t+1}.0.0-0`:n?(d("replaceCaret pr",n),"0"===t?"0"===a?`>=${t}.${a}.${r}-${n} <${t}.${a}.${+r+1}-0`:`>=${t}.${a}.${r}-${n} <${t}.${+a+1}.0-0`:`>=${t}.${a}.${r}-${n} <${+t+1}.0.0-0`):(d("no pr"),"0"===t?"0"===a?`>=${t}.${a}.${r}${s} <${t}.${a}.${+r+1}-0`:`>=${t}.${a}.${r}${s} <${t}.${+a+1}.0-0`:`>=${t}.${a}.${r} <${+t+1}.0.0-0`),d("caret return",o),o})},C=(e,t)=>(d("replaceXRanges",e,t),e.split(/\s+/).map(e=>N(e,t)).join(" ")),N=(c,u)=>{c=c.trim();var e=u.loose?p[h.XRANGELOOSE]:p[h.XRANGE];return c.replace(e,(e,t,a,r,n,o)=>{d("xRange",c,e,t,a,r,n,o);var i=y(a),s=i||y(r),l=s||y(n);return"="===t&&l&&(t=""),o=u.includePrerelease?"-0":"",i?e=">"===t||"<"===t?"<0.0.0-0":"*":t&&l?(s&&(r=0),n=0,">"===t?(t=">=",n=s?(a=+a+1,r=0):(r=+r+1,0)):"<="===t&&(t="<",s?a=+a+1:r=+r+1),e=t+a+`.${r}.`+n+(o="<"===t?"-0":o)):s?e=`>=${a}.0.0${o} <${+a+1}.0.0-0`:l&&(e=`>=${a}.${r}.0${o} <${a}.${+r+1}.0-0`),d("xRange return",e),e})},x=(e,t)=>(d("replaceStars",e,t),e.trim().replace(p[h.STAR],"")),I=(e,t)=>(d("replaceGTE0",e,t),e.trim().replace(p[t.includePrerelease?h.GTE0PRE:h.GTE0],"")),L=h=>(e,t,a,r,n,o,i,s,l,c,u,d,p)=>((t=y(a)?"":y(r)?`>=${a}.0.0`+(h?"-0":""):y(n)?`>=${a}.${r}.0`+(h?"-0":""):o?">="+t:">="+t+(h?"-0":""))+" "+(s=y(l)?"":y(c)?`<${+l+1}.0.0-0`:y(u)?`<${l}.${+c+1}.0-0`:d?`<=${l}.${c}.${u}-`+d:h?`<${l}.${c}.${+u+1}-0`:"<="+s)).trim(),O=(t,a,e)=>{for(let e=0;e")||!e.operator.startsWith(">"))&&!(this.operator.startsWith("<")&&e.operator.startsWith("<")||this.semver.version===e.semver.version&&this.operator.includes("=")&&e.operator.includes("=")||s(this.semver,"<",e.semver,t)&&this.operator.startsWith(">")&&e.operator.startsWith("<")||s(this.semver,">",e.semver,t)&&this.operator.startsWith("<")&&e.operator.startsWith(">")));throw new TypeError("a Comparator is required")}},n=(t.exports=r,F()),{safeRe:o,t:i}=V(),s=fe(),l=U(),c=H(),u=K()}}),Se=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/satisfies.js"(e,t){var r=K();t.exports=(e,t,a)=>{try{t=new r(t,a)}catch(e){return!1}return t.test(e)}}}),ke=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/to-comparators.js"(e,t){var a=K();t.exports=(e,t)=>new a(e,t).set.map(e=>e.map(e=>e.value).join(" ").trim().split(" "))}}),we=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/max-satisfying.js"(e,t){var i=H(),s=K();t.exports=(e,t,a)=>{let r=null,n=null,o=null;try{o=new s(t,a)}catch(e){return null}return e.forEach(e=>{!o.test(e)||r&&-1!==n.compare(e)||(r=e,n=new i(r,a))}),r}}}),Ee=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/min-satisfying.js"(e,t){var i=H(),s=K();t.exports=(e,t,a)=>{let r=null,n=null,o=null;try{o=new s(t,a)}catch(e){return null}return e.forEach(e=>{!o.test(e)||r&&1!==n.compare(e)||(r=e,n=new i(r,a))}),r}}}),Ce=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/min-version.js"(e,t){var o=H(),a=K(),i=ce();t.exports=(t,e)=>{t=new a(t,e);let r=new o("0.0.0");if(t.test(r))return r;if(r=new o("0.0.0-0"),t.test(r))return r;r=null;for(let e=0;e{var t=new o(e.semver.version);switch(e.operator){case">":0===t.prerelease.length?t.patch++:t.prerelease.push(0),t.raw=t.format();case"":case">=":a&&!i(t,a)||(a=t);break;case"<":case"<=":break;default:throw new Error("Unexpected operation: "+e.operator)}}),!a||r&&!i(r,a)||(r=a)}return r&&t.test(r)?r:null}}}),Ne=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/valid.js"(e,t){var a=K();t.exports=(e,t)=>{try{return new a(e,t).range||"*"}catch(e){return null}}}}),xe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/outside.js"(e,t){var a=H(),p=ye(),h=p["ANY"],m=K(),f=Se(),g=ce(),v=ue(),b=me(),y=he();t.exports=(r,n,e,o)=>{r=new a(r,o),n=new m(n,o);let i,s,l,c,u;switch(e){case">":i=g,s=b,l=v,c=">",u=">=";break;case"<":i=v,s=y,l=g,c="<",u="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(f(r,n,o))return!1;for(let e=0;e{e.semver===h&&(e=new p(">=0.0.0")),t=t||e,a=a||e,i(e.semver,t.semver,o)?t=e:l(e.semver,a.semver,o)&&(a=e)}),t.operator===c||t.operator===u)return!1;if((!a.operator||a.operator===c)&&s(r,a.semver))return!1;if(a.operator===u&&l(r,a.semver))return!1}return!0}}}),Ie=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/gtr.js"(e,t){var r=xe();t.exports=(e,t,a)=>r(e,t,">",a)}}),Le=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/ltr.js"(e,t){var r=xe();t.exports=(e,t,a)=>r(e,t,"<",a)}}),Oe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/intersects.js"(e,t){var r=K();t.exports=(e,t,a)=>(e=new r(e,a),t=new r(t,a),e.intersects(t,a))}}),Te=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/simplify.js"(e,t){var h=Se(),m=G();t.exports=(e,t,a)=>{var r=[];let n=null,o=null;var i=e.sort((e,t)=>m(e,t,a));for(const p of i){var s=h(p,t,a);n=s?(o=p,n||p):(o&&r.push([n,o]),o=null)}n&&r.push([n,null]);var l,c,u=[];for([l,c]of r)l===c?u.push(l):c||l!==i[0]?c?l===i[0]?u.push("<="+c):u.push(l+" - "+c):u.push(">="+l):u.push("*");var e=u.join(" || "),d="string"==typeof t.raw?t.raw:String(t);return e.length=0.0.0-0")],k=[new a(">=0.0.0")],w=(e,t,a)=>{return!e||!(0<(a=y(e.semver,t.semver,a)))&&(a<0||">"===t.operator&&">="===e.operator)?t:e},E=(e,t,a)=>{return!e||!((a=y(e.semver,t.semver,a))<0)&&(0{if(t!==a){t=new s(t,r),a=new s(a,r);let e=!1;e:for(const o of t.set){for(const i of a.set){var n=((s,l,c)=>{if(s!==l){if(1===s.length&&s[0].semver===v){if(1===l.length&&l[0].semver===v)return!0;s=c.includePrerelease?S:k}if(1===l.length&&l[0].semver===v){if(c.includePrerelease)return!0;l=k}var u=new Set,d,p;let e,t;for(const h of s)">"===h.operator||">="===h.operator?e=w(e,h,c):"<"===h.operator||"<="===h.operator?t=E(t,h,c):u.add(h.semver);if(1="!==e.operator||"<="!==t.operator))return null}for(const m of u){if(e&&!b(m,String(e),c))return null;if(t&&!b(m,String(t),c))return null;for(const f of l)if(!b(m,String(f),c))return!1;return!0}let r,n,o=!(!t||c.includePrerelease||!t.semver.prerelease.length)&&t.semver,i=!(!e||c.includePrerelease||!e.semver.prerelease.length)&&e.semver;o&&1===o.prerelease.length&&"<"===t.operator&&0===o.prerelease[0]&&(o=!1);for(const g of l){if(n=n||">"===g.operator||">="===g.operator,r=r||"<"===g.operator||"<="===g.operator,e)if(i&&g.semver.prerelease&&g.semver.prerelease.length&&g.semver.major===i.major&&g.semver.minor===i.minor&&g.semver.patch===i.patch&&(i=!1),">"===g.operator||">="===g.operator){if((d=w(e,g,c))===g&&d!==e)return!1}else if(">="===e.operator&&!b(e.semver,String(g),c))return!1;if(t)if(o&&g.semver.prerelease&&g.semver.prerelease.length&&g.semver.major===o.major&&g.semver.minor===o.minor&&g.semver.patch===o.patch&&(o=!1),"<"===g.operator||"<="===g.operator){if((p=E(t,g,c))===g&&p!==t)return!1}else if("<="===t.operator&&!b(t.semver,String(g),c))return!1;if(!g.operator&&(t||e)&&0!==a)return!1}if(e&&r&&!t&&0!==a)return!1;if(t&&n&&!e&&0!==a)return!1;if(i||o)return!1}return true})(o,i,r);if(e=e||null!==n,n)continue e}if(e)return!1}}return!0}}}),a=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/index.js"(j,e){var t=V(),a=J(),r=H(),n=W(),o=q(),i=X(),s=Z(),l=Y(),c=Q(),u=ee(),d=te(),p=ae(),h=re(),m=G(),f=ne(),g=oe(),v=ie(),b=se(),y=le(),S=ce(),k=ue(),w=de(),E=pe(),C=he(),N=me(),x=fe(),I=ge(),L=ye(),O=K(),T=Se(),A=ke(),P=we(),_=Ee(),R=Ce(),M=Ne(),$=xe(),D=Ie(),z=Le(),U=Oe(),F=Te(),B=Ae();e.exports={parse:o,valid:i,clean:s,inc:l,diff:c,major:u,minor:d,patch:p,prerelease:h,compare:m,rcompare:f,compareLoose:g,compareBuild:v,sort:b,rsort:y,gt:S,lt:k,eq:w,neq:E,gte:C,lte:N,cmp:x,coerce:I,Comparator:L,Range:O,satisfies:T,toComparators:A,maxSatisfying:P,minSatisfying:_,minVersion:R,validRange:M,outside:$,gtr:D,ltr:z,intersects:U,simplifyRange:F,subset:B,SemVer:r,re:t.re,src:t.src,tokens:t.t,SEMVER_SPEC_VERSION:a.SEMVER_SPEC_VERSION,RELEASE_TYPES:a.RELEASE_TYPES,compareIdentifiers:n.compareIdentifiers,rcompareIdentifiers:n.rcompareIdentifiers}}}),Pe=e({"node_modules/.pnpm/chroma-js@2.4.2/node_modules/chroma-js/chroma.js"(e,t){var a;a=function(){"use strict";for(var e=function(e,t,a){return void 0===a&&(a=1),e<(t=void 0===t?0:t)?t:a>16,t>>8&255,255&t,1];if(e.match(tt))return 4===(e=5!==e.length&&9!==e.length?e:e.substr(1)).length&&(e=(e=e.split(""))[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]),[(t=parseInt(e,16))>>24&255,t>>16&255,t>>8&255,Math.round((255&t)/255*100)/100];throw new Error("unknown hex color: "+e)}function xe(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a,r,n,o=(e=ut(e,"hsi"))[0],i=e[1],s=e[2];return isNaN(o)&&(o=0),isNaN(i)&&(i=0),360f.t1?e*e*e:f.t2*(e-f.t0)}function Ae(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a=(e=Rt(e,"lab"))[0],r=e[1],n=e[2],a=(a+16)/116,r=isNaN(r)?a:a+r/500,n=isNaN(n)?a:a-n/200;return a=f.Yn*Te(a),r=f.Xn*Te(r),n=f.Zn*Te(n),[Oe(3.2404542*r-1.5371385*a-.4985314*n),Oe(-.969266*r+1.8760108*a+.041556*n),Oe(.0556434*r-.2040259*a+1.0572252*n),3>16,e>>8&255,255&e,1];throw new Error("unknown num color: "+e)}function $e(e){var t,a,r=(e=e/100)<66?(t=255,a=e<6?0:-155.25485562709179-.44596950469579133*(a=e-2)+104.49216199393888*S(a),e<20?0:.8274096064007395*(r=e-10)-254.76935184120902+115.67994401066147*S(r)):(t=351.97690566805693+.114206453784165*(t=e-55)-40.25366309332127*S(t),a=325.4494125711974+.07943456536662342*(a=e-50)-28.0852963507957*S(a),255);return[t,a,r,1]}function De(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a=(n=Ea(e,"rgb"))[0],r=n[1],n=n[2],a=[Ia(a/255),Ia(r/255),Ia(n/255)],o=Ca(.4122214708*(r=a[0])+.5363325363*(n=a[1])+.0514459929*(a=a[2])),i=Ca(.2119034982*r+.6806995451*n+.1073969566*a),r=Ca(.0883024619*r+.2817188376*n+.6299787005*a);return[.2104542553*o+.793617785*i-.0040720468*r,1.9779984951*o-2.428592205*i+.4505937099*r,.0259040371*o+.7827717662*i-.808675766*r]}var c=l,ze=i,u=o,Ue=e.type,Fe=V,Be=q,Ve=(ze.prototype.css=function(e){return Fe(this._rgb,e)},c.css=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(ze,[null].concat(e,["css"])))},u.format.css=Be,u.autodetect.push({p:5,test:function(e){for(var t=[],a=arguments.length-1;0m.t3?At(e,1/3):e/m.t2+m.t0},f=u,Rt=e.unpack,Mt=Math.pow,jt=e.unpack,$t=e.type,c=l,Dt=i,g=o,zt=Le,Ut=(Dt.prototype.lab=function(){return zt(this._rgb)},c.lab=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(Dt,[null].concat(e,["lab"])))},g.format.lab=Ae,g.autodetect.push({p:2,test:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];if(e=jt(e,"lab"),"array"===$t(e)&&3===e.length)return"lab"}}),e.unpack),Ft=e.RAD2DEG,Bt=Math.sqrt,Vt=Math.atan2,Ht=Math.round,qt=e.unpack,Gt=Le,Kt=Pe,Jt=e.unpack,Wt=e.DEG2RAD,Xt=Math.sin,Zt=Math.cos,Yt=e.unpack,Qt=_e,ea=Ae,ta=e.unpack,aa=Re,ra=e.unpack,na=e.type,c=l,v=i,oa=o,ia=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a=qt(e,"rgb"),r=a[0],n=a[1],a=a[2],r=Gt(r,n,a),n=r[0],a=r[1],r=r[2];return Kt(n,a,r)},g=(v.prototype.lch=function(){return ia(this._rgb)},v.prototype.hcl=function(){return ia(this._rgb).reverse()},c.lch=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(v,[null].concat(e,["lch"])))},c.hcl=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(v,[null].concat(e,["hcl"])))},oa.format.lch=Re,oa.format.hcl=Me,["lch","hcl"].forEach(function(a){return oa.autodetect.push({p:2,test:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];if(e=ra(e,a),"array"===na(e)&&3===e.length)return a}})}),{aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflower:"#6495ed",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"}),c=i,b=o,sa=e.type,y=g,la=Ne,ca=Ce,ua=(c.prototype.name=function(){for(var e=ca(this._rgb,"rgb"),t=0,a=Object.keys(y);t=n/r?i=s:o=s}return ka(s)},Ea=(k.prototype.temp=k.prototype.kelvin=k.prototype.temperature=function(){return wa(this._rgb)},c.temp=c.kelvin=c.temperature=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(k,[null].concat(e,["temp"])))},b.format.temp=b.format.kelvin=b.format.temperature=$e,e.unpack),Ca=Math.cbrt,Na=Math.pow,xa=Math.sign;function Ia(e){var t=Math.abs(e);return t<.04045?e/12.92:(xa(e)||1)*Na((t+.055)/1.055,2.4)}function La(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a=(e=Oa(e,"lab"))[0],r=e[1],n=e[2],o=w(a+.3963377774*r+.2158037573*n,3),i=w(a-.1055613458*r-.0638541728*n,3),a=w(a-.0894841775*r-1.291485548*n,3);return[255*Aa(4.0767416621*o-3.3077115913*i+.2309699292*a),255*Aa(-1.2684380046*o+2.6097574011*i-.3413193965*a),255*Aa(-.0041960863*o-.7034186147*i+1.707614701*a),3=m[a];)a++;return a-1},w=function(e){return e},E=function(e){return e};return a(c),d.classes=function(e){var t;return null!=e?("array"===O(e)?p=[(m=e)[0],e[e.length-1]]:(t=L.analyze(p),m=0===e?[t.min,t.max]:L.limits(t,"e",e)),d):m},d.domain=function(a){if(!arguments.length)return p;g=a[0],v=a[a.length-1],l=[];var e=f.length;if(a.length===e&&g!==v)for(var t=0,r=Array.from(a);t=i[t+1];)t++;var a=(e-i[t])/(i[t+1]-i[t]);return o[t]+a*(o[t+1]-o[t])}))}return p=[g,v],d},d.mode=function(e){return arguments.length?(i=e,r(),d):i},d.range=function(e,t){return a(e),d},d.out=function(e){return n=e,d},d.spread=function(e){return arguments.length?(t=e,d):t},d.correctLightness=function(e){return r(),w=(e=null==e?!0:e)?function(e){for(var t=u(0,!0).lab()[0],a=u(1,!0).lab()[0],r=a 0");var l=Math.LOG10E*Kr(r),j=Math.LOG10E*Kr(n);i.push(r);for(var c=1;c.9999999)l[3]=1;return new Cr(Nr(l))}for(var p,h=e.shift(),m=h.get(o),f=[],g=0,v=0,b=0;b"}}:{children:o})),C.createElement("textarea",{ref:function(e){return t._input=e},style:w(w(w({},I.editor),I.textarea),n),className:N+(s?" ".concat(s):""),id:i,value:a,onChange:this._handleChange,onKeyDown:this._handleKeyDown,onClick:v,onKeyUp:S,onFocus:b,onBlur:y,disabled:c,form:u,maxLength:d,minLength:p,name:h,placeholder:m,readOnly:f,required:g,autoFocus:l,autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:!1,"data-gramm":!1}),C.createElement("style",{dangerouslySetInnerHTML:{__html:x}}))},s.defaultProps={tabSize:2,insertSpaces:!0,ignoreTabKey:!1,padding:0},s);function s(){var f=null!==t&&t.apply(this,arguments)||this;return f.state={capture:!0},f._recordCurrentState=function(){var e,t,a=f._input;a&&(e=a.value,t=a.selectionStart,a=a.selectionEnd,f._recordChange({value:e,selectionStart:t,selectionEnd:a}))},f._getLines=function(e,t){return e.substring(0,t).split("\n")},f._recordChange=function(e,t){void 0===t&&(t=!1);var a=f._history,r=a.stack,a=a.offset,a=(r.length&&-1=i.reach);b+=v.value.length,v=v.next){var y=v.value;if(a.length>t.length)return;if(!(y instanceof A)){var S,k=1;if(m){if(!(S=P(g,b,t,h))||S.index>=t.length)break;var w=S.index,E=S.index+S[0].length,C=b;for(C+=v.value.length;C<=w;)v=v.next,C+=v.value.length;if(C-=v.value.length,b=C,v.value instanceof A)continue;for(var N=v;N!==a.tail&&(Ci.reach&&(i.reach=y),v.prev),I=(I&&(O=_(a,O,I),b+=I.length),R(a,O,k),new A(s,p?T.tokenize(x,p):x,f,x));v=_(a,O,I),L&&_(a,v,L),1i.reach&&(i.reach=x.reach)}}}}}(e,n,t,n.head,0),n),i=[],s=o.head.next;s!==o.tail;)i.push(s.value),s=s.next;return i},hooks:{all:{},add:function(e,t){var a=T.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=T.hooks.all[e];if(a&&a.length)for(var r,n=0;r=a[n++];)r(t)}},Token:A},l.Prism=T,A.stringify=function t(e,a){if("string"==typeof e)return e;var r;if(Array.isArray(e))return r="",e.forEach(function(e){r+=t(e,a)}),r;var n,o={type:e.type,content:t(e.content,a),tag:"span",classes:["token",e.type],attributes:{},language:a},e=e.alias,i=(e&&(Array.isArray(e)?Array.prototype.push.apply(o.classes,e):o.classes.push(e)),T.hooks.run("wrap",o),"");for(n in o.attributes)i+=" "+n+'="'+(o.attributes[n]||"").replace(/"/g,""")+'"';return"<"+o.tag+' class="'+o.classes.join(" ")+'"'+i+">"+o.content+""},l.document?((n=T.util.currentScript())&&(T.filename=n.src,n.hasAttribute("data-manual"))&&(T.manual=!0),T.manual||("loading"===(o=document.readyState)||"interactive"===o&&n&&n.defer?document.addEventListener("DOMContentLoaded",i):window.requestAnimationFrame?window.requestAnimationFrame(i):window.setTimeout(i,16))):l.addEventListener&&!T.disableWorkerMessageHandler&&l.addEventListener("message",function(e){var e=JSON.parse(e.data),t=e.language,a=e.code,e=e.immediateClose;l.postMessage(T.highlight(a,T.languages[t],t)),e&&l.close()},!1),T);function A(e,t,a,r){this.type=e,this.content=t,this.alias=a,this.length=0|(r||"").length}function P(e,t,a,r){e.lastIndex=t;t=e.exec(a);return t&&r&&t[1]&&(e=t[1].length,t.index+=e,t[0]=t[0].slice(e)),t}function c(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function _(e,t,a){var r=t.next,a={value:a,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}function R(e,t,a){for(var r=t.next,n=0;nfunction(){return Yr.default.createElement(Zr,null)}};for(A in De)_($e,A,{get:De[A],enumerable:!0});var ze=t(b()),Ue={type:"logger",log(e){this.output("log",e)},warn(e){this.output("warn",e)},error(e){this.output("error",e)},output(e,t){console&&console[e]&&console[e].apply(console,t)}},Fe=class{constructor(e){this.init(e,1{this.observers[e]||(this.observers[e]=new Map);var t=this.observers[e].get(a)||0;this.observers[e].set(a,t+1)}),this}off(e,t){this.observers[e]&&(t?this.observers[e].delete(t):delete this.observers[e])}emit(r){for(var e=arguments.length,n=new Array(1{var[t,a]=e;for(let e=0;e{var[t,a]=e;for(let e=0;e{a=e,r=t});return e.resolve=a,e.reject=r,e}function Ve(e){return null==e?"":""+e}function He(e,t,a){e.forEach(e=>{t[e]&&(a[e]=t[e])})}var qe=/###/g;function Ge(e,t,a){function r(e){return e&&-1":">",'"':""","'":"'","/":"/"};function Ye(e){return"string"==typeof e?e.replace(/[&<>"'\/]/g,e=>Ze[e]):e}var Qe=[" ",",","?","!",";"],et=new class{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){var t=this.regExpMap.get(e);return void 0!==t||(t=new RegExp(e),this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,t),this.regExpQueue.push(e)),t}}(20);function tt(e,t,a){t=t||"",a=a||"";var r=Qe.filter(e=>t.indexOf(e)<0&&a.indexOf(e)<0);if(0===r.length)return 1;var n,r=et.getRegExp(`(${r.map(e=>"?"===e?"\\?":e).join("|")})`);let o=!r.test(e);return o||0<(n=e.indexOf(a))&&!r.test(e.substring(0,n))&&(o=!0),o}function at(e,t,a){var o=2t[e]&&0{this.processors[e]&&(t=this.processors[e].process(t,a,r,n))}),t}},it={},st=class extends r{constructor(e){var t=1{a=w&&a!==u?a:N;this.options.missingKeyHandler?this.options.missingKeyHandler(e,s,t,a,x,r):this.backendConnector&&this.backendConnector.saveMissing&&this.backendConnector.saveMissing(e,s,t,a,x,r),this.emit("missingKey",e,s,t,u)};this.options.saveMissing&&(this.options.saveMissingPlurals&&g?t.forEach(t=>{var e=this.pluralResolver.getSuffixes(t,r);E&&r[`defaultValue${this.options.pluralSeparator}zero`]&&e.indexOf(this.options.pluralSeparator+"zero")<0&&e.push(this.options.pluralSeparator+"zero"),e.forEach(e=>{I([t],i+e,r["defaultValue"+e]||C)})}):I(t,i,C))}u=this.extendTranslation(u,a,r,c,n),t&&u===i&&this.options.appendNamespaceToMissingKey&&(u=s+":"+i),(t||e)&&this.options.parseMissingKeyHandler&&(u="v1"!==this.options.compatibilityAPI?this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?s+":"+i:i,e?u:void 0):this.options.parseMissingKeyHandler(u))}return e?(c.res=u,c.usedParams=this.getUsedParamsDetails(r),c):u}extendTranslation(a,r,n,o,i){var s=this;if(this.i18nFormat&&this.i18nFormat.parse)a=this.i18nFormat.parse(a,{...this.options.interpolation.defaultVariables,...n},n.lng||this.language||o.usedLng,o.usedNS,o.usedKey,{resolved:o});else if(!n.skipInterpolation){n.interpolation&&this.interpolator.init({...n,interpolation:{...this.options.interpolation,...n.interpolation}});var l="string"==typeof a&&(n&&n.interpolation&&void 0!==n.interpolation.skipOnVariables?n:this.options).interpolation.skipOnVariables;let e,t=(l&&(c=a.match(this.interpolator.nestingRegexp),e=c&&c.length),n.replace&&"string"!=typeof n.replace?n.replace:n);this.options.interpolation.defaultVariables&&(t={...this.options.interpolation.defaultVariables,...t}),a=this.interpolator.interpolate(a,t,n.lng||this.language,n),l&&(l=(c=a.match(this.interpolator.nestingRegexp))&&c.length,e{if(!this.isValidLookup(p)){t=this.extractFromKey(t,d);const s=t.key;r=s;let e=t.namespaces;this.options.fallbackNS&&(e=e.concat(this.options.fallbackNS));const l=void 0!==d.count&&"string"!=typeof d.count,c=l&&!d.ordinal&&0===d.count&&this.pluralResolver.shouldUseIntlApi(),u=void 0!==d.context&&("string"==typeof d.context||"number"==typeof d.context)&&""!==d.context,a=d.lngs||this.languageUtils.toResolveHierarchy(d.lng||this.language,d.fallbackLng);e.forEach(i=>{this.isValidLookup(p)||(n=i,!it[a[0]+"-"+i]&&this.utils&&this.utils.hasLoadedNamespace&&!this.utils.hasLoadedNamespace(n)&&(it[a[0]+"-"+i]=!0,this.logger.warn(`key "${r}" for languages "${a.join(", ")}" won't get resolved as namespace "${n}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!")),a.forEach(t=>{if(!this.isValidLookup(p)){m=t;var e,a=[s];if(this.i18nFormat&&this.i18nFormat.addLookupKeys)this.i18nFormat.addLookupKeys(a,s,t,i,d);else{let e;l&&(e=this.pluralResolver.getSuffix(t,d.count,d));var r,n=this.options.pluralSeparator+"zero",o=this.options.pluralSeparator+"ordinal"+this.options.pluralSeparator;l&&(a.push(s+e),d.ordinal&&0===e.indexOf(o)&&a.push(s+e.replace(o,this.options.pluralSeparator)),c)&&a.push(s+n),u&&(r=""+s+this.options.contextSeparator+d.context,a.push(r),l)&&(a.push(r+e),d.ordinal&&0===e.indexOf(o)&&a.push(r+e.replace(o,this.options.pluralSeparator)),c)&&a.push(r+n)}for(;e=a.pop();)this.isValidLookup(p)||(h=e,p=this.getResource(t,i,e,d))}}))})}}),{res:p,usedKey:r,exactUsedKey:h,usedLng:m,usedNS:n}}isValidLookup(e){return!(void 0===e||!this.options.returnNull&&null===e||!this.options.returnEmptyString&&""===e)}getResource(e,t,a){var r=3e.toLowerCase()):2===e.length?(e[0]=e[0].toLowerCase(),e[1]=e[1].toUpperCase(),-1{a||(e=this.formatLanguageCode(e),this.options.supportedLngs&&!this.isSupportedCode(e))||(a=e)}),!a&&this.options.supportedLngs&&e.forEach(e=>{if(!a){const t=this.getLanguagePartFromCode(e);if(this.isSupportedCode(t))return a=t;a=this.options.supportedLngs.find(e=>e===t||!(e.indexOf("-")<0&&t.indexOf("-")<0)&&(0{e&&(this.isSupportedCode(e)?a.push(e):this.logger.warn("rejecting language code not found in supportedLngs: "+e))};return"string"==typeof e&&(-1{a.indexOf(e)<0&&r(this.formatLanguageCode(e))}),a}},ut=[{lngs:["ach","ak","am","arn","br","fil","gun","ln","mfe","mg","mi","oc","pt","pt-BR","tg","tl","ti","tr","uz","wa"],nr:[1,2],fc:1},{lngs:["af","an","ast","az","bg","bn","ca","da","de","dev","el","en","eo","es","et","eu","fi","fo","fur","fy","gl","gu","ha","hi","hu","hy","ia","it","kk","kn","ku","lb","mai","ml","mn","mr","nah","nap","nb","ne","nl","nn","no","nso","pa","pap","pms","ps","pt-PT","rm","sco","se","si","so","son","sq","sv","sw","ta","te","tk","ur","yo"],nr:[1,2],fc:2},{lngs:["ay","bo","cgg","fa","ht","id","ja","jbo","ka","km","ko","ky","lo","ms","sah","su","th","tt","ug","vi","wo","zh"],nr:[1],fc:3},{lngs:["be","bs","cnr","dz","hr","ru","sr","uk"],nr:[1,2,5],fc:4},{lngs:["ar"],nr:[0,1,2,3,11,100],fc:5},{lngs:["cs","sk"],nr:[1,2,5],fc:6},{lngs:["csb","pl"],nr:[1,2,5],fc:7},{lngs:["cy"],nr:[1,2,3,8],fc:8},{lngs:["fr"],nr:[1,2],fc:9},{lngs:["ga"],nr:[1,2,3,7,11],fc:10},{lngs:["gd"],nr:[1,2,3,20],fc:11},{lngs:["is"],nr:[1,2],fc:12},{lngs:["jv"],nr:[0,1],fc:13},{lngs:["kw"],nr:[1,2,3,4],fc:14},{lngs:["lt"],nr:[1,2,10],fc:15},{lngs:["lv"],nr:[1,2,0],fc:16},{lngs:["mk"],nr:[1,2],fc:17},{lngs:["mnk"],nr:[0,1,2],fc:18},{lngs:["mt"],nr:[1,2,11,20],fc:19},{lngs:["or"],nr:[2,1],fc:2},{lngs:["ro"],nr:[1,2,20],fc:20},{lngs:["sl"],nr:[5,1,2,3],fc:21},{lngs:["he","iw"],nr:[1,2,20,21],fc:22}],dt={1:function(e){return Number(1{t.lngs.forEach(e=>{a[e]={numbers:t.nr,plurals:dt[t.fc]}})}),a}var gt=class{constructor(e){var t=1""+t+e)}getSuffixes(t){let a=1mt[e]-mt[t]).map(e=>""+this.options.prepend+(a.ordinal?"ordinal"+this.options.prepend:"")+e):e.numbers.map(e=>this.getSuffix(t,e,a)):[]}getSuffix(e,t){var a=2this.options.prepend&&a.toString()?this.options.prepend+a.toString():a.toString();return"v1"===this.options.compatibilityJSON?1===a?"":"number"==typeof a?"_plural_"+a.toString():r():"v2"===this.options.compatibilityJSON||this.options.simplifyPluralSuffix&&2===e.numbers.length&&1===e.numbers[0]?r():this.options.prepend&&t.toString()?this.options.prepend+t.toString():t.toString()}shouldUseIntlApi(){return!pt.includes(this.options.compatibilityJSON)}};function vt(e,t,a,r,n){var o,i,s,l=3e),this.init(e)}init(){var e=0e&&e.source===t?(e.lastIndex=0,e):new RegExp(t,"g");this.regexp=e(this.regexp,this.prefix+"(.+?)"+this.suffix),this.regexpUnescape=e(this.regexpUnescape,""+this.prefix+this.unescapePrefix+"(.+?)"+this.unescapeSuffix+this.suffix),this.nestingRegexp=e(this.nestingRegexp,this.nestingPrefix+"(.+?)"+this.nestingSuffix)}interpolate(r,a,n,o){let i,s,l;const c=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{};function t(e){return e.replace(/\$/g,"$$$$")}const u=e=>{var t;return e.indexOf(this.formatSeparator)<0?(t=vt(a,c,e,this.options.keySeparator,this.options.ignoreJSONStructure),this.alwaysFormat?this.format(t,void 0,n,{...o,...a,interpolationkey:e}):t):(e=(t=e.split(this.formatSeparator)).shift().trim(),t=t.join(this.formatSeparator).trim(),this.format(vt(a,c,e,this.options.keySeparator,this.options.ignoreJSONStructure),t,n,{...o,...a,interpolationkey:e}))},d=(this.resetRegExp(),o&&o.missingInterpolationHandler||this.options.missingInterpolationHandler),p=(o&&o.interpolation&&void 0!==o.interpolation.skipOnVariables?o:this.options).interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:e=>t(e)},{regex:this.regexp,safeValue:e=>this.escapeValue?t(this.escape(e)):t(e)}].forEach(e=>{for(l=0;i=e.regex.exec(r);){var t=i[1].trim();if(void 0===(s=u(t)))if("function"==typeof d){var a=d(r,i,o);s="string"==typeof a?a:""}else{if(!o||!Object.prototype.hasOwnProperty.call(o,t)){if(p){s=i[0];continue}this.logger.warn(`missed to pass in variable ${t} for interpolating `+r)}s=""}else"string"==typeof s||this.useRawValueToEscape||(s=Ve(s));a=e.safeValue(s);if(r=r.replace(i[0],a),p?(e.regex.lastIndex+=s.length,e.regex.lastIndex-=i[0].length):e.regex.lastIndex=0,++l>=this.maxReplaces)break}}),r}nest(a,r){let n=2e.trim()),o[1]=c.shift(),e=c,t=!0),(i=r(l.call(this,o[1].trim(),s),s))&&o[0]===a&&"string"!=typeof i)return i;(i="string"!=typeof i?Ve(i):i)||(this.logger.warn(`missed to resolve ${o[1]} for nesting `+a),i=""),t&&(i=e.reduce((e,t)=>this.format(e,t,n.lng,{...n,interpolationkey:o[1].trim()}),i.trim())),a=a.replace(o[0],i),this.regexp.lastIndex=0}return a}};function yt(e){let t=e.toLowerCase().trim();const a={};return-1{var t;e&&([e,...t]=e.split(":"),t=t.join(":").trim().replace(/^'+|'+$/g,""),a[e.trim()]||(a[e.trim()]=t),"false"===t&&(a[e.trim()]=!1),"true"===t&&(a[e.trim()]=!0),isNaN(t)||(a[e.trim()]=parseInt(t,10)))})),{formatName:t,formatOptions:a}}function o(o){const i={};return function(e,t,a){var r=t+JSON.stringify(a);let n=i[r];return n||(n=o(rt(t),a),i[r]=n),n(e)}}var St=class{constructor(){var e=0{const a=new Intl.NumberFormat(e,{...t});return e=>a.format(e)}),currency:o((e,t)=>{const a=new Intl.NumberFormat(e,{...t,style:"currency"});return e=>a.format(e)}),datetime:o((e,t)=>{const a=new Intl.DateTimeFormat(e,{...t});return e=>a.format(e)}),relativetime:o((e,t)=>{const a=new Intl.RelativeTimeFormat(e,{...t});return e=>a.format(e,t.range||"day")}),list:o((e,t)=>{const a=new Intl.ListFormat(e,{...t});return e=>a.format(e)})},this.init(e)}init(e){var t=(1{var{formatName:a,formatOptions:r}=yt(a);if(this.formats[a]){let e=t;try{var n=s&&s.formatParams&&s.formatParams[s.interpolationkey]||{},o=n.locale||n.lng||s.locale||s.lng||i;e=this.formats[a](t,o,{...r,...s,...n})}catch(e){this.logger.warn(e)}return e}return this.logger.warn("there was no format function for "+a),t},e)}};function kt(e,t){void 0!==e.pending[t]&&(delete e.pending[t],e.pendingCount--)}var wt=class extends r{constructor(e,t,a){var r=3{let r=!0;t.forEach(e=>{var t=a+"|"+e;!n.reload&&this.store.hasResourceBundle(a,e)?this.state[t]=2:this.state[t]<0||(1===this.state[t]?void 0===i[t]&&(i[t]=!0):(this.state[t]=1,r=!1,void 0===i[t]&&(i[t]=!0),void 0===o[t]&&(o[t]=!0),void 0===l[e]&&(l[e]=!0)))}),r||(s[a]=!0)}),(Object.keys(o).length||Object.keys(i).length)&&this.queue.push({pending:i,pendingCount:Object.keys(i).length,loaded:{},errors:[],callback:a}),{toLoad:Object.keys(o),pending:Object.keys(i),toLoadLanguages:Object.keys(s),toLoadNamespaces:Object.keys(l)}}loaded(e,t,a){var r=e.split("|");const n=r[0],o=r[1],i=(t&&this.emit("failedLoading",n,o,t),a&&this.store.addResourceBundle(n,o,a,void 0,void 0,{skipCopy:!0}),this.state[e]=t?-1:2,{});this.queue.forEach(a=>{Je(a.loaded,[n],o),kt(a,e),t&&a.errors.push(t),0!==a.pendingCount||a.done||(Object.keys(a.loaded).forEach(t=>{i[t]||(i[t]={});var e=a.loaded[t];e.length&&e.forEach(e=>{void 0===i[t][e]&&(i[t][e]=!0)})}),a.done=!0,a.errors.length?a.callback(a.errors):a.callback())}),this.emit("loaded",i),this.queue=this.queue.filter(e=>!e.done)}read(r,n,o){let i=3=this.maxParallelReads)this.waitingReads.push({lng:r,ns:n,fcName:o,tried:i,wait:s,callback:l});else{this.readingCalls++;const a=(e,t)=>{var a;this.readingCalls--,0{this.read.call(this,r,n,o,i+1,2*s,l)},s):l(e,t)};var e=this.backend[o].bind(this.backend);if(2!==e.length)return e(r,n,a);try{var t=e(r,n);t&&"function"==typeof t.then?t.then(e=>a(null,e)).catch(a):a(null,t)}catch(e){a(e)}}}prepareLoading(e,t){var a=2{this.loadOne(e)})}load(e,t,a){this.prepareLoading(e,t,{},a)}reload(e,t,a){this.prepareLoading(e,t,{reload:!0},a)}loadOne(a){let r=1{e&&this.logger.warn(`${r}loading namespace ${o} for language ${n} failed`,e),!e&&t&&this.logger.log(`${r}loaded namespace ${o} for language `+n,t),this.loaded(a,e,t)})}saveMissing(t,a,r,n,o){var i=5{};if(this.services.utils&&this.services.utils.hasLoadedNamespace&&!this.services.utils.hasLoadedNamespace(a))this.logger.warn(`did not save key "${r}" as the namespace "${a}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");else if(null!=r&&""!==r){if(this.backend&&this.backend.create){i={...i,isUpdate:o},o=this.backend.create.bind(this.backend);if(o.length<6)try{let e;(e=5===o.length?o(t,a,r,n,i):o(t,a,r,n))&&"function"==typeof e.then?e.then(e=>s(null,e)).catch(s):s(null,e)}catch(e){s(e)}else o(t,a,r,n,s,i)}t&&t[0]&&this.store.addResource(t[0],a,r,n)}}};function Et(){return{debug:!1,initImmediate:!0,ns:["translation"],defaultNS:["translation"],fallbackLng:["dev"],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:"all",preload:!1,simplifyPluralSuffix:!0,keySeparator:".",nsSeparator:":",pluralSeparator:"_",contextSeparator:"_",partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:"fallback",saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:function(e){let t={};if("object"==typeof e[1]&&(t=e[1]),"string"==typeof e[1]&&(t.defaultValue=e[1]),"string"==typeof e[2]&&(t.tDescription=e[2]),"object"==typeof e[2]||"object"==typeof e[3]){const a=e[3]||e[2];Object.keys(a).forEach(e=>{t[e]=a[e]})}return t},interpolation:{escapeValue:!0,format:e=>e,prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!0}}}function Ct(e){return"string"==typeof e.ns&&(e.ns=[e.ns]),"string"==typeof e.fallbackLng&&(e.fallbackLng=[e.fallbackLng]),"string"==typeof e.fallbackNS&&(e.fallbackNS=[e.fallbackNS]),e.supportedLngs&&e.supportedLngs.indexOf("cimode")<0&&(e.supportedLngs=e.supportedLngs.concat(["cimode"])),e}function Nt(){}function xt(t){Object.getOwnPropertyNames(Object.getPrototypeOf(t)).forEach(e=>{"function"==typeof t[e]&&(t[e]=t[e].bind(t))})}var It=class extends r{constructor(){let e=0{this.init(e,t)},0)}}init(){var n=this;let e=0{e.init&&e.init(this)})}this.format=this.options.interpolation.format,a=a||Nt,!this.options.fallbackLng||this.services.languageDetector||this.options.lng||0<(o=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng)).length&&"dev"!==o[0]&&(this.options.lng=o[0]),this.services.languageDetector||this.options.lng||this.logger.warn("init: no languageDetector is used and no lng is defined");["getResource","hasResourceBundle","getResourceBundle","getDataByLanguage"].forEach(e=>{this[e]=function(){return n.store[e](...arguments)}});["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(e=>{this[e]=function(){return n.store[e](...arguments),n}});const s=Be();t=()=>{var e=(e,t)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn("init: i18next is already initialized. You should call init just once!"),this.isInitialized=!0,this.options.isClone||this.logger.log("initialized",this.options),this.emit("initialized",this.options),s.resolve(t),a(e,t)};if(this.languages&&"v1"!==this.options.compatibilityAPI&&!this.isInitialized)return e(null,this.t.bind(this));this.changeLanguage(this.options.lng,e)};return this.options.resources||!this.options.initImmediate?t():setTimeout(t,0),s}loadResources(e){let t=1{e&&"cimode"!==e&&this.services.languageUtils.toResolveHierarchy(e).forEach(e=>{"cimode"!==e&&r.indexOf(e)<0&&r.push(e)})};a?n(a):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(e=>n(e)),this.options.preload&&this.options.preload.forEach(e=>n(e)),this.services.backendConnector.load(r,this.options.ns,e=>{e||this.resolvedLanguage||!this.language||this.setResolvedLanguage(this.language),t(e)})}else t(null)}reloadResources(e,t,a){const r=Be();return e=e||this.languages,t=t||this.options.ns,a=a||Nt,this.services.backendConnector.reload(e,t,e=>{r.resolve(),a(e)}),r}use(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(e.type)return"backend"===e.type&&(this.modules.backend=e),("logger"===e.type||e.log&&e.warn&&e.error)&&(this.modules.logger=e),"languageDetector"===e.type&&(this.modules.languageDetector=e),"i18nFormat"===e.type&&(this.modules.i18nFormat=e),"postProcessor"===e.type&&ot.addPostProcessor(e),"formatter"===e.type&&(this.modules.formatter=e),"3rdParty"===e.type&&this.modules.external.push(e),this;throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()")}setResolvedLanguage(e){if(e&&this.languages&&!(-1<["cimode","dev"].indexOf(e)))for(let e=0;e{this.language=e,this.languages=this.services.languageUtils.toResolveHierarchy(e),this.resolvedLanguage=void 0,this.setResolvedLanguage(e)}),s=(e,t)=>{t?(i(t),this.translator.changeLanguage(t),this.isLanguageChangingTo=void 0,this.emit("languageChanged",t),this.logger.log("languageChanged",t)):this.isLanguageChangingTo=void 0,o.resolve(function(){return n.t(...arguments)}),r&&r(e,function(){return n.t(...arguments)})};var e=e=>{const t="string"==typeof(e=a||e||!this.services.languageDetector?e:[])?e:this.services.languageUtils.getBestMatchFromCodes(e);t&&(this.language||i(t),this.translator.language||this.translator.changeLanguage(t),this.services.languageDetector)&&this.services.languageDetector.cacheUserLanguage&&this.services.languageDetector.cacheUserLanguage(t),this.loadResources(t,e=>{s(e,t)})};return a||!this.services.languageDetector||this.services.languageDetector.async?!a&&this.services.languageDetector&&this.services.languageDetector.async?0===this.services.languageDetector.detect.length?this.services.languageDetector.detect().then(e):this.services.languageDetector.detect(e):e(a):e(this.services.languageDetector.detect()),o}getFixedT(e,t,l){var c=this;function u(e,t){let a;if("object"!=typeof t){for(var r=arguments.length,n=new Array(2""+a.keyPrefix+i+e):a.keyPrefix?""+a.keyPrefix+i+e:e,c.t(s,a)}return"string"==typeof e?u.lng=e:u.lngs=e,u.ns=t,u.keyPrefix=l,u}t(){return this.translator&&this.translator.translate(...arguments)}exists(){return this.translator&&this.translator.exists(...arguments)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e){var t=1{e=this.services.backendConnector.state[e+"|"+t];return-1===e||2===e};if(t.precheck){t=t.precheck(this,o);if(void 0!==t)return t}return!!this.hasResourceBundle(a,e)||!(this.services.backendConnector.backend&&(!this.options.resources||this.options.partialBundledLanguages)&&(!o(a,e)||r&&!o(n,e)))}loadNamespaces(e,t){const a=Be();return this.options.ns?((e="string"==typeof e?[e]:e).forEach(e=>{this.options.ns.indexOf(e)<0&&this.options.ns.push(e)}),this.loadResources(e=>{a.resolve(),t&&t(e)}),a):(t&&t(),Promise.resolve())}loadLanguages(e,t){const a=Be(),r=this.options.preload||[];e=(e="string"==typeof e?[e]:e).filter(e=>r.indexOf(e)<0);return e.length?(this.options.preload=r.concat(e),this.loadResources(e=>{a.resolve(),t&&t(e)}),a):(t&&t(),Promise.resolve())}dir(e){var t;return!(e=e||this.resolvedLanguage||(this.languages&&0{n[e]=this[e]}),n.services={...this.services},n.services.utils={hasLoadedNamespace:n.hasLoadedNamespace.bind(n)},a&&(n.store=new nt(this.store.data,r),n.services.resourceStore=n.store),n.translator=new st(n.services,r),n.translator.on("*",function(e){for(var t=arguments.length,a=new Array(1()=>{if(t.isInitialized)a();else{const e=()=>{setTimeout(()=>{t.off("initialized",e)},0),a()};t.on("initialized",e)}};function At(e,t,a){e.loadNamespaces(t,Tt(e,a))}function Pt(t,e,a,r){(a="string"==typeof a?[a]:a).forEach(e=>{t.options.ns.indexOf(e)<0&&t.options.ns.push(e)}),t.loadLanguages(e,Tt(t,r))}function _t(a,e,t){let r=2{if(r.bindI18n&&-1{e=a.services.backendConnector.state[e+"|"+t];return-1===e||2===e},!(n.bindI18n&&-1",">":">","'":"'","'":"'",""":'"',""":'"'," ":" "," ":" ","©":"©","©":"©","®":"®","®":"®","…":"…","…":"…","/":"/","/":"/"},$t=e=>jt[e],Dt={bindI18n:"languageChanged",bindI18nStore:"",transEmptyNodeValue:"",transSupportBasicHtmlNodes:!0,transWrapTextNodes:"",transKeepBasicHtmlNodesFor:["br","strong","i","p"],useSuspense:!0,unescape:e=>e.replace(Mt,$t)};var z={type:"3rdParty",init(e){!function(e){var t=0{this.usedNamespaces[e]||(this.usedNamespaces[e]=!0)})}getUsedNamespaces(){return Object.keys(this.usedNamespaces)}},k=t(b(),1),Ft=(e,t)=>{const a=(0,k.useRef)();return(0,k.useEffect)(()=>{a.current=t?a.current:e},[e,t]),a.current};function Bt(e,t,a,r){return e.getFixedT(t,a,r)}function Vt(e,t){let r=1"string"==typeof t?t:t&&"object"==typeof t&&"string"==typeof t.defaultValue?t.defaultValue:Array.isArray(e)?e[e.length-1]:e,{},!1]).t=n,o.i18n={},o.ready=!1,o;s.options.react&&void 0!==s.options.react.wait&&Ot("It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.");const l={...Dt,...s.options.react,...r},{useSuspense:c,keyPrefix:u}=l;let d=e||i||s.options&&s.options.defaultNS;d="string"==typeof d?[d]:d||["translation"],s.reportNamespaces.addUsedNamespaces&&s.reportNamespaces.addUsedNamespaces(d);const p=(s.isInitialized||s.initializedStoreOnce)&&d.every(e=>_t(e,s,l)),h=(n=s,o=r.lng||null,i="fallback"===l.nsMode?d:d[0],a=u,(0,k.useCallback)(Bt(n,o,i,a),[n,o,i,a])),m=()=>h,f=()=>Bt(s,r.lng||null,"fallback"===l.nsMode?d:d[0],u),[g,v]=(0,k.useState)(m);let b=d.join();r.lng&&(b=""+r.lng+b);const y=Ft(b),S=(0,k.useRef)(!0);(0,k.useEffect)(()=>{const{bindI18n:e,bindI18nStore:t}=l;function a(){S.current&&v(f)}return S.current=!0,p||c||(r.lng?Pt(s,r.lng,d,()=>{S.current&&v(f)}):At(s,d,()=>{S.current&&v(f)})),p&&y&&y!==b&&S.current&&v(f),e&&s&&s.on(e,a),t&&s&&s.store.on(t,a),()=>{S.current=!1,e&&s&&e.split(" ").forEach(e=>s.off(e,a)),t&&s&&t.split(" ").forEach(e=>s.store.off(e,a))}},[s,b]),(0,k.useEffect)(()=>{S.current&&p&&v(m)},[s,u,p]);n=[g,s,p];if(n.t=g,n.i18n=s,(n.ready=p)||!p&&!c)return n;throw new Promise(e=>{r.lng?Pt(s,r.lng,d,()=>e()):At(s,d,()=>e())})}var Ht=t(b(),1);function qt(i,e){let s=1(0,Ht.createElement)(a,Object.assign({},e,{forwardedRef:t}))):a}}t(b(),1),t(b(),1),t(b(),1);function Gt(e){return(Gt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function Kt(e){e=function(e,t){if("object"!==Gt(e)||null===e)return e;var a=e[Symbol.toPrimitive];if(void 0===a)return("string"===t?String:Number)(e);if("object"!==Gt(a=a.call(e,t||"default")))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}(e,"string");return"symbol"===Gt(e)?e:String(e)}function Jt(e,t){for(var a=0;a{t=localStorage.getItem(t);if(!t)return e;try{return JSON.parse(t)}catch(e){return t}}),Sa=e=>{const a={section:/^\s*\[\s*([^\]]*)\s*\]\s*$/,param:/^\s*([^=]+?)\s*=\s*(.*?)\s*$/,comment:/^\s*;.*$/},r={};e=e.split(/[\r\n]+/);let n=null;return e.forEach(function(e){var t;a.comment.test(e)||(a.param.test(e)?e.includes("xrdb")?(delete r[n??""],n=null):(t=e.match(a.param),n&&t&&(r[n][t[1]]=t[2].split(";")[0].trim())):a.section.test(e)?(t=e.match(a.section))&&(r[t[1]]={},n=t[1]):0==e.length&&(n=n&&null))}),r},ka=e=>{var t=document.querySelector("style.marketplaceSnippets"),t=(t&&t.remove(),document.createElement("style")),e=e.reduce((e,t)=>e=(e+=`/* ${t.title} - ${t.description} */ +var marketplace=(()=>{var A,P=Object.create,M=Object.defineProperty,_=Object.getOwnPropertyDescriptor,R=Object.getOwnPropertyNames,j=Object.getPrototypeOf,D=Object.prototype.hasOwnProperty,e=(e,t)=>function(){return t||(0,e[R(e)[0]])((t={exports:{}}).exports,t),t.exports},$=(t,a,r,n)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let e of R(a))D.call(t,e)||e===r||M(t,e,{get:()=>a[e],enumerable:!(n=_(a,e))||n.enumerable});return t},t=(e,t,a)=>(a=null!=e?P(j(e)):{},$(!t&&e&&e.__esModule?a:M(a,"default",{value:e,enumerable:!0}),e)),b=e({"external-global-plugin:react"(e,t){t.exports=Spicetify.React}}),z=e({"node_modules/.pnpm/void-elements@3.1.0/node_modules/void-elements/index.js"(e,t){t.exports={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0}}}),J=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/constants.js"(e,t){var a=Number.MAX_SAFE_INTEGER||9007199254740991;t.exports={MAX_LENGTH:256,MAX_SAFE_COMPONENT_LENGTH:16,MAX_SAFE_BUILD_LENGTH:250,MAX_SAFE_INTEGER:a,RELEASE_TYPES:["major","premajor","minor","preminor","patch","prepatch","prerelease"],SEMVER_SPEC_VERSION:"2.0.0",FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}}}),U=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/debug.js"(e,t){var a="object"==typeof process&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...e)=>console.error("SEMVER",...e):()=>{};t.exports=a}}),V=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/re.js"(e,t){var{MAX_SAFE_COMPONENT_LENGTH:a,MAX_SAFE_BUILD_LENGTH:r,MAX_LENGTH:n}=J(),o=U(),i=(e=t.exports={}).re=[],s=e.safeRe=[],l=e.src=[],c=e.t={},u=0,t="[a-zA-Z0-9-]",d=[["\\s",1],["\\d",n],[t,r]],n=(e,t,a)=>{var r=(e=>{for(var[t,a]of d)e=e.split(t+"*").join(`${t}{0,${a}}`).split(t+"+").join(`${t}{1,${a}}`);return e})(t),n=u++;o(e,n,t),c[e]=n,l[n]=t,i[n]=new RegExp(t,a?"g":void 0),s[n]=new RegExp(r,a?"g":void 0)};n("NUMERICIDENTIFIER","0|[1-9]\\d*"),n("NUMERICIDENTIFIERLOOSE","\\d+"),n("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${t}*`),n("MAINVERSION",`(${l[c.NUMERICIDENTIFIER]})\\.(${l[c.NUMERICIDENTIFIER]})\\.(${l[c.NUMERICIDENTIFIER]})`),n("MAINVERSIONLOOSE",`(${l[c.NUMERICIDENTIFIERLOOSE]})\\.(${l[c.NUMERICIDENTIFIERLOOSE]})\\.(${l[c.NUMERICIDENTIFIERLOOSE]})`),n("PRERELEASEIDENTIFIER",`(?:${l[c.NUMERICIDENTIFIER]}|${l[c.NONNUMERICIDENTIFIER]})`),n("PRERELEASEIDENTIFIERLOOSE",`(?:${l[c.NUMERICIDENTIFIERLOOSE]}|${l[c.NONNUMERICIDENTIFIER]})`),n("PRERELEASE",`(?:-(${l[c.PRERELEASEIDENTIFIER]}(?:\\.${l[c.PRERELEASEIDENTIFIER]})*))`),n("PRERELEASELOOSE",`(?:-?(${l[c.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${l[c.PRERELEASEIDENTIFIERLOOSE]})*))`),n("BUILDIDENTIFIER",t+"+"),n("BUILD",`(?:\\+(${l[c.BUILDIDENTIFIER]}(?:\\.${l[c.BUILDIDENTIFIER]})*))`),n("FULLPLAIN",`v?${l[c.MAINVERSION]}${l[c.PRERELEASE]}?${l[c.BUILD]}?`),n("FULL",`^${l[c.FULLPLAIN]}$`),n("LOOSEPLAIN",`[v=\\s]*${l[c.MAINVERSIONLOOSE]}${l[c.PRERELEASELOOSE]}?${l[c.BUILD]}?`),n("LOOSE",`^${l[c.LOOSEPLAIN]}$`),n("GTLT","((?:<|>)?=?)"),n("XRANGEIDENTIFIERLOOSE",l[c.NUMERICIDENTIFIERLOOSE]+"|x|X|\\*"),n("XRANGEIDENTIFIER",l[c.NUMERICIDENTIFIER]+"|x|X|\\*"),n("XRANGEPLAIN",`[v=\\s]*(${l[c.XRANGEIDENTIFIER]})(?:\\.(${l[c.XRANGEIDENTIFIER]})(?:\\.(${l[c.XRANGEIDENTIFIER]})(?:${l[c.PRERELEASE]})?${l[c.BUILD]}?)?)?`),n("XRANGEPLAINLOOSE",`[v=\\s]*(${l[c.XRANGEIDENTIFIERLOOSE]})(?:\\.(${l[c.XRANGEIDENTIFIERLOOSE]})(?:\\.(${l[c.XRANGEIDENTIFIERLOOSE]})(?:${l[c.PRERELEASELOOSE]})?${l[c.BUILD]}?)?)?`),n("XRANGE",`^${l[c.GTLT]}\\s*${l[c.XRANGEPLAIN]}$`),n("XRANGELOOSE",`^${l[c.GTLT]}\\s*${l[c.XRANGEPLAINLOOSE]}$`),n("COERCEPLAIN",`(^|[^\\d])(\\d{1,${a}})(?:\\.(\\d{1,${a}}))?(?:\\.(\\d{1,${a}}))?`),n("COERCE",l[c.COERCEPLAIN]+"(?:$|[^\\d])"),n("COERCEFULL",l[c.COERCEPLAIN]+`(?:${l[c.PRERELEASE]})?(?:${l[c.BUILD]})?(?:$|[^\\d])`),n("COERCERTL",l[c.COERCE],!0),n("COERCERTLFULL",l[c.COERCEFULL],!0),n("LONETILDE","(?:~>?)"),n("TILDETRIM",`(\\s*)${l[c.LONETILDE]}\\s+`,!0),e.tildeTrimReplace="$1~",n("TILDE",`^${l[c.LONETILDE]}${l[c.XRANGEPLAIN]}$`),n("TILDELOOSE",`^${l[c.LONETILDE]}${l[c.XRANGEPLAINLOOSE]}$`),n("LONECARET","(?:\\^)"),n("CARETTRIM",`(\\s*)${l[c.LONECARET]}\\s+`,!0),e.caretTrimReplace="$1^",n("CARET",`^${l[c.LONECARET]}${l[c.XRANGEPLAIN]}$`),n("CARETLOOSE",`^${l[c.LONECARET]}${l[c.XRANGEPLAINLOOSE]}$`),n("COMPARATORLOOSE",`^${l[c.GTLT]}\\s*(${l[c.LOOSEPLAIN]})$|^$`),n("COMPARATOR",`^${l[c.GTLT]}\\s*(${l[c.FULLPLAIN]})$|^$`),n("COMPARATORTRIM",`(\\s*)${l[c.GTLT]}\\s*(${l[c.LOOSEPLAIN]}|${l[c.XRANGEPLAIN]})`,!0),e.comparatorTrimReplace="$1$2$3",n("HYPHENRANGE",`^\\s*(${l[c.XRANGEPLAIN]})\\s+-\\s+(${l[c.XRANGEPLAIN]})\\s*$`),n("HYPHENRANGELOOSE",`^\\s*(${l[c.XRANGEPLAINLOOSE]})\\s+-\\s+(${l[c.XRANGEPLAINLOOSE]})\\s*$`),n("STAR","(<|>)?=?\\s*\\*"),n("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$"),n("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")}}),B=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/parse-options.js"(e,t){var a=Object.freeze({loose:!0}),r=Object.freeze({});t.exports=e=>e?"object"!=typeof e?a:e:r}}),W=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/internal/identifiers.js"(e,t){var n=/^[0-9]+$/,a=(e,t)=>{var a=n.test(e),r=n.test(t);return a&&r&&(e=+e,t=+t),e===t?0:a&&!r||(!r||a)&&ea(t,e)}}}),H=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/classes/semver.js"(e,t){var n=U(),{MAX_LENGTH:a,MAX_SAFE_INTEGER:r}=J(),{safeRe:o,t:i}=V(),s=B(),l=W()["compareIdentifiers"],c=class{constructor(e,t){if(t=s(t),e instanceof c){if(e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease)return e;e=e.version}else if("string"!=typeof e)throw new TypeError(`Invalid version. Must be a string. Got type "${typeof e}".`);if(e.length>a)throw new TypeError(`version is longer than ${a} characters`);n("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;t=e.trim().match(t.loose?o[i.LOOSE]:o[i.FULL]);if(!t)throw new TypeError("Invalid Version: "+e);if(this.raw=e,this.major=+t[1],this.minor=+t[2],this.patch=+t[3],this.major>r||this.major<0)throw new TypeError("Invalid major version");if(this.minor>r||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>r||this.patch<0)throw new TypeError("Invalid patch version");t[4]?this.prerelease=t[4].split(".").map(e=>{if(/^[0-9]+$/.test(e)){var t=+e;if(0<=t&&t{if(e instanceof r)return e;try{return new r(e,t)}catch(e){if(a)throw e;return null}}}}),Z=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/valid.js"(e,t){var a=q();t.exports=(e,t)=>{e=a(e,t);return e?e.version:null}}}),X=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/clean.js"(e,t){var a=q();t.exports=(e,t)=>{e=a(e.trim().replace(/^[=v]+/,""),t);return e?e.version:null}}}),Y=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/inc.js"(e,t){var o=H();t.exports=(e,t,a,r,n)=>{"string"==typeof a&&(n=r,r=a,a=void 0);try{return new o(e instanceof o?e.version:e,a).inc(t,r,n).version}catch(e){return null}}}}),Q=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/diff.js"(e,t){var o=q();t.exports=(e,t)=>{var a,r,e=o(e,null,!0),t=o(t,null,!0),n=e.compare(t);return 0===n?null:(r=!!(a=(n=0new a(e,t).major}}),te=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/minor.js"(e,t){var a=H();t.exports=(e,t)=>new a(e,t).minor}}),ae=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/patch.js"(e,t){var a=H();t.exports=(e,t)=>new a(e,t).patch}}),re=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/prerelease.js"(e,t){var a=q();t.exports=(e,t)=>{e=a(e,t);return e&&e.prerelease.length?e.prerelease:null}}}),G=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/compare.js"(e,t){var r=H();t.exports=(e,t,a)=>new r(e,a).compare(new r(t,a))}}),ne=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/rcompare.js"(e,t){var r=G();t.exports=(e,t,a)=>r(t,e,a)}}),oe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/compare-loose.js"(e,t){var a=G();t.exports=(e,t)=>a(e,t,!0)}}),ie=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/compare-build.js"(e,t){var r=H();t.exports=(e,t,a)=>{e=new r(e,a),t=new r(t,a);return e.compare(t)||e.compareBuild(t)}}}),se=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/sort.js"(e,t){var r=ie();t.exports=(e,a)=>e.sort((e,t)=>r(e,t,a))}}),le=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/rsort.js"(e,t){var r=ie();t.exports=(e,a)=>e.sort((e,t)=>r(t,e,a))}}),ce=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/gt.js"(e,t){var r=G();t.exports=(e,t,a)=>0r(e,t,a)<0}}),de=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/eq.js"(e,t){var r=G();t.exports=(e,t,a)=>0===r(e,t,a)}}),pe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/neq.js"(e,t){var r=G();t.exports=(e,t,a)=>0!==r(e,t,a)}}),he=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/gte.js"(e,t){var r=G();t.exports=(e,t,a)=>0<=r(e,t,a)}}),me=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/lte.js"(e,t){var r=G();t.exports=(e,t,a)=>r(e,t,a)<=0}}),fe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/cmp.js"(e,t){var n=de(),o=pe(),i=ce(),s=he(),l=ue(),c=me();t.exports=(e,t,a,r)=>{switch(t){case"===":return(e="object"==typeof e?e.version:e)===(a="object"==typeof a?a.version:a);case"!==":return(e="object"==typeof e?e.version:e)!==(a="object"==typeof a?a.version:a);case"":case"=":case"==":return n(e,a,r);case"!=":return o(e,a,r);case">":return i(e,a,r);case">=":return s(e,a,r);case"<":return l(e,a,r);case"<=":return c(e,a,r);default:throw new TypeError("Invalid operator: "+t)}}}}),ge=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/coerce.js"(e,t){var u=H(),d=q(),{safeRe:p,t:h}=V();t.exports=(e,t)=>{if(e instanceof u)return e;if("string"!=typeof(e="number"==typeof e?String(e):e))return null;let a=null;if((t=t||{}).rtl){for(var r,n=t.includePrerelease?p[h.COERCERTLFULL]:p[h.COERCERTL];(r=n.exec(e))&&(!a||a.index+a[0].length!==e.length);)a&&r.index+r[0].length===a.index+a[0].length||(a=r),n.lastIndex=r.index+r[1].length+r[2].length;n.lastIndex=-1}else a=e.match(t.includePrerelease?p[h.COERCEFULL]:p[h.COERCE]);var o,i,s,l,c;return null===a?null:(o=a[2],i=a[3]||"0",s=a[4]||"0",l=t.includePrerelease&&a[5]?"-"+a[5]:"",c=t.includePrerelease&&a[6]?"+"+a[6]:"",d(o+`.${i}.`+s+l+c,t))}}}),F=e({"node_modules/.pnpm/yallist@4.0.0/node_modules/yallist/iterator.js"(e,t){"use strict";t.exports=function(e){e.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}}}),ve=e({"node_modules/.pnpm/yallist@4.0.0/node_modules/yallist/yallist.js"(e,t){"use strict";function o(e){var t=this;if((t=t instanceof o?t:new o).tail=null,t.head=null,t.length=0,e&&"function"==typeof e.forEach)e.forEach(function(e){t.push(e)});else if(0this.length&&(t=this.length);for(var r=0,n=this.head;null!==n&&rthis.length&&(t=this.length);for(var r=this.length,n=this.tail;null!==n&&tthis.length?this.length-1:e)<0&&(e=this.length+e);for(var r=0,n=this.head;null!==n&&r1,m=(e,t,a)=>{t=e[h].get(t);if(t){var r=t.value;if(f(e,r)){if(v(e,t),!e[o])return}else a&&(e[n]&&(t.value.now=Date.now()),e[p].unshiftNode(t));return r.value}},f=(e,t)=>{var a;return!(!t||!t.maxAge&&!e[c])&&(a=Date.now()-t.now,t.maxAge?a>t.maxAge:e[c]&&a>e[c])},g=t=>{if(t[s]>t[i])for(let e=t[p].tail;t[s]>t[i]&&null!==e;){var a=e.prev;v(t,e),e=a}},v=(e,t)=>{var a;t&&(a=t.value,e[u]&&e[u](a.key,a.value),e[s]-=a.length,e[h].delete(a.key),e[p].removeNode(t))},b=class{constructor(e,t,a,r,n){this.key=e,this.value=t,this.length=a,this.now=r,this.maxAge=n||0}},y=(e,t,a,r)=>{let n=a.value;f(e,n)&&(v(e,a),e[o]||(n=void 0)),n&&t.call(r,n.value,n.key,e)};t.exports=class{constructor(e){if((e=(e="number"==typeof e?{max:e}:e)||{}).max&&("number"!=typeof e.max||e.max<0))throw new TypeError("max must be a non-negative number");this[i]=e.max||1/0;var t=e.length||r;if(this[l]="function"!=typeof t?r:t,this[o]=e.stale||!1,e.maxAge&&"number"!=typeof e.maxAge)throw new TypeError("maxAge must be a number");this[c]=e.maxAge||0,this[u]=e.dispose,this[d]=e.noDisposeOnSet||!1,this[n]=e.updateAgeOnGet||!1,this.reset()}set max(e){if("number"!=typeof e||e<0)throw new TypeError("max must be a non-negative number");this[i]=e||1/0,g(this)}get max(){return this[i]}set allowStale(e){this[o]=!!e}get allowStale(){return this[o]}set maxAge(e){if("number"!=typeof e)throw new TypeError("maxAge must be a non-negative number");this[c]=e,g(this)}get maxAge(){return this[c]}set lengthCalculator(e){(e="function"!=typeof e?r:e)!==this[l]&&(this[l]=e,this[s]=0,this[p].forEach(e=>{e.length=this[l](e.value,e.key),this[s]+=e.length})),g(this)}get lengthCalculator(){return this[l]}get length(){return this[s]}get itemCount(){return this[p].length}rforEach(t,a){a=a||this;for(let e=this[p].tail;null!==e;){var r=e.prev;y(this,t,e,a),e=r}}forEach(t,a){a=a||this;for(let e=this[p].head;null!==e;){var r=e.next;y(this,t,e,a),e=r}}keys(){return this[p].toArray().map(e=>e.key)}values(){return this[p].toArray().map(e=>e.value)}reset(){this[u]&&this[p]&&this[p].length&&this[p].forEach(e=>this[u](e.key,e.value)),this[h]=new Map,this[p]=new a,this[s]=0}dump(){return this[p].map(e=>!f(this,e)&&{k:e.key,v:e.value,e:e.now+(e.maxAge||0)}).toArray().filter(e=>e)}dumpLru(){return this[p]}set(e,t,a){if((a=a||this[c])&&"number"!=typeof a)throw new TypeError("maxAge must be a number");var r,n=a?Date.now():0,o=this[l](t,e);return this[h].has(e)?o>this[i]?(v(this,this[h].get(e)),!1):(r=this[h].get(e).value,this[u]&&!this[d]&&this[u](e,r.value),r.now=n,r.maxAge=a,r.value=t,this[s]+=o-r.length,r.length=o,this.get(e),g(this),!0):(r=new b(e,t,o,n,a)).length>this[i]?(this[u]&&this[u](e,t),!1):(this[s]+=r.length,this[p].unshift(r),this[h].set(e,this[p].head),g(this),!0)}has(e){return!!this[h].has(e)&&(e=this[h].get(e).value,!f(this,e))}get(e){return m(this,e,!0)}peek(e){return m(this,e,!1)}pop(){var e=this[p].tail;return e?(v(this,e),e.value):null}del(e){v(this,this[h].get(e))}load(t){this.reset();var a=Date.now();for(let e=t.length-1;0<=e;e--){var r=t[e],n=r.e||0;0===n?this.set(r.k,r.v):0<(n=n-a)&&this.set(r.k,r.v,n)}}prune(){this[h].forEach((e,t)=>m(this,t,!1))}}}}),K=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/classes/range.js"(e,t){var r=class{constructor(e,t){if(t=n(t),e instanceof r)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new r(e.raw,t);if(e instanceof l)return this.raw=e.value,this.set=[[e]],this.format(),this;if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e.trim().split(/\s+/).join(" "),this.set=this.raw.split("||").map(e=>this.parseRange(e.trim())).filter(e=>e.length),!this.set.length)throw new TypeError("Invalid SemVer Range: "+this.raw);if(1!v(e[0])),0===this.set.length)this.set=[t];else if(1e.join(" ").trim()).join("||").trim(),this.range}toString(){return this.range}parseRange(e){var t=((this.options.includePrerelease&&f)|(this.options.loose&&g))+":"+e,a=s.get(t);if(a)return a;var a=this.options.loose,r=a?p[h.HYPHENRANGELOOSE]:p[h.HYPHENRANGE];e=e.replace(r,L(this.options.includePrerelease)),d("hyphen replace",e),e=e.replace(p[h.COMPARATORTRIM],c),d("comparator trim",e),e=e.replace(p[h.TILDETRIM],u),d("tilde trim",e),e=e.replace(p[h.CARETTRIM],m),d("caret trim",e);let n=e.split(" ").map(e=>b(e,this.options)).join(" ").split(/\s+/).map(e=>I(e,this.options));a&&(n=n.filter(e=>(d("loose invalid filter",e,this.options),!!e.match(p[h.COMPARATORLOOSE])))),d("range list",n);var o=new Map;for(const i of n.map(e=>new l(e,this.options))){if(v(i))return[i];o.set(i.value,i)}1i(t,a)&&e.set.some(e=>i(e,a)&&t.every(t=>e.every(e=>t.intersects(e,a)))));throw new TypeError("a Range is required")}test(t){if(t){if("string"==typeof t)try{t=new a(t,this.options)}catch(e){return!1}for(let e=0;e"<0.0.0-0"===e.value,o=e=>""===e.value,i=(e,t)=>{let a=!0;var r=e.slice();let n=r.pop();for(;a&&r.length;)a=r.every(e=>n.intersects(e,t)),n=r.pop();return a},b=(e,t)=>(d("comp",e,t),e=w(e,t),d("caret",e),e=S(e,t),d("tildes",e),e=C(e,t),d("xrange",e),e=x(e,t),d("stars",e),e),y=e=>!e||"x"===e.toLowerCase()||"*"===e,S=(e,t)=>e.trim().split(/\s+/).map(e=>k(e,t)).join(" "),k=(i,e)=>{e=e.loose?p[h.TILDELOOSE]:p[h.TILDE];return i.replace(e,(e,t,a,r,n)=>{d("tilde",i,e,t,a,r,n);let o;return o=y(t)?"":y(a)?`>=${t}.0.0 <${+t+1}.0.0-0`:y(r)?`>=${t}.${a}.0 <${t}.${+a+1}.0-0`:n?(d("replaceTilde pr",n),`>=${t}.${a}.${r}-${n} <${t}.${+a+1}.0-0`):`>=${t}.${a}.${r} <${t}.${+a+1}.0-0`,d("tilde return",o),o})},w=(e,t)=>e.trim().split(/\s+/).map(e=>E(e,t)).join(" "),E=(i,e)=>{d("caret",i,e);var t=e.loose?p[h.CARETLOOSE]:p[h.CARET];const s=e.includePrerelease?"-0":"";return i.replace(t,(e,t,a,r,n)=>{d("caret",i,e,t,a,r,n);let o;return o=y(t)?"":y(a)?`>=${t}.0.0${s} <${+t+1}.0.0-0`:y(r)?"0"===t?`>=${t}.${a}.0${s} <${t}.${+a+1}.0-0`:`>=${t}.${a}.0${s} <${+t+1}.0.0-0`:n?(d("replaceCaret pr",n),"0"===t?"0"===a?`>=${t}.${a}.${r}-${n} <${t}.${a}.${+r+1}-0`:`>=${t}.${a}.${r}-${n} <${t}.${+a+1}.0-0`:`>=${t}.${a}.${r}-${n} <${+t+1}.0.0-0`):(d("no pr"),"0"===t?"0"===a?`>=${t}.${a}.${r}${s} <${t}.${a}.${+r+1}-0`:`>=${t}.${a}.${r}${s} <${t}.${+a+1}.0-0`:`>=${t}.${a}.${r} <${+t+1}.0.0-0`),d("caret return",o),o})},C=(e,t)=>(d("replaceXRanges",e,t),e.split(/\s+/).map(e=>N(e,t)).join(" ")),N=(c,u)=>{c=c.trim();var e=u.loose?p[h.XRANGELOOSE]:p[h.XRANGE];return c.replace(e,(e,t,a,r,n,o)=>{d("xRange",c,e,t,a,r,n,o);var i=y(a),s=i||y(r),l=s||y(n);return"="===t&&l&&(t=""),o=u.includePrerelease?"-0":"",i?e=">"===t||"<"===t?"<0.0.0-0":"*":t&&l?(s&&(r=0),n=0,">"===t?(t=">=",n=s?(a=+a+1,r=0):(r=+r+1,0)):"<="===t&&(t="<",s?a=+a+1:r=+r+1),e=t+a+`.${r}.`+n+(o="<"===t?"-0":o)):s?e=`>=${a}.0.0${o} <${+a+1}.0.0-0`:l&&(e=`>=${a}.${r}.0${o} <${a}.${+r+1}.0-0`),d("xRange return",e),e})},x=(e,t)=>(d("replaceStars",e,t),e.trim().replace(p[h.STAR],"")),I=(e,t)=>(d("replaceGTE0",e,t),e.trim().replace(p[t.includePrerelease?h.GTE0PRE:h.GTE0],"")),L=h=>(e,t,a,r,n,o,i,s,l,c,u,d,p)=>((t=y(a)?"":y(r)?`>=${a}.0.0`+(h?"-0":""):y(n)?`>=${a}.${r}.0`+(h?"-0":""):o?">="+t:">="+t+(h?"-0":""))+" "+(s=y(l)?"":y(c)?`<${+l+1}.0.0-0`:y(u)?`<${l}.${+c+1}.0-0`:d?`<=${l}.${c}.${u}-`+d:h?`<${l}.${c}.${+u+1}-0`:"<="+s)).trim(),O=(t,a,e)=>{for(let e=0;e")||!e.operator.startsWith(">"))&&!(this.operator.startsWith("<")&&e.operator.startsWith("<")||this.semver.version===e.semver.version&&this.operator.includes("=")&&e.operator.includes("=")||s(this.semver,"<",e.semver,t)&&this.operator.startsWith(">")&&e.operator.startsWith("<")||s(this.semver,">",e.semver,t)&&this.operator.startsWith("<")&&e.operator.startsWith(">")));throw new TypeError("a Comparator is required")}},n=(t.exports=r,B()),{safeRe:o,t:i}=V(),s=fe(),l=U(),c=H(),u=K()}}),Se=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/functions/satisfies.js"(e,t){var r=K();t.exports=(e,t,a)=>{try{t=new r(t,a)}catch(e){return!1}return t.test(e)}}}),ke=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/to-comparators.js"(e,t){var a=K();t.exports=(e,t)=>new a(e,t).set.map(e=>e.map(e=>e.value).join(" ").trim().split(" "))}}),we=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/max-satisfying.js"(e,t){var i=H(),s=K();t.exports=(e,t,a)=>{let r=null,n=null,o=null;try{o=new s(t,a)}catch(e){return null}return e.forEach(e=>{!o.test(e)||r&&-1!==n.compare(e)||(r=e,n=new i(r,a))}),r}}}),Ee=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/min-satisfying.js"(e,t){var i=H(),s=K();t.exports=(e,t,a)=>{let r=null,n=null,o=null;try{o=new s(t,a)}catch(e){return null}return e.forEach(e=>{!o.test(e)||r&&1!==n.compare(e)||(r=e,n=new i(r,a))}),r}}}),Ce=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/min-version.js"(e,t){var o=H(),a=K(),i=ce();t.exports=(t,e)=>{t=new a(t,e);let r=new o("0.0.0");if(t.test(r))return r;if(r=new o("0.0.0-0"),t.test(r))return r;r=null;for(let e=0;e{var t=new o(e.semver.version);switch(e.operator){case">":0===t.prerelease.length?t.patch++:t.prerelease.push(0),t.raw=t.format();case"":case">=":a&&!i(t,a)||(a=t);break;case"<":case"<=":break;default:throw new Error("Unexpected operation: "+e.operator)}}),!a||r&&!i(r,a)||(r=a)}return r&&t.test(r)?r:null}}}),Ne=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/valid.js"(e,t){var a=K();t.exports=(e,t)=>{try{return new a(e,t).range||"*"}catch(e){return null}}}}),xe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/outside.js"(e,t){var a=H(),p=ye(),h=p["ANY"],m=K(),f=Se(),g=ce(),v=ue(),b=me(),y=he();t.exports=(r,n,e,o)=>{r=new a(r,o),n=new m(n,o);let i,s,l,c,u;switch(e){case">":i=g,s=b,l=v,c=">",u=">=";break;case"<":i=v,s=y,l=g,c="<",u="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(f(r,n,o))return!1;for(let e=0;e{e.semver===h&&(e=new p(">=0.0.0")),t=t||e,a=a||e,i(e.semver,t.semver,o)?t=e:l(e.semver,a.semver,o)&&(a=e)}),t.operator===c||t.operator===u)return!1;if((!a.operator||a.operator===c)&&s(r,a.semver))return!1;if(a.operator===u&&l(r,a.semver))return!1}return!0}}}),Ie=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/gtr.js"(e,t){var r=xe();t.exports=(e,t,a)=>r(e,t,">",a)}}),Le=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/ltr.js"(e,t){var r=xe();t.exports=(e,t,a)=>r(e,t,"<",a)}}),Oe=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/intersects.js"(e,t){var r=K();t.exports=(e,t,a)=>(e=new r(e,a),t=new r(t,a),e.intersects(t,a))}}),Te=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/ranges/simplify.js"(e,t){var h=Se(),m=G();t.exports=(e,t,a)=>{var r=[];let n=null,o=null;var i=e.sort((e,t)=>m(e,t,a));for(const p of i){var s=h(p,t,a);n=s?(o=p,n||p):(o&&r.push([n,o]),o=null)}n&&r.push([n,null]);var l,c,u=[];for([l,c]of r)l===c?u.push(l):c||l!==i[0]?c?l===i[0]?u.push("<="+c):u.push(l+" - "+c):u.push(">="+l):u.push("*");var e=u.join(" || "),d="string"==typeof t.raw?t.raw:String(t);return e.length=0.0.0-0")],k=[new a(">=0.0.0")],w=(e,t,a)=>{return!e||!(0<(a=y(e.semver,t.semver,a)))&&(a<0||">"===t.operator&&">="===e.operator)?t:e},E=(e,t,a)=>{return!e||!((a=y(e.semver,t.semver,a))<0)&&(0{if(t!==a){t=new s(t,r),a=new s(a,r);let e=!1;e:for(const o of t.set){for(const i of a.set){var n=((s,l,c)=>{if(s!==l){if(1===s.length&&s[0].semver===v){if(1===l.length&&l[0].semver===v)return!0;s=c.includePrerelease?S:k}if(1===l.length&&l[0].semver===v){if(c.includePrerelease)return!0;l=k}var u=new Set,d,p;let e,t;for(const h of s)">"===h.operator||">="===h.operator?e=w(e,h,c):"<"===h.operator||"<="===h.operator?t=E(t,h,c):u.add(h.semver);if(1="!==e.operator||"<="!==t.operator))return null}for(const m of u){if(e&&!b(m,String(e),c))return null;if(t&&!b(m,String(t),c))return null;for(const f of l)if(!b(m,String(f),c))return!1;return!0}let r,n,o=!(!t||c.includePrerelease||!t.semver.prerelease.length)&&t.semver,i=!(!e||c.includePrerelease||!e.semver.prerelease.length)&&e.semver;o&&1===o.prerelease.length&&"<"===t.operator&&0===o.prerelease[0]&&(o=!1);for(const g of l){if(n=n||">"===g.operator||">="===g.operator,r=r||"<"===g.operator||"<="===g.operator,e)if(i&&g.semver.prerelease&&g.semver.prerelease.length&&g.semver.major===i.major&&g.semver.minor===i.minor&&g.semver.patch===i.patch&&(i=!1),">"===g.operator||">="===g.operator){if((d=w(e,g,c))===g&&d!==e)return!1}else if(">="===e.operator&&!b(e.semver,String(g),c))return!1;if(t)if(o&&g.semver.prerelease&&g.semver.prerelease.length&&g.semver.major===o.major&&g.semver.minor===o.minor&&g.semver.patch===o.patch&&(o=!1),"<"===g.operator||"<="===g.operator){if((p=E(t,g,c))===g&&p!==t)return!1}else if("<="===t.operator&&!b(t.semver,String(g),c))return!1;if(!g.operator&&(t||e)&&0!==a)return!1}if(e&&r&&!t&&0!==a)return!1;if(t&&n&&!e&&0!==a)return!1;if(i||o)return!1}return true})(o,i,r);if(e=e||null!==n,n)continue e}if(e)return!1}}return!0}}}),a=e({"node_modules/.pnpm/semver@7.6.0/node_modules/semver/index.js"(j,e){var t=V(),a=J(),r=H(),n=W(),o=q(),i=Z(),s=X(),l=Y(),c=Q(),u=ee(),d=te(),p=ae(),h=re(),m=G(),f=ne(),g=oe(),v=ie(),b=se(),y=le(),S=ce(),k=ue(),w=de(),E=pe(),C=he(),N=me(),x=fe(),I=ge(),L=ye(),O=K(),T=Se(),A=ke(),P=we(),M=Ee(),_=Ce(),R=Ne(),D=xe(),$=Ie(),z=Le(),U=Oe(),B=Te(),F=Ae();e.exports={parse:o,valid:i,clean:s,inc:l,diff:c,major:u,minor:d,patch:p,prerelease:h,compare:m,rcompare:f,compareLoose:g,compareBuild:v,sort:b,rsort:y,gt:S,lt:k,eq:w,neq:E,gte:C,lte:N,cmp:x,coerce:I,Comparator:L,Range:O,satisfies:T,toComparators:A,maxSatisfying:P,minSatisfying:M,minVersion:_,validRange:R,outside:D,gtr:$,ltr:z,intersects:U,simplifyRange:B,subset:F,SemVer:r,re:t.re,src:t.src,tokens:t.t,SEMVER_SPEC_VERSION:a.SEMVER_SPEC_VERSION,RELEASE_TYPES:a.RELEASE_TYPES,compareIdentifiers:n.compareIdentifiers,rcompareIdentifiers:n.rcompareIdentifiers}}}),Pe=e({"node_modules/.pnpm/chroma-js@2.4.2/node_modules/chroma-js/chroma.js"(e,t){var a;a=function(){"use strict";for(var e=function(e,t,a){return void 0===a&&(a=1),e<(t=void 0===t?0:t)?t:a>16,t>>8&255,255&t,1];if(e.match(tt))return 4===(e=5!==e.length&&9!==e.length?e:e.substr(1)).length&&(e=(e=e.split(""))[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]),[(t=parseInt(e,16))>>24&255,t>>16&255,t>>8&255,Math.round((255&t)/255*100)/100];throw new Error("unknown hex color: "+e)}function xe(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a,r,n,o=(e=ut(e,"hsi"))[0],i=e[1],s=e[2];return isNaN(o)&&(o=0),isNaN(i)&&(i=0),360f.t1?e*e*e:f.t2*(e-f.t0)}function Ae(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a=(e=_t(e,"lab"))[0],r=e[1],n=e[2],a=(a+16)/116,r=isNaN(r)?a:a+r/500,n=isNaN(n)?a:a-n/200;return a=f.Yn*Te(a),r=f.Xn*Te(r),n=f.Zn*Te(n),[Oe(3.2404542*r-1.5371385*a-.4985314*n),Oe(-.969266*r+1.8760108*a+.041556*n),Oe(.0556434*r-.2040259*a+1.0572252*n),3>16,e>>8&255,255&e,1];throw new Error("unknown num color: "+e)}function De(e){var t,a,r=(e=e/100)<66?(t=255,a=e<6?0:-155.25485562709179-.44596950469579133*(a=e-2)+104.49216199393888*S(a),e<20?0:.8274096064007395*(r=e-10)-254.76935184120902+115.67994401066147*S(r)):(t=351.97690566805693+.114206453784165*(t=e-55)-40.25366309332127*S(t),a=325.4494125711974+.07943456536662342*(a=e-50)-28.0852963507957*S(a),255);return[t,a,r,1]}function $e(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a=(n=Ea(e,"rgb"))[0],r=n[1],n=n[2],a=[Ia(a/255),Ia(r/255),Ia(n/255)],o=Ca(.4122214708*(r=a[0])+.5363325363*(n=a[1])+.0514459929*(a=a[2])),i=Ca(.2119034982*r+.6806995451*n+.1073969566*a),r=Ca(.0883024619*r+.2817188376*n+.6299787005*a);return[.2104542553*o+.793617785*i-.0040720468*r,1.9779984951*o-2.428592205*i+.4505937099*r,.0259040371*o+.7827717662*i-.808675766*r]}var c=l,ze=i,u=o,Ue=e.type,Be=V,Fe=q,Ve=(ze.prototype.css=function(e){return Be(this._rgb,e)},c.css=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(ze,[null].concat(e,["css"])))},u.format.css=Fe,u.autodetect.push({p:5,test:function(e){for(var t=[],a=arguments.length-1;0m.t3?At(e,1/3):e/m.t2+m.t0},f=u,_t=e.unpack,Rt=Math.pow,jt=e.unpack,Dt=e.type,c=l,$t=i,g=o,zt=Le,Ut=($t.prototype.lab=function(){return zt(this._rgb)},c.lab=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply($t,[null].concat(e,["lab"])))},g.format.lab=Ae,g.autodetect.push({p:2,test:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];if(e=jt(e,"lab"),"array"===Dt(e)&&3===e.length)return"lab"}}),e.unpack),Bt=e.RAD2DEG,Ft=Math.sqrt,Vt=Math.atan2,Ht=Math.round,qt=e.unpack,Gt=Le,Kt=Pe,Jt=e.unpack,Wt=e.DEG2RAD,Zt=Math.sin,Xt=Math.cos,Yt=e.unpack,Qt=Me,ea=Ae,ta=e.unpack,aa=_e,ra=e.unpack,na=e.type,c=l,v=i,oa=o,ia=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a=qt(e,"rgb"),r=a[0],n=a[1],a=a[2],r=Gt(r,n,a),n=r[0],a=r[1],r=r[2];return Kt(n,a,r)},g=(v.prototype.lch=function(){return ia(this._rgb)},v.prototype.hcl=function(){return ia(this._rgb).reverse()},c.lch=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(v,[null].concat(e,["lch"])))},c.hcl=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(v,[null].concat(e,["hcl"])))},oa.format.lch=_e,oa.format.hcl=Re,["lch","hcl"].forEach(function(a){return oa.autodetect.push({p:2,test:function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];if(e=ra(e,a),"array"===na(e)&&3===e.length)return a}})}),{aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflower:"#6495ed",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"}),c=i,b=o,sa=e.type,y=g,la=Ne,ca=Ce,ua=(c.prototype.name=function(){for(var e=ca(this._rgb,"rgb"),t=0,a=Object.keys(y);t=n/r?i=s:o=s}return ka(s)},Ea=(k.prototype.temp=k.prototype.kelvin=k.prototype.temperature=function(){return wa(this._rgb)},c.temp=c.kelvin=c.temperature=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return new(Function.prototype.bind.apply(k,[null].concat(e,["temp"])))},b.format.temp=b.format.kelvin=b.format.temperature=De,e.unpack),Ca=Math.cbrt,Na=Math.pow,xa=Math.sign;function Ia(e){var t=Math.abs(e);return t<.04045?e/12.92:(xa(e)||1)*Na((t+.055)/1.055,2.4)}function La(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];var a=(e=Oa(e,"lab"))[0],r=e[1],n=e[2],o=w(a+.3963377774*r+.2158037573*n,3),i=w(a-.1055613458*r-.0638541728*n,3),a=w(a-.0894841775*r-1.291485548*n,3);return[255*Aa(4.0767416621*o-3.3077115913*i+.2309699292*a),255*Aa(-1.2684380046*o+2.6097574011*i-.3413193965*a),255*Aa(-.0041960863*o-.7034186147*i+1.707614701*a),3=m[a];)a++;return a-1},w=function(e){return e},E=function(e){return e};return a(c),d.classes=function(e){var t;return null!=e?("array"===O(e)?p=[(m=e)[0],e[e.length-1]]:(t=L.analyze(p),m=0===e?[t.min,t.max]:L.limits(t,"e",e)),d):m},d.domain=function(a){if(!arguments.length)return p;g=a[0],v=a[a.length-1],l=[];var e=f.length;if(a.length===e&&g!==v)for(var t=0,r=Array.from(a);t=i[t+1];)t++;var a=(e-i[t])/(i[t+1]-i[t]);return o[t]+a*(o[t+1]-o[t])}))}return p=[g,v],d},d.mode=function(e){return arguments.length?(i=e,r(),d):i},d.range=function(e,t){return a(e),d},d.out=function(e){return n=e,d},d.spread=function(e){return arguments.length?(t=e,d):t},d.correctLightness=function(e){return r(),w=(e=null==e?!0:e)?function(e){for(var t=u(0,!0).lab()[0],a=u(1,!0).lab()[0],r=a 0");var l=Math.LOG10E*Kr(r),j=Math.LOG10E*Kr(n);i.push(r);for(var c=1;c.9999999)l[3]=1;return new Cr(Nr(l))}for(var p,h=e.shift(),m=h.get(o),f=[],g=0,v=0,b=0;b"}}:{children:o})),C.createElement("textarea",{ref:function(e){return t._input=e},style:w(w(w({},I.editor),I.textarea),n),className:N+(s?" ".concat(s):""),id:i,value:a,onChange:this._handleChange,onKeyDown:this._handleKeyDown,onClick:v,onKeyUp:S,onFocus:b,onBlur:y,disabled:c,form:u,maxLength:d,minLength:p,name:h,placeholder:m,readOnly:f,required:g,autoFocus:l,autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:!1,"data-gramm":!1}),C.createElement("style",{dangerouslySetInnerHTML:{__html:x}}))},s.defaultProps={tabSize:2,insertSpaces:!0,ignoreTabKey:!1,padding:0},s);function s(){var f=null!==t&&t.apply(this,arguments)||this;return f.state={capture:!0},f._recordCurrentState=function(){var e,t,a=f._input;a&&(e=a.value,t=a.selectionStart,a=a.selectionEnd,f._recordChange({value:e,selectionStart:t,selectionEnd:a}))},f._getLines=function(e,t){return e.substring(0,t).split("\n")},f._recordChange=function(e,t){void 0===t&&(t=!1);var a=f._history,r=a.stack,a=a.offset,a=(r.length&&-1=i.reach);b+=v.value.length,v=v.next){var y=v.value;if(a.length>t.length)return;if(!(y instanceof A)){var S,k=1;if(m){if(!(S=P(g,b,t,h))||S.index>=t.length)break;var w=S.index,E=S.index+S[0].length,C=b;for(C+=v.value.length;C<=w;)v=v.next,C+=v.value.length;if(C-=v.value.length,b=C,v.value instanceof A)continue;for(var N=v;N!==a.tail&&(Ci.reach&&(i.reach=y),v.prev),I=(I&&(O=M(a,O,I),b+=I.length),_(a,O,k),new A(s,p?T.tokenize(x,p):x,f,x));v=M(a,O,I),L&&M(a,v,L),1i.reach&&(i.reach=x.reach)}}}}}(e,n,t,n.head,0),n),i=[],s=o.head.next;s!==o.tail;)i.push(s.value),s=s.next;return i},hooks:{all:{},add:function(e,t){var a=T.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=T.hooks.all[e];if(a&&a.length)for(var r,n=0;r=a[n++];)r(t)}},Token:A},l.Prism=T,A.stringify=function t(e,a){if("string"==typeof e)return e;var r;if(Array.isArray(e))return r="",e.forEach(function(e){r+=t(e,a)}),r;var n,o={type:e.type,content:t(e.content,a),tag:"span",classes:["token",e.type],attributes:{},language:a},e=e.alias,i=(e&&(Array.isArray(e)?Array.prototype.push.apply(o.classes,e):o.classes.push(e)),T.hooks.run("wrap",o),"");for(n in o.attributes)i+=" "+n+'="'+(o.attributes[n]||"").replace(/"/g,""")+'"';return"<"+o.tag+' class="'+o.classes.join(" ")+'"'+i+">"+o.content+""},l.document?((n=T.util.currentScript())&&(T.filename=n.src,n.hasAttribute("data-manual"))&&(T.manual=!0),T.manual||("loading"===(o=document.readyState)||"interactive"===o&&n&&n.defer?document.addEventListener("DOMContentLoaded",i):window.requestAnimationFrame?window.requestAnimationFrame(i):window.setTimeout(i,16))):l.addEventListener&&!T.disableWorkerMessageHandler&&l.addEventListener("message",function(e){var e=JSON.parse(e.data),t=e.language,a=e.code,e=e.immediateClose;l.postMessage(T.highlight(a,T.languages[t],t)),e&&l.close()},!1),T);function A(e,t,a,r){this.type=e,this.content=t,this.alias=a,this.length=0|(r||"").length}function P(e,t,a,r){e.lastIndex=t;t=e.exec(a);return t&&r&&t[1]&&(e=t[1].length,t.index+=e,t[0]=t[0].slice(e)),t}function c(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function M(e,t,a){var r=t.next,a={value:a,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}function _(e,t,a){for(var r=t.next,n=0;nfunction(){return Yr.default.createElement(Xr,null)}};for(A in $e)M(De,A,{get:$e[A],enumerable:!0});var ze=t(b()),Ue={type:"logger",log(e){this.output("log",e)},warn(e){this.output("warn",e)},error(e){this.output("error",e)},output(e,t){console&&console[e]&&console[e].apply(console,t)}},Be=class{constructor(e){this.init(e,1{this.observers[e]||(this.observers[e]=new Map);var t=this.observers[e].get(a)||0;this.observers[e].set(a,t+1)}),this}off(e,t){this.observers[e]&&(t?this.observers[e].delete(t):delete this.observers[e])}emit(r){for(var e=arguments.length,n=new Array(1{var[t,a]=e;for(let e=0;e{var[t,a]=e;for(let e=0;e{a=e,r=t});return e.resolve=a,e.reject=r,e}function Ve(e){return null==e?"":""+e}function He(e,t,a){e.forEach(e=>{t[e]&&(a[e]=t[e])})}var qe=/###/g;function Ge(e,t,a){function r(e){return e&&-1":">",'"':""","'":"'","/":"/"};function Ye(e){return"string"==typeof e?e.replace(/[&<>"'\/]/g,e=>Xe[e]):e}var Qe=[" ",",","?","!",";"],et=new class{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){var t=this.regExpMap.get(e);return void 0!==t||(t=new RegExp(e),this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,t),this.regExpQueue.push(e)),t}}(20);function tt(e,t,a){t=t||"",a=a||"";var r=Qe.filter(e=>t.indexOf(e)<0&&a.indexOf(e)<0);if(0===r.length)return 1;var n,r=et.getRegExp(`(${r.map(e=>"?"===e?"\\?":e).join("|")})`);let o=!r.test(e);return o||0<(n=e.indexOf(a))&&!r.test(e.substring(0,n))&&(o=!0),o}function at(e,t,a){var o=2t[e]&&0{this.processors[e]&&(t=this.processors[e].process(t,a,r,n))}),t}},it={},st=class extends r{constructor(e){var t=1{a=w&&a!==u?a:N;this.options.missingKeyHandler?this.options.missingKeyHandler(e,s,t,a,x,r):this.backendConnector&&this.backendConnector.saveMissing&&this.backendConnector.saveMissing(e,s,t,a,x,r),this.emit("missingKey",e,s,t,u)};this.options.saveMissing&&(this.options.saveMissingPlurals&&g?t.forEach(t=>{var e=this.pluralResolver.getSuffixes(t,r);E&&r[`defaultValue${this.options.pluralSeparator}zero`]&&e.indexOf(this.options.pluralSeparator+"zero")<0&&e.push(this.options.pluralSeparator+"zero"),e.forEach(e=>{I([t],i+e,r["defaultValue"+e]||C)})}):I(t,i,C))}u=this.extendTranslation(u,a,r,c,n),t&&u===i&&this.options.appendNamespaceToMissingKey&&(u=s+":"+i),(t||e)&&this.options.parseMissingKeyHandler&&(u="v1"!==this.options.compatibilityAPI?this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?s+":"+i:i,e?u:void 0):this.options.parseMissingKeyHandler(u))}return e?(c.res=u,c.usedParams=this.getUsedParamsDetails(r),c):u}extendTranslation(a,r,n,o,i){var s=this;if(this.i18nFormat&&this.i18nFormat.parse)a=this.i18nFormat.parse(a,{...this.options.interpolation.defaultVariables,...n},n.lng||this.language||o.usedLng,o.usedNS,o.usedKey,{resolved:o});else if(!n.skipInterpolation){n.interpolation&&this.interpolator.init({...n,interpolation:{...this.options.interpolation,...n.interpolation}});var l="string"==typeof a&&(n&&n.interpolation&&void 0!==n.interpolation.skipOnVariables?n:this.options).interpolation.skipOnVariables;let e,t=(l&&(c=a.match(this.interpolator.nestingRegexp),e=c&&c.length),n.replace&&"string"!=typeof n.replace?n.replace:n);this.options.interpolation.defaultVariables&&(t={...this.options.interpolation.defaultVariables,...t}),a=this.interpolator.interpolate(a,t,n.lng||this.language,n),l&&(l=(c=a.match(this.interpolator.nestingRegexp))&&c.length,e{if(!this.isValidLookup(p)){t=this.extractFromKey(t,d);const s=t.key;r=s;let e=t.namespaces;this.options.fallbackNS&&(e=e.concat(this.options.fallbackNS));const l=void 0!==d.count&&"string"!=typeof d.count,c=l&&!d.ordinal&&0===d.count&&this.pluralResolver.shouldUseIntlApi(),u=void 0!==d.context&&("string"==typeof d.context||"number"==typeof d.context)&&""!==d.context,a=d.lngs||this.languageUtils.toResolveHierarchy(d.lng||this.language,d.fallbackLng);e.forEach(i=>{this.isValidLookup(p)||(n=i,!it[a[0]+"-"+i]&&this.utils&&this.utils.hasLoadedNamespace&&!this.utils.hasLoadedNamespace(n)&&(it[a[0]+"-"+i]=!0,this.logger.warn(`key "${r}" for languages "${a.join(", ")}" won't get resolved as namespace "${n}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!")),a.forEach(t=>{if(!this.isValidLookup(p)){m=t;var e,a=[s];if(this.i18nFormat&&this.i18nFormat.addLookupKeys)this.i18nFormat.addLookupKeys(a,s,t,i,d);else{let e;l&&(e=this.pluralResolver.getSuffix(t,d.count,d));var r,n=this.options.pluralSeparator+"zero",o=this.options.pluralSeparator+"ordinal"+this.options.pluralSeparator;l&&(a.push(s+e),d.ordinal&&0===e.indexOf(o)&&a.push(s+e.replace(o,this.options.pluralSeparator)),c)&&a.push(s+n),u&&(r=""+s+this.options.contextSeparator+d.context,a.push(r),l)&&(a.push(r+e),d.ordinal&&0===e.indexOf(o)&&a.push(r+e.replace(o,this.options.pluralSeparator)),c)&&a.push(r+n)}for(;e=a.pop();)this.isValidLookup(p)||(h=e,p=this.getResource(t,i,e,d))}}))})}}),{res:p,usedKey:r,exactUsedKey:h,usedLng:m,usedNS:n}}isValidLookup(e){return!(void 0===e||!this.options.returnNull&&null===e||!this.options.returnEmptyString&&""===e)}getResource(e,t,a){var r=3e.toLowerCase()):2===e.length?(e[0]=e[0].toLowerCase(),e[1]=e[1].toUpperCase(),-1{a||(e=this.formatLanguageCode(e),this.options.supportedLngs&&!this.isSupportedCode(e))||(a=e)}),!a&&this.options.supportedLngs&&e.forEach(e=>{if(!a){const t=this.getLanguagePartFromCode(e);if(this.isSupportedCode(t))return a=t;a=this.options.supportedLngs.find(e=>e===t||!(e.indexOf("-")<0&&t.indexOf("-")<0)&&(0{e&&(this.isSupportedCode(e)?a.push(e):this.logger.warn("rejecting language code not found in supportedLngs: "+e))};return"string"==typeof e&&(-1{a.indexOf(e)<0&&r(this.formatLanguageCode(e))}),a}},ut=[{lngs:["ach","ak","am","arn","br","fil","gun","ln","mfe","mg","mi","oc","pt","pt-BR","tg","tl","ti","tr","uz","wa"],nr:[1,2],fc:1},{lngs:["af","an","ast","az","bg","bn","ca","da","de","dev","el","en","eo","es","et","eu","fi","fo","fur","fy","gl","gu","ha","hi","hu","hy","ia","it","kk","kn","ku","lb","mai","ml","mn","mr","nah","nap","nb","ne","nl","nn","no","nso","pa","pap","pms","ps","pt-PT","rm","sco","se","si","so","son","sq","sv","sw","ta","te","tk","ur","yo"],nr:[1,2],fc:2},{lngs:["ay","bo","cgg","fa","ht","id","ja","jbo","ka","km","ko","ky","lo","ms","sah","su","th","tt","ug","vi","wo","zh"],nr:[1],fc:3},{lngs:["be","bs","cnr","dz","hr","ru","sr","uk"],nr:[1,2,5],fc:4},{lngs:["ar"],nr:[0,1,2,3,11,100],fc:5},{lngs:["cs","sk"],nr:[1,2,5],fc:6},{lngs:["csb","pl"],nr:[1,2,5],fc:7},{lngs:["cy"],nr:[1,2,3,8],fc:8},{lngs:["fr"],nr:[1,2],fc:9},{lngs:["ga"],nr:[1,2,3,7,11],fc:10},{lngs:["gd"],nr:[1,2,3,20],fc:11},{lngs:["is"],nr:[1,2],fc:12},{lngs:["jv"],nr:[0,1],fc:13},{lngs:["kw"],nr:[1,2,3,4],fc:14},{lngs:["lt"],nr:[1,2,10],fc:15},{lngs:["lv"],nr:[1,2,0],fc:16},{lngs:["mk"],nr:[1,2],fc:17},{lngs:["mnk"],nr:[0,1,2],fc:18},{lngs:["mt"],nr:[1,2,11,20],fc:19},{lngs:["or"],nr:[2,1],fc:2},{lngs:["ro"],nr:[1,2,20],fc:20},{lngs:["sl"],nr:[5,1,2,3],fc:21},{lngs:["he","iw"],nr:[1,2,20,21],fc:22}],dt={1:function(e){return Number(1{t.lngs.forEach(e=>{a[e]={numbers:t.nr,plurals:dt[t.fc]}})}),a}var gt=class{constructor(e){var t=1""+t+e)}getSuffixes(t){let a=1mt[e]-mt[t]).map(e=>""+this.options.prepend+(a.ordinal?"ordinal"+this.options.prepend:"")+e):e.numbers.map(e=>this.getSuffix(t,e,a)):[]}getSuffix(e,t){var a=2this.options.prepend&&a.toString()?this.options.prepend+a.toString():a.toString();return"v1"===this.options.compatibilityJSON?1===a?"":"number"==typeof a?"_plural_"+a.toString():r():"v2"===this.options.compatibilityJSON||this.options.simplifyPluralSuffix&&2===e.numbers.length&&1===e.numbers[0]?r():this.options.prepend&&t.toString()?this.options.prepend+t.toString():t.toString()}shouldUseIntlApi(){return!pt.includes(this.options.compatibilityJSON)}};function vt(e,t,a,r,n){var o,i,s,l=3e),this.init(e)}init(){var e=0e&&e.source===t?(e.lastIndex=0,e):new RegExp(t,"g");this.regexp=e(this.regexp,this.prefix+"(.+?)"+this.suffix),this.regexpUnescape=e(this.regexpUnescape,""+this.prefix+this.unescapePrefix+"(.+?)"+this.unescapeSuffix+this.suffix),this.nestingRegexp=e(this.nestingRegexp,this.nestingPrefix+"(.+?)"+this.nestingSuffix)}interpolate(r,a,n,o){let i,s,l;const c=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{};function t(e){return e.replace(/\$/g,"$$$$")}const u=e=>{var t;return e.indexOf(this.formatSeparator)<0?(t=vt(a,c,e,this.options.keySeparator,this.options.ignoreJSONStructure),this.alwaysFormat?this.format(t,void 0,n,{...o,...a,interpolationkey:e}):t):(e=(t=e.split(this.formatSeparator)).shift().trim(),t=t.join(this.formatSeparator).trim(),this.format(vt(a,c,e,this.options.keySeparator,this.options.ignoreJSONStructure),t,n,{...o,...a,interpolationkey:e}))},d=(this.resetRegExp(),o&&o.missingInterpolationHandler||this.options.missingInterpolationHandler),p=(o&&o.interpolation&&void 0!==o.interpolation.skipOnVariables?o:this.options).interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:e=>t(e)},{regex:this.regexp,safeValue:e=>this.escapeValue?t(this.escape(e)):t(e)}].forEach(e=>{for(l=0;i=e.regex.exec(r);){var t=i[1].trim();if(void 0===(s=u(t)))if("function"==typeof d){var a=d(r,i,o);s="string"==typeof a?a:""}else{if(!o||!Object.prototype.hasOwnProperty.call(o,t)){if(p){s=i[0];continue}this.logger.warn(`missed to pass in variable ${t} for interpolating `+r)}s=""}else"string"==typeof s||this.useRawValueToEscape||(s=Ve(s));a=e.safeValue(s);if(r=r.replace(i[0],a),p?(e.regex.lastIndex+=s.length,e.regex.lastIndex-=i[0].length):e.regex.lastIndex=0,++l>=this.maxReplaces)break}}),r}nest(a,r){let n=2e.trim()),o[1]=c.shift(),e=c,t=!0),(i=r(l.call(this,o[1].trim(),s),s))&&o[0]===a&&"string"!=typeof i)return i;(i="string"!=typeof i?Ve(i):i)||(this.logger.warn(`missed to resolve ${o[1]} for nesting `+a),i=""),t&&(i=e.reduce((e,t)=>this.format(e,t,n.lng,{...n,interpolationkey:o[1].trim()}),i.trim())),a=a.replace(o[0],i),this.regexp.lastIndex=0}return a}};function yt(e){let t=e.toLowerCase().trim();const a={};return-1{var t;e&&([e,...t]=e.split(":"),t=t.join(":").trim().replace(/^'+|'+$/g,""),a[e.trim()]||(a[e.trim()]=t),"false"===t&&(a[e.trim()]=!1),"true"===t&&(a[e.trim()]=!0),isNaN(t)||(a[e.trim()]=parseInt(t,10)))})),{formatName:t,formatOptions:a}}function o(o){const i={};return function(e,t,a){var r=t+JSON.stringify(a);let n=i[r];return n||(n=o(rt(t),a),i[r]=n),n(e)}}var St=class{constructor(){var e=0{const a=new Intl.NumberFormat(e,{...t});return e=>a.format(e)}),currency:o((e,t)=>{const a=new Intl.NumberFormat(e,{...t,style:"currency"});return e=>a.format(e)}),datetime:o((e,t)=>{const a=new Intl.DateTimeFormat(e,{...t});return e=>a.format(e)}),relativetime:o((e,t)=>{const a=new Intl.RelativeTimeFormat(e,{...t});return e=>a.format(e,t.range||"day")}),list:o((e,t)=>{const a=new Intl.ListFormat(e,{...t});return e=>a.format(e)})},this.init(e)}init(e){var t=(1{var{formatName:a,formatOptions:r}=yt(a);if(this.formats[a]){let e=t;try{var n=s&&s.formatParams&&s.formatParams[s.interpolationkey]||{},o=n.locale||n.lng||s.locale||s.lng||i;e=this.formats[a](t,o,{...r,...s,...n})}catch(e){this.logger.warn(e)}return e}return this.logger.warn("there was no format function for "+a),t},e)}};function kt(e,t){void 0!==e.pending[t]&&(delete e.pending[t],e.pendingCount--)}var wt=class extends r{constructor(e,t,a){var r=3{let r=!0;t.forEach(e=>{var t=a+"|"+e;!n.reload&&this.store.hasResourceBundle(a,e)?this.state[t]=2:this.state[t]<0||(1===this.state[t]?void 0===i[t]&&(i[t]=!0):(this.state[t]=1,r=!1,void 0===i[t]&&(i[t]=!0),void 0===o[t]&&(o[t]=!0),void 0===l[e]&&(l[e]=!0)))}),r||(s[a]=!0)}),(Object.keys(o).length||Object.keys(i).length)&&this.queue.push({pending:i,pendingCount:Object.keys(i).length,loaded:{},errors:[],callback:a}),{toLoad:Object.keys(o),pending:Object.keys(i),toLoadLanguages:Object.keys(s),toLoadNamespaces:Object.keys(l)}}loaded(e,t,a){var r=e.split("|");const n=r[0],o=r[1],i=(t&&this.emit("failedLoading",n,o,t),a&&this.store.addResourceBundle(n,o,a,void 0,void 0,{skipCopy:!0}),this.state[e]=t?-1:2,{});this.queue.forEach(a=>{Je(a.loaded,[n],o),kt(a,e),t&&a.errors.push(t),0!==a.pendingCount||a.done||(Object.keys(a.loaded).forEach(t=>{i[t]||(i[t]={});var e=a.loaded[t];e.length&&e.forEach(e=>{void 0===i[t][e]&&(i[t][e]=!0)})}),a.done=!0,a.errors.length?a.callback(a.errors):a.callback())}),this.emit("loaded",i),this.queue=this.queue.filter(e=>!e.done)}read(r,n,o){let i=3=this.maxParallelReads)this.waitingReads.push({lng:r,ns:n,fcName:o,tried:i,wait:s,callback:l});else{this.readingCalls++;const a=(e,t)=>{var a;this.readingCalls--,0{this.read.call(this,r,n,o,i+1,2*s,l)},s):l(e,t)};var e=this.backend[o].bind(this.backend);if(2!==e.length)return e(r,n,a);try{var t=e(r,n);t&&"function"==typeof t.then?t.then(e=>a(null,e)).catch(a):a(null,t)}catch(e){a(e)}}}prepareLoading(e,t){var a=2{this.loadOne(e)})}load(e,t,a){this.prepareLoading(e,t,{},a)}reload(e,t,a){this.prepareLoading(e,t,{reload:!0},a)}loadOne(a){let r=1{e&&this.logger.warn(`${r}loading namespace ${o} for language ${n} failed`,e),!e&&t&&this.logger.log(`${r}loaded namespace ${o} for language `+n,t),this.loaded(a,e,t)})}saveMissing(t,a,r,n,o){var i=5{};if(this.services.utils&&this.services.utils.hasLoadedNamespace&&!this.services.utils.hasLoadedNamespace(a))this.logger.warn(`did not save key "${r}" as the namespace "${a}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");else if(null!=r&&""!==r){if(this.backend&&this.backend.create){i={...i,isUpdate:o},o=this.backend.create.bind(this.backend);if(o.length<6)try{let e;(e=5===o.length?o(t,a,r,n,i):o(t,a,r,n))&&"function"==typeof e.then?e.then(e=>s(null,e)).catch(s):s(null,e)}catch(e){s(e)}else o(t,a,r,n,s,i)}t&&t[0]&&this.store.addResource(t[0],a,r,n)}}};function Et(){return{debug:!1,initImmediate:!0,ns:["translation"],defaultNS:["translation"],fallbackLng:["dev"],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:"all",preload:!1,simplifyPluralSuffix:!0,keySeparator:".",nsSeparator:":",pluralSeparator:"_",contextSeparator:"_",partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:"fallback",saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:function(e){let t={};if("object"==typeof e[1]&&(t=e[1]),"string"==typeof e[1]&&(t.defaultValue=e[1]),"string"==typeof e[2]&&(t.tDescription=e[2]),"object"==typeof e[2]||"object"==typeof e[3]){const a=e[3]||e[2];Object.keys(a).forEach(e=>{t[e]=a[e]})}return t},interpolation:{escapeValue:!0,format:e=>e,prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!0}}}function Ct(e){return"string"==typeof e.ns&&(e.ns=[e.ns]),"string"==typeof e.fallbackLng&&(e.fallbackLng=[e.fallbackLng]),"string"==typeof e.fallbackNS&&(e.fallbackNS=[e.fallbackNS]),e.supportedLngs&&e.supportedLngs.indexOf("cimode")<0&&(e.supportedLngs=e.supportedLngs.concat(["cimode"])),e}function Nt(){}function xt(t){Object.getOwnPropertyNames(Object.getPrototypeOf(t)).forEach(e=>{"function"==typeof t[e]&&(t[e]=t[e].bind(t))})}var It=class extends r{constructor(){let e=0{this.init(e,t)},0)}}init(){var n=this;let e=0{e.init&&e.init(this)})}this.format=this.options.interpolation.format,a=a||Nt,!this.options.fallbackLng||this.services.languageDetector||this.options.lng||0<(o=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng)).length&&"dev"!==o[0]&&(this.options.lng=o[0]),this.services.languageDetector||this.options.lng||this.logger.warn("init: no languageDetector is used and no lng is defined");["getResource","hasResourceBundle","getResourceBundle","getDataByLanguage"].forEach(e=>{this[e]=function(){return n.store[e](...arguments)}});["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(e=>{this[e]=function(){return n.store[e](...arguments),n}});const s=Fe();t=()=>{var e=(e,t)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn("init: i18next is already initialized. You should call init just once!"),this.isInitialized=!0,this.options.isClone||this.logger.log("initialized",this.options),this.emit("initialized",this.options),s.resolve(t),a(e,t)};if(this.languages&&"v1"!==this.options.compatibilityAPI&&!this.isInitialized)return e(null,this.t.bind(this));this.changeLanguage(this.options.lng,e)};return this.options.resources||!this.options.initImmediate?t():setTimeout(t,0),s}loadResources(e){let t=1{e&&"cimode"!==e&&this.services.languageUtils.toResolveHierarchy(e).forEach(e=>{"cimode"!==e&&r.indexOf(e)<0&&r.push(e)})};a?n(a):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(e=>n(e)),this.options.preload&&this.options.preload.forEach(e=>n(e)),this.services.backendConnector.load(r,this.options.ns,e=>{e||this.resolvedLanguage||!this.language||this.setResolvedLanguage(this.language),t(e)})}else t(null)}reloadResources(e,t,a){const r=Fe();return e=e||this.languages,t=t||this.options.ns,a=a||Nt,this.services.backendConnector.reload(e,t,e=>{r.resolve(),a(e)}),r}use(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(e.type)return"backend"===e.type&&(this.modules.backend=e),("logger"===e.type||e.log&&e.warn&&e.error)&&(this.modules.logger=e),"languageDetector"===e.type&&(this.modules.languageDetector=e),"i18nFormat"===e.type&&(this.modules.i18nFormat=e),"postProcessor"===e.type&&ot.addPostProcessor(e),"formatter"===e.type&&(this.modules.formatter=e),"3rdParty"===e.type&&this.modules.external.push(e),this;throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()")}setResolvedLanguage(e){if(e&&this.languages&&!(-1<["cimode","dev"].indexOf(e)))for(let e=0;e{this.language=e,this.languages=this.services.languageUtils.toResolveHierarchy(e),this.resolvedLanguage=void 0,this.setResolvedLanguage(e)}),s=(e,t)=>{t?(i(t),this.translator.changeLanguage(t),this.isLanguageChangingTo=void 0,this.emit("languageChanged",t),this.logger.log("languageChanged",t)):this.isLanguageChangingTo=void 0,o.resolve(function(){return n.t(...arguments)}),r&&r(e,function(){return n.t(...arguments)})};var e=e=>{const t="string"==typeof(e=a||e||!this.services.languageDetector?e:[])?e:this.services.languageUtils.getBestMatchFromCodes(e);t&&(this.language||i(t),this.translator.language||this.translator.changeLanguage(t),this.services.languageDetector)&&this.services.languageDetector.cacheUserLanguage&&this.services.languageDetector.cacheUserLanguage(t),this.loadResources(t,e=>{s(e,t)})};return a||!this.services.languageDetector||this.services.languageDetector.async?!a&&this.services.languageDetector&&this.services.languageDetector.async?0===this.services.languageDetector.detect.length?this.services.languageDetector.detect().then(e):this.services.languageDetector.detect(e):e(a):e(this.services.languageDetector.detect()),o}getFixedT(e,t,l){var c=this;function u(e,t){let a;if("object"!=typeof t){for(var r=arguments.length,n=new Array(2""+a.keyPrefix+i+e):a.keyPrefix?""+a.keyPrefix+i+e:e,c.t(s,a)}return"string"==typeof e?u.lng=e:u.lngs=e,u.ns=t,u.keyPrefix=l,u}t(){return this.translator&&this.translator.translate(...arguments)}exists(){return this.translator&&this.translator.exists(...arguments)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e){var t=1{e=this.services.backendConnector.state[e+"|"+t];return-1===e||2===e};if(t.precheck){t=t.precheck(this,o);if(void 0!==t)return t}return!!this.hasResourceBundle(a,e)||!(this.services.backendConnector.backend&&(!this.options.resources||this.options.partialBundledLanguages)&&(!o(a,e)||r&&!o(n,e)))}loadNamespaces(e,t){const a=Fe();return this.options.ns?((e="string"==typeof e?[e]:e).forEach(e=>{this.options.ns.indexOf(e)<0&&this.options.ns.push(e)}),this.loadResources(e=>{a.resolve(),t&&t(e)}),a):(t&&t(),Promise.resolve())}loadLanguages(e,t){const a=Fe(),r=this.options.preload||[];e=(e="string"==typeof e?[e]:e).filter(e=>r.indexOf(e)<0&&this.services.languageUtils.isSupportedCode(e));return e.length?(this.options.preload=r.concat(e),this.loadResources(e=>{a.resolve(),t&&t(e)}),a):(t&&t(),Promise.resolve())}dir(e){var t;return!(e=e||this.resolvedLanguage||(this.languages&&0{n[e]=this[e]}),n.services={...this.services},n.services.utils={hasLoadedNamespace:n.hasLoadedNamespace.bind(n)},a&&(n.store=new nt(this.store.data,r),n.services.resourceStore=n.store),n.translator=new st(n.services,r),n.translator.on("*",function(e){for(var t=arguments.length,a=new Array(1()=>{if(t.isInitialized)a();else{const e=()=>{setTimeout(()=>{t.off("initialized",e)},0),a()};t.on("initialized",e)}};function At(e,t,a){e.loadNamespaces(t,Tt(e,a))}function Pt(t,e,a,r){(a="string"==typeof a?[a]:a).forEach(e=>{t.options.ns.indexOf(e)<0&&t.options.ns.push(e)}),t.loadLanguages(e,Tt(t,r))}function Mt(a,e,t){let r=2{if(r.bindI18n&&-1{e=a.services.backendConnector.state[e+"|"+t];return-1===e||2===e},!(n.bindI18n&&-1",">":">","'":"'","'":"'",""":'"',""":'"'," ":" "," ":" ","©":"©","©":"©","®":"®","®":"®","…":"…","…":"…","/":"/","/":"/"},Dt=e=>jt[e],$t={bindI18n:"languageChanged",bindI18nStore:"",transEmptyNodeValue:"",transSupportBasicHtmlNodes:!0,transWrapTextNodes:"",transKeepBasicHtmlNodesFor:["br","strong","i","p"],useSuspense:!0,unescape:e=>e.replace(Rt,Dt)};var z={type:"3rdParty",init(e){!function(e){var t=0{this.usedNamespaces[e]||(this.usedNamespaces[e]=!0)})}getUsedNamespaces(){return Object.keys(this.usedNamespaces)}},k=t(b(),1),Bt=(e,t)=>{const a=(0,k.useRef)();return(0,k.useEffect)(()=>{a.current=t?a.current:e},[e,t]),a.current};function Ft(e,t,a,r){return e.getFixedT(t,a,r)}function Vt(e,t){let r=1"string"==typeof t?t:t&&"object"==typeof t&&"string"==typeof t.defaultValue?t.defaultValue:Array.isArray(e)?e[e.length-1]:e,{},!1]).t=n,o.i18n={},o.ready=!1,o;s.options.react&&void 0!==s.options.react.wait&&Ot("It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.");const l={...$t,...s.options.react,...r},{useSuspense:c,keyPrefix:u}=l;let d=e||i||s.options&&s.options.defaultNS;d="string"==typeof d?[d]:d||["translation"],s.reportNamespaces.addUsedNamespaces&&s.reportNamespaces.addUsedNamespaces(d);const p=(s.isInitialized||s.initializedStoreOnce)&&d.every(e=>Mt(e,s,l)),h=(n=s,o=r.lng||null,i="fallback"===l.nsMode?d:d[0],a=u,(0,k.useCallback)(Ft(n,o,i,a),[n,o,i,a])),m=()=>h,f=()=>Ft(s,r.lng||null,"fallback"===l.nsMode?d:d[0],u),[g,v]=(0,k.useState)(m);let b=d.join();r.lng&&(b=""+r.lng+b);const y=Bt(b),S=(0,k.useRef)(!0);(0,k.useEffect)(()=>{const{bindI18n:e,bindI18nStore:t}=l;function a(){S.current&&v(f)}return S.current=!0,p||c||(r.lng?Pt(s,r.lng,d,()=>{S.current&&v(f)}):At(s,d,()=>{S.current&&v(f)})),p&&y&&y!==b&&S.current&&v(f),e&&s&&s.on(e,a),t&&s&&s.store.on(t,a),()=>{S.current=!1,e&&s&&e.split(" ").forEach(e=>s.off(e,a)),t&&s&&t.split(" ").forEach(e=>s.store.off(e,a))}},[s,b]),(0,k.useEffect)(()=>{S.current&&p&&v(m)},[s,u,p]);n=[g,s,p];if(n.t=g,n.i18n=s,(n.ready=p)||!p&&!c)return n;throw new Promise(e=>{r.lng?Pt(s,r.lng,d,()=>e()):At(s,d,()=>e())})}var Ht=t(b(),1);function qt(i,e){let s=1(0,Ht.createElement)(a,Object.assign({},e,{forwardedRef:t}))):a}}t(b(),1),t(b(),1),t(b(),1);function Gt(e){return(Gt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function Kt(e){e=function(e,t){if("object"!==Gt(e)||null===e)return e;var a=e[Symbol.toPrimitive];if(void 0===a)return("string"===t?String:Number)(e);if("object"!==Gt(a=a.call(e,t||"default")))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}(e,"string");return"symbol"===Gt(e)?e:String(e)}function Jt(e,t){for(var a=0;a{t=localStorage.getItem(t);if(!t)return e;try{return JSON.parse(t)}catch(e){return t}}),Sa=e=>{const a={section:/^\s*\[\s*([^\]]*)\s*\]\s*$/,param:/^\s*([^=]+?)\s*=\s*(.*?)\s*$/,comment:/^\s*;.*$/},r={};e=e.split(/[\r\n]+/);let n=null;return e.forEach(function(e){var t;a.comment.test(e)||(a.param.test(e)?e.includes("xrdb")?(delete r[n??""],n=null):(t=e.match(a.param),n&&t&&(r[n][t[1]]=t[2].split(";")[0].trim())):a.section.test(e)?(t=e.match(a.section))&&(r[t[1]]={},n=t[1]):0==e.length&&(n=n&&null))}),r},ka=e=>{var t=document.querySelector("style.marketplaceSnippets"),t=(t&&t.remove(),document.createElement("style")),e=e.reduce((e,t)=>e=(e+=`/* ${t.title} - ${t.description} */ `)+t.code+` -`,"");t.innerHTML=e,t.classList.add("marketplaceSnippets"),document.body.appendChild(t)},wa=(e,t)=>{let a=[];return e&&0({name:e.name,url:Pa(e.url)})):a.push({name:t,url:"https://github.com/"+t}),a},Ea=e=>e?Object.keys(e).map(e=>({key:e,value:e})):[],Ca=e=>[{key:"stars",value:e("grid.sort.stars")},{key:"newest",value:e("grid.sort.newest")},{key:"oldest",value:e("grid.sort.oldest")},{key:"lastUpdated",value:e("grid.sort.lastUpdated")},{key:"mostStale",value:e("grid.sort.mostStale")},{key:"a-z",value:e("grid.sort.aToZ")},{key:"z-a",value:e("grid.sort.zToA")}],Na=(...e)=>{console.debug("Resetting Marketplace");const t=[];0===e.length&&Object.keys(localStorage).forEach(e=>{e.startsWith("marketplace:")&&t.push(e)}),e.forEach(e=>{switch(e){case"extensions":t.push(...C(w.installedExtensions,[])),t.push(w.installedExtensions);break;case"snippets":t.push(...C(w.installedSnippets,[])),t.push(w.installedSnippets);break;case"theme":t.push(...C(w.installedThemes,[])),t.push(w.installedThemes),t.push(w.themeInstalled);break;default:console.error("Unknown category: "+e)}}),t.forEach(e=>{localStorage.removeItem(e),console.debug("Removed "+e)}),console.debug("Marketplace has been reset"),location.reload()},xa=a=>{var e=document.querySelector("style.marketplaceCSS.marketplaceScheme");if(e&&e.remove(),a){e=document.createElement("style");e.classList.add("marketplaceCSS"),e.classList.add("marketplaceScheme");let t=":root {";Object.keys(a).forEach(e=>{t=(t+=`--spice-${e}: #${a[e]};`)+`--spice-rgb-${e}: ${(e=>{if(3===e.length)e=e.split("").map(e=>e+e).join("");else{if(6!=e.length)throw"Only 3- or 6-digit hex colours are allowed.";if(e.match(/[^0-9a-f]/i))throw"Only hex colours are allowed."}e=e.match(/.{1,2}/g);if(e&&3===e.length)return[parseInt(e[0],16),parseInt(e[1],16),parseInt(e[2],16)];throw"Could not parse hex colour."})(a[e])};`}),t+="}",e.innerHTML=t,document.body.appendChild(e)}},Ia=e=>{try{var t,a,r=document.querySelector("link[href='user.css']"),n=(r&&r.remove(),document.querySelector("style.marketplaceCSS.marketplaceUserCSS"));n&&n.remove(),e?((t=document.createElement("style")).classList.add("marketplaceCSS"),t.classList.add("marketplaceUserCSS"),t.innerHTML=e,document.body.appendChild(t)):((a=document.createElement("link")).setAttribute("rel","stylesheet"),a.setAttribute("href","user.css"),a.classList.add("userCSS"),document.body.appendChild(a))}catch(e){console.warn(e)}},La=async(e,t)=>{if(!e.cssURL)throw new Error("No CSS URL provided");t||=await async function(){for(const e of["net","xyz"])try{if("opaqueredirect"===(await fetch("https://cdn.jsdelivr."+e,{redirect:"manual",cache:"no-cache"})).type)return e}catch(e){console.error(e);continue}}();var t=(e=>{const t=new URL(e);return t.host,t.host==="raw.githubusercontent.com"})(e.cssURL)?`https://cdn.jsdelivr.${t}/gh/${e.user}/${e.repo}@${e.branch}/`+e.manifest.usercss:e.cssURL,a=t.replace("/user.css","/assets/");console.debug("Parsing CSS: ",t);let r=await fetch(t+"?time="+Date.now()).then(e=>e.text());for(const i of r.matchAll(/url\(['|"](?.+?)['|"]\)/gm)||[]){var n,o=i?.groups?.path;!o||o.startsWith("http")||o.startsWith("data")||(n=a+o.replace(/\.\//g,""),r=r.replace(o,n))}return r};function Oa(e,r){e&&e.forEach(e=>{var t=r||e.user+"-"+e.repo,a=window.sessionStorage.getItem(t),a=a?JSON.parse(a):[];a.push(e),window.sessionStorage.setItem(t,JSON.stringify(a))})}async function Ta(e,t,a){try{var r={text:e,context:t+"/"+a,mode:"gfm"},n=await fetch("https://api.github.com/markdown",{method:"POST",body:JSON.stringify(r)});if(n.ok)return await n.text();throw Spicetify.showNotification(y("notifications.markdownParsingError",{status:n.status}),!0)}catch(e){return null}}function Aa(e){var t="snippet"===e.type?"snippet:":`${e.item.user}/${e.item.repo}/`;let a;switch(e.type){case"snippet":a=e.item.title.replaceAll(" ","-");break;case"theme":a=e.item.manifest?.usercss||"";break;case"extension":a=e.item.manifest?.main||"";break;case"app":a=e.item.manifest?.name?.replaceAll(" ","-")||""}return"marketplace:installed:"+t+a}var Pa=e=>{var t=decodeURI(e).trim().toLowerCase();return t.startsWith("javascript:")||t.startsWith("data:")||t.startsWith("vbscript:")?"about:blank":e},_a=(e,t)=>{e=e.title||e?.manifest?.name||"",t=t.title||t?.manifest?.name||"";return e.localeCompare(t)},Ra=(e,t)=>{return void 0===e.created||void 0===t.created?0:(e=new Date(e.created),new Date(t.created).getTime()-e.getTime())},Ma=(e,t)=>{return void 0===e.lastUpdated||void 0===t.lastUpdated?0:(e=new Date(e.lastUpdated),new Date(t.lastUpdated).getTime()-e.getTime())},ja=(e,t)=>{switch(t){case"a-z":e.sort((e,t)=>_a(e,t));break;case"z-a":e.sort((e,t)=>_a(t,e));break;case"newest":e.sort((e,t)=>Ra(e,t));break;case"oldest":e.sort((e,t)=>Ra(t,e));break;case"lastUpdated":e.sort((e,t)=>Ma(e,t));break;case"mostStale":e.sort((e,t)=>Ma(t,e));break;default:e.sort((e,t)=>t.stars-e.stars)}};var c=t(b()),f=t(b()),$a=t(_e()),Da=t(Re()),za=(i=Prism,a=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/,i.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+a.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+a.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+a.source+"$"),alias:"url"}}},selector:{pattern:RegExp(`(^|[{}\\s])[^{}\\s](?:[^{};"'\\s]|\\s+(?![\\s{])|`+a.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:a,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},i.languages.css.atrule.inside.rest=i.languages.css,(a=i.languages.markup)&&(a.tag.addInlined("style","css"),a.tag.addAttribute("style","css")),t(b())),Ua="button-module__button___hf2qg_marketplace",Fa="button-module__circle___EZ88P_marketplace",g=e=>{var t=e.type||"round",a=[Ua];return"circle"===t&&a.push(Fa),e.classes&&a.push(...e.classes),za.default.createElement("button",{className:a.join(" "),onClick:e.onClick,"aria-label":e.label||"",disabled:e.disabled},e.children)},Ba=r=>{var e="marketplace-customCSS-preview";const[n,t]=f.default.useState("ADD_SNIPPET"!==r.type&&r.content?.item.code||""),[a,o]=f.default.useState("ADD_SNIPPET"!==r.type&&r.content?.item.title||""),[i,s]=f.default.useState("ADD_SNIPPET"!==r.type&&r.content?.item.description||""),[l,c]=f.default.useState("ADD_SNIPPET"!==r.type&&r.content?.item.imageURL||""),u=()=>a.replace(/\n/g,"").replaceAll(" ","-");const d="marketplace:installed:snippet:"+u(),[p,h]=f.default.useState(!!C(d));let m;return f.default.createElement("div",{id:"marketplace-add-snippet-container"},f.default.createElement("div",{className:"marketplace-customCSS-input-container"},f.default.createElement("label",{htmlFor:"marketplace-custom-css"},y("snippets.customCSS")),f.default.createElement("div",{className:"marketplace-code-editor-wrapper marketplace-code-editor"},f.default.createElement($a.default,{value:n,onValueChange:e=>t(e),highlight:e=>(0,Da.highlight)(e,Da.languages.css),textareaId:"marketplace-custom-css",textareaClassName:"snippet-code-editor",readOnly:"VIEW_SNIPPET"===r.type,placeholder:y("snippets.customCSSPlaceholder"),style:{}}))),f.default.createElement("div",{className:"marketplace-customCSS-input-container"},f.default.createElement("label",{htmlFor:"marketplace-customCSS-name-submit"},y("snippets.snippetName")),f.default.createElement("input",{id:"marketplace-customCSS-name-submit",className:"marketplace-code-editor",value:a,onChange:e=>{"VIEW_SNIPPET"!==r.type&&o(e.target.value)},placeholder:y("snippets.snippetNamePlaceholder")})),f.default.createElement("div",{className:"marketplace-customCSS-input-container"},f.default.createElement("label",{htmlFor:"marketplace-customCSS-description-submit"},y("snippets.snippetDesc")),f.default.createElement("input",{id:"marketplace-customCSS-description-submit",className:"marketplace-code-editor",value:i,onChange:e=>{"VIEW_SNIPPET"!==r.type&&s(e.target.value)},placeholder:y("snippets.snippetDescPlaceholder")})),f.default.createElement("div",{className:"marketplace-customCSS-input-container"},f.default.createElement("label",{htmlFor:e},y("snippets.snippetPreview")," ","VIEW_SNIPPET"!==r.type&&`(${y("snippets.optional")})`),l&&f.default.createElement("label",{htmlFor:e,style:{textAlign:"center"}},f.default.createElement("img",{className:"marketplace-customCSS-image-preview",src:l,alt:"Preview"}))),"VIEW_SNIPPET"!==r.type&&f.default.createElement(f.default.Fragment,null,f.default.createElement(g,{onClick:()=>{m.click()}},l.length?y("snippets.changeImage"):y("snippets.addImage"),f.default.createElement("input",{id:e,type:"file",style:{display:"none"},ref:e=>m=e,onChange:async e=>{if(e.target.files?.[0])try{r=e.target.files?.[0];var t=await new Promise((e,t)=>{const a=new FileReader;a.readAsDataURL(r),a.onload=()=>{e(a.result)},a.onerror=e=>{t(e)}});t&&c(t)}catch(e){console.error(e)}var r}})),f.default.createElement(g,{onClick:()=>{var e,t=u(),a=i.trim();p&&"EDIT_SNIPPET"!==r.type?Spicetify.showNotification(y("snippets.duplicateName"),!0):(console.debug("Installing snippet: "+t),r.content&&r.content.item.title!==t&&(console.debug("Deleting outdated snippet: "+r.content.item.title),localStorage.removeItem("marketplace:installed:snippet:"+r.content.item.title),e=C(w.installedSnippets,[]).filter(e=>e!=="marketplace:installed:snippet:"+r.content?.item.title),localStorage.setItem(w.installedSnippets,JSON.stringify(e))),localStorage.setItem(d,JSON.stringify({title:t,code:n,description:a,imageURL:l,custom:!0})),-1===(e=C(w.installedSnippets,[])).indexOf(d)&&(e.push(d),localStorage.setItem(w.installedSnippets,JSON.stringify(e))),t=e.map(e=>C(e)),ka(t),Spicetify.PopupModal.hide(),"EDIT_SNIPPET"===r.type&&location.reload())},disabled:!u()||!n.replace(/\n/g,"\\n")},y("snippets.saveCSS"))),"VIEW_SNIPPET"===r.type&&f.default.createElement(g,{onClick:()=>{r.callback&&r.callback(),h(!p)}},p?y("remove"):y("install")))},Va=t(b()),Ha=()=>Va.default.createElement("div",{id:"marketplace-reload-container"},Va.default.createElement("p",null,y("reloadModal.description")),Va.default.createElement("div",{className:"marketplace-reload-modal__button-container"},Va.default.createElement(g,{onClick:()=>{Spicetify.PopupModal.hide(),location.reload()}},y("reloadModal.reloadNow")),Va.default.createElement(g,{onClick:()=>{Spicetify.PopupModal.hide()}},y("reloadModal.reloadLater")))),u=t(b()),d=t(b()),qa=t(b()),Ga="toggle-module__toggle-wrapper___ocE5z_marketplace",Ka="toggle-module__disabled___OYAYf_marketplace",Ja="toggle-module__toggle-input___ceLM4_marketplace",Wa="toggle-module__toggle-indicator-wrapper___6Lcp0_marketplace",Xa="toggle-module__toggle-indicator___nCxwE_marketplace",Za=e=>{var t="toggle:"+e.storageKey,a=[Ga];return!1===e.clickable&&a.push(Ka),qa.default.createElement("label",{className:a.join(" ")},qa.default.createElement("input",{className:Ja,type:"checkbox",checked:e.enabled,"data-storage-key":e.storageKey,id:t,title:"Toggle for "+e.storageKey,onChange:e.onChange}),qa.default.createElement("span",{className:Wa},qa.default.createElement("span",{className:Xa})))},Ya=t(b()),Qa=t(e()),er=t=>{var e=t.sortBoxOptions.map(e=>({value:e.key,label:e.value})),a=t.sortBoxOptions.find(t.sortBySelectedFn);return Ya.default.createElement("div",{className:"marketplace-sortBox"},Ya.default.createElement("div",{className:"marketplace-sortBox-header"},Ya.default.createElement("div",{className:"marketplace-sortBox-header-title"}),Ya.default.createElement(Qa.default,{placeholder:"Select an option",options:e,value:a?.key,onChange:e=>{t.onChange(e.value)}})))},tr=t(b()),ar=()=>tr.default.createElement("svg",{role:"img",height:"16",width:"16",className:"Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4",viewBox:"0 0 16 16"},tr.default.createElement("path",{d:"M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z"}),tr.default.createElement("path",{d:"M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z"})),rr=window.Spicetify,p=a=>{var e=a.type,t="dropdown"===e?"dropdown:"+a.storageKey:"toggle:"+a.storageKey,r=!!a.modalConfig.visual[a.storageKey];return void 0!==a.description&&null!==a.description||(a.description=""),"dropdown"===e&&a.options?d.default.createElement("div",{className:"settings-row"},d.default.createElement("label",{htmlFor:t,className:"col description"},a.name),d.default.createElement("div",{className:"col action"},d.default.createElement(er,{sortBoxOptions:a.options.map(e=>({key:e,value:e})),onChange:e=>{return e=e,t=a.storageKey,a.modalConfig.visual[t]=e,localStorage.setItem("marketplace:"+t,String(e)),void a.updateConfig(a.modalConfig);var t},sortBySelectedFn:e=>e.key==a.modalConfig.visual[a.storageKey]}),d.default.createElement(rr.ReactComponent.TooltipWrapper,{label:d.default.createElement(d.default.Fragment,null,a.description.split("\n").map(e=>d.default.createElement(d.default.Fragment,null,e,d.default.createElement("br",null)))),renderInline:!0,showDelay:10,placement:"top",labelClassName:"marketplace-settings-tooltip",disabled:!1},d.default.createElement("div",{className:"marketplace-tooltip-icon"},d.default.createElement(ar,null))))):d.default.createElement("div",{className:"settings-row"},d.default.createElement("label",{htmlFor:t,className:"col description"},a.name),d.default.createElement("div",{className:"col action"},d.default.createElement(Za,{name:a.name,storageKey:a.storageKey,enabled:r,onChange:e=>{var t=e.target.checked,e=e.target.dataset.storageKey;a.modalConfig.visual[e]=t,console.debug(`toggling ${e} to `+t),localStorage.setItem("marketplace:"+e,String(t)),a.updateConfig(a.modalConfig)}})))},h=t(b()),nr=r=>{var e="toggle:"+r.name;const t=r.modalConfig.tabs.reduce((e,t,a)=>t.name===r.name?a:e,-1);var a=r.modalConfig.tabs[t]["enabled"];function n(e,t){var t=e+t,a=r.modalConfig.tabs[t];r.modalConfig.tabs[t]=r.modalConfig.tabs[e],r.modalConfig.tabs[e]=a,localStorage.setItem(w.tabs,JSON.stringify(r.modalConfig.tabs)),r.updateConfig(r.modalConfig)}return h.default.createElement("div",{className:"settings-row"},h.default.createElement("label",{htmlFor:e,className:"col description"},y("tabs."+r.name)),h.default.createElement("div",{className:"col action"},h.default.createElement("button",{title:"Move up",className:"arrow-btn",disabled:0===t,onClick:()=>n(t,-1)},h.default.createElement("svg",{height:"16",width:"16",viewBox:"0 0 16 16",fill:"currentColor",dangerouslySetInnerHTML:{__html:String(Spicetify.SVGIcons["chart-up"])}})),h.default.createElement("button",{title:"Move down",className:"arrow-btn",disabled:t===r.modalConfig.tabs.length-1,onClick:()=>n(t,1)},h.default.createElement("svg",{height:"16",width:"16",viewBox:"0 0 16 16",fill:"currentColor",dangerouslySetInnerHTML:{__html:String(Spicetify.SVGIcons["chart-down"])}})),h.default.createElement(Za,{name:r.name,storageKey:"tab:"+r.name,clickable:"Extensions"!==r.name,enabled:a,onChange:e=>{r.modalConfig.tabs[t].enabled=e.target.checked,localStorage.setItem(w.tabs,JSON.stringify(r.modalConfig.tabs)),r.updateConfig(r.modalConfig)}})))},or=async()=>{const e=new MutationObserver(async()=>{var t;document.querySelector(".GenericModal[aria-label='Settings']")||(t=100,await new Promise(e=>setTimeout(e,t)),N("BACKUP"),e.disconnect())});e.observe(document.body,{childList:!0,subtree:!0}),Spicetify.PopupModal.hide()},ir=({CONFIG:e,updateAppConfig:t})=>{const[a,r]=u.default.useState({...e}),[n,o]=u.default.useState(y("settings.versionBtn")),i=e=>{t({...e}),r({...e})};e=document.querySelector("body > generic-modal button.main-trackCreditsModal-closeBtn");const s=document.querySelector("body > generic-modal > div");e&&s&&(e.onclick=()=>location.reload(),e.setAttribute("style","cursor: pointer;"),s.onclick=e=>{e.target===s&&location.reload()});e=C(w.albumArtBasedColor)?u.default.createElement(u.default.Fragment,null,u.default.createElement(p,{name:y("settings.albumArtBasedColorsMode"),storageKey:"albumArtBasedColorsMode",modalConfig:a,updateConfig:i,type:"dropdown",options:["monochromeDark","monochromeLight","analogicComplement","analogic","triad","quad"],description:y("settings.almbumArtColorsModeToolTip")}),u.default.createElement(p,{name:y("settings.albumArtBasedColorsVibrancy"),storageKey:"albumArtBasedColorsVibrancy",modalConfig:a,updateConfig:i,type:"dropdown",options:["desaturated","lightVibrant","prominent","vibrant"],description:y("settings.albumArtBasedColorsVibrancyToolTip")})):null;return u.default.createElement("div",{id:"marketplace-config-container"},u.default.createElement("h2",{className:"settings-heading"},y("settings.optionsHeading")),u.default.createElement(p,{name:y("settings.starCountLabel"),storageKey:"stars",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.tagsLabel"),storageKey:"tags",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.showArchived"),storageKey:"showArchived",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.devToolsLabel"),storageKey:"themeDevTools",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.hideInstalledLabel"),storageKey:"hideInstalled",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.colourShiftLabel"),storageKey:"colorShift",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.albumArtBasedColors"),storageKey:"albumArtBasedColors",modalConfig:a,updateConfig:i}),e,u.default.createElement("h2",{className:"settings-heading"},y("settings.tabsHeading")),u.default.createElement("div",{className:"tabs-container"},a.tabs.map(({name:e},t)=>u.default.createElement(nr,{key:t,name:e,modalConfig:a,updateConfig:i}))),u.default.createElement("h2",{className:"settings-heading"},y("settings.resetHeading")),u.default.createElement("div",{className:"settings-row"},u.default.createElement("label",{className:"col description"},y("settings.resetDescription")),u.default.createElement("div",{className:"col action"},u.default.createElement(g,{onClick:()=>Na()},y("settings.resetBtn")))),u.default.createElement("h2",{className:"settings-heading"},y("settings.backupHeading")),u.default.createElement("div",{className:"settings-row"},u.default.createElement("label",{className:"col description"},y("settings.backupLabel")),u.default.createElement("div",{className:"col action"},u.default.createElement(g,{onClick:or},y("settings.backupBtn")))),u.default.createElement("h2",null,y("settings.versionHeading")),u.default.createElement("div",{className:"setting-row"},u.default.createElement("label",{className:"col description"},y("grid.spicetifyMarketplace")," ",ma),u.default.createElement("div",{className:"col action"},u.default.createElement(g,{onClick:()=>{Spicetify.Platform.ClipboardAPI.copy(ma),o(y("settings.versionCopied")),setTimeout(()=>o(y("settings.versionBtn")),3e3)}},n))))},m=t(b()),sr=t(_e()),lr=t(Re()),cr=(Prism.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0},section:{pattern:/(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,lookbehind:!0,inside:{"section-name":{pattern:/(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,lookbehind:!0,alias:"selector"},punctuation:/\[|\]/}},key:{pattern:/(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,lookbehind:!0,alias:"attr-value",inside:{"inner-value":{pattern:/^("|').+(?=\1$)/,lookbehind:!0}}},punctuation:/=/},localStorage.getItem(w.themeInstalled)),ur=cr?C(cr):null,dr=()=>{const[a,t]=m.default.useState(ur?(e=>{let t="";for(const a in e)if(Object.prototype.hasOwnProperty.call(e,a))if("object"==typeof e[a]){t+=`[${a}] +`,"");t.innerHTML=e,t.classList.add("marketplaceSnippets"),document.body.appendChild(t)},wa=(e,t)=>{let a=[];return e&&0({name:e.name,url:Pa(e.url)})):a.push({name:t,url:"https://github.com/"+t}),a},Ea=e=>e?Object.keys(e).map(e=>({key:e,value:e})):[],Ca=e=>[{key:"stars",value:e("grid.sort.stars")},{key:"newest",value:e("grid.sort.newest")},{key:"oldest",value:e("grid.sort.oldest")},{key:"lastUpdated",value:e("grid.sort.lastUpdated")},{key:"mostStale",value:e("grid.sort.mostStale")},{key:"a-z",value:e("grid.sort.aToZ")},{key:"z-a",value:e("grid.sort.zToA")}],Na=(...e)=>{console.debug("Resetting Marketplace");const t=[];0===e.length&&Object.keys(localStorage).forEach(e=>{e.startsWith("marketplace:")&&t.push(e)}),e.forEach(e=>{switch(e){case"extensions":t.push(...C(w.installedExtensions,[])),t.push(w.installedExtensions);break;case"snippets":t.push(...C(w.installedSnippets,[])),t.push(w.installedSnippets);break;case"theme":t.push(...C(w.installedThemes,[])),t.push(w.installedThemes),t.push(w.themeInstalled);break;default:console.error("Unknown category: "+e)}}),t.forEach(e=>{localStorage.removeItem(e),console.debug("Removed "+e)}),console.debug("Marketplace has been reset"),location.reload()},xa=a=>{var e=document.querySelector("style.marketplaceCSS.marketplaceScheme");if(e&&e.remove(),a){e=document.createElement("style");e.classList.add("marketplaceCSS"),e.classList.add("marketplaceScheme");let t=":root {";Object.keys(a).forEach(e=>{t=(t+=`--spice-${e}: #${a[e]};`)+`--spice-rgb-${e}: ${(e=>{if(3===e.length)e=e.split("").map(e=>e+e).join("");else{if(6!=e.length)throw"Only 3- or 6-digit hex colours are allowed.";if(e.match(/[^0-9a-f]/i))throw"Only hex colours are allowed."}e=e.match(/.{1,2}/g);if(e&&3===e.length)return[parseInt(e[0],16),parseInt(e[1],16),parseInt(e[2],16)];throw"Could not parse hex colour."})(a[e])};`}),t+="}",e.innerHTML=t,document.body.appendChild(e)}},Ia=e=>{try{var t,a,r=document.querySelector("link[href='user.css']"),n=(r&&r.remove(),document.querySelector("style.marketplaceCSS.marketplaceUserCSS"));n&&n.remove(),e?((t=document.createElement("style")).classList.add("marketplaceCSS"),t.classList.add("marketplaceUserCSS"),t.innerHTML=e,document.body.appendChild(t)):((a=document.createElement("link")).setAttribute("rel","stylesheet"),a.setAttribute("href","user.css"),a.classList.add("userCSS"),document.body.appendChild(a))}catch(e){console.warn(e)}},La=async(e,t)=>{if(!e.cssURL)throw new Error("No CSS URL provided");t||=await async function(){for(const e of["net","xyz"])try{if("opaqueredirect"===(await fetch("https://cdn.jsdelivr."+e,{redirect:"manual",cache:"no-cache"})).type)return e}catch(e){console.error(e);continue}}();var t=(e=>{const t=new URL(e);return t.host,t.host==="raw.githubusercontent.com"})(e.cssURL)?`https://cdn.jsdelivr.${t}/gh/${e.user}/${e.repo}@${e.branch}/`+e.manifest.usercss:e.cssURL,a=t.replace("/user.css","/assets/");console.debug("Parsing CSS: ",t);let r=await fetch(t+"?time="+Date.now()).then(e=>e.text());for(const i of r.matchAll(/url\(['|"](?.+?)['|"]\)/gm)||[]){var n,o=i?.groups?.path;!o||o.startsWith("http")||o.startsWith("data")||(n=a+o.replace(/\.\//g,""),r=r.replace(o,n))}return r};function Oa(e,r){e&&e.forEach(e=>{var t=r||e.user+"-"+e.repo,a=window.sessionStorage.getItem(t),a=a?JSON.parse(a):[];a.push(e),window.sessionStorage.setItem(t,JSON.stringify(a))})}async function Ta(e,t,a){try{var r={text:e,context:t+"/"+a,mode:"gfm"},n=await fetch("https://api.github.com/markdown",{method:"POST",body:JSON.stringify(r)});if(n.ok)return await n.text();throw Spicetify.showNotification(y("notifications.markdownParsingError",{status:n.status}),!0)}catch(e){return null}}function Aa(e){var t="snippet"===e.type?"snippet:":`${e.item.user}/${e.item.repo}/`;let a;switch(e.type){case"snippet":a=e.item.title.replaceAll(" ","-");break;case"theme":a=e.item.manifest?.usercss||"";break;case"extension":a=e.item.manifest?.main||"";break;case"app":a=e.item.manifest?.name?.replaceAll(" ","-")||""}return"marketplace:installed:"+t+a}var Pa=e=>{var t=decodeURI(e).trim().toLowerCase();return t.startsWith("javascript:")||t.startsWith("data:")||t.startsWith("vbscript:")?"about:blank":e},Ma=(e,t)=>{e=e.title||e?.manifest?.name||"",t=t.title||t?.manifest?.name||"";return e.localeCompare(t)},_a=(e,t)=>{return void 0===e.created||void 0===t.created?0:(e=new Date(e.created),new Date(t.created).getTime()-e.getTime())},Ra=(e,t)=>{return void 0===e.lastUpdated||void 0===t.lastUpdated?0:(e=new Date(e.lastUpdated),new Date(t.lastUpdated).getTime()-e.getTime())},ja=(e,t)=>{switch(t){case"a-z":e.sort((e,t)=>Ma(e,t));break;case"z-a":e.sort((e,t)=>Ma(t,e));break;case"newest":e.sort((e,t)=>_a(e,t));break;case"oldest":e.sort((e,t)=>_a(t,e));break;case"lastUpdated":e.sort((e,t)=>Ra(e,t));break;case"mostStale":e.sort((e,t)=>Ra(t,e));break;default:e.sort((e,t)=>t.stars-e.stars)}};var c=t(b()),f=t(b()),Da=t(Me()),$a=t(_e()),za=(i=Prism,a=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/,i.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+a.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+a.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+a.source+"$"),alias:"url"}}},selector:{pattern:RegExp(`(^|[{}\\s])[^{}\\s](?:[^{};"'\\s]|\\s+(?![\\s{])|`+a.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:a,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},i.languages.css.atrule.inside.rest=i.languages.css,(a=i.languages.markup)&&(a.tag.addInlined("style","css"),a.tag.addAttribute("style","css")),t(b())),Ua="button-module__button___hf2qg_marketplace",Ba="button-module__circle___EZ88P_marketplace",g=e=>{var t=e.type||"round",a=[Ua];return"circle"===t&&a.push(Ba),e.classes&&a.push(...e.classes),za.default.createElement("button",{className:a.join(" "),onClick:e.onClick,"aria-label":e.label||"",disabled:e.disabled},e.children)},Fa=r=>{var e="marketplace-customCSS-preview";const[n,t]=f.default.useState("ADD_SNIPPET"!==r.type&&r.content?.item.code||""),[a,o]=f.default.useState("ADD_SNIPPET"!==r.type&&r.content?.item.title||""),[i,s]=f.default.useState("ADD_SNIPPET"!==r.type&&r.content?.item.description||""),[l,c]=f.default.useState("ADD_SNIPPET"!==r.type&&r.content?.item.imageURL||""),u=()=>a.replace(/\n/g,"").replaceAll(" ","-");const d="marketplace:installed:snippet:"+u(),[p,h]=f.default.useState(!!C(d));let m;return f.default.createElement("div",{id:"marketplace-add-snippet-container"},f.default.createElement("div",{className:"marketplace-customCSS-input-container"},f.default.createElement("label",{htmlFor:"marketplace-custom-css"},y("snippets.customCSS")),f.default.createElement("div",{className:"marketplace-code-editor-wrapper marketplace-code-editor"},f.default.createElement(Da.default,{value:n,onValueChange:e=>t(e),highlight:e=>(0,$a.highlight)(e,$a.languages.css),textareaId:"marketplace-custom-css",textareaClassName:"snippet-code-editor",readOnly:"VIEW_SNIPPET"===r.type,placeholder:y("snippets.customCSSPlaceholder"),style:{}}))),f.default.createElement("div",{className:"marketplace-customCSS-input-container"},f.default.createElement("label",{htmlFor:"marketplace-customCSS-name-submit"},y("snippets.snippetName")),f.default.createElement("input",{id:"marketplace-customCSS-name-submit",className:"marketplace-code-editor",value:a,onChange:e=>{"VIEW_SNIPPET"!==r.type&&o(e.target.value)},placeholder:y("snippets.snippetNamePlaceholder")})),f.default.createElement("div",{className:"marketplace-customCSS-input-container"},f.default.createElement("label",{htmlFor:"marketplace-customCSS-description-submit"},y("snippets.snippetDesc")),f.default.createElement("input",{id:"marketplace-customCSS-description-submit",className:"marketplace-code-editor",value:i,onChange:e=>{"VIEW_SNIPPET"!==r.type&&s(e.target.value)},placeholder:y("snippets.snippetDescPlaceholder")})),f.default.createElement("div",{className:"marketplace-customCSS-input-container"},f.default.createElement("label",{htmlFor:e},y("snippets.snippetPreview")," ","VIEW_SNIPPET"!==r.type&&`(${y("snippets.optional")})`),l&&f.default.createElement("label",{htmlFor:e,style:{textAlign:"center"}},f.default.createElement("img",{className:"marketplace-customCSS-image-preview",src:l,alt:"Preview"}))),"VIEW_SNIPPET"!==r.type&&f.default.createElement(f.default.Fragment,null,f.default.createElement(g,{onClick:()=>{m.click()}},l.length?y("snippets.changeImage"):y("snippets.addImage"),f.default.createElement("input",{id:e,type:"file",style:{display:"none"},ref:e=>m=e,onChange:async e=>{if(e.target.files?.[0])try{r=e.target.files?.[0];var t=await new Promise((e,t)=>{const a=new FileReader;a.readAsDataURL(r),a.onload=()=>{e(a.result)},a.onerror=e=>{t(e)}});t&&c(t)}catch(e){console.error(e)}var r}})),f.default.createElement(g,{onClick:()=>{var e,t=u(),a=i.trim();p&&"EDIT_SNIPPET"!==r.type?Spicetify.showNotification(y("snippets.duplicateName"),!0):(console.debug("Installing snippet: "+t),r.content&&r.content.item.title!==t&&(console.debug("Deleting outdated snippet: "+r.content.item.title),localStorage.removeItem("marketplace:installed:snippet:"+r.content.item.title),e=C(w.installedSnippets,[]).filter(e=>e!=="marketplace:installed:snippet:"+r.content?.item.title),localStorage.setItem(w.installedSnippets,JSON.stringify(e))),localStorage.setItem(d,JSON.stringify({title:t,code:n,description:a,imageURL:l,custom:!0})),-1===(e=C(w.installedSnippets,[])).indexOf(d)&&(e.push(d),localStorage.setItem(w.installedSnippets,JSON.stringify(e))),t=e.map(e=>C(e)),ka(t),Spicetify.PopupModal.hide(),"EDIT_SNIPPET"===r.type&&location.reload())},disabled:!u()||!n.replace(/\n/g,"\\n")},y("snippets.saveCSS"))),"VIEW_SNIPPET"===r.type&&f.default.createElement(g,{onClick:()=>{r.callback&&r.callback(),h(!p)}},p?y("remove"):y("install")))},Va=t(b()),Ha=()=>Va.default.createElement("div",{id:"marketplace-reload-container"},Va.default.createElement("p",null,y("reloadModal.description")),Va.default.createElement("div",{className:"marketplace-reload-modal__button-container"},Va.default.createElement(g,{onClick:()=>{Spicetify.PopupModal.hide(),location.reload()}},y("reloadModal.reloadNow")),Va.default.createElement(g,{onClick:()=>{Spicetify.PopupModal.hide()}},y("reloadModal.reloadLater")))),u=t(b()),d=t(b()),qa=t(b()),Ga="toggle-module__toggle-wrapper___ocE5z_marketplace",Ka="toggle-module__disabled___OYAYf_marketplace",Ja="toggle-module__toggle-input___ceLM4_marketplace",Wa="toggle-module__toggle-indicator-wrapper___6Lcp0_marketplace",Za="toggle-module__toggle-indicator___nCxwE_marketplace",Xa=e=>{var t="toggle:"+e.storageKey,a=[Ga];return!1===e.clickable&&a.push(Ka),qa.default.createElement("label",{className:a.join(" ")},qa.default.createElement("input",{className:Ja,type:"checkbox",checked:e.enabled,"data-storage-key":e.storageKey,id:t,title:"Toggle for "+e.storageKey,onChange:e.onChange}),qa.default.createElement("span",{className:Wa},qa.default.createElement("span",{className:Za})))},Ya=t(b()),Qa=t(e()),er=t=>{var e=t.sortBoxOptions.map(e=>({value:e.key,label:e.value})),a=t.sortBoxOptions.find(t.sortBySelectedFn);return Ya.default.createElement("div",{className:"marketplace-sortBox"},Ya.default.createElement("div",{className:"marketplace-sortBox-header"},Ya.default.createElement("div",{className:"marketplace-sortBox-header-title"}),Ya.default.createElement(Qa.default,{placeholder:"Select an option",options:e,value:a?.key,onChange:e=>{t.onChange(e.value)}})))},tr=t(b()),ar=()=>tr.default.createElement("svg",{role:"img",height:"16",width:"16",className:"Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4",viewBox:"0 0 16 16"},tr.default.createElement("path",{d:"M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z"}),tr.default.createElement("path",{d:"M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z"})),rr=window.Spicetify,p=a=>{var e=a.type,t="dropdown"===e?"dropdown:"+a.storageKey:"toggle:"+a.storageKey,r=!!a.modalConfig.visual[a.storageKey];return void 0!==a.description&&null!==a.description||(a.description=""),"dropdown"===e&&a.options?d.default.createElement("div",{className:"settings-row"},d.default.createElement("label",{htmlFor:t,className:"col description"},a.name),d.default.createElement("div",{className:"col action"},d.default.createElement(er,{sortBoxOptions:a.options.map(e=>({key:e,value:e})),onChange:e=>{return e=e,t=a.storageKey,a.modalConfig.visual[t]=e,localStorage.setItem("marketplace:"+t,String(e)),void a.updateConfig(a.modalConfig);var t},sortBySelectedFn:e=>e.key==a.modalConfig.visual[a.storageKey]}),d.default.createElement(rr.ReactComponent.TooltipWrapper,{label:d.default.createElement(d.default.Fragment,null,a.description.split("\n").map(e=>d.default.createElement(d.default.Fragment,null,e,d.default.createElement("br",null)))),renderInline:!0,showDelay:10,placement:"top",labelClassName:"marketplace-settings-tooltip",disabled:!1},d.default.createElement("div",{className:"marketplace-tooltip-icon"},d.default.createElement(ar,null))))):d.default.createElement("div",{className:"settings-row"},d.default.createElement("label",{htmlFor:t,className:"col description"},a.name),d.default.createElement("div",{className:"col action"},d.default.createElement(Xa,{name:a.name,storageKey:a.storageKey,enabled:r,onChange:e=>{var t=e.target.checked,e=e.target.dataset.storageKey;a.modalConfig.visual[e]=t,console.debug(`toggling ${e} to `+t),localStorage.setItem("marketplace:"+e,String(t)),a.updateConfig(a.modalConfig)}})))},h=t(b()),nr=r=>{var e="toggle:"+r.name;const t=r.modalConfig.tabs.reduce((e,t,a)=>t.name===r.name?a:e,-1);var a=r.modalConfig.tabs[t]["enabled"];function n(e,t){var t=e+t,a=r.modalConfig.tabs[t];r.modalConfig.tabs[t]=r.modalConfig.tabs[e],r.modalConfig.tabs[e]=a,localStorage.setItem(w.tabs,JSON.stringify(r.modalConfig.tabs)),r.updateConfig(r.modalConfig)}return h.default.createElement("div",{className:"settings-row"},h.default.createElement("label",{htmlFor:e,className:"col description"},y("tabs."+r.name)),h.default.createElement("div",{className:"col action"},h.default.createElement("button",{title:"Move up",className:"arrow-btn",disabled:0===t,onClick:()=>n(t,-1)},h.default.createElement("svg",{height:"16",width:"16",viewBox:"0 0 16 16",fill:"currentColor",dangerouslySetInnerHTML:{__html:String(Spicetify.SVGIcons["chart-up"])}})),h.default.createElement("button",{title:"Move down",className:"arrow-btn",disabled:t===r.modalConfig.tabs.length-1,onClick:()=>n(t,1)},h.default.createElement("svg",{height:"16",width:"16",viewBox:"0 0 16 16",fill:"currentColor",dangerouslySetInnerHTML:{__html:String(Spicetify.SVGIcons["chart-down"])}})),h.default.createElement(Xa,{name:r.name,storageKey:"tab:"+r.name,clickable:"Extensions"!==r.name,enabled:a,onChange:e=>{r.modalConfig.tabs[t].enabled=e.target.checked,localStorage.setItem(w.tabs,JSON.stringify(r.modalConfig.tabs)),r.updateConfig(r.modalConfig)}})))},or=async()=>{const e=new MutationObserver(async()=>{var t;document.querySelector(".GenericModal[aria-label='Settings']")||(t=100,await new Promise(e=>setTimeout(e,t)),N("BACKUP"),e.disconnect())});e.observe(document.body,{childList:!0,subtree:!0}),Spicetify.PopupModal.hide()},ir=({CONFIG:e,updateAppConfig:t})=>{const[a,r]=u.default.useState({...e}),[n,o]=u.default.useState(y("settings.versionBtn")),i=e=>{t({...e}),r({...e})};e=document.querySelector("body > generic-modal button.main-trackCreditsModal-closeBtn");const s=document.querySelector("body > generic-modal > div");e&&s&&(e.onclick=()=>location.reload(),e.setAttribute("style","cursor: pointer;"),s.onclick=e=>{e.target===s&&location.reload()});e=C(w.albumArtBasedColor)?u.default.createElement(u.default.Fragment,null,u.default.createElement(p,{name:y("settings.albumArtBasedColorsMode"),storageKey:"albumArtBasedColorsMode",modalConfig:a,updateConfig:i,type:"dropdown",options:["monochromeDark","monochromeLight","analogicComplement","analogic","triad","quad"],description:y("settings.almbumArtColorsModeToolTip")}),u.default.createElement(p,{name:y("settings.albumArtBasedColorsVibrancy"),storageKey:"albumArtBasedColorsVibrancy",modalConfig:a,updateConfig:i,type:"dropdown",options:["desaturated","lightVibrant","prominent","vibrant"],description:y("settings.albumArtBasedColorsVibrancyToolTip")})):null;return u.default.createElement("div",{id:"marketplace-config-container"},u.default.createElement("h2",{className:"settings-heading"},y("settings.optionsHeading")),u.default.createElement(p,{name:y("settings.starCountLabel"),storageKey:"stars",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.tagsLabel"),storageKey:"tags",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.showArchived"),storageKey:"showArchived",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.devToolsLabel"),storageKey:"themeDevTools",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.hideInstalledLabel"),storageKey:"hideInstalled",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.colourShiftLabel"),storageKey:"colorShift",modalConfig:a,updateConfig:i}),u.default.createElement(p,{name:y("settings.albumArtBasedColors"),storageKey:"albumArtBasedColors",modalConfig:a,updateConfig:i}),e,u.default.createElement("h2",{className:"settings-heading"},y("settings.tabsHeading")),u.default.createElement("div",{className:"tabs-container"},a.tabs.map(({name:e},t)=>u.default.createElement(nr,{key:t,name:e,modalConfig:a,updateConfig:i}))),u.default.createElement("h2",{className:"settings-heading"},y("settings.resetHeading")),u.default.createElement("div",{className:"settings-row"},u.default.createElement("label",{className:"col description"},y("settings.resetDescription")),u.default.createElement("div",{className:"col action"},u.default.createElement(g,{onClick:()=>Na()},y("settings.resetBtn")))),u.default.createElement("h2",{className:"settings-heading"},y("settings.backupHeading")),u.default.createElement("div",{className:"settings-row"},u.default.createElement("label",{className:"col description"},y("settings.backupLabel")),u.default.createElement("div",{className:"col action"},u.default.createElement(g,{onClick:or},y("settings.backupBtn")))),u.default.createElement("h2",null,y("settings.versionHeading")),u.default.createElement("div",{className:"setting-row"},u.default.createElement("label",{className:"col description"},y("grid.spicetifyMarketplace")," ",ma),u.default.createElement("div",{className:"col action"},u.default.createElement(g,{onClick:()=>{Spicetify.Platform.ClipboardAPI.copy(ma),o(y("settings.versionCopied")),setTimeout(()=>o(y("settings.versionBtn")),3e3)}},n))))},m=t(b()),sr=t(Me()),lr=t(_e()),cr=(Prism.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0},section:{pattern:/(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,lookbehind:!0,inside:{"section-name":{pattern:/(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,lookbehind:!0,alias:"selector"},punctuation:/\[|\]/}},key:{pattern:/(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,lookbehind:!0,alias:"attr-value",inside:{"inner-value":{pattern:/^("|').+(?=\1$)/,lookbehind:!0}}},punctuation:/=/},localStorage.getItem(w.themeInstalled)),ur=cr?C(cr):null,dr=()=>{const[a,t]=m.default.useState(ur?(e=>{let t="";for(const a in e)if(Object.prototype.hasOwnProperty.call(e,a))if("object"==typeof e[a]){t+=`[${a}] `;for(const r in e[a])Object.prototype.hasOwnProperty.call(e[a],r)&&(t+=`${r}=${e[a][r]} `)}else t+=`${a}=${e[a]} -`;return t})(ur.schemes):y("devTools.noThemeInstalled"));return m.default.createElement("div",{id:"marketplace-theme-dev-tools-container",className:"marketplace-theme-dev-tools-container"},m.default.createElement("div",{className:"devtools-column"},m.default.createElement("label",{htmlFor:"color-ini-editor"},m.default.createElement("h2",{className:"devtools-heading"},y("devTools.colorIniEditor"))),m.default.createElement("div",{className:"marketplace-code-editor-wrapper marketplace-code-editor"},m.default.createElement(sr.default,{value:a,onValueChange:e=>t(e),highlight:e=>(0,lr.highlight)(e,lr.languages.ini),textareaId:"color-ini-editor",textareaClassName:"color-ini-editor",readOnly:!ur,placeholder:y("devTools.colorIniEditorPlaceholder"),style:{fontFamily:"monospace",resize:"none"}})),m.default.createElement(g,{onClick:()=>{var e=a;{var t;cr?(t=Sa(e),ur.schemes=t,localStorage.setItem(cr,JSON.stringify(ur))):Spicetify.showNotification(y("devTools.noThemeManifest"),!0)}}},y("save"))),m.default.createElement("div",{className:"devtools-column"},m.default.createElement("h2",{className:"devtools-heading"},y("devTools.invalidCSS")),m.default.createElement("div",{className:"marketplace-code-editor-wrapper marketplace-code-editor"},function(){var e=document.querySelector("body > style.marketplaceCSS.marketplaceUserCSS")?.innerHTML,t=new RegExp(".-?[_a-zA-Z]+[_a-zA-Z0-9-]*\\s*{","g");if(!e)return["Error: Class name list not found; please create an issue"];var a=[];for(const o of e.matchAll(t)){var r=o[0].replace(/{/g,"").trim(),n=r.split(" ");let t;for(let e=0;em.default.createElement("div",{key:t,className:"invalid-css-text"},e)))))},v=t(b()),pr=t(_e()),hr=t(Re()),mr=(Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Prism.languages.webmanifest=Prism.languages.json,()=>{const[e,t]=v.default.useState("");const a=t=>{if(t){let e;try{e=JSON.parse(t)}catch(e){return void Spicetify.showNotification(y("backupModal.invalidJSON"))}var a;a=e,console.debug("Importing Marketplace"),Na(),Object.keys(a).forEach(e=>{localStorage.setItem(e,a[e]),console.debug("Imported "+e)}),location.reload()}else Spicetify.showNotification(y("backupModal.noDataPasted"))};return v.default.createElement("div",{id:"marketplace-backup-container"},v.default.createElement("div",{className:"marketplace-backup-input-container"},v.default.createElement("label",{htmlFor:"marketplace-backup"},y("backupModal.inputLabel")),v.default.createElement("div",{className:"marketplace-code-editor-wrapper marketplace-code-editor"},v.default.createElement(pr.default,{value:e,onValueChange:e=>t(e),highlight:e=>(0,hr.highlight)(e,hr.languages.css),textareaId:"marketplace-import-text",textareaClassName:"import-textarea",readOnly:!1,className:"marketplace-code-editor-textarea",placeholder:y("backupModal.inputPlaceholder"),style:{}}))),v.default.createElement(v.default.Fragment,null,v.default.createElement(g,{classes:["marketplace-backup-button"],onClick:()=>{var e=(()=>{const t={};return Object.keys(localStorage).forEach(e=>{e.startsWith("marketplace:")&&(t[e]=localStorage.getItem(e))}),t})();Spicetify.Platform.ClipboardAPI.copy(JSON.stringify(e)),Spicetify.showNotification(y("backupModal.settingsCopied")),Spicetify.PopupModal.hide()}},y("backupModal.exportBtn")),v.default.createElement(g,{classes:["marketplace-backup-button"],onClick:()=>{a(e)}},y("backupModal.importBtn")),v.default.createElement(g,{classes:["marketplace-backup-button"],onClick:async()=>{var e=await(await(await window.showOpenFilePicker())[0].getFile()).text();a(e)}},y("backupModal.fileImportBtn"))))}),S=t(b());var fr=function(){const[e,t]=S.default.useState(null);return S.default.useEffect(()=>{!async function(){try{var{body:e,tag_name:t,message:a}=await(await fetch(ba)).json();return e&&t&&!a?{version:t.replace("v",""),changelog:await Ta(e.match(/## What's Changed([\s\S]*?)(\r\n\r|\n\n##)/)[1],"spicetify","spicetify-marketplace")}:null}catch(e){return console.error(e),null}}().then(e=>t(e))},[]),S.default.createElement("div",{id:"marketplace-update-container"},S.default.createElement("div",{id:"marketplace-update-description"},S.default.createElement("h4",null,y("updateModal.description")),S.default.createElement("a",{href:va+"/tag/v1.0.1"},y("updateModal.currentVersion",{version:ma})),S.default.createElement("a",{href:va+"/tag/v"+e?.version},y("updateModal.latestVersion",{version:e?.version}))),S.default.createElement("hr",null),S.default.createElement("div",{id:"marketplace-update-whats-changed"},S.default.createElement("h3",{className:"marketplace-update-header"},y("updateModal.whatsChanged")),S.default.createElement("details",null,S.default.createElement("summary",null,y("updateModal.seeChangelog")),S.default.createElement("ul",{dangerouslySetInnerHTML:{__html:e?.changelog??""}}))),S.default.createElement("hr",null),S.default.createElement("div",{id:"marketplace-update-guide"},S.default.createElement("h3",{className:"marketplace-update-header"},y("updateModal.howToUpgrade")),S.default.createElement("a",{href:"https://github.com/spicetify/spicetify-marketplace/wiki/Installation"},y("updateModal.viewGuide"))))},N=(e,t,a,r,n)=>{e=((e,t,a,r,n)=>{switch(e){case"ADD_SNIPPET":return{title:y("snippets.addTitle"),content:c.default.createElement(Ba,{type:e}),isLarge:!0};case"EDIT_SNIPPET":return{title:y("snippets.editTitle"),content:c.default.createElement(Ba,{type:e,content:r}),isLarge:!0};case"VIEW_SNIPPET":return{title:y("snippets.viewTitle"),content:c.default.createElement(Ba,{type:e,content:r,callback:n}),isLarge:!0};case"RELOAD":return{title:y("reloadModal.title"),content:c.default.createElement(Ha,null),isLarge:!1};case"SETTINGS":return{title:y("settings.title"),content:c.default.createElement(ir,{CONFIG:t,updateAppConfig:a}),isLarge:!0};case"THEME_DEV_TOOLS":return{title:y("devTools.title"),content:c.default.createElement(dr,null),isLarge:!0};case"BACKUP":return{title:y("backupModal.title"),content:c.default.createElement(mr,null),isLarge:!0};case"UPDATE":return{title:y("updateModal.title"),content:c.default.createElement(fr,null),isLarge:!0};default:return{title:"",content:c.default.createElement("div",null),isLarge:!1}}})(e,t,a,r,n),Spicetify.PopupModal.display(e)};async function gr(e,t=1,a=[],r=!1){let n=`https://api.github.com/search/repositories?q=${encodeURIComponent("topic:"+e)}&per_page=100`;t&&(n+="&page="+t);var o=JSON.parse(window.sessionStorage.getItem(e+"-page-"+t)||"null")||await fetch(n).then(e=>e.json()).catch(()=>null);return o?.items?(window.sessionStorage.setItem(e+"-page-"+t,JSON.stringify(o)),{...o,page_count:o.items.length,items:o.items.filter(e=>!a.includes(e.html_url)&&(r||!e.archived))}):(Spicetify.showNotification(y("notifications.tooManyRequests"),!0,5e3),{items:[]})}var Pe=new Blob([` +`;return t})(ur.schemes):y("devTools.noThemeInstalled"));return m.default.createElement("div",{id:"marketplace-theme-dev-tools-container",className:"marketplace-theme-dev-tools-container"},m.default.createElement("div",{className:"devtools-column"},m.default.createElement("label",{htmlFor:"color-ini-editor"},m.default.createElement("h2",{className:"devtools-heading"},y("devTools.colorIniEditor"))),m.default.createElement("div",{className:"marketplace-code-editor-wrapper marketplace-code-editor"},m.default.createElement(sr.default,{value:a,onValueChange:e=>t(e),highlight:e=>(0,lr.highlight)(e,lr.languages.ini),textareaId:"color-ini-editor",textareaClassName:"color-ini-editor",readOnly:!ur,placeholder:y("devTools.colorIniEditorPlaceholder"),style:{fontFamily:"monospace",resize:"none"}})),m.default.createElement(g,{onClick:()=>{var e=a;{var t;cr?(t=Sa(e),ur.schemes=t,localStorage.setItem(cr,JSON.stringify(ur))):Spicetify.showNotification(y("devTools.noThemeManifest"),!0)}}},y("save"))),m.default.createElement("div",{className:"devtools-column"},m.default.createElement("h2",{className:"devtools-heading"},y("devTools.invalidCSS")),m.default.createElement("div",{className:"marketplace-code-editor-wrapper marketplace-code-editor"},function(){var e=document.querySelector("body > style.marketplaceCSS.marketplaceUserCSS")?.innerHTML,t=new RegExp(".-?[_a-zA-Z]+[_a-zA-Z0-9-]*\\s*{","g");if(!e)return["Error: Class name list not found; please create an issue"];var a=[];for(const o of e.matchAll(t)){var r=o[0].replace(/{/g,"").trim(),n=r.split(" ");let t;for(let e=0;em.default.createElement("div",{key:t,className:"invalid-css-text"},e)))))},v=t(b()),pr=t(Me()),hr=t(_e()),mr=(Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Prism.languages.webmanifest=Prism.languages.json,()=>{const[e,t]=v.default.useState("");const a=t=>{if(t){let e;try{e=JSON.parse(t)}catch(e){return void Spicetify.showNotification(y("backupModal.invalidJSON"))}var a;a=e,console.debug("Importing Marketplace"),Na(),Object.keys(a).forEach(e=>{localStorage.setItem(e,a[e]),console.debug("Imported "+e)}),location.reload()}else Spicetify.showNotification(y("backupModal.noDataPasted"))};return v.default.createElement("div",{id:"marketplace-backup-container"},v.default.createElement("div",{className:"marketplace-backup-input-container"},v.default.createElement("label",{htmlFor:"marketplace-backup"},y("backupModal.inputLabel")),v.default.createElement("div",{className:"marketplace-code-editor-wrapper marketplace-code-editor"},v.default.createElement(pr.default,{value:e,onValueChange:e=>t(e),highlight:e=>(0,hr.highlight)(e,hr.languages.css),textareaId:"marketplace-import-text",textareaClassName:"import-textarea",readOnly:!1,className:"marketplace-code-editor-textarea",placeholder:y("backupModal.inputPlaceholder"),style:{}}))),v.default.createElement(v.default.Fragment,null,v.default.createElement(g,{classes:["marketplace-backup-button"],onClick:()=>{var e=(()=>{const t={};return Object.keys(localStorage).forEach(e=>{e.startsWith("marketplace:")&&(t[e]=localStorage.getItem(e))}),t})();Spicetify.Platform.ClipboardAPI.copy(JSON.stringify(e)),Spicetify.showNotification(y("backupModal.settingsCopied")),Spicetify.PopupModal.hide()}},y("backupModal.exportBtn")),v.default.createElement(g,{classes:["marketplace-backup-button"],onClick:()=>{a(e)}},y("backupModal.importBtn")),v.default.createElement(g,{classes:["marketplace-backup-button"],onClick:async()=>{var e=await(await(await window.showOpenFilePicker())[0].getFile()).text();a(e)}},y("backupModal.fileImportBtn"))))}),S=t(b());var fr=function(){const[e,t]=S.default.useState(null);return S.default.useEffect(()=>{!async function(){try{var{body:e,tag_name:t,message:a}=await(await fetch(ba)).json();return e&&t&&!a?{version:t.replace("v",""),changelog:await Ta(e.match(/## What's Changed([\s\S]*?)(\r\n\r|\n\n##)/)[1],"spicetify","spicetify-marketplace")}:null}catch(e){return console.error(e),null}}().then(e=>t(e))},[]),S.default.createElement("div",{id:"marketplace-update-container"},S.default.createElement("div",{id:"marketplace-update-description"},S.default.createElement("h4",null,y("updateModal.description")),S.default.createElement("a",{href:va+"/tag/v1.0.2"},y("updateModal.currentVersion",{version:ma})),S.default.createElement("a",{href:va+"/tag/v"+e?.version},y("updateModal.latestVersion",{version:e?.version}))),S.default.createElement("hr",null),S.default.createElement("div",{id:"marketplace-update-whats-changed"},S.default.createElement("h3",{className:"marketplace-update-header"},y("updateModal.whatsChanged")),S.default.createElement("details",null,S.default.createElement("summary",null,y("updateModal.seeChangelog")),S.default.createElement("ul",{dangerouslySetInnerHTML:{__html:e?.changelog??""}}))),S.default.createElement("hr",null),S.default.createElement("div",{id:"marketplace-update-guide"},S.default.createElement("h3",{className:"marketplace-update-header"},y("updateModal.howToUpgrade")),S.default.createElement("a",{href:"https://github.com/spicetify/spicetify-marketplace/wiki/Installation"},y("updateModal.viewGuide"))))},N=(e,t,a,r,n)=>{e=((e,t,a,r,n)=>{switch(e){case"ADD_SNIPPET":return{title:y("snippets.addTitle"),content:c.default.createElement(Fa,{type:e}),isLarge:!0};case"EDIT_SNIPPET":return{title:y("snippets.editTitle"),content:c.default.createElement(Fa,{type:e,content:r}),isLarge:!0};case"VIEW_SNIPPET":return{title:y("snippets.viewTitle"),content:c.default.createElement(Fa,{type:e,content:r,callback:n}),isLarge:!0};case"RELOAD":return{title:y("reloadModal.title"),content:c.default.createElement(Ha,null),isLarge:!1};case"SETTINGS":return{title:y("settings.title"),content:c.default.createElement(ir,{CONFIG:t,updateAppConfig:a}),isLarge:!0};case"THEME_DEV_TOOLS":return{title:y("devTools.title"),content:c.default.createElement(dr,null),isLarge:!0};case"BACKUP":return{title:y("backupModal.title"),content:c.default.createElement(mr,null),isLarge:!0};case"UPDATE":return{title:y("updateModal.title"),content:c.default.createElement(fr,null),isLarge:!0};default:return{title:"",content:c.default.createElement("div",null),isLarge:!1}}})(e,t,a,r,n),Spicetify.PopupModal.display(e)};async function gr(e,t=1,a=[],r=!1){let n=`https://api.github.com/search/repositories?q=${encodeURIComponent("topic:"+e)}&per_page=100`;t&&(n+="&page="+t);var o=JSON.parse(window.sessionStorage.getItem(e+"-page-"+t)||"null")||await fetch(n).then(e=>e.json()).catch(()=>null);return o?.items?(window.sessionStorage.setItem(e+"-page-"+t,JSON.stringify(o)),{...o,page_count:o.items.length,items:o.items.filter(e=>!a.includes(e.html_url)&&(r||!e.archived))}):(Spicetify.showNotification(y("notifications.tooManyRequests"),!0,5e3),{items:[]})}var Pe=new Blob([` self.addEventListener('message', async (event) => { const url = event.data; const response = await fetch(url); const data = await response.json().catch(() => null); self.postMessage(data); }); -`],{type:"application/javascript"}),vr=URL.createObjectURL(Pe);async function br(e,t,a){var r=e+"-"+t,n=window.sessionStorage.getItem(r),o=JSON.parse(window.sessionStorage.getItem("noManifests")||"[]");if(n)return JSON.parse(n);n=`https://raw.githubusercontent.com/${e}/${t}/${a}/manifest.json`;if(o.includes(n))return null;let i=await async function(e){const r=new Worker(vr);return new Promise(t=>{const a=e=>{r.terminate(),t(e)};r.postMessage(e),r.addEventListener("message",e=>a(e.data),{once:!0}),r.addEventListener("error",()=>a(null),{once:!0})})}(n);return i?(Oa(i=Array.isArray(i)?i:[i],r),i):Oa([n],"noManifests")}async function yr(e,r,n,o=!1){try{var t=e.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/);if(!t||!t.groups)return null;const{user:i,repo:s}=t.groups;return(await br(i,s,r)).reduce((e,t)=>{var a=t.branch||r,a={manifest:t,title:t.name,subtitle:t.description,authors:wa(t.authors,i),user:i,repo:s,branch:a,imageURL:t.preview&&t.preview.startsWith("http")?t.preview:`https://raw.githubusercontent.com/${i}/${s}/${a}/`+t.preview,extensionURL:t.main.startsWith("http")?t.main:`https://raw.githubusercontent.com/${i}/${s}/${a}/`+t.main,readmeURL:t.readme&&t.readme.startsWith("http")?t.readme:`https://raw.githubusercontent.com/${i}/${s}/${a}/`+t.readme,stars:n,tags:t.tags};return t&&t.name&&t.description&&t.main&&(o&&localStorage.getItem(`marketplace:installed:${i}/${s}/`+t.main)||e.push(a)),e},[])}catch{return null}}async function Sr(e,r,n){try{var t=e.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/);if(!t||!t.groups)return null;const{user:o,repo:i}=t.groups;return(await br(o,i,r)).reduce((e,t)=>{var a=t.branch||r,a={manifest:t,title:t.name,subtitle:t.description,authors:wa(t.authors,o),user:o,repo:i,branch:a,imageURL:t.preview&&t.preview.startsWith("http")?t.preview:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.preview,readmeURL:t.readme&&t.readme.startsWith("http")?t.readme:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.readme,stars:n,tags:t.tags,cssURL:t.usercss.startsWith("http")?t.usercss:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.usercss,schemesURL:t.schemes?t.schemes.startsWith("http")?t.schemes:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.schemes:null,include:t.include};return t?.name&&t?.usercss&&t?.description&&e.push(a),e},[])}catch{return null}}async function kr(e,r,n){try{var t=e.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/);if(!t||!t.groups)return null;const{user:o,repo:i}=t.groups;return(await br(o,i,r)).reduce((e,t)=>{var a=t.branch||r,a={manifest:t,title:t.name,subtitle:t.description,authors:wa(t.authors,o),user:o,repo:i,branch:a,imageURL:t.preview&&t.preview.startsWith("http")?t.preview:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.preview,readmeURL:t.readme&&t.readme.startsWith("http")?t.readme:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.readme,stars:n,tags:t.tags};return t&&t.name&&t.description&&e.push(a),e},[])}catch{return null}}var wr=async()=>{return(await fetch("https://raw.githubusercontent.com/spicetify/spicetify-marketplace/main/resources/blacklist.json").then(e=>e.json()).catch(()=>({}))).repos},Er=async()=>{var e=await fetch("https://raw.githubusercontent.com/spicetify/spicetify-marketplace/main/resources/snippets.json").then(e=>e.json()).catch(()=>[]);return e.length?e.reduce((e,t)=>{t={...t};return t.preview&&(t.imageURL=t.preview.startsWith("http")?t.preview:"https://raw.githubusercontent.com/spicetify/spicetify-marketplace/main/"+t.preview,delete t.preview),e.push(t),e},[]):[]},Cr=t(b()),Nr=class extends Cr.default.Component{render(){return Cr.default.createElement("div",{onClick:this.props.onClick},Cr.default.createElement("p",{style:{fontSize:100,lineHeight:"65px"}},"»"),Cr.default.createElement("span",{style:{fontSize:20}},"Load more"))}},x=t(b()),xr=()=>x.default.createElement("svg",{width:"100px",height:"100px",viewBox:"0 0 100 100",preserveAspectRatio:"xMidYMid"},x.default.createElement("circle",{cx:"50",cy:"50",r:"0",fill:"none",stroke:"currentColor",strokeWidth:"2"},x.default.createElement("animate",{attributeName:"r",repeatCount:"indefinite",dur:"1s",values:"0;40",keyTimes:"0;1",keySplines:"0 0.2 0.8 1",calcMode:"spline",begin:"0s"}),x.default.createElement("animate",{attributeName:"opacity",repeatCount:"indefinite",dur:"1s",values:"1;0",keyTimes:"0;1",keySplines:"0.2 0 0.8 1",calcMode:"spline",begin:"0s"})),x.default.createElement("circle",{cx:"50",cy:"50",r:"0",fill:"none",stroke:"currentColor",strokeWidth:"2"},x.default.createElement("animate",{attributeName:"r",repeatCount:"indefinite",dur:"1s",values:"0;40",keyTimes:"0;1",keySplines:"0 0.2 0.8 1",calcMode:"spline",begin:"-0.5s"}),x.default.createElement("animate",{attributeName:"opacity",repeatCount:"indefinite",dur:"1s",values:"1;0",keyTimes:"0;1",keySplines:"0.2 0 0.8 1",calcMode:"spline",begin:"-0.5s"}))),Ir=t(b()),Lr=()=>Ir.default.createElement("svg",{role:"img",width:"16",height:"16",viewBox:"0 0 24 24","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg"},Ir.default.createElement("path",{d:"M24 13.616v-3.232c-1.651-.587-2.694-.752-3.219-2.019v-.001c-.527-1.271.1-2.134.847-3.707l-2.285-2.285c-1.561.742-2.433 1.375-3.707.847h-.001c-1.269-.526-1.435-1.576-2.019-3.219h-3.232c-.582 1.635-.749 2.692-2.019 3.219h-.001c-1.271.528-2.132-.098-3.707-.847l-2.285 2.285c.745 1.568 1.375 2.434.847 3.707-.527 1.271-1.584 1.438-3.219 2.02v3.232c1.632.58 2.692.749 3.219 2.019.53 1.282-.114 2.166-.847 3.707l2.285 2.286c1.562-.743 2.434-1.375 3.707-.847h.001c1.27.526 1.436 1.579 2.019 3.219h3.232c.582-1.636.75-2.69 2.027-3.222h.001c1.262-.524 2.12.101 3.698.851l2.285-2.286c-.744-1.563-1.375-2.433-.848-3.706.527-1.271 1.588-1.44 3.221-2.021zm-12 2.384c-2.209 0-4-1.791-4-4s1.791-4 4-4 4 1.791 4 4-1.791 4-4 4z",fill:"currentColor"})),Or=t(b()),Tr=()=>Or.default.createElement("svg",{className:"devtools-icon",version:"1.1",viewBox:"1 1 22 22",xmlSpace:"preserve",xmlns:"http://www.w3.org/2000/svg"},Or.default.createElement("g",{className:"devtools-icon-internal",id:"grid_system"}),Or.default.createElement("g",{id:"_icons"},Or.default.createElement("path",{d:"M18,12v-0.9l0.7-5.7C18.8,4.5,18.6,3.7,18,3c-0.6-0.6-1.4-1-2.2-1H8.3C7.4,2,6.6,2.4,6,3C5.4,3.7,5.2,4.5,5.3,5.4L6,11.1 V12c0,1.6,1.3,2.9,2.8,3l-0.4,2.9c-0.1,1,0.2,2.1,0.8,2.9S11,22,12,22s2-0.5,2.7-1.2s1-1.8,0.8-2.9L15.2,15 C16.7,14.9,18,13.6,18,12z M7.5,4.3C7.7,4.1,8,4,8.3,4H13v2c0,0.6,0.4,1,1,1s1-0.4,1-1V4h0.7c0.3,0,0.6,0.1,0.8,0.3 c0.2,0.2,0.3,0.5,0.2,0.8L16.1,10H7.9L7.3,5.1C7.2,4.8,7.3,4.6,7.5,4.3z M13.2,19.4c-0.6,0.7-1.8,0.7-2.4,0 c-0.3-0.4-0.4-0.8-0.4-1.3l0.5-3.2h2.3l0.5,3.2C13.7,18.6,13.5,19.1,13.2,19.4z M15,13h-1h-4H9c-0.6,0-1-0.4-1-1h8 C16,12.6,15.6,13,15,13z"}))),I=t(b()),Ar=t(e()),i=class extends I.default.Component{constructor(e){super(e)}render(){var e=this.props["t"];return this.props.item.enabled?I.default.createElement("li",{className:"marketplace-tabBar-headerItem","data-tab":this.props.item.value,onClick:e=>{e.preventDefault(),this.props.switchTo(this.props.item)}},I.default.createElement("a",{"aria-current":"page",className:"marketplace-tabBar-headerItemLink "+(this.props.item.active?"marketplace-tabBar-active":""),draggable:"false",href:""},I.default.createElement("span",{className:"main-type-mestoBold"},e("tabs."+this.props.item.value)))):null}},Pr=qt()(i),_r=I.default.memo(function({items:e,switchTo:t}){return I.default.createElement("li",{className:"marketplace-tabBar-headerItem"},I.default.createElement(Ar.default,{className:"main-type-mestoBold",options:e,value:"More",placeholder:"More",onChange:t}))}),Rr=e=>{const t=document.querySelector(".Root__main-view .os-resize-observer-host")??document.querySelector(".Root__main-view .os-size-observer");if(!t)return null;const[a,r]=(0,I.useState)(t.clientWidth),n=()=>r(t.clientWidth),o=()=>{var e=document.querySelector(".marketplace-tabBar"),t=document.querySelector(".main-topBar-topbarContentWrapper");e&&t?(e&&t&&"/marketplace"===Spicetify.Platform.History.location.pathname&&(t.appendChild(e),document.querySelector(".main-topBar-container")?.setAttribute("style","contain: unset;")),Spicetify.Platform.History.listen(({pathname:e})=>{"/marketplace"!=e&&(document.querySelector(".marketplace-tabBar")?.remove(),document.querySelector(".main-topBar-container")?.removeAttribute("style"))})):setTimeout(o,100)};return(0,I.useEffect)(()=>{const e=new ResizeObserver(n);return e.observe(t),()=>{e.disconnect()}}),(0,I.useEffect)(()=>{o()}),I.default.createElement(Mr,{windowSize:a,links:e.links,activeLink:e.activeLink,switchCallback:e.switchCallback})},Mr=I.default.memo(function({links:e,activeLink:a,switchCallback:t,windowSize:r=1/0}){const n=I.default.useRef(null),[o,i]=(0,I.useState)([]),[s,l]=(0,I.useState)(0),[c,u]=(0,I.useState)([]),d=e.map(({name:e,enabled:t})=>{return{label:e,value:e,active:e===a,enabled:t}});return(0,I.useEffect)(()=>{n.current&&l(n.current.clientWidth)},[r,n.current?.clientWidth]),(0,I.useEffect)(()=>{var e;n.current&&(e=Array.from(n.current.children).map(e=>e.clientWidth),i(e))},[e]),(0,I.useEffect)(()=>{if(n.current)if(o.reduce((e,t)=>e+t,0)<=s)u([]);else{var e=Math.max(...o);const r=[];let a=e;o.forEach((e,t)=>{s>=a+e?a+=e:r.push(t)}),u(r)}},[s,o]),I.default.createElement("nav",{className:"marketplace-tabBar marketplace-tabBar-nav"},I.default.createElement("ul",{className:"marketplace-tabBar-header",ref:n},d.filter((e,t)=>!c.includes(t)).map(e=>I.default.createElement(Pr,{key:e.value,item:e,switchTo:t})),c.length||0===o.length?I.default.createElement(_r,{items:c.map(e=>d[e]).filter(e=>e),switchTo:t}):null))}),L=t(b()),jr=t(b()),$r=()=>jr.default.createElement("svg",{role:"img",width:"16",height:"16",viewBox:"0 0 448 512","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg"},jr.default.createElement("path",{d:"M53.21 467c1.562 24.84 23.02 45 47.9 45h245.8c24.88 0 46.33-20.16 47.9-45L416 128H32L53.21 467zM432 32H320l-11.58-23.16c-2.709-5.42-8.25-8.844-14.31-8.844H153.9c-6.061 0-11.6 3.424-14.31 8.844L128 32H16c-8.836 0-16 7.162-16 16V80c0 8.836 7.164 16 16 16h416c8.838 0 16-7.164 16-16V48C448 39.16 440.8 32 432 32z",fill:"currentColor"})),Dr=t(b()),zr=()=>Dr.default.createElement("svg",{role:"img",width:"16",height:"16",viewBox:"0 0 512 512","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg"},Dr.default.createElement("path",{d:"M480 352h-133.5l-45.25 45.25C289.2 409.3 273.1 416 256 416s-33.16-6.656-45.25-18.75L165.5 352H32c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h448c17.67 0 32-14.33 32-32v-96C512 366.3 497.7 352 480 352zM432 456c-13.2 0-24-10.8-24-24c0-13.2 10.8-24 24-24s24 10.8 24 24C456 445.2 445.2 456 432 456zM233.4 374.6C239.6 380.9 247.8 384 256 384s16.38-3.125 22.62-9.375l128-128c12.49-12.5 12.49-32.75 0-45.25c-12.5-12.5-32.76-12.5-45.25 0L288 274.8V32c0-17.67-14.33-32-32-32C238.3 0 224 14.33 224 32v242.8L150.6 201.4c-12.49-12.5-32.75-12.5-45.25 0c-12.49 12.5-12.49 32.75 0 45.25L233.4 374.6z",fill:"currentColor"})),Ur=t(b()),Fr=()=>Ur.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24"},Ur.default.createElement("path",{d:"M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z",fill:"currentColor"})),Br=t(b()),Vr=e=>{return Br.default.createElement("div",{className:"marketplace-card__authors"},e.authors.map((e,t)=>Br.default.createElement("a",{title:e.name,className:"marketplace-card__author",href:e.url,draggable:"false",dir:"auto",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),key:t},e.name)))},Hr=t(b()),qr=r=>{const[e,t]=Hr.default.useState(!1),n={[y("grid.externalJS")]:"external JS",[y("grid.archived")]:"archived",[y("grid.dark")]:"dark",[y("grid.light")]:"light"};var a=e=>{return e.filter((e,t,a)=>a.indexOf(e)===t).reduce((e,t)=>{var a=n[t]||t;return!r.showTags&&t!==y("grid.externalJS")&&t!==y("grid.archived")||e.push(Hr.default.createElement("li",{className:"marketplace-card__tag",draggable:!1,"data-tag":a},t)),e},[])};let o=r.tags.sort(e=>e===y("grid.externalJS")||e===y("grid.archived")?-1:1),i=[];return 1{e.stopPropagation(),t(!0)}},"..."):null)},O=window.Spicetify,Gr=class extends L.default.Component{tags;menuType;localStorageKey;key=null;type=Gr;constructor(e){super(e),this.menuType=O.ReactComponent.Menu,this.localStorageKey=Aa(e),Object.assign(this,e),this.tags=e.item.tags||[],e.item.include&&this.tags.push(y("grid.externalJS")),e.item.archived&&this.tags.push(y("grid.archived")),this.state={installed:null!==localStorage.getItem(this.localStorageKey),stars:this.props.item.stars||0,tagsExpanded:!1,externalUrl:this.props.item.user&&this.props.item.repo?`https://github.com/${this.props.item.user}/`+this.props.item.repo:"",lastUpdated:this.props.item.user&&this.props.item.repo?this.props.item.lastUpdated:void 0,created:this.props.item.user&&this.props.item.repo?this.props.item.created:void 0}}isInstalled(){return null!==localStorage.getItem(this.localStorageKey)}async componentDidMount(){if("Installed"===this.props.CONFIG.activeTab&&"snippet"!==this.props.type){var e=`https://api.github.com/repos/${this.props.item.user}/`+this.props.item.repo,{stargazers_count:e,pushed_at:t}=await fetch(e).then(e=>e.json());if(this.state.stars!==e&&this.props.CONFIG.visual.stars&&console.debug("Stars updated to: "+e),this.state.lastUpdated!==t)switch(console.debug("New update pushed at: "+t),this.props.type){case"extension":this.installExtension();break;case"theme":this.installTheme(!0)}}}buttonClicked(){if("extension"===this.props.type)this.isInstalled()?(console.debug("Extension already installed, removing"),this.removeExtension()):this.installExtension(),N("RELOAD");else if("theme"===this.props.type){var e=localStorage.getItem(w.themeInstalled),e=e?C(e,{}):{};if(this.isInstalled())console.debug("Theme already installed, removing"),this.removeTheme(this.localStorageKey);else{var t=localStorage.getItem(w.localTheme);if(null!=t&&"marketplace"!==t.toLowerCase())return void O.showNotification(y("notifications.wrongLocalTheme"),!0,5e3);this.removeTheme(),this.installTheme()}(this.props.item.manifest?.include||e.include)&&N("RELOAD")}else"app"===this.props.type?window.open(this.state.externalUrl,"_blank"):"snippet"===this.props.type?this.isInstalled()?(console.debug("Snippet already installed, removing"),this.removeSnippet()):this.installSnippet():console.error("Unknown card type")}installExtension(){var e,t,a,r,n,o,i,s,l,c,u,d;console.debug("Installing extension "+this.localStorageKey),this.props.item?({manifest:d,title:e,subtitle:t,authors:a,user:r,repo:n,branch:o,imageURL:i,extensionURL:s,readmeURL:l,lastUpdated:c,created:u}=this.props.item,localStorage.setItem(this.localStorageKey,JSON.stringify({manifest:d,type:this.props.type,title:e,subtitle:t,authors:a,user:r,repo:n,branch:o,imageURL:i,extensionURL:s,readmeURL:l,stars:this.state.stars,lastUpdated:c,created:u})),-1===(d=C(w.installedExtensions,[])).indexOf(this.localStorageKey)&&(d.push(this.localStorageKey),localStorage.setItem(w.installedExtensions,JSON.stringify(d))),console.debug("Installed"),this.setState({installed:!0})):O.showNotification(y("notifications.extensionInstallationError"),!0)}removeExtension(){var e;localStorage.getItem(this.localStorageKey)&&(console.debug("Removing extension "+this.localStorageKey),localStorage.removeItem(this.localStorageKey),e=C(w.installedExtensions,[]).filter(e=>e!==this.localStorageKey),localStorage.setItem(w.installedExtensions,JSON.stringify(e)),console.debug("Removed"),this.setState({installed:!1}))}async installTheme(a=!1){var r=this.props["item"];if(r){console.debug("Installing theme "+this.localStorageKey);let e={},t=null;a?({schemes:a,activeScheme:n}=C(this.localStorageKey,{}),e=a,t=n):r.schemesURL&&(a=await(await fetch(r.schemesURL)).text(),e=Sa(a));var n=t||Object.keys(e)[0]||null,{manifest:a,title:o,subtitle:i,authors:s,user:l,repo:c,branch:u,imageURL:d,extensionURL:p,readmeURL:h,cssURL:m,schemesURL:f,include:g,lastUpdated:v,created:b}=(console.debug(e,n),r),a=(localStorage.setItem(this.localStorageKey,JSON.stringify({manifest:a,type:this.props.type,title:o,subtitle:i,authors:s,user:l,repo:c,branch:u,imageURL:d,extensionURL:p,readmeURL:h,stars:this.state.stars,tags:this.tags,cssURL:m,schemesURL:f,include:g,schemes:e,activeScheme:n,lastUpdated:v,created:b})),C(w.installedThemes,[]));-1===a.indexOf(this.localStorageKey)&&(a.push(this.localStorageKey),localStorage.setItem(w.installedThemes,JSON.stringify(a)),localStorage.setItem(w.themeInstalled,this.localStorageKey)),console.debug("Installed"),r.include||(this.fetchAndInjectUserCSS(this.localStorageKey),this.props.updateActiveTheme(this.localStorageKey),this.props.updateColourSchemes(e,n),(o=this.props.item.manifest?.name)&&(O.Config.current_theme=o),n&&(O.Config.color_scheme=n)),this.setState({installed:!0})}else O.showNotification(y("notifications.themeInstallationError"),!0)}removeTheme(t){var e=(t=t||localStorage.getItem(w.themeInstalled))&&localStorage.getItem(t);t&&e&&(console.debug("Removing theme "+t),localStorage.removeItem(t),localStorage.removeItem(w.themeInstalled),e=C(w.installedThemes,[]).filter(e=>e!==t),localStorage.setItem(w.installedThemes,JSON.stringify(e)),console.debug("Removed"),this.fetchAndInjectUserCSS(null),this.props.updateActiveTheme(null),this.props.updateColourSchemes(null,null),O.Config.current_theme="marketplace",O.Config.color_scheme="marketplace",this.setState({installed:!1}))}installSnippet(){console.debug("Installing snippet "+this.localStorageKey),localStorage.setItem(this.localStorageKey,JSON.stringify({code:this.props.item.code,title:this.props.item.title,description:this.props.item.description,imageURL:this.props.item.imageURL}));var e=C(w.installedSnippets,[]),e=(-1===e.indexOf(this.localStorageKey)&&(e.push(this.localStorageKey),localStorage.setItem(w.installedSnippets,JSON.stringify(e))),e.map(e=>C(e)));ka(e),this.setState({installed:!0})}removeSnippet(){localStorage.removeItem(this.localStorageKey);var e=C(w.installedSnippets,[]).filter(e=>e!==this.localStorageKey),e=(localStorage.setItem(w.installedSnippets,JSON.stringify(e)),e.map(e=>C(e)));ka(e),this.setState({installed:!1})}async fetchAndInjectUserCSS(e){try{var t=window.sessionStorage.getItem("marketplace-request-tld")||void 0,a=e?await La(this.props.item,t):void 0;Ia(a)}catch(e){console.warn(e)}}openReadme(){this.props.item?.manifest?.readme?O.Platform.History.push({pathname:ga+"/readme",state:{data:{title:this.props.item.title,user:this.props.item.user,repo:this.props.item.repo,branch:this.props.item.branch,readmeURL:this.props.item.readmeURL,type:this.props.type,install:this.buttonClicked.bind(this),isInstalled:this.isInstalled.bind(this)}}}):O.showNotification(y("notifications.noReadmeFile"),!0)}render(){var e,t,a=this.isInstalled();return"Installed"!==this.props.CONFIG.activeTab||a?(e=["main-card-card","marketplace-card--"+this.props.type],a&&e.push("marketplace-card--installed"),t=[],"snippet"!==this.props.type&&this.props.visual.stars&&t.push("★ "+this.state.stars),L.default.createElement("div",{className:e.join(" "),onClick:()=>{if("snippet"===this.props.type){var e=this.props.item.title.replace(/\n/g,"");if(C("marketplace:installed:snippet:"+e)?.custom)return N("EDIT_SNIPPET",void 0,void 0,this.props);N("VIEW_SNIPPET",void 0,void 0,this.props,this.buttonClicked.bind(this))}else this.openReadme()}},L.default.createElement("div",{className:"main-card-draggable",draggable:"true"},L.default.createElement("div",{className:"main-card-imageContainer"},L.default.createElement("div",{className:"main-cardImage-imageWrapper"},L.default.createElement("div",null,L.default.createElement("img",{alt:"","aria-hidden":"false",draggable:"false",loading:"lazy",src:this.props.item.imageURL,className:"main-image-image main-cardImage-image",onError:e=>{e.currentTarget.setAttribute("src","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII"),e.currentTarget.closest(".main-cardImage-imageWrapper")?.classList.add("main-cardImage-imageWrapper--error")}})))),L.default.createElement("div",{className:"main-card-cardMetadata"},L.default.createElement("a",{draggable:"false",title:"snippet"===this.props.type?this.props.item.title:this.props.item.manifest?.name,className:"main-cardHeader-link",dir:"auto",href:"snippet"!==this.props.type?this.state.externalUrl:"https://github.com/spicetify/spicetify-marketplace/blob/main/src/resources/snippets.ts",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation()},L.default.createElement("div",{className:"main-cardHeader-text main-type-balladBold"},this.props.item.title)),L.default.createElement("div",{className:"main-cardSubHeader-root main-type-mestoBold marketplace-cardSubHeader"},this.props.item.authors&&L.default.createElement(Vr,{authors:this.props.item.authors}),L.default.createElement("span",null,t.join(" ‒ "))),L.default.createElement("p",{className:"marketplace-card-desc"},"snippet"===this.props.type?this.props.item.description:this.props.item.manifest?.description),this.props.item.lastUpdated&&L.default.createElement("p",{className:"marketplace-card-desc"},y("grid.lastUpdated",{val:new Date(this.props.item.lastUpdated),formatParams:{val:{year:"numeric",month:"long",day:"numeric"}}})),this.tags.length?L.default.createElement("div",{className:"marketplace-card__bottom-meta main-type-mestoBold"},L.default.createElement(qr,{tags:this.tags,showTags:this.props.CONFIG.visual.tags})):null,a&&L.default.createElement("div",{className:"marketplace-card__bottom-meta main-type-mestoBold"},"✓ ",y("grid.installed")),L.default.createElement(O.ReactComponent.TooltipWrapper,{label:"app"===this.props.type?y("github"):y(a?"remove":"install"),renderInline:!0},L.default.createElement("div",{className:"main-card-PlayButtonContainer"},L.default.createElement(g,{classes:["marketplace-installButton"],type:"circle",label:"app"===this.props.type?y("github"):y(a?"remove":"install"),onClick:e=>{e.stopPropagation(),this.buttonClicked()}},"app"===this.props.type?L.default.createElement(Fr,null):a?L.default.createElement($r,null):L.default.createElement(zr,null)))))))):(console.debug("Card item not installed"),null)}},Kr=qt()(Gr),Jr=window.Spicetify,a=class extends s.default.Component{constructor(e){super(e),Object.assign(this,e),this.updateAppConfig=e.updateAppConfig.bind(this),this.sortConfig={by:C(w.sort,"top")},this.state={version:ma,newUpdate:!1,searchValue:"",cards:[],tabs:e.CONFIG.tabs,rest:!0,endOfList:!1,schemes:e.CONFIG.theme.schemes,activeScheme:e.CONFIG.theme.activeScheme,activeThemeKey:e.CONFIG.theme.activeThemeKey}}searchRequested;endOfList=!1;lastScroll=0;requestQueue=[];requestPage=0;cardList=[];sortConfig;gridUpdateTabs;gridUpdatePostsVisual;checkScroll;CONFIG;updateAppConfig;BLACKLIST;SNIPPETS;getInstalledTheme(){var e=localStorage.getItem(w.themeInstalled);return(e=e&&localStorage.getItem(e))?JSON.parse(e):null}newRequest(e){this.cardList=[];var t=[];this.requestQueue.unshift(t),this.loadAmount(t,e)}appendCard(e,t,a){a===this.props.CONFIG.activeTab&&(a=s.default.createElement(Kr,{item:e,key:`${this.props.CONFIG.activeTab}:${e.user}:`+e.title,CONFIG:this.CONFIG,visual:this.props.CONFIG.visual,type:t,activeThemeKey:this.state.activeThemeKey,updateColourSchemes:this.updateColourSchemes.bind(this),updateActiveTheme:this.setActiveTheme.bind(this)}),this.cardList.push(a))}updateSort(e){e&&(this.sortConfig.by=e,localStorage.setItem(w.sort,e)),this.requestPage=0,this.cardList=[],this.setState({cards:[],rest:!1,endOfList:!1}),this.endOfList=!1,this.newRequest(E)}updateTabs(){this.setState({tabs:[...this.props.CONFIG.tabs]})}updatePostsVisual(){this.cardList=this.cardList.map((e,t)=>s.default.createElement(Kr,{...e.props,key:t.toString(),CONFIG:this.CONFIG})),this.setState({cards:[...this.cardList]})}switchTo(e){this.CONFIG.activeTab=e.value,localStorage.setItem(w.activeTab,e.value),this.cardList=[],this.requestPage=0,this.setState({cards:[],rest:!1,endOfList:!1}),this.endOfList=!1,this.newRequest(E)}async loadPage(t){const a=this.CONFIG.activeTab;switch(a){case"Extensions":var e=await gr("spicetify-extensions",this.requestPage,this.BLACKLIST,this.CONFIG.visual.showArchived),r=[];for(const h of e.items){var n=await yr(h.contents_url,h.default_branch,h.stargazers_count,this.CONFIG.visual.hideInstalled);if(1({...e,archived:h.archived,lastUpdated:h.pushed_at,created:h.created_at})))}ja(r,localStorage.getItem("marketplace:sort")||"stars");for(const m of r)this.appendCard(m,"extension",a);this.setState({cards:this.cardList});var o=-1{e=C(e);if(1({...e,archived:b.archived,lastUpdated:b.pushed_at,created:b.created_at})))}this.setState({cards:this.cardList}),ja(c,localStorage.getItem("marketplace:sort")||"stars");for(const y of c)this.appendCard(y,"theme",a);e=-1({...e,archived:S.archived,lastUpdated:S.pushed_at,created:S.created_at})))}this.setState({cards:this.cardList}),ja(d,localStorage.getItem("marketplace:sort")||"stars");for(const k of d)this.appendCard(k,"app",a);i=-1this.appendCard(e,"snippet",a)),this.setState({cards:this.cardList}))}return this.setState({rest:!0,endOfList:!0}),this.endOfList=!0,0}async loadAmount(t,e=E){for(this.setState({rest:!1}),e+=this.cardList.length,this.requestPage=await this.loadPage(t);this.requestPage&&-1!==this.requestPage&&this.cardList.lengthe!==t):(this.requestQueue.shift(),this.setState({rest:!0}))}loadMore(){this.state.rest&&!this.endOfList&&this.loadAmount(this.requestQueue[0],E)}updateColourSchemes(e,t){console.debug("updateColourSchemes",e,t),this.CONFIG.theme.schemes=e,(this.CONFIG.theme.activeScheme=t)&&(Jr.Config.color_scheme=t),e&&t&&e[t]?xa(this.CONFIG.theme.schemes[t]):xa(null);var a=C(w.themeInstalled),r=C(a);r?(r.activeScheme=t,console.debug(r),localStorage.setItem(a,JSON.stringify(r))):console.debug("No installed theme data"),this.setState({schemes:e,activeScheme:t})}async componentDidMount(){fetch(ba).then(e=>e.json()).then(e=>{if(e.message)throw e;this.setState({version:e.name});try{this.setState({newUpdate:ya.default.gt(e.name,ma)})}catch(e){console.error(e)}},e=>{console.error("Failed to check for updates",e)}),this.gridUpdateTabs=this.updateTabs.bind(this),this.gridUpdatePostsVisual=this.updatePostsVisual.bind(this);var e=document.querySelector(".os-viewport")??document.querySelector("#main .main-view-container__scroll-node");this.checkScroll=this.isScrolledBottom.bind(this),e&&(e.addEventListener("scroll",this.checkScroll),this.cardList.length)?0=e.scrollHeight&&this.loadMore()}setActiveTheme(e){this.CONFIG.theme.activeThemeKey=e,this.setState({activeThemeKey:e})}getActiveScheme(){return this.state.activeScheme}render(){const a=this.props["t"];return s.default.createElement("section",{className:"contentSpacing"},s.default.createElement("div",{className:"marketplace-header"},s.default.createElement("div",{className:"marketplace-header__left"},this.state.newUpdate?s.default.createElement("button",{type:"button",title:a("grid.newUpdate"),className:"marketplace-header-icon-button",id:"marketplace-update",onClick:()=>N("UPDATE")},s.default.createElement(zr,null)," ",this.state.version):null,s.default.createElement("h2",{className:"marketplace-header__label"},a("grid.sort.label")),s.default.createElement(er,{onChange:e=>this.updateSort(e),sortBoxOptions:Ca(a),sortBySelectedFn:e=>e.key===this.CONFIG.sort})),s.default.createElement("div",{className:"marketplace-header__right"},this.CONFIG.visual.themeDevTools?s.default.createElement(Jr.ReactComponent.TooltipWrapper,{label:a("devTools.title"),renderInline:!0,placement:"bottom"},s.default.createElement("button",{type:"button","aria-label":a("devTools.title"),className:"marketplace-header-icon-button",onClick:()=>N("THEME_DEV_TOOLS")},s.default.createElement(Tr,null))):null,this.state.activeScheme?s.default.createElement(er,{onChange:e=>this.updateColourSchemes(this.state.schemes,e),sortBoxOptions:Ea(this.state.schemes),sortBySelectedFn:e=>e.key===this.getActiveScheme()}):null,s.default.createElement("div",{className:"searchbar--bar__wrapper"},s.default.createElement("input",{className:"searchbar-bar",type:"text",placeholder:`${a("grid.search")} ${a("tabs."+this.CONFIG.activeTab)}...`,value:this.state.searchValue,onChange:e=>{this.setState({searchValue:e.target.value})}})),s.default.createElement(Jr.ReactComponent.TooltipWrapper,{label:a("settings.title"),renderInline:!0,placement:"bottom"},s.default.createElement("button",{type:"button","aria-label":a("settings.title"),className:"marketplace-header-icon-button",id:"marketplace-settings-button",onClick:()=>N("SETTINGS",this.CONFIG,this.updateAppConfig)},s.default.createElement(Lr,null))))),[{handle:"extension",name:"Extensions"},{handle:"theme",name:"Themes"},{handle:"snippet",name:"Snippets"},{handle:"app",name:"Apps"}].map(t=>{var e=this.cardList.filter(e=>e.props.type===t.handle).filter(e=>{const t=this.state.searchValue.trim().toLowerCase();var{title:e,user:a,authors:r,tags:n}=e.props.item;return!t||e.toLowerCase().includes(t)||a?.toLowerCase().includes(t)||r?.some(e=>e.name.toLowerCase().includes(t))||n?.some(e=>e.toLowerCase().includes(t))}).map(e=>s.default.cloneElement(e,{activeThemeKey:this.state.activeThemeKey,key:e.key})).filter((t,e,a)=>a.findIndex(e=>e.key===t.key)===e);return e.length?s.default.createElement(s.default.Fragment,null,s.default.createElement("h2",{className:"marketplace-card-type-heading"},a("tabs."+t.name)),s.default.createElement("div",{className:"marketplace-grid main-gridContainer-gridContainer main-gridContainer-fixedWidth","data-tab":this.CONFIG.activeTab,"data-card-type":a("tabs."+t.name)},e)):null}),"Snippets"===this.CONFIG.activeTab?s.default.createElement(g,{classes:["marketplace-add-snippet-btn"],onClick:()=>N("ADD_SNIPPET")},"+ ",a("grid.addCSS")):null,s.default.createElement("footer",{className:"marketplace-footer"},!this.state.endOfList&&(this.state.rest&&0${this.props.t("readmePage.loading")}

`};getReadmeHTML=async()=>fetch(this.props.data.readmeURL).then(e=>{if(e.ok)return e.text();throw Spicetify.showNotification(`${this.props.t("readmePage.errorLoading")} (HTTP ${e.status})`,!0)}).then(e=>Ta(e,this.props.data.user,this.props.data.repo)).then(e=>(e||Spicetify.Platform.History.goBack(),e)).catch(e=>(console.error(e),Spicetify.Platform.History.goBack(),null));componentDidMount(){this.getReadmeHTML().then(e=>{null!=e&&this.setState({html:e})})}componentDidUpdate(){const e=document.querySelector("#marketplace-readme")?.closest("main");if(e){const t=setInterval(()=>{document.querySelector("#marketplace-readme")?(e.style.overflowY="visible",e.style.overflowY="auto"):(clearInterval(t),e.style.removeProperty("overflow-y"))},1e3)}document.querySelectorAll("#marketplace-readme img").forEach(e=>{e.addEventListener("error",e=>{var e=e.target,t=e.getAttribute("src"),t="/"===t?.charAt(0)?`https://raw.githubusercontent.com/${this.props.data.user}/${this.props.data.repo}/${this.props.data.branch}/`+t?.slice(1):this.props.data.readmeURL.substring(0,this.props.data.readmeURL.lastIndexOf("/"))+"/"+t;e.setAttribute("src",t)},{once:!0})})}buttonContent(){return"app"===this.props.data.type?{icon:T.default.createElement(Fr,null),text:this.props.t("github")}:this.state.isInstalled?{icon:T.default.createElement($r,null),text:this.props.t("remove")}:{icon:T.default.createElement(zr,null),text:this.props.t("install")}}render(){return T.default.createElement("section",{className:"contentSpacing"},T.default.createElement("div",{className:"marketplace-header"},T.default.createElement("div",{className:"marketplace-header__left"},T.default.createElement("h1",null,this.props.title)),T.default.createElement("div",{className:"marketplace-header__right"},T.default.createElement(g,{classes:["marketplace-header__button"],onClick:e=>{e.preventDefault(),this.props.data.install(),this.setState({isInstalled:!this.state.isInstalled})},label:this.buttonContent().text},this.buttonContent().icon," ",this.buttonContent().text))),"

Loading...

"===this.state.html?T.default.createElement("footer",{className:"marketplace-footer"},T.default.createElement(xr,null)):T.default.createElement("div",{id:"marketplace-readme",className:"marketplace-readme__container",dangerouslySetInnerHTML:{__html:this.state.html}}))}},Xr=qt()(_e),Re=(r.use(z).use(Wt).init({resources:ha,detection:{order:["navigator","htmlTag"]},fallbackLng:"en",interpolation:{escapeValue:!1}}),class extends ze.default.Component{state={count:0,CONFIG:{}};CONFIG;constructor(e){super(e);e=C(w.tabs,null);let t=[];try{if(t=JSON.parse(e),!Array.isArray(t))throw new Error("Could not parse marketplace tabs key");if(0===t.length)throw new Error("Empty marketplace tabs key");if(0!e).length)throw new Error("Falsey marketplace tabs key")}catch{t=fa,localStorage.setItem(w.tabs,JSON.stringify(t))}let a={},r=null;try{var n=C(w.themeInstalled,null);if(n){var o=C(n,null);if(!o)throw new Error("No installed theme data");a=o.schemes,r=o.activeScheme}else console.debug("No theme set as installed")}catch(e){console.error(e)}this.CONFIG={visual:{stars:JSON.parse(C("marketplace:stars",!0)),tags:JSON.parse(C("marketplace:tags",!0)),showArchived:JSON.parse(C("marketplace:showArchived",!1)),hideInstalled:JSON.parse(C("marketplace:hideInstalled",!1)),colorShift:JSON.parse(C("marketplace:colorShift",!1)),themeDevTools:JSON.parse(C("marketplace:themeDevTools",!1)),albumArtBasedColors:JSON.parse(C("marketplace:albumArtBasedColors",!1)),albumArtBasedColorsMode:C("marketplace:albumArtBasedColorsMode")||"monochrome-light",albumArtBasedColorsVibrancy:C("marketplace:albumArtBasedColorsVibrancy")||"PROMINENT",type:JSON.parse(C("marketplace:type",!1)),followers:JSON.parse(C("marketplace:followers",!1))},tabs:t,activeTab:C(w.activeTab,t[0]),theme:{activeThemeKey:C(w.themeInstalled,null),schemes:a,activeScheme:r},sort:C(w.sort,"stars")},this.CONFIG.activeTab&&this.CONFIG.tabs.filter(e=>e.name===this.CONFIG.activeTab).length||(this.CONFIG.activeTab=this.CONFIG.tabs[0].name)}updateConfig=e=>{this.CONFIG={...e},console.debug("updated config",this.CONFIG),this.setState({CONFIG:{...e}})};render(){var{location:e,replace:t}=Spicetify.Platform.History;return e.pathname===ga+"/readme"?e.state?.data?ze.default.createElement(Xr,{title:y("readmePage.title"),data:e.state.data}):(t(ga),null):ze.default.createElement(Wr,{title:y("grid.spicetifyMarketplace"),CONFIG:this.CONFIG,updateAppConfig:this.updateConfig})}}),Zr=qt()(Re),Yr=t(b());return Pe=je,D(_({},"__esModule",{value:!0}),Pe)})();const render=()=>marketplace.default(); \ No newline at end of file +`],{type:"application/javascript"}),vr=URL.createObjectURL(Pe);async function br(e,t,a){var r=e+"-"+t,n=window.sessionStorage.getItem(r),o=JSON.parse(window.sessionStorage.getItem("noManifests")||"[]");if(n)return JSON.parse(n);n=`https://raw.githubusercontent.com/${e}/${t}/${a}/manifest.json`;if(o.includes(n))return null;let i=await async function(e){const r=new Worker(vr);return new Promise(t=>{const a=e=>{r.terminate(),t(e)};r.postMessage(e),r.addEventListener("message",e=>a(e.data),{once:!0}),r.addEventListener("error",()=>a(null),{once:!0})})}(n);return i?(Oa(i=Array.isArray(i)?i:[i],r),i):Oa([n],"noManifests")}async function yr(e,r,n,o=!1){try{var t=e.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/);if(!t||!t.groups)return null;const{user:i,repo:s}=t.groups;return(await br(i,s,r)).reduce((e,t)=>{var a=t.branch||r,a={manifest:t,title:t.name,subtitle:t.description,authors:wa(t.authors,i),user:i,repo:s,branch:a,imageURL:t.preview&&t.preview.startsWith("http")?t.preview:`https://raw.githubusercontent.com/${i}/${s}/${a}/`+t.preview,extensionURL:t.main.startsWith("http")?t.main:`https://raw.githubusercontent.com/${i}/${s}/${a}/`+t.main,readmeURL:t.readme&&t.readme.startsWith("http")?t.readme:`https://raw.githubusercontent.com/${i}/${s}/${a}/`+t.readme,stars:n,tags:t.tags};return t&&t.name&&t.description&&t.main&&(o&&localStorage.getItem(`marketplace:installed:${i}/${s}/`+t.main)||e.push(a)),e},[])}catch{return null}}async function Sr(e,r,n){try{var t=e.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/);if(!t||!t.groups)return null;const{user:o,repo:i}=t.groups;return(await br(o,i,r)).reduce((e,t)=>{var a=t.branch||r,a={manifest:t,title:t.name,subtitle:t.description,authors:wa(t.authors,o),user:o,repo:i,branch:a,imageURL:t.preview&&t.preview.startsWith("http")?t.preview:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.preview,readmeURL:t.readme&&t.readme.startsWith("http")?t.readme:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.readme,stars:n,tags:t.tags,cssURL:t.usercss.startsWith("http")?t.usercss:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.usercss,schemesURL:t.schemes?t.schemes.startsWith("http")?t.schemes:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.schemes:null,include:t.include};return t?.name&&t?.usercss&&t?.description&&e.push(a),e},[])}catch{return null}}async function kr(e,r,n){try{var t=e.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/);if(!t||!t.groups)return null;const{user:o,repo:i}=t.groups;return(await br(o,i,r)).reduce((e,t)=>{var a=t.branch||r,a={manifest:t,title:t.name,subtitle:t.description,authors:wa(t.authors,o),user:o,repo:i,branch:a,imageURL:t.preview&&t.preview.startsWith("http")?t.preview:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.preview,readmeURL:t.readme&&t.readme.startsWith("http")?t.readme:`https://raw.githubusercontent.com/${o}/${i}/${a}/`+t.readme,stars:n,tags:t.tags};return t&&t.name&&t.description&&e.push(a),e},[])}catch{return null}}var wr=async()=>{return(await fetch("https://raw.githubusercontent.com/spicetify/spicetify-marketplace/main/resources/blacklist.json").then(e=>e.json()).catch(()=>({}))).repos},Er=async()=>{var e=await fetch("https://raw.githubusercontent.com/spicetify/spicetify-marketplace/main/resources/snippets.json").then(e=>e.json()).catch(()=>[]);return e.length?e.reduce((e,t)=>{t={...t};return t.preview&&(t.imageURL=t.preview.startsWith("http")?t.preview:"https://raw.githubusercontent.com/spicetify/spicetify-marketplace/main/"+t.preview,delete t.preview),e.push(t),e},[]):[]},Cr=t(b()),Nr=class extends Cr.default.Component{render(){return Cr.default.createElement("div",{onClick:this.props.onClick},Cr.default.createElement("p",{style:{fontSize:100,lineHeight:"65px"}},"»"),Cr.default.createElement("span",{style:{fontSize:20}},"Load more"))}},x=t(b()),xr=()=>x.default.createElement("svg",{width:"100px",height:"100px",viewBox:"0 0 100 100",preserveAspectRatio:"xMidYMid"},x.default.createElement("circle",{cx:"50",cy:"50",r:"0",fill:"none",stroke:"currentColor",strokeWidth:"2"},x.default.createElement("animate",{attributeName:"r",repeatCount:"indefinite",dur:"1s",values:"0;40",keyTimes:"0;1",keySplines:"0 0.2 0.8 1",calcMode:"spline",begin:"0s"}),x.default.createElement("animate",{attributeName:"opacity",repeatCount:"indefinite",dur:"1s",values:"1;0",keyTimes:"0;1",keySplines:"0.2 0 0.8 1",calcMode:"spline",begin:"0s"})),x.default.createElement("circle",{cx:"50",cy:"50",r:"0",fill:"none",stroke:"currentColor",strokeWidth:"2"},x.default.createElement("animate",{attributeName:"r",repeatCount:"indefinite",dur:"1s",values:"0;40",keyTimes:"0;1",keySplines:"0 0.2 0.8 1",calcMode:"spline",begin:"-0.5s"}),x.default.createElement("animate",{attributeName:"opacity",repeatCount:"indefinite",dur:"1s",values:"1;0",keyTimes:"0;1",keySplines:"0.2 0 0.8 1",calcMode:"spline",begin:"-0.5s"}))),Ir=t(b()),Lr=()=>Ir.default.createElement("svg",{role:"img",width:"16",height:"16",viewBox:"0 0 24 24","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg"},Ir.default.createElement("path",{d:"M24 13.616v-3.232c-1.651-.587-2.694-.752-3.219-2.019v-.001c-.527-1.271.1-2.134.847-3.707l-2.285-2.285c-1.561.742-2.433 1.375-3.707.847h-.001c-1.269-.526-1.435-1.576-2.019-3.219h-3.232c-.582 1.635-.749 2.692-2.019 3.219h-.001c-1.271.528-2.132-.098-3.707-.847l-2.285 2.285c.745 1.568 1.375 2.434.847 3.707-.527 1.271-1.584 1.438-3.219 2.02v3.232c1.632.58 2.692.749 3.219 2.019.53 1.282-.114 2.166-.847 3.707l2.285 2.286c1.562-.743 2.434-1.375 3.707-.847h.001c1.27.526 1.436 1.579 2.019 3.219h3.232c.582-1.636.75-2.69 2.027-3.222h.001c1.262-.524 2.12.101 3.698.851l2.285-2.286c-.744-1.563-1.375-2.433-.848-3.706.527-1.271 1.588-1.44 3.221-2.021zm-12 2.384c-2.209 0-4-1.791-4-4s1.791-4 4-4 4 1.791 4 4-1.791 4-4 4z",fill:"currentColor"})),Or=t(b()),Tr=()=>Or.default.createElement("svg",{className:"devtools-icon",version:"1.1",viewBox:"1 1 22 22",xmlSpace:"preserve",xmlns:"http://www.w3.org/2000/svg"},Or.default.createElement("g",{className:"devtools-icon-internal",id:"grid_system"}),Or.default.createElement("g",{id:"_icons"},Or.default.createElement("path",{d:"M18,12v-0.9l0.7-5.7C18.8,4.5,18.6,3.7,18,3c-0.6-0.6-1.4-1-2.2-1H8.3C7.4,2,6.6,2.4,6,3C5.4,3.7,5.2,4.5,5.3,5.4L6,11.1 V12c0,1.6,1.3,2.9,2.8,3l-0.4,2.9c-0.1,1,0.2,2.1,0.8,2.9S11,22,12,22s2-0.5,2.7-1.2s1-1.8,0.8-2.9L15.2,15 C16.7,14.9,18,13.6,18,12z M7.5,4.3C7.7,4.1,8,4,8.3,4H13v2c0,0.6,0.4,1,1,1s1-0.4,1-1V4h0.7c0.3,0,0.6,0.1,0.8,0.3 c0.2,0.2,0.3,0.5,0.2,0.8L16.1,10H7.9L7.3,5.1C7.2,4.8,7.3,4.6,7.5,4.3z M13.2,19.4c-0.6,0.7-1.8,0.7-2.4,0 c-0.3-0.4-0.4-0.8-0.4-1.3l0.5-3.2h2.3l0.5,3.2C13.7,18.6,13.5,19.1,13.2,19.4z M15,13h-1h-4H9c-0.6,0-1-0.4-1-1h8 C16,12.6,15.6,13,15,13z"}))),I=t(b()),Ar=t(e()),i=class extends I.default.Component{constructor(e){super(e)}render(){var e=this.props["t"];return this.props.item.enabled?I.default.createElement("li",{className:"marketplace-tabBar-headerItem","data-tab":this.props.item.value,onClick:e=>{e.preventDefault(),this.props.switchTo(this.props.item)}},I.default.createElement("a",{"aria-current":"page",className:"marketplace-tabBar-headerItemLink "+(this.props.item.active?"marketplace-tabBar-active":""),draggable:"false",href:""},I.default.createElement("span",{className:"main-type-mestoBold"},e("tabs."+this.props.item.value)))):null}},Pr=qt()(i),Mr=I.default.memo(function({items:e,switchTo:t}){return I.default.createElement("li",{className:"marketplace-tabBar-headerItem"},I.default.createElement(Ar.default,{className:"main-type-mestoBold",options:e,value:"More",placeholder:"More",onChange:t}))}),_r=e=>{const t=document.querySelector(".Root__main-view .os-resize-observer-host")??document.querySelector(".Root__main-view .os-size-observer");if(!t)return null;const[a,r]=(0,I.useState)(t.clientWidth),n=()=>r(t.clientWidth),o=()=>{var e=document.querySelector(".marketplace-tabBar"),t=document.querySelector(".main-topBar-topbarContentWrapper");e&&t?(e&&t&&"/marketplace"===Spicetify.Platform.History.location.pathname&&(t.appendChild(e),document.querySelector(".main-topBar-container")?.setAttribute("style","contain: unset;")),Spicetify.Platform.History.listen(({pathname:e})=>{"/marketplace"!=e&&(document.querySelector(".marketplace-tabBar")?.remove(),document.querySelector(".main-topBar-container")?.removeAttribute("style"))})):setTimeout(o,100)};return(0,I.useEffect)(()=>{const e=new ResizeObserver(n);return e.observe(t),()=>{e.disconnect()}}),(0,I.useEffect)(()=>{o()}),I.default.createElement(Rr,{windowSize:a,links:e.links,activeLink:e.activeLink,switchCallback:e.switchCallback})},Rr=I.default.memo(function({links:e,activeLink:a,switchCallback:t,windowSize:r=1/0}){const n=I.default.useRef(null),[o,i]=(0,I.useState)([]),[s,l]=(0,I.useState)(0),[c,u]=(0,I.useState)([]),d=e.map(({name:e,enabled:t})=>{return{label:e,value:e,active:e===a,enabled:t}});return(0,I.useEffect)(()=>{n.current&&l(n.current.clientWidth)},[r,n.current?.clientWidth]),(0,I.useEffect)(()=>{var e;n.current&&(e=Array.from(n.current.children).map(e=>e.clientWidth),i(e))},[e]),(0,I.useEffect)(()=>{if(n.current)if(o.reduce((e,t)=>e+t,0)<=s)u([]);else{var e=Math.max(...o);const r=[];let a=e;o.forEach((e,t)=>{s>=a+e?a+=e:r.push(t)}),u(r)}},[s,o]),I.default.createElement("nav",{className:"marketplace-tabBar marketplace-tabBar-nav"},I.default.createElement("ul",{className:"marketplace-tabBar-header",ref:n},d.filter((e,t)=>!c.includes(t)).map(e=>I.default.createElement(Pr,{key:e.value,item:e,switchTo:t})),c.length||0===o.length?I.default.createElement(Mr,{items:c.map(e=>d[e]).filter(e=>e),switchTo:t}):null))}),L=t(b()),jr=t(b()),Dr=()=>jr.default.createElement("svg",{role:"img",width:"16",height:"16",viewBox:"0 0 448 512","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg"},jr.default.createElement("path",{d:"M53.21 467c1.562 24.84 23.02 45 47.9 45h245.8c24.88 0 46.33-20.16 47.9-45L416 128H32L53.21 467zM432 32H320l-11.58-23.16c-2.709-5.42-8.25-8.844-14.31-8.844H153.9c-6.061 0-11.6 3.424-14.31 8.844L128 32H16c-8.836 0-16 7.162-16 16V80c0 8.836 7.164 16 16 16h416c8.838 0 16-7.164 16-16V48C448 39.16 440.8 32 432 32z",fill:"currentColor"})),$r=t(b()),zr=()=>$r.default.createElement("svg",{role:"img",width:"16",height:"16",viewBox:"0 0 512 512","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg"},$r.default.createElement("path",{d:"M480 352h-133.5l-45.25 45.25C289.2 409.3 273.1 416 256 416s-33.16-6.656-45.25-18.75L165.5 352H32c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h448c17.67 0 32-14.33 32-32v-96C512 366.3 497.7 352 480 352zM432 456c-13.2 0-24-10.8-24-24c0-13.2 10.8-24 24-24s24 10.8 24 24C456 445.2 445.2 456 432 456zM233.4 374.6C239.6 380.9 247.8 384 256 384s16.38-3.125 22.62-9.375l128-128c12.49-12.5 12.49-32.75 0-45.25c-12.5-12.5-32.76-12.5-45.25 0L288 274.8V32c0-17.67-14.33-32-32-32C238.3 0 224 14.33 224 32v242.8L150.6 201.4c-12.49-12.5-32.75-12.5-45.25 0c-12.49 12.5-12.49 32.75 0 45.25L233.4 374.6z",fill:"currentColor"})),Ur=t(b()),Br=()=>Ur.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24"},Ur.default.createElement("path",{d:"M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z",fill:"currentColor"})),Fr=t(b()),Vr=e=>{return Fr.default.createElement("div",{className:"marketplace-card__authors"},e.authors.map((e,t)=>Fr.default.createElement("a",{title:e.name,className:"marketplace-card__author",href:e.url,draggable:"false",dir:"auto",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),key:t},e.name)))},Hr=t(b()),qr=r=>{const[e,t]=Hr.default.useState(!1),n={[y("grid.externalJS")]:"external JS",[y("grid.archived")]:"archived",[y("grid.dark")]:"dark",[y("grid.light")]:"light"};var a=e=>{return e.filter((e,t,a)=>a.indexOf(e)===t).reduce((e,t)=>{var a=n[t]||t;return!r.showTags&&t!==y("grid.externalJS")&&t!==y("grid.archived")||e.push(Hr.default.createElement("li",{className:"marketplace-card__tag",draggable:!1,"data-tag":a},t)),e},[])};let o=r.tags.sort(e=>e===y("grid.externalJS")||e===y("grid.archived")?-1:1),i=[];return 1{e.stopPropagation(),t(!0)}},"..."):null)},O=window.Spicetify,Gr=class extends L.default.Component{tags;menuType;localStorageKey;key=null;type=Gr;constructor(e){super(e),this.menuType=O.ReactComponent.Menu,this.localStorageKey=Aa(e),Object.assign(this,e),this.tags=e.item.tags||[],e.item.include&&this.tags.push(y("grid.externalJS")),e.item.archived&&this.tags.push(y("grid.archived")),this.state={installed:null!==localStorage.getItem(this.localStorageKey),stars:this.props.item.stars||0,tagsExpanded:!1,externalUrl:this.props.item.user&&this.props.item.repo?`https://github.com/${this.props.item.user}/`+this.props.item.repo:"",lastUpdated:this.props.item.user&&this.props.item.repo?this.props.item.lastUpdated:void 0,created:this.props.item.user&&this.props.item.repo?this.props.item.created:void 0}}isInstalled(){return null!==localStorage.getItem(this.localStorageKey)}async componentDidMount(){if("Installed"===this.props.CONFIG.activeTab&&"snippet"!==this.props.type){var e=`https://api.github.com/repos/${this.props.item.user}/`+this.props.item.repo,{stargazers_count:e,pushed_at:t}=await fetch(e).then(e=>e.json());if(this.state.stars!==e&&this.props.CONFIG.visual.stars&&console.debug("Stars updated to: "+e),this.state.lastUpdated!==t)switch(console.debug("New update pushed at: "+t),this.props.type){case"extension":this.installExtension();break;case"theme":this.installTheme(!0)}}}buttonClicked(){if("extension"===this.props.type)this.isInstalled()?(console.debug("Extension already installed, removing"),this.removeExtension()):this.installExtension(),N("RELOAD");else if("theme"===this.props.type){var e=localStorage.getItem(w.themeInstalled),e=e?C(e,{}):{};if(this.isInstalled())console.debug("Theme already installed, removing"),this.removeTheme(this.localStorageKey);else{var t=localStorage.getItem(w.localTheme);if(null!=t&&"marketplace"!==t.toLowerCase())return void O.showNotification(y("notifications.wrongLocalTheme"),!0,5e3);this.removeTheme(),this.installTheme()}(this.props.item.manifest?.include||e.include)&&N("RELOAD")}else"app"===this.props.type?window.open(this.state.externalUrl,"_blank"):"snippet"===this.props.type?this.isInstalled()?(console.debug("Snippet already installed, removing"),this.removeSnippet()):this.installSnippet():console.error("Unknown card type")}installExtension(){var e,t,a,r,n,o,i,s,l,c,u,d;console.debug("Installing extension "+this.localStorageKey),this.props.item?({manifest:d,title:e,subtitle:t,authors:a,user:r,repo:n,branch:o,imageURL:i,extensionURL:s,readmeURL:l,lastUpdated:c,created:u}=this.props.item,localStorage.setItem(this.localStorageKey,JSON.stringify({manifest:d,type:this.props.type,title:e,subtitle:t,authors:a,user:r,repo:n,branch:o,imageURL:i,extensionURL:s,readmeURL:l,stars:this.state.stars,lastUpdated:c,created:u})),-1===(d=C(w.installedExtensions,[])).indexOf(this.localStorageKey)&&(d.push(this.localStorageKey),localStorage.setItem(w.installedExtensions,JSON.stringify(d))),console.debug("Installed"),this.setState({installed:!0})):O.showNotification(y("notifications.extensionInstallationError"),!0)}removeExtension(){var e;localStorage.getItem(this.localStorageKey)&&(console.debug("Removing extension "+this.localStorageKey),localStorage.removeItem(this.localStorageKey),e=C(w.installedExtensions,[]).filter(e=>e!==this.localStorageKey),localStorage.setItem(w.installedExtensions,JSON.stringify(e)),console.debug("Removed"),this.setState({installed:!1}))}async installTheme(a=!1){var r=this.props["item"];if(r){console.debug("Installing theme "+this.localStorageKey);let e={},t=null;a?({schemes:a,activeScheme:n}=C(this.localStorageKey,{}),e=a,t=n):r.schemesURL&&(a=await(await fetch(r.schemesURL)).text(),e=Sa(a));var n=t||Object.keys(e)[0]||null,{manifest:a,title:o,subtitle:i,authors:s,user:l,repo:c,branch:u,imageURL:d,extensionURL:p,readmeURL:h,cssURL:m,schemesURL:f,include:g,lastUpdated:v,created:b}=(console.debug(e,n),r),a=(localStorage.setItem(this.localStorageKey,JSON.stringify({manifest:a,type:this.props.type,title:o,subtitle:i,authors:s,user:l,repo:c,branch:u,imageURL:d,extensionURL:p,readmeURL:h,stars:this.state.stars,tags:this.tags,cssURL:m,schemesURL:f,include:g,schemes:e,activeScheme:n,lastUpdated:v,created:b})),C(w.installedThemes,[]));-1===a.indexOf(this.localStorageKey)&&(a.push(this.localStorageKey),localStorage.setItem(w.installedThemes,JSON.stringify(a)),localStorage.setItem(w.themeInstalled,this.localStorageKey)),console.debug("Installed"),r.include||(this.fetchAndInjectUserCSS(this.localStorageKey),this.props.updateActiveTheme(this.localStorageKey),this.props.updateColourSchemes(e,n),(o=this.props.item.manifest?.name)&&(O.Config.current_theme=o),n&&(O.Config.color_scheme=n)),this.setState({installed:!0})}else O.showNotification(y("notifications.themeInstallationError"),!0)}removeTheme(t){var e=(t=t||localStorage.getItem(w.themeInstalled))&&localStorage.getItem(t);t&&e&&(console.debug("Removing theme "+t),localStorage.removeItem(t),localStorage.removeItem(w.themeInstalled),e=C(w.installedThemes,[]).filter(e=>e!==t),localStorage.setItem(w.installedThemes,JSON.stringify(e)),console.debug("Removed"),this.fetchAndInjectUserCSS(null),this.props.updateActiveTheme(null),this.props.updateColourSchemes(null,null),O.Config.current_theme="marketplace",O.Config.color_scheme="marketplace",this.setState({installed:!1}))}installSnippet(){console.debug("Installing snippet "+this.localStorageKey),localStorage.setItem(this.localStorageKey,JSON.stringify({code:this.props.item.code,title:this.props.item.title,description:this.props.item.description,imageURL:this.props.item.imageURL}));var e=C(w.installedSnippets,[]),e=(-1===e.indexOf(this.localStorageKey)&&(e.push(this.localStorageKey),localStorage.setItem(w.installedSnippets,JSON.stringify(e))),e.map(e=>C(e)));ka(e),this.setState({installed:!0})}removeSnippet(){localStorage.removeItem(this.localStorageKey);var e=C(w.installedSnippets,[]).filter(e=>e!==this.localStorageKey),e=(localStorage.setItem(w.installedSnippets,JSON.stringify(e)),e.map(e=>C(e)));ka(e),this.setState({installed:!1})}async fetchAndInjectUserCSS(e){try{var t=window.sessionStorage.getItem("marketplace-request-tld")||void 0,a=e?await La(this.props.item,t):void 0;Ia(a)}catch(e){console.warn(e)}}openReadme(){this.props.item?.manifest?.readme?O.Platform.History.push({pathname:ga+"/readme",state:{data:{title:this.props.item.title,user:this.props.item.user,repo:this.props.item.repo,branch:this.props.item.branch,readmeURL:this.props.item.readmeURL,type:this.props.type,install:this.buttonClicked.bind(this),isInstalled:this.isInstalled.bind(this)}}}):O.showNotification(y("notifications.noReadmeFile"),!0)}render(){var e,t,a=this.isInstalled();return"Installed"!==this.props.CONFIG.activeTab||a?(e=["main-card-card","marketplace-card--"+this.props.type],a&&e.push("marketplace-card--installed"),t=[],"snippet"!==this.props.type&&this.props.visual.stars&&t.push("★ "+this.state.stars),L.default.createElement("div",{className:e.join(" "),onClick:()=>{if("snippet"===this.props.type){var e=this.props.item.title.replace(/\n/g,"");if(C("marketplace:installed:snippet:"+e)?.custom)return N("EDIT_SNIPPET",void 0,void 0,this.props);N("VIEW_SNIPPET",void 0,void 0,this.props,this.buttonClicked.bind(this))}else this.openReadme()}},L.default.createElement("div",{className:"main-card-draggable",draggable:"true"},L.default.createElement("div",{className:"main-card-imageContainer"},L.default.createElement("div",{className:"main-cardImage-imageWrapper"},L.default.createElement("div",null,L.default.createElement("img",{alt:"","aria-hidden":"false",draggable:"false",loading:"lazy",src:this.props.item.imageURL,className:"main-image-image main-cardImage-image",onError:e=>{e.currentTarget.setAttribute("src","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII"),e.currentTarget.closest(".main-cardImage-imageWrapper")?.classList.add("main-cardImage-imageWrapper--error")}})))),L.default.createElement("div",{className:"main-card-cardMetadata"},L.default.createElement("a",{draggable:"false",title:"snippet"===this.props.type?this.props.item.title:this.props.item.manifest?.name,className:"main-cardHeader-link",dir:"auto",href:"snippet"!==this.props.type?this.state.externalUrl:"https://github.com/spicetify/spicetify-marketplace/blob/main/src/resources/snippets.ts",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation()},L.default.createElement("div",{className:"main-cardHeader-text main-type-balladBold"},this.props.item.title)),L.default.createElement("div",{className:"main-cardSubHeader-root main-type-mestoBold marketplace-cardSubHeader"},this.props.item.authors&&L.default.createElement(Vr,{authors:this.props.item.authors}),L.default.createElement("span",null,t.join(" ‒ "))),L.default.createElement("p",{className:"marketplace-card-desc"},"snippet"===this.props.type?this.props.item.description:this.props.item.manifest?.description),this.props.item.lastUpdated&&L.default.createElement("p",{className:"marketplace-card-desc"},y("grid.lastUpdated",{val:new Date(this.props.item.lastUpdated),formatParams:{val:{year:"numeric",month:"long",day:"numeric"}}})),this.tags.length?L.default.createElement("div",{className:"marketplace-card__bottom-meta main-type-mestoBold"},L.default.createElement(qr,{tags:this.tags,showTags:this.props.CONFIG.visual.tags})):null,a&&L.default.createElement("div",{className:"marketplace-card__bottom-meta main-type-mestoBold"},"✓ ",y("grid.installed")),L.default.createElement(O.ReactComponent.TooltipWrapper,{label:"app"===this.props.type?y("github"):y(a?"remove":"install"),renderInline:!0},L.default.createElement("div",{className:"main-card-PlayButtonContainer"},L.default.createElement(g,{classes:["marketplace-installButton"],type:"circle",label:"app"===this.props.type?y("github"):y(a?"remove":"install"),onClick:e=>{e.stopPropagation(),this.buttonClicked()}},"app"===this.props.type?L.default.createElement(Br,null):a?L.default.createElement(Dr,null):L.default.createElement(zr,null)))))))):(console.debug("Card item not installed"),null)}},Kr=qt()(Gr),Jr=window.Spicetify,a=class extends s.default.Component{constructor(e){super(e),Object.assign(this,e),this.updateAppConfig=e.updateAppConfig.bind(this),this.sortConfig={by:C(w.sort,"top")},this.state={version:ma,newUpdate:!1,searchValue:"",cards:[],tabs:e.CONFIG.tabs,rest:!0,endOfList:!1,schemes:e.CONFIG.theme.schemes,activeScheme:e.CONFIG.theme.activeScheme,activeThemeKey:e.CONFIG.theme.activeThemeKey}}searchRequested;endOfList=!1;lastScroll=0;requestQueue=[];requestPage=0;cardList=[];sortConfig;gridUpdateTabs;gridUpdatePostsVisual;checkScroll;CONFIG;updateAppConfig;BLACKLIST;SNIPPETS;getInstalledTheme(){var e=localStorage.getItem(w.themeInstalled);return(e=e&&localStorage.getItem(e))?JSON.parse(e):null}newRequest(e){this.cardList=[];var t=[];this.requestQueue.unshift(t),this.loadAmount(t,e)}appendCard(e,t,a){a===this.props.CONFIG.activeTab&&(a=s.default.createElement(Kr,{item:e,key:`${this.props.CONFIG.activeTab}:${e.user}:`+e.title,CONFIG:this.CONFIG,visual:this.props.CONFIG.visual,type:t,activeThemeKey:this.state.activeThemeKey,updateColourSchemes:this.updateColourSchemes.bind(this),updateActiveTheme:this.setActiveTheme.bind(this)}),this.cardList.push(a))}updateSort(e){e&&(this.sortConfig.by=e,localStorage.setItem(w.sort,e)),this.requestPage=0,this.cardList=[],this.setState({cards:[],rest:!1,endOfList:!1}),this.endOfList=!1,this.newRequest(E)}updateTabs(){this.setState({tabs:[...this.props.CONFIG.tabs]})}updatePostsVisual(){this.cardList=this.cardList.map((e,t)=>s.default.createElement(Kr,{...e.props,key:t.toString(),CONFIG:this.CONFIG})),this.setState({cards:[...this.cardList]})}switchTo(e){this.CONFIG.activeTab=e.value,localStorage.setItem(w.activeTab,e.value),this.cardList=[],this.requestPage=0,this.setState({cards:[],rest:!1,endOfList:!1}),this.endOfList=!1,this.newRequest(E)}async loadPage(t){const a=this.CONFIG.activeTab;switch(a){case"Extensions":var e=await gr("spicetify-extensions",this.requestPage,this.BLACKLIST,this.CONFIG.visual.showArchived),r=[];for(const h of e.items){var n=await yr(h.contents_url,h.default_branch,h.stargazers_count,this.CONFIG.visual.hideInstalled);if(1({...e,archived:h.archived,lastUpdated:h.pushed_at,created:h.created_at})))}ja(r,localStorage.getItem("marketplace:sort")||"stars");for(const m of r)this.appendCard(m,"extension",a);this.setState({cards:this.cardList});var o=-1{e=C(e);if(1({...e,archived:b.archived,lastUpdated:b.pushed_at,created:b.created_at})))}this.setState({cards:this.cardList}),ja(c,localStorage.getItem("marketplace:sort")||"stars");for(const y of c)this.appendCard(y,"theme",a);e=-1({...e,archived:S.archived,lastUpdated:S.pushed_at,created:S.created_at})))}this.setState({cards:this.cardList}),ja(d,localStorage.getItem("marketplace:sort")||"stars");for(const k of d)this.appendCard(k,"app",a);i=-1this.appendCard(e,"snippet",a)),this.setState({cards:this.cardList}))}return this.setState({rest:!0,endOfList:!0}),this.endOfList=!0,0}async loadAmount(t,e=E){for(this.setState({rest:!1}),e+=this.cardList.length,this.requestPage=await this.loadPage(t);this.requestPage&&-1!==this.requestPage&&this.cardList.lengthe!==t):(this.requestQueue.shift(),this.setState({rest:!0}))}loadMore(){this.state.rest&&!this.endOfList&&this.loadAmount(this.requestQueue[0],E)}updateColourSchemes(e,t){console.debug("updateColourSchemes",e,t),this.CONFIG.theme.schemes=e,(this.CONFIG.theme.activeScheme=t)&&(Jr.Config.color_scheme=t),e&&t&&e[t]?xa(this.CONFIG.theme.schemes[t]):xa(null);var a=C(w.themeInstalled),r=C(a);r?(r.activeScheme=t,console.debug(r),localStorage.setItem(a,JSON.stringify(r))):console.debug("No installed theme data"),this.setState({schemes:e,activeScheme:t})}async componentDidMount(){fetch(ba).then(e=>e.json()).then(e=>{if(e.message)throw e;this.setState({version:e.name});try{this.setState({newUpdate:ya.default.gt(e.name,ma)})}catch(e){console.error(e)}},e=>{console.error("Failed to check for updates",e)}),this.gridUpdateTabs=this.updateTabs.bind(this),this.gridUpdatePostsVisual=this.updatePostsVisual.bind(this);var e=document.querySelector(".os-viewport")??document.querySelector("#main .main-view-container__scroll-node");this.checkScroll=this.isScrolledBottom.bind(this),e&&(e.addEventListener("scroll",this.checkScroll),this.cardList.length)?0=e.scrollHeight&&this.loadMore()}setActiveTheme(e){this.CONFIG.theme.activeThemeKey=e,this.setState({activeThemeKey:e})}getActiveScheme(){return this.state.activeScheme}render(){const a=this.props["t"];return s.default.createElement("section",{className:"contentSpacing"},s.default.createElement("div",{className:"marketplace-header"},s.default.createElement("div",{className:"marketplace-header__left"},this.state.newUpdate?s.default.createElement("button",{type:"button",title:a("grid.newUpdate"),className:"marketplace-header-icon-button",id:"marketplace-update",onClick:()=>N("UPDATE")},s.default.createElement(zr,null)," ",this.state.version):null,s.default.createElement("h2",{className:"marketplace-header__label"},a("grid.sort.label")),s.default.createElement(er,{onChange:e=>this.updateSort(e),sortBoxOptions:Ca(a),sortBySelectedFn:e=>e.key===this.CONFIG.sort})),s.default.createElement("div",{className:"marketplace-header__right"},this.CONFIG.visual.themeDevTools?s.default.createElement(Jr.ReactComponent.TooltipWrapper,{label:a("devTools.title"),renderInline:!0,placement:"bottom"},s.default.createElement("button",{type:"button","aria-label":a("devTools.title"),className:"marketplace-header-icon-button",onClick:()=>N("THEME_DEV_TOOLS")},s.default.createElement(Tr,null))):null,this.state.activeScheme?s.default.createElement(er,{onChange:e=>this.updateColourSchemes(this.state.schemes,e),sortBoxOptions:Ea(this.state.schemes),sortBySelectedFn:e=>e.key===this.getActiveScheme()}):null,s.default.createElement("div",{className:"searchbar--bar__wrapper"},s.default.createElement("input",{className:"searchbar-bar",type:"text",placeholder:`${a("grid.search")} ${a("tabs."+this.CONFIG.activeTab)}...`,value:this.state.searchValue,onChange:e=>{this.setState({searchValue:e.target.value})}})),s.default.createElement(Jr.ReactComponent.TooltipWrapper,{label:a("settings.title"),renderInline:!0,placement:"bottom"},s.default.createElement("button",{type:"button","aria-label":a("settings.title"),className:"marketplace-header-icon-button",id:"marketplace-settings-button",onClick:()=>N("SETTINGS",this.CONFIG,this.updateAppConfig)},s.default.createElement(Lr,null))))),[{handle:"extension",name:"Extensions"},{handle:"theme",name:"Themes"},{handle:"snippet",name:"Snippets"},{handle:"app",name:"Apps"}].map(t=>{var e=this.cardList.filter(e=>e.props.type===t.handle).filter(e=>{const t=this.state.searchValue.trim().toLowerCase();var{title:e,user:a,authors:r,tags:n}=e.props.item;return!t||e.toLowerCase().includes(t)||a?.toLowerCase().includes(t)||r?.some(e=>e.name.toLowerCase().includes(t))||n?.some(e=>e.toLowerCase().includes(t))}).map(e=>s.default.cloneElement(e,{activeThemeKey:this.state.activeThemeKey,key:e.key})).filter((t,e,a)=>a.findIndex(e=>e.key===t.key)===e);return e.length?s.default.createElement(s.default.Fragment,null,s.default.createElement("h2",{className:"marketplace-card-type-heading"},a("tabs."+t.name)),s.default.createElement("div",{className:"marketplace-grid main-gridContainer-gridContainer main-gridContainer-fixedWidth","data-tab":this.CONFIG.activeTab,"data-card-type":a("tabs."+t.name)},e)):null}),"Snippets"===this.CONFIG.activeTab?s.default.createElement(g,{classes:["marketplace-add-snippet-btn"],onClick:()=>N("ADD_SNIPPET")},"+ ",a("grid.addCSS")):null,s.default.createElement("footer",{className:"marketplace-footer"},!this.state.endOfList&&(this.state.rest&&0${this.props.t("readmePage.loading")}

`};getReadmeHTML=async()=>fetch(this.props.data.readmeURL).then(e=>{if(e.ok)return e.text();throw Spicetify.showNotification(`${this.props.t("readmePage.errorLoading")} (HTTP ${e.status})`,!0)}).then(e=>Ta(e,this.props.data.user,this.props.data.repo)).then(e=>(e||Spicetify.Platform.History.goBack(),e)).catch(e=>(console.error(e),Spicetify.Platform.History.goBack(),null));componentDidMount(){this.getReadmeHTML().then(e=>{null!=e&&this.setState({html:e})})}componentDidUpdate(){const e=document.querySelector("#marketplace-readme")?.closest("main");if(e){const t=setInterval(()=>{document.querySelector("#marketplace-readme")?(e.style.overflowY="visible",e.style.overflowY="auto"):(clearInterval(t),e.style.removeProperty("overflow-y"))},1e3)}document.querySelectorAll("#marketplace-readme img").forEach(e=>{e.addEventListener("error",e=>{var e=e.target,t=e.getAttribute("src"),t="/"===t?.charAt(0)?`https://raw.githubusercontent.com/${this.props.data.user}/${this.props.data.repo}/${this.props.data.branch}/`+t?.slice(1):this.props.data.readmeURL.substring(0,this.props.data.readmeURL.lastIndexOf("/"))+"/"+t;e.setAttribute("src",t)},{once:!0})})}buttonContent(){return"app"===this.props.data.type?{icon:T.default.createElement(Br,null),text:this.props.t("github")}:this.state.isInstalled?{icon:T.default.createElement(Dr,null),text:this.props.t("remove")}:{icon:T.default.createElement(zr,null),text:this.props.t("install")}}render(){var e="control"!==JSON.parse(localStorage.getItem("spicetify-exp-features")||"{}").enableGlobalNavBar?.value&&!0;return T.default.createElement("section",{className:"contentSpacing"},T.default.createElement("div",{className:"marketplace-header",style:{marginTop:e?"60px":"0px"}},T.default.createElement("div",{className:"marketplace-header__left"},T.default.createElement("h1",null,this.props.title)),T.default.createElement("div",{className:"marketplace-header__right"},T.default.createElement(g,{classes:["marketplace-header__button"],onClick:e=>{e.preventDefault(),this.props.data.install(),this.setState({isInstalled:!this.state.isInstalled})},label:this.buttonContent().text},this.buttonContent().icon," ",this.buttonContent().text))),"

Loading...

"===this.state.html?T.default.createElement("footer",{className:"marketplace-footer"},T.default.createElement(xr,null)):T.default.createElement("div",{id:"marketplace-readme",className:"marketplace-readme__container",dangerouslySetInnerHTML:{__html:this.state.html}}))}},Zr=qt()(Me),_e=(r.use(z).use(Wt).init({resources:ha,detection:{order:["navigator","htmlTag"]},fallbackLng:"en",interpolation:{escapeValue:!1}}),class extends ze.default.Component{state={count:0,CONFIG:{}};CONFIG;constructor(e){super(e);e=C(w.tabs,null);let t=[];try{if(t=JSON.parse(e),!Array.isArray(t))throw new Error("Could not parse marketplace tabs key");if(0===t.length)throw new Error("Empty marketplace tabs key");if(0!e).length)throw new Error("Falsey marketplace tabs key")}catch{t=fa,localStorage.setItem(w.tabs,JSON.stringify(t))}let a={},r=null;try{var n=C(w.themeInstalled,null);if(n){var o=C(n,null);if(!o)throw new Error("No installed theme data");a=o.schemes,r=o.activeScheme}else console.debug("No theme set as installed")}catch(e){console.error(e)}this.CONFIG={visual:{stars:JSON.parse(C("marketplace:stars",!0)),tags:JSON.parse(C("marketplace:tags",!0)),showArchived:JSON.parse(C("marketplace:showArchived",!1)),hideInstalled:JSON.parse(C("marketplace:hideInstalled",!1)),colorShift:JSON.parse(C("marketplace:colorShift",!1)),themeDevTools:JSON.parse(C("marketplace:themeDevTools",!1)),albumArtBasedColors:JSON.parse(C("marketplace:albumArtBasedColors",!1)),albumArtBasedColorsMode:C("marketplace:albumArtBasedColorsMode")||"monochrome-light",albumArtBasedColorsVibrancy:C("marketplace:albumArtBasedColorsVibrancy")||"PROMINENT",type:JSON.parse(C("marketplace:type",!1)),followers:JSON.parse(C("marketplace:followers",!1))},tabs:t,activeTab:C(w.activeTab,t[0]),theme:{activeThemeKey:C(w.themeInstalled,null),schemes:a,activeScheme:r},sort:C(w.sort,"stars")},this.CONFIG.activeTab&&this.CONFIG.tabs.filter(e=>e.name===this.CONFIG.activeTab).length||(this.CONFIG.activeTab=this.CONFIG.tabs[0].name)}updateConfig=e=>{this.CONFIG={...e},console.debug("updated config",this.CONFIG),this.setState({CONFIG:{...e}})};render(){var{location:e,replace:t}=Spicetify.Platform.History;return e.pathname===ga+"/readme"?e.state?.data?ze.default.createElement(Zr,{title:y("readmePage.title"),data:e.state.data}):(t(ga),null):ze.default.createElement(Wr,{title:y("grid.spicetifyMarketplace"),CONFIG:this.CONFIG,updateAppConfig:this.updateConfig})}}),Xr=qt()(_e),Yr=t(b());return Pe=je,$(M({},"__esModule",{value:!0}),Pe)})();const render=()=>marketplace.default(); \ No newline at end of file diff --git a/.config/spicetify/CustomApps/stats/extension.css b/.config/spicetify/CustomApps/stats/extension.css new file mode 100644 index 00000000..7534af3f --- /dev/null +++ b/.config/spicetify/CustomApps/stats/extension.css @@ -0,0 +1,76 @@ +/* ../../../AppData/Local/Temp/tmp-15744-866d0PjWRxih/18d53b11b111/config_modal.css */ +#config-container { + gap: 10px; + display: flex; + flex-direction: column; +} +#config-container .section-header { + box-sizing: border-box; + -webkit-tap-highlight-color: transparent; + margin-block: 0px; + font-size: 1.125rem; + font-weight: 700; + color: var(--spice-text); +} +#config-container .col.description { + box-sizing: border-box; + -webkit-tap-highlight-color: transparent; + margin-block: 0px; + font-size: 0.875rem; + font-weight: 400; + color: var(--spice-subtext); +} +#config-container .disabled { + opacity: 0; + pointer-events: none; +} +#config-container .text-input { + background: rgba(var(--spice-rgb-selected-row), 0.1); + border: 1px solid transparent; + border-radius: 4px; + color: var(--spice-text); + font-family: inherit; + font-size: 14px; + height: 32px; + padding: 0 12px; + width: 100%; +} +#config-container .text-input:focus { + background-color: var(--spice-tab-active); + border: 1px solid var(--spice-button-disabled); + outline: none; +} +#config-container .dropdown-input { + background-color: var(--spice-tab-active); + border: 0; + border-radius: 4px; + color: rgba(var(--spice-rgb-selected-row), 0.7); + font-size: 14px; + font-weight: 400; + height: 32px; + letter-spacing: 0.24px; + line-height: 20px; + padding: 0 32px 0 12px; + width: 100%; +} +#config-container .tooltip-icon { + float: right; + margin-left: 10px; + display: flex; + align-items: center; + height: 22px; + fill: var(--spice-subtext); +} +#config-container .tooltip-icon:hover { + fill: var(--spice-text); +} +#config-container .tooltip { + text-align: center; +} +#config-container .setting-row { + display: flex; + justify-content: space-between; +} +#config-container .playback-progressbar { + width: 200px; +} diff --git a/.config/spicetify/CustomApps/stats/extension.js b/.config/spicetify/CustomApps/stats/extension.js index 7d9c28ab..ef6499cd 100644 --- a/.config/spicetify/CustomApps/stats/extension.js +++ b/.config/spicetify/CustomApps/stats/extension.js @@ -8,22 +8,9 @@ var stats = (() => { var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; - var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; - var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; - var __spreadValues = (a, b) => { - for (var prop in b || (b = {})) - if (__hasOwnProp.call(b, prop)) - __defNormalProp(a, prop, b[prop]); - if (__getOwnPropSymbols) - for (var prop of __getOwnPropSymbols(b)) { - if (__propIsEnum.call(b, prop)) - __defNormalProp(a, prop, b[prop]); - } - return a; - }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; @@ -39,6 +26,10 @@ var stats = (() => { isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); + var __publicField = (obj, key, value) => { + __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + return value; + }; // external-global-plugin:react var require_react = __commonJS({ @@ -48,24 +39,44 @@ var stats = (() => { }); // src/extensions/extension.tsx - var import_react7 = __toESM(require_react()); + var import_react15 = __toESM(require_react()); // src/pages/playlist.tsx - var import_react6 = __toESM(require_react()); + var import_react12 = __toESM(require_react()); // src/components/cards/stat_card.tsx var import_react = __toESM(require_react()); - var StatCard = (props) => { - return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { + function formatValue(name, value) { + switch (name) { + case "tempo": + return `${Math.round(value)} bpm`; + case "popularity": + return `${Math.round(value)} %`; + default: + return `${Math.round(value * 100)} %`; + } + } + function normalizeString(inputString) { + return inputString.charAt(0).toUpperCase() + inputString.slice(1).toLowerCase(); + } + function StatCard(props) { + const { TextComponent } = Spicetify.ReactComponent; + const { label, value } = props; + return /* @__PURE__ */ import_react.default.createElement("div", { className: "main-card-card" - }, /* @__PURE__ */ import_react.default.createElement("div", { - className: "stats-cardValue" - }, props.value), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("div", { - className: "TypeElement-balladBold-textBase-4px-type main-cardHeader-text stats-cardText", - "data-encore-id": "type" - }, props.stat)))); - }; - var stat_card_default = import_react.default.memo(StatCard); + }, /* @__PURE__ */ import_react.default.createElement(TextComponent, { + as: "div", + semanticColor: "textBase", + variant: "alto", + children: typeof value === "number" ? formatValue(label, value) : value + }), /* @__PURE__ */ import_react.default.createElement(TextComponent, { + as: "div", + semanticColor: "textBase", + variant: "balladBold", + children: normalizeString(label) + })); + } + var stat_card_default = StatCard; // src/components/cards/genres_card.tsx var import_react2 = __toESM(require_react()); @@ -94,98 +105,388 @@ var stats = (() => { className: `main-card-card stats-genreCard` }, genreLines(genresArray, total)); }; - var genres_card_default = import_react2.default.memo(genresCard); + var genres_card_default = genresCard; - // src/components/cards/artist_card.tsx + // ../library/src/components/collection_menu.tsx + var import_react5 = __toESM(require_react()); + + // ../library/src/components/text_input_dialog.tsx var import_react3 = __toESM(require_react()); - var DraggableComponent = (props) => { - var _a, _b; - const dragHandler = (_b = (_a = Spicetify.ReactHook).DragHandler) == null ? void 0 : _b.call(_a, [props.uri], props.title); - return /* @__PURE__ */ import_react3.default.createElement("div", { - onDragStart: dragHandler, - draggable: "true", - className: "main-card-draggable" - }, props.children); - }; - var Card = ({ name, image, uri, subtext }) => { - const goToArtist = (uriString) => { - if (uriString.includes("last")) { - return window.open(uriString, "_blank"); - } - const uriObj = Spicetify.URI.fromString(uriString); - const url = uriObj.toURLPath(true); - Spicetify.Platform.History.push(url); - Spicetify.Platform.History.goForward(); + var TextInputDialog = (props) => { + const { ButtonPrimary } = Spicetify.ReactComponent; + const { def, placeholder, onSave } = props; + const [value, setValue] = import_react3.default.useState(def); + const onSubmit = (e) => { + e.preventDefault(); + Spicetify.PopupModal.hide(); + onSave(value); }; - const isArtist = uri.includes("artist"); - const MenuWrapper = import_react3.default.memo((props) => { - return isArtist ? /* @__PURE__ */ import_react3.default.createElement(Spicetify.ReactComponent.ArtistMenu, __spreadValues({}, props)) : /* @__PURE__ */ import_react3.default.createElement(Spicetify.ReactComponent.AlbumMenu, __spreadValues({}, props)); - }); - return /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement(Spicetify.ReactComponent.ContextMenu, { - menu: /* @__PURE__ */ import_react3.default.createElement(MenuWrapper, { - uri - }), - trigger: "right-click" - }, /* @__PURE__ */ import_react3.default.createElement("div", { - className: "main-card-card" - }, /* @__PURE__ */ import_react3.default.createElement(DraggableComponent, { - uri, - title: name - }, /* @__PURE__ */ import_react3.default.createElement("div", { - className: "main-card-imageContainer" - }, /* @__PURE__ */ import_react3.default.createElement("div", { - className: `main-cardImage-imageWrapper ${isArtist ? `main-cardImage-circular` : ""}` - }, /* @__PURE__ */ import_react3.default.createElement("div", { - className: "" - }, /* @__PURE__ */ import_react3.default.createElement("img", { - "aria-hidden": "false", - draggable: "false", - loading: "lazy", - src: image, - className: `main-image-image main-cardImage-image ${isArtist ? `main-cardImage-circular` : ""} main-image-loaded` - }))), /* @__PURE__ */ import_react3.default.createElement("div", { - className: "main-card-PlayButtonContainer", - onClick: () => Spicetify.Player.playUri(uri) - }, /* @__PURE__ */ import_react3.default.createElement("div", { - className: "main-playButton-PlayButton" - }, /* @__PURE__ */ import_react3.default.createElement("button", { + return /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("form", { + className: "text-input-form", + onSubmit + }, /* @__PURE__ */ import_react3.default.createElement("label", { + className: "text-input-wrapper" + }, /* @__PURE__ */ import_react3.default.createElement("input", { + className: "text-input", + type: "text", + value, + placeholder, + onChange: (e) => setValue(e.target.value) + })), /* @__PURE__ */ import_react3.default.createElement("button", { + type: "submit", "data-encore-id": "buttonPrimary", - className: "Button-md-useBrowserDefaultFocusStyle Button-md-buttonPrimary-useBrowserDefaultFocusStyle Button-medium-buttonPrimary-useBrowserDefaultFocusStyle" + className: "Button-sc-qlcn5g-0 Button-small-buttonPrimary" }, /* @__PURE__ */ import_react3.default.createElement("span", { - className: "ButtonInner-md-iconOnly ButtonInner-medium-iconOnly encore-bright-accent-set" - }, /* @__PURE__ */ import_react3.default.createElement("span", { - "aria-hidden": "true", - className: "Wrapper-md-24-only Wrapper-medium-medium-only" - }, /* @__PURE__ */ import_react3.default.createElement("svg", { + className: "ButtonInner-sc-14ud5tc-0 ButtonInner-small encore-bright-accent-set" + }, "Save")))); + }; + var text_input_dialog_default = TextInputDialog; + + // ../library/src/components/leading_icon.tsx + var import_react4 = __toESM(require_react()); + var LeadingIcon = ({ path }) => { + return /* @__PURE__ */ import_react4.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: `${path}` + }, + iconSize: 16 + }); + }; + var leading_icon_default = LeadingIcon; + + // ../library/src/components/collection_menu.tsx + var editIconPath = ''; + var deleteIconPath = ''; + var CollectionMenu = ({ id }) => { + const { Menu, MenuItem } = Spicetify.ReactComponent; + const deleteCollection = () => { + SpicetifyLibrary.CollectionWrapper.deleteCollection(id); + }; + const renameCollection = () => { + const name = SpicetifyLibrary.CollectionWrapper.getCollection(id).name; + const rename = (newName) => { + SpicetifyLibrary.CollectionWrapper.renameCollection(id, newName); + }; + Spicetify.PopupModal.display({ + title: "Rename Collection", + content: /* @__PURE__ */ import_react5.default.createElement(text_input_dialog_default, { + def: name, + onSave: rename + }) + }); + }; + const image = SpicetifyLibrary.CollectionWrapper.getCollection(id).imgUrl; + const setCollectionImage = () => { + const setImg = (imgUrl) => { + SpicetifyLibrary.CollectionWrapper.setCollectionImage(id, imgUrl); + }; + Spicetify.PopupModal.display({ + title: "Set Collection Image", + content: /* @__PURE__ */ import_react5.default.createElement(text_input_dialog_default, { + def: image, + placeholder: "Image URL", + onSave: setImg + }) + }); + }; + const removeImage = () => { + SpicetifyLibrary.CollectionWrapper.removeCollectionImage(id); + }; + return /* @__PURE__ */ import_react5.default.createElement(Menu, null, /* @__PURE__ */ import_react5.default.createElement(MenuItem, { + leadingIcon: /* @__PURE__ */ import_react5.default.createElement(leading_icon_default, { + path: editIconPath + }), + onClick: renameCollection + }, "Rename"), /* @__PURE__ */ import_react5.default.createElement(MenuItem, { + leadingIcon: /* @__PURE__ */ import_react5.default.createElement(leading_icon_default, { + path: deleteIconPath + }), + onClick: deleteCollection + }, "Delete"), /* @__PURE__ */ import_react5.default.createElement(MenuItem, { + leadingIcon: /* @__PURE__ */ import_react5.default.createElement(leading_icon_default, { + path: editIconPath + }), + onClick: setCollectionImage + }, "Set Collection Image"), image && /* @__PURE__ */ import_react5.default.createElement(MenuItem, { + leadingIcon: /* @__PURE__ */ import_react5.default.createElement(leading_icon_default, { + path: deleteIconPath + }), + onClick: removeImage + }, "Remove Collection Image")); + }; + var collection_menu_default = CollectionMenu; + + // ../library/src/components/folder_menu.tsx + var import_react6 = __toESM(require_react()); + var editIconPath2 = ''; + var deleteIconPath2 = ''; + var FolderMenu = ({ uri }) => { + const { MenuItem, Menu } = Spicetify.ReactComponent; + const image = SpicetifyLibrary.FolderImageWrapper.getFolderImage(uri); + const setImage = () => { + const setNewImage = (newUrl) => { + SpicetifyLibrary.FolderImageWrapper.setFolderImage({ uri, url: newUrl }); + }; + Spicetify.PopupModal.display({ + title: "Set Folder Image", + content: /* @__PURE__ */ import_react6.default.createElement(text_input_dialog_default, { + def: image, + onSave: setNewImage + }) + }); + }; + const removeImage = () => { + SpicetifyLibrary.FolderImageWrapper.removeFolderImage(uri); + }; + return /* @__PURE__ */ import_react6.default.createElement(Menu, null, /* @__PURE__ */ import_react6.default.createElement(MenuItem, { + leadingIcon: /* @__PURE__ */ import_react6.default.createElement(leading_icon_default, { + path: editIconPath2 + }), + onClick: setImage + }, "Set Folder Image"), image && /* @__PURE__ */ import_react6.default.createElement(MenuItem, { + leadingIcon: /* @__PURE__ */ import_react6.default.createElement(leading_icon_default, { + path: deleteIconPath2 + }), + onClick: removeImage + }, "Remove Folder Image")); + }; + var folder_menu_default = FolderMenu; + + // ../shared/components/spotify_card.tsx + var import_react8 = __toESM(require_react()); + + // ../shared/components/folder_fallback.tsx + var import_react7 = __toESM(require_react()); + var FolderSVG = (e) => { + return /* @__PURE__ */ import_react7.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + viewBox: "0 0 24 24", + size: "xxlarge", + dangerouslySetInnerHTML: { + __html: '' + }, + ...e + }); + }; + var folder_fallback_default = FolderSVG; + + // ../shared/components/spotify_card.tsx + function SpotifyCard(props) { + const { Cards, TextComponent, ArtistMenu, AlbumMenu, PodcastShowMenu, PlaylistMenu, ContextMenu } = Spicetify.ReactComponent; + const { FeatureCard: Card, CardImage } = Cards; + const { createHref, push } = Spicetify.Platform.History; + const { type, header, uri, imageUrl, subheader, artistUri } = props; + const backupImageUrl = type === "folder" || type === "collection" ? "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/folder_placeholder.png" : "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/def_placeholder.png"; + const Menu = () => { + switch (type) { + case "artist": + return /* @__PURE__ */ import_react8.default.createElement(ArtistMenu, { + uri + }); + case "album": + return /* @__PURE__ */ import_react8.default.createElement(AlbumMenu, { + uri, + artistUri, + canRemove: true + }); + case "playlist": + return /* @__PURE__ */ import_react8.default.createElement(PlaylistMenu, { + uri + }); + case "show": + return /* @__PURE__ */ import_react8.default.createElement(PodcastShowMenu, { + uri + }); + case "collection": + return /* @__PURE__ */ import_react8.default.createElement(collection_menu_default, { + id: uri + }); + case "folder": + return /* @__PURE__ */ import_react8.default.createElement(folder_menu_default, { + uri + }); + default: + return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null); + } + }; + const lastfmProps = type === "lastfm" ? { onClick: () => window.open(uri, "_blank"), isPlayable: false, delegateNavigation: true } : {}; + const folderProps = type === "folder" ? { + delegateNavigation: true, + onClick: () => { + createHref({ pathname: `/library/folder/${uri}` }); + push({ pathname: `/library/folder/${uri}` }); + } + } : {}; + const collectionProps = type === "collection" ? { + delegateNavigation: true, + onClick: () => { + createHref({ pathname: `/library/collection/${uri}` }); + push({ pathname: `/library/collection/${uri}` }); + } + } : {}; + return /* @__PURE__ */ import_react8.default.createElement(ContextMenu, { + menu: Menu(), + trigger: "right-click" + }, /* @__PURE__ */ import_react8.default.createElement(Card, { + featureIdentifier: type, + headerText: header, + renderCardImage: () => /* @__PURE__ */ import_react8.default.createElement(CardImage, { + images: [ + { + height: 640, + url: imageUrl, + width: 640 + } + ], + isCircular: type === "artist", + FallbackComponent: folder_fallback_default + }), + renderSubHeaderContent: () => /* @__PURE__ */ import_react8.default.createElement(TextComponent, { + as: "div", + variant: "mesto", + semanticColor: "textSubdued", + children: subheader + }), + uri, + ...lastfmProps, + ...folderProps, + ...collectionProps + })); + } + var spotify_card_default = SpotifyCard; + + // ../shared/components/status.tsx + var import_react9 = __toESM(require_react()); + var ErrorIcon = () => { + return /* @__PURE__ */ import_react9.default.createElement("svg", { + "data-encore-id": "icon", role: "img", - height: "24", - width: "24", + "aria-hidden": "true", + viewBox: "0 0 24 24", + className: "status-icon" + }, /* @__PURE__ */ import_react9.default.createElement("path", { + d: "M11 18v-2h2v2h-2zm0-4V6h2v8h-2z" + }), /* @__PURE__ */ import_react9.default.createElement("path", { + d: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12z" + })); + }; + var LibraryIcon = () => { + return /* @__PURE__ */ import_react9.default.createElement("svg", { + role: "img", + height: "46", + width: "46", "aria-hidden": "true", viewBox: "0 0 24 24", "data-encore-id": "icon", - className: "Svg-img-24 Svg-img-24-icon Svg-img-icon-medium" - }, /* @__PURE__ */ import_react3.default.createElement("path", { - d: "m7.05 3.606 13.49 7.788a.7.7 0 0 1 0 1.212L7.05 20.394A.7.7 0 0 1 6 19.788V4.212a.7.7 0 0 1 1.05-.606z" - })))))))), /* @__PURE__ */ import_react3.default.createElement("div", { - className: "main-card-cardMetadata" - }, /* @__PURE__ */ import_react3.default.createElement("a", { - draggable: "false", - className: "main-cardHeader-link", - dir: "auto" - }, /* @__PURE__ */ import_react3.default.createElement("div", { - className: "TypeElement-balladBold-textBase-4px-type main-cardHeader-text", - "data-encore-id": "type" - }, name)), /* @__PURE__ */ import_react3.default.createElement("div", { - className: "TypeElement-mesto-textSubdued-type main-cardSubHeader-root", - "data-encore-id": "type" - }, /* @__PURE__ */ import_react3.default.createElement("span", null, subtext))), /* @__PURE__ */ import_react3.default.createElement("div", { - className: "main-card-cardLink", - onClick: () => goToArtist(uri) - }))))); + className: "status-icon" + }, /* @__PURE__ */ import_react9.default.createElement("path", { + d: "M14.5 2.134a1 1 0 0 1 1 0l6 3.464a1 1 0 0 1 .5.866V21a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1V3a1 1 0 0 1 .5-.866zM16 4.732V20h4V7.041l-4-2.309zM3 22a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1zm6 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1z" + })); }; - var artist_card_default = import_react3.default.memo(Card); + var Status = (props) => { + const [isVisible, setIsVisible] = import_react9.default.useState(false); + import_react9.default.useEffect(() => { + const to = setTimeout(() => { + setIsVisible(true); + }, 500); + return () => clearTimeout(to); + }, []); + return isVisible ? /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement("div", { + className: "loadingWrapper" + }, props.icon === "error" ? /* @__PURE__ */ import_react9.default.createElement(ErrorIcon, null) : /* @__PURE__ */ import_react9.default.createElement(LibraryIcon, null), /* @__PURE__ */ import_react9.default.createElement("h1", null, props.heading), /* @__PURE__ */ import_react9.default.createElement("h3", null, props.subheading))) : /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null); + }; + var status_default = Status; + + // src/components/inline_grid.tsx + var import_react10 = __toESM(require_react()); + function scrollGrid(event) { + const { target } = event; + if (!(target instanceof HTMLElement)) + return; + const grid = target.parentNode?.querySelector("div"); + if (!grid) + return; + grid.scrollLeft += grid.clientWidth; + if (grid.scrollWidth - grid.clientWidth - grid.scrollLeft <= grid.clientWidth) { + grid.setAttribute("data-scroll", "end"); + } else { + grid.setAttribute("data-scroll", "both"); + } + } + function scrollGridLeft(event) { + const { target } = event; + if (!(target instanceof HTMLElement)) + return; + const grid = target.parentNode?.querySelector("div"); + if (!grid) + return; + grid.scrollLeft -= grid.clientWidth; + if (grid.scrollLeft <= grid.clientWidth) { + grid.setAttribute("data-scroll", "start"); + } else { + grid.setAttribute("data-scroll", "both"); + } + } + function InlineGrid(props) { + const { children, special } = props; + return /* @__PURE__ */ import_react10.default.createElement("section", { + className: "stats-gridInlineSection" + }, /* @__PURE__ */ import_react10.default.createElement("button", { + className: "stats-scrollButton", + onClick: scrollGridLeft + }, "<"), /* @__PURE__ */ import_react10.default.createElement("button", { + className: "stats-scrollButton", + onClick: scrollGrid + }, ">"), /* @__PURE__ */ import_react10.default.createElement("div", { + className: `main-gridContainer-gridContainer stats-gridInline${special ? " stats-specialGrid" : ""}`, + "data-scroll": "start" + }, children)); + } + var inline_grid_default = import_react10.default.memo(InlineGrid); + + // src/components/shelf.tsx + var import_react11 = __toESM(require_react()); + function Shelf(props) { + const { TextComponent } = Spicetify.ReactComponent; + const { title, children } = props; + return /* @__PURE__ */ import_react11.default.createElement("section", { + className: "main-shelf-shelf Shelf" + }, /* @__PURE__ */ import_react11.default.createElement("div", { + className: "main-shelf-header" + }, /* @__PURE__ */ import_react11.default.createElement("div", { + className: "main-shelf-topRow" + }, /* @__PURE__ */ import_react11.default.createElement("div", { + className: "main-shelf-titleWrapper" + }, /* @__PURE__ */ import_react11.default.createElement(TextComponent, { + children: title, + as: "h2", + variant: "canon", + semanticColor: "textBase" + })))), /* @__PURE__ */ import_react11.default.createElement("section", null, children)); + } + var shelf_default = import_react11.default.memo(Shelf); + + // src/endpoints.ts + var SPOTIFY = { + toptracks: (range) => `https://api.spotify.com/v1/me/top/tracks?limit=50&offset=0&time_range=${range}`, + topartists: (range) => `https://api.spotify.com/v1/me/top/artists?limit=50&offset=0&time_range=${range}`, + artists: (artists) => `https://api.spotify.com/v1/artists?ids=${filter(artists)}`, + rootlist: "sp://core-playlist/v1/rootlist", + playlist: (uri) => `sp://core-playlist/v1/playlist/${uri}`, + search: (track, artist) => `https://api.spotify.com/v1/search?q=track:${filter(track)}+artist:${filter(artist)}&type=track`, + searchartist: (artist) => `https://api.spotify.com/v1/search?q=artist:${filter(artist)}&type=artist`, + searchalbum: (album, artist) => `https://api.spotify.com/v1/search?q=${filter(album)}+artist:${filter(artist)}&type=album`, + audiofeatures: (ids) => `https://api.spotify.com/v1/audio-features?ids=${ids}`, + queryliked: (ids) => `https://api.spotify.com/v1/me/tracks/contains?ids=${ids}` + }; + var PLACEHOLDER = "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/stats/src/styles/placeholder.png"; // src/funcs.ts + function filter(str) { + const normalizedStr = str.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); + return normalizedStr.replace(/[^a-zA-Z0-9\-._~:/?#[\]@!$&()*+,;= ]/g, "").replace(/ /g, "+"); + } var apiRequest = async (name, url, timeout = 5, log = true) => { try { const timeStart = window.performance.now(); @@ -217,12 +518,11 @@ var stats = (() => { batches.push(batch); } const promises = batches.map((batch, index) => { - const url = `https://api.spotify.com/v1/audio-features?ids=${batch.join(",")}`; - return apiRequest("audioFeaturesBatch" + index, url, 5, false); + return apiRequest(`audioFeaturesBatch${index}`, SPOTIFY.audiofeatures(batch.join(",")), 5, false); }); const responses = await Promise.all(promises); const data = responses.reduce((acc, response) => { - if (!(response == null ? void 0 : response.audio_features)) + if (!response?.audio_features) return acc; return acc.concat(response.audio_features); }, []); @@ -232,17 +532,12 @@ var stats = (() => { let album_keys = Object.keys(albums).filter((id) => id.match(/^[a-zA-Z0-9]{22}$/)).sort((a, b) => albums[b] - albums[a]).slice(0, 100); let release_years = {}; let total_album_tracks = 0; + const cachedAlbumsSet = new Set(cachedAlbums?.map((album) => album.uri)); let top_albums = await Promise.all( album_keys.map(async (albumID) => { - var _a, _b, _c; let albumMeta; - if (cachedAlbums) { - for (let i = 0; i < cachedAlbums.length; i++) { - if (cachedAlbums[i].uri === `spotify:album:${albumID}`) { - albumMeta = cachedAlbums[i]; - break; - } - } + if (cachedAlbums && cachedAlbumsSet.has(`spotify:album:${albumID}`)) { + albumMeta = cachedAlbums.find((album) => album.uri === `spotify:album:${albumID}`); } if (!albumMeta) { try { @@ -252,20 +547,20 @@ var stats = (() => { offset: 0, limit: 50 }); - if (!((_b = (_a = albumMeta == null ? void 0 : albumMeta.data) == null ? void 0 : _a.albumUnion) == null ? void 0 : _b.name)) + if (!albumMeta?.data?.albumUnion?.name) throw new Error("Invalid URI"); } catch (e) { console.error("stats - album metadata request failed:", e); return; } } - const releaseYear = (albumMeta == null ? void 0 : albumMeta.release_year) || albumMeta.data.albumUnion.date.isoString.slice(0, 4); + const releaseYear = albumMeta?.release_year || albumMeta.data.albumUnion.date.isoString.slice(0, 4); release_years[releaseYear] = (release_years[releaseYear] || 0) + albums[albumID]; total_album_tracks += albums[albumID]; return { name: albumMeta.name || albumMeta.data.albumUnion.name, uri: albumMeta.uri || albumMeta.data.albumUnion.uri, - image: albumMeta.image || ((_c = albumMeta.data.albumUnion.coverArt.sources[0]) == null ? void 0 : _c.url) || "https://commons.wikimedia.org/wiki/File:Black_square.jpg", + image: albumMeta.image || albumMeta.data.albumUnion.coverArt.sources[0]?.url || PLACEHOLDER, release_year: releaseYear, freq: albums[albumID] }; @@ -275,15 +570,13 @@ var stats = (() => { return [top_albums, Object.entries(release_years), total_album_tracks]; }; var fetchTopArtists = async (artists) => { - var _a; if (Object.keys(artists).length === 0) return [[], [], 0]; let artist_keys = Object.keys(artists).filter((id) => id.match(/^[a-zA-Z0-9]{22}$/)).sort((a, b) => artists[b] - artists[a]).slice(0, 50); let genres = {}; let total_genre_tracks = 0; - const artistsMeta = await apiRequest("artistsMetadata", `https://api.spotify.com/v1/artists?ids=${artist_keys.join(",")}`); - let top_artists = (_a = artistsMeta == null ? void 0 : artistsMeta.artists) == null ? void 0 : _a.map((artist) => { - var _a2; + const artistsMeta = await apiRequest("artistsMetadata", SPOTIFY.artists(artist_keys.join(","))); + let top_artists = artistsMeta?.artists?.map((artist) => { if (!artist) return null; artist.genres.forEach((genre) => { @@ -293,7 +586,7 @@ var stats = (() => { return { name: artist.name, uri: artist.uri, - image: ((_a2 = artist.images[2]) == null ? void 0 : _a2.url) || "https://commons.wikimedia.org/wiki/File:Black_square.jpg", + image: artist.images[2]?.url || PLACEHOLDER, freq: artists[artist.id] }; }); @@ -302,90 +595,16 @@ var stats = (() => { return [top_artists, top_genres, total_genre_tracks]; }; - // src/components/status.tsx - var import_react4 = __toESM(require_react()); - var ErrorIcon = () => { - return /* @__PURE__ */ import_react4.default.createElement("svg", { - "data-encore-id": "icon", - role: "img", - "aria-hidden": "true", - viewBox: "0 0 24 24", - className: "status-icon" - }, /* @__PURE__ */ import_react4.default.createElement("path", { - d: "M11 18v-2h2v2h-2zm0-4V6h2v8h-2z" - }), /* @__PURE__ */ import_react4.default.createElement("path", { - d: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12z" - })); - }; - var LibraryIcon = () => { - return /* @__PURE__ */ import_react4.default.createElement("svg", { - role: "img", - height: "46", - width: "46", - "aria-hidden": "true", - viewBox: "0 0 24 24", - "data-encore-id": "icon", - className: "status-icon" - }, /* @__PURE__ */ import_react4.default.createElement("path", { - d: "M14.5 2.134a1 1 0 0 1 1 0l6 3.464a1 1 0 0 1 .5.866V21a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1V3a1 1 0 0 1 .5-.866zM16 4.732V20h4V7.041l-4-2.309zM3 22a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1zm6 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1z" - })); - }; - var Status = (props) => { - const [isVisible, setIsVisible] = import_react4.default.useState(false); - import_react4.default.useEffect(() => { - const to = setTimeout(() => { - setIsVisible(true); - }, 500); - return () => clearTimeout(to); - }, []); - return isVisible ? /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement("div", { - className: "stats-loadingWrapper" - }, props.icon === "error" ? /* @__PURE__ */ import_react4.default.createElement(ErrorIcon, null) : /* @__PURE__ */ import_react4.default.createElement(LibraryIcon, null), /* @__PURE__ */ import_react4.default.createElement("h1", null, props.heading), /* @__PURE__ */ import_react4.default.createElement("h3", null, props.subheading))) : /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null); - }; - var status_default = Status; - - // src/components/inline_grid.tsx - var import_react5 = __toESM(require_react()); - var scrollGrid = (event) => { - const grid = event.target.parentNode.querySelector("div"); - grid.scrollLeft += grid.clientWidth; - if (grid.scrollWidth - grid.clientWidth - grid.scrollLeft <= grid.clientWidth) { - grid.setAttribute("data-scroll", "end"); - } else { - grid.setAttribute("data-scroll", "both"); - } - }; - var scrollGridLeft = (event) => { - const grid = event.target.parentNode.querySelector("div"); - grid.scrollLeft -= grid.clientWidth; - if (grid.scrollLeft <= grid.clientWidth) { - grid.setAttribute("data-scroll", "start"); - } else { - grid.setAttribute("data-scroll", "both"); - } - }; - var InlineGrid = (props) => { - return /* @__PURE__ */ import_react5.default.createElement("section", { - className: "stats-gridInlineSection" - }, /* @__PURE__ */ import_react5.default.createElement("button", { - className: "stats-scrollButton", - onClick: scrollGridLeft - }, "<"), /* @__PURE__ */ import_react5.default.createElement("button", { - className: "stats-scrollButton", - onClick: scrollGrid - }, ">"), /* @__PURE__ */ import_react5.default.createElement("div", { - className: `main-gridContainer-gridContainer stats-gridInline${props.special ? " stats-specialGrid" : ""}`, - "data-scroll": "start" - }, props.children)); - }; - var inline_grid_default = InlineGrid; - // src/pages/playlist.tsx var PlaylistPage = ({ uri }) => { - const [library, setLibrary] = import_react6.default.useState(100); + const { ReactComponent, ReactQuery, Platform, _platform } = Spicetify; + const { History, ReduxStore } = Platform; + const { QueryClientProvider, QueryClient } = ReactQuery; + const { Router, Route, Routes, PlatformProvider, StoreProvider } = ReactComponent; + const [library, setLibrary] = import_react12.default.useState(100); const fetchData = async () => { const start = window.performance.now(); - const playlistMeta = await apiRequest("playlistMeta", `sp://core-playlist/v1/playlist/${uri}`); + const playlistMeta = await apiRequest("playlistMeta", SPOTIFY.playlist(uri)); if (!playlistMeta) { setLibrary(200); return; @@ -430,7 +649,11 @@ var stats = (() => { audioFeatures[feature] += track[feature]; }); } - audioFeatures = __spreadValues({ popularity, explicitness: explicitCount }, audioFeatures); + audioFeatures = { + popularity, + explicitness: explicitCount, + ...audioFeatures + }; for (let key in audioFeatures) { audioFeatures[key] /= fetchedFeatures.length; } @@ -449,158 +672,393 @@ var stats = (() => { setLibrary(stats2); console.log("total playlist stats fetch time:", window.performance.now() - start); }; - import_react6.default.useEffect(() => { + import_react12.default.useEffect(() => { fetchData(); }, []); switch (library) { case 200: - return /* @__PURE__ */ import_react6.default.createElement(status_default, { + return /* @__PURE__ */ import_react12.default.createElement(status_default, { icon: "error", heading: "Failed to Fetch Stats", subheading: "Make an issue on Github" }); case 100: - return /* @__PURE__ */ import_react6.default.createElement(status_default, { + return /* @__PURE__ */ import_react12.default.createElement(status_default, { icon: "library", heading: "Analysing the Playlist", subheading: "This may take a while" }); } - const parseVal = (obj) => { - switch (obj[0]) { - case "tempo": - return Math.round(obj[1]) + "bpm"; - case "popularity": - return Math.round(obj[1]) + "%"; - default: - return Math.round(obj[1] * 100) + "%"; - } - }; - const statCards = []; - Object.entries(library.audioFeatures).forEach((obj) => { - statCards.push(/* @__PURE__ */ import_react6.default.createElement(stat_card_default, { - stat: obj[0][0].toUpperCase() + obj[0].slice(1), - value: parseVal(obj) - })); - }); - const artistCards = library.artists.map((artist) => /* @__PURE__ */ import_react6.default.createElement(artist_card_default, { - name: artist.name, - image: artist.image, - uri: artist.uri, - subtext: `Appears in ${artist.freq} tracks` - })); - const albumCards = library.albums.map((album) => { - return /* @__PURE__ */ import_react6.default.createElement(artist_card_default, { - name: album.name, - image: album.image, - uri: album.uri, - subtext: `Appears in ${album.freq} tracks` + const statCards = Object.entries(library.audioFeatures).map(([key, value]) => { + return /* @__PURE__ */ import_react12.default.createElement(stat_card_default, { + label: key, + value }); }); - return /* @__PURE__ */ import_react6.default.createElement("div", { - className: "stats-page" - }, /* @__PURE__ */ import_react6.default.createElement("section", { + const artistCards = library.artists.map((artist) => { + return /* @__PURE__ */ import_react12.default.createElement(spotify_card_default, { + type: "artist", + uri: artist.uri, + header: artist.name, + subheader: `Appears in ${artist.freq} tracks`, + imageUrl: artist.image + }); + }); + const albumCards = library.albums.map((album) => { + return /* @__PURE__ */ import_react12.default.createElement(spotify_card_default, { + type: "album", + uri: album.uri, + header: album.name, + subheader: `Appears in ${album.freq} tracks`, + imageUrl: album.image + }); + }); + return /* @__PURE__ */ import_react12.default.createElement("div", { + id: "stats-app", + className: "page-content encore-dark-theme encore-base-set" + }, /* @__PURE__ */ import_react12.default.createElement("section", { className: "stats-libraryOverview" - }, /* @__PURE__ */ import_react6.default.createElement(stat_card_default, { - stat: "Total Tracks", - value: library.trackCount - }), /* @__PURE__ */ import_react6.default.createElement(stat_card_default, { - stat: "Total Artists", - value: library.artistCount - }), /* @__PURE__ */ import_react6.default.createElement(stat_card_default, { - stat: "Total Minutes", - value: Math.floor(library.totalDuration / 60) - }), /* @__PURE__ */ import_react6.default.createElement(stat_card_default, { - stat: "Total Hours", + }, /* @__PURE__ */ import_react12.default.createElement(stat_card_default, { + label: "Total Tracks", + value: library.trackCount.toString() + }), /* @__PURE__ */ import_react12.default.createElement(stat_card_default, { + label: "Total Artists", + value: library.artistCount.toString() + }), /* @__PURE__ */ import_react12.default.createElement(stat_card_default, { + label: "Total Minutes", + value: Math.floor(library.totalDuration / 60).toString() + }), /* @__PURE__ */ import_react12.default.createElement(stat_card_default, { + label: "Total Hours", value: (library.totalDuration / (60 * 60)).toFixed(1) - })), /* @__PURE__ */ import_react6.default.createElement("section", null, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react6.default.createElement("h2", { - className: "Type__TypeElement-sc-goli3j-0 TypeElement-canon-textBase-type main-shelf-title" - }, "Most Frequent Genres")))), /* @__PURE__ */ import_react6.default.createElement(genres_card_default, { + })), /* @__PURE__ */ import_react12.default.createElement(shelf_default, { + title: "Most Frequent Genres" + }, /* @__PURE__ */ import_react12.default.createElement(genres_card_default, { genres: library.genres, total: library.genresDenominator - }), /* @__PURE__ */ import_react6.default.createElement(inline_grid_default, { + }), /* @__PURE__ */ import_react12.default.createElement(inline_grid_default, { special: true - }, statCards)), /* @__PURE__ */ import_react6.default.createElement("section", { - className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react6.default.createElement("h2", { - className: "Type__TypeElement-sc-goli3j-0 TypeElement-canon-textBase-type main-shelf-title" - }, "Most Frequent Artists")))), /* @__PURE__ */ import_react6.default.createElement(inline_grid_default, null, artistCards)), /* @__PURE__ */ import_react6.default.createElement("section", { - className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react6.default.createElement("h2", { - className: "Type__TypeElement-sc-goli3j-0 TypeElement-canon-textBase-type main-shelf-title" - }, "Most Frequent Albums")))), /* @__PURE__ */ import_react6.default.createElement(inline_grid_default, null, albumCards)), /* @__PURE__ */ import_react6.default.createElement("section", { - className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react6.default.createElement("h2", { - className: "Type__TypeElement-sc-goli3j-0 TypeElement-canon-textBase-type main-shelf-title" - }, "Release Year Distribution")))), /* @__PURE__ */ import_react6.default.createElement("section", null, /* @__PURE__ */ import_react6.default.createElement(genres_card_default, { + }, statCards)), /* @__PURE__ */ import_react12.default.createElement(shelf_default, { + title: "Release Year Distribution" + }, /* @__PURE__ */ import_react12.default.createElement(genres_card_default, { genres: library.years, total: library.yearsDenominator - })))); + }))); }; - var playlist_default = import_react6.default.memo(PlaylistPage); + var playlist_default = import_react12.default.memo(PlaylistPage); // package.json - var version = "0.3.0"; + var version = "0.3.3"; - // src/constants.ts - var STATS_VERSION = version; + // ../shared/config/config_wrapper.tsx + var import_react14 = __toESM(require_react()); + + // ../shared/config/config_modal.tsx + var import_react13 = __toESM(require_react()); + var TextInput = (props) => { + const handleTextChange = (event) => { + props.callback(event.target.value); + }; + return /* @__PURE__ */ import_react13.default.createElement("label", { + className: "text-input-wrapper" + }, /* @__PURE__ */ import_react13.default.createElement("input", { + className: "text-input", + type: "text", + value: props.value || "", + "data-storage-key": props.storageKey, + placeholder: props.placeholder, + id: `text-input:${props.storageKey}`, + title: `Text input for ${props.storageKey}`, + onChange: handleTextChange + })); + }; + var Dropdown = (props) => { + const handleDropdownChange = (event) => { + props.callback(event.target.value); + }; + return /* @__PURE__ */ import_react13.default.createElement("label", { + className: "dropdown-wrapper" + }, /* @__PURE__ */ import_react13.default.createElement("select", { + className: "dropdown-input", + value: props.value, + "data-storage-key": props.storageKey, + id: `dropdown:${props.storageKey}`, + title: `Dropdown for ${props.storageKey}`, + onChange: handleDropdownChange + }, props.options.map((option, index) => /* @__PURE__ */ import_react13.default.createElement("option", { + key: index, + value: option + }, option)))); + }; + var ToggleInput = (props) => { + const { Toggle } = Spicetify.ReactComponent; + const handleToggleChange = (newValue) => { + props.callback(newValue); + }; + return /* @__PURE__ */ import_react13.default.createElement(Toggle, { + id: `toggle:${props.storageKey}`, + value: props.value, + onSelected: (newValue) => handleToggleChange(newValue) + }); + }; + var SliderInput = (props) => { + const { Slider } = Spicetify.ReactComponent; + const handleSliderChange = (newValue) => { + const calculatedValue = props.min + newValue * (props.max - props.min); + props.callback(calculatedValue); + }; + const value = (props.value - props.min) / (props.max - props.min); + return /* @__PURE__ */ import_react13.default.createElement(Slider, { + id: `slider:${props.storageKey}`, + value, + min: 0, + max: 1, + step: 0.1, + onDragMove: (newValue) => handleSliderChange(newValue), + onDragStart: () => { + }, + onDragEnd: () => { + } + }); + }; + var TooltipIcon = () => { + return /* @__PURE__ */ import_react13.default.createElement("svg", { + role: "img", + height: "16", + width: "16", + className: "Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4", + viewBox: "0 0 16 16" + }, /* @__PURE__ */ import_react13.default.createElement("path", { + d: "M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z" + }), /* @__PURE__ */ import_react13.default.createElement("path", { + d: "M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z" + })); + }; + var ConfigRow = (props) => { + return /* @__PURE__ */ import_react13.default.createElement("div", { + className: "setting-row" + }, /* @__PURE__ */ import_react13.default.createElement("label", { + className: "col description" + }, props.name, props.desc && /* @__PURE__ */ import_react13.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + label: /* @__PURE__ */ import_react13.default.createElement("div", { + dangerouslySetInnerHTML: { __html: props.desc } + }), + renderInline: true, + showDelay: 10, + placement: "top", + labelClassName: "tooltip", + disabled: false + }, /* @__PURE__ */ import_react13.default.createElement("div", { + className: "tooltip-icon" + }, /* @__PURE__ */ import_react13.default.createElement(TooltipIcon, null)))), /* @__PURE__ */ import_react13.default.createElement("div", { + className: "col action" + }, props.children)); + }; + var ConfigModal = (props) => { + const { config, structure, appKey, updateAppConfig } = props; + const [modalConfig, setModalConfig] = import_react13.default.useState({ ...config }); + const modalRows = structure.map((modalRow, index) => { + const key = modalRow.key; + const currentValue = modalConfig[key]; + const updateItem = (state) => { + console.debug(`toggling ${key} to ${state}`); + localStorage.setItem(`${appKey}:config:${key}`, String(state)); + if (modalRow.callback) + modalRow.callback(state); + const newConfig = { ...modalConfig }; + newConfig[key] = state; + updateAppConfig(newConfig); + setModalConfig(newConfig); + }; + const header = modalRow.sectionHeader; + const element = () => { + switch (modalRow.type) { + case "toggle": + return /* @__PURE__ */ import_react13.default.createElement(ToggleInput, { + storageKey: key, + value: currentValue, + callback: updateItem + }); + case "text": + return /* @__PURE__ */ import_react13.default.createElement(TextInput, { + storageKey: key, + value: currentValue, + callback: updateItem + }); + case "dropdown": + return /* @__PURE__ */ import_react13.default.createElement(Dropdown, { + storageKey: key, + value: currentValue, + options: modalRow.options, + callback: updateItem + }); + case "slider": + return /* @__PURE__ */ import_react13.default.createElement(SliderInput, { + storageKey: key, + value: currentValue, + min: modalRow.min, + max: modalRow.max, + step: modalRow.step, + callback: updateItem + }); + } + }; + return /* @__PURE__ */ import_react13.default.createElement(import_react13.default.Fragment, null, header && index !== 0 && /* @__PURE__ */ import_react13.default.createElement("br", null), header && /* @__PURE__ */ import_react13.default.createElement("h2", { + className: "section-header" + }, modalRow.sectionHeader), /* @__PURE__ */ import_react13.default.createElement(ConfigRow, { + name: modalRow.name, + desc: modalRow.desc + }, element())); + }); + return /* @__PURE__ */ import_react13.default.createElement("div", { + className: "config-container" + }, modalRows); + }; + var config_modal_default = ConfigModal; + + // ../shared/config/config_wrapper.tsx + var _ConfigWrapper = class { + Config; + launchModal; + constructor(modalStructure, key) { + const config = modalStructure.map((modalStructureRow) => { + const value = _ConfigWrapper.getLocalStorageDataFromKey( + `${key}:config:${modalStructureRow.key}`, + modalStructureRow.def + ); + modalStructureRow.callback?.(value); + return { [modalStructureRow.key]: value }; + }); + this.Config = Object.assign({}, ...config); + this.launchModal = (callback) => { + const updateConfig = (config2) => { + this.Config = { ...config2 }; + callback?.(config2); + }; + Spicetify.PopupModal.display({ + title: `${key.charAt(0).toUpperCase() + key.slice(1)} Settings`, + content: /* @__PURE__ */ import_react14.default.createElement(config_modal_default, { + config: this.Config, + structure: modalStructure, + appKey: key, + updateAppConfig: updateConfig + }), + isLarge: true + }); + }; + } + }; + var ConfigWrapper = _ConfigWrapper; + __publicField(ConfigWrapper, "getLocalStorageDataFromKey", (key, fallback) => { + const data = localStorage.getItem(key); + if (data) { + try { + return JSON.parse(data); + } catch (err) { + return data; + } + } else { + return fallback; + } + }); + var config_wrapper_default = ConfigWrapper; // src/extensions/extension.tsx - (async function stats() { - if (!Spicetify.Platform) { - setTimeout(stats, 100); + var SpicetifyStats = class { + ConfigWrapper = new config_wrapper_default( + [ + { + name: "Last.fm Api Key", + key: "api-key", + type: "text", + def: null, + placeholder: "Enter API Key", + desc: `You can get this by visiting www.last.fm/api/account/create and simply entering any name.
You'll need to make an account first, which is a plus.`, + sectionHeader: "Last.fm Integration" + }, + { + name: "Last.fm Username", + key: "lastfm-user", + type: "text", + def: null, + placeholder: "Enter Username" + }, + { + name: "Use Last.fm for Stats", + key: "use-lastfm", + type: "toggle", + def: false, + desc: `Last.fm charts your stats purely based on the streaming count, whereas Spotify factors in other variables` + }, + { + name: "Artists Page", + key: "show-artists", + type: "toggle", + def: true, + sectionHeader: "Pages" + }, + { name: "Tracks Page", key: "show-tracks", type: "toggle", def: true }, + { + name: "Albums Page", + key: "show-albums", + type: "toggle", + def: false, + desc: `Requires Last.fm API key and username` + }, + { name: "Genres Page", key: "show-genres", type: "toggle", def: true }, + { name: "Library Page", key: "show-library", type: "toggle", def: true }, + { + name: "Charts Page", + key: "show-charts", + type: "toggle", + def: true, + desc: `Requires Last.fm API key` + } + ], + "stats" + ); + }; + window.SpicetifyStats = new SpicetifyStats(); + (function stats() { + const { + PopupModal, + LocalStorage, + Topbar, + Platform: { History } + } = Spicetify; + if (!PopupModal || !LocalStorage || !Topbar || !History) { + setTimeout(stats, 300); return; } const version2 = localStorage.getItem("stats:version"); - if (!version2 || version2 !== STATS_VERSION) { + if (!version2 || version2 !== version) { for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key.startsWith("stats:") && !key.startsWith("stats:config:")) { localStorage.removeItem(key); } } - localStorage.setItem("stats:version", STATS_VERSION); + localStorage.setItem("stats:version", version); } - Spicetify.LocalStorage.set("stats:cache-info", JSON.stringify([0, 0, 0, 0, 0, 0])); + LocalStorage.set("stats:cache-info", JSON.stringify([0, 0, 0, 0, 0, 0])); const styleLink = document.createElement("link"); styleLink.rel = "stylesheet"; styleLink.href = "/spicetify-routes-stats.css"; document.head.appendChild(styleLink); - const playlistEdit = new Spicetify.Topbar.Button("playlist-stats", "visualizer", () => { - const playlistUri = `spotify:playlist:${Spicetify.Platform.History.location.pathname.split("/")[2]}`; - Spicetify.PopupModal.display({ title: "Playlist Stats", content: /* @__PURE__ */ import_react7.default.createElement(playlist_default, { + const playlistEdit = new Topbar.Button("playlist-stats", "visualizer", () => { + const playlistUri = `spotify:playlist:${History.location.pathname.split("/")[2]}`; + PopupModal.display({ title: "Playlist Stats", content: /* @__PURE__ */ import_react15.default.createElement(playlist_default, { uri: playlistUri }), isLarge: true }); }); playlistEdit.element.classList.toggle("hidden", true); - Spicetify.Platform.History.listen(({ pathname }) => { + function setTopbarButtonVisibility(pathname) { const [, type, uid] = pathname.split("/"); const isPlaylistPage = type === "playlist" && uid; playlistEdit.element.classList.toggle("hidden", !isPlaylistPage); + } + setTopbarButtonVisibility(History.location.pathname); + History.listen(({ pathname }) => { + setTopbarButtonVisibility(pathname); }); })(); })(); diff --git a/.config/spicetify/CustomApps/stats/index.js b/.config/spicetify/CustomApps/stats/index.js index 62f796f9..56fcfc30 100644 --- a/.config/spicetify/CustomApps/stats/index.js +++ b/.config/spicetify/CustomApps/stats/index.js @@ -1,39 +1,10 @@ var stats = (() => { var __create = Object.create; var __defProp = Object.defineProperty; - var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; - var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; - var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; - var __propIsEnum = Object.prototype.propertyIsEnumerable; - var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; - var __spreadValues = (a, b) => { - for (var prop in b || (b = {})) - if (__hasOwnProp.call(b, prop)) - __defNormalProp(a, prop, b[prop]); - if (__getOwnPropSymbols) - for (var prop of __getOwnPropSymbols(b)) { - if (__propIsEnum.call(b, prop)) - __defNormalProp(a, prop, b[prop]); - } - return a; - }; - var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); - var __objRest = (source, exclude) => { - var target = {}; - for (var prop in source) - if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) - target[prop] = source[prop]; - if (source != null && __getOwnPropSymbols) - for (var prop of __getOwnPropSymbols(source)) { - if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) - target[prop] = source[prop]; - } - return target; - }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; @@ -69,23 +40,23 @@ var stats = (() => { } }); - // node_modules/spicetify-creator/dist/temp/index.jsx - var temp_exports = {}; - __export(temp_exports, { + // ../../../AppData/Local/Temp/spicetify-creator/index.jsx + var spicetify_creator_exports = {}; + __export(spicetify_creator_exports, { default: () => render }); // src/app.tsx - var import_react24 = __toESM(require_react()); + var import_react29 = __toESM(require_react()); - // node_modules/spcr-navigation-bar/useNavigationBar.tsx + // ../node_modules/spcr-navigation-bar/useNavigationBar.tsx var import_react3 = __toESM(require_react()); - // node_modules/spcr-navigation-bar/navBar.tsx + // ../node_modules/spcr-navigation-bar/navBar.tsx var import_react2 = __toESM(require_react()); var import_react_dom = __toESM(require_react_dom()); - // node_modules/spcr-navigation-bar/optionsMenu.tsx + // ../node_modules/spcr-navigation-bar/optionsMenu.tsx var import_react = __toESM(require_react()); var OptionsMenuItemIcon = /* @__PURE__ */ import_react.default.createElement("svg", { width: 16, @@ -134,10 +105,10 @@ var stats = (() => { }); var optionsMenu_default = OptionsMenu; - // postcss-module:C:\Users\user\AppData\Local\Temp\tmp-6912-LESOepgMxajG\18ca59b28c22\navBar.module.css - var navBar_module_default = { "topBarHeaderItem": "navBar-module__topBarHeaderItem___v29bR_stats", "topBarHeaderItemLink": "navBar-module__topBarHeaderItemLink___VeyBY_stats", "topBarActive": "navBar-module__topBarActive___-qYPu_stats", "topBarNav": "navBar-module__topBarNav___1OtdR_stats", "optionsMenuDropBox": "navBar-module__optionsMenuDropBox___tD9mA_stats" }; + // postcss-module:C:\Users\user\AppData\Local\Temp\tmp-17120-n3iWRzissBjg\18f3cbbb4bc3\navBar.module.css + var navBar_module_default = { "topBarHeaderItem": "navBar-module__topBarHeaderItem___piw4C_stats", "topBarHeaderItemLink": "navBar-module__topBarHeaderItemLink___xA4uv_stats", "topBarActive": "navBar-module__topBarActive___XhWpm_stats", "topBarNav": "navBar-module__topBarNav___qWGeZ_stats", "optionsMenuDropBox": "navBar-module__optionsMenuDropBox___pzfNI_stats" }; - // node_modules/spcr-navigation-bar/navBar.tsx + // ../node_modules/spcr-navigation-bar/navBar.tsx var NavbarItem2 = class { constructor(link, isActive) { this.link = link; @@ -152,7 +123,7 @@ var stats = (() => { props.switchTo(props.item.link); } }, /* @__PURE__ */ import_react2.default.createElement("a", { - className: `${navBar_module_default.topBarHeaderItemLink} queue-tabBar-headerItemLink ${props.item.isActive ? navBar_module_default.topBarActive + " queue-tabBar-active" : ""}`, + className: `${navBar_module_default.topBarHeaderItemLink} ${props.item.isActive ? navBar_module_default.topBarActive : ""}`, "aria-current": "page", draggable: false, href: "" @@ -171,7 +142,7 @@ var stats = (() => { })); }); var NavbarContent = (props) => { - const resizeHost = document.querySelector(".Root__main-view .os-resize-observer-host"); + const resizeHost = document.querySelector(".Root__main-view .os-resize-observer-host") ?? document.querySelector(".Root__main-view .os-size-observer"); const [windowSize, setWindowSize] = (0, import_react2.useState)(resizeHost.clientWidth); const resizeHandler = () => setWindowSize(resizeHost.clientWidth); (0, import_react2.useEffect)(() => { @@ -235,7 +206,7 @@ var stats = (() => { return /* @__PURE__ */ import_react2.default.createElement("nav", { className: navBar_module_default.topBarNav }, /* @__PURE__ */ import_react2.default.createElement("ul", { - className: navBar_module_default.topBarHeader + " queue-tabBar-header", + className: navBar_module_default.topBarHeader, ref: navBarListRef }, items.filter((_, id) => !outOfRangeItemIndexes.includes(id)).map( (item) => /* @__PURE__ */ import_react2.default.createElement(NavbarItemComponent, { @@ -249,7 +220,7 @@ var stats = (() => { }; var navBar_default = NavbarContent; - // node_modules/spcr-navigation-bar/useNavigationBar.tsx + // ../node_modules/spcr-navigation-bar/useNavigationBar.tsx var useNavigationBar = (links) => { const [activeLink, setActiveLink] = (0, import_react3.useState)(links[0]); const navbar = /* @__PURE__ */ import_react3.default.createElement(navBar_default, { @@ -262,37 +233,39 @@ var stats = (() => { var useNavigationBar_default = useNavigationBar; // src/pages/top_artists.tsx - var import_react11 = __toESM(require_react()); + var import_react17 = __toESM(require_react()); - // src/components/hooks/useDropdownMenu.tsx + // ../shared/dropdown/useDropdownMenu.tsx var import_react5 = __toESM(require_react()); - // src/components/dropdown.tsx + // ../shared/dropdown/dropdown.tsx var import_react4 = __toESM(require_react()); - var activeStyle = { - backgroundColor: "rgba(var(--spice-rgb-selected-row),.1)" - }; - var Icon = (props) => { - return /* @__PURE__ */ import_react4.default.createElement(Spicetify.ReactComponent.IconComponent, __spreadProps(__spreadValues({}, props), { - className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small", - "data-encore-id": "icon", - viewBox: "0 0 16 16", - height: "16", - width: "16" - }), /* @__PURE__ */ import_react4.default.createElement("path", { - d: "M15.53 2.47a.75.75 0 0 1 0 1.06L4.907 14.153.47 9.716a.75.75 0 0 1 1.06-1.06l3.377 3.376L14.47 2.47a.75.75 0 0 1 1.06 0z" - })); - }; - var MenuItem = ({ option, isActive, switchCallback }) => { - return /* @__PURE__ */ import_react4.default.createElement(Spicetify.ReactComponent.MenuItem, { + function CheckIcon() { + return /* @__PURE__ */ import_react4.default.createElement(Spicetify.ReactComponent.IconComponent, { + iconSize: 16, + semanticColor: "textBase", + dangerouslySetInnerHTML: { + __html: '' + } + }); + } + var MenuItem = (props) => { + const { ReactComponent } = Spicetify; + const { option, isActive, switchCallback } = props; + const activeStyle = { + backgroundColor: "rgba(var(--spice-rgb-selected-row),.1)" + }; + return /* @__PURE__ */ import_react4.default.createElement(ReactComponent.MenuItem, { trigger: "click", onClick: () => switchCallback(option), "data-checked": isActive, - trailingIcon: isActive && /* @__PURE__ */ import_react4.default.createElement(Icon, null), + trailingIcon: isActive ? /* @__PURE__ */ import_react4.default.createElement(CheckIcon, null) : void 0, style: isActive ? activeStyle : void 0 - }, option); + }, option.name); }; - var DropdownMenu = ({ options, activeOption, switchCallback }) => { + var DropdownMenu = (props) => { + const { ContextMenu, Menu, TextComponent } = Spicetify.ReactComponent; + const { options, activeOption, switchCallback } = props; const optionItems = options.map((option) => { return /* @__PURE__ */ import_react4.default.createElement(MenuItem, { option, @@ -300,22 +273,23 @@ var stats = (() => { switchCallback }); }); - const MenuWrapper2 = (props) => { - return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement(Spicetify.ReactComponent.Menu, __spreadValues({}, props), optionItems)); + const MenuWrapper2 = (props2) => { + return /* @__PURE__ */ import_react4.default.createElement(Menu, { + ...props2 + }, optionItems); }; - return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement(Spicetify.ReactComponent.ContextMenu, { + return /* @__PURE__ */ import_react4.default.createElement(ContextMenu, { menu: /* @__PURE__ */ import_react4.default.createElement(MenuWrapper2, null), trigger: "click" }, /* @__PURE__ */ import_react4.default.createElement("button", { className: "x-sortBox-sortDropdown", type: "button", role: "combobox", - "aria-controls": "sortboxlist-29ad4489-2ff4-4a03-8c0c-ffc6f90c2fed", "aria-expanded": "false" - }, /* @__PURE__ */ import_react4.default.createElement("span", { - className: "TypeElement-mesto-type", - "data-encore-id": "type" - }, activeOption), /* @__PURE__ */ import_react4.default.createElement("svg", { + }, /* @__PURE__ */ import_react4.default.createElement(TextComponent, { + variant: "mesto", + semanticColor: "textSubdued" + }, activeOption.name), /* @__PURE__ */ import_react4.default.createElement("svg", { role: "img", height: "16", width: "16", @@ -325,116 +299,309 @@ var stats = (() => { "data-encore-id": "icon" }, /* @__PURE__ */ import_react4.default.createElement("path", { d: "m14 6-6 6-6-6h12z" - }))))); + })))); }; var dropdown_default = DropdownMenu; - // src/components/hooks/useDropdownMenu.tsx - var useDropdownMenu = (options, displayOptions, storageVariable) => { - const initialOption = Spicetify.LocalStorage.get(`stats:${storageVariable}:active-option`); + // ../shared/dropdown/useDropdownMenu.tsx + var useDropdownMenu = (options, storageVariable) => { + const initialOptionID = storageVariable && Spicetify.LocalStorage.get(`${storageVariable}:active-option`); + const initialOption = initialOptionID && options.find((e) => e.id === initialOptionID); const [activeOption, setActiveOption] = (0, import_react5.useState)(initialOption || options[0]); + const [availableOptions, setAvailableOptions] = (0, import_react5.useState)(options); const dropdown = /* @__PURE__ */ import_react5.default.createElement(dropdown_default, { - options: displayOptions, - activeOption: displayOptions[options.indexOf(activeOption)], + options: availableOptions, + activeOption, switchCallback: (option) => { - setActiveOption(options[displayOptions.indexOf(option)]); - Spicetify.LocalStorage.set(`stats:${storageVariable}:active-option`, options[displayOptions.indexOf(option)]); + setActiveOption(option); + if (storageVariable) + Spicetify.LocalStorage.set(`${storageVariable}:active-option`, option.id); } }); - return [dropdown, activeOption, setActiveOption]; + return [dropdown, activeOption, setActiveOption, setAvailableOptions]; }; var useDropdownMenu_default = useDropdownMenu; - // src/components/cards/artist_card.tsx + // ../library/src/components/collection_menu.tsx + var import_react8 = __toESM(require_react()); + + // ../library/src/components/text_input_dialog.tsx var import_react6 = __toESM(require_react()); - var DraggableComponent = (props) => { - var _a, _b; - const dragHandler = (_b = (_a = Spicetify.ReactHook).DragHandler) == null ? void 0 : _b.call(_a, [props.uri], props.title); - return /* @__PURE__ */ import_react6.default.createElement("div", { - onDragStart: dragHandler, - draggable: "true", - className: "main-card-draggable" - }, props.children); - }; - var Card = ({ name, image, uri, subtext }) => { - const goToArtist = (uriString) => { - if (uriString.includes("last")) { - return window.open(uriString, "_blank"); - } - const uriObj = Spicetify.URI.fromString(uriString); - const url = uriObj.toURLPath(true); - Spicetify.Platform.History.push(url); - Spicetify.Platform.History.goForward(); + var TextInputDialog = (props) => { + const { ButtonPrimary } = Spicetify.ReactComponent; + const { def, placeholder, onSave } = props; + const [value, setValue] = import_react6.default.useState(def); + const onSubmit = (e) => { + e.preventDefault(); + Spicetify.PopupModal.hide(); + onSave(value); }; - const isArtist = uri.includes("artist"); - const MenuWrapper2 = import_react6.default.memo((props) => { - return isArtist ? /* @__PURE__ */ import_react6.default.createElement(Spicetify.ReactComponent.ArtistMenu, __spreadValues({}, props)) : /* @__PURE__ */ import_react6.default.createElement(Spicetify.ReactComponent.AlbumMenu, __spreadValues({}, props)); - }); - return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement(Spicetify.ReactComponent.ContextMenu, { - menu: /* @__PURE__ */ import_react6.default.createElement(MenuWrapper2, { - uri - }), - trigger: "right-click" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-card-card" - }, /* @__PURE__ */ import_react6.default.createElement(DraggableComponent, { - uri, - title: name - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-card-imageContainer" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: `main-cardImage-imageWrapper ${isArtist ? `main-cardImage-circular` : ""}` - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "" - }, /* @__PURE__ */ import_react6.default.createElement("img", { - "aria-hidden": "false", - draggable: "false", - loading: "lazy", - src: image, - className: `main-image-image main-cardImage-image ${isArtist ? `main-cardImage-circular` : ""} main-image-loaded` - }))), /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-card-PlayButtonContainer", - onClick: () => Spicetify.Player.playUri(uri) - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-playButton-PlayButton" - }, /* @__PURE__ */ import_react6.default.createElement("button", { + return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement("form", { + className: "text-input-form", + onSubmit + }, /* @__PURE__ */ import_react6.default.createElement("label", { + className: "text-input-wrapper" + }, /* @__PURE__ */ import_react6.default.createElement("input", { + className: "text-input", + type: "text", + value, + placeholder, + onChange: (e) => setValue(e.target.value) + })), /* @__PURE__ */ import_react6.default.createElement("button", { + type: "submit", "data-encore-id": "buttonPrimary", - className: "Button-md-useBrowserDefaultFocusStyle Button-md-buttonPrimary-useBrowserDefaultFocusStyle Button-medium-buttonPrimary-useBrowserDefaultFocusStyle" + className: "Button-sc-qlcn5g-0 Button-small-buttonPrimary" }, /* @__PURE__ */ import_react6.default.createElement("span", { - className: "ButtonInner-md-iconOnly ButtonInner-medium-iconOnly encore-bright-accent-set" - }, /* @__PURE__ */ import_react6.default.createElement("span", { - "aria-hidden": "true", - className: "Wrapper-md-24-only Wrapper-medium-medium-only" - }, /* @__PURE__ */ import_react6.default.createElement("svg", { - role: "img", - height: "24", - width: "24", - "aria-hidden": "true", - viewBox: "0 0 24 24", - "data-encore-id": "icon", - className: "Svg-img-24 Svg-img-24-icon Svg-img-icon-medium" - }, /* @__PURE__ */ import_react6.default.createElement("path", { - d: "m7.05 3.606 13.49 7.788a.7.7 0 0 1 0 1.212L7.05 20.394A.7.7 0 0 1 6 19.788V4.212a.7.7 0 0 1 1.05-.606z" - })))))))), /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-card-cardMetadata" - }, /* @__PURE__ */ import_react6.default.createElement("a", { - draggable: "false", - className: "main-cardHeader-link", - dir: "auto" - }, /* @__PURE__ */ import_react6.default.createElement("div", { - className: "TypeElement-balladBold-textBase-4px-type main-cardHeader-text", - "data-encore-id": "type" - }, name)), /* @__PURE__ */ import_react6.default.createElement("div", { - className: "TypeElement-mesto-textSubdued-type main-cardSubHeader-root", - "data-encore-id": "type" - }, /* @__PURE__ */ import_react6.default.createElement("span", null, subtext))), /* @__PURE__ */ import_react6.default.createElement("div", { - className: "main-card-cardLink", - onClick: () => goToArtist(uri) - }))))); + className: "ButtonInner-sc-14ud5tc-0 ButtonInner-small encore-bright-accent-set" + }, "Save")))); }; - var artist_card_default = import_react6.default.memo(Card); + var text_input_dialog_default = TextInputDialog; + + // ../library/src/components/leading_icon.tsx + var import_react7 = __toESM(require_react()); + var LeadingIcon = ({ path }) => { + return /* @__PURE__ */ import_react7.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: `${path}` + }, + iconSize: 16 + }); + }; + var leading_icon_default = LeadingIcon; + + // ../library/src/components/collection_menu.tsx + var editIconPath = ''; + var deleteIconPath = ''; + var CollectionMenu = ({ id }) => { + const { Menu, MenuItem: MenuItem2 } = Spicetify.ReactComponent; + const deleteCollection = () => { + SpicetifyLibrary.CollectionWrapper.deleteCollection(id); + }; + const renameCollection = () => { + const name = SpicetifyLibrary.CollectionWrapper.getCollection(id).name; + const rename = (newName) => { + SpicetifyLibrary.CollectionWrapper.renameCollection(id, newName); + }; + Spicetify.PopupModal.display({ + title: "Rename Collection", + content: /* @__PURE__ */ import_react8.default.createElement(text_input_dialog_default, { + def: name, + onSave: rename + }) + }); + }; + const image = SpicetifyLibrary.CollectionWrapper.getCollection(id).imgUrl; + const setCollectionImage = () => { + const setImg = (imgUrl) => { + SpicetifyLibrary.CollectionWrapper.setCollectionImage(id, imgUrl); + }; + Spicetify.PopupModal.display({ + title: "Set Collection Image", + content: /* @__PURE__ */ import_react8.default.createElement(text_input_dialog_default, { + def: image, + placeholder: "Image URL", + onSave: setImg + }) + }); + }; + const removeImage = () => { + SpicetifyLibrary.CollectionWrapper.removeCollectionImage(id); + }; + return /* @__PURE__ */ import_react8.default.createElement(Menu, null, /* @__PURE__ */ import_react8.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react8.default.createElement(leading_icon_default, { + path: editIconPath + }), + onClick: renameCollection + }, "Rename"), /* @__PURE__ */ import_react8.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react8.default.createElement(leading_icon_default, { + path: deleteIconPath + }), + onClick: deleteCollection + }, "Delete"), /* @__PURE__ */ import_react8.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react8.default.createElement(leading_icon_default, { + path: editIconPath + }), + onClick: setCollectionImage + }, "Set Collection Image"), image && /* @__PURE__ */ import_react8.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react8.default.createElement(leading_icon_default, { + path: deleteIconPath + }), + onClick: removeImage + }, "Remove Collection Image")); + }; + var collection_menu_default = CollectionMenu; + + // ../library/src/components/folder_menu.tsx + var import_react9 = __toESM(require_react()); + var editIconPath2 = ''; + var deleteIconPath2 = ''; + var FolderMenu = ({ uri }) => { + const { MenuItem: MenuItem2, Menu } = Spicetify.ReactComponent; + const image = SpicetifyLibrary.FolderImageWrapper.getFolderImage(uri); + const setImage = () => { + const setNewImage = (newUrl) => { + SpicetifyLibrary.FolderImageWrapper.setFolderImage({ uri, url: newUrl }); + }; + Spicetify.PopupModal.display({ + title: "Set Folder Image", + content: /* @__PURE__ */ import_react9.default.createElement(text_input_dialog_default, { + def: image, + onSave: setNewImage + }) + }); + }; + const removeImage = () => { + SpicetifyLibrary.FolderImageWrapper.removeFolderImage(uri); + }; + return /* @__PURE__ */ import_react9.default.createElement(Menu, null, /* @__PURE__ */ import_react9.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react9.default.createElement(leading_icon_default, { + path: editIconPath2 + }), + onClick: setImage + }, "Set Folder Image"), image && /* @__PURE__ */ import_react9.default.createElement(MenuItem2, { + leadingIcon: /* @__PURE__ */ import_react9.default.createElement(leading_icon_default, { + path: deleteIconPath2 + }), + onClick: removeImage + }, "Remove Folder Image")); + }; + var folder_menu_default = FolderMenu; + + // ../shared/components/spotify_card.tsx + var import_react11 = __toESM(require_react()); + + // ../shared/components/folder_fallback.tsx + var import_react10 = __toESM(require_react()); + var FolderSVG = (e) => { + return /* @__PURE__ */ import_react10.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + viewBox: "0 0 24 24", + size: "xxlarge", + dangerouslySetInnerHTML: { + __html: '' + }, + ...e + }); + }; + var folder_fallback_default = FolderSVG; + + // ../shared/components/spotify_card.tsx + function SpotifyCard(props) { + const { Cards, TextComponent, ArtistMenu, AlbumMenu, PodcastShowMenu, PlaylistMenu, ContextMenu } = Spicetify.ReactComponent; + const { FeatureCard: Card, CardImage } = Cards; + const { createHref, push } = Spicetify.Platform.History; + const { type, header, uri, imageUrl, subheader, artistUri } = props; + const backupImageUrl = type === "folder" || type === "collection" ? "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/folder_placeholder.png" : "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/def_placeholder.png"; + const Menu = () => { + switch (type) { + case "artist": + return /* @__PURE__ */ import_react11.default.createElement(ArtistMenu, { + uri + }); + case "album": + return /* @__PURE__ */ import_react11.default.createElement(AlbumMenu, { + uri, + artistUri, + canRemove: true + }); + case "playlist": + return /* @__PURE__ */ import_react11.default.createElement(PlaylistMenu, { + uri + }); + case "show": + return /* @__PURE__ */ import_react11.default.createElement(PodcastShowMenu, { + uri + }); + case "collection": + return /* @__PURE__ */ import_react11.default.createElement(collection_menu_default, { + id: uri + }); + case "folder": + return /* @__PURE__ */ import_react11.default.createElement(folder_menu_default, { + uri + }); + default: + return /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null); + } + }; + const lastfmProps = type === "lastfm" ? { onClick: () => window.open(uri, "_blank"), isPlayable: false, delegateNavigation: true } : {}; + const folderProps = type === "folder" ? { + delegateNavigation: true, + onClick: () => { + createHref({ pathname: `/library/folder/${uri}` }); + push({ pathname: `/library/folder/${uri}` }); + } + } : {}; + const collectionProps = type === "collection" ? { + delegateNavigation: true, + onClick: () => { + createHref({ pathname: `/library/collection/${uri}` }); + push({ pathname: `/library/collection/${uri}` }); + } + } : {}; + return /* @__PURE__ */ import_react11.default.createElement(ContextMenu, { + menu: Menu(), + trigger: "right-click" + }, /* @__PURE__ */ import_react11.default.createElement(Card, { + featureIdentifier: type, + headerText: header, + renderCardImage: () => /* @__PURE__ */ import_react11.default.createElement(CardImage, { + images: [ + { + height: 640, + url: imageUrl, + width: 640 + } + ], + isCircular: type === "artist", + FallbackComponent: folder_fallback_default + }), + renderSubHeaderContent: () => /* @__PURE__ */ import_react11.default.createElement(TextComponent, { + as: "div", + variant: "mesto", + semanticColor: "textSubdued", + children: subheader + }), + uri, + ...lastfmProps, + ...folderProps, + ...collectionProps + })); + } + var spotify_card_default = SpotifyCard; + + // src/endpoints.ts + var lfmperiods = { + short_term: "1month", + medium_term: "6month", + long_term: "overall" + }; + var LASTFM = { + toptracks: (user, key, range) => `http://ws.audioscrobbler.com/2.0/?method=user.gettoptracks&user=${user}&api_key=${key}&format=json&period=${lfmperiods[range]}`, + topalbums: (user, key, range) => `https://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user=${user}&api_key=${key}&format=json&period=${lfmperiods[range]}`, + topartists: (user, key, range) => `https://ws.audioscrobbler.com/2.0/?method=user.gettopartists&user=${user}&api_key=${key}&format=json&period=${lfmperiods[range]}`, + charts: (key, type) => `http://ws.audioscrobbler.com/2.0/?method=chart.gettop${type}&api_key=${key}&format=json` + }; + var SPOTIFY = { + toptracks: (range) => `https://api.spotify.com/v1/me/top/tracks?limit=50&offset=0&time_range=${range}`, + topartists: (range) => `https://api.spotify.com/v1/me/top/artists?limit=50&offset=0&time_range=${range}`, + artists: (artists) => `https://api.spotify.com/v1/artists?ids=${filter(artists)}`, + rootlist: "sp://core-playlist/v1/rootlist", + playlist: (uri) => `sp://core-playlist/v1/playlist/${uri}`, + search: (track, artist) => `https://api.spotify.com/v1/search?q=track:${filter(track)}+artist:${filter(artist)}&type=track`, + searchartist: (artist) => `https://api.spotify.com/v1/search?q=artist:${filter(artist)}&type=artist`, + searchalbum: (album, artist) => `https://api.spotify.com/v1/search?q=${filter(album)}+artist:${filter(artist)}&type=album`, + audiofeatures: (ids) => `https://api.spotify.com/v1/audio-features?ids=${ids}`, + queryliked: (ids) => `https://api.spotify.com/v1/me/tracks/contains?ids=${ids}` + }; + var PLACEHOLDER = "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/stats/src/styles/placeholder.png"; // src/funcs.ts + function filter(str) { + const normalizedStr = str.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); + return normalizedStr.replace(/[^a-zA-Z0-9\-._~:/?#[\]@!$&()*+,;= ]/g, "").replace(/ /g, "+"); + } var updatePageCache = (i, callback, activeOption, lib = false) => { let cacheInfo = Spicetify.LocalStorage.get("stats:cache-info"); if (!cacheInfo) @@ -483,12 +650,11 @@ var stats = (() => { batches.push(batch); } const promises = batches.map((batch, index) => { - const url = `https://api.spotify.com/v1/audio-features?ids=${batch.join(",")}`; - return apiRequest("audioFeaturesBatch" + index, url, 5, false); + return apiRequest(`audioFeaturesBatch${index}`, SPOTIFY.audiofeatures(batch.join(",")), 5, false); }); const responses = await Promise.all(promises); const data = responses.reduce((acc, response) => { - if (!(response == null ? void 0 : response.audio_features)) + if (!response?.audio_features) return acc; return acc.concat(response.audio_features); }, []); @@ -498,17 +664,12 @@ var stats = (() => { let album_keys = Object.keys(albums).filter((id) => id.match(/^[a-zA-Z0-9]{22}$/)).sort((a, b) => albums[b] - albums[a]).slice(0, 100); let release_years = {}; let total_album_tracks = 0; + const cachedAlbumsSet = new Set(cachedAlbums?.map((album) => album.uri)); let top_albums = await Promise.all( album_keys.map(async (albumID) => { - var _a, _b, _c; let albumMeta; - if (cachedAlbums) { - for (let i = 0; i < cachedAlbums.length; i++) { - if (cachedAlbums[i].uri === `spotify:album:${albumID}`) { - albumMeta = cachedAlbums[i]; - break; - } - } + if (cachedAlbums && cachedAlbumsSet.has(`spotify:album:${albumID}`)) { + albumMeta = cachedAlbums.find((album) => album.uri === `spotify:album:${albumID}`); } if (!albumMeta) { try { @@ -518,20 +679,20 @@ var stats = (() => { offset: 0, limit: 50 }); - if (!((_b = (_a = albumMeta == null ? void 0 : albumMeta.data) == null ? void 0 : _a.albumUnion) == null ? void 0 : _b.name)) + if (!albumMeta?.data?.albumUnion?.name) throw new Error("Invalid URI"); } catch (e) { console.error("stats - album metadata request failed:", e); return; } } - const releaseYear = (albumMeta == null ? void 0 : albumMeta.release_year) || albumMeta.data.albumUnion.date.isoString.slice(0, 4); + const releaseYear = albumMeta?.release_year || albumMeta.data.albumUnion.date.isoString.slice(0, 4); release_years[releaseYear] = (release_years[releaseYear] || 0) + albums[albumID]; total_album_tracks += albums[albumID]; return { name: albumMeta.name || albumMeta.data.albumUnion.name, uri: albumMeta.uri || albumMeta.data.albumUnion.uri, - image: albumMeta.image || ((_c = albumMeta.data.albumUnion.coverArt.sources[0]) == null ? void 0 : _c.url) || "https://commons.wikimedia.org/wiki/File:Black_square.jpg", + image: albumMeta.image || albumMeta.data.albumUnion.coverArt.sources[0]?.url || PLACEHOLDER, release_year: releaseYear, freq: albums[albumID] }; @@ -541,15 +702,13 @@ var stats = (() => { return [top_albums, Object.entries(release_years), total_album_tracks]; }; var fetchTopArtists = async (artists) => { - var _a; if (Object.keys(artists).length === 0) return [[], [], 0]; let artist_keys = Object.keys(artists).filter((id) => id.match(/^[a-zA-Z0-9]{22}$/)).sort((a, b) => artists[b] - artists[a]).slice(0, 50); let genres = {}; let total_genre_tracks = 0; - const artistsMeta = await apiRequest("artistsMetadata", `https://api.spotify.com/v1/artists?ids=${artist_keys.join(",")}`); - let top_artists = (_a = artistsMeta == null ? void 0 : artistsMeta.artists) == null ? void 0 : _a.map((artist) => { - var _a2; + const artistsMeta = await apiRequest("artistsMetadata", SPOTIFY.artists(artist_keys.join(","))); + let top_artists = artistsMeta?.artists?.map((artist) => { if (!artist) return null; artist.genres.forEach((genre) => { @@ -559,7 +718,7 @@ var stats = (() => { return { name: artist.name, uri: artist.uri, - image: ((_a2 = artist.images[2]) == null ? void 0 : _a2.url) || "https://commons.wikimedia.org/wiki/File:Black_square.jpg", + image: artist.images[2]?.url || PLACEHOLDER, freq: artists[artist.id] }; }); @@ -567,71 +726,17 @@ var stats = (() => { const top_genres = Object.entries(genres).sort((a, b) => b[1] - a[1]).slice(0, 10); return [top_artists, top_genres, total_genre_tracks]; }; - function filterLink(str) { - const normalizedStr = str.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); - return normalizedStr.replace(/[^a-zA-Z0-9\-._~:/?#[\]@!$&()*+,;= ]/g, "").replace(/ /g, "+"); - } - var convertToSpotify = async (data, type) => { + var convertTrackData = async (data) => { return await Promise.all( data.map(async (item) => { - if (type === "artists") { - const spotifyItem2 = await Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/search?q=${filterLink(item.name)}&type=artist`).then( - (res) => { - var _a; - return (_a = res.artists) == null ? void 0 : _a.items[0]; - } - ); - if (!spotifyItem2) { - console.log(`https://api.spotify.com/v1/search?q=${filterLink(item.name)}&type=artist`); - return { - name: item.name, - image: item.image[0]["#text"], - uri: item.url, - id: item.mbid - }; - } - return { - name: item.name, - image: spotifyItem2.images[0].url, - uri: spotifyItem2.uri, - id: spotifyItem2.id, - genres: spotifyItem2.genres - }; - } - if (type === "albums") { - const spotifyItem2 = await Spicetify.CosmosAsync.get( - `https://api.spotify.com/v1/search?q=${filterLink(item.name)}+artist:${filterLink(item.artist.name)}&type=album` - ).then((res) => { - var _a; - return (_a = res.albums) == null ? void 0 : _a.items[0]; - }); - if (!spotifyItem2) { - console.log(`https://api.spotify.com/v1/search?q=${filterLink(item.name)}+artist:${filterLink(item.artist.name)}&type=album`); - return { - name: item.name, - image: item.image[2]["#text"], - uri: item.url, - id: item.mbid - }; - } - return { - name: item.name, - image: spotifyItem2.images[0].url, - uri: spotifyItem2.uri, - id: spotifyItem2.id - }; - } - const spotifyItem = await Spicetify.CosmosAsync.get( - `https://api.spotify.com/v1/search?q=track:${filterLink(item.name)}+artist:${filterLink(item.artist.name)}&type=track` - ).then((res) => { - var _a; - return (_a = res.tracks) == null ? void 0 : _a.items[0]; - }); + const spotifyItem = await Spicetify.CosmosAsync.get(SPOTIFY.search(item.name, item.artist.name)).then( + (res) => res.tracks?.items[0] + ); if (!spotifyItem) { - console.log(`https://api.spotify.com/v1/search?q=track:${filterLink(item.name)}+artist:${filterLink(item.artist.name)}&type=track`); + console.log(`couldn't find track: ${item.name} by ${item.artist.name}`); return { name: item.name, - image: item.image[0]["#text"], + image: PLACEHOLDER, uri: item.url, artists: [{ name: item.artist.name, uri: item.artist.url }], duration: 0, @@ -657,6 +762,55 @@ var stats = (() => { }) ); }; + var convertAlbumData = async (data) => { + return await Promise.all( + data.map(async (item) => { + const spotifyItem = await Spicetify.CosmosAsync.get(SPOTIFY.searchalbum(item.name, item.artist.name)).then( + (res) => res.albums?.items[0] + ); + if (!spotifyItem) { + console.log(`couldn't find album: ${item.name} by ${item.artist.name}`); + return { + name: item.name, + image: PLACEHOLDER, + uri: item.url, + id: item.mbid + }; + } + return { + name: item.name, + image: spotifyItem.images[0].url, + uri: spotifyItem.uri, + id: spotifyItem.id + }; + }) + ); + }; + var convertArtistData = async (data) => { + return await Promise.all( + data.map(async (item) => { + const spotifyItem = await Spicetify.CosmosAsync.get(SPOTIFY.searchartist(item.name)).then( + (res) => res.artists?.items[0] + ); + if (!spotifyItem) { + console.log(`couldn't find artist: ${item.name}`); + return { + name: item.name, + image: PLACEHOLDER, + uri: item.url, + id: item.mbid + }; + } + return { + name: item.name, + image: spotifyItem.images[0].url, + uri: spotifyItem.uri, + id: spotifyItem.id, + genres: spotifyItem.genres + }; + }) + ); + }; var checkLiked = async (tracks) => { const nullIndexes = []; tracks.forEach((track, index) => { @@ -664,7 +818,9 @@ var stats = (() => { nullIndexes.push(index); } }); - const apiResponse = await apiRequest("checkLiked", `https://api.spotify.com/v1/me/tracks/contains?ids=${tracks.filter((e) => e).join(",")}`); + const apiResponse = await apiRequest("checkLiked", SPOTIFY.queryliked(tracks.filter((e) => e).join(","))); + if (!apiResponse) + return; const response = []; let nullIndexesIndex = 0; for (let i = 0; i < tracks.length; i++) { @@ -700,28 +856,31 @@ var stats = (() => { }); if (context) { const { sessionId } = Spicetify.Platform.PlayerAPI.getState(); - Spicetify.Platform.PlayerAPI.updateContext(sessionId, { uri: `spotify:user:${Spicetify.Platform.LibraryAPI._currentUsername}:top:tracks`, url: "" }); + Spicetify.Platform.PlayerAPI.updateContext(sessionId, { + uri: `spotify:user:${Spicetify.Platform.LibraryAPI._currentUsername}:top:tracks`, + url: "" + }); } Spicetify.Player.next(); } - // src/components/status.tsx - var import_react7 = __toESM(require_react()); + // ../shared/components/status.tsx + var import_react12 = __toESM(require_react()); var ErrorIcon = () => { - return /* @__PURE__ */ import_react7.default.createElement("svg", { + return /* @__PURE__ */ import_react12.default.createElement("svg", { "data-encore-id": "icon", role: "img", "aria-hidden": "true", viewBox: "0 0 24 24", className: "status-icon" - }, /* @__PURE__ */ import_react7.default.createElement("path", { + }, /* @__PURE__ */ import_react12.default.createElement("path", { d: "M11 18v-2h2v2h-2zm0-4V6h2v8h-2z" - }), /* @__PURE__ */ import_react7.default.createElement("path", { + }), /* @__PURE__ */ import_react12.default.createElement("path", { d: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12z" })); }; var LibraryIcon = () => { - return /* @__PURE__ */ import_react7.default.createElement("svg", { + return /* @__PURE__ */ import_react12.default.createElement("svg", { role: "img", height: "46", width: "46", @@ -729,270 +888,284 @@ var stats = (() => { viewBox: "0 0 24 24", "data-encore-id": "icon", className: "status-icon" - }, /* @__PURE__ */ import_react7.default.createElement("path", { + }, /* @__PURE__ */ import_react12.default.createElement("path", { d: "M14.5 2.134a1 1 0 0 1 1 0l6 3.464a1 1 0 0 1 .5.866V21a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1V3a1 1 0 0 1 .5-.866zM16 4.732V20h4V7.041l-4-2.309zM3 22a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1zm6 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1z" })); }; var Status = (props) => { - const [isVisible, setIsVisible] = import_react7.default.useState(false); - import_react7.default.useEffect(() => { + const [isVisible, setIsVisible] = import_react12.default.useState(false); + import_react12.default.useEffect(() => { const to = setTimeout(() => { setIsVisible(true); }, 500); return () => clearTimeout(to); }, []); - return isVisible ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement("div", { - className: "stats-loadingWrapper" - }, props.icon === "error" ? /* @__PURE__ */ import_react7.default.createElement(ErrorIcon, null) : /* @__PURE__ */ import_react7.default.createElement(LibraryIcon, null), /* @__PURE__ */ import_react7.default.createElement("h1", null, props.heading), /* @__PURE__ */ import_react7.default.createElement("h3", null, props.subheading))) : /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null); + return isVisible ? /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement("div", { + className: "loadingWrapper" + }, props.icon === "error" ? /* @__PURE__ */ import_react12.default.createElement(ErrorIcon, null) : /* @__PURE__ */ import_react12.default.createElement(LibraryIcon, null), /* @__PURE__ */ import_react12.default.createElement("h1", null, props.heading), /* @__PURE__ */ import_react12.default.createElement("h3", null, props.subheading))) : /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null); }; var status_default = Status; - // src/components/page_header.tsx - var import_react10 = __toESM(require_react()); + // ../shared/components/page_container.tsx + var import_react14 = __toESM(require_react()); - // src/components/buttons/refresh_button.tsx - var import_react8 = __toESM(require_react()); - var RefreshButton = ({ refreshCallback }) => { - return /* @__PURE__ */ import_react8.default.createElement("div", { - className: "x-filterBox-filterInputContainer stats-refreshButton", - role: "search", - "aria-expanded": "false" - }, /* @__PURE__ */ import_react8.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { - label: "Refresh", + // src/components/buttons/create_playlist_button.tsx + var import_react13 = __toESM(require_react()); + async function createPlaylistAsync(infoToCreatePlaylist) { + const { Platform, showNotification } = Spicetify; + const { RootlistAPI, PlaylistAPI } = Platform; + try { + const { playlistName, itemsUris } = infoToCreatePlaylist; + const playlistUri = await RootlistAPI.createPlaylist(playlistName, { before: "start" }); + await PlaylistAPI.add(playlistUri, itemsUris, { before: "start" }); + } catch (error) { + console.error(error); + showNotification("Failed to create playlist", true, 1e3); + } + } + function CreatePlaylistButton(props) { + const { TooltipWrapper, ButtonSecondary } = Spicetify.ReactComponent; + const { infoToCreatePlaylist } = props; + return /* @__PURE__ */ import_react13.default.createElement(TooltipWrapper, { + label: "Turn Into Playlist", renderInline: true, - placement: "bottom" - }, /* @__PURE__ */ import_react8.default.createElement("button", { - className: "x-filterBox-expandButton", - "aria-hidden": "false", - "aria-label": "Search in playlists", - onClick: () => refreshCallback() - }, /* @__PURE__ */ import_react8.default.createElement("svg", { - role: "img", - height: "16", - width: "16", - "aria-hidden": "true", - className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small x-filterBox-searchIcon", - viewBox: "0 0 16 16", - "data-encore-id": "icon" - }, /* @__PURE__ */ import_react8.default.createElement("path", { - d: "M0 4.75A3.75 3.75 0 0 1 3.75 1h8.5A3.75 3.75 0 0 1 16 4.75v5a3.75 3.75 0 0 1-3.75 3.75H9.81l1.018 1.018a.75.75 0 1 1-1.06 1.06L6.939 12.75l2.829-2.828a.75.75 0 1 1 1.06 1.06L9.811 12h2.439a2.25 2.25 0 0 0 2.25-2.25v-5a2.25 2.25 0 0 0-2.25-2.25h-8.5A2.25 2.25 0 0 0 1.5 4.75v5A2.25 2.25 0 0 0 3.75 12H5v1.5H3.75A3.75 3.75 0 0 1 0 9.75v-5z" - }))))); - }; - var refresh_button_default = RefreshButton; + placement: "top" + }, /* @__PURE__ */ import_react13.default.createElement(ButtonSecondary, { + "aria-label": "Turn Into Playlist", + children: "Turn Into Playlist", + semanticColor: "textBase", + buttonSize: "sm", + onClick: () => createPlaylistAsync(infoToCreatePlaylist), + className: "stats-make-playlist-button" + })); + } + var create_playlist_button_default = CreatePlaylistButton; - // src/components/buttons/settings_button.tsx - var import_react9 = __toESM(require_react()); - var SettingsButton = ({ config }) => { - return /* @__PURE__ */ import_react9.default.createElement("div", { - className: "x-filterBox-filterInputContainer stats-refreshButton", - role: "search", - "aria-expanded": "false" - }, /* @__PURE__ */ import_react9.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + // ../shared/components/page_container.tsx + var PageContainer = (props) => { + const { title, infoToCreatePlaylist, headerEls, children } = props; + const { TextComponent } = Spicetify.ReactComponent; + return /* @__PURE__ */ import_react14.default.createElement("section", { + className: "contentSpacing" + }, /* @__PURE__ */ import_react14.default.createElement("div", { + className: "page-header" + }, /* @__PURE__ */ import_react14.default.createElement("div", { + className: "header-left" + }, /* @__PURE__ */ import_react14.default.createElement(TextComponent, { + children: title, + as: "h1", + variant: "canon", + semanticColor: "textBase" + }), infoToCreatePlaylist ? /* @__PURE__ */ import_react14.default.createElement(create_playlist_button_default, { + infoToCreatePlaylist + }) : null), /* @__PURE__ */ import_react14.default.createElement("div", { + className: "header-right" + }, headerEls)), /* @__PURE__ */ import_react14.default.createElement("div", { + className: "page-content" + }, children)); + }; + var page_container_default = PageContainer; + + // ../shared/components/settings_button.tsx + var import_react15 = __toESM(require_react()); + function SettingsIcon() { + return /* @__PURE__ */ import_react15.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + dangerouslySetInnerHTML: { + __html: '' + }, + iconSize: 16 + }); + } + function SettingsButton(props) { + const { TooltipWrapper, ButtonTertiary } = Spicetify.ReactComponent; + const { configWrapper } = props; + return /* @__PURE__ */ import_react15.default.createElement(TooltipWrapper, { label: "Settings", renderInline: true, - placement: "bottom" - }, /* @__PURE__ */ import_react9.default.createElement("button", { - className: "x-filterBox-expandButton", - "aria-hidden": "false", - "aria-label": "Search in playlists", - onClick: config.launchModal - }, /* @__PURE__ */ import_react9.default.createElement("svg", { - role: "img", - width: "16", - height: "16", - viewBox: "0 0 24 24", - "aria-hidden": "true", - xmlns: "http://www.w3.org/2000/svg" - }, /* @__PURE__ */ import_react9.default.createElement("path", { - d: "M24 13.616v-3.232c-1.651-.587-2.694-.752-3.219-2.019v-.001c-.527-1.271.1-2.134.847-3.707l-2.285-2.285c-1.561.742-2.433 1.375-3.707.847h-.001c-1.269-.526-1.435-1.576-2.019-3.219h-3.232c-.582 1.635-.749 2.692-2.019 3.219h-.001c-1.271.528-2.132-.098-3.707-.847l-2.285 2.285c.745 1.568 1.375 2.434.847 3.707-.527 1.271-1.584 1.438-3.219 2.02v3.232c1.632.58 2.692.749 3.219 2.019.53 1.282-.114 2.166-.847 3.707l2.285 2.286c1.562-.743 2.434-1.375 3.707-.847h.001c1.27.526 1.436 1.579 2.019 3.219h3.232c.582-1.636.75-2.69 2.027-3.222h.001c1.262-.524 2.12.101 3.698.851l2.285-2.286c-.744-1.563-1.375-2.433-.848-3.706.527-1.271 1.588-1.44 3.221-2.021zm-12 2.384c-2.209 0-4-1.791-4-4s1.791-4 4-4 4 1.791 4 4-1.791 4-4 4z", - fill: "currentColor" - }))))); - }; + placement: "top" + }, /* @__PURE__ */ import_react15.default.createElement(ButtonTertiary, { + buttonSize: "sm", + onClick: configWrapper.launchModal, + "aria-label": "Settings", + iconOnly: SettingsIcon + })); + } var settings_button_default = SettingsButton; - // src/components/page_header.tsx - var PageHeader = ({ title, callback, config, dropdown, createPlaylist, children }) => { - const createPlaylistButton = createPlaylist && /* @__PURE__ */ import_react10.default.createElement("button", { - className: "stats-createPlaylistButton", - "data-encore-id": "buttonSecondary", - "aria-expanded": "false", - onClick: createPlaylist - }, "Turn Into Playlist"); - return /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("section", { - className: "contentSpacing" - }, /* @__PURE__ */ import_react10.default.createElement("div", { - className: `collection-collection-header stats-header` - }, /* @__PURE__ */ import_react10.default.createElement("h1", { - "data-encore-id": "type", - className: "TypeElement-canon-type" - }, title, createPlaylistButton ? createPlaylistButton : null), /* @__PURE__ */ import_react10.default.createElement("div", { - className: "collection-searchBar-searchBar" - }, /* @__PURE__ */ import_react10.default.createElement(refresh_button_default, { - refreshCallback: callback - }), /* @__PURE__ */ import_react10.default.createElement(settings_button_default, { - config - }), dropdown)), /* @__PURE__ */ import_react10.default.createElement("div", null, children))); - }; - var page_header_default = import_react10.default.memo(PageHeader); + // src/components/buttons/refresh_button.tsx + var import_react16 = __toESM(require_react()); + function RefreshIcon() { + return /* @__PURE__ */ import_react16.default.createElement(Spicetify.ReactComponent.IconComponent, { + semanticColor: "textSubdued", + iconSize: 16, + dangerouslySetInnerHTML: { + __html: '' + } + }); + } + function RefreshButton(props) { + const { ButtonTertiary, TooltipWrapper } = Spicetify.ReactComponent; + const { callback } = props; + return /* @__PURE__ */ import_react16.default.createElement(TooltipWrapper, { + label: "Refresh", + renderInline: true, + placement: "top" + }, /* @__PURE__ */ import_react16.default.createElement(ButtonTertiary, { + buttonSize: "sm", + onClick: callback, + "aria-label": "Refresh", + iconOnly: RefreshIcon + })); + } + var refresh_button_default = RefreshButton; // src/pages/top_artists.tsx - var topArtistsReq = async (time_range, config) => { - if (config.CONFIG["use-lastfm"] === true) { - if (!config.CONFIG["api-key"] || !config.CONFIG["lastfm-user"]) { + var topArtistsReq = async (time_range, configWrapper) => { + const { config } = configWrapper; + if (config["use-lastfm"] === true) { + if (!config["api-key"] || !config["lastfm-user"]) return 300; - } - const lastfmperiods = { - short_term: "1month", - medium_term: "6month", - long_term: "overall" - }; - const response = await apiRequest( - "lastfm", - `https://ws.audioscrobbler.com/2.0/?method=user.gettopartists&user=${config.CONFIG["lastfm-user"]}&api_key=${config.CONFIG["api-key"]}&format=json&period=${lastfmperiods[time_range]}` - ); - if (!response) { + const { ["lastfm-user"]: user, ["api-key"]: key } = config; + const response = await apiRequest("lastfm", LASTFM.topartists(user, key, time_range)); + if (!response) return 200; - } - return await convertToSpotify(response.topartists.artist, "artists"); + return await convertArtistData(response.topartists.artist); } else { - const response = await apiRequest("topArtists", `https://api.spotify.com/v1/me/top/artists?limit=50&offset=0&time_range=${time_range}`); - if (!response) { + const response = await apiRequest("topArtists", SPOTIFY.topartists(time_range)); + if (!response) return 200; - } return response.items.map((artist) => { + const image = artist.images[2]?.url || artist.images[1]?.url || PLACEHOLDER; return { id: artist.id, name: artist.name, - image: artist.images[2] ? artist.images[2].url : artist.images[1] ? artist.images[1].url : "https://images.squarespace-cdn.com/content/v1/55fc0004e4b069a519961e2d/1442590746571-RPGKIXWGOO671REUNMCB/image-asset.gif", + image, uri: artist.uri, genres: artist.genres }; }); } }; - var ArtistsPage = ({ config }) => { - const [topArtists, setTopArtists] = import_react11.default.useState(100); - const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default( - ["short_term", "medium_term", "long_term"], - ["Past Month", "Past 6 Months", "All Time"], - `top-artists` - ); + var DropdownOptions = [ + { id: "short_term", name: "Past Month" }, + { id: "medium_term", name: "Past 6 Months" }, + { id: "long_term", name: "All Time" } + ]; + var ArtistsPage = ({ configWrapper }) => { + const [topArtists, setTopArtists] = import_react17.default.useState(100); + const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default(DropdownOptions, "stats:top-artists"); const fetchTopArtists2 = async (time_range, force, set = true) => { if (!force) { let storedData = Spicetify.LocalStorage.get(`stats:top-artists:${time_range}`); - if (storedData) { - setTopArtists(JSON.parse(storedData)); - return; - } + if (storedData) + return setTopArtists(JSON.parse(storedData)); } const start = window.performance.now(); - const topArtists2 = await topArtistsReq(time_range, config); + const topArtists2 = await topArtistsReq(time_range, configWrapper); if (set) setTopArtists(topArtists2); Spicetify.LocalStorage.set(`stats:top-artists:${time_range}`, JSON.stringify(topArtists2)); console.log("total artists fetch time:", window.performance.now() - start); }; - import_react11.default.useEffect(() => { - updatePageCache(0, fetchTopArtists2, activeOption); + import_react17.default.useEffect(() => { + updatePageCache(0, fetchTopArtists2, activeOption.id); }, []); - import_react11.default.useEffect(() => { - fetchTopArtists2(activeOption); + import_react17.default.useEffect(() => { + fetchTopArtists2(activeOption.id); }, [activeOption]); + const refresh = () => { + fetchTopArtists2(activeOption.id, true); + }; const props = { - callback: () => fetchTopArtists2(activeOption, true), - config, - dropdown + title: "Top Artists", + headerEls: [dropdown, /* @__PURE__ */ import_react17.default.createElement(refresh_button_default, { + callback: refresh + }), /* @__PURE__ */ import_react17.default.createElement(settings_button_default, { + configWrapper + })] }; switch (topArtists) { case 300: - return /* @__PURE__ */ import_react11.default.createElement(page_header_default, __spreadValues({ - title: `Top Artists` - }, props), /* @__PURE__ */ import_react11.default.createElement(status_default, { + return /* @__PURE__ */ import_react17.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react17.default.createElement(status_default, { icon: "error", heading: "No API Key or Username", subheading: "Please enter these in the settings menu" })); case 200: - return /* @__PURE__ */ import_react11.default.createElement(page_header_default, __spreadValues({ - title: `Top Artists` - }, props), /* @__PURE__ */ import_react11.default.createElement(status_default, { + return /* @__PURE__ */ import_react17.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react17.default.createElement(status_default, { icon: "error", heading: "Failed to Fetch Top Artists", subheading: "An error occurred while fetching the data" })); case 100: - return /* @__PURE__ */ import_react11.default.createElement(page_header_default, __spreadValues({ - title: `Top Artists` - }, props), /* @__PURE__ */ import_react11.default.createElement(status_default, { + return /* @__PURE__ */ import_react17.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react17.default.createElement(status_default, { icon: "library", heading: "Loading", subheading: "Fetching data..." })); } - const artistCards = topArtists.map((artist, index) => /* @__PURE__ */ import_react11.default.createElement(artist_card_default, { - key: artist.id, - name: artist.name, - image: artist.image, + const artistCards = topArtists.map((artist, index) => /* @__PURE__ */ import_react17.default.createElement(spotify_card_default, { + type: artist.uri.includes("last") ? "lastfm" : "artist", uri: artist.uri, - subtext: `#${index + 1} Artist` + header: artist.name, + subheader: `#${index + 1} Artist`, + imageUrl: artist.image })); - return /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, /* @__PURE__ */ import_react11.default.createElement(page_header_default, __spreadValues({ - title: "Top Artists" - }, props), /* @__PURE__ */ import_react11.default.createElement("div", { - className: `main-gridContainer-gridContainer stats-grid` + return /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react17.default.createElement("div", { + className: `main-gridContainer-gridContainer grid` }, artistCards))); }; - var top_artists_default = import_react11.default.memo(ArtistsPage); + var top_artists_default = import_react17.default.memo(ArtistsPage); // src/pages/top_tracks.tsx - var import_react14 = __toESM(require_react()); + var import_react20 = __toESM(require_react()); // src/components/track_row.tsx - var import_react12 = __toESM(require_react()); - function formatDuration(durationMs) { - const totalSeconds = Math.floor(durationMs / 1e3); - const minutes = Math.floor(totalSeconds / 60); - const seconds = totalSeconds % 60; - return `${minutes.toString().padStart(1, "0")}:${seconds.toString().padStart(2, "0")}`; - } + var import_react18 = __toESM(require_react()); var ArtistLink = ({ name, uri, index, length }) => { - return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement("a", { + return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("a", { draggable: "true", dir: "auto", href: uri, tabIndex: -1 }, name), index === length ? null : ", "); }; - var ExplicitBadge = import_react12.default.memo(() => { - return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement("span", { + var ExplicitBadge = import_react18.default.memo(() => { + return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("span", { className: "TypeElement-ballad-textSubdued-type main-trackList-rowBadges", "data-encore-id": "type" - }, /* @__PURE__ */ import_react12.default.createElement("span", { + }, /* @__PURE__ */ import_react18.default.createElement("span", { "aria-label": "Explicit", className: "main-tag-container", title: "Explicit" }, "E"))); }); var LikedIcon = ({ active, uri }) => { - const [liked, setLiked] = import_react12.default.useState(active); - let id = uri.split(":")[2]; + const [liked, setLiked] = import_react18.default.useState(active); const toggleLike = () => { if (liked) { - Spicetify.CosmosAsync.del("https://api.spotify.com/v1/me/tracks?ids=" + id); - Spicetify.Snackbar.enqueueSnackbar("Removed from your Liked Songs"); + Spicetify.Platform.LibraryAPI.remove(uri); } else { - Spicetify.CosmosAsync.put("https://api.spotify.com/v1/me/tracks?ids=" + id); - Spicetify.Snackbar.enqueueSnackbar("Added to your Liked Songs"); + Spicetify.Platform.LibraryAPI.add(uri); } setLiked(!liked); }; - import_react12.default.useEffect(() => { + import_react18.default.useEffect(() => { setLiked(active); }, [active]); - return /* @__PURE__ */ import_react12.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + return /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { label: liked ? `Remove from Your Library` : "Save to Your Library", placement: "top" - }, /* @__PURE__ */ import_react12.default.createElement("button", { + }, /* @__PURE__ */ import_react18.default.createElement("button", { type: "button", role: "switch", "aria-checked": liked, @@ -1000,7 +1173,7 @@ var stats = (() => { onClick: toggleLike, className: liked ? "main-addButton-button main-trackList-rowHeartButton main-addButton-active" : "main-addButton-button main-trackList-rowHeartButton", tabIndex: -1 - }, /* @__PURE__ */ import_react12.default.createElement("svg", { + }, /* @__PURE__ */ import_react18.default.createElement("svg", { role: "img", height: "16", width: "16", @@ -1008,70 +1181,75 @@ var stats = (() => { viewBox: "0 0 16 16", "data-encore-id": "icon", className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small" - }, /* @__PURE__ */ import_react12.default.createElement("path", { + }, /* @__PURE__ */ import_react18.default.createElement("path", { d: liked ? "M15.724 4.22A4.313 4.313 0 0 0 12.192.814a4.269 4.269 0 0 0-3.622 1.13.837.837 0 0 1-1.14 0 4.272 4.272 0 0 0-6.21 5.855l5.916 7.05a1.128 1.128 0 0 0 1.727 0l5.916-7.05a4.228 4.228 0 0 0 .945-3.577z" : "M1.69 2A4.582 4.582 0 0 1 8 2.023 4.583 4.583 0 0 1 11.88.817h.002a4.618 4.618 0 0 1 3.782 3.65v.003a4.543 4.543 0 0 1-1.011 3.84L9.35 14.629a1.765 1.765 0 0 1-2.093.464 1.762 1.762 0 0 1-.605-.463L1.348 8.309A4.582 4.582 0 0 1 1.689 2zm3.158.252A3.082 3.082 0 0 0 2.49 7.337l.005.005L7.8 13.664a.264.264 0 0 0 .311.069.262.262 0 0 0 .09-.069l5.312-6.33a3.043 3.043 0 0 0 .68-2.573 3.118 3.118 0 0 0-2.551-2.463 3.079 3.079 0 0 0-2.612.816l-.007.007a1.501 1.501 0 0 1-2.045 0l-.009-.008a3.082 3.082 0 0 0-2.121-.861z" })))); }; - var DraggableComponent2 = (_a) => { - var _b = _a, { uri, title } = _b, props = __objRest(_b, ["uri", "title"]); - var _a2, _b2; - const dragHandler = (_b2 = (_a2 = Spicetify.ReactHook).DragHandler) == null ? void 0 : _b2.call(_a2, [uri], title); - return /* @__PURE__ */ import_react12.default.createElement("div", __spreadValues({ + var DraggableComponent = ({ + uri, + title, + ...props + }) => { + const dragHandler = Spicetify.ReactHook.DragHandler?.([uri], title); + return /* @__PURE__ */ import_react18.default.createElement("div", { onDragStart: dragHandler, - draggable: "true" - }, props), props.children); + draggable: "true", + ...props + }, props.children); }; function playAndQueue(uri, uris) { uris = uris.filter((u) => !u.includes("last")); uris = uris.concat(uris.splice(0, uris.indexOf(uri))); queue(uris); } - var MenuWrapper = import_react12.default.memo((props) => /* @__PURE__ */ import_react12.default.createElement(Spicetify.ReactComponent.AlbumMenu, __spreadValues({}, props))); + var MenuWrapper = import_react18.default.memo((props) => /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.AlbumMenu, { + ...props + })); var TrackRow = (props) => { const ArtistLinks = props.artists.map((artist, index) => { - return /* @__PURE__ */ import_react12.default.createElement(ArtistLink, { + return /* @__PURE__ */ import_react18.default.createElement(ArtistLink, { index, length: props.artists.length - 1, name: artist.name, uri: artist.uri }); }); - return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement(Spicetify.ReactComponent.ContextMenu, { - menu: /* @__PURE__ */ import_react12.default.createElement(MenuWrapper, { + return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.ContextMenu, { + menu: /* @__PURE__ */ import_react18.default.createElement(MenuWrapper, { uri: props.uri }), trigger: "right-click" - }, /* @__PURE__ */ import_react12.default.createElement("div", { + }, /* @__PURE__ */ import_react18.default.createElement("div", { role: "row", "aria-rowindex": 2, "aria-selected": "false" - }, /* @__PURE__ */ import_react12.default.createElement(DraggableComponent2, { + }, /* @__PURE__ */ import_react18.default.createElement(DraggableComponent, { uri: props.uri, title: `${props.name} \u2022 ${props.artists.map((artist) => artist.name).join(", ")}`, className: "main-trackList-trackListRow main-trackList-trackListRowGrid", role: "presentation", onClick: (event) => event.detail === 2 && playAndQueue(props.uri, props.uris), style: { height: 56 } - }, /* @__PURE__ */ import_react12.default.createElement("div", { + }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "main-trackList-rowSectionIndex", role: "gridcell", "aria-colindex": 1, tabIndex: -1 - }, /* @__PURE__ */ import_react12.default.createElement("div", { + }, /* @__PURE__ */ import_react18.default.createElement("div", { uri: props.uri, className: "main-trackList-rowMarker" - }, /* @__PURE__ */ import_react12.default.createElement("span", { + }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "TypeElement-ballad-type main-trackList-number", "data-encore-id": "type" - }, props.index), /* @__PURE__ */ import_react12.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + }, props.index), /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { label: `Play ${props.name} by ${props.artists.map((artist) => artist.name).join(", ")}`, placement: "top" - }, /* @__PURE__ */ import_react12.default.createElement("button", { + }, /* @__PURE__ */ import_react18.default.createElement("button", { className: "main-trackList-rowImagePlayButton", "aria-label": `Play ${props.name}`, tabIndex: -1, onClick: () => playAndQueue(props.uri, props.uris) - }, /* @__PURE__ */ import_react12.default.createElement("svg", { + }, /* @__PURE__ */ import_react18.default.createElement("svg", { role: "img", height: "24", width: "24", @@ -1079,14 +1257,14 @@ var stats = (() => { className: "Svg-img-24 Svg-img-24-icon main-trackList-rowPlayPauseIcon", viewBox: "0 0 24 24", "data-encore-id": "icon" - }, /* @__PURE__ */ import_react12.default.createElement("path", { + }, /* @__PURE__ */ import_react18.default.createElement("path", { d: "m7.05 3.606 13.49 7.788a.7.7 0 0 1 0 1.212L7.05 20.394A.7.7 0 0 1 6 19.788V4.212a.7.7 0 0 1 1.05-.606z" - })))))), /* @__PURE__ */ import_react12.default.createElement("div", { + })))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "main-trackList-rowSectionStart", role: "gridcell", "aria-colindex": 2, tabIndex: -1 - }, /* @__PURE__ */ import_react12.default.createElement("img", { + }, /* @__PURE__ */ import_react18.default.createElement("img", { "aria-hidden": "false", draggable: "false", loading: "eager", @@ -1095,55 +1273,55 @@ var stats = (() => { className: "main-image-image main-trackList-rowImage main-image-loaded", width: "40", height: "40" - }), /* @__PURE__ */ import_react12.default.createElement("div", { + }), /* @__PURE__ */ import_react18.default.createElement("div", { className: "main-trackList-rowMainContent" - }, /* @__PURE__ */ import_react12.default.createElement("div", { + }, /* @__PURE__ */ import_react18.default.createElement("div", { dir: "auto", className: "TypeElement-ballad-textBase TypeElement-ballad-textBase-type main-trackList-rowTitle standalone-ellipsis-one-line", "data-encore-id": "type" - }, props.name), props.explicit && /* @__PURE__ */ import_react12.default.createElement(ExplicitBadge, null), /* @__PURE__ */ import_react12.default.createElement("span", { + }, props.name), props.explicit && /* @__PURE__ */ import_react18.default.createElement(ExplicitBadge, null), /* @__PURE__ */ import_react18.default.createElement("span", { className: "TypeElement-mesto-textSubdued TypeElement-mesto-textSubdued-type main-trackList-rowSubTitle standalone-ellipsis-one-line", "data-encore-id": "type" - }, ArtistLinks))), /* @__PURE__ */ import_react12.default.createElement("div", { + }, ArtistLinks))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "main-trackList-rowSectionVariable", role: "gridcell", "aria-colindex": 3, tabIndex: -1 - }, /* @__PURE__ */ import_react12.default.createElement("span", { + }, /* @__PURE__ */ import_react18.default.createElement("span", { "data-encore-id": "type", className: "TypeElement-mesto TypeElement-mesto-type" - }, /* @__PURE__ */ import_react12.default.createElement("a", { + }, /* @__PURE__ */ import_react18.default.createElement("a", { draggable: "true", className: "standalone-ellipsis-one-line", dir: "auto", href: props.album_uri, tabIndex: -1 - }, props.album))), /* @__PURE__ */ import_react12.default.createElement("div", { + }, props.album))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "main-trackList-rowSectionEnd", role: "gridcell", "aria-colindex": 5, tabIndex: -1 - }, /* @__PURE__ */ import_react12.default.createElement(LikedIcon, { + }, /* @__PURE__ */ import_react18.default.createElement(LikedIcon, { active: props.liked || false, uri: props.uri - }), /* @__PURE__ */ import_react12.default.createElement("div", { + }), /* @__PURE__ */ import_react18.default.createElement("div", { className: "TypeElement-mesto-textSubdued TypeElement-mesto-textSubdued-type main-trackList-rowDuration", "data-encore-id": "type" - }, formatDuration(props.duration)), /* @__PURE__ */ import_react12.default.createElement(Spicetify.ReactComponent.ContextMenu, { - menu: /* @__PURE__ */ import_react12.default.createElement(MenuWrapper, { + }, Spicetify.Player.formatTime(props.duration)), /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.ContextMenu, { + menu: /* @__PURE__ */ import_react18.default.createElement(MenuWrapper, { uri: props.uri }), trigger: "click" - }, /* @__PURE__ */ import_react12.default.createElement("button", { + }, /* @__PURE__ */ import_react18.default.createElement("button", { type: "button", "aria-haspopup": "menu", "aria-label": `More options for ${props.name}`, className: "main-moreButton-button Button-sm-16-buttonTertiary-iconOnly-condensed-useBrowserDefaultFocusStyle Button-small-small-buttonTertiary-iconOnly-condensed-useBrowserDefaultFocusStyle main-trackList-rowMoreButton", tabIndex: -1 - }, /* @__PURE__ */ import_react12.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + }, /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { label: `More options for ${props.name} by ${props.artists.map((artist) => artist.name).join(", ")}`, placement: "top" - }, /* @__PURE__ */ import_react12.default.createElement("span", null, /* @__PURE__ */ import_react12.default.createElement("svg", { + }, /* @__PURE__ */ import_react18.default.createElement("span", null, /* @__PURE__ */ import_react18.default.createElement("svg", { role: "img", height: "16", width: "16", @@ -1151,72 +1329,72 @@ var stats = (() => { viewBox: "0 0 16 16", "data-encore-id": "icon", className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small" - }, /* @__PURE__ */ import_react12.default.createElement("path", { + }, /* @__PURE__ */ import_react18.default.createElement("path", { d: "M3 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm6.5 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zM16 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" }))))))))))); }; - var track_row_default = import_react12.default.memo(TrackRow); + var track_row_default = import_react18.default.memo(TrackRow); // src/components/tracklist.tsx - var import_react13 = __toESM(require_react()); + var import_react19 = __toESM(require_react()); var Tracklist = ({ minified = false, children }) => { - return /* @__PURE__ */ import_react13.default.createElement("div", { + return /* @__PURE__ */ import_react19.default.createElement("div", { role: "grid", "aria-rowcount": minified ? 5 : 50, "aria-colcount": 4, className: "main-trackList-trackList main-trackList-indexable", tabIndex: 0 - }, !minified && /* @__PURE__ */ import_react13.default.createElement("div", { + }, !minified && /* @__PURE__ */ import_react19.default.createElement("div", { className: "main-trackList-trackListHeader", role: "presentation" - }, /* @__PURE__ */ import_react13.default.createElement("div", { + }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "main-trackList-trackListHeaderRow main-trackList-trackListRowGrid", role: "row", "aria-rowindex": 1 - }, /* @__PURE__ */ import_react13.default.createElement("div", { + }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "main-trackList-rowSectionIndex", role: "columnheader", "aria-colindex": 1, "aria-sort": "none", tabIndex: -1 - }, "#"), /* @__PURE__ */ import_react13.default.createElement("div", { + }, "#"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "main-trackList-rowSectionStart", role: "columnheader", "aria-colindex": 2, "aria-sort": "none", tabIndex: -1 - }, /* @__PURE__ */ import_react13.default.createElement("button", { + }, /* @__PURE__ */ import_react19.default.createElement("button", { className: "main-trackList-column main-trackList-sortable", tabIndex: -1 - }, /* @__PURE__ */ import_react13.default.createElement("span", { + }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "TypeElement-mesto-type standalone-ellipsis-one-line", "data-encore-id": "type" - }, "Title"))), /* @__PURE__ */ import_react13.default.createElement("div", { + }, "Title"))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "main-trackList-rowSectionVariable", role: "columnheader", "aria-colindex": 3, "aria-sort": "none", tabIndex: -1 - }, /* @__PURE__ */ import_react13.default.createElement("button", { + }, /* @__PURE__ */ import_react19.default.createElement("button", { className: "main-trackList-column main-trackList-sortable", tabIndex: -1 - }, /* @__PURE__ */ import_react13.default.createElement("span", { + }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "TypeElement-mesto-type standalone-ellipsis-one-line", "data-encore-id": "type" - }, "Album"))), /* @__PURE__ */ import_react13.default.createElement("div", { + }, "Album"))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "main-trackList-rowSectionEnd", role: "columnheader", "aria-colindex": 5, "aria-sort": "none", tabIndex: -1 - }, /* @__PURE__ */ import_react13.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { + }, /* @__PURE__ */ import_react19.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { label: "Duration", placement: "top" - }, /* @__PURE__ */ import_react13.default.createElement("button", { + }, /* @__PURE__ */ import_react19.default.createElement("button", { "aria-label": "Duration", className: "main-trackList-column main-trackList-durationHeader main-trackList-sortable", tabIndex: -1 - }, /* @__PURE__ */ import_react13.default.createElement("svg", { + }, /* @__PURE__ */ import_react19.default.createElement("svg", { role: "img", height: "16", width: "16", @@ -1224,188 +1402,198 @@ var stats = (() => { viewBox: "0 0 16 16", "data-encore-id": "icon", className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small" - }, /* @__PURE__ */ import_react13.default.createElement("path", { + }, /* @__PURE__ */ import_react19.default.createElement("path", { d: "M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zM0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8z" - }), /* @__PURE__ */ import_react13.default.createElement("path", { + }), /* @__PURE__ */ import_react19.default.createElement("path", { d: "M8 3.25a.75.75 0 0 1 .75.75v3.25H11a.75.75 0 0 1 0 1.5H7.25V4A.75.75 0 0 1 8 3.25z" - }))))))), /* @__PURE__ */ import_react13.default.createElement("div", { + }))))))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "main-rootlist-wrapper", role: "presentation", style: { height: (minified ? 5 : 50) * 56 } - }, /* @__PURE__ */ import_react13.default.createElement("div", { + }, /* @__PURE__ */ import_react19.default.createElement("div", { role: "presentation" }, children))); }; var tracklist_default = Tracklist; // src/pages/top_tracks.tsx - var topTracksReq = async (time_range, config) => { - if (config.CONFIG["use-lastfm"] === true) { - if (!config.CONFIG["api-key"] || !config.CONFIG["lastfm-user"]) { + var topTracksReq = async (time_range, configWrapper) => { + const { config } = configWrapper; + if (config["use-lastfm"] === true) { + if (!config["api-key"] || !config["lastfm-user"]) return 300; - } - const lastfmperiods = { - short_term: "1month", - medium_term: "6month", - long_term: "overall" - }; - const lastfmData = await apiRequest( - "lastfm", - `https://ws.audioscrobbler.com/2.0/?method=user.gettoptracks&user=${config.CONFIG["lastfm-user"]}&api_key=${config.CONFIG["api-key"]}&format=json&period=${lastfmperiods[time_range]}` - ); - if (!lastfmData) { + const { ["lastfm-user"]: user, ["api-key"]: key } = config; + const lastfmData = await apiRequest("lastfm", LASTFM.toptracks(user, key, time_range)); + if (!lastfmData) return 200; - } - const spotifyData = await convertToSpotify(lastfmData.toptracks.track, "tracks"); - const fetchedLikedArray = await checkLiked(spotifyData.map((track) => track.id)); - if (!fetchedLikedArray) { + const spotifyData = await convertTrackData(lastfmData.toptracks.track); + const likedArray2 = await checkLiked(spotifyData.map((track) => track.id)); + if (!likedArray2) return 200; - } spotifyData.forEach((track, index) => { - track.liked = fetchedLikedArray[index]; + track.liked = likedArray2[index]; }); return spotifyData; - } else { - const response = await apiRequest("topTracks", `https://api.spotify.com/v1/me/top/tracks?limit=50&offset=0&time_range=${time_range}`); - if (!response) { - return 200; - } - const fetchedLikedArray = await checkLiked(response.items.map((track) => track.id)); - if (!fetchedLikedArray) { - return 200; - } - return response.items.map((track, index) => { - return { - liked: fetchedLikedArray[index], - name: track.name, - image: track.album.images[2] ? track.album.images[2].url : track.album.images[1] ? track.album.images[1].url : "https://images.squarespace-cdn.com/content/v1/55fc0004e4b069a519961e2d/1442590746571-RPGKIXWGOO671REUNMCB/image-asset.gif", - uri: track.uri, - id: track.id, - artists: track.artists.map((artist) => ({ name: artist.name, uri: artist.uri })), - duration: track.duration_ms, - album: track.album.name, - album_uri: track.album.uri, - popularity: track.popularity, - explicit: track.explicit, - release_year: track.album.release_date.slice(0, 4) - }; - }); } + const response = await apiRequest("topTracks", SPOTIFY.toptracks(time_range)); + if (!response) + return 200; + const likedArray = await checkLiked(response.items.map((track) => track.id)); + if (!likedArray) + return 200; + return response.items.map((track, index) => { + const images = track.album.images; + const image = images[2]?.url || images[1]?.url || PLACEHOLDER; + return { + liked: likedArray[index], + name: track.name, + image, + uri: track.uri, + id: track.id, + artists: track.artists.map((artist) => ({ + name: artist.name, + uri: artist.uri + })), + duration: track.duration_ms, + album: track.album.name, + album_uri: track.album.uri, + popularity: track.popularity, + explicit: track.explicit, + release_year: track.album.release_date.slice(0, 4) + }; + }); }; - var TracksPage = ({ config }) => { - const [topTracks, setTopTracks] = import_react14.default.useState(100); - const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default( - ["short_term", "medium_term", "long_term"], - ["Past Month", "Past 6 Months", "All Time"], - "top-tracks" - ); + var DropdownOptions2 = [ + { id: "short_term", name: "Past Month" }, + { id: "medium_term", name: "Past 6 Months" }, + { id: "long_term", name: "All Time" } + ]; + var TracksPage = ({ configWrapper }) => { + const { LocalStorage } = Spicetify; + const [topTracks, setTopTracks] = import_react20.default.useState(100); + const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions2, "stats:top-tracks"); const fetchTopTracks = async (time_range, force, set = true) => { if (!force) { - let storedData = Spicetify.LocalStorage.get(`stats:top-tracks:${time_range}`); - if (storedData) { - setTopTracks(JSON.parse(storedData)); - return; - } + const storedData = LocalStorage.get(`stats:top-tracks:${time_range}`); + if (storedData) + return setTopTracks(JSON.parse(storedData)); } const start = window.performance.now(); - if (!time_range) - return; - const topTracks2 = await topTracksReq(time_range, config); + const topTracks2 = await topTracksReq(time_range, configWrapper); if (set) setTopTracks(topTracks2); - Spicetify.LocalStorage.set(`stats:top-tracks:${time_range}`, JSON.stringify(topTracks2)); + LocalStorage.set(`stats:top-tracks:${time_range}`, JSON.stringify(topTracks2)); console.log("total tracks fetch time:", window.performance.now() - start); }; - import_react14.default.useEffect(() => { - updatePageCache(1, fetchTopTracks, activeOption); + import_react20.default.useEffect(() => { + updatePageCache(1, fetchTopTracks, activeOption.id); }, []); - import_react14.default.useEffect(() => { - fetchTopTracks(activeOption); + import_react20.default.useEffect(() => { + fetchTopTracks(activeOption.id); }, [activeOption]); + const refresh = () => { + fetchTopTracks(activeOption.id, true); + }; const props = { - callback: () => fetchTopTracks(activeOption, true), - config, - dropdown, - createPlaylist: () => { - } + title: "Top Tracks", + headerEls: [dropdown, /* @__PURE__ */ import_react20.default.createElement(refresh_button_default, { + callback: refresh + }), /* @__PURE__ */ import_react20.default.createElement(settings_button_default, { + configWrapper + })] }; switch (topTracks) { case 300: - return /* @__PURE__ */ import_react14.default.createElement(page_header_default, __spreadValues({ - title: `Top Tracks` - }, props), /* @__PURE__ */ import_react14.default.createElement(status_default, { + return /* @__PURE__ */ import_react20.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react20.default.createElement(status_default, { icon: "error", heading: "No API Key or Username", subheading: "Please enter these in the settings menu" })); case 200: - return /* @__PURE__ */ import_react14.default.createElement(page_header_default, __spreadValues({ - title: `TopTracks` - }, props), /* @__PURE__ */ import_react14.default.createElement(status_default, { + return /* @__PURE__ */ import_react20.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react20.default.createElement(status_default, { icon: "error", heading: "Failed to Fetch Top Tracks", subheading: "An error occurred while fetching the data" })); case 100: - return /* @__PURE__ */ import_react14.default.createElement(page_header_default, __spreadValues({ - title: `Top Tracks` - }, props), /* @__PURE__ */ import_react14.default.createElement(status_default, { + return /* @__PURE__ */ import_react20.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react20.default.createElement(status_default, { icon: "library", heading: "Loading", subheading: "Fetching data..." })); } - const createPlaylist = async () => { - await Spicetify.CosmosAsync.post("sp://core-playlist/v1/rootlist", { - operation: "create", - name: `Top Songs - ${activeOption}`, - playlist: true, - public: false, - uris: topTracks.map((track) => track.uri) - }).catch(() => Spicetify.Snackbar.enqueueSnackbar("The playlist could not be created.")); + const infoToCreatePlaylist = { + playlistName: `Top Songs - ${activeOption}`, + itemsUris: topTracks.map((track) => track.uri) }; - props.createPlaylist = createPlaylist; - const trackRows = topTracks.map((track, index) => /* @__PURE__ */ import_react14.default.createElement(track_row_default, __spreadProps(__spreadValues({ - index: index + 1 - }, track), { + const trackRows = topTracks.map((track, index) => /* @__PURE__ */ import_react20.default.createElement(track_row_default, { + index: index + 1, + ...track, uris: topTracks.map((track2) => track2.uri) - }))); - return /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement(page_header_default, __spreadValues({ - title: "Top Tracks" - }, props), /* @__PURE__ */ import_react14.default.createElement(tracklist_default, null, trackRows))); + })); + return /* @__PURE__ */ import_react20.default.createElement(page_container_default, { + ...props, + infoToCreatePlaylist + }, /* @__PURE__ */ import_react20.default.createElement(tracklist_default, null, trackRows)); }; - var top_tracks_default = import_react14.default.memo(TracksPage); + var top_tracks_default = import_react20.default.memo(TracksPage); // src/pages/top_genres.tsx - var import_react18 = __toESM(require_react()); + var import_react25 = __toESM(require_react()); // src/components/cards/stat_card.tsx - var import_react15 = __toESM(require_react()); - var StatCard = (props) => { - return /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement("div", { + var import_react21 = __toESM(require_react()); + function formatValue(name, value) { + switch (name) { + case "tempo": + return `${Math.round(value)} bpm`; + case "popularity": + return `${Math.round(value)} %`; + default: + return `${Math.round(value * 100)} %`; + } + } + function normalizeString(inputString) { + return inputString.charAt(0).toUpperCase() + inputString.slice(1).toLowerCase(); + } + function StatCard(props) { + const { TextComponent } = Spicetify.ReactComponent; + const { label, value } = props; + return /* @__PURE__ */ import_react21.default.createElement("div", { className: "main-card-card" - }, /* @__PURE__ */ import_react15.default.createElement("div", { - className: "stats-cardValue" - }, props.value), /* @__PURE__ */ import_react15.default.createElement("div", null, /* @__PURE__ */ import_react15.default.createElement("div", { - className: "TypeElement-balladBold-textBase-4px-type main-cardHeader-text stats-cardText", - "data-encore-id": "type" - }, props.stat)))); - }; - var stat_card_default = import_react15.default.memo(StatCard); + }, /* @__PURE__ */ import_react21.default.createElement(TextComponent, { + as: "div", + semanticColor: "textBase", + variant: "alto", + children: typeof value === "number" ? formatValue(label, value) : value + }), /* @__PURE__ */ import_react21.default.createElement(TextComponent, { + as: "div", + semanticColor: "textBase", + variant: "balladBold", + children: normalizeString(label) + })); + } + var stat_card_default = StatCard; // src/components/cards/genres_card.tsx - var import_react16 = __toESM(require_react()); + var import_react22 = __toESM(require_react()); var genreLine = (name, value, limit, total) => { - return /* @__PURE__ */ import_react16.default.createElement("div", { + return /* @__PURE__ */ import_react22.default.createElement("div", { className: "stats-genreRow" - }, /* @__PURE__ */ import_react16.default.createElement("div", { + }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "stats-genreRowFill", style: { width: `calc(${value / limit * 100}% + ${(limit - value) / (limit - 1) * 100}px)` } - }, /* @__PURE__ */ import_react16.default.createElement("span", { + }, /* @__PURE__ */ import_react22.default.createElement("span", { className: "stats-genreText" - }, name)), /* @__PURE__ */ import_react16.default.createElement("span", { + }, name)), /* @__PURE__ */ import_react22.default.createElement("span", { className: "stats-genreValue" }, Math.round(value / total * 100) + "%")); }; @@ -1416,76 +1604,109 @@ var stats = (() => { }; var genresCard = ({ genres, total }) => { const genresArray = genres.sort(([, a], [, b]) => b - a).slice(0, 10); - return /* @__PURE__ */ import_react16.default.createElement("div", { + return /* @__PURE__ */ import_react22.default.createElement("div", { className: `main-card-card stats-genreCard` }, genreLines(genresArray, total)); }; - var genres_card_default = import_react16.default.memo(genresCard); + var genres_card_default = genresCard; // src/components/inline_grid.tsx - var import_react17 = __toESM(require_react()); - var scrollGrid = (event) => { - const grid = event.target.parentNode.querySelector("div"); + var import_react23 = __toESM(require_react()); + function scrollGrid(event) { + const { target } = event; + if (!(target instanceof HTMLElement)) + return; + const grid = target.parentNode?.querySelector("div"); + if (!grid) + return; grid.scrollLeft += grid.clientWidth; if (grid.scrollWidth - grid.clientWidth - grid.scrollLeft <= grid.clientWidth) { grid.setAttribute("data-scroll", "end"); } else { grid.setAttribute("data-scroll", "both"); } - }; - var scrollGridLeft = (event) => { - const grid = event.target.parentNode.querySelector("div"); + } + function scrollGridLeft(event) { + const { target } = event; + if (!(target instanceof HTMLElement)) + return; + const grid = target.parentNode?.querySelector("div"); + if (!grid) + return; grid.scrollLeft -= grid.clientWidth; if (grid.scrollLeft <= grid.clientWidth) { grid.setAttribute("data-scroll", "start"); } else { grid.setAttribute("data-scroll", "both"); } - }; - var InlineGrid = (props) => { - return /* @__PURE__ */ import_react17.default.createElement("section", { + } + function InlineGrid(props) { + const { children, special } = props; + return /* @__PURE__ */ import_react23.default.createElement("section", { className: "stats-gridInlineSection" - }, /* @__PURE__ */ import_react17.default.createElement("button", { + }, /* @__PURE__ */ import_react23.default.createElement("button", { className: "stats-scrollButton", onClick: scrollGridLeft - }, "<"), /* @__PURE__ */ import_react17.default.createElement("button", { + }, "<"), /* @__PURE__ */ import_react23.default.createElement("button", { className: "stats-scrollButton", onClick: scrollGrid - }, ">"), /* @__PURE__ */ import_react17.default.createElement("div", { - className: `main-gridContainer-gridContainer stats-gridInline${props.special ? " stats-specialGrid" : ""}`, + }, ">"), /* @__PURE__ */ import_react23.default.createElement("div", { + className: `main-gridContainer-gridContainer stats-gridInline${special ? " stats-specialGrid" : ""}`, "data-scroll": "start" - }, props.children)); - }; - var inline_grid_default = InlineGrid; + }, children)); + } + var inline_grid_default = import_react23.default.memo(InlineGrid); + + // src/components/shelf.tsx + var import_react24 = __toESM(require_react()); + function Shelf(props) { + const { TextComponent } = Spicetify.ReactComponent; + const { title, children } = props; + return /* @__PURE__ */ import_react24.default.createElement("section", { + className: "main-shelf-shelf Shelf" + }, /* @__PURE__ */ import_react24.default.createElement("div", { + className: "main-shelf-header" + }, /* @__PURE__ */ import_react24.default.createElement("div", { + className: "main-shelf-topRow" + }, /* @__PURE__ */ import_react24.default.createElement("div", { + className: "main-shelf-titleWrapper" + }, /* @__PURE__ */ import_react24.default.createElement(TextComponent, { + children: title, + as: "h2", + variant: "canon", + semanticColor: "textBase" + })))), /* @__PURE__ */ import_react24.default.createElement("section", null, children)); + } + var shelf_default = import_react24.default.memo(Shelf); // src/pages/top_genres.tsx - var GenresPage = ({ config }) => { - const [topGenres, setTopGenres] = import_react18.default.useState(100); - const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default( - ["short_term", "medium_term", "long_term"], - ["Past Month", "Past 6 Months", "All Time"], - "top-genres" - ); + var DropdownOptions3 = [ + { id: "short_term", name: "Past Month" }, + { id: "medium_term", name: "Past 6 Months" }, + { id: "long_term", name: "All Time" } + ]; + var GenresPage = ({ configWrapper }) => { + const { LocalStorage } = Spicetify; + const [topGenres, setTopGenres] = import_react25.default.useState(100); + const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions3, "stats:top-genres"); const fetchTopGenres = async (time_range, force, set = true, force_refetch) => { if (!force) { - let storedData = Spicetify.LocalStorage.get(`stats:top-genres:${time_range}`); - if (storedData) { - setTopGenres(JSON.parse(storedData)); - return; - } + let storedData = LocalStorage.get(`stats:top-genres:${time_range}`); + if (storedData) + return setTopGenres(JSON.parse(storedData)); } const start = window.performance.now(); - const cacheInfo = JSON.parse(Spicetify.LocalStorage.get("stats:cache-info")); + const cacheInfo = JSON.parse(LocalStorage.get("stats:cache-info")); const fetchedItems = await Promise.all( ["artists", "tracks"].map(async (type, index) => { if (cacheInfo[index] === true && !force_refetch) { - return await JSON.parse(Spicetify.LocalStorage.get(`stats:top-${type}:${time_range}`)); + return await JSON.parse(LocalStorage.get(`stats:top-${type}:${time_range}`)); } - const fetchedItems2 = await (type === "artists" ? topArtistsReq(time_range, config) : topTracksReq(time_range, config)); + const fetchedItems2 = await (type === "artists" ? topArtistsReq(time_range, configWrapper) : topTracksReq(time_range, configWrapper)); cacheInfo[index] = true; cacheInfo[2] = true; - Spicetify.LocalStorage.set(`stats:top-${type}:${time_range}`, JSON.stringify(fetchedItems2)); - Spicetify.LocalStorage.set("stats:cache-info", JSON.stringify(cacheInfo)); + LocalStorage.set(`stats:top-${type}:${time_range}`, JSON.stringify(fetchedItems2)); + LocalStorage.set("stats:cache-info", JSON.stringify(cacheInfo)); return fetchedItems2; }) ); @@ -1493,8 +1714,8 @@ var stats = (() => { if (fetchedItems[i] === 200 || fetchedItems[i] === 300) return setTopGenres(fetchedItems[i]); } - const fetchedArtists = fetchedItems[0].filter((artist) => artist == null ? void 0 : artist.genres); - const fetchedTracks = fetchedItems[1].filter((track) => track == null ? void 0 : track.id); + const fetchedArtists = fetchedItems[0].filter((artist) => artist?.genres); + const fetchedTracks = fetchedItems[1].filter((track) => track?.id); const genres = fetchedArtists.reduce((acc, artist) => { artist.genres.forEach((genre) => { const index = acc.findIndex(([g]) => g === genre); @@ -1525,12 +1746,12 @@ var stats = (() => { return track.id; }); async function testDupe(track) { - const spotifyItem = await Spicetify.CosmosAsync.get( - `https://api.spotify.com/v1/search?q=track:${filterLink(track.name)}+artist:${filterLink(track.artists[0].name)}&type=track` - ).then((res) => { - var _a; - return (_a = res.tracks) == null ? void 0 : _a.items; - }); + const spotifyItem = await apiRequest( + "track", + SPOTIFY.search(track.name, track.artists[0].name), + 1, + false + ).then((res) => res.tracks?.items); if (!spotifyItem) return false; return spotifyItem.some((item) => { @@ -1540,7 +1761,7 @@ var stats = (() => { let obscureTracks2 = []; for (let i = 0; i < fetchedTracks.length; i++) { let track = fetchedTracks[i]; - if (!(track == null ? void 0 : track.popularity)) + if (!track?.popularity) continue; if (obscureTracks2.length < 5) { const dupe = await testDupe(track); @@ -1580,131 +1801,126 @@ var stats = (() => { audioFeatures[feature] += track[feature]; }); } - audioFeatures = __spreadValues({ popularity: trackPopularity, explicitness }, audioFeatures); + audioFeatures = { + popularity: trackPopularity, + explicitness, + ...audioFeatures + }; for (let key in audioFeatures) { audioFeatures[key] = audioFeatures[key] / 50; } console.log("total genres fetch time:", window.performance.now() - start); if (set) - setTopGenres({ genres, features: audioFeatures, years: releaseData, obscureTracks: obscureTracks2 }); - Spicetify.LocalStorage.set( + setTopGenres({ + genres, + features: audioFeatures, + years: releaseData, + obscureTracks: obscureTracks2 + }); + LocalStorage.set( `stats:top-genres:${time_range}`, - JSON.stringify({ genres, features: audioFeatures, years: releaseData, obscureTracks: obscureTracks2 }) + JSON.stringify({ + genres, + features: audioFeatures, + years: releaseData, + obscureTracks: obscureTracks2 + }) ); }; - import_react18.default.useEffect(() => { - updatePageCache(2, fetchTopGenres, activeOption); + import_react25.default.useEffect(() => { + updatePageCache(2, fetchTopGenres, activeOption.id); }, []); - import_react18.default.useEffect(() => { - fetchTopGenres(activeOption); + import_react25.default.useEffect(() => { + fetchTopGenres(activeOption.id); }, [activeOption]); + const refresh = () => { + fetchTopGenres(activeOption.id, true); + }; const props = { - callback: () => fetchTopGenres(activeOption, true, true, true), - config, - dropdown + title: "Top Genres", + headerEls: [dropdown, /* @__PURE__ */ import_react25.default.createElement(refresh_button_default, { + callback: refresh + }), /* @__PURE__ */ import_react25.default.createElement(settings_button_default, { + configWrapper + })] }; switch (topGenres) { case 300: - return /* @__PURE__ */ import_react18.default.createElement(page_header_default, __spreadValues({ - title: `Top Genres` - }, props), /* @__PURE__ */ import_react18.default.createElement(status_default, { + return /* @__PURE__ */ import_react25.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react25.default.createElement(status_default, { icon: "error", heading: "No API Key or Username", subheading: "Please enter these in the settings menu" })); case 200: - return /* @__PURE__ */ import_react18.default.createElement(page_header_default, __spreadValues({ - title: "Top Genres" - }, props), /* @__PURE__ */ import_react18.default.createElement(status_default, { + return /* @__PURE__ */ import_react25.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react25.default.createElement(status_default, { icon: "error", heading: "Failed to Fetch Top Genres", subheading: "An error occurred while fetching the data" })); case 100: - return /* @__PURE__ */ import_react18.default.createElement(page_header_default, __spreadValues({ - title: `Top Genres` - }, props), /* @__PURE__ */ import_react18.default.createElement(status_default, { + return /* @__PURE__ */ import_react25.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react25.default.createElement(status_default, { icon: "library", heading: "Loading", subheading: "Fetching data..." })); } - const parseVal = (key) => { - switch (key) { - case "tempo": - return Math.round(topGenres.features[key]) + "bpm"; - case "popularity": - return Math.round(topGenres.features[key]) + "%"; - default: - return Math.round(topGenres.features[key] * 100) + "%"; - } - }; - const statCards = []; - for (let key in topGenres.features) { - statCards.push(/* @__PURE__ */ import_react18.default.createElement(stat_card_default, { - stat: key[0].toUpperCase() + key.slice(1), - value: parseVal(key) - })); - } - const obscureTracks = topGenres.obscureTracks.map((track, index) => /* @__PURE__ */ import_react18.default.createElement(track_row_default, __spreadProps(__spreadValues({ - index: index + 1 - }, track), { + const statCards = Object.entries(topGenres.features).map(([key, value]) => { + return /* @__PURE__ */ import_react25.default.createElement(stat_card_default, { + label: key, + value + }); + }); + const obscureTracks = topGenres.obscureTracks.map((track, index) => /* @__PURE__ */ import_react25.default.createElement(track_row_default, { + index: index + 1, + ...track, uris: topGenres.obscureTracks.map((track2) => track2.uri) - }))); - return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement(page_header_default, __spreadValues({ - title: "Top Genres" - }, props), /* @__PURE__ */ import_react18.default.createElement("section", { + })); + return /* @__PURE__ */ import_react25.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react25.default.createElement("section", { className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react18.default.createElement(genres_card_default, { + }, /* @__PURE__ */ import_react25.default.createElement(genres_card_default, { genres: topGenres.genres, total: 1275 - }), /* @__PURE__ */ import_react18.default.createElement(inline_grid_default, { + }), /* @__PURE__ */ import_react25.default.createElement(inline_grid_default, { special: true - }, statCards)), /* @__PURE__ */ import_react18.default.createElement("section", { - className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react18.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react18.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react18.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react18.default.createElement("h2", { - className: "Type__TypeElement-sc-goli3j-0 TypeElement-canon-textBase-type main-shelf-title" - }, "Release Year Distribution")))), /* @__PURE__ */ import_react18.default.createElement("section", null, /* @__PURE__ */ import_react18.default.createElement(genres_card_default, { + }, statCards)), /* @__PURE__ */ import_react25.default.createElement(shelf_default, { + title: "Release Year Distribution" + }, /* @__PURE__ */ import_react25.default.createElement(genres_card_default, { genres: topGenres.years, total: 50 - }))), /* @__PURE__ */ import_react18.default.createElement("section", { - className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react18.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react18.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react18.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react18.default.createElement("h2", { - className: "Type__TypeElement-sc-goli3j-0 TypeElement-canon-textBase-type main-shelf-title" - }, "Most Obscure Tracks")))), /* @__PURE__ */ import_react18.default.createElement("section", null, /* @__PURE__ */ import_react18.default.createElement(tracklist_default, { + })), /* @__PURE__ */ import_react25.default.createElement(shelf_default, { + title: "Most Obscure Tracks" + }, /* @__PURE__ */ import_react25.default.createElement(tracklist_default, { minified: true - }, obscureTracks))))); + }, obscureTracks))); }; - var top_genres_default = import_react18.default.memo(GenresPage); + var top_genres_default = import_react25.default.memo(GenresPage); // src/pages/library.tsx - var import_react19 = __toESM(require_react()); - var LibraryPage = ({ config }) => { - const [library, setLibrary] = import_react19.default.useState(100); - const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default(["owned", "all"], ["My Playlists", "All Playlists"], "library"); + var import_react26 = __toESM(require_react()); + var DropdownOptions4 = [ + { id: "owned", name: "My Playlists" }, + { id: "all", name: "All Playlists" } + ]; + var LibraryPage = ({ configWrapper }) => { + const [library, setLibrary] = import_react26.default.useState(100); + const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default(DropdownOptions4, "stats:library"); const fetchData = async (option, force, set = true) => { try { if (!force) { let storedData = Spicetify.LocalStorage.get(`stats:library:${option}`); - if (storedData) { - setLibrary(JSON.parse(storedData)); - return; - } + if (storedData) + return setLibrary(JSON.parse(storedData)); } const start = window.performance.now(); - const rootlistItems = await apiRequest("rootlist", "sp://core-playlist/v1/rootlist"); + const rootlistItems = await apiRequest("rootlist", SPOTIFY.rootlist); const flattenPlaylists = (items) => { const playlists2 = []; items.forEach((row) => { @@ -1719,7 +1935,7 @@ var stats = (() => { }); return playlists2; }; - let playlists = flattenPlaylists(rootlistItems == null ? void 0 : rootlistItems.rows); + let playlists = flattenPlaylists(rootlistItems?.rows); playlists = playlists.sort((a, b) => a.ownedBySelf === b.ownedBySelf ? 0 : a.ownedBySelf ? -1 : 1); let indexOfFirstNotOwned = -1; let playlistUris = []; @@ -1737,7 +1953,7 @@ var stats = (() => { }, 0); const playlistsMeta = await Promise.all( playlistUris.map((uri) => { - return apiRequest("playlistsMetadata", `sp://core-playlist/v1/playlist/${uri}`, 5, false); + return apiRequest("playlistsMetadata", SPOTIFY.playlist(uri), 5, false); }) ); let duration = 0; @@ -1764,7 +1980,7 @@ var stats = (() => { } duration += playlist.playlist.duration; playlist.items.forEach((track) => { - if (!(track == null ? void 0 : track.album)) + if (!track?.album) return; if (track.link.includes("local")) return; @@ -1783,7 +1999,10 @@ var stats = (() => { const [topArtists, topGenres, topGenresTotal] = await fetchTopArtists(artists); const [ownedTopArtists, ownedTopGenres, ownedTopGenresTotal] = await fetchTopArtists(ownedArtists); const [topAlbums, releaseYears, releaseYearsTotal] = await fetchTopAlbums(albums); - const [ownedTopAlbums, ownedReleaseYears, ownedReleaseYearsTotal] = await fetchTopAlbums(ownedAlbums, topAlbums); + const [ownedTopAlbums, ownedReleaseYears, ownedReleaseYearsTotal] = await fetchTopAlbums( + ownedAlbums, + topAlbums + ); const fetchedFeatures = await fetchAudioFeatures(trackIDs); const audioFeatures = { danceability: 0, @@ -1798,7 +2017,11 @@ var stats = (() => { let ownedAudioFeatures = {}; for (let i = 0; i < fetchedFeatures.length; i++) { if (i === ownedTrackCount) { - ownedAudioFeatures = __spreadValues({ popularity: ownedPopularity, explicitness: ownedExplicitCount }, audioFeatures); + ownedAudioFeatures = { + popularity: ownedPopularity, + explicitness: ownedExplicitCount, + ...audioFeatures + }; } if (!fetchedFeatures[i]) continue; @@ -1807,7 +2030,11 @@ var stats = (() => { audioFeatures[feature] += track[feature]; }); } - const allAudioFeatures = __spreadValues({ popularity, explicitness: explicitCount }, audioFeatures); + const allAudioFeatures = { + popularity, + explicitness: explicitCount, + ...audioFeatures + }; for (let key in allAudioFeatures) { allAudioFeatures[key] /= fetchedFeatures.length; } @@ -1856,588 +2083,335 @@ var stats = (() => { setLibrary(200); } }; - import_react19.default.useEffect(() => { - updatePageCache(3, fetchData, activeOption, true); + import_react26.default.useEffect(() => { + updatePageCache(3, fetchData, activeOption.id, true); }, []); - import_react19.default.useEffect(() => { - fetchData(activeOption); + import_react26.default.useEffect(() => { + fetchData(activeOption.id); }, [activeOption]); + const refresh = () => { + fetchData(activeOption.id, true); + }; const props = { - callback: () => fetchData(activeOption, true), - config, - dropdown + title: "Library Analysis", + headerEls: [dropdown, /* @__PURE__ */ import_react26.default.createElement(refresh_button_default, { + callback: refresh + }), /* @__PURE__ */ import_react26.default.createElement(settings_button_default, { + configWrapper + })] }; switch (library) { case 300: - return /* @__PURE__ */ import_react19.default.createElement(page_header_default, __spreadValues({ - title: `Library Analysis` - }, props), /* @__PURE__ */ import_react19.default.createElement(status_default, { + return /* @__PURE__ */ import_react26.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react26.default.createElement(status_default, { icon: "error", heading: "No Playlists In Your Library", subheading: "Try adding some playlists first" })); case 200: - return /* @__PURE__ */ import_react19.default.createElement(page_header_default, __spreadValues({ - title: `Library Analysis` - }, props), /* @__PURE__ */ import_react19.default.createElement(status_default, { + return /* @__PURE__ */ import_react26.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react26.default.createElement(status_default, { icon: "error", heading: "Failed to Fetch Stats", subheading: "Make an issue on Github" })); case 100: - return /* @__PURE__ */ import_react19.default.createElement(page_header_default, __spreadValues({ - title: `Library Analysis` - }, props), /* @__PURE__ */ import_react19.default.createElement(status_default, { + return /* @__PURE__ */ import_react26.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react26.default.createElement(status_default, { icon: "library", heading: "Analysing your Library", subheading: "This may take a while" })); } - const parseVal = (obj) => { - switch (obj[0]) { - case "tempo": - return Math.round(obj[1]) + "bpm"; - case "popularity": - return Math.round(obj[1]) + "%"; - default: - return Math.round(obj[1] * 100) + "%"; - } - }; - const statCards = []; - Object.entries(library.audioFeatures).forEach((obj) => { - statCards.push(/* @__PURE__ */ import_react19.default.createElement(stat_card_default, { - stat: obj[0][0].toUpperCase() + obj[0].slice(1), - value: parseVal(obj) - })); - }); - const artistCards = library.artists.slice(0, 10).map((artist) => /* @__PURE__ */ import_react19.default.createElement(artist_card_default, { - name: artist.name, - image: artist.image, - uri: artist.uri, - subtext: `Appears in ${artist.freq} tracks` - })); - const albumCards = library.albums.map((album) => { - return /* @__PURE__ */ import_react19.default.createElement(artist_card_default, { - name: album.name, - image: album.image, - uri: album.uri, - subtext: `Appears in ${album.freq} tracks` + const statCards = Object.entries(library.audioFeatures).map(([key, value]) => { + return /* @__PURE__ */ import_react26.default.createElement(stat_card_default, { + label: key, + value }); }); - return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement(page_header_default, __spreadValues({ - title: "Library Analysis" - }, props), /* @__PURE__ */ import_react19.default.createElement("section", { + const artistCards = library.artists.slice(0, 10).map((artist) => { + return /* @__PURE__ */ import_react26.default.createElement(spotify_card_default, { + type: "artist", + uri: artist.uri, + header: artist.name, + subheader: `Appears in ${artist.freq} tracks`, + imageUrl: artist.image + }); + }); + const albumCards = library.albums.map((album) => { + return /* @__PURE__ */ import_react26.default.createElement(spotify_card_default, { + type: "album", + uri: album.uri, + header: album.name, + subheader: `Appears in ${album.freq} tracks`, + imageUrl: album.image + }); + }); + return /* @__PURE__ */ import_react26.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react26.default.createElement("section", { className: "stats-libraryOverview" - }, /* @__PURE__ */ import_react19.default.createElement(stat_card_default, { - stat: "Total Playlists", - value: library.playlistCount - }), /* @__PURE__ */ import_react19.default.createElement(stat_card_default, { - stat: "Total Tracks", - value: library.trackCount - }), /* @__PURE__ */ import_react19.default.createElement(stat_card_default, { - stat: "Total Artists", - value: library.artistCount - }), /* @__PURE__ */ import_react19.default.createElement(stat_card_default, { - stat: "Total Minutes", - value: Math.floor(library.totalDuration / 60) - }), /* @__PURE__ */ import_react19.default.createElement(stat_card_default, { - stat: "Total Hours", + }, /* @__PURE__ */ import_react26.default.createElement(stat_card_default, { + label: "Total Playlists", + value: library.playlistCount.toString() + }), /* @__PURE__ */ import_react26.default.createElement(stat_card_default, { + label: "Total Tracks", + value: library.trackCount.toString() + }), /* @__PURE__ */ import_react26.default.createElement(stat_card_default, { + label: "Total Artists", + value: library.artistCount.toString() + }), /* @__PURE__ */ import_react26.default.createElement(stat_card_default, { + label: "Total Minutes", + value: Math.floor(library.totalDuration / 60).toString() + }), /* @__PURE__ */ import_react26.default.createElement(stat_card_default, { + label: "Total Hours", value: (library.totalDuration / (60 * 60)).toFixed(1) - })), /* @__PURE__ */ import_react19.default.createElement("section", { - className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react19.default.createElement("h2", { - className: "TypeElement-canon-textBase-type main-shelf-title" - }, "Most Frequent Genres")))), /* @__PURE__ */ import_react19.default.createElement(genres_card_default, { + })), /* @__PURE__ */ import_react26.default.createElement(shelf_default, { + title: "Most Frequent Genres" + }, /* @__PURE__ */ import_react26.default.createElement(genres_card_default, { genres: library.genres, total: library.genresDenominator - }), /* @__PURE__ */ import_react19.default.createElement(inline_grid_default, { + }), /* @__PURE__ */ import_react26.default.createElement(inline_grid_default, { special: true - }, statCards)), /* @__PURE__ */ import_react19.default.createElement("section", { - className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react19.default.createElement("h2", { - className: "TypeElement-canon-textBase-type main-shelf-title" - }, "Most Frequent Artists")))), /* @__PURE__ */ import_react19.default.createElement(inline_grid_default, null, artistCards)), /* @__PURE__ */ import_react19.default.createElement("section", { - className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react19.default.createElement("h2", { - className: "TypeElement-canon-textBase-type main-shelf-title" - }, "Most Frequent Albums")))), /* @__PURE__ */ import_react19.default.createElement(inline_grid_default, null, albumCards)), /* @__PURE__ */ import_react19.default.createElement("section", { - className: "main-shelf-shelf Shelf" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-header" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-topRow" - }, /* @__PURE__ */ import_react19.default.createElement("div", { - className: "main-shelf-titleWrapper" - }, /* @__PURE__ */ import_react19.default.createElement("h2", { - className: "Type__TypeElement-sc-goli3j-0 TypeElement-canon-textBase-type main-shelf-title" - }, "Release Year Distribution")))), /* @__PURE__ */ import_react19.default.createElement("section", null, /* @__PURE__ */ import_react19.default.createElement(genres_card_default, { + }, statCards)), /* @__PURE__ */ import_react26.default.createElement(shelf_default, { + title: "Most Frequent Artists" + }, /* @__PURE__ */ import_react26.default.createElement(inline_grid_default, null, artistCards)), /* @__PURE__ */ import_react26.default.createElement(shelf_default, { + title: "Most Frequent Albums" + }, /* @__PURE__ */ import_react26.default.createElement(inline_grid_default, null, albumCards)), /* @__PURE__ */ import_react26.default.createElement(shelf_default, { + title: "Release Year Distribution" + }, /* @__PURE__ */ import_react26.default.createElement(genres_card_default, { genres: library.years, total: library.yearsDenominator - }))))); + }))); }; - var library_default = import_react19.default.memo(LibraryPage); + var library_default = import_react26.default.memo(LibraryPage); // src/pages/charts.tsx - var import_react20 = __toESM(require_react()); - var ChartsPage = ({ config }) => { - var _a; - const [chartData, setChartData] = import_react20.default.useState(100); - const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default(["artists", "tracks"], ["Top Artists", "Top Tracks"], "charts"); + var import_react27 = __toESM(require_react()); + var DropdownOptions5 = [ + { id: "artists", name: "Top Artists" }, + { id: "tracks", name: "Top Tracks" } + ]; + var ChartsPage = ({ configWrapper }) => { + const [chartData, setChartData] = import_react27.default.useState(100); + const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default(DropdownOptions5, "stats:charts"); async function fetchChartData(type, force, set = true) { if (!force) { let storedData = Spicetify.LocalStorage.get(`stats:charts:${type}`); - if (storedData) { - setChartData(JSON.parse(storedData)); - return; - } - } - const api_key = config.CONFIG["api-key"]; - if (!api_key) { - setChartData(200); - return; - } - const response = await apiRequest("charts", `http://ws.audioscrobbler.com/2.0/?method=chart.gettop${type}&api_key=${api_key}&format=json`); - if (!response) { - setChartData(500); - return; + if (storedData) + return setChartData(JSON.parse(storedData)); } + const api_key = configWrapper.config["api-key"]; + if (!api_key) + return setChartData(200); + const response = await apiRequest("charts", LASTFM.charts(api_key, type)); + if (!response) + return setChartData(500); const data = response[type].track || response[type].artist; - const cardData = await convertToSpotify(data, type); + const cardData = await (type == "artists" ? convertArtistData(data) : convertTrackData(data)); if (type === "tracks") { - const fetchedLikedArray = await checkLiked(cardData.map((track) => track.id)); - if (!fetchedLikedArray) { - setChartData(200); - return; - } + const likedArray = await checkLiked(cardData.map((track) => track.id)); + if (!likedArray) + return setChartData(200); cardData.forEach((track, index) => { - track.liked = fetchedLikedArray[index]; + track.liked = likedArray[index]; }); } if (set) setChartData(cardData); Spicetify.LocalStorage.set(`stats:charts:${type}`, JSON.stringify(cardData)); } - import_react20.default.useEffect(() => { - updatePageCache(4, fetchChartData, activeOption, "charts"); + import_react27.default.useEffect(() => { + updatePageCache(4, fetchChartData, activeOption.id, "charts"); }, []); - import_react20.default.useEffect(() => { - fetchChartData(activeOption); + import_react27.default.useEffect(() => { + fetchChartData(activeOption.id); }, [activeOption]); + const refresh = () => { + fetchChartData(activeOption.id, true); + }; const props = { - callback: () => fetchChartData(activeOption, true), - config, - dropdown + title: "Top Albums", + headerEls: [dropdown, /* @__PURE__ */ import_react27.default.createElement(refresh_button_default, { + callback: refresh + }), /* @__PURE__ */ import_react27.default.createElement(settings_button_default, { + configWrapper + })] }; switch (chartData) { case 200: - return /* @__PURE__ */ import_react20.default.createElement(page_header_default, __spreadValues({ - title: `Charts - Top ${activeOption.charAt(0).toUpperCase()}${activeOption.slice(1)}` - }, props), /* @__PURE__ */ import_react20.default.createElement(status_default, { + return /* @__PURE__ */ import_react27.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react27.default.createElement(status_default, { icon: "error", heading: "No API Key", subheading: "Please enter your Last.fm API key in the settings menu." })); case 500: - return /* @__PURE__ */ import_react20.default.createElement(page_header_default, __spreadValues({ - title: `Charts - Top ${activeOption.charAt(0).toUpperCase()}${activeOption.slice(1)}` - }, props), /* @__PURE__ */ import_react20.default.createElement(status_default, { + return /* @__PURE__ */ import_react27.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react27.default.createElement(status_default, { icon: "error", heading: "Error", subheading: "An error occurred while fetching the data." })); case 100: - return /* @__PURE__ */ import_react20.default.createElement(page_header_default, __spreadValues({ - title: `Charts - Top ${activeOption.charAt(0).toUpperCase()}${activeOption.slice(1)}` - }, props), /* @__PURE__ */ import_react20.default.createElement(status_default, { + return /* @__PURE__ */ import_react27.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react27.default.createElement(status_default, { icon: "library", heading: "Loading", subheading: "Fetching data from Last.fm..." })); } - if (!((_a = chartData[0]) == null ? void 0 : _a.album)) { - const artistCards = chartData.map((artist, index) => /* @__PURE__ */ import_react20.default.createElement(artist_card_default, { - key: artist.id, - name: artist.name, - image: artist.image, - uri: artist.uri, - subtext: `#${index + 1} Artist` - })); - return /* @__PURE__ */ import_react20.default.createElement(page_header_default, __spreadValues({ - title: "Charts - Top Artists" - }, props), /* @__PURE__ */ import_react20.default.createElement("div", { - className: `main-gridContainer-gridContainer stats-grid` + if (!chartData[0]?.album) { + const artistCards = chartData.map((artist, index) => { + const type = artist.uri.startsWith("https") ? "lastfm" : "artist"; + return /* @__PURE__ */ import_react27.default.createElement(spotify_card_default, { + type, + uri: artist.uri, + header: artist.name, + subheader: `#${index + 1} Artist`, + imageUrl: artist.image + }); + }); + props.title = `Charts - Top Artists`; + return /* @__PURE__ */ import_react27.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react27.default.createElement("div", { + className: `main-gridContainer-gridContainer grid` }, artistCards)); } else { - const createPlaylist = async () => { - const date = new Date(); - const day = date.getDate(); - const month = date.getMonth() + 1; - const year = date.getFullYear(); - const shortDate = `${year}/${month < 10 ? `0${month}` : month}/${day < 10 ? `0${day}` : day}`; - await Spicetify.CosmosAsync.post("sp://core-playlist/v1/rootlist", { - operation: "create", - name: `Charts - Top Tracks - ${shortDate}`, - playlist: true, - public: false, - uris: chartData.map((track) => track.uri) - }).catch(() => Spicetify.Snackbar.enqueueSnackbar("The playlist could not be created.")); + const date = new Date().toLocaleDateString("en-US", { + year: "numeric", + month: "2-digit", + day: "2-digit" + }); + const infoToCreatePlaylist = { + playlistName: `Charts - Top Tracks - ${date}`, + itemsUris: chartData.map((track) => track.uri) }; - props.createPlaylist = createPlaylist; - let tracksData = chartData; - const trackRows = chartData.map((track, index) => /* @__PURE__ */ import_react20.default.createElement(track_row_default, __spreadProps(__spreadValues({ - index: index + 1 - }, track), { + const trackRows = chartData.map((track, index) => /* @__PURE__ */ import_react27.default.createElement(track_row_default, { + index: index + 1, + ...track, uris: chartData.map((track2) => track2.uri) - }))); - return /* @__PURE__ */ import_react20.default.createElement(page_header_default, __spreadValues({ - title: "Charts - Top Tracks" - }, props), /* @__PURE__ */ import_react20.default.createElement(tracklist_default, null, trackRows)); + })); + props.title = `Charts - Top Tracks`; + return /* @__PURE__ */ import_react27.default.createElement(page_container_default, { + ...props, + infoToCreatePlaylist + }, /* @__PURE__ */ import_react27.default.createElement(tracklist_default, null, trackRows)); } }; - var charts_default = ChartsPage; + var charts_default = import_react27.default.memo(ChartsPage); // src/pages/top_albums.tsx - var import_react21 = __toESM(require_react()); - var topAlbumsReq = async (time_range, config) => { - if (!config.CONFIG["api-key"] || !config.CONFIG["lastfm-user"]) { + var import_react28 = __toESM(require_react()); + var topAlbumsReq = async (time_range, configWrapper) => { + const { config } = configWrapper; + if (!config["api-key"] || !config["lastfm-user"]) return 300; - } - const lastfmperiods = { - short_term: "1month", - medium_term: "6month", - long_term: "overall" - }; - const response = await apiRequest( - "lastfm", - `https://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user=${config.CONFIG["lastfm-user"]}&api_key=${config.CONFIG["api-key"]}&format=json&period=${lastfmperiods[time_range]}` - ); - if (!response) { + const { ["lastfm-user"]: user, ["api-key"]: key } = config; + const response = await apiRequest("lastfm", LASTFM.topalbums(user, key, time_range)); + if (!response) return 200; - } - return await convertToSpotify(response.topalbums.album, "albums"); + return await convertAlbumData(response.topalbums.album); }; - var AlbumsPage = ({ config }) => { - const [topAlbums, setTopAlbums] = import_react21.default.useState(100); - const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default( - ["short_term", "medium_term", "long_term"], - ["Past Month", "Past 6 Months", "All Time"], - `top-albums` - ); + var DropdownOptions6 = [ + { id: "short_term", name: "Past Month" }, + { id: "medium_term", name: "Past 6 Months" }, + { id: "long_term", name: "All Time" } + ]; + var AlbumsPage = ({ configWrapper }) => { + const { LocalStorage } = Spicetify; + const [topAlbums, setTopAlbums] = import_react28.default.useState(100); + const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions6, "stats:top-albums"); const fetchTopAlbums2 = async (time_range, force, set = true) => { if (!force) { - let storedData = Spicetify.LocalStorage.get(`stats:top-albums:${time_range}`); - if (storedData) { - setTopAlbums(JSON.parse(storedData)); - return; - } + let storedData = LocalStorage.get(`stats:top-albums:${time_range}`); + if (storedData) + return setTopAlbums(JSON.parse(storedData)); } const start = window.performance.now(); - const topAlbums2 = await topAlbumsReq(time_range, config); + const topAlbums2 = await topAlbumsReq(time_range, configWrapper); if (set) setTopAlbums(topAlbums2); - Spicetify.LocalStorage.set(`stats:top-albums:${time_range}`, JSON.stringify(topAlbums2)); + LocalStorage.set(`stats:top-albums:${time_range}`, JSON.stringify(topAlbums2)); console.log("total albums fetch time:", window.performance.now() - start); }; - import_react21.default.useEffect(() => { - updatePageCache(5, fetchTopAlbums2, activeOption); + import_react28.default.useEffect(() => { + updatePageCache(5, fetchTopAlbums2, activeOption.id); }, []); - import_react21.default.useEffect(() => { - fetchTopAlbums2(activeOption); + import_react28.default.useEffect(() => { + fetchTopAlbums2(activeOption.id); }, [activeOption]); + const refresh = () => { + fetchTopAlbums2(activeOption.id, true); + }; const props = { - callback: () => fetchTopAlbums2(activeOption, true), - config, - dropdown + title: "Top Albums", + headerEls: [dropdown, /* @__PURE__ */ import_react28.default.createElement(refresh_button_default, { + callback: refresh + }), /* @__PURE__ */ import_react28.default.createElement(settings_button_default, { + configWrapper + })] }; switch (topAlbums) { case 300: - return /* @__PURE__ */ import_react21.default.createElement(page_header_default, __spreadValues({ - title: `Top Albums` - }, props), /* @__PURE__ */ import_react21.default.createElement(status_default, { + return /* @__PURE__ */ import_react28.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react28.default.createElement(status_default, { icon: "error", heading: "No API Key or Username", subheading: "Please enter these in the settings menu" })); case 200: - return /* @__PURE__ */ import_react21.default.createElement(page_header_default, __spreadValues({ - title: `Top Albums` - }, props), /* @__PURE__ */ import_react21.default.createElement(status_default, { + return /* @__PURE__ */ import_react28.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react28.default.createElement(status_default, { icon: "error", heading: "Failed to Fetch Top Artists", subheading: "An error occurred while fetching the data" })); case 100: - return /* @__PURE__ */ import_react21.default.createElement(page_header_default, __spreadValues({ - title: `Top Albums` - }, props), /* @__PURE__ */ import_react21.default.createElement(status_default, { + return /* @__PURE__ */ import_react28.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react28.default.createElement(status_default, { icon: "library", heading: "Loading", subheading: "Fetching data..." })); } - const albumCards = topAlbums.map((album, index) => /* @__PURE__ */ import_react21.default.createElement(artist_card_default, { - key: album.id, - name: album.name, - image: album.image, - uri: album.uri, - subtext: `#${index + 1} Album` - })); - return /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement(page_header_default, __spreadValues({ - title: "Top Albums" - }, props), /* @__PURE__ */ import_react21.default.createElement("div", { - className: `main-gridContainer-gridContainer stats-grid` - }, albumCards))); + const albumCards = topAlbums.map((album, index) => { + const type = album.uri.startsWith("https") ? "lastfm" : "album"; + return /* @__PURE__ */ import_react28.default.createElement(spotify_card_default, { + type, + uri: album.uri, + header: album.name, + subheader: `#${index + 1} Album`, + imageUrl: album.image + }); + }); + return /* @__PURE__ */ import_react28.default.createElement(page_container_default, { + ...props + }, /* @__PURE__ */ import_react28.default.createElement("div", { + className: `main-gridContainer-gridContainer grid` + }, albumCards)); }; - var top_albums_default = import_react21.default.memo(AlbumsPage); + var top_albums_default = import_react28.default.memo(AlbumsPage); // package.json - var version = "0.3.0"; - - // src/constants.ts - var STATS_VERSION = version; - var LATEST_RELEASE = "https://api.github.com/repos/harbassan/spicetify-stats/releases"; - - // src/components/hooks/useConfig.tsx - var import_react23 = __toESM(require_react()); - - // src/components/settings_modal.tsx - var import_react22 = __toESM(require_react()); - var Toggle = (props) => { - const toggleId = `toggle:${props.storageKey}`; - return /* @__PURE__ */ import_react22.default.createElement("label", { - className: "toggle-wrapper" - }, /* @__PURE__ */ import_react22.default.createElement("input", { - className: "toggle-input", - type: "checkbox", - checked: props.enabled, - "data-storage-key": props.storageKey, - id: toggleId, - title: `Toggle for ${props.storageKey}`, - onChange: props.onChange - }), /* @__PURE__ */ import_react22.default.createElement("span", { - className: "toggle-indicator-wrapper" - }, /* @__PURE__ */ import_react22.default.createElement("span", { - className: "toggle-indicator" - }))); - }; - var TextInput = (props) => { - const textId = `text-input:${props.storageKey}`; - return /* @__PURE__ */ import_react22.default.createElement("label", { - className: "text-input-wrapper" - }, /* @__PURE__ */ import_react22.default.createElement("input", { - className: "text-input", - type: "text", - value: props.value || "", - "data-storage-key": props.storageKey, - placeholder: props.placeholder, - id: textId, - title: `Text input for ${props.storageKey}`, - onChange: props.onChange - })); - }; - var Dropdown = (props) => { - const dropdownId = `dropdown:${props.storageKey}`; - return /* @__PURE__ */ import_react22.default.createElement("label", { - className: "dropdown-wrapper" - }, /* @__PURE__ */ import_react22.default.createElement("select", { - className: "dropdown-input", - value: props.value, - "data-storage-key": props.storageKey, - id: dropdownId, - title: `Dropdown for ${props.storageKey}`, - onChange: props.onChange - }, props.options.map((option, index) => /* @__PURE__ */ import_react22.default.createElement("option", { - key: index, - value: option - }, option)))); - }; - var TooltipIcon = () => { - return /* @__PURE__ */ import_react22.default.createElement("svg", { - role: "img", - height: "16", - width: "16", - className: "Svg-sc-ytk21e-0 uPxdw nW1RKQOkzcJcX6aDCZB4", - viewBox: "0 0 16 16" - }, /* @__PURE__ */ import_react22.default.createElement("path", { - d: "M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z" - }), /* @__PURE__ */ import_react22.default.createElement("path", { - d: "M7.25 12.026v-1.5h1.5v1.5h-1.5zm.884-7.096A1.125 1.125 0 007.06 6.39l-1.431.448a2.625 2.625 0 115.13-.784c0 .54-.156 1.015-.503 1.488-.3.408-.7.652-.973.818l-.112.068c-.185.116-.26.203-.302.283-.046.087-.097.245-.097.57h-1.5c0-.47.072-.898.274-1.277.206-.385.507-.645.827-.846l.147-.092c.285-.177.413-.257.526-.41.169-.23.213-.397.213-.602 0-.622-.503-1.125-1.125-1.125z" - })); - }; - var ConfigRow = (props) => { - const enabled = !!props.modalConfig[props.storageKey]; - const value = props.modalConfig[props.storageKey]; - const updateItem = (storageKey, state) => { - props.modalConfig[storageKey] = state; - console.debug(`toggling ${storageKey} to ${state}`); - localStorage.setItem(`stats:config:${storageKey}`, String(state)); - props.updateConfig(props.modalConfig); - }; - const settingsToggleChange = (e) => { - updateItem(e.target.dataset.storageKey, e.target.checked); - }; - const settingsTextChange = (e) => { - updateItem(e.target.dataset.storageKey, e.target.value); - }; - const settingsDropdownChange = (e) => { - updateItem(e.target.dataset.storageKey, e.target.value); - }; - const element = () => { - switch (props.type) { - case "dropdown": - return /* @__PURE__ */ import_react22.default.createElement(Dropdown, { - name: props.name, - storageKey: props.storageKey, - value, - options: props.options || [], - onChange: settingsDropdownChange - }); - case "text": - return /* @__PURE__ */ import_react22.default.createElement(TextInput, { - name: props.name, - storageKey: props.storageKey, - value, - placeholder: props.placeholder, - onChange: settingsTextChange - }); - default: - return /* @__PURE__ */ import_react22.default.createElement(Toggle, { - name: props.name, - storageKey: props.storageKey, - enabled, - onChange: settingsToggleChange - }); - } - }; - return /* @__PURE__ */ import_react22.default.createElement("div", { - className: "setting-row" - }, /* @__PURE__ */ import_react22.default.createElement("label", { - className: "col description" - }, props.name, props.desc && /* @__PURE__ */ import_react22.default.createElement(Spicetify.ReactComponent.TooltipWrapper, { - label: /* @__PURE__ */ import_react22.default.createElement("div", { - dangerouslySetInnerHTML: { __html: props.desc } - }), - renderInline: true, - showDelay: 10, - placement: "top", - labelClassName: "tooltip", - disabled: false - }, /* @__PURE__ */ import_react22.default.createElement("div", { - className: "tooltip-icon" - }, /* @__PURE__ */ import_react22.default.createElement(TooltipIcon, null)))), /* @__PURE__ */ import_react22.default.createElement("div", { - className: "col action" - }, element())); - }; - var SettingsModal = ({ CONFIG, settings, updateAppConfig }) => { - const [modalConfig, setModalConfig] = import_react22.default.useState(__spreadValues({}, CONFIG)); - const updateConfig = (CONFIG2) => { - updateAppConfig(__spreadValues({}, CONFIG2)); - setModalConfig(__spreadValues({}, CONFIG2)); - }; - const configRows = settings.map((setting, index) => { - if (setting.sectionHeader) { - return /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, index != 0 ? /* @__PURE__ */ import_react22.default.createElement("br", null) : /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null), /* @__PURE__ */ import_react22.default.createElement("h2", { - className: "section-header" - }, setting.sectionHeader), /* @__PURE__ */ import_react22.default.createElement(ConfigRow, { - name: setting.name, - storageKey: setting.key, - type: setting.type, - options: setting.options, - placeholder: setting.placeholder, - desc: setting.desc, - modalConfig, - updateConfig - })); - } - return /* @__PURE__ */ import_react22.default.createElement(ConfigRow, { - name: setting.name, - storageKey: setting.key, - type: setting.type, - options: setting.options, - placeholder: setting.placeholder, - desc: setting.desc, - modalConfig, - updateConfig - }); - }); - return /* @__PURE__ */ import_react22.default.createElement("div", { - id: "stats-config-container" - }, configRows); - }; - var settings_modal_default = SettingsModal; - - // src/components/hooks/useConfig.tsx - var getLocalStorageDataFromKey = (key, fallback) => { - const data = localStorage.getItem(key); - if (data) { - try { - return JSON.parse(data); - } catch (err) { - return data; - } - } else { - return fallback; - } - }; - var useConfig = (settings) => { - const settingsArray = settings.map((setting) => { - return { [setting.key]: getLocalStorageDataFromKey(`stats:config:${setting.key}`, setting.def) }; - }); - const [CONFIG, setCONFIG] = import_react23.default.useState(Object.assign({}, ...settingsArray)); - const updateConfig = (config) => { - setCONFIG(__spreadValues({}, config)); - console.log("updated config", config); - }; - const launchModal = () => { - Spicetify.PopupModal.display({ - title: "Statistics Settings", - content: /* @__PURE__ */ import_react23.default.createElement(settings_modal_default, { - CONFIG, - settings, - updateAppConfig: updateConfig - }), - isLarge: true - }); - }; - return { CONFIG, launchModal }; - }; - var useConfig_default = useConfig; + var version = "0.3.3"; // src/app.tsx - var pages = { - ["Artists"]: /* @__PURE__ */ import_react24.default.createElement(top_artists_default, null), - ["Tracks"]: /* @__PURE__ */ import_react24.default.createElement(top_tracks_default, null), - ["Albums"]: /* @__PURE__ */ import_react24.default.createElement(top_albums_default, null), - ["Genres"]: /* @__PURE__ */ import_react24.default.createElement(top_genres_default, null), - ["Library"]: /* @__PURE__ */ import_react24.default.createElement(library_default, null), - ["Charts"]: /* @__PURE__ */ import_react24.default.createElement(charts_default, null) - }; var checkForUpdates = (setNewUpdate) => { - fetch(LATEST_RELEASE).then((res) => res.json()).then( + fetch("https://api.github.com/repos/harbassan/spicetify-apps/releases").then((res) => res.json()).then( (result) => { - try { - setNewUpdate(result[0].name.slice(1) !== STATS_VERSION); - } catch (err) { - console.log(err); - } + const releases = result.filter((release) => release.name.startsWith("stats")); + setNewUpdate(releases[0].name.slice(7) !== version); }, (error) => { console.log("Failed to check for updates", error); @@ -2445,65 +2419,66 @@ var stats = (() => { ); }; var App = () => { - const config = useConfig_default([ - { - name: "Last.fm Api Key", - key: "api-key", - type: "text", - def: null, - placeholder: "Enter API Key", - desc: `You can get this by visiting www.last.fm/api/account/create and simply entering any name.
You'll need to make an account first, which is a plus.`, - sectionHeader: "Last.fm Integration" - }, - { - name: "Last.fm Username", - key: "lastfm-user", - type: "text", - def: null, - placeholder: "Enter Username" - }, - { - name: "Use Last.fm for Stats", - key: "use-lastfm", - type: "toggle", - def: false, - desc: `Last.fm charts your stats purely based on the streaming count, whereas Spotify factors in other variables` - }, - { name: "Artists Page", key: "show-artists", type: "toggle", def: true, sectionHeader: "Pages" }, - { name: "Tracks Page", key: "show-tracks", type: "toggle", def: true }, - { name: "Albums Page", key: "show-albums", type: "toggle", def: false, desc: `Requires Last.fm API key and username` }, - { name: "Genres Page", key: "show-genres", type: "toggle", def: true }, - { name: "Library Page", key: "show-library", type: "toggle", def: true }, - { name: "Charts Page", key: "show-charts", type: "toggle", def: true, desc: `Requires Last.fm API key` } - ]); - const tabPages = ["Artists", "Tracks", "Albums", "Genres", "Library", "Charts"].filter((page) => config.CONFIG[`show-${page.toLowerCase()}`]); + const [config, setConfig] = import_react29.default.useState({ ...SpicetifyStats.ConfigWrapper.Config }); + const launchModal = () => { + SpicetifyStats.ConfigWrapper.launchModal(setConfig); + }; + const configWrapper = { + config, + launchModal + }; + const pages = { + ["Artists"]: /* @__PURE__ */ import_react29.default.createElement(top_artists_default, { + configWrapper + }), + ["Tracks"]: /* @__PURE__ */ import_react29.default.createElement(top_tracks_default, { + configWrapper + }), + ["Albums"]: /* @__PURE__ */ import_react29.default.createElement(top_albums_default, { + configWrapper + }), + ["Genres"]: /* @__PURE__ */ import_react29.default.createElement(top_genres_default, { + configWrapper + }), + ["Library"]: /* @__PURE__ */ import_react29.default.createElement(library_default, { + configWrapper + }), + ["Charts"]: /* @__PURE__ */ import_react29.default.createElement(charts_default, { + configWrapper + }) + }; + const tabPages = ["Artists", "Tracks", "Albums", "Genres", "Library", "Charts"].filter( + (page) => configWrapper.config[`show-${page.toLowerCase()}`] + ); const [navBar, activeLink, setActiveLink] = useNavigationBar_default(tabPages); - const [hasPageSwitched, setHasPageSwitched] = import_react24.default.useState(false); - const [newUpdate, setNewUpdate] = import_react24.default.useState(false); - import_react24.default.useEffect(() => { + const [hasPageSwitched, setHasPageSwitched] = import_react29.default.useState(false); + const [newUpdate, setNewUpdate] = import_react29.default.useState(false); + import_react29.default.useEffect(() => { setActiveLink(Spicetify.LocalStorage.get("stats:active-link") || "Artists"); checkForUpdates(setNewUpdate); setHasPageSwitched(true); }, []); - import_react24.default.useEffect(() => { + import_react29.default.useEffect(() => { Spicetify.LocalStorage.set("stats:active-link", activeLink); }, [activeLink]); if (!hasPageSwitched) { - return /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null); + return /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null); } - return /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, newUpdate && /* @__PURE__ */ import_react24.default.createElement("div", { + return /* @__PURE__ */ import_react29.default.createElement("div", { + id: "stats-app" + }, navBar, newUpdate && /* @__PURE__ */ import_react29.default.createElement("div", { className: "new-update" - }, "New app update available! Visit ", /* @__PURE__ */ import_react24.default.createElement("a", { - href: "https://github.com/harbassan/spicetify-stats/releases" - }, "harbassan/spicetify-stats"), " to install."), navBar, import_react24.default.cloneElement(pages[activeLink], { config })); + }, "New app update available! Visit", " ", /* @__PURE__ */ import_react29.default.createElement("a", { + href: "https://github.com/harbassan/spicetify-apps/releases" + }, "harbassan/spicetify-apps"), " to install."), pages[activeLink]); }; var app_default = App; - // node_modules/spicetify-creator/dist/temp/index.jsx - var import_react25 = __toESM(require_react()); + // ../../../AppData/Local/Temp/spicetify-creator/index.jsx + var import_react30 = __toESM(require_react()); function render() { - return /* @__PURE__ */ import_react25.default.createElement(app_default, null); + return /* @__PURE__ */ import_react30.default.createElement(app_default, null); } - return __toCommonJS(temp_exports); + return __toCommonJS(spicetify_creator_exports); })(); const render=()=>stats.default(); diff --git a/.config/spicetify/CustomApps/stats/style.css b/.config/spicetify/CustomApps/stats/style.css index 06ea2de8..ba798f30 100644 --- a/.config/spicetify/CustomApps/stats/style.css +++ b/.config/spicetify/CustomApps/stats/style.css @@ -1,17 +1,17 @@ -/* ../../AppData/Local/Temp/tmp-6912-LESOepgMxajG/18ca59b28c22/navBar.module.css */ -.navBar-module__topBarHeaderItem___v29bR_stats { +/* ../../../AppData/Local/Temp/tmp-17120-n3iWRzissBjg/18f3cbbb4bc3/navBar.module.css */ +.navBar-module__topBarHeaderItem___piw4C_stats { -webkit-app-region: no-drag; display: inline-block; pointer-events: auto; } -.navBar-module__topBarHeaderItemLink___VeyBY_stats { +.navBar-module__topBarHeaderItemLink___xA4uv_stats { margin: 0 8px 0 0; } -.navBar-module__topBarActive___-qYPu_stats { +.navBar-module__topBarActive___XhWpm_stats { background-color: var(--spice-tab-active); border-radius: 4px; } -.navBar-module__topBarHeaderItemLink___VeyBY_stats { +.navBar-module__topBarHeaderItemLink___xA4uv_stats { border-radius: 4px; color: var(--spice-text); display: inline-block; @@ -21,12 +21,12 @@ text-decoration: none !important; cursor: pointer; } -.navBar-module__topBarNav___1OtdR_stats { +.navBar-module__topBarNav___qWGeZ_stats { -webkit-app-region: drag; pointer-events: none; width: 100%; } -.navBar-module__topBarHeaderItem___v29bR_stats .navBar-module__optionsMenuDropBox___tD9mA_stats { +.navBar-module__topBarHeaderItem___piw4C_stats .navBar-module__optionsMenuDropBox___pzfNI_stats { color: var(--spice-text); border: 0; max-width: 150px; @@ -38,74 +38,45 @@ -moz-appearance: none; appearance: none; } -.navBar-module__topBarHeaderItem___v29bR_stats .navBar-module__optionsMenuDropBox___tD9mA_stats svg { +.navBar-module__topBarHeaderItem___piw4C_stats .navBar-module__optionsMenuDropBox___pzfNI_stats svg { position: absolute; margin-left: 8px; } -div.navBar-module__topBarHeaderItemLink___VeyBY_stats { +div.navBar-module__topBarHeaderItemLink___xA4uv_stats { padding: 0; } -/* ../../AppData/Local/Temp/tmp-6912-LESOepgMxajG/18ca59b275b0/app.css */ -.stats-grid { - --grid-gap: 24px; - grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)) !important; -} -.stats-refreshButton { - width: 32px; - height: 32px; -} -.collection-searchBar-searchBar { - display: flex; - gap: 8px; -} -.stats-specialGrid { - grid-template-columns: repeat(11, 180px) !important; -} -.stats-gridInline { +/* ../../../AppData/Local/Temp/tmp-17120-n3iWRzissBjg/18f3cbbb33e0/app.css */ +#stats-app .stats-gridInline { --grid-gap: 24px; grid-template-columns: repeat(10, 180px) !important; overflow-x: hidden; scroll-behavior: smooth; margin-top: 5px; } -[data-scroll=both] { +#stats-app [data-scroll=both] { -webkit-mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent); mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent); } -[data-scroll=end] { +#stats-app [data-scroll=end] { -webkit-mask-image: linear-gradient(to right, transparent, black 10%); mask-image: linear-gradient(to right, transparent, black 10%); } -[data-scroll=start] { +#stats-app [data-scroll=start] { -webkit-mask-image: linear-gradient(to right, black 90%, transparent); mask-image: linear-gradient(to right, black 90%, transparent); } -.stats-loadingWrapper { - display: flex; - justify-content: center; - align-items: center; - min-height: 60vh; - flex-direction: column; - gap: 16px; -} -.stats-libraryOverview { - display: flex; - gap: 24px; - align-items: center; - margin-bottom: 16px; -} -.stats-page { - display: flex; - flex-direction: column; - gap: 24px; -} -.stats-trackPageTitle { +#stats-app .stats-libraryOverview { display: flex; gap: 24px; align-items: center; } -.stats-scrollButton { +#stats-app .stats-trackPageTitle { + display: flex; + gap: 24px; + align-items: center; +} +#stats-app .stats-scrollButton { width: 40px; border-radius: 8px; border: none; @@ -114,69 +85,20 @@ div.navBar-module__topBarHeaderItemLink___VeyBY_stats { background-color: var(--spice-player); color: var(--spice-subtext); } -.stats-scrollButton:hover { +#stats-app .stats-scrollButton:hover { background-color: var(--spice-card); -} -.stats-createPlaylistButton { - margin-left: 24px; - box-sizing: border-box; - -webkit-tap-highlight-color: transparent; - font-size: 0.8125rem; - font-weight: 700; - font-family: var(--font-family, CircularSp, CircularSp-Arab, CircularSp-Hebr, CircularSp-Cyrl, CircularSp-Grek, CircularSp-Deva, var(--fallback-fonts, sans-serif)); - background-color: transparent; - border-radius: 500px; - cursor: pointer; - position: relative; - text-align: center; - text-decoration: none; - text-transform: none; - touch-action: manipulation; - transition-duration: 33ms; - transition-property: - background-color, - border-color, - color, - box-shadow, - filter, - transform; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - vertical-align: middle; - transform: translate3d(0px, 0px, 0px); - padding-block: 3px; - padding-inline: 15px; - border: 1px solid var(--essential-subdued, #878787); - color: var(--text-base, #000000); - min-block-size: 32px; - display: inline-flex; - align-items: center; - justify-content: center; -} -.stats-createPlaylistButton:hover { - transform: scale(1.04); - border-color: var(--essential-base, #000000); -} -.stats-header { - -webkit-box-pack: justify; - -ms-flex-pack: justify; - -webkit-box-align: center; - -ms-flex-align: center; - align-content: space-between; - align-items: center; color: var(--spice-text); - display: flex; - justify-content: space-between; - margin: 16px 0; } -.stats-tracklistHeader > div { +#stats-app .stats-tracklistHeader > div { display: flex; -webkit-app-region: no-drag; gap: 20px; align-items: center; } -.stats-genreCard { +#stats-app .stats-make-playlist-button { + margin-inline-start: 12px; +} +#stats-app .stats-genreCard { display: flex; flex-direction: column; gap: 10px; @@ -185,44 +107,36 @@ div.navBar-module__topBarHeaderItemLink___VeyBY_stats { background: var(--spice-player); position: relative; } -.stats-genreRow { +#stats-app .stats-genreRow { width: 100%; height: 20px; display: flex; gap: 10px; } -.stats-genreRowFill { +#stats-app .stats-genreRowFill { background: var(--spice-button); height: 100%; border-radius: 8px; display: flex; align-items: center; } -.stats-genreText { +#stats-app .stats-genreText { color: var(--spice-player); font-size: 0.875rem; margin-left: 7px; font-weight: bold; } -.stats-genreValue { +#stats-app .stats-genreValue { color: var(--spice-text); font-size: 0.875rem; } -.stats-cardValue { - font-size: 2rem; - font-weight: bold; - color: var(--spice-text); +#stats-app .stats-genreCard + .stats-gridInlineSection { + margin-top: 3px; } -.stats-cardText { - color: var(--spice-text); -} -.new-update { - background-color: var(--spice-player); - color: var(--spice-text); - border-radius: 8px; - padding: 2px 12px; - margin: 0 24px; - border: 0px; +#stats-app .main-trackList-rowHeartButton, +#stats-app .main-trackList-rowMoreButton { + background-color: transparent; + border: none; } .GenericModal[aria-label="Playlist Stats"] .main-embedWidgetGenerator-container { width: 80vw; @@ -232,25 +146,14 @@ div.navBar-module__topBarHeaderItemLink___VeyBY_stats { .GenericModal[aria-label="Playlist Stats"] .main-shelf-title { color: var(--spice-text); } -.status-icon { - width: 40px; - height: 40px; - fill: currentColor; -} -/* ../../AppData/Local/Temp/tmp-6912-LESOepgMxajG/18ca59b28921/settings_modal.css */ -#stats-config-container { +/* ../../../AppData/Local/Temp/tmp-17120-n3iWRzissBjg/18f3cbbb48b1/config_modal.css */ +.config-container { gap: 10px; display: flex; flex-direction: column; } -#stats-config-container .toggle-wrapper { - display: inline-flex; - position: relative; - align-items: center; - cursor: pointer; -} -#stats-config-container .section-header { +.config-container .section-header { box-sizing: border-box; -webkit-tap-highlight-color: transparent; margin-block: 0px; @@ -258,7 +161,7 @@ div.navBar-module__topBarHeaderItemLink___VeyBY_stats { font-weight: 700; color: var(--spice-text); } -#stats-config-container .col.description { +.config-container .col.description { box-sizing: border-box; -webkit-tap-highlight-color: transparent; margin-block: 0px; @@ -266,60 +169,11 @@ div.navBar-module__topBarHeaderItemLink___VeyBY_stats { font-weight: 400; color: var(--spice-subtext); } -#stats-config-container .disabled { +.config-container .disabled { opacity: 0; pointer-events: none; } -#stats-config-container .toggle-input { - opacity: 0; - pointer-events: none; - position: absolute; -} -#stats-config-container .toggle-input:checked ~ .toggle-indicator-wrapper { - background-color: var(--spice-text); -} -#stats-config-container .toggle-input:checked ~ .toggle-indicator-wrapper .toggle-indicator { - background-color: #fff; - left: auto; - right: 2px; - right: 3px; -} -#stats-config-container .toggle-input:hover ~ .toggle-indicator-wrapper { - filter: brightness(1.3); -} -#stats-config-container .toggle-input:hover:checked ~ .toggle-indicator-wrapper { - filter: brightness(1.15); -} -#stats-config-container .toggle-input:active:not([disabled]) ~ .toggle-indicator-wrapper .toggle-indicator { - width: 20px; -} -#stats-config-container .toggle-indicator-wrapper { - background-color: #535353; - border-radius: 24px; - height: 24px; - position: relative; - width: 42px; -} -#stats-config-container .toggle-indicator { - background: #fff; - border-radius: inherit; - height: 20px; - left: 2px; - position: absolute; - top: 2px; - transition: - background-color, - left, - right, - width 0.1s ease; - width: 20px; - height: 18px; - width: 18px; - top: 3px; - left: 3px; - background: var(--spice-shadow) !important; -} -#stats-config-container .text-input { +.config-container .text-input { background: rgba(var(--spice-rgb-selected-row), 0.1); border: 1px solid transparent; border-radius: 4px; @@ -330,12 +184,12 @@ div.navBar-module__topBarHeaderItemLink___VeyBY_stats { padding: 0 12px; width: 100%; } -#stats-config-container .text-input:focus { +.config-container .text-input:focus { background-color: var(--spice-tab-active); border: 1px solid var(--spice-button-disabled); outline: none; } -#stats-config-container .dropdown-input { +.config-container .dropdown-input { background-color: var(--spice-tab-active); border: 0; border-radius: 4px; @@ -348,7 +202,7 @@ div.navBar-module__topBarHeaderItemLink___VeyBY_stats { padding: 0 32px 0 12px; width: 100%; } -#stats-config-container .tooltip-icon { +.config-container .tooltip-icon { float: right; margin-left: 10px; display: flex; @@ -356,13 +210,67 @@ div.navBar-module__topBarHeaderItemLink___VeyBY_stats { height: 22px; fill: var(--spice-subtext); } -#stats-config-container .tooltip-icon:hover { +.config-container .tooltip-icon:hover { fill: var(--spice-text); } -#stats-config-container .tooltip { +.config-container .tooltip { text-align: center; } -#stats-config-container .setting-row { +.config-container .setting-row { display: flex; justify-content: space-between; } +.config-container .playback-progressbar { + width: 200px; +} + +/* ../../../AppData/Local/Temp/tmp-17120-n3iWRzissBjg/18f3cbbb49f2/shared.css */ +.grid { + --grid-gap: 24px; + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)) !important; +} +.loadingWrapper { + display: flex; + justify-content: center; + align-items: center; + min-height: 60vh; + flex-direction: column; + gap: 16px; +} +.loadingWrapper .status-icon { + width: 40px; + height: 40px; + fill: currentColor; +} +.page-content { + display: flex; + flex-direction: column; + gap: 24px; +} +.page-header { + align-content: space-between; + align-items: center; + display: flex; + justify-content: space-between; + margin: 16px 0; +} +.page-header .header-right, +.page-header .header-left { + display: flex; + align-items: center; + gap: 8px; +} +.page-header .header-right { + justify-content: flex-end; +} +.page-header .header-left { + justify-content: flex-start; +} +.new-update { + background-color: var(--spice-player); + color: var(--spice-text); + border-radius: 8px; + padding: 2px 12px; + margin: 0 24px; + border: 0px; +} diff --git a/.config/spicetify/Extensions/adblock.js b/.config/spicetify/Extensions/adblock.js deleted file mode 100644 index 6220d04f..00000000 --- a/.config/spicetify/Extensions/adblock.js +++ /dev/null @@ -1,59 +0,0 @@ -//@ts-check - -// NAME: adblock -// AUTHOR: CharlieS1103 -// DESCRIPTION: Block all audio and UI ads on Spotify - -/// - -(function adblock() { - const { Platform} = Spicetify; - if (!(Platform)) { - setTimeout(adblock, 300) - return - } - - var styleSheet = document.createElement("style") - - styleSheet.innerHTML = - ` - .MnW5SczTcbdFHxLZ_Z8j, .WiPggcPDzbwGxoxwLWFf, .ReyA3uE3K7oEz7PTTnAn, .main-leaderboardComponent-container, .sponsor-container, a.link-subtle.main-navBar-navBarLink.GKnnhbExo0U9l7Jz2rdc{ - display: none !important; - } - ` - document.body.appendChild(styleSheet) - delayAds() - var billboard = Spicetify.Platform.AdManagers.billboard.displayBillboard; - Spicetify.Platform.AdManagers.billboard.displayBillboard = function (arguments) { - Spicetify.Platform.AdManagers.billboard.finish() - // hook before call - var ret = billboard.apply(this, arguments); - // hook after call - console.log("Adblock.js: Billboard blocked! Leave a star!") - Spicetify.Platform.AdManagers.billboard.finish() - const observer = new MutationObserver((mutations, obs) => { - const billboardAd = document.getElementById('view-billboard-ad'); - if (billboardAd) { - Spicetify.Platform.AdManagers.billboard.finish() - obs.disconnect(); - return; - } - }); - - observer.observe(document, { - childList: true, - subtree: true - }); - return ret; - }; - function delayAds() { - console.log("Ads delayed: Adblock.js") - Spicetify.Platform.AdManagers.audio.audioApi.cosmosConnector.increaseStreamTime(-100000000000) - Spicetify.Platform.AdManagers.billboard.billboardApi.cosmosConnector.increaseStreamTime(-100000000000) - } - setInterval(delayAds, 720 *10000); - - -})() - - diff --git a/.config/spicetify/Extensions/copyPlaylist.js b/.config/spicetify/Extensions/copyPlaylist.js deleted file mode 100644 index 4616d75a..00000000 --- a/.config/spicetify/Extensions/copyPlaylist.js +++ /dev/null @@ -1,654 +0,0 @@ -// NAME: Copy Playlists -// AUTHOR: einzigartigerName -// DESCRIPTION: copy/combine playlist/queue directly in Spotify - -(function CopyPlaylist() { - - const { CosmosAPI, BridgeAPI, LocalStorage, PlaybackControl, ContextMenu, URI } = Spicetify - if (!(CosmosAPI || BridgeAPI)) { - setTimeout(CopyPlaylist, 1000); - return; - } - - const STORAGE_KEY = "combine_buffer_spicetify" - const TOP_BTN_TOOLTIP = "Combine Playlists" - const MENU_BTN_CREATE_NEW = "Create Playlist" - const MENU_BTN_INSERT_BUFFER = "Copy to Buffer" - - class PlaylistCollection { - constructor() { - const menu = createMenu() - this.container = menu.container - this.items = menu.menu - this.lastScroll = 0 - this.container.onclick = () => { - this.storeScroll() - this.container.remove() - } - this.pattern - this.apply() - } - - apply() { - this.items.textContent = '' // Remove all childs - this.items.append(createMenuItem("Create Playlist", () => highjackCreateDialog(mergePlaylists(this.pattern)))) - this.items.append(createMenuItem("Clear Buffer", () => LIST.clearStorage())) - - const select = createPatternSelect(this.filter); - select.onchange = (event) => { - this.pattern = event.srcElement.selectedIndex; - } - this.items.append(select); - - const collection = this.getStorage(); - collection.forEach((item) => this.items.append(new CardContainer(item))) - } - - getStorage() { - const storageRaw = LocalStorage.get(STORAGE_KEY); - let storage = []; - - if (storageRaw) { - storage = JSON.parse(storageRaw); - } else { - LocalStorage.set(STORAGE_KEY, "[]") - } - - return storage; - } - - addToStorage(data) { - - /** @type {Object[]} */ - const storage = this.getStorage(); - storage.push(data); - - LocalStorage.set(STORAGE_KEY, JSON.stringify(storage)); - this.apply() - } - - removeFromStorage(id) { - const storage = this.getStorage() - .filter(item => item.id !== id) - - LocalStorage.set(STORAGE_KEY, JSON.stringify(storage)); - this.apply() - } - - clearStorage() { - LocalStorage.set(STORAGE_KEY, "[]"); - this.apply() - } - - moveItem(uri, direction) { - var storage = this.getStorage() - - var from; - - for (var i = 0; i < storage.length; i++) { - if (storage[i].uri === uri) { - from = i - break; - } - } - if (!from) { return } - - var to = from + direction - if (to < 0 || to >= storage.length) { return } - - var tmp = storage[from] - storage[from] = storage[to] - storage[to] = tmp - - LocalStorage.set(STORAGE_KEY, JSON.stringify(storage)); - this.apply() - } - - changePosition(x, y) { - this.items.style.left = x + "px" - this.items.style.top = y + 10 + "px" - } - - storeScroll() { - this.lastScroll = this.items.scrollTop - } - - setScroll() { - this.items.scrollTop = this.lastScroll - } - } - - /* - * Displays Stored Playlist - * {id, uri, name, tracks, imgUri, owner} - */ - class CardContainer extends HTMLElement { - constructor(info) { - super() - - this.innerHTML = ` -` - - const up = this.querySelector(".order-controls-up") - up.onclick = (event) => { - LIST.moveItem(info.uri, -1) - event.stopPropagation() - } - - const remove = this.querySelector(".order-controls-remove") - remove.onclick = (event) => { - LIST.removeFromStorage(info.id) - event.stopPropagation() - } - - const down = this.querySelector(".order-controls-down") - down.onclick = (event) => { - LIST.moveItem(info.uri, +1) - event.stopPropagation() - } - - const imageLink = this.querySelector(".card-image-link"); - const infoLink = this.querySelector(".card-info-link"); - - if (imageLink) imageLink.addEventListener("click", ((e) => showPlaylist(e))); - - if (infoLink) infoLink.addEventListener("click", ((e) => showPlaylist(e))); - } - } - - customElements.define("combine-buffer-card-container", CardContainer) - - const LIST = new PlaylistCollection() - - // New Playlist Button - const playlistDialogButton = document.querySelector("#new-playlist-button-mount-point > div > button") - if (!playlistDialogButton) return; - - document.querySelector("#view-browser-navigation-top-bar") - .append(createTopBarButton()) - - createPlaylistContextMenu().register() - - - /************************************************************************** - UI Building - **************************************************************************/ - // If Queue Page add Buttons - const iframeInterval = setInterval(() => { - /** @type {HTMLIFrameElement} */ - const currentIframe = document.querySelector("iframe.active"); - if (!currentIframe || - currentIframe.id !== "app-queue" - ) { - return; - } - - const headers = currentIframe.contentDocument.querySelectorAll( - ".glue-page-header__buttons" - ); - - for (const e of headers) { - e.append(createQueueButton( - "Save as Playlist", - "Save the current Queue as a new Playlist", - () => { - let tracks = getQueueTracks(); - highjackCreateDialog(tracks); - }, - )); - - e.append(createQueueButton( - "Copy into Buffer", - "Insert the current Queue into the Buffer", - () => { queueToBuffer() }, - )); - } - - if (headers.length > 0) clearInterval(iframeInterval); - }, 500) - - // Creates the Main Menu - function createMenu() { - const container = document.createElement("div") - container.id = "combine-playlist-spicetify" - container.className = "context-menu-container" - container.style.zIndex = "1029" - - const style = document.createElement("style") - style.textContent = ` -#combine-menu { - display: inline-block; - width: 33%; - max-height: 70%; - overflow: hidden auto; - padding: 10px -} -.combine-pattern { - margin-top: 7px; -} -.order-controls { - position: absolute; - right: 0; - padding: 0 5px 5px 0; - z-index: 3 -} -.button.button-icon-only::before { - color: var(--modspotify_main_fg); -} -.order-controls-up { - position: relative; - top: 100%; -} -.order-controls-remove { - position: relative; - top: 50%; -} -.order-controls-down { - position: relative; - bottom: 100%; -} -.card-info-subtitle-owner { - color: var(--modspotify_secondary_fg); -} -.card-info-subtitle-tracks { - font-weight: lighter; - color: var(--modspotify_secondary_fg); -} -` - - const menu = document.createElement("ul") - menu.id = "combine-menu" - menu.className = "context-menu" - - container.append(style, menu) - - return { container, menu } - } - - // Creates a Button in the Combine Menu - function createMenuItem(name, callback) { - const item = document.createElement("div"); - item.classList.add("item"); - item.onclick = callback; - item.onmouseover = () => item.classList.add("hover"); - item.onmouseleave = () => item.classList.remove("hover"); - - const text = document.createElement("span"); - text.classList.add("text"); - text.innerText = name; - - item.append(text); - - return item; - } - - // Creates the SubMenu in Playlist Context - function createPlaylistContextMenu() { - var createFromCurrent = new Spicetify.ContextMenu.Item( - MENU_BTN_CREATE_NEW, - (uris) => { - if (uris.length === 1) { - fetchPlaylist(uris[0]) - .then((buffer) => highjackCreateDialog(buffer.tracks)) - .catch((err) => Spicetify.showNotification(`${err}`)); - return; - } else { - Spicetify.showNotification("Unable to find Playlist URI") - } - }, - (_) => true - ) - - var insertIntoBuffer = new Spicetify.ContextMenu.Item( - MENU_BTN_INSERT_BUFFER, - (uris) => { - - if (uris.length === 1) { - fetchPlaylist(uris[0]) - .then((buffer) => {LIST.addToStorage(buffer)}) - .catch((err) => Spicetify.showNotification(`${err}`)); - return; - } - }, - (_) => true - ) - - return new Spicetify.ContextMenu.SubMenu( - "Copy Playlist", - [ createFromCurrent, insertIntoBuffer], - (uris) => { - if (uris.length === 1) { - const uriObj = Spicetify.URI.fromString(uris[0]); - switch (uriObj.type) { - case Spicetify.URI.Type.PLAYLIST: - case Spicetify.URI.Type.PLAYLIST_V2: - return true; - } - return false; - } - // Multiple Items selected. - return false; - } - ) - } - - // Creates the Button to View Merge Buffer - function createTopBarButton() { - const button = document.createElement("button") - button.classList.add("button", "spoticon-copy-16", "merge-button") - button.setAttribute("data-tooltip", TOP_BTN_TOOLTIP) - button.setAttribute("data-contextmenu", "") - button.setAttribute("data-uri", "spotify:special:copy") - button.onclick = () => { - const bound = button.getBoundingClientRect() - LIST.changePosition(bound.left, bound.top) - document.body.append(LIST.container) - LIST.setScroll() - } - return button - } - - // Creates the Dropdown Menu for Merge Pattern - function createPatternSelect(defaultOpt = 0) { - const select = document.createElement("select"); - select.className = "GlueDropdown combine-pattern"; - - const appendOpt = document.createElement("option"); - appendOpt.text = "Append"; - - const shuffleOpt = document.createElement("option"); - shuffleOpt.text = "Shuffle"; - - const alternateOpt = document.createElement("option"); - alternateOpt.text = "Alternate"; - - select.onclick = (ev) => ev.stopPropagation(); - select.append(appendOpt, shuffleOpt, alternateOpt); - select.options[defaultOpt].selected = true; - - return select; - } - - // Queue button - function createQueueButton(name, tooltip, callback) { - const b = document.createElement("button"); - b.classList.add("button", "button-green"); - b.innerText = name; - b.setAttribute("data-tooltip", tooltip); - b.onclick = callback; - return b; - } - - // Highjack Spotifies 'New Playlist' Dialog - function highjackCreateDialog(tracks) { - playlistDialogButton.click() - - var createButton = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__submit-button-container > button") - var buttonContainer = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__submit-button-container") - - var highjackedButton = createButton.cloneNode(true) - highjackedButton.addEventListener("click", () => onCreateNewPlaylist(tracks)) - - window.addEventListener("keypress", (event) => { - if (event.code === `Enter`) { - // Cancel the default action, if needed - event.preventDefault(); - // Trigger the button element with a click - createButton.click(); - } - }); - - createButton.remove() - buttonContainer.insertAdjacentElement("afterbegin", highjackedButton) - } - - - /************************************************************************** - OnCLick Functions - **************************************************************************/ - // Create a new Playlist from Inputs - function onCreateNewPlaylist(tracks) { - var exitButton = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__close-button > button"); - var nameInput = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__content > div.PlaylistAnnotationModal__playlist-name > input") - var descInput = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__content > div.PlaylistAnnotationModal__playlist-description > textarea") - var imageInput = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__content > div.PlaylistAnnotationModal__img-container > div > div.PlaylistAnnotationModal__img-holder > img") - - var name = nameInput.value - if (!name) { - name = nameInput.getAttribute("placeholder") - } - - var desc = descInput.value - - var img; - if (imageInput) { - img = imageInput.getAttribute("src") - } - - createPlaylist(name) - .then(res => addTracks(res.uri, tracks)) - .then((_) => Spicetify.showNotification(`Created Playlist: "${name}"`)) - .catch((err) => Spicetify.showNotification(`${err}`)); - - exitButton.click() - - if (exitButton) { - exitButton.click() - } - } - - // Get All Tracks in Queue and remove delimiter - function getQueueTracks() { - return Spicetify.Queue.next_tracks - .map((t) => t.uri) - .filter((t) => { return t != "spotify:delimiter"; }) - } - - // Copy the Queue to the Combine Buffer - function queueToBuffer() { - let tracks = getQueueTracks(); - - var date = new Date() - var year = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(date); - var month = new Intl.DateTimeFormat('en', { month: 'short' }).format(date); - var day = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date); - - const timeOptions = { hour: 'numeric', minute: 'numeric', hour12: false}; - var time = new Intl.DateTimeFormat(`en`, timeOptions).format(date); - - let queue = { - id: `spotify:queue-${date}`, - uri: `spotify:queue`, - name: "Queue", - imgUri: undefined, - tracks: tracks, - owner: `${time} - ${day} ${month} ${year}`, - } - - LIST.addToStorage(queue); - } - - // Show the clicked Playlist - async function showPlaylist(event) { - console.log(event) - } - - - /************************************************************************** - Merge Playlists - **************************************************************************/ - // Merge all Playlists - function mergePlaylists(pattern) { - var tracks = LIST.getStorage().map((pl) => pl.tracks) - - switch (pattern) { - case 1: return shuffle(tracks); - case 2: return alternate(tracks); - default: return append(tracks); - } - } - - // Alternate Playlists - function alternate(arrays) { - var combined = [] - - while (arrays.length != 0) { - var current = arrays.shift() - if (current.length != 0) { - combined.push(current.shift()) - - if (current.length != 0) { - arrays.push(current) - } - } - } - - return combined - } - - // Shuffle all tracks using the Durstenfeld Shuffle - function shuffle(arrays) { - var combined = append(arrays) - - for (var i = combined.length - 1; i > 0; i--) { - var j = Math.floor(Math.random() * (i + 1)); - var temp = combined[i]; - combined[i] = combined[j]; - combined[j] = temp; - } - - return combined; - } - - // Simply Concat all Playlist - function append(arrays) { - var combined = [] - arrays.forEach((arr) => combined = combined.concat(arr)) - - return combined; - } - - /************************************************************************** - Calls to the CosmosAPI - **************************************************************************/ - // Fetch all Track from Playlist URI - async function fetchPlaylist(uri) { - return await new Promise((resolve, reject) => { - Spicetify.BridgeAPI.cosmosJSON( - { - method: "GET", - uri: `sp://core-playlist/v1/playlist/${uri}/`, - body: { - policy: { - link: true, - }, - }, - }, - (error, res) => { - if (error) { - reject(error); - return; - } - - let id = `${uri}-${new Date()}` - let tracks = res.items.map((track) => track.link) - let img = res.playlist.picture - let name = res.playlist.name - let owner = res.playlist.owner.name - - let playlist = {id: id, uri: uri, name: name, tracks: tracks, imgUri: img, owner: owner} - - resolve(playlist); - } - ); - }); - } - - // Create a new Playlist - async function createPlaylist(name) { - return await new Promise((resolve, reject) => { - Spicetify.BridgeAPI.cosmosJSON( - { - method: "POST", - uri: `sp://core-playlist/v1/rootlist`, - body: { - operation: "create", - playlist: !0, - before: "start", - name: name, - }, - }, - (error, res) => { - if (error) { - reject(error); - return; - } - - resolve(res); - } - ); - }); - } - - // add track list to playlist - async function addTracks(uri, tracks) { - return await new Promise((resolve, reject) => { - Spicetify.BridgeAPI.cosmosJSON( - { - method: "POST", - uri: `sp://core-playlist/v1/playlist/${uri}`, - body: { - operation: "add", - uris: tracks, - after: "end" - } - }, - (error, res) => { - if (error) { - reject(error); - return; - } - - resolve(res); - } - ); - }); - } -})(); diff --git a/.config/spicetify/Extensions/fullScreen.js b/.config/spicetify/Extensions/fullScreen.js deleted file mode 100644 index fe6c5c50..00000000 --- a/.config/spicetify/Extensions/fullScreen.js +++ /dev/null @@ -1,3087 +0,0 @@ -// @ts-nocheck - -// NAME: Full Screen Mode -// AUTHOR: daksh2k -// DESCRIPTION: Fancy artwork and track status display. - -/// - -const translations = { - "en-US": { - langName: "English", - context: { - queue: "Playing from queue", - track: "Playing track", - album: "Playing from album", - artist: "Playing from artist", - playlist: "Playing from playlist", - playlistFolder: "Playing from playlist folder", - search: "Playing from search", - searchDest: "Songs", - collection: "Playing from collection", - likedSongs: "Liked Songs", - trackRadio: "Playing from track radio", - artistRadio: "Playing from artist radio", - albumRadio: "Playing from album radio", - playlistRadio: "Playing from playlist radio", - }, - upnext: "UP NEXT", - unknownArtist: "Artist (Unavailable)", - settings: { - switchToTV: "Switch to TV Mode", - switchToFullscreen: "Switch to Default Mode", - tvModeConfig: "TV Mode Configuration", - fullscreenConfig: "Full Screen Configuration", - exit: "Exit", - - pluginSettings: "Plugin Settings", - fsHideOriginal: "Hide Stock Button(Spotify Premium)", - language: "Language", - - lyricsHeader: "Lyrics Settings", - lyrics: "Lyrics", - lyricsAlignment: { - setting: "Lyrics Alignment", - left: "Left", - center: "Center", - right: "Right", - }, - lyricsAnimationTempo: "Lyrics Animation Tempo", - - generalHeader: "General Settings", - progressBar: "Progress Bar", - playerControls: "Player Controls", - trimTitle: "Trim Title", - trimTitleUpNext: "Trim Title(Up Next)", - showAlbum: { - setting: "Show Album", - never: "Never", - always: "Always", - date: "Show with Release Date", - }, - showAllArtists: "Show All Artists", - icons: "Icons", - songChangeAnimation: "Song Change Animation", - fullscreen: "Fullscreen", - - extraHeader: "Extra Functionality", - backgroundChoice: { - setting: "Background choice", - color: "Solid color", - artwork: "Artwork", - }, - extraControls: "Extra Controls", - upnextDisplay: "Upnext Display", - contextDisplay: { - setting: "Context Display", - always: "Always", - never: "Never", - mouse: "On mouse movement", - }, - volumeDisplay: { - setting: "Volume Bar Display", - always: "Always", - never: "Never", - mouse: "On mouse movement", - volume: "On volume change", - }, - - appearanceHeader: "Advanced/Appearance", - appearanceSubHeader: "Only change if you know what you are doing!", - backgroundColor: { - setting: "Color Choice on Colored Background", - vibrant: "Vibrant", - prominent: "Prominent", - desaturated: "Desaturated (recommended)", - lightVibrant: "Light Vibrant", - darkVibrant: "Dark Vibrant", - vibrantNonAlarming: "Vibrant Non Alarming", - }, - themedButtons: "Themed Buttons", - themedIcons: "Themed Icons", - invertColors: { - setting: "Invert Colors", - never: "Never", - always: "Always", - auto: "Automatic (Based on BG)", - }, - backAnimationTime: "Background Animation Time", - upnextScroll: { - setting: "Upnext Scroll Animation", - mq: "Marquee/Scrolling", - sp: "Spotify/Translating", - }, - upnextTime: "Upnext Time to Show", - backgroundBlur: "Background Blur", - backgroundBrightness: "Background Brightness", - - cgfReset: "Reset Config", - reload: "Reload Client", - }, - tvBtnDesc: "TV Mode Display", - fullscreenBtnDesc: "Full Screen", - }, - "it-IT": { - langName: "Italiano", - context: { - queue: "Riproduzione da coda", - track: "Riproduzione brano", - album: "Riproduzione album", - artist: "Riproduzione artista", - playlist: "Riproduzione playlist", - playlistFolder: "Riproduzione da cartella playlist", - search: "Riproduzione da ricerca", - searchDest: "Brani", - collection: "Riproduzione dalla libreria", - likedSongs: "Brani che ti piacciono", - trackRadio: "Radio dal brano", - artistRadio: "Radio da artista", - albumRadio: "Radio da album", - playlistRadio: "Radio da playlist", - }, - upnext: "In coda", - unknownArtist: "Artista sconosciuto", - settings: { - switchToTV: "Passa a modalità TV", - switchToFullscreen: "Passa a modalità fullscreen", - tvModeConfig: "Modalità TV", - fullscreenConfig: "Modalità fullscreen", - exit: "Esci", - - pluginSettings: "Impostazioni plugin", - fsHideOriginal: "Pulsante Nascondi Stock (Spotify Premium)", - language: "Lingua", - - lyricsHeader: "Impostazioni testo", - lyrics: "Mostra testo", - lyricsAlignment: { - setting: "Allineamento testo", - left: "Sinistra", - center: "Centro", - right: "Destra", - }, - lyricsAnimationTempo: "Durata animazione testo", - - generalHeader: "Impostazioni generali", - progressBar: "Barra di avanzamento", - playerControls: "Controlli player", - trimTitle: "Accorcia titolo", - trimTitleUpNext: "Accorcia titolo in Up next", - showAlbum: { - setting: "Mostra album", - never: "Mai", - always: "Sempre", - date: "Mostra con data di uscita", - }, - showAllArtists: "Mostra tutti gli artisti", - icons: "Icone", - songChangeAnimation: "Animazione cambio brano", - fullscreen: "Schermo intero", - - extraHeader: "Funzionalità aggiuntive", - backgroundChoice: { - setting: "Scelta sfondo", - color: "Tinta unita", - artwork: "Artwork", - }, - extraControls: "Controlli aggiuntivi", - upnextDisplay: "Mostra Up next", - contextDisplay: { - setting: "Mostra contesto", - always: "Sempre", - never: "Mai", - mouse: "Al movimento del mouse", - }, - volumeDisplay: { - setting: "Mostra barra volume", - always: "Sempre", - never: "Mai", - mouse: "Al movimento del mouse", - volume: "Al cambio volume", - }, - - appearanceHeader: "Avanzato/Aspetto", - appearanceSubHeader: "Cambia solo se sai cosa stai facendo!", - backgroundColor: { - setting: "Colore su sfondo tinta unita", - vibrant: "Vibrant", - prominent: "Prominent", - desaturated: "Desaturato (raccomandato)", - lightVibrant: "Vibrant chiaro", - darkVibrant: "Vibrant scuro", - vibrantNonAlarming: "Vibrant delicato", - }, - themedButtons: "Pulsanti a tema", - themedIcons: "Icone a tema", - invertColors: { - setting: "Inverti colori", - never: "Mai", - always: "Sempre", - auto: "Automatico (basato su sfondo)", - }, - backAnimationTime: "Durata animazione sfondo", - upnextScroll: { - setting: "Scorrimento Up next", - mq: "Scorrimento", - sp: "Traslazione", - }, - upnextTime: "Tempo per mostrare Up next", - backgroundBlur: "Sfocamento sfondo", - backgroundBrightness: "Luminosità sfondo", - - cgfReset: "Resetta configurazione", - reload: "Ricarica client", - }, - tvBtnDesc: "Modalità TV", - fullscreenBtnDesc: "Schermo intero", - }, - "zh-CN": { - langName: "简体中文", - context: { - queue: "正在从队列播放", - track: "正在播放", - album: "正在从专辑播放", - artist: "正在从艺人播放", - playlist: "正在从歌单播放", - playlistFolder: "正在从歌单文件夹播放", - search: "正在从搜索结果播放", - searchDest: "歌曲", - collection: "正在从合辑播放", - likedSongs: "已点赞的歌曲", - trackRadio: "正在从歌曲电台播放", - artistRadio: "正在从艺人电台播放", - albumRadio: "正在从专辑电台播放", - playlistRadio: "正在从歌单电台播放", - }, - upnext: "下一首", - unknownArtist: "未知歌手", - settings: { - switchToTV: "切换至电视模式", - switchToFullscreen: "切换至默认模式", - tvModeConfig: "电视模式配置", - fullscreenConfig: "全屏模式配置", - exit: "退出", - - pluginSettings: "插件设置", - fsHideOriginal: "隐藏切换至原版按钮 (Spotify Premium)", - language: "语言", - - lyricsHeader: "歌词设置", - lyrics: "歌词", - lyricsAlignment: { - setting: "歌词对齐方式", - left: "靠左", - center: "居中", - right: "靠右", - }, - lyricsAnimationTempo: "歌词动画速度", - - generalHeader: "通用设置", - progressBar: "播放进度条", - playerControls: "播放控制", - trimTitle: "缩短标题", - trimTitleUpNext: "缩短标题 (下一首提示)", - showAlbum: { - setting: "显示标题", - never: "永不", - always: "总是", - date: "与发布日期一起显示", - }, - showAllArtists: "显示所有艺人", - icons: "显示图标", - songChangeAnimation: "切歌动画", - fullscreen: "全屏", - - extraHeader: "额外功能", - backgroundChoice: { - setting: "背景", - color: "纯色", - artwork: "艺术画", - }, - extraControls: "额外控件", - upnextDisplay: "下一首提示", - contextDisplay: { - setting: "内容来源显示", - always: "总是", - never: "从不", - mouse: "当鼠标移动时", - }, - volumeDisplay: { - setting: "音量显示", - always: "总是", - never: "从不", - mouse: "当鼠标移动时", - volume: "当音量调节时", - }, - - appearanceHeader: "高级/外观", - appearanceSubHeader: "不要动除非你知道自己在做什么", - backgroundColor: { - setting: "纯色背景的颜色配置", - vibrant: "Vibrant", - prominent: "Prominent", - desaturated: "Desaturated (推荐)", - lightVibrant: "Light Vibrant", - darkVibrant: "Dark Vibrant", - vibrantNonAlarming: "Vibrant Non Alarming", - }, - themedButtons: "主题色按钮", - themedIcons: "主题色图标", - invertColors: { - setting: "反转颜色", - never: "从不", - always: "总是", - auto: "自动(基于背景)", - }, - backAnimationTime: "背景动画时间", - upnextScroll: { - setting: "下一首提示滚动", - mq: "Marquee/滚动", - sp: "Spotify/变换", - }, - upnextTime: "下一首提示显示时间", - backgroundBlur: "背景模糊", - backgroundBrightness: "背景亮度", - - cgfReset: "重置配置", - reload: "重新载入应用", - }, - tvBtnDesc: "电视模式显示", - fullscreenBtnDesc: "全屏", - }, -}; - -let INIT_RETRIES = 0; -function fullScreen() { - const extraBar = - document.querySelector(".main-nowPlayingBar-right")?.childNodes[0] || - document.querySelector(".ExtraControls") || - document.querySelector(".ClYTTKGdd9KB7D9MXicj"); - const topBar = document.querySelector(".main-topBar-historyButtons"); - const { CosmosAsync, Keyboard, Player, Platform } = Spicetify; - - let entriesToVerify = [topBar, extraBar, CosmosAsync, Keyboard, Player, Platform]; - - if (INIT_RETRIES > 50) { - entriesToVerify.forEach((entry) => { - if (!entry) { - console.error("Spicetify method not available. Report issue on GitHub or run Spicetify.test() to test."); - Spicetify.showNotification(`Error initializing "fullscreen.js" extension. Spicetify method not available. Report issue on GitHub.`); - } - }); - return; - } - if (entriesToVerify.some((it) => !it)) { - setTimeout(fullScreen, 300); - INIT_RETRIES += 1; - return; - } - Spicetify.Keyboard.registerShortcut( - { - key: Spicetify.Keyboard.KEYS["T"], - ctrl: false, - shift: false, - alt: false, - }, - openwithTV - ); - Spicetify.Keyboard.registerShortcut( - { - key: Spicetify.Keyboard.KEYS["F"], - ctrl: false, - shift: false, - alt: false, - }, - openwithDef - ); - - function openwithTV() { - if (!document.body.classList.contains("fsd-activated") || !CONFIG.tvMode || ACTIVE !== "tv") { - if (!CONFIG.tvMode || ACTIVE !== "tv") { - CONFIG["tvMode"] = true; - ACTIVE = "tv"; - saveConfig(); - render(); - } - activate(); - } else deactivate(); - } - - function openwithDef() { - if (!document.body.classList.contains("fsd-activated") || CONFIG.tvMode || ACTIVE !== "def") { - if (CONFIG.tvMode || ACTIVE !== "def") { - CONFIG["tvMode"] = false; - ACTIVE = "def"; - saveConfig(); - render(); - } - activate(); - } else deactivate(); - } - const DEFAULTS = { - tv: { - lyricsDisplay: true, - lyricsAlignment: "right", - animationTempo: 0.2, - progressBarDisplay: false, - playerControls: false, - trimTitle: true, - trimTitleUpNext: true, - showAlbum: "d", - showAllArtists: true, - icons: true, - titleMovingIcon: false, - enableFade: true, - enableFullscreen: true, - extraControls: false, - upnextDisplay: true, - contextDisplay: "a", - volumeDisplay: "o", - themedButtons: true, - themedIcons: true, - invertColors: "n", - backAnimationTime: 0.4, - upNextAnim: "sp", - upnextTimeToShow: 45, - blurSize: 0, - backgroundBrightness: 0.4, - }, - def: { - lyricsDisplay: true, - lyricsAlignment: "right", - animationTempo: 0.2, - progressBarDisplay: true, - playerControls: true, - trimTitle: true, - trimTitleUpNext: true, - showAlbum: "n", - showAllArtists: true, - icons: false, - titleMovingIcon: false, - enableFade: true, - enableFullscreen: true, - backgroundChoice: "a", - extraControls: true, - upnextDisplay: true, - contextDisplay: "m", - volumeDisplay: "o", - themedButtons: true, - themedIcons: false, - invertColors: "n", - backAnimationTime: 1, - upNextAnim: "sp", - upnextTimeToShow: 30, - coloredBackChoice: "DESATURATED", - blurSize: 24, - backgroundBrightness: 0.7, - }, - tvMode: false, - locale: "en-US", - fsHideOriginal: false, - }; - const CONFIG = getConfig(); - if (localStorage.getItem("full-screen:inverted") === null) { - localStorage.setItem("full-screen:inverted", "{}"); - } - - const INVERTED = JSON.parse(localStorage.getItem("full-screen:inverted") ?? "{}"); - let ACTIVE = CONFIG.tvMode ? "tv" : "def"; - let LOCALE = CONFIG.locale; - - const OFFLINESVG = `data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCI+CiAgPHJlY3Qgc3R5bGU9ImZpbGw6I2ZmZmZmZiIgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiB4PSIwIiB5PSIwIiAvPgogIDxwYXRoIGZpbGw9IiNCM0IzQjMiIGQ9Ik0yNi4yNSAxNi4xNjJMMjEuMDA1IDEzLjEzNEwyMS4wMTIgMjIuNTA2QzIwLjU5NCAyMi4xOTIgMjAuMDgxIDIxLjk5OSAxOS41MTkgMjEuOTk5QzE4LjE0MSAyMS45OTkgMTcuMDE5IDIzLjEyMSAxNy4wMTkgMjQuNDk5QzE3LjAxOSAyNS44NzggMTguMTQxIDI2Ljk5OSAxOS41MTkgMjYuOTk5QzIwLjg5NyAyNi45OTkgMjIuMDE5IDI1Ljg3OCAyMi4wMTkgMjQuNDk5QzIyLjAxOSAyNC40MjIgMjIuMDA2IDE0Ljg2NyAyMi4wMDYgMTQuODY3TDI1Ljc1IDE3LjAyOUwyNi4yNSAxNi4xNjJaTTE5LjUxOSAyNS45OThDMTguNjkyIDI1Ljk5OCAxOC4wMTkgMjUuMzI1IDE4LjAxOSAyNC40OThDMTguMDE5IDIzLjY3MSAxOC42OTIgMjIuOTk4IDE5LjUxOSAyMi45OThDMjAuMzQ2IDIyLjk5OCAyMS4wMTkgMjMuNjcxIDIxLjAxOSAyNC40OThDMjEuMDE5IDI1LjMyNSAyMC4zNDYgMjUuOTk4IDE5LjUxOSAyNS45OThaIi8+Cjwvc3ZnPgo=`; - - const style = document.createElement("style"); - - const container = document.createElement("div"); - container.id = "full-screen-display"; - container.classList.add("Video", "VideoPlayer--fullscreen", "VideoPlayer--landscape"); - - let cover, - back, - title, - artist, - album, - prog, - elaps, - durr, - play, - ctx_container, - ctx_icon, - ctx_source, - ctx_name, - fsd_myUp, - fsd_nextCover, - fsd_up_next_text, - fsd_next_tit_art, - fsd_next_tit_art_inner, - fsd_first_span, - fsd_second_span, - volumeContainer, - volumeCurr, - volumeBarInner, - volumeIcon, - playingIcon, - pausedIcon, - nextControl, - backControl, - heart, - shuffle, - repeat, - invertButton, - lyrics; - const nextTrackImg = new Image(); - const artistImg = new Image(); - - function render() { - container.classList.toggle("lyrics-active", !!CONFIG[ACTIVE].lyricsDisplay); - if (!CONFIG[ACTIVE].lyricsDisplay || !CONFIG[ACTIVE].extraControls) container.classList.remove("lyrics-hide-force"); - const styleBase = ` -#full-screen-display { - display: none; - z-index: 100; - position: fixed; - width: 100%; - height: 100%; - cursor: default; - left: 0; - top: 0; - --transition-duration: .8s; - --transition-function: ease-in-out; - --main-color: 255,255,255; - --contrast-color: 0,0,0; - --primary-color: rgba(var(--main-color),1); - --secondary-color: rgba(var(--main-color),.7); - --tertiary-color: rgba(var(--main-color),.5); - --theme-color: 175,175,175; - --theme-background-color: rgba(175,175,175,.6); - --theme-hover-color: rgba(175,175,175,.3); - --theme-main-color: rgba(var(--theme-color),1); -} -#full-screen-display.themed-buttons{ - --theme-background-color: rgba(var(--theme-color),.6); - --theme-hover-color: rgba(var(--theme-color),.3); -} -.unavailable{ - color: var(--tertiary-color) !important; - pointer-events: none !important; - opacity: .5 !important; - background: transparent !important; -} -/* -.unavailable::after{ - content: ""; - display: block; - background-color: #FFF; - bottom: 50%; - left: 0; - right: 0; - position: absolute; - transform: rotateZ(45deg); - width: 25px; - height: 1.5px; -} -.unavailable::before{ - content: ""; - display: block; - background-color: #FFF; - bottom: 50%; - left: 0; - right: 0; - position: absolute; - transform: rotateZ(-45deg); - width: 25px; - height: 1.5px; -} -*/ -@keyframes fadeUp{ - 0%{ - opacity:0; - transform:translateY(-10px) - } - to{ - opacity:1; - transform:translateY(0) - } -} -@keyframes fadeDo{ - 0%{ - opacity:0; - transform:translateY(10px) - } - to{ - opacity:1; - transform:translateY(0) - } -} -@keyframes fadeRi{ - 0%{ - opacity:0; - transform:translateX(10px) - } - to{ - opacity:1; - transform:translateX(0) - } -} -@keyframes fadeLe{ - 0%{ - opacity:0; - transform:translateX(-10px) - } - to{ - opacity:1; - transform:translateX(0) - } -} -.fade-do{ - animation: fadeDo .5s cubic-bezier(.3, 0, 0, 1); -} -.fade-up{ - animation: fadeUp .5s cubic-bezier(.3, 0, 0, 1); -} -.fade-ri{ - animation: fadeRi .5s cubic-bezier(.3, 0, 0, 1); -} -.fade-le{ - animation: fadeLe .5s cubic-bezier(.3, 0, 0, 1); -} -button.dot-after{ - padding-bottom: 3px !important; -} -.dot-after:after{ - background-color: currentColor; - border-radius: 50%; - bottom: 3px; - content: ""; - display: block; - height: 4px; - left: 50%; - position: absolute; - transform: translateX(-50%); - width: 4px; -} -#fsd-ctx-container { - background-color: transparent; - color: var(--secondary-color); - position: fixed; - float: left; - top: 30px; - left: 50px; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - text-align: left; - z-index: 50; - transition: all 1s ease-in-out; - opacity: 1; - max-width: 40%; -} -#fsd-ctx-details{ - padding-left: 18px; - line-height: initial; - font-size: 18px; - overflow: hidden; -} -#fsd-ctx-icon{ - width: 48px; - height : 48px; -} -#fsd-ctx-icon svg{ - fill: var(--primary-color) !important; -} -#fsd-ctx-source{ - text-transform: uppercase; -} -#fsd-ctx-name{ - font-weight: 700; - font-size: 20px; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; -} -.ctx-no-name{ - padding-bottom: 2px; - font-size: 24px; - font-weight: 600; -} -#fsd-upnext-container{ - float: right; - width: 472px; - height: 102px; - max-width: 45%; - position: fixed; - top: 45px; - right: 60px; - display: flex; - border: 1px solid rgba(130,130,130,.7); - border-radius: 10px; - background-color: rgba(20,20,20,1); - flex-direction: row; - text-align: left; - z-index: 50; - transition: transform .8s ease-in-out; - transform: translateX(600px); -} -#fsd_next_art_image{ - background-size: cover; - background-position: center; - width: 100px; - height: 100px; - border-radius: 9px 0 0 9px; -} -#fsd_next_details{ - padding-left: 18px; - padding-top: 17px; - line-height: initial; - width: calc(100% - 115px); - color: rgba(255,255,255,1); - font-size: 19px; - overflow: hidden; -} -#fsd_next_tit_art{ - padding-top: 9px; - font-size: 22px; - font-weight: 700; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} -@keyframes fsd_cssmarquee { - 0% { - transform: translateX(0%); - } - 18% { - transform: translateX(0%); - } - 100% { - transform: translateX(var(--translate_width_fsd)); - } -} -@keyframes fsd_translate { - 0%,10% { - transform: translateX(0%); - } - 50%,55% { - transform: translateX(var(--translate_width_fsd)); - } - 100% { - transform: translateX(0%); - } -} -#fsd-volume-container{ - position: fixed; - text-align: center; - background-color: transparent; - color: var(--primary-color); - float: left; - top: 30%; - left: 30px; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - z-index: 50; - height: 200px; - max-height: 33vh; - transition: transform .8s var(--transition-function); -} -#fsd-volume-container.v-hidden{ - transform: translateX(-100px) scale(.1); -} -#fsd-volume-container:hover{ - transform: translateX(0px) scale(1); -} -#fsd-volume-bar{ - margin: 8px 0; - border-radius: 4px; - background-color: rgba(var(--main-color),.35); - overflow: hidden; - width: 8px; - height: 100%; - display: flex; - align-items: end; -} -#fsd-volume-bar-inner{ - width: 100%; - border-radius: 4px; - background-color: var(--primary-color); - box-shadow: 4px 0 12px rgba(0, 0, 0, 0.8); - transition: height .2s var(--transition-function); -} -#fsd-volume-icon svg{ - fill: var(--primary-color) !important; -} -.unavailable #fsd-volume-bar-inner{ - height: 100%; - background-color: var(--tertiary-color); -} -#fsd-volume{ - width: 50px; - font-size: 18px; -} -#fad-lyrics-plus-container{ - transition: transform var(--transition-duration) var(--transition-function); - position: absolute; - right: -50px; - max-width: 50%; - top: 7.5vh; -} -.lyrics-unavailable #fad-lyrics-plus-container, .lyrics-hide-force #fad-lyrics-plus-container{ - transform: translateX(1000px) scale3d(.1,.1,.1) rotate(45deg); -} -#fad-lyrics-plus-container .lyrics-lyricsContainer-LyricsContainer{ - --lyrics-color-active: var(--primary-color) !important; - --lyrics-color-inactive: var(--tertiary-color) !important; - --lyrics-highlight-background: rgba(var(--contrast-color),.7) !important; - --lyrics-align-text: ${CONFIG[ACTIVE].lyricsAlignment} !important; - --animation-tempo: ${CONFIG[ACTIVE].animationTempo}s !important; - height: 85vh !important; -} -.lyrics-config-button{ - margin-right: 20px; -} -#fsd-foreground { - position: relative; - top: 0; - left: 0; - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - color: var(--primary-color); - transition: all var(--transition-duration) var(--transition-function); -} -#fsd-art-image { - position: relative; - width: 100%; - height: 100%; - padding-bottom: 100%; - border-radius: 8px; - background-size: cover; -} -#fsd-art-inner { - position: absolute; - left: 3%; - bottom: 0; - width: 94%; - height: 94%; - z-index: -1; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.6) !important; - transform: translateZ(0); -} -#fsd-artist{ - font-weight: 500; - color: var(--secondary-color); -} -#fsd-album{ - font-weight: 400; - color: var(--tertiary-color); -} -.fsd-controls{ - display: flex; - flex-direction: row; - column-gap: 10px; -} -#fsd-progress { - width: 100%; - height: 6px; - border-radius: 4px; - background-color: rgba(var(--main-color),.35); - overflow: hidden; -} -#fsd-progress-inner { - height: 100%; - border-radius: 4px; - background-color: var(--primary-color); - box-shadow: 4px 0 12px rgba(0, 0, 0, 0.8); -} -#fsd-elapsed, #fsd-duration{ - min-width: 35px; - text-align: center; -} -#fsd-elapsed { - margin-right: 10px; -} -#fsd-duration { - margin-left: 10px; -} -#fsd-background { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - z-index: -2; -} - -#full-screen-display .fs-button{ - background: transparent; - border: 0; - border-radius: 8px; - color: var(--primary-color); - padding: 3px 5px 0 5px; - cursor: pointer; - position: relative; - transition: all .3s var(--transition-function), transform .1s var(--transition-function); -} -#full-screen-display .fs-button:hover{ - transform: scale(1.2); - filter: saturate(1.5) contrast(1.5) !important; - background: var(--theme-hover-color); -} -#full-screen-display .fs-button.button-active{ - background: var(--theme-background-color) !important; - filter: saturate(1.5) contrast(1.5) !important; -} - -#fsd-foreground svg{ - fill: var(--primary-color); - transition: all .3s var(--transition-function); -} -.themed-icons #fsd-foreground svg{ - fill: var(--theme-main-color); - filter: saturate(1.8); -} -.themed-icons.themed-buttons .fs-button.button-active svg{ - fill: var(--primary-color) !important; -} -.fsd-background-fade { - transition: background-image var(--fs-transition) linear; -} -body.fsd-activated #full-screen-display { - display: block; -} -.fsd-activated .Root__top-bar, .fsd-activated .Root__nav-bar, .fsd-activated .Root__main-view, .fsd-activated .Root__now-playing-bar{ - visibility: hidden; - display: none; -} -.main-notificationBubbleContainer-NotificationBubbleContainer{ - z-index: 1000; -}`; - - const styleChoices = [ - ` -#full-screen-display, -#full-screen-display.lyrics-unavailable, -#full-screen-display.lyrics-hide-force{ - --fsd-foreground-transform: 50%; - --fsd-art-max-width: 600px; - --fsd-items-max-width: 580px; - --fsd-title-size: 50px; - --fsd-sec-size: 28px; -} -#full-screen-display.lyrics-active :not(#full-screen-display.lyrics-unavailable *,#full-screen-display.lyrics-hide-force *){ - --fsd-foreground-transform: 0px; - --fsd-art-max-width: 500px; - --fsd-items-max-width: 480px; - --fsd-title-size: 40px; - --fsd-sec-size: 23px; -} - -#fsd-art, #fsd-details, #fsd-status, #fsd-progress-container{ - transition: all var(--transition-duration) var(--transition-function); -} - -#fsd-foreground { - transform: translateX(var(--fsd-foreground-transform)); - width: 50%; - flex-direction: column; - text-align: center; -} -#fsd-art { - width: calc(100vh - 300px); - max-width: var(--fsd-art-max-width); - min-width: 300px; -} - -#fsd-title{ - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - overflow: hidden; -} -#fsd-album, #fsd-artist{ - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; - overflow: hidden; -} - -#fsd-progress-container { - width: 28vw; - max-width: var(--fsd-items-max-width); - display: flex; - align-items: center; -} -#fsd-details { - padding-top: 30px; - line-height: initial; - max-width: var(--fsd-items-max-width); - color: var(--primary-color); -} -#fsd-status { - display: flex; - width: 28vw; - max-width: var(--fsd-items-max-width); - align-items: center; - justify-content: space-between; - flex-direction: row; -} -#fsd-status.active { - margin: 5px auto 0; - gap: 10px; -} - -#fsd-title { - font-size: var(--fsd-title-size); - font-weight: 900; - transition: all var(--transition-duration) var(--transition-function); -} -#fsd-artist,#fsd-album{ - font-size: var(--fsd-sec-size); - transition: all var(--transition-duration) var(--transition-function); -} -@media (max-width: 900px), (max-height: 900px){ - #fsd-title{ - font-size: 35px; - font-weight: 600; - } -} - -#fsd-title svg{ - width: 35px; - height: 35px; -} -.lyrics-active #fsd-title svg{ - width: 30px; - height: 30px; -} -.lyrics-unavailable #fsd-title svg,.lyrics-hide-force #fsd-title svg{ - width: 35px; - height: 35px; -} -#playing-icon{ - width: 28px !important; - height: 28px !important; - margin-right: 7px; -} -.lyrics-active #playing-icon{ - margin-right: 2px; -} -.lyrics-unavailable #playing-icon,.lyrics-hide-force #playing-icon{ - margin-right: 7px; -} - -#fsd-artist svg, #fsd-album svg{ - width: calc(var(--fsd-sec-size) - 6px); - height: calc(var(--fsd-sec-size) - 6px); - margin-right: 5px; -} - -.fsd-controls { - margin-top: 10px; - margin-bottom: 5px; -} -.fsd-controls-left{ - width: 30%; - justify-content: flex-start; -} -.fsd-controls-center{ - width: 40%; - justify-content: center; - margin: 10px auto 5px; -} -.fsd-controls-right{ - width: 30%; - justify-content: flex-end; -} -`, - `#fsd-background-image { - height: 100%; - background-size: cover; - filter: brightness(${CONFIG[ACTIVE].backgroundBrightness}) blur(${CONFIG[ACTIVE].blurSize}px); - background-position: center; - transform: translateZ(0); -} - -#fsd-foreground { - flex-direction: row; - text-align: left; - justify-content: left; - align-items: flex-end; - position: absolute; - top: auto; - bottom: 75px; -} -.lyrics-active #fsd-foreground{ - width: max-content; - max-width: 65%; -} - -#fsd-art { - width: calc(100vw - 840px); - min-width: 180px; - max-width: 220px; - margin-left: 65px; -} - -#fsd-progress-container { - width: 100%; - max-width: 450px; - display: flex; - align-items: center; -} -.fsd-controls + #fsd-progress-container{ - padding-left: 10px; -} -#fsd-details { - padding-left: 30px; - line-height: initial; - width: 80%; - color: var(--primary-color); -} -#fsd-title, #fsd-album, #fsd-artist{ - display: flex; - justify-content: flex-start; - align-items: baseline; - gap: 5px; -} -#fsd-title span, #fsd-album span, #fsd-artist span{ - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; - overflow: hidden; -} -#fsd-title span{ - -webkit-line-clamp: 3; -} -#fsd-title svg, #fsd-artist svg, #fsd-album svg{ - flex: 0 0 auto; -} -#fsd-album{ - position: relative; -} -#fsd-album svg{ - position: absolute; - top: 7px; -} -#fsd-album svg + span{ - margin-left: 40px; -} -#fsd-title { - font-size: 62px; - font-weight: 900; -} -@media (max-width: 900px), (max-height: 800px){ - #fsd-title{ - font-size: 40px; - font-weight: 600; - } - #fsd-artist, #fsd-album { - font-size: 20px; - } -} -#fsd-artist, #fsd-album { - font-size: 28px; -} -#fsd-title svg{ - width: 35px; - height: 45px; -} -#playing-icon{ - width: 30px !important; - height: 40px !important; - margin-right: 5px; -} -#fsd-artist svg, #fsd-album svg { - margin-right: 15px; - width: 22px; - height: 22px; -} -#fsd-status { - display: flex; - flex-direction: row; - min-width: 450px; - max-width: 450px; - align-items: center; - justify-content: space-between; -} -#fsd-status.active { - column-gap: 10px; - margin: 10px 0; -} -`, - ]; - const iconStyleChoices = [ - ` -#fsd-title svg, #fsd-artist svg, #fsd-album svg { - display: none; -}`, - ` -#fsd-title svg, #fsd-artist svg, #fsd-album svg { - transition: all var(--transition-duration) var(--transition-function); - display: inline-block; -}`, - ]; - Spicetify.Player.removeEventListener("songchange", updateInfo); - if (progressListener) clearInterval(progressListener); - Spicetify.Player.removeEventListener("onplaypause", updatePlayerControls); - Spicetify.Player.removeEventListener("onplaypause", updatePlayingIcon); - Spicetify.Player.origin._events.removeListener("update", updateExtraControls); - heartObserver.disconnect(); - - Spicetify.Player.origin._events.removeListener("queue_update", updateUpNext); - Spicetify.Player.origin._events.removeListener("update", updateUpNextShow); - window.removeEventListener("resize", updateUpNext); - upNextShown = false; - - if (Spicetify.Platform?.PlaybackAPI === undefined) Spicetify.Player.origin._events.removeListener("volume", updateVolume); - else Spicetify.Platform.PlaybackAPI._events.removeListener("volume", updateVolume); - - if (origLoc !== "/lyrics-plus" && document.body.classList.contains("fsd-activated")) { - Spicetify.Platform.History.push(origLoc); - Spicetify.Platform.History.entries.splice(Spicetify.Platform.History.entries.length - 3, 2); - Spicetify.Platform.History.index = Spicetify.Platform.History.index > 0 ? Spicetify.Platform.History.index - 2 : -1; - Spicetify.Platform.History.length = Spicetify.Platform.History.length > 1 ? Spicetify.Platform.History.length - 2 : 0; - } - window.dispatchEvent(new Event("fad-request")); - window.removeEventListener("lyrics-plus-update", handleLyricsUpdate); - - container.removeEventListener("mousemove", hideCursor); - container.removeEventListener("mousemove", hideContext); - container.removeEventListener("mousemove", hideVolume); - - if (curTimer) clearTimeout(curTimer); - if (ctxTimer) clearTimeout(ctxTimer); - if (volTimer) clearTimeout(volTimer); - - style.innerHTML = styleBase + styleChoices[CONFIG.tvMode ? 1 : 0] + iconStyleChoices[CONFIG[ACTIVE].icons ? 1 : 0]; - - container.innerHTML = ` -${ - CONFIG.tvMode - ? `
-
-
` - : `` -} - ${ - CONFIG[ACTIVE].contextDisplay !== "n" - ? ` -
-
-
-
-
-
-
` - : "" - } - ${ - CONFIG[ACTIVE].upnextDisplay - ? ` -
-
-
-
-
-
-
-
- - -
-
-
` - : "" - } -${ - CONFIG[ACTIVE].volumeDisplay !== "n" - ? ` -
- -
- -
` - : "" -} -${CONFIG[ACTIVE].lyricsDisplay ? `
` : ""} -
-
-
-
-
-
-
-
- - - -
-
- ${Spicetify.SVGIcons.artist} - -
- ${ - CONFIG[ACTIVE].showAlbum !== "n" - ? `
- ${CONFIG[ACTIVE].icons ? `${Spicetify.SVGIcons.album}` : ""} - -
` - : "" - } -
- ${ - CONFIG[ACTIVE].extraControls - ? `
- - -
` - : "" - } - ${ - CONFIG[ACTIVE].playerControls - ? ` -
- - - -
` - : "" - } - ${ - CONFIG[ACTIVE].extraControls - ? `
- ${ - CONFIG[ACTIVE].invertColors === "d" - ? `` - : "" - } - - ${ - CONFIG[ACTIVE].lyricsDisplay - ? `` - : "" - } -
` - : "" - } - ${ - CONFIG.tvMode && !(CONFIG[ACTIVE].playerControls && CONFIG[ACTIVE].extraControls) - ? `${ - CONFIG[ACTIVE].progressBarDisplay - ? `
- -
- -
` - : "" - }` - : "" - } -
- ${ - CONFIG.tvMode && CONFIG[ACTIVE].playerControls && CONFIG[ACTIVE].extraControls - ? `${ - CONFIG[ACTIVE].progressBarDisplay - ? `
- -
- -
` - : "" - }` - : "" - } -
- ${ - CONFIG.tvMode - ? "" - : `${ - CONFIG[ACTIVE].progressBarDisplay - ? `
- -
- -
` - : "" - }` - } -
`; - if (CONFIG.tvMode) back = container.querySelector("#fsd-background-image"); - else { - back = container.querySelector("canvas"); - back && (back.width = window.innerWidth); - back && (back.height = window.innerHeight); - } - cover = container.querySelector("#fsd-art-image"); - title = container.querySelector("#fsd-title span"); - artist = container.querySelector("#fsd-artist span"); - album = container.querySelector("#fsd-album span"); - - if (CONFIG[ACTIVE].contextDisplay !== "n") { - ctx_container = container.querySelector("#fsd-ctx-container"); - ctx_icon = container.querySelector("#fsd-ctx-icon"); - ctx_source = container.querySelector("#fsd-ctx-source"); - ctx_name = container.querySelector("#fsd-ctx-name"); - } - if (CONFIG[ACTIVE].upnextDisplay) { - fsd_myUp = container.querySelector("#fsd-upnext-container"); - fsd_myUp.onclick = Spicetify.Player.next; - fsd_nextCover = container.querySelector("#fsd_next_art_image"); - fsd_up_next_text = container.querySelector("#fsd_up_next_text"); - fsd_next_tit_art = container.querySelector("#fsd_next_tit_art"); - fsd_next_tit_art_inner = container.querySelector("#fsd_next_tit_art_inner"); - fsd_first_span = container.querySelector("#fsd_first_span"); - fsd_second_span = container.querySelector("#fsd_second_span"); - } - if (CONFIG[ACTIVE].volumeDisplay !== "n") { - volumeContainer = container.querySelector("#fsd-volume-container"); - volumeCurr = container.querySelector("#fsd-volume"); - volumeBarInner = container.querySelector("#fsd-volume-bar-inner"); - volumeIcon = container.querySelector("#fsd-volume-icon"); - volumeIcon && (volumeIcon.onclick = Spicetify.Player.toggleMute); - } - if (CONFIG[ACTIVE].progressBarDisplay) { - prog = container.querySelector("#fsd-progress-inner"); - durr = container.querySelector("#fsd-duration"); - elaps = container.querySelector("#fsd-elapsed"); - } - if (CONFIG[ACTIVE].icons) { - playingIcon = container.querySelector("#playing-icon"); - - //Clicking on playing icon disables it and remembers the config - playingIcon && (playingIcon.onclick = () => { - CONFIG[ACTIVE]["titleMovingIcon"] = false; - saveConfig(); - playingIcon.classList.add("hidden"); - pausedIcon.classList.remove("hidden"); - }); - pausedIcon = container.querySelector("#paused-icon"); - pausedIcon && (pausedIcon.onclick = () => { - CONFIG[ACTIVE]["titleMovingIcon"] = true; - saveConfig(); - playingIcon.classList.remove("hidden"); - pausedIcon.classList.add("hidden"); - updatePlayingIcon({ data: { is_paused: !Spicetify.Player.isPlaying() } }); - }); - } - if (CONFIG[ACTIVE].playerControls) { - play = container.querySelector("#fsd-play"); - play && (play.onclick = () => { - fadeAnimation(play); - Spicetify.Player.togglePlay(); - }); - nextControl = container.querySelector("#fsd-next"); - nextControl && (nextControl.onclick = () => { - fadeAnimation(nextControl, "fade-ri"); - Spicetify.Player.next(); - }); - backControl = container.querySelector("#fsd-back"); - backControl && (backControl.onclick = () => { - fadeAnimation(backControl, "fade-le"); - Spicetify.Player.back(); - }); - } - if (CONFIG[ACTIVE].extraControls) { - heart = container.querySelector("#fsd-heart"); - shuffle = container.querySelector("#fsd-shuffle"); - repeat = container.querySelector("#fsd-repeat"); - - heart && (heart.onclick = () => { - fadeAnimation(heart); - Spicetify.Player.toggleHeart(); - }); - shuffle && (shuffle.onclick = () => { - fadeAnimation(shuffle); - Spicetify.Player.toggleShuffle(); - }); - repeat && (repeat.onclick = () => { - fadeAnimation(repeat); - Spicetify.Player.toggleRepeat(); - }); - if (CONFIG[ACTIVE].invertColors === "d") { - invertButton = container.querySelector("#fsd-invert"); - invertButton && (invertButton.onclick = () => { - fadeAnimation(invertButton); - if (invertButton.classList.contains("button-active")) - invertButton.innerHTML = ``; - else - invertButton.innerHTML = ``; - invertButton.classList.toggle("button-active"); - if (getComputedStyle(container).getPropertyValue("--main-color").startsWith("0")) { - container.style.setProperty("--main-color", "255,255,255"); - container.style.setProperty("--contrast-color", "0,0,0"); - if (!CONFIG.tvMode && CONFIG.def.backgroundChoice === "a") - INVERTED[Spicetify.Player.data.track?.metadata?.album_uri?.split(":")[2]] = false; - } else { - container.style.setProperty("--main-color", "0,0,0"); - container.style.setProperty("--contrast-color", "255,255,255"); - if (!CONFIG.tvMode && CONFIG.def.backgroundChoice === "a") - INVERTED[Spicetify.Player.data.track?.metadata?.album_uri?.split(":")[2]] = true; - } - localStorage.setItem("full-screen:inverted", JSON.stringify(INVERTED)); - }); - } - if (CONFIG[ACTIVE].lyricsDisplay) { - lyrics = container.querySelector("#fsd-lyrics"); - lyrics && (lyrics.onclick = () => { - fadeAnimation(lyrics); - container.classList.toggle("lyrics-hide-force"); - lyrics.classList.toggle("button-active"); - lyrics.innerHTML = - container.classList.contains("lyrics-unavailable") || container.classList.contains("lyrics-hide-force") - ? ` - - - ` - : ``; - }); - } - } - } - - const classes = ["video", "video-full-screen", "video-full-window", "video-full-screen--hide-ui", "fsd-activated"]; - - function fullScreenOn() { - if (!document.fullscreen) document.documentElement.requestFullscreen(); - } - - function fullScreenOff() { - if (document.fullscreen) document.exitFullscreen(); - } - - function getToken() { - return Spicetify.Platform.AuthorizationAPI._tokenProvider({ - preferCached: true, - }).then((res) => res.accessToken); - } - - async function getTrackInfo(id) { - return fetch(`https://api.spotify.com/v1/tracks/${id}`, { - headers: { - Authorization: `Bearer ${await getToken()}`, - }, - }).then((res) => res.json()); - // return Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/tracks/${id}`) - } - - async function getAlbumInfo(id) { - return fetch(`https://api.spotify.com/v1/albums/${id}`, { - headers: { - Authorization: `Bearer ${await getToken()}`, - }, - }).then((res) => res.json()); - // return Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/albums/${id}`) - } - - function getPlaylistInfo(uri) { - return Spicetify.CosmosAsync.get(`sp://core-playlist/v1/playlist/${uri}`); - } - - async function getArtistInfo(id) { - return fetch( - `https://api-partner.spotify.com/pathfinder/v1/query?operationName=queryArtistOverview&variables=%7B%22uri%22%3A%22spotify%3Aartist%3A${id}%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%22d66221ea13998b2f81883c5187d174c8646e4041d67f5b1e103bc262d447e3a0%22%7D%7D`, - { - headers: { - Authorization: `Bearer ${await getToken()}`, - }, - } - ) - .then((res) => res.json()) - .then((res) => res.data.artist); - // return Spicetify.CosmosAsync.get(`https://api-partner.spotify.com/pathfinder/v1/query?operationName=queryArtistOverview&variables=%7B%22uri%22%3A%22spotify%3Aartist%3A${id}%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%22d66221ea13998b2f81883c5187d174c8646e4041d67f5b1e103bc262d447e3a0%22%7D%7D`).then(res => res.data.artist) - } - - async function searchArt(name) { - return fetch(`https://api.spotify.com/v1/search?q="${name}"&type=artist&limit=2`, { - headers: { - Authorization: `Bearer ${await getToken()}`, - }, - }).then((res) => res.json()); - // return Spicetify.CosmosAsync.get(`https://api.spotify.com/v1/search?q="${name}"&type=artist&limit=2`) - } - - // Add fade animation on button click - function fadeAnimation(ele, anim = "fade-do") { - ele.classList.remove(anim); - ele.classList.add(anim); - setTimeout(() => { - ele.classList.remove(anim); - }, 800); - } - - // Utility function to add a observer with wait for element support - function addObserver(observer, selector, options) { - const ele = document.querySelector(selector); - if (!ele) { - setTimeout(() => { - addObserver(observer, selector, options); - }, 2000); - return; - } - observer.observe(ele, options); - } - - // Converting hex to rgb - function hexToRgb(hex) { - // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") - let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; - hex = hex.replace(shorthandRegex, function (m, r, g, b) { - return r + r + g + g + b + b; - }); - let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result ? `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}` : null; - } - - async function getImageAndLoad(meta) { - if (meta.artist_uri == null) return meta.image_xlarge_url; - let arUri = meta.artist_uri.split(":")[2]; - if (meta.artist_uri.split(":")[1] === "local") { - let res = await searchArt(meta.artist_name).catch((err) => console.error(err)); - arUri = res ? res.artists.items[0].id : ""; - } - let artistInfo = await getArtistInfo(arUri).catch((err) => console.error(err)); - return artistInfo?.visuals?.headerImage?.sources[0].url ?? meta.image_xlarge_url; - } - - // Set the timeout to show upnext or hide when song ends - let upnextTimer, - upNextShown = false; - - function updateUpNextShow() { - setTimeout(() => { - let timetogo = getShowTime(); - if (upnextTimer) { - clearTimeout(upnextTimer); - upnextTimer = 0; - } - if (timetogo < 10) { - if (!upNextShown || fsd_myUp.style.transform !== "translateX(0px)") { - updateUpNext(); - } - upNextShown = true; - } else { - fsd_myUp.style.transform = "translateX(600px)"; - upNextShown = false; - if (!Spicetify.Player.origin._state.isPaused) { - upnextTimer = setTimeout(() => { - updateUpNext(); - upNextShown = true; - }, timetogo); - } - } - }, 100); - } - - // Return the total time left to show the upnext timer - function getShowTime() { - let showBefore = CONFIG[ACTIVE].upnextTimeToShow * 1000; - let dur = Spicetify.Player.data.duration; - let curProg = Spicetify.Player.getProgress(); - - if (dur - curProg <= showBefore) return -1; - else return dur - showBefore - curProg; - } - - let colorsCache = []; - async function colorExtractor(uri) { - const presentInCache = colorsCache.filter(obj => obj.uri === uri) - if(presentInCache.length > 0) return presentInCache[0].colors; - const body = await Spicetify.CosmosAsync.get(`wg://colorextractor/v1/extract-presets?uri=${uri}&format=json`); - if (body.entries && body.entries.length) { - const list = {}; - for (const color of body.entries[0].color_swatches) { - list[color.preset] = `#${color.color.toString(16).padStart(6, "0")}`; - } - if(colorsCache.length > 20) colorsCache.shift(); - colorsCache.push({uri, colors: list}); - return list; - } - throw "No colors returned."; - } - - async function updateInfo() { - const meta = Spicetify.Player.data.track?.metadata; - - if (CONFIG[ACTIVE].contextDisplay !== "n") updateContext().catch((err) => console.error("Error getting context: ", err)); - - // prepare title - let rawTitle = meta?.title; - if (CONFIG[ACTIVE].trimTitle) { - rawTitle = rawTitle - .replace(/\(.+?\)/g, "") - .replace(/\[.+?\]/g, "") - .replace(/\s\-\s.+?$/, "") - .trim(); - if (!rawTitle) rawTitle = meta?.title; - } - - // prepare artist - let artistName; - if (CONFIG[ACTIVE].showAllArtists) { - artistName = Object.keys(meta) - .filter((key) => key.startsWith("artist_name")) - .sort() - .map((key) => meta[key]) - .join(", "); - } else { - artistName = meta?.artist_name; - } - - // prepare album - let albumText; - if (CONFIG[ACTIVE].showAlbum !== "n") { - albumText = meta?.album_title || ""; - if (album) album.innerText = albumText || ""; - const albumURI = meta?.album_uri; - if (albumURI?.startsWith("spotify:album:") && CONFIG[ACTIVE].showAlbum === "d") { - getAlbumInfo(albumURI.replace("spotify:album:", "")) - .then((albumInfo) => { - if (!albumInfo?.release_date) throw Error("No release Date"); - const albumDate = new Date(albumInfo.release_date); - const recentDate = new Date(); - recentDate.setMonth(recentDate.getMonth() - 18); - const dateStr = albumDate.toLocaleString( - LOCALE, - albumDate > recentDate ? { year: "numeric", month: "short" } : { year: "numeric" } - ); - albumText += " • " + dateStr.charAt(0).toUpperCase() + dateStr.slice(1); - if (album) album.innerText = albumText || ""; - }) - .catch((err) => console.error(err)); - } - } - - // prepare duration - let durationText; - if (CONFIG[ACTIVE].progressBarDisplay) { - durationText = Spicetify.Player.formatTime(meta?.duration); - } - const previousImg = nextTrackImg.cloneNode(); - - nextTrackImg.src = meta?.image_xlarge_url; - - // Wait until next track image is downloaded then update UI text and images - nextTrackImg.onload = async () => { - if (!CONFIG.tvMode) { - updateMainColor(Spicetify.Player.data.track?.uri, meta); - updateThemeColor(Spicetify.Player.data.track?.uri); - if (CONFIG.def.backgroundChoice == "a") { - animateCanvas(previousImg, nextTrackImg); - } else { - animateColor(await getNextColor()); - } - } - cover.style.backgroundImage = `url("${nextTrackImg.src}")`; - title.innerText = rawTitle || ""; - artist.innerText = artistName || ""; - if (durr) { - durr.innerText = durationText || ""; - } - new Image().src = Spicetify?.Queue?.nextTracks[0]?.contextTrack?.metadata.image_xlarge_url; - }; - nextTrackImg.onerror = () => { - // Placeholder - console.error("Check your Internet! Unable to load Image"); - nextTrackImg.src = OFFLINESVG; - }; - if (CONFIG.tvMode) { - artistImg.src = await getImageAndLoad(meta); - updateMainColor(artistImg.src, meta); - updateThemeColor(artistImg.src); - artistImg.onload = async () => { - back.style.backgroundImage = `url("${artistImg.src}")`; - let newurl = await getImageAndLoad(Spicetify?.Queue?.nextTracks[0]?.contextTrack?.metadata); - new Image().src = newurl; - }; - } - } - - async function getNextColor() { - let nextColor; - const imageColors = await colorExtractor(Spicetify.Player.data.track?.uri).catch((err) => console.warn(err)); - if (!imageColors || !imageColors[CONFIG.def.coloredBackChoice]) nextColor = "#444444"; - else nextColor = imageColors[CONFIG.def.coloredBackChoice]; - return nextColor; - } - async function updateMainColor(imageURL, meta) { - switch (CONFIG[ACTIVE].invertColors) { - case "a": - container.style.setProperty("--main-color", "0,0,0"); - container.style.setProperty("--contrast-color", "255,255,255"); - break; - case "d": - let mainColor, contrastColor; - if (!CONFIG.tvMode && CONFIG.def.backgroundChoice === "a" && meta.album_uri.split(":")[2] in INVERTED) { - mainColor = INVERTED[meta.album_uri.split(":")[2]] ? "0,0,0" : "255,255,255"; - } else { - let imageProminentColor; - const imageColors = await colorExtractor(imageURL).catch((err) => console.warn(err)); - if (CONFIG.tvMode || CONFIG.def.backgroundChoice == "a") { - if (!imageColors?.PROMINENT) imageProminentColor = "0,0,0"; - else imageProminentColor = hexToRgb(imageColors.PROMINENT); - } else { - if (!imageColors || !imageColors[CONFIG.def.coloredBackChoice]) imageProminentColor = hexToRgb("#444444"); - else imageProminentColor = hexToRgb(imageColors[CONFIG.def.coloredBackChoice]); - } - const thresholdValue = 260 - CONFIG[ACTIVE].backgroundBrightness * 100; - const isLightBG = - Number(imageProminentColor?.split(",")[0]) * 0.299 + - Number(imageProminentColor?.split(",")[1]) * 0.587 + - Number(imageProminentColor?.split(",")[2]) * 0.114 > - thresholdValue; - mainColor = isLightBG && CONFIG[ACTIVE].backgroundBrightness > 0.3 ? "0,0,0" : "255,255,255"; - contrastColor = isLightBG && CONFIG[ACTIVE].backgroundBrightness > 0.3 ? "255,255,255" : "0,0,0"; - } - container.style.setProperty("--main-color", mainColor); - container.style.setProperty("--contrast-color", contrastColor ?? "0,0,0"); - if (CONFIG[ACTIVE].extraControls) { - invertButton.classList.remove("button-active"); - invertButton.innerHTML = ``; - } - break; - case "n": - default: - container.style.setProperty("--main-color", "255,255,255"); - container.style.setProperty("--contrast-color", "0,0,0"); - break; - } - } - //Set main theme color for the display - async function updateThemeColor(imageURL) { - if ( - !(!CONFIG.tvMode && CONFIG.def.backgroundChoice == "c" && CONFIG.def.coloredBackChoice == "VIBRANT") && - (CONFIG[ACTIVE].themedButtons || CONFIG[ACTIVE].themedIcons) - ) { - container.classList.toggle("themed-buttons", !!CONFIG[ACTIVE].themedButtons); - container.classList.toggle("themed-icons", !!CONFIG[ACTIVE].themedIcons); - let themeVibrantColor; - const artColors = await colorExtractor(imageURL).catch((err) => console.warn(err)); - if (!artColors?.VIBRANT) themeVibrantColor = "175,175,175"; - else themeVibrantColor = hexToRgb(artColors.VIBRANT); - container.style.setProperty("--theme-color", themeVibrantColor); - } else { - container.classList.remove("themed-buttons", "themed-icons"); - container.style.setProperty("--theme-color", "175,175,175"); - } - } - - function handleLyricsUpdate(evt) { - if (evt.detail.isLoading) return; - container.classList.toggle("lyrics-unavailable", !(evt.detail.available && evt.detail?.synced?.length > 1)); - if (CONFIG[ACTIVE].extraControls) { - lyrics.classList.toggle("hidden", container.classList.contains("lyrics-unavailable")); - } - } - - let prevColor = "#000000"; - async function animateColor(nextColor) { - const configTransitionTime = CONFIG[ACTIVE].backAnimationTime; - const { innerWidth: width, innerHeight: height } = window; - back.width = width; - back.height = height; - - const ctx = back.getContext("2d"); - - if (!CONFIG[ACTIVE].enableFade) { - ctx.globalAlpha = 1; - ctx.fillStyle = nextColor; - ctx.fillRect(0, 0, width, height); - return; - } - - let previousTimeStamp, - done = false, - start; - const animate = (timestamp) => { - if (start === undefined) start = timestamp; - const elapsed = timestamp - start; - - if (previousTimeStamp !== timestamp) { - const factor = Math.min(elapsed / (configTransitionTime * 1000), 1.0); - ctx.globalAlpha = 1; - ctx.fillStyle = prevColor; - ctx.fillRect(0, 0, width, height); - ctx.globalAlpha = Math.sin((Math.PI / 2) * factor); - ctx.fillStyle = nextColor; - ctx.fillRect(0, 0, width, height); - if (factor === 1.0) done = true; - } - if (elapsed < configTransitionTime * 1000) { - previousTimeStamp = timestamp; - !done && requestAnimationFrame(animate); - } else { - prevColor = nextColor; - } - }; - - requestAnimationFrame(animate); - } - - function animateCanvas(prevImg, nextImg) { - const configTransitionTime = CONFIG[ACTIVE].backAnimationTime; - const { innerWidth: width, innerHeight: height } = window; - back.width = width; - back.height = height; - - const ctx = back.getContext("2d"); - ctx.imageSmoothingEnabled = false; - ctx.filter = `brightness(${CONFIG[ACTIVE].backgroundBrightness}) blur(${CONFIG[ACTIVE].blurSize}px)`; - const blur = CONFIG[ACTIVE].blurSize; - - const x = -blur * 2; - - let y, dim; - if (width > height) { - dim = width; - y = x - (width - height) / 2; - } else { - dim = height; - y = x; - } - const size = dim + 4 * blur; - - if (!CONFIG[ACTIVE].enableFade) { - ctx.globalAlpha = 1; - ctx.drawImage(nextImg, x, y, size, size); - return; - } - - let prevTimeStamp, - start, - done = false; - - const animate = (timestamp) => { - if (start === undefined) start = timestamp; - - const elapsed = timestamp - start; - - if (prevTimeStamp !== timestamp) { - const factor = Math.min(elapsed / (configTransitionTime * 1000), 1.0); - ctx.globalAlpha = 1; - ctx.drawImage(prevImg, x, y, size, size); - ctx.globalAlpha = Math.sin((Math.PI / 2) * factor); - ctx.drawImage(nextImg, x, y, size, size); - if (factor === 1.0) done = true; - } - if (elapsed < configTransitionTime * 1000) { - prevTimeStamp = timestamp; - !done && requestAnimationFrame(animate); - } - }; - - requestAnimationFrame(animate); - } - - let prevUriObj; - async function getContext() { - let ctxIcon = "", - ctxSource, - ctxName; - if (Spicetify.Player.data.track?.provider === "queue") { - ctxIcon = ``; - ctxSource = translations[LOCALE].context.queue; - ctxName = ""; - } else { - const uriObj = Spicetify.URI.fromString(Spicetify.Player.data.context_uri); - if (JSON.stringify(uriObj) === JSON.stringify(prevUriObj) && ctxSource != undefined && ctxName != undefined) - return [ctxIcon, ctxSource, ctxName]; - prevUriObj = uriObj; - switch (uriObj.type) { - case Spicetify.URI.Type.TRACK: - ctxIcon = ``; - ctxSource = translations[LOCALE].context.track; - await getTrackInfo(uriObj._base62Id).then((meta) => (ctxName = `${meta.name} • ${meta.artists[0].name}`)); - break; - case Spicetify.URI.Type.SEARCH: - ctxIcon = Spicetify.SVGIcons["search-active"]; - ctxSource = translations[LOCALE].context.search; - ctxName = `"${uriObj.query}" in ${translations[LOCALE].context.searchDest}`; - break; - case Spicetify.URI.Type.COLLECTION: - ctxIcon = Spicetify.SVGIcons["heart-active"]; - ctxSource = translations[LOCALE].context.collection; - ctxName = translations[LOCALE].context.likedSongs; - break; - case Spicetify.URI.Type.PLAYLIST_V2: - ctxIcon = Spicetify.SVGIcons["playlist"]; - ctxSource = translations[LOCALE].context.playlist; - ctxName = Spicetify.Player.data.context_metadata?.context_description || ""; - break; - - case Spicetify.URI.Type.STATION: - case Spicetify.URI.Type.RADIO: - ctxIcon = ``; - const rType = uriObj.args[0]; - switch (rType) { - case "album": - ctxSource = translations[LOCALE].context.albumRadio; - await getAlbumInfo(uriObj.args[1]).then((meta) => (ctxName = meta.name)); - break; - case "track": - ctxSource = translations[LOCALE].context.trackRadio; - await getTrackInfo(uriObj.args[1]).then((meta) => (ctxName = `${meta.name} • ${meta.artists[0].name}`)); - break; - case "artist": - ctxSource = translations[LOCALE].context.artistRadio; - await getArtistInfo(uriObj.args[1]).then((meta) => (ctxName = meta?.profile?.name)); - break; - case "playlist": - case "playlist-v2": - ctxSource = translations[LOCALE].context.playlistRadio; - ctxIcon = ``; - await getPlaylistInfo("spotify:playlist:" + uriObj.args[1]).then((meta) => (ctxName = meta.playlist.name)); - break; - default: - ctxName = ""; - } - break; - - case Spicetify.URI.Type.PLAYLIST: - ctxIcon = Spicetify.SVGIcons[uriObj.type]; - ctxSource = translations[LOCALE].context.playlist; - ctxName = Spicetify.Player.data.context_metadata.context_description || ""; - break; - case Spicetify.URI.Type.ALBUM: - ctxIcon = Spicetify.SVGIcons[uriObj.type]; - ctxSource = translations[LOCALE].context.album; - ctxName = Spicetify.Player.data.context_metadata.context_description || ""; - break; - - case Spicetify.URI.Type.ARTIST: - ctxIcon = Spicetify.SVGIcons[uriObj.type]; - ctxSource = translations[LOCALE].context.artist; - ctxName = Spicetify.Player.data.context_metadata.context_description || ""; - break; - - case Spicetify.URI.Type.FOLDER: - ctxIcon = Spicetify.SVGIcons["playlist-folder"]; - ctxSource = translations[LOCALE].context.playlistFolder; - const res = await Spicetify.CosmosAsync.get(`sp://core-playlist/v1/rootlist`, { - policy: { folder: { rows: true, link: true, name: true } }, - }); - for (const item of res.rows) { - if (item.type === "folder" && item.link === Spicetify.Player.data.context_uri) { - ctxName = item.name; - break; - } - } - break; - default: - ctxSource = uriObj.type; - ctxName = Spicetify.Player.data?.context_metadata?.context_description || ""; - } - } - return [ctxIcon, ctxSource, ctxName]; - } - - // Get the context and update it - async function updateContext() { - let ctxIcon, ctxSource, ctxName; - [ctxIcon, ctxSource, ctxName] = await getContext().catch((err) => console.error(err)); - ctx_source.classList.toggle("ctx-no-name", !ctxName); - - //Set default icon if no icon is returned - if (!ctxIcon) ctxIcon = Spicetify.SVGIcons.spotify; - ctx_icon.innerHTML = /^${ctxIcon}` - : ctxIcon; - - //Only change the DOM if context is changed - if (ctx_source.innerText.toLowerCase() !== `${ctxSource}`.toLowerCase() || ctx_name.innerText.toLowerCase() !== ctxName.toLowerCase()) { - ctx_source.innerText = `${ctxSource}`; - ctx_name.innerText = ctxName; - if (CONFIG[ACTIVE].contextDisplay === "m") hideContext(); - } - } - - function updateUpNextInfo() { - fsd_up_next_text.innerText = translations[LOCALE].upnext.toUpperCase(); - let metadata = {}; - const queue_metadata = Spicetify.Queue.nextTracks[0]; - if (queue_metadata) { - metadata = queue_metadata?.contextTrack?.metadata; - } else { - metadata["artist_name"] = ""; - metadata["title"] = ""; - } - - let rawTitle = metadata.title; - if (CONFIG[ACTIVE].trimTitleUpNext) { - rawTitle = rawTitle - .replace(/\(.+?\)/g, "") - .replace(/\[.+?\]/g, "") - .replace(/\s\-\s.+?$/, "") - .trim(); - if (!rawTitle) rawTitle = metadata.title; - } - const artistNameNext = Object.keys(metadata) - .filter((key) => key.startsWith("artist_name")) - .sort() - .map((key) => metadata[key]) - .join(", "); - - let next_artist; - if (artistNameNext) { - next_artist = artistNameNext; - } else { - next_artist = translations[LOCALE].unknownArtist; - } - const next_image = metadata.image_xlarge_url; - if (next_image) { - fsd_nextCover.style.backgroundImage = `url("${next_image}")`; - } else { - if (metadata.image_url) fsd_nextCover.style.backgroundImage = `url("${metadata.image_url}")`; - else { - fsd_nextCover.style.backgroundImage = `url("${OFFLINESVG}")`; - } - } - fsd_first_span.innerText = rawTitle + " • " + next_artist; - fsd_second_span.innerText = rawTitle + " • " + next_artist; - } - - async function updateUpNext() { - if ( - Spicetify.Player.data.duration - Spicetify.Player.getProgress() <= CONFIG[ACTIVE].upnextTimeToShow * 1000 + 50 && - Spicetify.Queue?.nextTracks[0]?.contextTrack?.metadata?.title - ) { - await updateUpNextInfo(); - fsd_myUp.style.transform = "translateX(0px)"; - upNextShown = true; - let animTime; - if (fsd_second_span.offsetWidth > fsd_next_tit_art.offsetWidth - 2) { - switch (CONFIG[ACTIVE].upNextAnim) { - case "mq": - fsd_first_span.style.paddingRight = "80px"; - animTime = 5000 * (fsd_first_span.offsetWidth / 400); - fsd_myUp.style.setProperty("--translate_width_fsd", `-${fsd_first_span.offsetWidth + 3.5}px`); - fsd_next_tit_art_inner.style.animation = "fsd_cssmarquee " + animTime + "ms linear 800ms infinite"; - break; - case "sp": - default: - fsd_first_span.style.paddingRight = "0px"; - fsd_second_span.innerText = ""; - animTime = (fsd_first_span.offsetWidth - fsd_next_tit_art.offsetWidth - 2) / 0.05; - // animTime= 3000*(fsd_first_span.offsetWidth/fsd_next_tit_art.offsetWidth) - fsd_myUp.style.setProperty("--translate_width_fsd", `-${fsd_first_span.offsetWidth - fsd_next_tit_art.offsetWidth + 5}px`); - fsd_next_tit_art_inner.style.animation = `fsd_translate ${animTime > 1500 ? animTime : 1500}ms linear 800ms infinite`; - break; - } - } else { - fsd_first_span.style.paddingRight = "0px"; - fsd_next_tit_art_inner.style.animation = "none"; - fsd_second_span.innerText = ""; - } - } else { - upNextShown = false; - fsd_myUp.style.transform = "translateX(600px)"; - fsd_first_span.style.paddingRight = "0px"; - fsd_next_tit_art_inner.style.animation = "none"; - fsd_second_span.innerText = ""; - } - } - - let prevVolume = Spicetify.Player?.origin?._volume?._volume ?? Spicetify.Platform?.PlaybackAPI?._volume; - - function updateVolume(data) { - const volume = !data ? Spicetify.Player?.origin?._volume?._volume ?? Spicetify.Platform?.PlaybackAPI?._volume : data.data.volume; - if (volume !== prevVolume || !data) { - //Only update volume when there is a change or on initial fire - prevVolume = volume; - if (CONFIG[ACTIVE].volumeDisplay === "o" || CONFIG[ACTIVE].volumeDisplay === "m") { - volumeContainer.classList.remove("v-hidden"); - } - volumeBarInner.style.height = volume * 100 + "%"; - let currVol = Math.round(volume * 100) === -100 ? "%" : Math.round(volume * 100); - volumeCurr.innerText = currVol + "%"; - volumeContainer.classList.toggle("unavailable", typeof currVol !== "number"); - if (typeof currVol !== "number" || currVol > 60) - volumeIcon.innerHTML = `${Spicetify.SVGIcons["volume"]}`; - else if (currVol > 30) - volumeIcon.innerHTML = `${Spicetify.SVGIcons["volume-two-wave"]}`; - else if (currVol > 0) - volumeIcon.innerHTML = `${Spicetify.SVGIcons["volume-one-wave"]}`; - else - volumeIcon.innerHTML = `${Spicetify.SVGIcons["volume-off"]}`; - if (CONFIG[ACTIVE].volumeDisplay === "o" || CONFIG[ACTIVE].volumeDisplay === "m") { - hideVolume(); - } - } - } - - function updateProgress() { - const progress = Spicetify.Player.formatTime(Spicetify.Player.getProgress()); - if (!Spicetify.Player.origin._state.isPaused || elaps.innerText !== progress) { - prog.style.width = Spicetify.Player.getProgressPercent() * 100 + "%"; - elaps.innerText = progress; - } - } - - function updatePlayingIcon({ data }) { - if (data.is_paused) { - pausedIcon.classList.remove("hidden"); - playingIcon.classList.add("hidden"); - } else { - pausedIcon.classList.toggle("hidden", CONFIG[ACTIVE].titleMovingIcon); - playingIcon.classList.toggle("hidden", !CONFIG[ACTIVE].titleMovingIcon); - } - } - - function updatePlayerControls({ data }) { - fadeAnimation(play); - if (data.is_paused) { - play.innerHTML = `${Spicetify.SVGIcons.play}`; - } else { - play.innerHTML = `${Spicetify.SVGIcons.pause}`; - } - } - - let prevControlData = { - shuffle: Spicetify?.Player?.origin?._state?.shuffle, - repeat: Spicetify?.Player?.origin?._state?.repeat, - }; - - function updateExtraControls(data) { - data = !data ? Spicetify.Player.origin._state : data.data; - updateHeart(); - if (prevControlData?.shuffle !== data?.shuffle) fadeAnimation(shuffle); - if (prevControlData?.repeat !== data?.repeat) fadeAnimation(repeat); - prevControlData = { - shuffle: data?.shuffle, - repeat: data?.repeat, - }; - repeat.classList.toggle("dot-after", data?.repeat !== 0); - repeat.classList.toggle("button-active", data?.repeat !== 0); - - shuffle.classList.toggle("dot-after", data?.shuffle); - shuffle.classList.toggle("button-active", data?.shuffle); - if (data?.repeat === 2) { - repeat.innerHTML = `${Spicetify.SVGIcons["repeat-once"]}`; - } else { - repeat.innerHTML = `${Spicetify.SVGIcons["repeat"]}`; - } - if (data.restrictions) { - shuffle.classList.toggle("unavailable", !data?.restrictions?.canToggleShuffle); - repeat.classList.toggle("unavailable", !data?.restrictions?.canToggleRepeatTrack && !data?.restrictions?.canToggleRepeatContext); - } - } - - let prevHeartData = Spicetify?.Player?.origin?._state?.item?.metadata["collection.in_collection"]; - - function updateHeart() { - const meta = Spicetify?.Player?.origin?._state?.item; - heart.classList.toggle("unavailable", meta?.metadata["collection.can_add"] !== "true"); - if (prevHeartData !== meta?.metadata["collection.in_collection"]) fadeAnimation(heart); - prevHeartData = meta?.metadata["collection.in_collection"]; - if (meta?.metadata["collection.in_collection"] === "true" || Spicetify.Player.getHeart()) { - heart.innerHTML = `${Spicetify.SVGIcons["heart-active"]}`; - heart.classList.add("button-active"); - } else { - heart.innerHTML = `${Spicetify.SVGIcons["heart"]}`; - heart.classList.remove("button-active"); - } - } - - let curTimer, ctxTimer, volTimer; - - function hideCursor() { - if (curTimer) { - clearTimeout(curTimer); - curTimer = 0; - } - container.style.cursor = "default"; - curTimer = setTimeout(() => (container.style.cursor = "none"), 2000); - } - - function hideContext() { - if (ctxTimer) { - clearTimeout(ctxTimer); - ctxTimer = 0; - } - ctx_container.style.opacity = 1; - ctxTimer = setTimeout(() => (ctx_container.style.opacity = 0), 3000); - } - - function hideVolume() { - if (volTimer) { - clearTimeout(volTimer); - volTimer = 0; - } - volumeContainer.classList.remove("v-hidden"); - volTimer = setTimeout(() => volumeContainer.classList.add("v-hidden"), 3000); - } - - let origLoc, progressListener; - const heartObserver = new MutationObserver(updateHeart); - - function activate() { - container.style.setProperty("--fs-transition", `${CONFIG[ACTIVE].backAnimationTime}s`); - updateInfo(); - Spicetify.Player.addEventListener("songchange", updateInfo); - container.addEventListener("mousemove", hideCursor); - hideCursor(); - container.querySelector("#fsd-foreground").oncontextmenu = openConfig; - container.querySelector("#fsd-foreground").ondblclick = deactivate; - back.oncontextmenu = openConfig; - back.ondblclick = deactivate; - if (CONFIG[ACTIVE].contextDisplay === "m") { - container.addEventListener("mousemove", hideContext); - hideContext(); - } - if (CONFIG[ACTIVE].upnextDisplay) { - updateUpNextShow(); - Spicetify.Player.origin._events.addListener("queue_update", updateUpNext); - Spicetify.Player.origin._events.addListener("update", updateUpNextShow); - window.addEventListener("resize", updateUpNext); - } - if (CONFIG[ACTIVE].volumeDisplay !== "n") { - if (Spicetify.Platform?.PlaybackAPI === undefined) Spicetify.Player.origin._events.addListener("volume", updateVolume); - else Spicetify.Platform.PlaybackAPI._events.addListener("volume", updateVolume); - updateVolume(); - if (CONFIG[ACTIVE].volumeDisplay === "m") { - container.addEventListener("mousemove", hideVolume); - hideVolume(); - } - } - if (CONFIG[ACTIVE].enableFade) { - cover.classList.add("fsd-background-fade"); - if (CONFIG.tvMode) back.classList.add("fsd-background-fade"); - } else { - cover.classList.remove("fsd-background-fade"); - if (CONFIG.tvMode) back.classList.remove("fsd-background-fade"); - } - if (CONFIG[ACTIVE].icons) { - updatePlayingIcon({ data: { is_paused: !Spicetify.Player.isPlaying() } }); - Spicetify.Player.addEventListener("onplaypause", updatePlayingIcon); - } - if (CONFIG[ACTIVE].progressBarDisplay) { - updateProgress(); - progressListener = setInterval(updateProgress, 500); - } - if (CONFIG[ACTIVE].playerControls) { - updatePlayerControls({ data: { is_paused: !Spicetify.Player.isPlaying() } }); - Spicetify.Player.addEventListener("onplaypause", updatePlayerControls); - } - if (CONFIG[ACTIVE].extraControls) { - updateExtraControls(); - addObserver(heartObserver, ".control-button-heart", { attributes: true, attributeFilter: ["aria-checked"] }); - Spicetify.Player.origin._events.addListener("update", updateExtraControls); - } - document.body.classList.add(...classes); - if (CONFIG[ACTIVE].enableFullscreen) fullScreenOn(); - else fullScreenOff(); - document.querySelector(".Root__top-container")?.append(style, container); - if (CONFIG[ACTIVE].lyricsDisplay) { - window.addEventListener("lyrics-plus-update", handleLyricsUpdate); - origLoc = Spicetify.Platform.History.location.pathname; - if (origLoc !== "/lyrics-plus") { - Spicetify.Platform.History.push("/lyrics-plus"); - } - window.dispatchEvent(new Event("fad-request")); - } - Spicetify.Keyboard.registerShortcut( - { - key: Spicetify.Keyboard.KEYS["F11"], - ctrl: false, - shift: false, - alt: false, - }, - fsToggle - ); - Spicetify.Keyboard.registerShortcut( - { - key: Spicetify.Keyboard.KEYS["ESCAPE"], - ctrl: false, - shift: false, - alt: false, - }, - deactivate - ); - } - - function deactivate() { - Spicetify.Player.removeEventListener("songchange", updateInfo); - container.removeEventListener("mousemove", hideCursor); - if (CONFIG[ACTIVE].contextDisplay === "m") { - container.removeEventListener("mousemove", hideContext); - } - if (CONFIG[ACTIVE].upnextDisplay) { - upNextShown = false; - Spicetify.Player.origin._events.removeListener("queue_update", updateUpNext); - Spicetify.Player.origin._events.removeListener("update", updateUpNextShow); - window.removeEventListener("resize", updateUpNext); - } - if (CONFIG[ACTIVE].volumeDisplay !== "n") { - if (Spicetify.Platform?.PlaybackAPI === undefined) Spicetify.Player.origin._events.removeListener("volume", updateVolume); - else Spicetify.Platform.PlaybackAPI._events.removeListener("volume", updateVolume); - if (CONFIG[ACTIVE].volumeDisplay === "m") container.removeEventListener("mousemove", hideVolume); - } - if (CONFIG[ACTIVE].progressBarDisplay) { - clearInterval(progressListener); - } - if (CONFIG[ACTIVE].icons) { - Spicetify.Player.removeEventListener("onplaypause", updatePlayingIcon); - } - if (CONFIG[ACTIVE].playerControls) { - Spicetify.Player.removeEventListener("onplaypause", updatePlayerControls); - } - if (CONFIG[ACTIVE].extraControls) { - heartObserver.disconnect(); - Spicetify.Player.origin._events.removeListener("update", updateExtraControls); - } - document.body.classList.remove(...classes); - upNextShown = false; - if (CONFIG[ACTIVE].enableFullscreen) { - fullScreenOff(); - } - let popup = document.querySelector("body > generic-modal"); - if (popup) popup.remove(); - style.remove(); - container.remove(); - if (CONFIG[ACTIVE].lyricsDisplay) { - window.removeEventListener("lyrics-plus-update", handleLyricsUpdate); - if (origLoc !== "/lyrics-plus") { - Spicetify.Platform.History.push(origLoc); - Spicetify.Platform.History.entries.splice(Spicetify.Platform.History.entries.length - 3, 2); - Spicetify.Platform.History.index = Spicetify.Platform.History.index > 0 ? Spicetify.Platform.History.index - 2 : -1; - Spicetify.Platform.History.length = Spicetify.Platform.History.length > 1 ? Spicetify.Platform.History.length - 2 : 0; - } - window.dispatchEvent(new Event("fad-request")); - } - Spicetify.Keyboard._deregisterShortcut({ - key: Spicetify.Keyboard.KEYS["F11"], - ctrl: false, - shift: false, - alt: false, - }); - Spicetify.Keyboard._deregisterShortcut({ - key: Spicetify.Keyboard.KEYS["ESCAPE"], - ctrl: false, - shift: false, - alt: false, - }); - } - - function fsToggle() { - if (CONFIG[ACTIVE].enableFullscreen) { - CONFIG[ACTIVE]["enableFullscreen"] = false; - saveConfig(); - render(); - activate(); - } else { - CONFIG[ACTIVE]["enableFullscreen"] = true; - saveConfig(); - render(); - activate(); - } - } - - function getAvailableLanguages(translations) { - let languages = {}; - for (const lang in translations) { - languages[lang] = translations[lang].langName; - } - return languages; - } - - /** - * Merges keys from one object into another recursively. - */ - function mergeDefaultsInConfig(defaultObject, objectToMergeIn) { - Object.keys(defaultObject).forEach((key) => { - if (objectToMergeIn[key] === undefined) { - objectToMergeIn[key] = defaultObject[key]; - } else { - if (typeof defaultObject[key] === "object") { - mergeDefaultsInConfig(defaultObject[key], objectToMergeIn[key]); - } - } - }); - } - function getConfig() { - try { - const parsed = JSON.parse(localStorage.getItem("full-screen-config") ?? "{}"); - if (!!parsed && typeof parsed === "object") { - // mergeDefaultsInConfig(DEFAULTS, parsed); - Object.keys(DEFAULTS).forEach((key) => { - if (parsed[key] === undefined) { - parsed[key] = DEFAULTS[key]; - } else { - if (typeof DEFAULTS[key] === "object") { - Object.keys(DEFAULTS[key]) - .filter((subkey) => parsed[key][subkey] === undefined) - .forEach((subkey) => { - parsed[key][subkey] = DEFAULTS[key][subkey]; - }); - } - } - }); - localStorage.setItem("full-screen-config", JSON.stringify(parsed)); - return parsed; - } - throw ""; - } catch { - localStorage.setItem("full-screen-config", JSON.stringify(DEFAULTS)); - return DEFAULTS; - } - } - - function saveConfig() { - localStorage.setItem("full-screen-config", JSON.stringify(CONFIG)); - } - - function saveOption(key, value) { - CONFIG[ACTIVE][key] = value; - saveConfig(); - render(); - if (document.body.classList.contains("fsd-activated")) activate(); - } - - // Saves an option independent from TV or Fullscreen mode - function saveGlobalOption(key, value) { - CONFIG[key] = value; - LOCALE = CONFIG.locale; // Update locale (avoids reloading client to apply setting) - saveConfig(); - render(); - if (document.body.classList.contains("fsd-activated")) activate(); - } - - function createAdjust(name, key, unit = "", defaultValue, step, min, max, onChange = (val) => {}) { - let value = key in CONFIG[ACTIVE] ? CONFIG[ACTIVE][key] : defaultValue; - - function adjustValue(dir) { - let temp = value + dir * step; - if (temp < min) { - temp = min; - } else if (temp > max) { - temp = max; - } - value = Number(Number(temp).toFixed(step >= 1 ? 0 : 1)); - container.querySelector(".adjust-value").innerText = `${value}${unit}`; - plus && plus.classList.toggle("disabled", value === max); - minus && minus.classList.toggle("disabled", value === min); - onChange(value); - } - const container = document.createElement("div"); - container.innerHTML = ` -
- -
- -

${value}${unit}

- -
-
- `; - const minus = container.querySelector(".minus"); - const plus = container.querySelector(".plus"); - minus && minus.classList.toggle("disabled", value === min); - plus && plus.classList.toggle("disabled", value === max); - minus && (minus.onclick = () => adjustValue(-1)); - plus && (plus.onclick = () => adjustValue(1)); - return container; - } - - function createOptions(name, options, defaultValue, callback) { - const container = document.createElement("div"); - container.innerHTML = ` -
- -
- -
-
`; - const select = container.querySelector("select"); - select && (select.value = defaultValue); - select && (select.onchange = (e) => { - callback(e?.target?.value); - }); - return container; - } - - function createToggle(name, key, callback = (a,b) => {}) { - const container = document.createElement("div"); - container.innerHTML = ` -
- -
- -
-
`; - - const toggle = container.querySelector("input"); - toggle && (toggle.checked = CONFIG[ACTIVE][key]); - toggle && (toggle.onchange = (evt) => { - CONFIG[ACTIVE][key] = evt?.target?.checked; - saveConfig(); - render(); - callback(container, evt?.target?.checked); - if (document.body.classList.contains("fsd-activated")) { - activate(); - } - }); - return container; - } - - function headerText(text, subtext = "") { - const container = document.createElement("div"); - container.classList.add("subhead"); - const listHeader = document.createElement("h2"); - listHeader.innerText = text; - container.append(listHeader); - if (subtext) { - const listSub = document.createElement("i"); - listSub.innerText = "(" + subtext + ")"; - container.append(listSub); - } - return container; - } - let configContainer; - - function openConfig(evt) { - evt?.preventDefault(); - configContainer = document.createElement("div"); - configContainer.id = "full-screen-config-container"; - const style = document.createElement("style"); - style.innerHTML = ` - .GenericModal ::-webkit-scrollbar{ - width: 7px; - } - .GenericModal ::-webkit-scrollbar-thumb{ - border-radius: 2rem; - } - .main-trackCreditsModal-container{ - height: 75vh; - max-height: 600px; - width: clamp(500px,50vw,600px); - } - .setting-row::after { - content: ""; - display: table; - clear: both; - } - .setting-row-but{ - display: flex; - align-items: center; - justify-content: center; - } - .subhead{ - text-align: center; - padding: 5px 0; - } - .setting-row-but button{ - margin: 5px 10px; - } - .setting-row .col { - display: flex; - padding: 10px 0; - align-items: center; - } - .setting-row .col.description { - float: left; - padding-right: 15px; - } - .setting-row .col.action { - float: right; - text-align: right; - } - .switch { - position: relative; - display: inline-block; - width: 44px; - height: 20px; - } - .switch input { - opacity: 0; - width: 0; - height: 0; - } - .slider { - position: absolute; - cursor: pointer; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(150,150,150,.5); - transition: all .3s ease-in-out; - border-radius: 34px; - } - .slider:before { - position: absolute; - content: ""; - height: 24px; - width: 24px; - left: -2px; - bottom: -2px; - background-color: #EEE; - transition: all .3s ease-in-out; - border-radius: 50%; - } - input:checked + .slider { - background-color: rgba(var(--spice-rgb-button-disabled),.6); - } - input:focus + .slider { - box-shadow: 0 0 1px rgba(var(--spice-rgb-button-disabled),.6); - } - input:checked + .slider:before { - transform: translateX(24px); - background-color: var(--spice-button); - filter: brightness(1.1) saturate(1.2); - } - #full-screen-config-container select { - color: var(--spice-text); - background: var(--spice-card); - border: none; - height: 32px; - } - #full-screen-config-container option { - color: var(--spice-text); - background: var(--spice-card); - } - button.switch { - align-items: center; - border: 0px; - border-radius: 50%; - background-color: rgba(var(--spice-rgb-shadow), 0.7); - color: var(--spice-text); - cursor: pointer; - margin-inline-start: 12px; - padding: 8px; - width: 32px; - height: 32px; - } - button.switch.disabled, - button.switch[disabled] { - color: rgba(var(--spice-rgb-text), 0.3); - pointer-events: none; - } - button.switch.small { - width: 22px; - height: 22px; - padding: 3px; - } - .main-buttons-button{ - border: 2px solid transparent; - border-radius: 500px; - color: var(--spice-text); - cursor: pointer; - display: inline-block; - font-size: 12px; - font-weight: 700; - letter-spacing: 1.76px; - line-height: 18px; - padding: 8px 34px; - text-align: center; - text-transform: uppercase; - -webkit-transition: all 33ms cubic-bezier(.3,0,0,1); - transition: all 33ms cubic-bezier(.3,0,0,1); - white-space: nowrap; - will-change: transform; - } - .main-button-primary{ - background-color: var(--spice-button); - } - .main-button-secondary{ - background-color: transparent; - color: var(--spice-button); - border: 2px solid var(--spice-button); - } - #full-screen-config-container .adjust-value { - margin-inline: 12px; - width: 22px; - text-align: center; - } - `; - configContainer.append( - style, - (() => { - const container = document.createElement("div"); - container.innerHTML = ` -
- - -
`; - container.querySelector("#mode-exit").onclick = deactivate; - container.querySelector("#mode-switch").onclick = () => { - CONFIG.tvMode ? openwithDef() : openwithTV(); - document.querySelector("body > generic-modal")?.remove(); - }; - return document.body.classList.contains("fsd-activated") ? container : ""; - })(), - - headerText(translations[LOCALE].settings.pluginSettings), - createOptions(translations[LOCALE].settings.language, getAvailableLanguages(translations), CONFIG["locale"], (value) => - saveGlobalOption("locale", value) - ), - - headerText(translations[LOCALE].settings.lyricsHeader), - createToggle(translations[LOCALE].settings.lyrics, "lyricsDisplay", (row, status) => { - container.classList.remove("lyrics-unavailable"); - let nextEle = row.nextElementSibling; - while (!nextEle.classList.contains("subhead")) { - nextEle.classList.toggle("hidden", !status); - nextEle = nextEle.nextElementSibling; - } - }), - createOptions( - translations[LOCALE].settings.lyricsAlignment.setting, - { - left: translations[LOCALE].settings.lyricsAlignment.left, - center: translations[LOCALE].settings.lyricsAlignment.center, - right: translations[LOCALE].settings.lyricsAlignment.right, - }, - CONFIG[ACTIVE].lyricsAlignment, - (value) => saveOption("lyricsAlignment", value) - ), - createAdjust(translations[LOCALE].settings.lyricsAnimationTempo, "animationTempo", "s", 0.3, 0.1, 0, 1, (state) => { - CONFIG[ACTIVE]["animationTempo"] = state; - saveConfig(); - render(); - if (document.body.classList.contains("fsd-activated")) activate(); - }), - headerText(translations[LOCALE].settings.generalHeader), - createToggle(translations[LOCALE].settings.progressBar, "progressBarDisplay"), - createToggle(translations[LOCALE].settings.playerControls, "playerControls"), - createToggle(translations[LOCALE].settings.trimTitle, "trimTitle"), - createToggle(translations[LOCALE].settings.trimTitleUpNext, "trimTitleUpNext"), - createOptions( - translations[LOCALE].settings.showAlbum.setting, - { - n: translations[LOCALE].settings.showAlbum.never, - a: translations[LOCALE].settings.showAlbum.always, - d: translations[LOCALE].settings.showAlbum.date, - }, - CONFIG[ACTIVE].showAlbum, - (value) => saveOption("showAlbum", value) - ), - createToggle(translations[LOCALE].settings.showAllArtists, "showAllArtists"), - createToggle(translations[LOCALE].settings.icons, "icons"), - createToggle(translations[LOCALE].settings.songChangeAnimation, "enableFade"), - document.fullscreenEnabled ? createToggle(translations[LOCALE].settings.fullscreen, "enableFullscreen") : "", - headerText(translations[LOCALE].settings.extraHeader), - ACTIVE !== "tv" - ? createOptions( - translations[LOCALE].settings.backgroundChoice.setting, - { - c: translations[LOCALE].settings.backgroundChoice.color, - a: translations[LOCALE].settings.backgroundChoice.artwork, - }, - CONFIG.def.backgroundChoice, - (value) => saveOption("backgroundChoice", value) - ) - : "", - createToggle(translations[LOCALE].settings.extraControls, "extraControls"), - createToggle(translations[LOCALE].settings.upnextDisplay, "upnextDisplay"), - createOptions( - translations[LOCALE].settings.contextDisplay.setting, - { - n: translations[LOCALE].settings.contextDisplay.never, - m: translations[LOCALE].settings.contextDisplay.mouse, - a: translations[LOCALE].settings.contextDisplay.always, - }, - CONFIG[ACTIVE].contextDisplay, - (value) => saveOption("contextDisplay", value) - ), - createOptions( - translations[LOCALE].settings.volumeDisplay.setting, - { - a: translations[LOCALE].settings.volumeDisplay.always, - n: translations[LOCALE].settings.volumeDisplay.never, - m: translations[LOCALE].settings.volumeDisplay.mouse, - o: translations[LOCALE].settings.volumeDisplay.volume, - }, - CONFIG[ACTIVE].volumeDisplay, - (value) => saveOption("volumeDisplay", value) - ), - headerText(translations[LOCALE].settings.appearanceHeader, translations[LOCALE].settings.appearanceSubHeader), - ACTIVE !== "tv" - ? createOptions( - translations[LOCALE].settings.backgroundColor.setting, - { - VIBRANT: translations[LOCALE].settings.backgroundColor.vibrant, - PROMINENT: translations[LOCALE].settings.backgroundColor.prominent, - DESATURATED: translations[LOCALE].settings.backgroundColor.desaturated, - LIGHT_VIBRANT: translations[LOCALE].settings.backgroundColor.lightVibrant, - DARK_VIBRANT: translations[LOCALE].settings.backgroundColor.darkVibrant, - VIBRANT_NON_ALARMING: translations[LOCALE].settings.backgroundColor.vibrantNonAlarming, - }, - CONFIG.def.coloredBackChoice, - (value) => saveOption("coloredBackChoice", value) - ) - : "", - createToggle(translations[LOCALE].settings.themedButtons, "themedButtons"), - createToggle(translations[LOCALE].settings.themedIcons, "themedIcons"), - createOptions( - translations[LOCALE].settings.invertColors.setting, - { - n: translations[LOCALE].settings.invertColors.never, - a: translations[LOCALE].settings.invertColors.always, - d: translations[LOCALE].settings.invertColors.auto, - }, - CONFIG[ACTIVE].invertColors, - (value) => saveOption("invertColors", value) - ), - createAdjust(translations[LOCALE].settings.backAnimationTime, "backAnimationTime", "s", 0.8, 0.1, 0, 5, (state) => { - CONFIG[ACTIVE]["backAnimationTime"] = state; - saveConfig(); - render(); - if (document.body.classList.contains("fsd-activated")) activate(); - }), - createOptions( - translations[LOCALE].settings.upnextScroll.setting, - { - mq: translations[LOCALE].settings.upnextScroll.mq, - sp: translations[LOCALE].settings.upnextScroll.sp, - }, - CONFIG[ACTIVE].upNextAnim, - (value) => saveOption("upNextAnim", value) - ), - createAdjust(translations[LOCALE].settings.upnextTime, "upnextTimeToShow", "s", 30, 1, 5, 60, (state) => { - CONFIG[ACTIVE]["upnextTimeToShow"] = state; - saveConfig(); - updateUpNextShow(); - // render() - // if (document.body.classList.contains('fsd-activated')) - // activate() - }), - createAdjust(translations[LOCALE].settings.backgroundBlur, "blurSize", "px", 20, 4, 0, 100, (state) => { - CONFIG[ACTIVE]["blurSize"] = state; - saveConfig(); - render(); - if (document.body.classList.contains("fsd-activated")) activate(); - }), - createOptions( - translations[LOCALE].settings.backgroundBrightness, - { - 0: "0%", - 0.1: "10%", - 0.2: "20%", - 0.3: "30%", - 0.4: "40%", - 0.5: "50%", - 0.6: "60%", - 0.7: "70%", - 0.8: "80%", - 0.9: "90%", - 1: "100%", - }, - CONFIG[ACTIVE].backgroundBrightness, - (value) => saveOption("backgroundBrightness", Number(value)) - ), - (() => { - const container = document.createElement("div"); - container.innerHTML = ` -
- - -
`; - container.querySelector("#reset-switch").onclick = () => { - CONFIG[ACTIVE] = DEFAULTS[ACTIVE]; - saveConfig(); - render(); - if (document.body.classList.contains("fsd-activated")) { - activate(); - } - configContainer = ""; - setTimeout(openConfig, 5); - }; - container.querySelector("#reload-switch").onclick = () => { - location.reload(); - }; - return container; - })() - ); - Spicetify.PopupModal.display({ - title: ACTIVE === "tv" ? translations[LOCALE].settings.tvModeConfig : translations[LOCALE].settings.fullscreenConfig, - content: configContainer, - }); - } - - // container.ondblclick = deactivatemenu - - // Add Full Screen Button on bottom bar - const defButton = document.createElement("button"); - defButton.classList.add("button", "fsd-button", "control-button", "InvalidDropTarget"); - defButton.id = "fs-button"; - defButton.setAttribute("title", translations[LOCALE].fullscreenBtnDesc); - - defButton.innerHTML = ``; - defButton.onclick = openwithDef; - - defButton.oncontextmenu = (evt) => { - evt.preventDefault(); - ACTIVE = "def"; - openConfig(); - }; - - // if (CONFIG.fsHideOriginal) { - // if (extraBar.lastChild.classList.contains("control-button") || extraBar.lastChild.title == "Full screen") extraBar.lastChild.remove(); - // } - - extraBar?.append(defButton); - - // Add TV Mode Button on top bar - const tvButton = document.createElement("button"); - tvButton.classList.add("button", "tm-button", "main-topBar-button", "InvalidDropTarget"); - tvButton.innerHTML = ``; - tvButton.id = "TV-button"; - tvButton.setAttribute("title", translations[LOCALE].tvBtnDesc); - - tvButton.onclick = openwithTV; - - topBar?.append(tvButton); - tvButton.oncontextmenu = (evt) => { - evt.preventDefault(); - ACTIVE = "tv"; - openConfig(); - }; - - render(); -} - -fullScreen(); diff --git a/.config/spicetify/Extensions/genre.js b/.config/spicetify/Extensions/genre.js deleted file mode 100644 index 85c603bd..00000000 --- a/.config/spicetify/Extensions/genre.js +++ /dev/null @@ -1,125 +0,0 @@ -// - -(function Genre() { - const { CosmosAsync, Player } = Spicetify; - - /** - * Fetch genre from artist - * - * @param artistURI {string} - * @return {Promise} - */ - const fetchGenres = async (artistURI) => { - const res = await CosmosAsync.get( - `https://api.spotify.com/v1/artists/${artistURI}` - ); - // noinspection JSUnresolvedVariable - return res.genres.slice(0, 3) // Only keep the first 3 genres - }; - - /** - * Fetch playlist from The Sound of Spotify for a given genre - * @param {String} genre - * @return {String|null} - */ - const fetchSoundOfSpotifyPlaylist = async (genre) => { - const query = encodeURIComponent(`The Sound of ${genre}`); - // Check localStorage for playlist - const cached = localStorage.getItem(`everynoise:${query}`); - if (cached !== null) { - return cached; - } - - // Search for playlist and check results for the everynoise account - const re = new RegExp(`^the sound of ${genre.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`, 'i'); - const res = await CosmosAsync.get(`https://api.spotify.com/v1/search?q=${query}&type=playlist`) - for (const item of res.playlists.items) { - if (item.owner.id === "thesoundsofspotify" && re.test(item.name)) { - localStorage.setItem(`everynoise:${genre}`, item.uri); - return item.uri - } - } - return null; - }; - - - // Store the current playback id - let playback = null; - - /** - * - * @type {Node} - */ - let genreContainer = null; - - let infoContainer = document.querySelector('div.main-trackInfo-container'); - - /** - * Remove genre injection in the UI - */ - const cleanInjection = () => { - if (genreContainer !== null) { - try { - infoContainer.removeChild(genreContainer); - } catch (e) {} - } - }; - - /** - * Inject genres to UI - */ - const inject = () => { - Player.addEventListener('onprogress', async () => { - if (Player.data.track.metadata.hasOwnProperty('artist_uri')) { - // If the registered song isn't the same as the one currently being played then fetch genres - if (playback !== Player.data.playback_id) { - // Save the new track - playback = Player.data.playback_id; - const id = Player.data.track.metadata.artist_uri.split(':')[2]; - const genres = await fetchGenres(id); - - cleanInjection(); - - genreContainer = document.createElement('div'); - // noinspection JSUndefinedPropertyAssignment - genreContainer.className = 'main-trackInfo-genres ellipsis-one-line main-type-finale'; - // noinspection JSUnresolvedVariable - genreContainer.style.color = 'var(--spice-extratext)'; - - for (const i in genres) { - let element; - const uri = await fetchSoundOfSpotifyPlaylist(genres[i]); - if (uri !== null) { - element = document.createElement('a'); - element.innerHTML = genres[i]; - element.href = uri; - } else { - element = document.createElement('span'); - } - element.innerHTML = genres[i]; - element.style.fontSize ="11px"; - genreContainer.appendChild(element); - if (i < genres.length-1) { - const separator = document.createElement('span'); - separator.innerHTML = ', '; - genreContainer.appendChild(separator); - } - } - - infoContainer = document.querySelector('div.main-trackInfo-container'); - if(!infoContainer) cleanInjection(); - infoContainer.appendChild(genreContainer); - - } - } else { - cleanInjection(); - } - }); - }; - - if (!CosmosAsync) { - setTimeout(Genre, 500); - } else { - inject(); - } -})(); diff --git a/.config/spicetify/Extensions/hidePodcasts.js b/.config/spicetify/Extensions/hidePodcasts.js deleted file mode 100644 index 6bc4a454..00000000 --- a/.config/spicetify/Extensions/hidePodcasts.js +++ /dev/null @@ -1,5 +0,0 @@ -var hidePodcasts=(()=>{var T=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,t)=>("undefined"!=typeof require?require:e)[t]}):e)(function(e){if("react"===e)return Spicetify.React;if("react-dom"===e)return Spicetify.ReactDOM;if("undefined"!=typeof require)return require.apply(this,arguments);throw new Error('Dynamic require of "'+e+'" is not supported')});function C(e){return(C="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function U(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,o=new Array(t);n":">",'"':""","'":"'","/":"/"};function W(e){return"string"==typeof e?e.replace(/[&<>"'\/]/g,function(e){return $[e]}):e}var h="undefined"!=typeof window&&window.navigator&&void 0===window.navigator.userAgentData&&window.navigator.userAgent&&-1s+c;)c++,u=a[l=i.slice(s,s+c).join(r)];if(void 0===u)return;if(null===u)return null;if(n.endsWith(l)){if("string"==typeof u)return u;if(l&&"string"==typeof u[l])return u[l]}var p=i.slice(s+c).join(r);return p?e(u,p,r):void 0}a=a[i[s]]}return a}}(this.data&&this.data[e]&&this.data[e][t],n,r)}},{key:"addResource",value:function(e,t,n,o){var r=4=p.maxReplaces)break}var n,o}),r}},{key:"nest",value:function(e,t){var n,o=this,r=2=this.maxParallelReads?void this.waitingReads.push({lng:o,ns:r,fcName:i,tried:s,wait:c,callback:l}):(this.readingCalls++,this.backend[i](o,r,function(e,t){var n;a.readingCalls--,0",">":">","'":"'","'":"'",""":'"',""":'"'," ":" "," ":" ","©":"©","©":"©","®":"®","®":"®","…":"…","…":"…","/":"/","/":"/"};function Ne(t,e){var n,o=Object.keys(t);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(t),e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),o.push.apply(o,n)),o}function Ce(t){for(var e=1;e{t=localStorage.getItem(t);if(!t)return e;try{return JSON.parse(t)}catch(e){return t}}),Ye=(je.use(T).use(I).init({resources:{en:{translation:{menuTitle:"Hide podcasts",enabled:"Enabled",aggressiveMode:"Aggressive mode",searchPageShelfAriaLabel:"Browse all"}},fr:{translation:{menuTitle:"Masquer les balados",enabled:"Activé",aggressiveMode:"Mode agressif",searchPageShelfAriaLabel:"Paarcourir tout"}},de:{translation:{menuTitle:"Podcasts verstecken",enabled:"Aktiviert",aggressiveMode:"Aggressiver Modus",searchPageShelfAriaLabel:"Alles durchsuchen"}},it:{translation:{menuTitle:"Nascondi podcast",enabled:"Attivato",aggressiveMode:"Modalità aggressiva",searchPageShelfAriaLabel:"Sfoglia tutto"}}},detection:{order:["navigator","htmlTag"]},fallbackLng:"en",interpolation:{escapeValue:!1}}),"HidePodcastsEnabled"),Ge="HidePodcastsAggressiveMode";var Qe=async function(){const o=je["t"];let{Player:e,Menu:t,Platform:n}=Spicetify,r=document.querySelector(".main-view-container__scroll-node-child");for(;!(e&&t&&n&&r);)await new Promise(e=>setTimeout(e,100)),e=Spicetify.Player,t=Spicetify.Menu,n=Spicetify.Platform,r=document.querySelector(".main-view-container__scroll-node-child");let a=We(Ye,!0),i=We(Ge,!1);function s(){var e;e=a,document.body.classList.toggle("hide-podcasts-enabled",e);{const t=document.body;if(!t.classList.contains("hide-podcasts--style-injected")){const n=document.createElement("style");n.innerHTML=`.hide-podcasts-enabled .podcast-item { - display: none !important; - }.hide-podcasts-enabled .queue-tabBar-header a[href="/collection/podcasts"] { - display: none !important; - }`,t.appendChild(n),t.classList.add("hide-podcasts--style-injected")}}{const o=null==(e=document.querySelector('a[href="/collection/episodes"]'))?void 0:e.parentElement,r=(o&&o.classList.add("podcast-item"),document.querySelectorAll(".main-shelf-shelf")),i=(r.forEach(e=>{var t;0<[...e.querySelectorAll('.main-cardHeader-link[href^="/episode"]'),...e.querySelectorAll('.main-cardHeader-link[href^="/show"]')].length&&(t=e.getAttribute("aria-label"),console.log("Tagging carousel: "+t),e.classList.add("podcast-item"))}),document.querySelector('.x-categoryCard-CategoryCard[href="/genre/podcasts-web"]'));i&&(console.log("Tagging browsePodcastsCard: "+i),i.classList.add("podcast-item"))}}function c(t){const n=new MutationObserver(function(){var e;!r||(e="/search"===t?r.querySelector(`#searchPage .main-shelf-shelf[aria-label="${o("searchPageShelfAriaLabel")}"]`):r.querySelector("section"))&&(console.log(t,e),s(),i||n.disconnect())});n.observe(r,{childList:!0,subtree:!0})}new t.SubMenu(o("menuTitle"),[new t.Item(o("enabled"),a,e=>{a=!a,localStorage.setItem(Ye,a),e.setState(a),s()}),new t.Item(o("aggressiveMode"),i,e=>{i=!i,localStorage.setItem(Ge,i),e.setState(i),location.reload()})]).register(),c(n.History.location.pathname),n.History.listen(({pathname:e})=>{c(e)})};(async()=>{await Qe()})()})(); \ No newline at end of file diff --git a/.config/spicetify/Extensions/historyShortcut.js b/.config/spicetify/Extensions/historyShortcut.js deleted file mode 100644 index a4c65228..00000000 --- a/.config/spicetify/Extensions/historyShortcut.js +++ /dev/null @@ -1,127 +0,0 @@ -// NAME: History Shortcut -// AUTHOR: einzigartigerName -// DESCRIPTION: Adds a Shortcut to your Listening History to the Sidebar - -(function HistoryShortcut() { - - const { CosmosAPI, Player, LocalStorage, PlaybackControl, ContextMenu, URI } = Spicetify - if (!(CosmosAPI && Player && LocalStorage && PlaybackControl && ContextMenu && URI)) { - setTimeout(HistoryShortcut, 300) - return - } - - const ITEM_LABEL = "History" - - const HISTORY_DIV_CLASS = "SidebarListItem" - const HISTORY_DIV_CLASS_ACTIVE = "SidebarListItem SidebarListItem--is-active" - - const HISTORY_ANKER_CLASS = "SidebarListItemLink SidebarListItemLink--tall spoticon-time-24" - const HISTORY_ANKER_CLASS_ACTIVE = "SidebarListItemLink SidebarListItemLink--is-highlighted SidebarListItemLink--tall spoticon-time-24" - - let historyItem = createHistoyItem() - // Get Sidebar Lists - var topicList = document.querySelector("#view-navigation-bar > div > div.LeftSidebar__section > div > ul") - if (topicList) { - // Add to first in list - // On default layout this would be the Home/Browse/Radio List - topicList.appendChild(historyItem.div) - } else { - return - } - - const toCheckMutate = document.getElementById('view-content'); - const config = { attributes: true, childList: true, subtree: true }; - - let observerCallback = function(_, _) { - appQueue = document.getElementById("app-queue") - if (!appQueue){ return } - - if (appQueue.getAttribute("class") === "active" - && appQueue.getAttribute("data-app-uri") === "spotify:app:queue:history" - ) { - onClickHistory() - } else { - onLeaveHistory() - } - }; - - let observer = new MutationObserver(observerCallback) - observer.observe(toCheckMutate, config) - - - - // Deactivate Active Status for History Item - function onLeaveHistory() { - historyItem.div.setAttribute("class",HISTORY_DIV_CLASS) - historyItem.anker.setAttribute("class", HISTORY_ANKER_CLASS) - } - - // Activate Active Status for History Item - function onClickHistory() { - historyItem.div.setAttribute("class", HISTORY_DIV_CLASS_ACTIVE) - historyItem.anker.setAttribute("class", HISTORY_ANKER_CLASS_ACTIVE) - } - - // Construct the List Item - function createHistoyItem() { - /* List Item - *
  • - */ - let listItem = document.createElement("li") - listItem.setAttribute("class", HISTORY_DIV_CLASS) - - /* Outer Div Element - *
    - */ - let outer = document.createElement("div") - outer.setAttribute("class", "DropTarget SidebarListItem__drop-target") - - /* Middle Div Element - *
    - */ - let inner = document.createElement("div") - inner.setAttribute("class", "SidebarListItem__inner") - - /* Link Div Element - *