diff --git a/src/About.js b/src/About.js
new file mode 100644
index 00000000..e665b5a4
--- /dev/null
+++ b/src/About.js
@@ -0,0 +1,38 @@
+import React from "react";
+
+function About() {
+ return (
+
+
About
+
+ The Winamp Skin Museum is an attempt to build a fast ,{" "}
+ searchable , and shareable , interface for the collection of
+ Winamp Skins amassed by the{" "}
+ Internet Archive .
+
+
Features:
+
+
+ Infinite scroll preview images.
+
+
+ Experience skins with integrated{" "}
+ Webamp .
+
+
+ Fast search of indexed readme.txt texts.
+
+
+
+ Made by Jordan Eldredge (
+ @captbaritone ).
+
+
+ Come hang out with us in our{" "}
+ Discord server .
+
+
+ );
+}
+
+export default About;
diff --git a/src/App.css b/src/App.css
index b9a0464d..ed41b6b0 100644
--- a/src/App.css
+++ b/src/App.css
@@ -29,8 +29,12 @@ buton {
h1 {
font-size: 20px;
}
+h2 {
+ font-size: 17px;
+}
h1 a {
text-decoration: none;
+ color: rgba(255, 2550, 2550, 0.9);
}
#search h1 #logo {
@@ -39,7 +43,6 @@ h1 a {
#search h1 .name {
margin: 0 30px 0 0px;
- color: rgba(255, 2550, 2550, 0.9);
}
button {
@@ -98,6 +101,7 @@ button:active {
flex-direction: row;
align-items: center;
border-bottom: 2px solid rgb(32, 31, 51);
+ color: rgba(255, 2550, 2550, 0.9);
}
#search input {
@@ -204,3 +208,13 @@ body.overlay-open .overlay {
display: none;
}
}
+
+.static-content {
+ position: fixed;
+ background-color: white;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ padding: 30px;
+ line-height: 1.4em;
+}
diff --git a/src/App.js b/src/App.js
index bbd67944..68f7a6e0 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,11 +1,13 @@
import React from "react";
import { connect } from "react-redux";
import Head from "./Head";
+import About from "./About";
import Header from "./Header";
import Overlay from "./Overlay";
import SkinTable from "./SkinTable";
import FocusedSkin from "./FocusedSkin";
import * as Selectors from "./redux/selectors";
+import { ABOUT_PAGE } from "./constants";
// Render your table
@@ -34,10 +36,20 @@ class App extends React.Component {
this.setState({ rowHeight, columnWidth })
}
/>
- {!this._sizeIsSet() || this.props.selectedSkinHash == null || (
-
-
+ {this.props.aboutPage ? (
+
+
+ ) : (
+ !this._sizeIsSet() ||
+ this.props.selectedSkinHash == null || (
+
+
+
+ )
)}
);
@@ -46,7 +58,8 @@ class App extends React.Component {
const mapStateToProps = state => ({
selectedSkinHash: Selectors.getSelectedSkinHash(state),
- overlayShouldAnimate: Selectors.overlayShouldAnimate(state)
+ overlayShouldAnimate: Selectors.overlayShouldAnimate(state),
+ aboutPage: Selectors.getActiveContentPage(state) === ABOUT_PAGE
});
export default connect(mapStateToProps)(App);
diff --git a/src/Header.js b/src/Header.js
index 3fd8b7ce..e0a630c7 100644
--- a/src/Header.js
+++ b/src/Header.js
@@ -54,7 +54,6 @@ class Header extends React.Component {
this.props.setSearchQuery(e.target.value)}
value={this.props.searchQuery || ""}
placeholder={"Search..."}
@@ -63,13 +62,19 @@ class Header extends React.Component {
}}
/>
{
this.props.requestRandomSkin();
}}
>
Random
+ {
+ this.props.requestedAboutPage();
+ }}
+ >
+ ?
+
);
}
@@ -85,6 +90,9 @@ const mapDispatchToProps = dispatch => ({
},
requestRandomSkin() {
dispatch(Actions.requestedRandomSkin());
+ },
+ requestedAboutPage() {
+ dispatch(Actions.requestedAboutPage());
}
});
export default connect(
diff --git a/src/constants.js b/src/constants.js
index 2e3e496f..ede533ba 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -4,3 +4,4 @@ export const SCALE = 1 / 2;
export const SKIN_WIDTH = SCREENSHOT_WIDTH * SCALE;
export const SKIN_HEIGHT = SCREENSHOT_HEIGHT * SCALE;
export const SKIN_RATIO = SKIN_HEIGHT / SKIN_WIDTH;
+export const ABOUT_PAGE = "ABOUT_PAGE";
diff --git a/src/redux/actionCreators.js b/src/redux/actionCreators.js
index bb5840c3..ed5c30a6 100644
--- a/src/redux/actionCreators.js
+++ b/src/redux/actionCreators.js
@@ -34,3 +34,7 @@ export function selectSkinFile(fileName) {
export function gotFocusedSkinFile(content) {
return { type: "GOT_FOCUSED_SKIN_FILE", content };
}
+
+export function requestedAboutPage() {
+ return { type: "REQUESTED_ABOUT_PAGE" };
+}
diff --git a/src/redux/epics.js b/src/redux/epics.js
index aed29059..84f02b36 100644
--- a/src/redux/epics.js
+++ b/src/redux/epics.js
@@ -10,6 +10,9 @@ const urlChangedEpic = actions =>
actions.pipe(
filter(action => action.type === "URL_CHANGED"),
switchMap(action => {
+ if (action.location.pathname == "/about/") {
+ return of(Actions.requestedAboutPage());
+ }
const params = new URLSearchParams(action.location.search);
const query = params != null && params.get("query");
diff --git a/src/redux/selectors.js b/src/redux/selectors.js
index 54aed78a..f10714a0 100644
--- a/src/redux/selectors.js
+++ b/src/redux/selectors.js
@@ -1,5 +1,6 @@
import * as Utils from "../utils";
import skins from "../skins.json";
+import { ABOUT_PAGE } from "../constants";
export function getSelectedSkinHash(state) {
return state.selectedSkinHash;
@@ -40,6 +41,9 @@ export function getRandomSkinHash() {
}
export function getUrl(state) {
+ if (state.activeContentPage === ABOUT_PAGE) {
+ return "/about/";
+ }
const hash = getSelectedSkinHash(state);
const query = getSearchQuery(state);
if (hash) {
@@ -59,3 +63,7 @@ export function getPreviewImageUrl(state) {
const hash = getSelectedSkinHash(state);
return hash == null ? null : Utils.screenshotUrlFromHash(hash);
}
+
+export function getActiveContentPage(state) {
+ return state.activeContentPage;
+}
diff --git a/src/redux/store.js b/src/redux/store.js
index 14b204f9..872c0210 100644
--- a/src/redux/store.js
+++ b/src/redux/store.js
@@ -2,6 +2,7 @@ import { createStore as createReduxStore, applyMiddleware } from "redux";
import { createEpicMiddleware } from "redux-observable";
import * as Selectors from "./selectors";
import rootEpic from "./epics";
+import { ABOUT_PAGE } from "../constants";
const defaultState = {
searchQuery: null,
@@ -9,7 +10,8 @@ const defaultState = {
selectedSkinPosition: null,
matchingHashes: null,
skinZip: null,
- focusedSkinFile: null
+ focusedSkinFile: null,
+ activeContentPage: null
};
function reducer(state = defaultState, action) {
@@ -26,7 +28,8 @@ function reducer(state = defaultState, action) {
...state,
selectedSkinHash: null,
selectedSkinPosition: null,
- skinZip: null
+ skinZip: null,
+ activeContentPage: null
};
case "SEARCH_QUERY_CHANGED":
return {
@@ -63,6 +66,11 @@ function reducer(state = defaultState, action) {
content: action.content
}
};
+ case "REQUESTED_ABOUT_PAGE":
+ return {
+ ...state,
+ activeContentPage: ABOUT_PAGE
+ };
default:
return state;
}