Merge pull request #175 from lbryio/revert-174-merge-development-electron

Revert "Merge updates from development into Electron branch"
This commit is contained in:
alexliebowitz 2017-02-20 23:16:15 -05:00 committed by GitHub
commit c5da3de3c1
20 changed files with 140 additions and 347 deletions

View file

@ -1,23 +1,5 @@
[bumpversion]
current_version = 0.9.0rc6
current_version = 0.1.1
commit = True
tag = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)((?P<release>[a-z]+)(?P<candidate>\d+))?
serialize =
{major}.{minor}.{patch}{release}{candidate}
{major}.{minor}.{patch}
[bumpversion:file:package.json]
[bumpversion:part:release]
optional_value = production
values =
rc
production
[bumpversion:file:CHANGELOG.md]
search = [Unreleased]
replace = [Unreleased]
\#\# [{new_version}] - {now:%Y-%m-%d}

View file

@ -3,10 +3,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/).
The LBRY Web UI comes bundled as part of [LBRY App](https://github.com/lbryio/lbry-app). Web UI version numbers track corresponding version of LBRY App.
The LBRY Web UI comes bundled as part of [LBRY App](https://github.com/lbryio/lbry-app). Web UI version numbers should always match the corresponding version of LBRY App.
## [Unreleased]
### Changed
* Use local file for publishing
* Use local file and html5 for video playback
* Misc changes needed to make UI compatible with electron

37
dist/quit.html vendored
View file

@ -1,37 +0,0 @@
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>LBRY</title>
<link href='https://fonts.googleapis.com/css?family=Raleway:600,300' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
<link href="./js/mediaelement/mediaelementplayer.css" rel="stylesheet" type="text/css" />
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="./img/fav/favicon-194x194.png" sizes="194x194">
<link rel="icon" type="image/png" href="./img/fav/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="./img/fav/android-chrome-192x192.png" sizes="192x192">
<link rel="icon" type="image/png" href="./img/fav/favicon-16x16.png" sizes="16x16">
<meta name="msapplication-TileColor" content="#155B4A">
<meta name="msapplication-TileImage" content="/img/fav/mstile-144x144.png">
<meta name="theme-color" content="#155B4A">
<style>
body {
background-color: "#155b4a"
}
</style>
</head>
<div id="canvas">
<div class="load-screen" style="color: white; min-height: 100vh; min-width: 100vw; display: flex; flex-direction: column; align-items: center; justify-content: center;">
<img src="./img/lbry-white-485x160.png" alt="LBRY">
<div style="margin-top: 24px; width: 325px; text-align: center;">
<h3>
<span>Shutting Down <span class="busy-indicator"></span>
</span>
</h3>
</div>
</div>
</div>
</html>

37
dist/warning.html vendored
View file

@ -1,37 +0,0 @@
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>LBRY</title>
<link href='https://fonts.googleapis.com/css?family=Raleway:600,300' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
<link href="./js/mediaelement/mediaelementplayer.css" rel="stylesheet" type="text/css" />
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="./img/fav/favicon-194x194.png" sizes="194x194">
<link rel="icon" type="image/png" href="./img/fav/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="./img/fav/android-chrome-192x192.png" sizes="192x192">
<link rel="icon" type="image/png" href="./img/fav/favicon-16x16.png" sizes="16x16">
<meta name="msapplication-TileColor" content="#155B4A">
<meta name="msapplication-TileImage" content="/img/fav/mstile-144x144.png">
<meta name="theme-color" content="#155B4A">
<style>
body {
background-color: "#155b4a"
}
</style>
</head>
<div id="canvas">
<div class="load-screen" style="color: white; min-height: 100vh; min-width: 100vw; display: flex; flex-direction: column; align-items: center; justify-content: center;">
<img src="./img/lbry-white-485x160.png" alt="LBRY">
<div style="margin-top: 24px; width: 325px; text-align: center;">
<h3>
<span>The daemon has unexpectedly shutdown. Goodbye.
</span>
</h3>
</div>
</div>
</div>
</html>

View file

@ -1,6 +1,4 @@
import React from 'react';
import {Line} from 'rc-progress';
import lbry from './lbry.js';
import SettingsPage from './page/settings.js';
import HelpPage from './page/help.js';
@ -21,11 +19,6 @@ import Header from './component/header.js';
import Modal from './component/modal.js';
import {Link} from './component/link.js';
const {remote, ipcRenderer} = require('electron');
const {download} = remote.require('electron-dl');
var App = React.createClass({
_error_key_labels: {
connectionString: 'API connection string',
@ -52,7 +45,6 @@ var App = React.createClass({
modal: null,
updateUrl: null,
isOldOSX: null,
downloadProgress: null,
};
},
componentWillMount: function() {
@ -78,9 +70,6 @@ var App = React.createClass({
} else if (versionInfo.os_system == 'Linux') {
var updateUrl = 'https://lbry.io/get/lbry.deb';
} else if (versionInfo.os_system == 'Windows') {
// A little weird, but for electron, the installer is
// actually an exe. Maybe a better url would
// be something like /get/windows ?
var updateUrl = 'https://lbry.io/get/lbry.msi';
} else {
var updateUrl = 'https://lbry.io/get';
@ -108,18 +97,8 @@ var App = React.createClass({
});
},
handleUpgradeClicked: function() {
// TODO: create a callback for onProgress and have the UI
// show download progress
// TODO: remove the saveAs popup. Thats just me being lazy and having
// some indication that the download is happening
// TODO: calling lbry.stop() ends up displaying the "daemon
// unexpectedly stopped" page. Have a better way of shutting down
let options = {
onProgress: (p) => this.setState({downloadProgress: Math.round(p * 100)}),
}
download(remote.getCurrentWindow(), this.state.updateUrl, options)
.then(dl => ipcRenderer.send('shutdown'));
this.setState({modal: 'downloading'});
lbry.stop();
window.location = this.state.updateUrl;
},
handleSkipClicked: function() {
sessionStorage.setItem('upgradeSkipped', true);
@ -232,11 +211,6 @@ var App = React.createClass({
: null}
</Modal>
// TODO: have color refence css color-primary
<Modal isOpen={this.state.modal == 'downloading'} contentLabel="Downloading Update" type="custom">
Downloading Update: {this.state.downloadProgress}% Complete
<Line percent={this.state.downloadProgress} strokeWidth="4"/>
</Modal>
<Modal isOpen={this.state.modal == 'error'} contentLabel="Error" type="custom"
className="error-modal" overlayClassName="error-modal-overlay" >
<h3 className="modal__header">Error</h3>

View file

@ -98,7 +98,7 @@ export let Address = React.createClass({
});
export let Thumbnail = React.createClass({
_defaultImageUri: lbry.imagePath('default-thumb.svg'),
_defaultImageUri: '/img/default-thumb.svg',
_maxLoadTime: 10000,
_isMounted: false,

View file

@ -38,15 +38,15 @@ var Drawer = React.createClass({
<nav id="drawer">
<div id="drawer-handle">
<Link title="Close" onClick={this.props.onCloseDrawer} icon="icon-bars" className="close-drawer-link"/>
<a href="/"><img src={lbry.imagePath("lbry-dark-1600x528.png")} style={drawerImageStyle}/></a>
<a href="/"><img src="./img/lbry-dark-1600x528.png" style={drawerImageStyle}/></a>
</div>
<DrawerItem href='index.html?discover' viewingPage={this.props.viewingPage} label="Discover" icon="icon-search" />
<DrawerItem href='index.html?publish' viewingPage={this.props.viewingPage} label="Publish" icon="icon-upload" />
<DrawerItem href='index.html?downloaded' subPages={['published']} viewingPage={this.props.viewingPage} label="My Files" icon='icon-cloud-download' />
<DrawerItem href="index.html?wallet" subPages={['send', 'receive', 'claim', 'referral']} viewingPage={this.props.viewingPage} label="My Wallet" badge={lbry.formatCredits(this.state.balance) } icon="icon-bank" />
<DrawerItem href='index.html?settings' viewingPage={this.props.viewingPage} label="Settings" icon='icon-gear' />
<DrawerItem href='index.html?help' viewingPage={this.props.viewingPage} label="Help" icon='icon-question-circle' />
{isLinux ? <Link href="index.html?start" icon="icon-close" className="close-lbry-link" /> : null}
<DrawerItem href='/?discover' viewingPage={this.props.viewingPage} label="Discover" icon="icon-search" />
<DrawerItem href='/?publish' viewingPage={this.props.viewingPage} label="Publish" icon="icon-upload" />
<DrawerItem href='/?downloaded' subPages={['published']} viewingPage={this.props.viewingPage} label="My Files" icon='icon-cloud-download' />
<DrawerItem href="/?wallet" subPages={['send', 'receive', 'claim', 'referral']} viewingPage={this.props.viewingPage} label="My Wallet" badge={lbry.formatCredits(this.state.balance) } icon="icon-bank" />
<DrawerItem href='/?settings' viewingPage={this.props.viewingPage} label="Settings" icon='icon-gear' />
<DrawerItem href='/?help' viewingPage={this.props.viewingPage} label="Help" icon='icon-question-circle' />
{isLinux ? <Link href="/?start" icon="icon-close" className="close-lbry-link" /> : null}
</nav>
);
}

View file

@ -121,15 +121,15 @@ export let FileTileStream = React.createClass({
<section className={ 'file-tile card ' + (obscureNsfw ? 'card-obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}>
<div className={"row-fluid card-content file-tile__row"}>
<div className="span3">
<a href={'/?show=' + this.props.name}><Thumbnail className="file-tile__thumbnail" src={metadata.thumbnail} alt={'Photo for ' + (title || this.props.name)} /></a>
<a href={'/?show=' + this.props.name}><Thumbnail className="file-tile__thumbnail" src={metadata.thumbnail} alt={`Photo for ${title}`} /></a>
</div>
<div className="span9">
{ !this.props.hidePrice
? <FilePrice name={this.props.name} />
: null}
<div className="meta"><a href={'index.html?show=' + this.props.name}>{'lbry://' + this.props.name}</a></div>
<div className="meta"><a href={'/?show=' + this.props.name}>{'lbry://' + this.props.name}</a></div>
<h3 className="file-tile__title">
<a href={'index.html?show=' + this.props.name}>
<a href={'/?show=' + this.props.name}>
<TruncatedText lines={1}>
{title}
</TruncatedText>
@ -196,4 +196,4 @@ export let FileTile = React.createClass({
return <FileTileStream sdHash={this.state.sdHash} metadata={this.state.metadata} {... this.props} />;
}
});
});

View file

@ -56,9 +56,6 @@ var FormField = React.createClass({
getValue: function() {
if (this.props.type == 'checkbox') {
return this.refs.field.checked;
}
else if (this.props.type == 'file') {
return this.refs.field.files[0].path;
} else {
return this.refs.field.value;
}

View file

@ -28,7 +28,6 @@ var SplashScreen = React.createClass({
});
lbry.resolveName('one', () => {
window.sessionStorage.setItem('loaded', 'y')
this.props.onLoadDone();
});
return;

View file

@ -13,27 +13,24 @@ var init = function() {
}
var canvas = document.getElementById('canvas');
if (window.sessionStorage.getItem('loaded') == 'y') {
ReactDOM.render(<App/>, canvas)
} else {
ReactDOM.render(
<SplashScreen message="Connecting" onLoadDone={function() {
// Redirect to the claim code page if needed. Find somewhere better for this logic
if (!localStorage.getItem('claimCodeDone') && window.location.search == '' || window.location.search == '?' || window.location.search == 'discover') {
lbry.getBalance((balance) => {
if (balance <= 0) {
window.location.href = '?claim';
} else {
ReactDOM.render(<App/>, canvas);
}
});
} else {
ReactDOM.render(
<SplashScreen message="Connecting" onLoadDone={function() {
// Redirect to the claim code page if needed. Find somewhere better for this logic
if (!localStorage.getItem('claimCodeDone') && window.location.search == '' || window.location.search == '?' || window.location.search == 'discover') {
lbry.getBalance((balance) => {
if (balance <= 0) {
window.location.href = '?claim';
} else {
ReactDOM.render(<App/>, canvas);
}
}}/>,
canvas
);
}
}
});
} else {
ReactDOM.render(<App/>, canvas);
}
}}/>,
canvas
);
};
init();

View file

@ -45,7 +45,14 @@ var PublishPage = React.createClass({
}
}
if (missingFieldFound) {
let fileProcessing = false;
if (this.state.fileInfo && !this.state.tempFileReady) {
this.refs.file.showAdvice('Your file is still processing.');
this.refs.file.focus();
fileProcessing = true;
}
if (missingFieldFound || fileProcessing) {
this.setState({
submitting: false,
});
@ -82,7 +89,7 @@ var PublishPage = React.createClass({
};
if (this.refs.file.getValue() !== '') {
publishArgs.file_path = this.refs.file.getValue();
publishArgs.file_path = this._tempFilePath;
}
lbry.publish(publishArgs, (message) => {
@ -107,6 +114,8 @@ var PublishPage = React.createClass({
}
},
getInitialState: function() {
this._tempFilePath = null;
return {
rawName: '',
name: '',
@ -118,12 +127,14 @@ var PublishPage = React.createClass({
myClaimValue: 0.0,
myClaimMetadata: null,
myClaimExists: null,
fileInfo: null,
copyrightNotice: '',
otherLicenseDescription: '',
otherLicenseUrl: '',
uploadProgress: 0.0,
uploaded: false,
errorMessage: null,
tempFileReady: false,
submitting: false,
modal: null,
};
@ -225,6 +236,56 @@ var PublishPage = React.createClass({
feeCurrency: event.target.value,
});
},
handleFileChange: function(event) {
event.preventDefault();
var fileInput = event.target;
this._tempFilePath = null;
if (fileInput.files.length == 0) {
// File was removed
this.setState({
fileInfo: null,
uploadProgress: 0.0,
uploaded: false,
tempFileReady: false,
});
} else {
var file = fileInput.files[0];
this.setState({
fileInfo: {
name: file.name,
size: file.size,
},
uploadProgress: 0.0,
uploaded: false,
tempFileReady: false,
});
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => {
this.setState({
uploadProgress: (event.loaded / event.total),
});
});
xhr.upload.addEventListener('load', (event) => {
this.setState({
uploaded: true,
});
});
xhr.addEventListener('load', (event) => {
this._tempFilePath = JSON.parse(xhr.responseText);
this.setState({
tempFileReady: true,
});
})
var formData = new FormData(fileInput.form);
formData.append('file', fileInput.files[0]);
xhr.open('POST', lbry.webUiUri + '/upload', true);
xhr.send(formData);
}
},
handleFeePrefChange: function(feeEnabled) {
this.setState({
isFee: feeEnabled
@ -272,6 +333,21 @@ var PublishPage = React.createClass({
document.title = "Publish";
},
componentDidUpdate: function() {
if (this.state.fileInfo && !this.state.tempFileReady) {
// A file was chosen but the daemon hasn't finished processing it yet, i.e. it's loading, so
// we're displaying a progress bar and need a value for it.
// React can't unset the "value" prop (to show an "indeterminate" bar) after it's already
// been set, so we have to manage it manually.
if (!this.state.uploaded) {
// Still uploading
this.refs.progress.setAttribute('value', this.state.uploadProgress);
} else {
// Fully uploaded and waiting for server to finish processing, so set progress bar to "indeterminite"
this.refs.progress.removeAttribute('value');
}
}
},
// Also getting a type warning here too
render: function() {
@ -294,7 +370,13 @@ var PublishPage = React.createClass({
<section className="card">
<h4>Choose File</h4>
<FormField name="file" ref="file" type="file" />
<FormField name="file" ref="file" type="file" onChange={this.handleFileChange} />
{ !this.state.fileInfo ? '' :
(!this.state.tempFileReady ? <div>
<progress ref='progress'></progress>
{!this.state.uploaded ? <span> Importing file into LBRY...</span> : <span> Processing file...</span>}
</div>
: <div>File ready for publishing!</div>) }
{ this.state.myClaimExists ? <div className="help">If you don't choose a file, the file from your existing claim will be used.</div> : null }
</section>

View file

@ -1,18 +1,8 @@
import React from 'react';
import {Icon} from '../component/common.js';
import {Link} from '../component/link.js';
import lbry from '../lbry.js';
import LoadScreen from '../component/load_screen.js'
const fs = require('fs');
const VideoStream = require('videostream');
var WatchPage = React.createClass({
_isMounted: false,
_controlsHideDelay: 3000, // Note: this needs to be shorter than the built-in delay in Electron, or Electron will hide the controls before us
_controlsHideTimeout: null,
propTypes: {
name: React.PropTypes.string,
},
@ -22,55 +12,19 @@ var WatchPage = React.createClass({
readyToPlay: false,
loadStatusMessage: "Requesting stream",
mimeType: null,
controlsShown: false,
};
},
componentDidMount: function() {
lbry.getStream(this.props.name);
this.updateLoadStatus();
},
handleBackClicked: function() {
history.back();
},
handleMouseMove: function() {
if (this._controlsTimeout) {
clearTimeout(this._controlsTimeout);
}
if (!this.state.controlsShown) {
this.setState({
controlsShown: true,
});
}
this._controlsTimeout = setTimeout(() => {
if (!this.isMounted) {
return;
}
this.setState({
controlsShown: false,
});
}, this._controlsHideDelay);
},
handleMouseOut: function() {
if (this._controlsTimeout) {
clearTimeout(this._controlsTimeout);
}
if (this.state.controlsShown) {
this.setState({
controlsShown: false,
});
}
},
updateLoadStatus: function() {
lbry.getFileStatus(this.props.name, (status) => {
if (!status || !['running', 'stopped'].includes(status.code) || status.written_bytes == 0) {
// Download hasn't started yet, so update status message (if available) then try again
// TODO: Would be nice to check if we have the MOOV before starting playing
if (status) {
this.setState({
loadStatusMessage: status.message,
loadStatusMessage: status.message
});
}
setTimeout(() => { this.updateLoadStatus() }, 250);
@ -79,17 +33,11 @@ var WatchPage = React.createClass({
readyToPlay: true,
mimeType: status.mime_type,
})
const mediaFile = {
createReadStream: function (opts) {
// Return a readable stream that provides the bytes
// between offsets "start" and "end" inclusive
console.log('Stream between ' + opts.start + ' and ' + opts.end + '.');
return fs.createReadStream(status.download_path, opts)
}
}
var elem = this.refs.video;
var videostream = VideoStream(mediaFile, elem);
elem.play();
var player = new MediaElementPlayer(this.refs.player, {
mode: 'shim',
plugins: ['flash'],
setDimensions: false,
});
}
});
},
@ -97,22 +45,10 @@ var WatchPage = React.createClass({
return (
!this.state.readyToPlay
? <LoadScreen message={'Loading video...'} details={this.state.loadStatusMessage} />
: <main className="video full-screen" onMouseMove={this.handleMouseMove} onMouseOut={this.handleMouseOut}>
<video width="100%" height="100%" id="video" ref="video" src={'/view?name=' + this.props.name}
controls={this.state.controlsShown}/>
{this.state.controlsShown
? <div className="video__overlay">
<div className="video__back">
<Link icon="icon-arrow-circle-o-left" className="video__back-link" onClick={this.handleBackClicked}/>
<div className="video__back-label">
<Icon icon="icon-caret-left" className="video__back-label-arrow" />
<div className="video__back-label-content">
Back to LBRY
</div>
</div>
</div>
</div>
: null}
: <main className="full-screen">
<video ref="player" width="100%" height="100%">
<source type={(this.state.mimeType == 'audio/m4a' || this.state.mimeType == 'audio/mp4a-latm') ? 'video/mp4' : this.state.mimeType} src={lbry.webUiUri + '/view?name=' + this.props.name} />
</video>
</main>
);
}

View file

@ -1,6 +1,6 @@
{
"name": "lbry-web-ui",
"version": "0.9.0rc6",
"version": "1.0.0",
"description": "LBRY web ui",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
@ -25,11 +25,9 @@
"clamp-js-main": "^0.11.1",
"mediaelement": "^2.23.4",
"node-sass": "^3.8.0",
"rc-progress": "^2.0.6",
"react": "^15.4.0",
"react-dom": "^15.4.0",
"react-modal": "^1.5.2",
"videostream": "^2.4.2"
"react-modal": "^1.5.2"
},
"devDependencies": {
"babel": "^6.5.2",
@ -47,7 +45,6 @@
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-react": "^6.7.1",
"node-sass": "^3.13.0",
"webpack": "^1.13.3",
"webpack-target-electron-renderer": "^0.4.0"
"webpack": "^1.13.3"
}
}

View file

@ -10,5 +10,4 @@
@import "component/_menu.scss";
@import "component/_tooltip.scss";
@import "component/_load-screen.scss";
@import "page/_developer.scss";
@import "page/_watch.scss";
@import "page/_developer.scss";

View file

@ -2,6 +2,7 @@
.load-screen {
color: white;
background-image: url("/img/lbry-bg.png");
background-size: cover;
min-height: 100vh;
min-width: 100vw;

View file

@ -1,51 +0,0 @@
.video {
background: #000;
}
.video__overlay {
position: absolute;
top: 0px;
left: 0px;
color: #fff;
z-index: 1;
}
.video__back {
margin-top: 30px;
margin-left: 50px;
display: flex;
flex-direction: row;
align-items: center;
}
.video__back-link {
font-size: 50px;
}
.video__back-label {
opacity: 0;
transition: opacity 100ms ease-in;
}
.video__back-link:hover + .video__back-label {
opacity: 1;
}
$video-back-background: #333;
$video-back-size: 20px;
.video__back-label-arrow {
color: $video-back-background;
font-size: $video-back-size;
}
.video__back-label-content {
display: inline-block;
margin-left: -2px;
font-size: $video-back-size;
padding: $spacing-vertical / 2;
border-radius: 3px;
background-color: $video-back-background;
color: #fff;
pointer-events: none;
}

View file

@ -16,7 +16,7 @@ if [ ! -d "$DIR/node_modules" ]; then
fi
# run sass once without --watch to force update. then run with --watch to keep watching
$DIR/node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none $DIR/scss/
$DIR/node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none --watch $DIR/scss/ &
$DIR/node_modules/.bin/node-sass --output $DIR/dist/css --sourcemap=none $DIR/scss/
$DIR/node_modules/.bin/node-sass --output $DIR/dist/css --sourcemap=none --watch $DIR/scss/ &
node_modules/.bin/webpack --config webpack.dev.config.js --progress --colors --watch
node_modules/.bin/webpack --progress --colors --watch

View file

@ -25,14 +25,13 @@ module.exports = {
loaders: [
{ test: /\.css$/, loader: "style!css" },
{
test: /\.jsx?$/,
loader: 'babel',
test: /\.jsx?$/,
loader: 'babel',
query: {
cacheDirectory: true,
presets:[ 'es2015', 'react', 'stage-2' ]
}
}
]
},
target: 'electron-main',
}
};

View file

@ -1,41 +0,0 @@
const path = require('path');
const PATHS = {
app: path.join(__dirname, 'app'),
dist: path.join(__dirname, '..', 'app', 'dist')
};
module.exports = {
entry: ['babel-polyfill', './js/main.js'],
output: {
path: path.join(PATHS.dist, 'js'),
publicPath: '/js/',
filename: "bundle.js",
pathinfo: true
},
debug: true,
cache: true,
devtool: 'eval',
module: {
preLoaders: [
{
test: /\.jsx?$/,
loaders: ['eslint'],
// define an include so we check just the files we need
include: PATHS.app
}
],
loaders: [
{ test: /\.css$/, loader: "style!css" },
{
test: /\.jsx?$/,
loader: 'babel',
query: {
cacheDirectory: true,
presets:[ 'es2015', 'react', 'stage-2' ]
}
}
]
},
target: 'electron-main',
};