Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(index): add search function #181

Merged
merged 8 commits into from
May 8, 2022
Merged
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 65 additions & 18 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/// <reference types="react-dom" />
/// <reference path="../spicetify-cli/globals.d.ts" />
/// <reference path="../spicetify-cli/jsHelper/spicetifyWrapper.js" />
/// <reference path="src/AddSnippetModal.js" />
/// <reference path="src/Card.js" />
/// <reference path="src/Icons.js" />
/// <reference path="src/Settings.js" />
Expand Down Expand Up @@ -142,6 +143,10 @@ const ITEMS_PER_REQUEST = 100;

let BLACKLIST = [];

// Search variables
let searchQuery = "";
let requested = false;

// eslint-disable-next-line no-redeclare, no-unused-vars
let gridUpdateTabs, gridUpdatePostsVisual;

Expand All @@ -150,6 +155,7 @@ class Grid extends react.Component {
super(props);
Object.assign(this, props);
this.state = {
searchValue: "",
cards: [],
tabs: CONFIG.tabs,
rest: true,
Expand Down Expand Up @@ -248,7 +254,8 @@ class Grid extends react.Component {
// Returns the next page number to fetch, or null if at end
// TODO: maybe we should rename `loadPage()`, since it's slightly confusing when we have github pages as well
async loadPage(queue) {
if (CONFIG.activeTab === "Extensions") {
switch (CONFIG.activeTab) {
case "Extensions": {
let pageOfRepos = await getExtensionRepos(requestPage);
for (const repo of pageOfRepos.items) {
let extensions = await fetchExtensionManifest(repo.contents_url, repo.default_branch, repo.stargazers_count);
Expand All @@ -275,7 +282,8 @@ class Grid extends react.Component {
console.log(`Parsed ${soFarResults}/${pageOfRepos.total_count} extensions`);
if (remainingResults > 0) return currentPage + 1;
else console.log("No more extension results");
} else if (CONFIG.activeTab === "Installed") {
break;
} case "Installed": {
const installedStuff = {
theme: getLocalStorageDataFromKey(LOCALSTORAGE_KEYS.installedThemes, []),
extension: getLocalStorageDataFromKey(LOCALSTORAGE_KEYS.installedExtensions, []),
Expand All @@ -298,10 +306,10 @@ class Grid extends react.Component {
});
}
}

break;
// Don't need to return a page number because
// installed extension do them all in one go, since it's local
} else if (CONFIG.activeTab == "Themes") {
} case "Themes": {
let pageOfRepos = await getThemeRepos(requestPage);
for (const repo of pageOfRepos.items) {

Expand All @@ -326,7 +334,8 @@ class Grid extends react.Component {
console.log(`Parsed ${soFarResults}/${pageOfRepos.total_count} themes`);
if (remainingResults > 0) return currentPage + 1;
else console.log("No more theme results");
} else if (CONFIG.activeTab == "Snippets") {
break;
} case "Snippets": {
let snippets = await fetchCssSnippets();

if (requestQueue.length > 1 && queue !== requestQueue[0]) {
Expand All @@ -336,8 +345,8 @@ class Grid extends react.Component {
if (snippets && snippets.length) {
snippets.forEach((snippet) => this.appendCard(snippet, "snippet"));
}

}
break;
}}

this.setState({ rest: true, endOfList: true });
endOfList = true;
Expand Down Expand Up @@ -537,21 +546,52 @@ class Grid extends react.Component {
}, SETTINGS_ICON),
// End of marketplace-header__right
),
// TODO: Add search bar and sort functionality
// react.createElement("div", {
// className: "searchbar--bar__wrapper",
// }, react.createElement("input", {
// className: "searchbar-bar",
// type: "text",
// placeholder: "Search for Extensions?",
// })),
react.createElement("div", {
className: "searchbar--bar__wrapper",
}, react.createElement("input", {
className: "searchbar-bar",
type: "text",
placeholder: "Search",
value: this.state.searchValue,
onChange: (event) => {
this.setState({ searchValue: event.target.value });
searchQuery = event.target.value;
},
onKeyDown: (event) => {
if (event.key === "Enter") {
this.setState({ endOfList: false });
endOfList = false;
this.newRequest(ITEMS_PER_REQUEST);
requested = true;
} else if ( // Refreshes result when user deletes all queries
((event.key === "Backspace") || (event.key === "Delete")) &&
requested &&
this.state.searchValue.trim() === ""
) {
this.setState({ endOfList: false });
endOfList = false;
theRealPadster marked this conversation as resolved.
Show resolved Hide resolved
this.newRequest(ITEMS_PER_REQUEST);
requested = false;
}
},
})),
),
[ // Add a header and grid for each card type if it has any cards
{ handle: "extension", name: "Extensions" },
{ handle: "theme", name: "Themes" },
{ handle: "snippet", name: "Snippets" },
].map((cardType) => {
const cardsOfType = cardList.filter((card) => card.props.type === cardType.handle)
.filter((card) => { // Search filter
const { searchValue } = this.state;
const { title, user } = card.props;

if (
searchValue.trim() === "" ||
title.toLowerCase().includes(searchValue.trim().toLowerCase()) ||
user.toLowerCase().includes(searchValue.trim().toLowerCase())
) return card;
})
.map((card) => {
// Clone the cards and update the prop to trigger re-render
// TODO: is it possible to only re-render the theme cards whose status have changed?
Expand Down Expand Up @@ -610,7 +650,10 @@ class Grid extends react.Component {
*/
async function getExtensionRepos(page = 1) {
// www is needed or it will block with "cross-origin" error.
let url = `https://api.github.com/search/repositories?q=${encodeURIComponent("topic:spicetify-extensions")}&per_page=${ITEMS_PER_REQUEST}`;
let url = `https://api.github.com/search/repositories?q=${encodeURIComponent(`topic:spicetify-extensions`)}&per_page=${ITEMS_PER_REQUEST}`;
kyrie25 marked this conversation as resolved.
Show resolved Hide resolved
if (searchQuery?.trim() !== "") {
url = `https://api.github.com/search/repositories?q=${encodeURIComponent(`${searchQuery} topic:spicetify-extensions`)}&per_page=${ITEMS_PER_REQUEST}`;
kyrie25 marked this conversation as resolved.
Show resolved Hide resolved
}

// We can test multiple pages with this URL (58 results), as well as broken iamges etc.
// let url = `https://api.github.com/search/repositories?q=${encodeURIComponent("topic:spicetify")}`;
Expand All @@ -621,6 +664,7 @@ async function getExtensionRepos(page = 1) {
const allRepos = await fetch(url).then(res => res.json()).catch(() => []);
if (!allRepos.items) {
Spicetify.showNotification("Too Many Requests, Cool Down.");
return null;
}
const filteredResults = {
...allRepos,
Expand Down Expand Up @@ -804,7 +848,9 @@ async function fetchThemeManifest(contents_url, branch, stars) {
*/
async function getThemeRepos(page = 1) {
theRealPadster marked this conversation as resolved.
Show resolved Hide resolved
let url = `https://api.github.com/search/repositories?q=${encodeURIComponent("topic:spicetify-themes")}&per_page=${ITEMS_PER_REQUEST}`;

if (searchQuery?.trim() !== "") {
url = `https://api.github.com/search/repositories?q=${encodeURIComponent(`${searchQuery} topic:spicetify-themes`)}&per_page=${ITEMS_PER_REQUEST}`;
kyrie25 marked this conversation as resolved.
Show resolved Hide resolved
}
// We can test multiple pages with this URL (58 results), as well as broken iamges etc.
// let url = `https://api.github.com/search/repositories?q=${encodeURIComponent("topic:spicetify")}`;
if (page) url += `&page=${page}`;
Expand All @@ -814,6 +860,7 @@ async function getThemeRepos(page = 1) {
const allThemes = await fetch(url).then(res => res.json()).catch(() => []);
if (!allThemes.items) {
Spicetify.showNotification("Too Many Requests, Cool Down.");
return null;
}
const filteredResults = {
...allThemes,
Expand All @@ -826,7 +873,7 @@ async function getThemeRepos(page = 1) {
return filteredResults;
}
function addToSessionStorage(items, key) {
if (!items || items == null) return;
if (!items) return;
theRealPadster marked this conversation as resolved.
Show resolved Hide resolved
items.forEach(item => {
if (!key) key = `${items.user}-${items.repo}`;
// If the key already exists, it will append to it instead of overwriting it
Expand Down