mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-23 18:17:38 +00:00
Move extracting the zip to the epic/store
This commit is contained in:
parent
5ff53e39f2
commit
4e0d362c96
4 changed files with 126 additions and 50 deletions
131
src/Readme.js
131
src/Readme.js
|
|
@ -1,66 +1,109 @@
|
|||
import React from "react";
|
||||
import JSZip from "jszip";
|
||||
import { connect } from "react-redux";
|
||||
import { switchMap } from "rxjs/operators";
|
||||
import { from, empty } from "rxjs";
|
||||
import { from } from "rxjs";
|
||||
import Disposable from "./Disposable";
|
||||
|
||||
export default class Readme extends React.Component {
|
||||
class Readme extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this._disposable = new Disposable();
|
||||
this.state = { readmeText: null };
|
||||
this.state = { focusedFile: null };
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._fetchReadme();
|
||||
}
|
||||
componentDidMount() {}
|
||||
|
||||
componentDidUpdate(_, oldState) {
|
||||
if (this.state.skinUrl != oldState.skinUrl) {
|
||||
this._fetchReadme();
|
||||
}
|
||||
}
|
||||
componentDidUpdate(_, oldState) {}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._disposable.dispose();
|
||||
}
|
||||
|
||||
_fetchReadme() {
|
||||
this._disposable.add(
|
||||
from(fetch(this.props.skinUrl))
|
||||
.pipe(
|
||||
switchMap(response => response.blob()),
|
||||
switchMap(blob => JSZip.loadAsync(blob)),
|
||||
switchMap(zip => {
|
||||
const readme = zip.file("readme.txt");
|
||||
if (readme == null) {
|
||||
return empty();
|
||||
}
|
||||
return readme.async("string");
|
||||
})
|
||||
)
|
||||
.subscribe(text => {
|
||||
console.log(text);
|
||||
// this.setState({ readmeText: text });
|
||||
})
|
||||
);
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.state.focusedFile.type) {
|
||||
case "txt":
|
||||
return (
|
||||
<textarea
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "300px"
|
||||
}}
|
||||
>
|
||||
{this.state.focusedFile.content}
|
||||
</textarea>
|
||||
);
|
||||
case "bmp":
|
||||
case "cur":
|
||||
const mimeType = `image/cur`;
|
||||
const content = URL.createObjectURL(
|
||||
new Blob([this.state.focusedFile.content], { type: mimeType })
|
||||
);
|
||||
return <img src={content} />;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
this.state.readmeText && (
|
||||
<pre
|
||||
style={{
|
||||
backgroundColor: "white",
|
||||
color: "black",
|
||||
position: "absolute",
|
||||
width: "500px",
|
||||
right: 0
|
||||
}}
|
||||
>
|
||||
{this.state.readmeText}
|
||||
</pre>
|
||||
)
|
||||
<div
|
||||
style={{
|
||||
position: "fixed",
|
||||
width: 500,
|
||||
left: 0,
|
||||
height: "100%",
|
||||
backgroundColor: "white",
|
||||
overflow: "scroll"
|
||||
}}
|
||||
>
|
||||
<ul style={{ float: "left" }}>
|
||||
{this.props.zip &&
|
||||
Object.keys(this.props.zip.files).map(fileName => (
|
||||
<li
|
||||
key={fileName}
|
||||
style={{
|
||||
fontWeight:
|
||||
this.state.focusedFile &&
|
||||
this.state.focusedFile.fileName === fileName
|
||||
? "bold"
|
||||
: "normal"
|
||||
}}
|
||||
>
|
||||
<a onClick={() => this._focusFile(fileName)}>{fileName}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div style={{ float: "left" }}>{this._renderFocusedFile()}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
zip: state.skinZip
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Readme);
|
||||
|
|
|
|||
|
|
@ -17,3 +17,7 @@ export function requestedRandomSkin() {
|
|||
export function gotNewMatchingHashes(matchingHashes) {
|
||||
return { type: "GOT_NEW_MATCHING_HASHES", matchingHashes };
|
||||
}
|
||||
|
||||
export function loadedSkinZip(zip) {
|
||||
return { type: "LOADED_SKIN_ZIP", zip };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { combineEpics } from "redux-observable";
|
||||
import { of, from } from "rxjs";
|
||||
import { of, from, empty } from "rxjs";
|
||||
import * as Actions from "./actionCreators";
|
||||
import * as Selectors from "./selectors";
|
||||
import { filter, switchMap, map } from "rxjs/operators";
|
||||
import * as Utils from "../utils";
|
||||
import { filter, switchMap, map, ignoreElements, tap } from "rxjs/operators";
|
||||
import { search } from "../algolia";
|
||||
|
||||
const urlChangedEpic = actions =>
|
||||
|
|
@ -20,6 +21,21 @@ const urlChangedEpic = actions =>
|
|||
})
|
||||
);
|
||||
|
||||
const selectedSkinEpic = actions =>
|
||||
actions.pipe(
|
||||
filter(action => action.type === "SELECTED_SKIN"),
|
||||
switchMap(action => {
|
||||
return from(fetch(Utils.skinUrlFromHash(action.hash))).pipe(
|
||||
switchMap(response => response.blob()),
|
||||
switchMap(async blob => {
|
||||
const JSZip = await import("jszip");
|
||||
return JSZip.loadAsync(blob);
|
||||
}),
|
||||
map(zip => Actions.loadedSkinZip(zip))
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
const searchEpic = actions =>
|
||||
actions.pipe(
|
||||
filter(action => action.type === "SEARCH_QUERY_CHANGED"),
|
||||
|
|
@ -44,4 +60,9 @@ const randomSkinEpic = (actions, states) =>
|
|||
return Actions.selectedSkin(Selectors.getRandomSkinHash(states.value));
|
||||
})
|
||||
);
|
||||
export default combineEpics(searchEpic, urlChangedEpic, randomSkinEpic);
|
||||
export default combineEpics(
|
||||
searchEpic,
|
||||
urlChangedEpic,
|
||||
selectedSkinEpic,
|
||||
randomSkinEpic
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ const defaultState = {
|
|||
searchQuery: null,
|
||||
selectedSkinHash: null,
|
||||
selectedSkinPosition: null,
|
||||
matchingHashes: null
|
||||
matchingHashes: null,
|
||||
skinZip: null
|
||||
};
|
||||
|
||||
function reducer(state = defaultState, action) {
|
||||
|
|
@ -16,13 +17,15 @@ function reducer(state = defaultState, action) {
|
|||
return {
|
||||
...state,
|
||||
selectedSkinHash: action.hash,
|
||||
selectedSkinPosition: action.position
|
||||
selectedSkinPosition: action.position,
|
||||
skinZip: null
|
||||
};
|
||||
case "CLOSE_MODAL":
|
||||
return {
|
||||
...state,
|
||||
selectedSkinHash: null,
|
||||
selectedSkinPosition: null
|
||||
selectedSkinPosition: null,
|
||||
skinZip: null
|
||||
};
|
||||
case "SEARCH_QUERY_CHANGED":
|
||||
return {
|
||||
|
|
@ -36,6 +39,11 @@ function reducer(state = defaultState, action) {
|
|||
...state,
|
||||
matchingHashes: action.matchingHashes
|
||||
};
|
||||
case "LOADED_SKIN_ZIP":
|
||||
return {
|
||||
...state,
|
||||
skinZip: action.zip
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue