diff --git a/src/components/Grid.tsx b/src/components/Grid.tsx index 47a72f7d..ec8156ac 100644 --- a/src/components/Grid.tsx +++ b/src/components/Grid.tsx @@ -5,7 +5,15 @@ import semver from "semver"; const Spicetify = window.Spicetify; import { ITEMS_PER_REQUEST, LATEST_RELEASE_URL, LOCALSTORAGE_KEYS, MARKETPLACE_VERSION } from "../constants"; -import { fetchAppManifest, fetchCssSnippets, fetchExtensionManifest, fetchThemeManifest, getBlacklist, getTaggedRepos } from "../logic/FetchRemotes"; +import { + fetchAppManifest, + fetchCssSnippets, + fetchExtensionManifest, + fetchRemoteSnippetsManifest, + fetchThemeManifest, + getBlacklist, + getTaggedRepos +} from "../logic/FetchRemotes"; import { openModal } from "../logic/LaunchModals"; import { generateSchemesOptions, generateSortOptions, getLocalStorageDataFromKey, injectColourScheme, sortCardItems } from "../logic/Utils"; import type { CardItem, CardType, Config, SchemeIni, Snippet, TabItemConfig } from "../types/marketplace-types"; @@ -350,7 +358,23 @@ class Grid extends React.Component< break; } case "Snippets": { - const snippets = this.SNIPPETS; + const pageOfRepos = await getTaggedRepos("spicetify-snippets", this.requestPage, this.BLACKLIST, this.CONFIG.visual.showArchived); + const remoteSnippets: Snippet[] = []; + for (const repo of pageOfRepos.items) { + const repoSnippets = await fetchRemoteSnippetsManifest(repo.contents_url, repo.default_branch, this.CONFIG.visual.hideInstalled); + + // I believe this stops the requests when switching tabs? + if (this.requestQueue.length > 1 && queue !== this.requestQueue[0]) { + // Stop this queue from continuing to fetch and append to cards list + return -1; + } + + if (repoSnippets?.length) { + remoteSnippets.push(...repoSnippets); + } + } + + const snippets = this.SNIPPETS?.concat(remoteSnippets); if (this.requestQueue.length > 1 && queue !== this.requestQueue[0]) { // Stop this queue from continuing to fetch and append to cards list diff --git a/src/logic/FetchRemotes.ts b/src/logic/FetchRemotes.ts index fa69383e..442c622b 100644 --- a/src/logic/FetchRemotes.ts +++ b/src/logic/FetchRemotes.ts @@ -83,6 +83,7 @@ async function fetchRepoManifest(url: string) { * @param branch Default branch name (e.g. main or master) * @returns The manifest object */ + async function getRepoManifest(user: string, repo: string, branch: string) { const key = `${user}-${repo}`; const sessionStorageItem = window.sessionStorage.getItem(key); @@ -335,3 +336,42 @@ export const fetchCssSnippets = async (hideInstalled = false) => { return snippets; }; + +export const fetchRemoteSnippetsManifest = async (contents_url: string, branch: string, hideInstalled = false) => { + try { + const regex_result = contents_url.match(/https:\/\/api\.github\.com\/repos\/(?.+)\/(?.+)\/contents/); + + // TODO: err handling? + if (!regex_result || !regex_result.groups) return null; + const { user, repo } = regex_result.groups; + + const manifests = await getRepoManifest(user, repo, branch); + + // Manifest is initially parsed + const parsedManifests: Snippet[] = manifests.reduce((accum, manifest) => { + const selectedBranch = manifest.branch || branch; + + // Check if manifest object is designated for a Snippet + if (manifest?.title && manifest.description && manifest.code && !manifest.main && !manifest.usercss) { + const item = { + title: manifest.title, + description: manifest.description, + code: manifest.code, + imageURL: manifest.preview?.startsWith("http") + ? manifest.preview + : `https://raw.githubusercontent.com/${user}/${repo}/${selectedBranch}/${manifest.preview}` + }; + + // Add to list unless we're hiding installed items and it's installed + if (!(hideInstalled && localStorage.getItem(`marketplace:installed:snippet:${manifest.title.replaceAll(" ", "-")}`))) { + accum.push(item); + } + } + return accum; + }, []); + + return parsedManifests; + } catch { + return null; + } +}; diff --git a/src/types/marketplace-types.d.ts b/src/types/marketplace-types.d.ts index 20d79cb6..daadc595 100644 --- a/src/types/marketplace-types.d.ts +++ b/src/types/marketplace-types.d.ts @@ -15,7 +15,7 @@ export type SortBoxOption = { value: string; }; -export type RepoTopic = "spicetify-extensions" | "spicetify-themes" | "spicetify-apps"; +export type RepoTopic = "spicetify-extensions" | "spicetify-themes" | "spicetify-apps" | "spicetify-snippets"; export type TabType = "Extensions" | "Themes" | "Snippets" | "Apps" | "Installed";