diff --git a/src/App.css b/src/App.css
index 20bba0e4..a674f063 100644
--- a/src/App.css
+++ b/src/App.css
@@ -2,6 +2,19 @@ body {
margin: 0;
}
+#search {
+ width: 100%;
+ background: black;
+ padding: 5px;
+ text-align: center;
+}
+
+#search input {
+ width: 100%;
+ border: none;
+ font-size: 40px;
+}
+
body.overlay-open {
overflow: hidden;
}
diff --git a/src/App.js b/src/App.js
index 8b1f9d08..5e379cf8 100644
--- a/src/App.js
+++ b/src/App.js
@@ -9,8 +9,6 @@ import * as Utils from "./utils";
import * as Selectors from "./redux/selectors";
import { SKIN_WIDTH, SKIN_HEIGHT, SKIN_RATIO } from "./constants";
-const hashes = Object.keys(skins);
-
const OVERSCAN_ROWS_LEADING = 10;
const OVERSCAN_ROWS_TRAILING = 4;
@@ -70,6 +68,7 @@ class App extends React.Component {
}
render() {
+ const hashes = this.props.skinHashes;
const columnCount = Math.floor(this.state.windowWidth / SKIN_WIDTH);
const columnWidth = this.state.windowWidth / columnCount; // TODO: Consider flooring this to get things aligned to the pixel
const rowHeight = columnWidth * SKIN_RATIO;
@@ -128,6 +127,14 @@ class App extends React.Component {
}
return (
+
+ this.props.setSearchQuery(e.target.value)}
+ value={this.props.searchQuery || ""}
+ placeholder={"Search Query"}
+ />
+
({
- selectedSkinHash: Selectors.getSelectedSkinHash(state)
+ selectedSkinHash: Selectors.getSelectedSkinHash(state),
+ searchQuery: Selectors.getSearchQuery(state),
+ skinHashes: Selectors.getMatchingSkinHashes(state)
});
const mapDispatchToProps = dispatch => ({
// TODO: Extract to action creator
setSelectedSkin(hash, position) {
dispatch({ type: "SELECT_SKIN", hash, position });
+ },
+ setSearchQuery(query) {
+ dispatch({ type: "SET_SEARCH_QUERY", query });
}
});
export default connect(
diff --git a/src/redux/selectors.js b/src/redux/selectors.js
index 31d20b2d..52bd288a 100644
--- a/src/redux/selectors.js
+++ b/src/redux/selectors.js
@@ -1,4 +1,5 @@
import * as Utils from "../utils";
+import skins from "../skins.json";
export function getSelectedSkinHash(state) {
return state.selectedSkinHash;
@@ -13,6 +14,23 @@ export function getSelectedSkinUrl(state) {
return hash == null ? null : Utils.screenshotUrlFromHash(hash);
}
+export function getSearchQuery(state) {
+ return state.searchQuery;
+}
+
+// TODO: Memoize this very expensive function
+export function getMatchingSkinHashes(state) {
+ const hashes = Object.keys(skins);
+ const searchQuery = getSearchQuery(state);
+ if (searchQuery == null) {
+ return hashes;
+ }
+ return hashes.filter(hash => {
+ const { fileName } = skins[hash];
+ return fileName.includes(searchQuery);
+ });
+}
+
export function getUrl(state) {
if (state.selectedSkinHash) {
// TODO: Add a human readable version
diff --git a/src/redux/store.js b/src/redux/store.js
index 4e77c6c4..4c10a132 100644
--- a/src/redux/store.js
+++ b/src/redux/store.js
@@ -2,6 +2,7 @@ import { createStore as createReduxStore } from "redux";
import * as Selectors from "./selectors";
const defaultState = {
+ searchQuery: null,
selectedSkinHash: null,
selectedSkinPosition: null
};
@@ -31,6 +32,11 @@ function reducer(state = defaultState, action) {
};
}
return defaultState;
+ case "SET_SEARCH_QUERY":
+ return {
+ ...state,
+ searchQuery: action.query
+ };
default:
return state;
}