🔧 chore(spicetify): update custom app

This commit is contained in:
Sergio Laín 2024-09-14 13:59:02 +02:00
parent 78b5bc7880
commit 9a9148c5f7
No known key found for this signature in database
GPG key ID: 8429B2EE312F8150
6 changed files with 1172 additions and 848 deletions

View file

@ -8,6 +8,7 @@ var library = (() => {
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty; 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 __export = (target, all) => { var __export = (target, all) => {
for (var name in all) for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true }); __defProp(target, name, { get: all[name], enumerable: true });
@ -21,6 +22,10 @@ var library = (() => {
return to; return to;
}; };
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// src/extensions/collections_wrapper.ts // src/extensions/collections_wrapper.ts
var collections_wrapper_exports = {}; var collections_wrapper_exports = {};
@ -77,7 +82,7 @@ var library = (() => {
var v4_default = v4; var v4_default = v4;
// src/extensions/collections_wrapper.ts // src/extensions/collections_wrapper.ts
var CollectionWrapper = class extends EventTarget { var _CollectionsWrapper = class extends EventTarget {
_collections; _collections;
constructor() { constructor() {
super(); super();
@ -90,115 +95,189 @@ var library = (() => {
getCollection(uri) { getCollection(uri) {
return this._collections.find((collection) => collection.uri === uri); return this._collections.find((collection) => collection.uri === uri);
} }
async requestAlbums({ sortOrder, textFilter }) { async getCollectionContents(uri) {
const collection = this.getCollection(uri);
if (!collection)
throw new Error("Collection not found");
const items = this._collections.filter((collection2) => collection2.parentCollection === uri);
const albums = await Spicetify.Platform.LibraryAPI.getContents({ const albums = await Spicetify.Platform.LibraryAPI.getContents({
filters: ["0"], filters: ["0"],
sortOrder,
textFilter,
offset: 0, offset: 0,
limit: 9999 limit: 9999
}); });
return albums; items.push(...albums.items.filter((album) => collection.items.includes(album.uri)));
return items;
} }
async getCollectionItems(props) { async getContents(props) {
const { collectionUri, textFilter, sortOrder, rootlist, limit = 9999, offset = 0 } = props; const { collectionUri, offset, limit, textFilter } = props;
let collectionItems = this._collections; let items = collectionUri ? await this.getCollectionContents(collectionUri) : this._collections;
let albumItems = []; const openedCollectionName = collectionUri ? this.getCollection(collectionUri)?.name : void 0;
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) { if (textFilter) {
let regex = new RegExp("\\b" + textFilter, "i"); const regex = new RegExp(`\\b${textFilter}`, "i");
collectionItems = collectionItems.filter((item) => { items = items.filter((collection) => regex.test(collection.name));
return regex.test(item.name);
});
} }
if (rootlist && !collectionUri) { items = items.slice(offset, offset + limit);
const res = await this.requestAlbums({ sortOrder, textFilter }); return { items, totalLength: this._collections.length, offset, openedCollectionName };
albumItems = res.items; }
if (!textFilter) { async cleanCollections() {
const collectionSet = new Set(this._collections.map((collection) => collection.items).flat()); for (const collection of this._collections) {
const uncommonElements = res.items.filter((item) => !collectionSet.has(item.uri)); const boolArray = await Spicetify.Platform.LibraryAPI.contains(...collection.items);
collectionItems = this._collections.filter((collection) => !collection.parentCollection); if (boolArray.includes(false)) {
albumItems = uncommonElements; collection.items = collection.items.filter((_, i) => boolArray[i]);
unfilteredLength = this._collections.length + uncommonElements.length; this.saveCollections();
Spicetify.showNotification("Album removed from collection");
this.syncCollection(collection.uri);
} }
} }
if (offset > 0) }
collectionItems = []; async syncCollection(uri) {
return { const collection = this.getCollection(uri);
openedCollection, if (!collection)
items: [...collectionItems, ...albumItems.slice(offset, offset + limit)], return;
totalLength: albumItems.length + collectionItems.length, const { PlaylistAPI } = Spicetify.Platform;
unfilteredLength if (!collection.syncedPlaylistUri)
}; return;
const playlist = await PlaylistAPI.getPlaylist(collection.syncedPlaylistUri);
const playlistTracks = playlist.contents.items.filter((t) => t.type === "track").map((t) => t.uri);
const collectionTracks = await this.getTracklist(uri);
const wanted = collectionTracks.filter((track) => !playlistTracks.includes(track));
const unwanted = playlistTracks.filter((track) => !collectionTracks.includes(track)).map((uri2) => ({ uri: uri2, uid: [] }));
if (wanted.length)
await PlaylistAPI.add(collection.syncedPlaylistUri, wanted, { before: "end" });
if (unwanted.length)
await PlaylistAPI.remove(collection.syncedPlaylistUri, unwanted);
}
unsyncCollection(uri) {
const collection = this.getCollection(uri);
if (!collection)
return;
collection.syncedPlaylistUri = void 0;
this.saveCollections();
}
async getTracklist(collectionUri) {
const collection = this.getCollection(collectionUri);
if (!collection)
return [];
return Promise.all(
collection.items.map(async (uri) => {
const album = await Spicetify.Platform.LibraryAPI.getAlbum(uri);
return album.items.map((t) => t.uri);
})
).then((tracks) => tracks.flat());
}
async convertToPlaylist(uri) {
const collection = this.getCollection(uri);
if (!collection)
return;
const { Platform, showNotification } = Spicetify;
const { RootlistAPI, PlaylistAPI } = Platform;
if (collection.syncedPlaylistUri) {
showNotification("Synced Playlist already exists", true);
return;
}
try {
const playlistUri = await RootlistAPI.createPlaylist(collection.name, { before: "start" });
const items = await this.getTracklist(uri);
await PlaylistAPI.add(playlistUri, items, { before: "start" });
collection.syncedPlaylistUri = playlistUri;
} catch (error) {
console.error(error);
showNotification("Failed to create playlist", true);
}
}
async createCollectionFromDiscog(artistUri) {
const [raw, info] = await Promise.all([
Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.queryArtistDiscographyAlbums, {
uri: artistUri,
offset: 0,
limit: 50
}),
Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.queryArtistOverview, {
uri: artistUri,
locale: Spicetify.Locale.getLocale(),
includePrerelease: false
})
]);
const items = raw?.data?.artistUnion.discography.albums?.items;
const name = info?.data?.artistUnion.profile.name;
const image = info?.data?.artistUnion.visuals.avatarImage?.sources?.[0]?.url;
if (!name || !items?.length) {
Spicetify.showNotification("Artist not found or has no albums");
return;
}
const collectionUri = this.createCollection(`${name} Albums`);
if (image)
this.setCollectionImage(collectionUri, image);
for (const album of items) {
this.addAlbumToCollection(collectionUri, album.releases.items[0].uri);
}
} }
createCollection(name, parentCollection = "") { createCollection(name, parentCollection = "") {
const uri = v4_default(); const id = v4_default();
const collection = { this._collections.push({
type: "collection", type: "collection",
uri, uri: id,
name, name,
items: [], items: [],
totalLength: 0, addedAt: new Date(),
imgUrl: "", lastPlayedAt: new Date(),
parentCollection parentCollection
}; });
this._collections.push(collection);
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection created"); Spicetify.showNotification("Collection created");
return id;
} }
deleteCollection(uri) { deleteCollection(uri) {
this._collections = this._collections.filter((collection) => collection.uri !== uri); this._collections = this._collections.filter((collection) => collection.uri !== uri);
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection deleted"); Spicetify.showNotification("Collection deleted");
} }
deleteCollectionAndAlbums(uri) {
const collection = this.getCollection(uri);
if (!collection)
return;
for (const album of collection.items) {
Spicetify.Platform.LibraryAPI.remove({ uris: [album] });
}
this.deleteCollection(uri);
}
async addAlbumToCollection(collectionUri, albumUri) { async addAlbumToCollection(collectionUri, albumUri) {
const collection = this.getCollection(collectionUri); const collection = this.getCollection(collectionUri);
if (!collection) if (!collection)
return; return;
await Spicetify.Platform.LibraryAPI.add({ uris: [albumUri] });
collection.items.push(albumUri); collection.items.push(albumUri);
collection.totalLength++;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Album added to collection"); Spicetify.showNotification("Album added to collection");
this.syncCollection(collectionUri);
} }
removeAlbumFromCollection(collectionUri, albumUri) { removeAlbumFromCollection(collectionUri, albumUri) {
const collection = this.getCollection(collectionUri); const collection = this.getCollection(collectionUri);
if (!collection) if (!collection)
return; return;
collection.items = collection.items.filter((item) => item !== albumUri); collection.items = collection.items.filter((item) => item !== albumUri);
collection.totalLength--;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Album removed from collection"); Spicetify.showNotification("Album removed from collection");
this.syncCollection(collectionUri);
} }
getCollectionsWithAlbum(albumUri) { getCollectionsWithAlbum(albumUri) {
return this._collections.filter((collection) => { return this._collections.filter((collection) => {
return collection.items.some((item) => item === albumUri); return collection.items.some((item) => item === albumUri);
}); });
} }
renameCollection(uri, newName) { renameCollection(uri, name) {
const collection = this.getCollection(uri); const collection = this.getCollection(uri);
if (!collection) if (!collection)
return; return;
collection.name = newName; collection.name = name;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection renamed"); Spicetify.showNotification("Collection renamed");
} }
setCollectionImage(uri, imgUrl) { setCollectionImage(uri, url) {
const collection = this.getCollection(uri); const collection = this.getCollection(uri);
if (!collection) if (!collection)
return; return;
collection.imgUrl = imgUrl; collection.image = url;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection image set"); Spicetify.showNotification("Collection image set");
} }
@ -206,12 +285,15 @@ var library = (() => {
const collection = this.getCollection(uri); const collection = this.getCollection(uri);
if (!collection) if (!collection)
return; return;
collection.imgUrl = ""; collection.image = void 0;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection image removed"); Spicetify.showNotification("Collection image removed");
} }
}; };
var collections_wrapper_default = CollectionWrapper; var CollectionsWrapper = _CollectionsWrapper;
__publicField(CollectionsWrapper, "INSTANCE", new _CollectionsWrapper());
window.CollectionsWrapper = CollectionsWrapper.INSTANCE;
var collections_wrapper_default = CollectionsWrapper;
return __toCommonJS(collections_wrapper_exports); return __toCommonJS(collections_wrapper_exports);
})(); })();

View file

@ -285,7 +285,9 @@ var library = (() => {
}); });
}; };
var ToggleFiltersButton = () => { var ToggleFiltersButton = () => {
const [direction, setDirection] = import_react3.default.useState(document.body.classList.contains("show-ylx-filters") ? "up" : "down"); const [direction, setDirection] = import_react3.default.useState(
document.body.classList.contains("show-ylx-filters") ? "up" : "down"
);
const { ButtonTertiary } = Spicetify.ReactComponent; const { ButtonTertiary } = Spicetify.ReactComponent;
const toggleDirection = () => { const toggleDirection = () => {
if (direction === "down") { if (direction === "down") {
@ -332,31 +334,207 @@ var library = (() => {
}; };
var collapse_button_default = CollapseButton; var collapse_button_default = CollapseButton;
// src/components/expand_button.tsx // src/components/album_menu_item.tsx
var import_react8 = __toESM(require_react());
// src/components/leading_icon.tsx
var import_react5 = __toESM(require_react()); var import_react5 = __toESM(require_react());
var expandLibrary = () => { var LeadingIcon = ({ path }) => {
Spicetify.Platform.LocalStorageAPI.setItem("ylx-sidebar-state", 0); return /* @__PURE__ */ import_react5.default.createElement(Spicetify.ReactComponent.IconComponent, {
};
var ExpandIcon = () => {
const { IconComponent } = Spicetify.ReactComponent;
return /* @__PURE__ */ import_react5.default.createElement(IconComponent, {
semanticColor: "textSubdued", semanticColor: "textSubdued",
dangerouslySetInnerHTML: { dangerouslySetInnerHTML: {
__html: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" ><path d="M7.19 1A.749.749 0 0 1 8.47.47L16 7.99l-7.53 7.521a.75.75 0 0 1-1.234-.815.75.75 0 0 1 .174-.243l5.72-5.714H.75a.75.75 0 1 1 0-1.498h12.38L7.41 1.529a.749.749 0 0 1-.22-.53z"></path></svg>' __html: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">${path}</svg>`
}, },
iconSize: 16 iconSize: 16
}); });
}; };
var ExpandButton = () => { var leading_icon_default = LeadingIcon;
const { ButtonTertiary } = Spicetify.ReactComponent;
return /* @__PURE__ */ import_react5.default.createElement(ButtonTertiary, { // src/components/text_input_dialog.tsx
buttonSize: "sm", var import_react6 = __toESM(require_react());
"aria-label": "Show Filters", var TextInputDialog = (props) => {
iconOnly: ExpandIcon, const { def, placeholder, onSave } = props;
onClick: expandLibrary const [value, setValue] = import_react6.default.useState(def || "");
const onSubmit = (e) => {
e.preventDefault();
Spicetify.PopupModal.hide();
onSave(value);
};
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-sc-qlcn5g-0 Button-small-buttonPrimary"
}, /* @__PURE__ */ import_react6.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_react7 = __toESM(require_react());
var SearchBar = (props) => {
const { setSearch, placeholder } = props;
const handleChange = (e) => {
setSearch(e.target.value);
};
return /* @__PURE__ */ import_react7.default.createElement("div", {
className: "x-filterBox-filterInputContainer x-filterBox-expandedOrHasFilter",
role: "search"
}, /* @__PURE__ */ import_react7.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_react7.default.createElement("div", {
className: "x-filterBox-overlay"
}, /* @__PURE__ */ import_react7.default.createElement("span", {
className: "x-filterBox-searchIconContainer"
}, /* @__PURE__ */ import_react7.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_react7.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_react7.default.createElement("button", {
className: "x-filterBox-expandButton",
"aria-hidden": "false",
"aria-label": "Search Playlists",
type: "button"
}, /* @__PURE__ */ import_react7.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_react7.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) => {
CollectionsWrapper.createCollection(value);
};
Spicetify.PopupModal.display({
title: "Create Collection",
content: /* @__PURE__ */ import_react8.default.createElement(text_input_dialog_default, {
def: "New Collection",
placeholder: "Collection Name",
onSave
})
}); });
}; };
var expand_button_default = ExpandButton; var CollectionSearchMenu = () => {
const { MenuItem } = Spicetify.ReactComponent;
const { SVGIcons } = Spicetify;
const [textFilter, setTextFilter] = import_react8.default.useState("");
const [collections, setCollections] = import_react8.default.useState(null);
const context = import_react8.default.useContext(Spicetify.ContextMenuV2._context);
const uri = context?.props?.uri;
import_react8.default.useEffect(() => {
const fetchCollections = async () => {
setCollections(await CollectionsWrapper.getContents({ textFilter, limit: 20, offset: 0 }));
};
fetchCollections();
}, [textFilter]);
if (!collections)
return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null);
const addToCollection = (collectionUri) => {
CollectionsWrapper.addAlbumToCollection(collectionUri, uri);
};
const activeCollections = CollectionsWrapper.getCollectionsWithAlbum(uri);
const hasCollections = activeCollections.length > 0;
const removeFromCollections = () => {
for (const collection of activeCollections) {
CollectionsWrapper.removeAlbumFromCollection(collection.uri, uri);
}
};
const allCollectionsLength = collections.totalLength;
const menuItems = collections.items.map((collection, index) => {
return /* @__PURE__ */ import_react8.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_react8.default.createElement("div", {
className: "main-contextMenu-filterPlaylistSearchContainer",
style: { "--context-menu-submenu-length": `${menuLength}` }
}, /* @__PURE__ */ import_react8.default.createElement("li", {
role: "presentation",
className: "main-contextMenu-filterPlaylistSearch"
}, /* @__PURE__ */ import_react8.default.createElement("div", {
role: "menuitem"
}, /* @__PURE__ */ import_react8.default.createElement(searchbar_default, {
setSearch: setTextFilter,
placeholder: "collections"
}))), /* @__PURE__ */ import_react8.default.createElement(MenuItem, {
key: "new-collection",
leadingIcon: /* @__PURE__ */ import_react8.default.createElement(leading_icon_default, {
path: SVGIcons.plus2px
}),
onClick: createCollection
}, "Create collection"), hasCollections && /* @__PURE__ */ import_react8.default.createElement(MenuItem, {
key: "remove-collection",
leadingIcon: /* @__PURE__ */ import_react8.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_react8.default.createElement(MenuSubMenuItem, {
displayText: "Add to collection",
divider: "after",
leadingIcon: /* @__PURE__ */ import_react8.default.createElement(leading_icon_default, {
path: SVGIcons.plus2px
})
}, /* @__PURE__ */ import_react8.default.createElement(CollectionSearchMenu, null));
};
var album_menu_item_default = AlbumMenuItem;
// src/components/artist_menu_item.tsx
var import_react9 = __toESM(require_react());
var ArtistMenuItem = () => {
const { MenuItem } = Spicetify.ReactComponent;
const { SVGIcons } = Spicetify;
const context = import_react9.default.useContext(Spicetify.ContextMenuV2._context);
const uri = context?.props?.uri;
return /* @__PURE__ */ import_react9.default.createElement(MenuItem, {
divider: "after",
leadingIcon: /* @__PURE__ */ import_react9.default.createElement(leading_icon_default, {
path: SVGIcons.plus2px
}),
onClick: () => CollectionsWrapper.createCollectionFromDiscog(uri)
}, "Create Discog Collection");
};
var artist_menu_item_default = ArtistMenuItem;
// ../node_modules/uuid/dist/esm-browser/rng.js // ../node_modules/uuid/dist/esm-browser/rng.js
var getRandomValues; var getRandomValues;
@ -407,7 +585,7 @@ var library = (() => {
var v4_default = v4; var v4_default = v4;
// src/extensions/collections_wrapper.ts // src/extensions/collections_wrapper.ts
var CollectionWrapper = class extends EventTarget { var _CollectionsWrapper = class extends EventTarget {
_collections; _collections;
constructor() { constructor() {
super(); super();
@ -420,115 +598,189 @@ var library = (() => {
getCollection(uri) { getCollection(uri) {
return this._collections.find((collection) => collection.uri === uri); return this._collections.find((collection) => collection.uri === uri);
} }
async requestAlbums({ sortOrder, textFilter }) { async getCollectionContents(uri) {
const collection = this.getCollection(uri);
if (!collection)
throw new Error("Collection not found");
const items = this._collections.filter((collection2) => collection2.parentCollection === uri);
const albums = await Spicetify.Platform.LibraryAPI.getContents({ const albums = await Spicetify.Platform.LibraryAPI.getContents({
filters: ["0"], filters: ["0"],
sortOrder,
textFilter,
offset: 0, offset: 0,
limit: 9999 limit: 9999
}); });
return albums; items.push(...albums.items.filter((album) => collection.items.includes(album.uri)));
return items;
} }
async getCollectionItems(props) { async getContents(props) {
const { collectionUri, textFilter, sortOrder, rootlist, limit = 9999, offset = 0 } = props; const { collectionUri, offset, limit, textFilter } = props;
let collectionItems = this._collections; let items = collectionUri ? await this.getCollectionContents(collectionUri) : this._collections;
let albumItems = []; const openedCollectionName = collectionUri ? this.getCollection(collectionUri)?.name : void 0;
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) { if (textFilter) {
let regex = new RegExp("\\b" + textFilter, "i"); const regex = new RegExp(`\\b${textFilter}`, "i");
collectionItems = collectionItems.filter((item) => { items = items.filter((collection) => regex.test(collection.name));
return regex.test(item.name);
});
} }
if (rootlist && !collectionUri) { items = items.slice(offset, offset + limit);
const res = await this.requestAlbums({ sortOrder, textFilter }); return { items, totalLength: this._collections.length, offset, openedCollectionName };
albumItems = res.items; }
if (!textFilter) { async cleanCollections() {
const collectionSet = new Set(this._collections.map((collection) => collection.items).flat()); for (const collection of this._collections) {
const uncommonElements = res.items.filter((item) => !collectionSet.has(item.uri)); const boolArray = await Spicetify.Platform.LibraryAPI.contains(...collection.items);
collectionItems = this._collections.filter((collection) => !collection.parentCollection); if (boolArray.includes(false)) {
albumItems = uncommonElements; collection.items = collection.items.filter((_, i) => boolArray[i]);
unfilteredLength = this._collections.length + uncommonElements.length; this.saveCollections();
Spicetify.showNotification("Album removed from collection");
this.syncCollection(collection.uri);
} }
} }
if (offset > 0) }
collectionItems = []; async syncCollection(uri) {
return { const collection = this.getCollection(uri);
openedCollection, if (!collection)
items: [...collectionItems, ...albumItems.slice(offset, offset + limit)], return;
totalLength: albumItems.length + collectionItems.length, const { PlaylistAPI } = Spicetify.Platform;
unfilteredLength if (!collection.syncedPlaylistUri)
}; return;
const playlist = await PlaylistAPI.getPlaylist(collection.syncedPlaylistUri);
const playlistTracks = playlist.contents.items.filter((t) => t.type === "track").map((t) => t.uri);
const collectionTracks = await this.getTracklist(uri);
const wanted = collectionTracks.filter((track) => !playlistTracks.includes(track));
const unwanted = playlistTracks.filter((track) => !collectionTracks.includes(track)).map((uri2) => ({ uri: uri2, uid: [] }));
if (wanted.length)
await PlaylistAPI.add(collection.syncedPlaylistUri, wanted, { before: "end" });
if (unwanted.length)
await PlaylistAPI.remove(collection.syncedPlaylistUri, unwanted);
}
unsyncCollection(uri) {
const collection = this.getCollection(uri);
if (!collection)
return;
collection.syncedPlaylistUri = void 0;
this.saveCollections();
}
async getTracklist(collectionUri) {
const collection = this.getCollection(collectionUri);
if (!collection)
return [];
return Promise.all(
collection.items.map(async (uri) => {
const album = await Spicetify.Platform.LibraryAPI.getAlbum(uri);
return album.items.map((t) => t.uri);
})
).then((tracks) => tracks.flat());
}
async convertToPlaylist(uri) {
const collection = this.getCollection(uri);
if (!collection)
return;
const { Platform, showNotification } = Spicetify;
const { RootlistAPI, PlaylistAPI } = Platform;
if (collection.syncedPlaylistUri) {
showNotification("Synced Playlist already exists", true);
return;
}
try {
const playlistUri = await RootlistAPI.createPlaylist(collection.name, { before: "start" });
const items = await this.getTracklist(uri);
await PlaylistAPI.add(playlistUri, items, { before: "start" });
collection.syncedPlaylistUri = playlistUri;
} catch (error) {
console.error(error);
showNotification("Failed to create playlist", true);
}
}
async createCollectionFromDiscog(artistUri) {
const [raw, info] = await Promise.all([
Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.queryArtistDiscographyAlbums, {
uri: artistUri,
offset: 0,
limit: 50
}),
Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.queryArtistOverview, {
uri: artistUri,
locale: Spicetify.Locale.getLocale(),
includePrerelease: false
})
]);
const items = raw?.data?.artistUnion.discography.albums?.items;
const name = info?.data?.artistUnion.profile.name;
const image = info?.data?.artistUnion.visuals.avatarImage?.sources?.[0]?.url;
if (!name || !items?.length) {
Spicetify.showNotification("Artist not found or has no albums");
return;
}
const collectionUri = this.createCollection(`${name} Albums`);
if (image)
this.setCollectionImage(collectionUri, image);
for (const album of items) {
this.addAlbumToCollection(collectionUri, album.releases.items[0].uri);
}
} }
createCollection(name, parentCollection = "") { createCollection(name, parentCollection = "") {
const uri = v4_default(); const id = v4_default();
const collection = { this._collections.push({
type: "collection", type: "collection",
uri, uri: id,
name, name,
items: [], items: [],
totalLength: 0, addedAt: new Date(),
imgUrl: "", lastPlayedAt: new Date(),
parentCollection parentCollection
}; });
this._collections.push(collection);
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection created"); Spicetify.showNotification("Collection created");
return id;
} }
deleteCollection(uri) { deleteCollection(uri) {
this._collections = this._collections.filter((collection) => collection.uri !== uri); this._collections = this._collections.filter((collection) => collection.uri !== uri);
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection deleted"); Spicetify.showNotification("Collection deleted");
} }
deleteCollectionAndAlbums(uri) {
const collection = this.getCollection(uri);
if (!collection)
return;
for (const album of collection.items) {
Spicetify.Platform.LibraryAPI.remove({ uris: [album] });
}
this.deleteCollection(uri);
}
async addAlbumToCollection(collectionUri, albumUri) { async addAlbumToCollection(collectionUri, albumUri) {
const collection = this.getCollection(collectionUri); const collection = this.getCollection(collectionUri);
if (!collection) if (!collection)
return; return;
await Spicetify.Platform.LibraryAPI.add({ uris: [albumUri] });
collection.items.push(albumUri); collection.items.push(albumUri);
collection.totalLength++;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Album added to collection"); Spicetify.showNotification("Album added to collection");
this.syncCollection(collectionUri);
} }
removeAlbumFromCollection(collectionUri, albumUri) { removeAlbumFromCollection(collectionUri, albumUri) {
const collection = this.getCollection(collectionUri); const collection = this.getCollection(collectionUri);
if (!collection) if (!collection)
return; return;
collection.items = collection.items.filter((item) => item !== albumUri); collection.items = collection.items.filter((item) => item !== albumUri);
collection.totalLength--;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Album removed from collection"); Spicetify.showNotification("Album removed from collection");
this.syncCollection(collectionUri);
} }
getCollectionsWithAlbum(albumUri) { getCollectionsWithAlbum(albumUri) {
return this._collections.filter((collection) => { return this._collections.filter((collection) => {
return collection.items.some((item) => item === albumUri); return collection.items.some((item) => item === albumUri);
}); });
} }
renameCollection(uri, newName) { renameCollection(uri, name) {
const collection = this.getCollection(uri); const collection = this.getCollection(uri);
if (!collection) if (!collection)
return; return;
collection.name = newName; collection.name = name;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection renamed"); Spicetify.showNotification("Collection renamed");
} }
setCollectionImage(uri, imgUrl) { setCollectionImage(uri, url) {
const collection = this.getCollection(uri); const collection = this.getCollection(uri);
if (!collection) if (!collection)
return; return;
collection.imgUrl = imgUrl; collection.image = url;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection image set"); Spicetify.showNotification("Collection image set");
} }
@ -536,201 +788,17 @@ var library = (() => {
const collection = this.getCollection(uri); const collection = this.getCollection(uri);
if (!collection) if (!collection)
return; return;
collection.imgUrl = ""; collection.image = void 0;
this.saveCollections(); this.saveCollections();
Spicetify.showNotification("Collection image removed"); Spicetify.showNotification("Collection image removed");
} }
}; };
var collections_wrapper_default = CollectionWrapper; var CollectionsWrapper2 = _CollectionsWrapper;
__publicField(CollectionsWrapper2, "INSTANCE", new _CollectionsWrapper());
// src/components/album_menu_item.tsx window.CollectionsWrapper = CollectionsWrapper2.INSTANCE;
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: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">${path}</svg>`
},
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 // src/extensions/folder_image_wrapper.ts
var FolderImageWrapper = class extends EventTarget { var _FolderImageWrapper = class extends EventTarget {
_folderImages; _folderImages;
constructor() { constructor() {
super(); super();
@ -757,7 +825,9 @@ var library = (() => {
localStorage.setItem("library:folderImages", JSON.stringify(this._folderImages)); localStorage.setItem("library:folderImages", JSON.stringify(this._folderImages));
} }
}; };
var folder_image_wrapper_default = FolderImageWrapper; var FolderImageWrapper2 = _FolderImageWrapper;
__publicField(FolderImageWrapper2, "INSTANCE", new _FolderImageWrapper());
window.FolderImageWrapper = FolderImageWrapper2.INSTANCE;
// src/extensions/extension.tsx // src/extensions/extension.tsx
var styleLink = document.createElement("link"); var styleLink = document.createElement("link");
@ -773,6 +843,7 @@ var library = (() => {
}; };
var FolderImage = ({ url }) => { var FolderImage = ({ url }) => {
return /* @__PURE__ */ import_react10.default.createElement("img", { return /* @__PURE__ */ import_react10.default.createElement("img", {
alt: "Folder Image",
"aria-hidden": "true", "aria-hidden": "true",
draggable: "false", draggable: "false",
loading: "eager", loading: "eager",
@ -793,7 +864,7 @@ var library = (() => {
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" 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 { var SpicetifyLibrary = class {
ConfigWrapper = new config_wrapper_default( ConfigWrapper = new config_wrapper_default(
[ [
{ {
@ -812,16 +883,25 @@ var library = (() => {
type: "toggle", type: "toggle",
def: false, def: false,
callback: setSearchBarSize callback: setSearchBarSize
} },
{
name: "Playlists Page",
key: "show-playlists",
type: "toggle",
def: true,
sectionHeader: "Pages"
},
{ name: "Albums Page", key: "show-albums", type: "toggle", def: true },
{ name: "Collections Page", key: "show-collections", type: "toggle", def: true },
{ name: "Artists Page", key: "show-artists", type: "toggle", def: true },
{ name: "Shows Page", key: "show-shows", type: "toggle", def: true }
], ],
"library" "library"
); );
CollectionWrapper = new collections_wrapper_default();
FolderImageWrapper = new folder_image_wrapper_default();
}; };
window.SpicetifyLibrary = new SpicetifyLibrary2(); window.SpicetifyLibrary = new SpicetifyLibrary();
(function wait() { (function wait() {
const { LocalStorageAPI } = Spicetify?.Platform; const { LocalStorageAPI } = Spicetify.Platform;
if (!LocalStorageAPI) { if (!LocalStorageAPI) {
setTimeout(wait, 100); setTimeout(wait, 100);
return; return;
@ -829,22 +909,23 @@ var library = (() => {
main(LocalStorageAPI); main(LocalStorageAPI);
})(); })();
function main(LocalStorageAPI) { function main(LocalStorageAPI) {
const isAlbum = (props) => { const isAlbum = (props) => props.uri?.includes("album");
return props.uri?.includes("album"); const isArtist = (props) => props.uri?.includes("artist");
};
Spicetify.ContextMenuV2.registerItem(/* @__PURE__ */ import_react10.default.createElement(album_menu_item_default, null), isAlbum); Spicetify.ContextMenuV2.registerItem(/* @__PURE__ */ import_react10.default.createElement(album_menu_item_default, null), isAlbum);
Spicetify.ContextMenuV2.registerItem(/* @__PURE__ */ import_react10.default.createElement(artist_menu_item_default, null), isArtist);
Spicetify.Platform.LibraryAPI.getEvents()._emitter.addListener("update", () => CollectionsWrapper.cleanCollections());
function injectFolderImages() { function injectFolderImages() {
const rootlist = document.querySelector(".main-rootlist-wrapper > div:nth-child(2)"); const rootlist = document.querySelector(".main-rootlist-wrapper > div:nth-child(2)");
if (!rootlist) if (!rootlist)
return setTimeout(injectFolderImages, 100); return setTimeout(injectFolderImages, 100);
setTimeout(() => { setTimeout(() => {
Array.from(rootlist.children).forEach((el) => { for (const el of Array.from(rootlist.children)) {
const uri = el.querySelector(".main-yourLibraryX-listItemGroup")?.getAttribute("aria-labelledby")?.slice(14); const uri = el.querySelector("[aria-labelledby]")?.getAttribute("aria-labelledby")?.slice(14);
if (uri?.includes("folder")) { if (uri?.includes("folder")) {
const imageBox = el.querySelector(".x-entityImage-imageContainer"); const imageBox = el.querySelector(".x-entityImage-imageContainer");
if (!imageBox) if (!imageBox)
return; return;
const imageUrl = window.SpicetifyLibrary.FolderImageWrapper.getFolderImage(uri); const imageUrl = FolderImageWrapper.getFolderImage(uri);
if (!imageUrl) if (!imageUrl)
import_react_dom.default.render(/* @__PURE__ */ import_react10.default.createElement(FolderPlaceholder, null), imageBox); import_react_dom.default.render(/* @__PURE__ */ import_react10.default.createElement(FolderPlaceholder, null), imageBox);
else else
@ -852,17 +933,13 @@ var library = (() => {
url: imageUrl url: imageUrl
}), imageBox); }), imageBox);
} }
}); }
}, 500); }, 500);
} }
injectFolderImages(); injectFolderImages();
window.SpicetifyLibrary.FolderImageWrapper.addEventListener("update", () => { FolderImageWrapper.addEventListener("update", injectFolderImages);
injectFolderImages();
});
function injectYLXButtons() { function injectYLXButtons() {
const ylx_filter = document.querySelector( const ylx_filter = document.querySelector(".main-yourLibraryX-libraryRootlist > .main-yourLibraryX-libraryFilter");
".main-yourLibraryX-libraryRootlist > .main-yourLibraryX-libraryFilter"
);
if (!ylx_filter) { if (!ylx_filter) {
return setTimeout(injectYLXButtons, 100); return setTimeout(injectYLXButtons, 100);
} }
@ -887,37 +964,17 @@ var library = (() => {
collapseButton 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"); const state = LocalStorageAPI.getItem("ylx-sidebar-state");
if (state === 0) { if (state === 0)
injectYLXButtons(); injectYLXButtons();
} else if (state === 1) {
injectExpandButton();
}
LocalStorageAPI.getEvents()._emitter.addListener("update", (e) => { LocalStorageAPI.getEvents()._emitter.addListener("update", (e) => {
const { key, value } = e.data; const { key, value } = e.data;
if (key === "ylx-sidebar-state" && value === 0) { if (key === "ylx-sidebar-state" && value === 0) {
injectFolderImages(); injectFolderImages();
injectYLXButtons(); injectYLXButtons();
removeExpandButton();
} }
if (key === "ylx-sidebar-state" && value === 1) { if (key === "ylx-sidebar-state" && value === 1) {
injectFolderImages(); injectFolderImages();
injectExpandButton();
} }
}); });
} }

View file

@ -8,6 +8,7 @@ var library = (() => {
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty; 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 __export = (target, all) => { var __export = (target, all) => {
for (var name in all) for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true }); __defProp(target, name, { get: all[name], enumerable: true });
@ -21,13 +22,17 @@ var library = (() => {
return to; return to;
}; };
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// src/extensions/folder_image_wrapper.ts // src/extensions/folder_image_wrapper.ts
var folder_image_wrapper_exports = {}; var folder_image_wrapper_exports = {};
__export(folder_image_wrapper_exports, { __export(folder_image_wrapper_exports, {
default: () => folder_image_wrapper_default default: () => folder_image_wrapper_default
}); });
var FolderImageWrapper = class extends EventTarget { var _FolderImageWrapper = class extends EventTarget {
_folderImages; _folderImages;
constructor() { constructor() {
super(); super();
@ -54,6 +59,9 @@ var library = (() => {
localStorage.setItem("library:folderImages", JSON.stringify(this._folderImages)); localStorage.setItem("library:folderImages", JSON.stringify(this._folderImages));
} }
}; };
var FolderImageWrapper = _FolderImageWrapper;
__publicField(FolderImageWrapper, "INSTANCE", new _FolderImageWrapper());
window.FolderImageWrapper = FolderImageWrapper.INSTANCE;
var folder_image_wrapper_default = FolderImageWrapper; var folder_image_wrapper_default = FolderImageWrapper;
return __toCommonJS(folder_image_wrapper_exports); return __toCommonJS(folder_image_wrapper_exports);
})(); })();

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8bc8b4/navBar.module.css */ /* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16f304/navBar.module.css */
.navBar-module__topBarHeaderItem___piw4C_library { .navBar-module__topBarHeaderItem___piw4C_library {
-webkit-app-region: no-drag; -webkit-app-region: no-drag;
display: inline-block; display: inline-block;
@ -46,7 +46,7 @@ div.navBar-module__topBarHeaderItemLink___xA4uv_library {
padding: 0; padding: 0;
} }
/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8baff0/app.css */ /* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16dc80/app.css */
:root { :root {
--library-card-size: 180px; --library-card-size: 180px;
--library-searchbar-size: 200px; --library-searchbar-size: 200px;
@ -57,6 +57,10 @@ div.navBar-module__topBarHeaderItemLink___xA4uv_library {
#library-app .grid { #library-app .grid {
grid-template-columns: repeat(auto-fill, minmax(var(--library-card-size), 1fr)) !important; grid-template-columns: repeat(auto-fill, minmax(var(--library-card-size), 1fr)) !important;
} }
#library-app .main-card-cardContainer {
width: 100%;
height: 100%;
}
#library-app .load-more-card { #library-app .load-more-card {
display: flex; display: flex;
gap: 10px; gap: 10px;
@ -100,7 +104,7 @@ div.navBar-module__topBarHeaderItemLink___xA4uv_library {
align-self: end; align-self: end;
} }
/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8bc361/external.css */ /* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16ee21/external.css */
body:not(.show-ylx-filters) .main-yourLibraryX-filterArea:not(:has(> .main-yourLibraryX-libraryFilter)), 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-header:not(:has(> .main-yourLibraryX-headerContent > .main-yourLibraryX-collapseButton > button:nth-child(2))),
.main-yourLibraryX-collapseButton > button:first-child, .main-yourLibraryX-collapseButton > button:first-child,
@ -113,10 +117,12 @@ body:not(.show-ylx-filters) .main-yourLibraryX-filterArea:not(:has(> .main-yourL
.main-yourLibraryX-header { .main-yourLibraryX-header {
margin-top: -8px; margin-top: -8px;
} }
.main-yourLibraryX-librarySortWrapper button span:first-child { .main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper button span:first-child,
.main-yourLibraryX-libraryFilter span[role=presentation] span[role=presentation] button span:first-child {
display: none; display: none;
} }
.main-yourLibraryX-librarySortWrapper { .main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper,
.main-yourLibraryX-libraryFilter span[role=presentation] {
margin-left: auto; margin-left: auto;
} }
.toggle-filters-button > button:after, .toggle-filters-button > button:after,
@ -140,21 +146,24 @@ li.main-yourLibraryX-navItem[data-id="/library"] {
li.main-yourLibraryX-navItem[data-id="/library"] > a { li.main-yourLibraryX-navItem[data-id="/library"] > a {
flex-grow: 1; flex-grow: 1;
} }
.toggle-filters-button > button, .main-yourLibraryX-libraryFilter .toggle-filters-button > button,
.collapse-button > button, .main-yourLibraryX-libraryFilter .collapse-button > button,
.main-yourLibraryX-librarySortWrapper > button { .main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper > button,
.main-yourLibraryX-libraryFilter span[role=presentation] span[role=presentation] > button {
padding: 0; padding: 0;
} }
.toggle-filters-button, .main-yourLibraryX-libraryFilter .toggle-filters-button,
.collapse-button, .main-yourLibraryX-libraryFilter .collapse-button,
.main-yourLibraryX-librarySortWrapper { .main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper,
.main-yourLibraryX-libraryFilter span[role=presentation] span[role=presentation] {
display: flex; display: flex;
flex-basis: 32px; flex-basis: 32px;
justify-content: center; justify-content: center;
min-width: 24px; min-width: 24px;
flex-shrink: 10; flex-shrink: 10;
} }
.main-yourLibraryX-librarySortWrapper > button > span:nth-child(2) { .main-yourLibraryX-libraryFilter .main-yourLibraryX-librarySortWrapper > button > span:nth-child(2),
.main-yourLibraryX-libraryFilter span[role=presentation] span[role=presentation] > button > span:nth-child(2) {
margin: 0; margin: 0;
} }
.LayoutResizer__resize-bar { .LayoutResizer__resize-bar {
@ -227,7 +236,7 @@ li.main-yourLibraryX-navItem[data-id="/library"] > a {
transform: scale(1.04); transform: scale(1.04);
} }
/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8bc5f2/config_modal.css */ /* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16f0a2/config_modal.css */
.config-container { .config-container {
gap: 10px; gap: 10px;
display: flex; display: flex;
@ -304,7 +313,7 @@ li.main-yourLibraryX-navItem[data-id="/library"] > a {
width: 200px; width: 200px;
} }
/* ../../../AppData/Local/Temp/tmp-5152-1Ex7Bvh4Tu6u/18f3cb8bc713/shared.css */ /* ../../../AppData/Local/Temp/tmp-4464-wbZ6O1BKhuot/19178f16f163/shared.css */
.grid { .grid {
--grid-gap: 24px; --grid-gap: 24px;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)) !important; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)) !important;
@ -327,6 +336,20 @@ li.main-yourLibraryX-navItem[data-id="/library"] > a {
flex-direction: column; flex-direction: column;
gap: 24px; gap: 24px;
} }
.badge {
position: absolute;
top: 3%;
left: 3%;
height: 30px;
width: 30px;
border-radius: 50%;
background-color: rgb(65, 110, 170);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
}
.page-header { .page-header {
align-content: space-between; align-content: space-between;
align-items: center; align-items: center;

View file

@ -29,4 +29,4 @@ custom_apps = library|lyrics-plus|marketplace|stats
; DO NOT CHANGE! ; DO NOT CHANGE!
[Backup] [Backup]
version = 1.2.42.290.g242057a2 version = 1.2.42.290.g242057a2
with = 2.37.1 with = 2.38.3