mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-23 18:17:38 +00:00
Improve skin inspector
This commit is contained in:
parent
4e0d362c96
commit
017a4f661d
5 changed files with 99 additions and 64 deletions
100
src/Readme.js
100
src/Readme.js
|
|
@ -1,49 +1,19 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { switchMap } from "rxjs/operators";
|
||||
import { from } from "rxjs";
|
||||
import Disposable from "./Disposable";
|
||||
import * as Actions from "./redux/actionCreators";
|
||||
|
||||
class Readme extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this._disposable = new Disposable();
|
||||
this.state = { focusedFile: null };
|
||||
}
|
||||
|
||||
componentDidMount() {}
|
||||
|
||||
componentDidUpdate(_, oldState) {}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._disposable.dispose();
|
||||
}
|
||||
|
||||
async _focusFile(fileName) {
|
||||
if (this.props.zip == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const file = await this.props.zip.file(fileName);
|
||||
const type = fileName
|
||||
.split(".")
|
||||
.pop()
|
||||
.toLowerCase();
|
||||
const methodFromType = {
|
||||
txt: "string",
|
||||
bmp: "blob",
|
||||
cur: "blob"
|
||||
};
|
||||
let content = await file.async(methodFromType[type]);
|
||||
this.setState({ focusedFile: { fileName, type, content } });
|
||||
}
|
||||
|
||||
_renderFocusedFile() {
|
||||
if (this.state.focusedFile == null) {
|
||||
if (this.props.focusedFile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.state.focusedFile.type) {
|
||||
const { ext, fileName, content } = this.props.focusedFile;
|
||||
if (content == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ext) {
|
||||
case "txt":
|
||||
return (
|
||||
<textarea
|
||||
|
|
@ -51,17 +21,18 @@ class Readme extends React.Component {
|
|||
width: "100%",
|
||||
height: "300px"
|
||||
}}
|
||||
>
|
||||
{this.state.focusedFile.content}
|
||||
</textarea>
|
||||
defaultValue={content}
|
||||
/>
|
||||
);
|
||||
case "bmp":
|
||||
case "cur":
|
||||
const mimeType = `image/cur`;
|
||||
const content = URL.createObjectURL(
|
||||
new Blob([this.state.focusedFile.content], { type: mimeType })
|
||||
const mimeType = `image/${ext}`;
|
||||
const url = URL.createObjectURL(
|
||||
new Blob([content], { type: mimeType })
|
||||
);
|
||||
return <img src={content} />;
|
||||
return <img src={url} alt={fileName} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,24 +48,22 @@ class Readme extends React.Component {
|
|||
overflow: "scroll"
|
||||
}}
|
||||
>
|
||||
<ul style={{ float: "left" }}>
|
||||
<select onChange={e => this.props.selectSkinFile(e.target.value)}>
|
||||
{this.props.zip &&
|
||||
Object.keys(this.props.zip.files).map(fileName => (
|
||||
<li
|
||||
<option
|
||||
key={fileName}
|
||||
style={{
|
||||
fontWeight:
|
||||
this.state.focusedFile &&
|
||||
this.state.focusedFile.fileName === fileName
|
||||
? "bold"
|
||||
: "normal"
|
||||
}}
|
||||
value={fileName}
|
||||
selected={
|
||||
this.props.focusedFile &&
|
||||
this.props.focusedFile.fileName === fileName
|
||||
}
|
||||
>
|
||||
<a onClick={() => this._focusFile(fileName)}>{fileName}</a>
|
||||
</li>
|
||||
{fileName}
|
||||
</option>
|
||||
))}
|
||||
</ul>
|
||||
<div style={{ float: "left" }}>{this._renderFocusedFile()}</div>
|
||||
</select>
|
||||
<div>{this._renderFocusedFile()}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -102,8 +71,19 @@ class Readme extends React.Component {
|
|||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
zip: state.skinZip
|
||||
zip: state.skinZip,
|
||||
focusedFile: state.focusedSkinFile
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Readme);
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
selectSkinFile(fileName) {
|
||||
dispatch(Actions.selectSkinFile(fileName));
|
||||
}
|
||||
};
|
||||
}
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(Readme);
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ class SkinTable extends React.Component {
|
|||
_handleResize() {
|
||||
const { windowWidth, windowHeight } = Utils.getWindowSize();
|
||||
if (
|
||||
windowWidth != this.state.windowWidth ||
|
||||
windowHeight != this.state.windowHeight
|
||||
windowWidth !== this.state.windowWidth ||
|
||||
windowHeight !== this.state.windowHeight
|
||||
) {
|
||||
this.setState({ windowWidth, windowHeight });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,3 +21,16 @@ export function gotNewMatchingHashes(matchingHashes) {
|
|||
export function loadedSkinZip(zip) {
|
||||
return { type: "LOADED_SKIN_ZIP", zip };
|
||||
}
|
||||
|
||||
export function selectSkinFile(fileName) {
|
||||
const ext = fileName
|
||||
.split(".")
|
||||
.pop()
|
||||
.toLowerCase();
|
||||
|
||||
return { type: "SELECTED_SKIN_FILE_TO_FOCUS", fileName, ext };
|
||||
}
|
||||
|
||||
export function gotFocusedSkinFile(content) {
|
||||
return { type: "GOT_FOCUSED_SKIN_FILE", content };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { of, from, empty } from "rxjs";
|
|||
import * as Actions from "./actionCreators";
|
||||
import * as Selectors from "./selectors";
|
||||
import * as Utils from "../utils";
|
||||
import { filter, switchMap, map, ignoreElements, tap } from "rxjs/operators";
|
||||
import { filter, switchMap, map, tap } from "rxjs/operators";
|
||||
import { search } from "../algolia";
|
||||
|
||||
const urlChangedEpic = actions =>
|
||||
|
|
@ -36,6 +36,28 @@ const selectedSkinEpic = actions =>
|
|||
})
|
||||
);
|
||||
|
||||
const focusedSkinFileEpic = (actions, states) =>
|
||||
actions.pipe(
|
||||
filter(action => action.type === "SELECTED_SKIN_FILE_TO_FOCUS"),
|
||||
switchMap(({ fileName, ext }) => {
|
||||
// TODO: Ensure this is never called with the wrong zip. Should this live in the "got zip" closure?
|
||||
const { skinZip } = states.value;
|
||||
if (skinZip == null) {
|
||||
// TODO: Should this throw?
|
||||
return empty();
|
||||
}
|
||||
|
||||
const methodFromExt = {
|
||||
txt: "string",
|
||||
bmp: "blob",
|
||||
cur: "blob"
|
||||
};
|
||||
return from(skinZip.file(fileName).async(methodFromExt[ext])).pipe(
|
||||
map(content => Actions.gotFocusedSkinFile(content))
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
const searchEpic = actions =>
|
||||
actions.pipe(
|
||||
filter(action => action.type === "SEARCH_QUERY_CHANGED"),
|
||||
|
|
@ -64,5 +86,6 @@ export default combineEpics(
|
|||
searchEpic,
|
||||
urlChangedEpic,
|
||||
selectedSkinEpic,
|
||||
focusedSkinFileEpic,
|
||||
randomSkinEpic
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ const defaultState = {
|
|||
selectedSkinHash: null,
|
||||
selectedSkinPosition: null,
|
||||
matchingHashes: null,
|
||||
skinZip: null
|
||||
skinZip: null,
|
||||
focusedSkinFile: null
|
||||
};
|
||||
|
||||
function reducer(state = defaultState, action) {
|
||||
|
|
@ -44,6 +45,24 @@ function reducer(state = defaultState, action) {
|
|||
...state,
|
||||
skinZip: action.zip
|
||||
};
|
||||
case "SELECTED_SKIN_FILE_TO_FOCUS": {
|
||||
return {
|
||||
...state,
|
||||
focusedSkinFile: {
|
||||
content: null,
|
||||
ext: action.ext,
|
||||
fileName: action.fileName
|
||||
}
|
||||
};
|
||||
}
|
||||
case "GOT_FOCUSED_SKIN_FILE":
|
||||
return {
|
||||
...state,
|
||||
focusedSkinFile: {
|
||||
...state.focusedSkinFile,
|
||||
content: action.content
|
||||
}
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue