mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-19 01:23:49 +00:00
Introduce first taste of React
Future PRs will move more code to React, but this seemed like a good place to start.
This commit is contained in:
parent
6a3e0bf214
commit
9d73441989
8 changed files with 200 additions and 168 deletions
3
.babelrc
Normal file
3
.babelrc
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"presets": ["react", "es2015"]
|
||||
}
|
||||
178
.eslintrc
178
.eslintrc
|
|
@ -1,9 +1,18 @@
|
|||
{
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
},
|
||||
"ecmaFeatures": {
|
||||
"modules": true
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "15.2"
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
|
|
@ -13,86 +22,87 @@
|
|||
},
|
||||
|
||||
"rules": {
|
||||
"block-scoped-var": 1,
|
||||
"brace-style": [1, "1tbs"],
|
||||
"camelcase": 2,
|
||||
"comma-dangle": [2, "never"],
|
||||
"comma-spacing": 2,
|
||||
"consistent-return": 1,
|
||||
"dot-notation": [2, { "allowKeywords": false }],
|
||||
"eol-last": 2,
|
||||
"eqeqeq": [2, "smart"],
|
||||
"guard-for-in": 2,
|
||||
"indent": [2, 2, {"SwitchCase": 1}],
|
||||
"key-spacing": 1,
|
||||
"linebreak-style": 2,
|
||||
"max-depth": [1, 4],
|
||||
"max-params": [1, 5],
|
||||
"new-cap": 2,
|
||||
"no-alert": 2,
|
||||
"no-caller": 2,
|
||||
"no-catch-shadow": 2,
|
||||
"no-debugger": 2,
|
||||
"no-delete-var": 2,
|
||||
"no-div-regex": 1,
|
||||
"no-dupe-args": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
"no-else-return": 1,
|
||||
"no-empty-character-class": 2,
|
||||
"no-empty-label": 2,
|
||||
"no-eval": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extend-native": 1,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-semi": 2,
|
||||
"no-fallthrough": 2,
|
||||
"no-floating-decimal": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-implied-eval": 2,
|
||||
"no-inner-declarations": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-label-var": 2,
|
||||
"no-lone-blocks": 2,
|
||||
"no-lonely-if": 2,
|
||||
"no-multi-spaces": 1,
|
||||
"no-multi-str": 2,
|
||||
"no-native-reassign": 2,
|
||||
"no-negated-in-lhs": 1,
|
||||
"no-nested-ternary": 2,
|
||||
"no-new-object": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-octal": 2,
|
||||
"no-octal-escape": 2,
|
||||
"no-proto": 2,
|
||||
"no-redeclare": 2,
|
||||
"no-shadow": 2,
|
||||
"no-spaced-func": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-trailing-spaces": 2,
|
||||
"no-undef": 2,
|
||||
"no-undef-init": 2,
|
||||
"no-undefined": 2,
|
||||
"no-unneeded-ternary": 2,
|
||||
"no-unreachable": 2,
|
||||
"no-unused-expressions": 2,
|
||||
"no-unused-vars": 2,
|
||||
"no-use-before-define": [2, "nofunc"],
|
||||
"no-with": 2,
|
||||
"quote-props": [1, "consistent-as-needed"],
|
||||
"quotes": [2, "single", "avoid-escape"],
|
||||
"radix": 2,
|
||||
"semi": 2,
|
||||
"space-after-keywords": [2, "always"],
|
||||
"space-before-keywords": [2, "always"],
|
||||
"space-before-function-paren": [2, {"anonymous": "never", "named": "never"}],
|
||||
"object-curly-spacing": [2, "never"],
|
||||
"space-infix-ops": 2,
|
||||
"space-return-throw-case": 2,
|
||||
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||
"use-isnan": 2,
|
||||
"valid-typeof": 2,
|
||||
"wrap-iife": 2
|
||||
"block-scoped-var": "warn",
|
||||
"brace-style": ["warn", "1tbs"],
|
||||
"camelcase": "error",
|
||||
"comma-dangle": ["error", "never"],
|
||||
"comma-spacing": "error",
|
||||
"consistent-return": "warn",
|
||||
"dot-notation": ["error", { "allowKeywords": false }],
|
||||
"eol-last": "error",
|
||||
"eqeqeq": ["error", "smart"],
|
||||
"guard-for-in": "error",
|
||||
"indent": ["error", 2, {"SwitchCase": 1}],
|
||||
"key-spacing": "warn",
|
||||
"linebreak-style": "error",
|
||||
"max-depth": ["warn", 4],
|
||||
"max-params": ["warn", 5],
|
||||
"new-cap": "error",
|
||||
"no-alert": "error",
|
||||
"no-caller": "error",
|
||||
"no-catch-shadow": "error",
|
||||
"no-debugger": "error",
|
||||
"no-delete-var": "error",
|
||||
"no-div-regex": "warn",
|
||||
"no-dupe-args": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-else-return": "warn",
|
||||
"no-empty-character-class": "error",
|
||||
"no-labels": "error",
|
||||
"no-eval": "error",
|
||||
"no-ex-assign": "error",
|
||||
"no-extend-native": "warn",
|
||||
"no-extra-boolean-cast": "error",
|
||||
"no-extra-semi": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-floating-decimal": "error",
|
||||
"no-func-assign": "error",
|
||||
"no-implied-eval": "error",
|
||||
"no-inner-declarations": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-label-var": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-lonely-if": "error",
|
||||
"no-multi-spaces": "warn",
|
||||
"no-multi-str": "error",
|
||||
"no-native-reassign": "error",
|
||||
"no-negated-in-lhs": "warn",
|
||||
"no-nested-ternary": "error",
|
||||
"no-new-object": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-obj-calls": "error",
|
||||
"no-octal": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-proto": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-shadow": "error",
|
||||
"no-spaced-func": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-undef": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-undefined": "error",
|
||||
"no-unneeded-ternary": "error",
|
||||
"no-unreachable": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-unused-vars": "error",
|
||||
"no-use-before-define": ["error", "nofunc"],
|
||||
"no-with": "error",
|
||||
"object-curly-spacing": ["error", "never"],
|
||||
"quote-props": ["warn", "consistent-as-needed"],
|
||||
"quotes": ["error", "single", "avoid-escape"],
|
||||
"radix": "error",
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-no-bind": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"semi": "error",
|
||||
"keyword-spacing": "error",
|
||||
"space-before-function-paren": ["error", {"anonymous": "never", "named": "never"}],
|
||||
"space-infix-ops": "error",
|
||||
"space-unary-ops": ["error", { "words": true, "nonwords": false }],
|
||||
"use-isnan": "error",
|
||||
"valid-typeof": "error",
|
||||
"wrap-iife": "error"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
83
js/ContextMenu.jsx
Normal file
83
js/ContextMenu.jsx
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import React from 'react';
|
||||
import MyFile from './my-file';
|
||||
|
||||
import '../css/context-menu.css';
|
||||
|
||||
class ContextMenu extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selected: false
|
||||
};
|
||||
|
||||
this.openFileDialog = this.openFileDialog.bind(this);
|
||||
this.close = this.close.bind(this);
|
||||
this.toggleMenu = this.toggleMenu.bind(this);
|
||||
this.closeMenu = this.closeMenu.bind(this);
|
||||
this.setSkin = this.setSkin.bind(this);
|
||||
}
|
||||
|
||||
componantWillMount() {
|
||||
// Clicking anywhere outside the context menu will close the window
|
||||
document.addEventListener('click', this.closeMenu);
|
||||
}
|
||||
|
||||
componantWillUnmount() {
|
||||
document.removeEventListener('click', this.closeMenu);
|
||||
}
|
||||
|
||||
openFileDialog() {
|
||||
this.props.winamp.openFileDialog();
|
||||
}
|
||||
|
||||
close() {
|
||||
// Close all of Winamp
|
||||
this.props.winamp.close();
|
||||
}
|
||||
|
||||
closeMenu() {
|
||||
this.setState({selected: false});
|
||||
}
|
||||
|
||||
toggleMenu(event) {
|
||||
this.setState({selected: !this.state.selected});
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
setSkin(e) {
|
||||
const filename = e.target.dataset.filename;
|
||||
const url = 'https://cdn.rawgit.com/captbaritone/winamp-skins/master/v2/' + filename;
|
||||
const skinFile = new MyFile();
|
||||
skinFile.setUrl(url);
|
||||
this.props.winamp.setSkin(skinFile);
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
var classes = this.state.selected ? 'selected' : '';
|
||||
return <div id='option' className={classes} onClick={this.toggleMenu}>
|
||||
<ul id='context-menu'>
|
||||
<li><a href='https://github.com/captbaritone/winamp2-js' target='_blank'>Winamp2-js...</a></li>
|
||||
<li className='hr'><hr /></li>
|
||||
<li id='context-play-file' onClick={this.openFileDialog}>Play File...</li>
|
||||
<li className='parent'>
|
||||
<ul>
|
||||
<li id='context-load-skin' onClick={this.openFileDialog}>Load Skin...</li>
|
||||
<li className='hr'><hr /></li>
|
||||
<li data-filename='base-2.91.wsz' onClick={this.setSkin} >{'<Base Skin>'}</li>
|
||||
<li data-filename='MacOSXAqua1-5.wsz' onClick={this.setSkin} >{'Mac OSX v1.5 (Aqua)'}</li>
|
||||
<li data-filename='TopazAmp1-2.wsz' onClick={this.setSkin} >{'TopazAmp'}</li>
|
||||
<li data-filename='Vizor1-01.wsz' onClick={this.setSkin} >{'Vizor'}</li>
|
||||
<li data-filename='XMMS-Turquoise.wsz' onClick={this.setSkin} >{'XMMS Turquoise '}</li>
|
||||
<li data-filename='ZaxonRemake1-0.wsz' onClick={this.setSkin} >{'Zaxon Remake'}</li>
|
||||
</ul>
|
||||
Skins
|
||||
</li>
|
||||
<li className='hr'><hr /></li>
|
||||
<li id='context-exit' onClick={this.close}>Exit</li>
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ContextMenu;
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
import MyFile from './my-file';
|
||||
var Context = function(winamp) {
|
||||
this.winamp = winamp;
|
||||
|
||||
var el = {
|
||||
option: document.getElementById('option'),
|
||||
playFile: document.getElementById('context-play-file'),
|
||||
loadSkin: document.getElementById('context-load-skin'),
|
||||
exit: document.getElementById('context-exit'),
|
||||
skinOptions: document.getElementsByClassName('skin-select')
|
||||
};
|
||||
|
||||
// Click anywhere to close the context menu
|
||||
document.addEventListener('click', function() {
|
||||
el.option.classList.remove('selected');
|
||||
});
|
||||
|
||||
// Click the context menu to close it
|
||||
el.option.addEventListener('click', function(e) {
|
||||
el.option.classList.toggle('selected');
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// Bind to each of the various skin options
|
||||
for (var i = 0; i < el.skinOptions.length; i++) {
|
||||
el.skinOptions[i].addEventListener('click', function(e) {
|
||||
this.loadSkin(e.target.dataset.skinUrl);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
// Play file and load skin both just spawn the file opener
|
||||
el.playFile.addEventListener('click', winamp.openFileDialog);
|
||||
el.loadSkin.addEventListener('click', winamp.openFileDialog);
|
||||
|
||||
// Close all of Winamp
|
||||
el.exit.addEventListener('click', winamp.close);
|
||||
};
|
||||
|
||||
Context.prototype.loadSkin = function(url) {
|
||||
var skinFile = new MyFile();
|
||||
skinFile.setUrl(url);
|
||||
this.winamp.setSkin(skinFile);
|
||||
};
|
||||
|
||||
module.exports = Context;
|
||||
|
|
@ -24,31 +24,7 @@ function el(tagName, attributes, content) {
|
|||
module.exports = el('div', {id: 'main-window', class: 'loading stop'}, [
|
||||
el('div', {id: 'loading'}, 'Loading...'),
|
||||
el('div', {id: 'title-bar', class: 'selected'}, [
|
||||
el('div', {id: 'option'}, [
|
||||
el('ul', {id: 'context-menu'}, [
|
||||
el('li', {}, [
|
||||
el('a', {href: 'https://github.com/captbaritone/winamp2-js', target: '_blank'}, 'Winamp2-js...')
|
||||
]),
|
||||
el('li', {class: 'hr'}, [ el('hr') ]),
|
||||
el('li', {id: 'context-play-file'}, 'Play File...'),
|
||||
el('li', {class: 'parent'}, [
|
||||
el('ul', {}, [
|
||||
el('li', {id: 'context-load-skin'}, 'Load Skin...'),
|
||||
el('li', {class: 'hr'}, [ el('hr') ]),
|
||||
el('li', {'class': 'skin-select', 'data-skin-url': 'https://cdn.rawgit.com/captbaritone/winamp-skins/master/v2/base-2.91.wsz'}, '<Base Skin>'),
|
||||
el('li', {'class': 'skin-select', 'data-skin-url': 'https://cdn.rawgit.com/captbaritone/winamp-skins/master/v2/MacOSXAqua1-5.wsz'}, 'Mac OSX v1.5 (Aqua)'),
|
||||
el('li', {'class': 'skin-select', 'data-skin-url': 'https://cdn.rawgit.com/captbaritone/winamp-skins/master/v2/TopazAmp1-2.wsz'}, 'TopazAmp'),
|
||||
el('li', {'class': 'skin-select', 'data-skin-url': 'https://cdn.rawgit.com/captbaritone/winamp-skins/master/v2/Vizor1-01.wsz'}, 'Vizor'),
|
||||
el('li', {'class': 'skin-select', 'data-skin-url': 'https://cdn.rawgit.com/captbaritone/winamp-skins/master/v2/XMMS-Turquoise.wsz'}, 'XMMS Turquoise '),
|
||||
el('li', {'class': 'skin-select', 'data-skin-url': 'https://cdn.rawgit.com/captbaritone/winamp-skins/master/v2/ZaxonRemake1-0.wsz'}, 'Zaxon Remake')
|
||||
// More here
|
||||
]),
|
||||
'Skins'
|
||||
]),
|
||||
el('li', {class: 'hr'}, [ el('hr') ]),
|
||||
el('li', {id: 'context-exit'}, 'Exit')
|
||||
])
|
||||
]),
|
||||
el('div', {id: 'context-menu-holder'}),
|
||||
el('div', {id: 'shade-time'}, [
|
||||
el('div', {id: 'shade-minus-sign'}),
|
||||
el('div', {id: 'shade-minute-first-digit', class: 'character'}),
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Browser from './browser';
|
||||
import mainWindowDom from './main-window-dom';
|
||||
import Winamp from './winamp';
|
||||
import Context from './context';
|
||||
import ContextMenu from './ContextMenu.jsx';
|
||||
import Hotkeys from './hotkeys';
|
||||
|
||||
import '../css/winamp.css';
|
||||
import '../css/main-window.css';
|
||||
import '../css/context-menu.css';
|
||||
|
||||
if (new Browser(window).isCompatible) {
|
||||
var mainWindowElement = document.createElement('div');
|
||||
|
|
@ -24,7 +26,7 @@ if (new Browser(window).isCompatible) {
|
|||
});
|
||||
|
||||
new Hotkeys(winamp);
|
||||
new Context(winamp);
|
||||
ReactDOM.render(<ContextMenu winamp={winamp} />, document.getElementById('context-menu-holder'));
|
||||
} else {
|
||||
document.getElementById('winamp').style.display = 'none';
|
||||
document.getElementById('browser-compatibility').style.display = 'block';
|
||||
|
|
|
|||
18
package.json
18
package.json
|
|
@ -4,7 +4,7 @@
|
|||
"description": "Winamp 2 implemented in HTML5 and JavaScript",
|
||||
"main": "index.html",
|
||||
"scripts": {
|
||||
"lint": "eslint js/*.js",
|
||||
"lint": "eslint js/*.js js/*.jsx",
|
||||
"build": "webpack --optimize-minimize",
|
||||
"serve": "webpack-dev-server",
|
||||
"weight": "npm run build && gzip-size built/winamp.js | pretty-bytes"
|
||||
|
|
@ -26,17 +26,23 @@
|
|||
},
|
||||
"homepage": "https://github.com/captbaritone/winamp2-js#readme",
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.10.1",
|
||||
"babel-core": "^6.10.4",
|
||||
"babel-loader": "^6.2.4",
|
||||
"babel-preset-es2015": "^6.9.0",
|
||||
"babel-preset-react": "^6.11.1",
|
||||
"css-loader": "^0.23.1",
|
||||
"eslint": "1.*",
|
||||
"style-loader": "^0.13.1",
|
||||
"webpack": "^1.13.0",
|
||||
"eslint": "2.*",
|
||||
"eslint-plugin-react": "^5.2.2",
|
||||
"gzip-size-cli": "^1.0.0",
|
||||
"pretty-bytes-cli": "^1.0.0"
|
||||
"pretty-bytes-cli": "^1.0.0",
|
||||
"style-loader": "^0.13.1",
|
||||
"webpack": "^1.13.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"jszip": "^2.6.0"
|
||||
"babel-plugin-transform-react-jsx": "^6.8.0",
|
||||
"jszip": "^2.6.0",
|
||||
"react": "^15.2.0",
|
||||
"react-dom": "^15.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,9 @@ module.exports = {
|
|||
loader: 'style-loader!css-loader'
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
test: /\.jsx?$/,
|
||||
exclude: /(node_modules|bower_components)/,
|
||||
loader: 'babel', // 'babel-loader' is also a legal name to reference
|
||||
query: {
|
||||
presets: ['es2015']
|
||||
}
|
||||
loader: 'babel' // 'babel-loader' is also a legal name to reference
|
||||
}
|
||||
],
|
||||
noParse: [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue