<commit_before>/******************************** Config **************************************/

var DEBUG = true;
var NUM_APPINFO_KEYS = 16;  // Number of keys declared in appinfo.json
                            // with values of 0 -> NUM_APPINFO_KEYS

/********************* PGE WS Module JS - DO NOT MODIFY ***********************/

var webSocket = null;

function Log(message) {
  if(DEBUG) console.log(message);
}

function hasKey(dict, key) {
  return typeof dict.payload[key] !== 'undefined';
}

var getValue = function(dict, key) {
  return hasKey(dict, key) ? dict.payload[key] : null;
}

function sendToPebble(dict) {
  Pebble.sendAppMessage(dict, function() {
    Log('Success: ' + JSON.stringify(dict));
  }, function() {
    Log('Failed: ' + JSON.stringify(dict));
  });
}

function connectToServer(url) {
  // Url. Example: ws://localhost:5000
  webSocket = new WebSocket(url);
  webSocket.onopen = function(event) {
    Log('Connection opened!');
    if(event.data) {
      onSocketOpen(event.data);
      PGEWSSocketProtocol(event.data);
    }
  };
  webSocket.onclose = function(event) {
    Log('onclose');
    sendToPebble({ 'PGE_WS_URL': 0 });
    onSocketClose();
  };
  webSocket.onmessage = function(event) {
    Log('onmessage');
    if(event.data) {
      if(!PGEWSSocketProtocol(event.data)) {
        // This was not a protocol message
        onSocketMessage(event.data);
      }
    } else {
      Log('onmessage with no data!');
    }
  };
  webSocket.onerror = function(event) {
    Log('onerror');
    sendToPebble({ 'PGE_WS_URL': 0 });
    onSocketError();
  };
}

function PGEWSAppMessageProtocol(dict) {
  Log('handling keys: ' + JSON.stringify(dict.payload));

  // WS URL from C and connect
  if(hasKey(dict, 'PGE_WS_URL')) {
    var url = getValue(dict, 'PGE_WS_URL');
    Log('Got WS URL: ' + url);
    connectToServer(url);
  }
}

function PGEWSForwardToServer(dict) {
  // Developer dictionary data to send to server
  if(webSocket) {
    var outgoing = {};

    // Check all appinfo.json keys
    for(var i = 0; i < NUM_APPINFO_KEYS; i += 1) {
      var key = 'PGE_WS_KEY_' + i; // String keys
      if(hasKey(dict, key)) {
        outgoing[key] = getValue(dict, key);
        Log('Added key: ' + key + ', value: ' + outgoing[key]);
      }
    }

    var packet = JSON.stringify(outgoing);
    if(packet.length > 4) {
      // Send this data
      webSocket.send(packet);
      Log('Sent developer data');
    }
  } else {
    Log('Data send requested, but webSocket is not ready');
  }
}

function PGEWSForwardToPebble(data) {
  var json = JSON.parse(data);
  var outgoing = {};

  for(var i = 0; i < NUM_APPINFO_KEYS; i += 1) {
    var key = 'PGE_WS_KEY_' + i;
    if(json[key]) {
      outgoing[key] = parseInt(json[key]);
    }
  }
  sendToPebble(outgoing);
}

var PGEWSSocketProtocol = function(data) {
  var json = JSON.parse(data);

  if(json.id) {
    sendToPebble({
      'PGE_WS_URL': 1, // success
      'PGE_WS_CLIENT_ID': parseInt(json.id)
    });
    return true;
  }

  return false;
}

function PGEWSReady() {
  sendToPebble({ 'PGE_WS_READY': 1 });
}

/**************************** End PGE WS Module JS ****************************/

/******************* Developer Implemented PGE WS callbacks *******************/

function onSocketOpen(data) {

}

function onSocketClose() {

}

function onSocketMessage(data) {
  // Auto-forward to Pebble
  PGEWSForwardToPebble(data);
}

function onSocketError() {

}

/****************************** PebbleKit JS **********************************/

Pebble.addEventListener('ready', function() {
  console.log('PebbleKitJS ready');
  PGEWSReady();
});

Pebble.addEventListener('appmessage', function(dict) {
  PGEWSAppMessageProtocol(dict);

  // Auto-forward to server
  PGEWSForwardToServer(dict);
});<commit_msg>Clean up JS logging<commit_after>/******************************** Config **************************************/

var DEBUG = true;
var VERBOSE = true;
var NUM_APPINFO_KEYS = 16;  // Number of keys declared in appinfo.json
                            // with values of 0 -> NUM_APPINFO_KEYS

/********************* PGE WS Module JS - DO NOT MODIFY ***********************/

var webSocket = null;

function logVerbose(message) {
  if(VERBOSE) console.log(message);
}

function logDebug(message) {
  if(DEBUG) console.log(message);
}

function log(message) {
  console.log(message);
}

function hasKey(dict, key) {
  return typeof dict.payload[key] !== 'undefined';
}

var getValue = function(dict, key) {
  return hasKey(dict, key) ? dict.payload[key] : null;
}

function sendToPebble(dict) {
  Pebble.sendAppMessage(dict, function() {
    logVerbose('Success: ' + JSON.stringify(dict));
  }, function() {
    logVerbose('Failed: ' + JSON.stringify(dict));
  });
}

function connectToServer(url) {
  // Url. Example: ws://localhost:5000
  webSocket = new WebSocket(url);
  webSocket.onopen = function(event) {
    logVerbose('Connection opened!');
    if(event.data) {
      onSocketOpen(event.data);
      PGEWSSocketProtocol(event.data);
    }
  };
  webSocket.onclose = function(event) {
    logVerbose('onclose');
    sendToPebble({ 'PGE_WS_URL': 0 });
    onSocketClose();
  };
  webSocket.onmessage = function(event) {
    logVerbose('onmessage');
    if(event.data) {
      if(!PGEWSSocketProtocol(event.data)) {
        // This was not a protocol message
        onSocketMessage(event.data);
      }
    } else {
      logVerbose('onmessage with no data!');
    }
  };
  webSocket.onerror = function(event) {
    logVerbose('onerror');
    sendToPebble({ 'PGE_WS_URL': 0 });
    onSocketError();
  };
}

function PGEWSAppMessageProtocol(dict) {
  logVerbose('handling keys: ' + JSON.stringify(dict.payload));

  // WS URL from C and connect
  if(hasKey(dict, 'PGE_WS_URL')) {
    var url = getValue(dict, 'PGE_WS_URL');
    logDebug('Got WS URL: ' + url);
    connectToServer(url);
  }
}

function PGEWSForwardToServer(dict) {
  // Developer dictionary data to send to server
  if(webSocket) {
    var outgoing = {};

    // Check all appinfo.json keys
    for(var i = 0; i < NUM_APPINFO_KEYS; i += 1) {
      var key = 'PGE_WS_KEY_' + i; // String keys
      if(hasKey(dict, key)) {
        outgoing[key] = getValue(dict, key);
        logVerbose('Added key: ' + key + ', value: ' + outgoing[key]);
      }
    }

    var packet = JSON.stringify(outgoing);
    if(packet.length > 4) {
      // Send this data
      logVerbose('Forwarding data to server: ' + packet);
      webSocket.send(packet);
    }
  } else {
    logVerbose('Data send requested, but webSocket is not ready');
  }
}

function PGEWSForwardToPebble(data) {
  var json = JSON.parse(data);
  var outgoing = {};

  for(var i = 0; i < NUM_APPINFO_KEYS; i += 1) {
    var key = 'PGE_WS_KEY_' + i;
    if(json[key]) {
      outgoing[key] = parseInt(json[key]);
    }
  }
  logVerbose('Forwarding data to Pebble: ' + JSON.stringify(outgoing));
  sendToPebble(outgoing);
}

var PGEWSSocketProtocol = function(data) {
  var json = JSON.parse(data);

  if(json.id) {
    sendToPebble({
      'PGE_WS_URL': 1, // success
      'PGE_WS_CLIENT_ID': parseInt(json.id)
    });
    return true;
  }

  return false;
}

function PGEWSReady() {
  sendToPebble({ 'PGE_WS_READY': 1 });
}

/**************************** End PGE WS Module JS ****************************/

/******************* Developer Implemented PGE WS callbacks *******************/

function onSocketOpen(data) {

}

function onSocketClose() {

}

function onSocketMessage(data) {
  // Auto-forward to Pebble
  PGEWSForwardToPebble(data);
}

function onSocketError() {

}

/****************************** PebbleKit JS **********************************/

Pebble.addEventListener('ready', function() {
  console.log('PebbleKitJS ready');
  PGEWSReady();
});

Pebble.addEventListener('appmessage', function(dict) {
  PGEWSAppMessageProtocol(dict);

  // Auto-forward to server
  PGEWSForwardToServer(dict);
});<|endoftext|>


<commit_before>/* @flow weak */
import { request } from '../utils'
import config from '../config'
import store from '../store'
import { fetchPackage } from '../components/Package/actions'

const { packageServer } = config
const devPackageServer = __PACKAGE_SERVER__

const io = require('socket.io-client/dist/socket.io.min.js')

export const fetchPackageList = () => request.get(`${devPackageServer || packageServer}/packages`)
export const fetchPackageInfo = (pkgName) =>
request.get(`${devPackageServer || packageServer}/packages/${pkgName}`)

export const fetchPackageScript = (pkgName) => {
  if (devPackageServer) {
    return request.get(`${devPackageServer}/static/${pkgName}.js`)
  }
}
export const enablePackageHotReload = () => {
  const socket = io.connect('http://localhost:4000', {
    // 'force new connection': true,
    reconnection: true,
    reconnectionDelay: 1500,
    reconnectionDelayMax: 10000,
    reconnectionAttempts: 5,
    transports: ['websocket']
  })
  socket.on('change', () => {
    console.log('plugin is reloading')
    const { localPackages } = store.getState().PackageState
    if (Object.keys(localPackages).length) {
      store.dispatch(fetchPackage(Object.keys(localPackages)[0]))
    }
  })
}
<commit_msg>修复一个地址写死的bug<commit_after>/* @flow weak */
import { request } from '../utils'
import config from '../config'
import store from '../store'
import { fetchPackage } from '../components/Package/actions'

const { packageServer } = config
const devPackageServer = __PACKAGE_SERVER__

const io = require('socket.io-client/dist/socket.io.min.js')

export const fetchPackageList = () => request.get(`${devPackageServer || packageServer}/packages`)
export const fetchPackageInfo = (pkgName) =>
request.get(`${devPackageServer || packageServer}/packages/${pkgName}`)

export const fetchPackageScript = (pkgName) => {
  if (devPackageServer) {
    return request.get(`${devPackageServer}/static/${pkgName}.js`)
  }
}
export const enablePackageHotReload = () => {
  const socket = io.connect(devPackageServer, {
    reconnection: true,
    reconnectionDelay: 1500,
    reconnectionDelayMax: 10000,
    reconnectionAttempts: 5,
    transports: ['websocket']
  })
  socket.on('change', () => {
    console.log('plugin is reloading')
    const { localPackages } = store.getState().PackageState
    if (Object.keys(localPackages).length) {
      store.dispatch(fetchPackage(Object.keys(localPackages)[0]))
    }
  })
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import axios from "axios";
import ReactMarkdown from 'react-markdown';
import './Songdetail.css';

const API = 'https://api.voornameninliedjes.nl/songs/';
const FLICKR_PHOTO_DETAIL = 'https://api.flickr.com/services/rest/?method=flickr.photos.getInfo&api_key=9676a28e9cb321d2721e813055abb6dc&format=json&nojsoncallback=true&photo_id=';
const FLICKR_USER_DETAIL = 'https://api.flickr.com/services/rest/?method=flickr.people.getInfo&api_key=9676a28e9cb321d2721e813055abb6dc&format=json&nojsoncallback=true&user_id=';
const FLICKR_LICENCES = 'https://api.flickr.com/services/rest/?method=flickr.photos.licenses.getInfo&api_key=9676a28e9cb321d2721e813055abb6dc&format=json&nojsoncallback=true'

class Songdetail extends Component {

  constructor(props) {
    super(props);

    this.state = {
      song: '',
      photo: '',
      owner: '',
      contribution: '',
      hasWikiPhoto: false,
      wikiPhotoUrl: '',
      wikiPhotoAttribution: ''
    };
  }

  componentDidMount() {
    const songId = this.props.match.params.id;

    axios.get(API + songId)
      .then(res => {
        const song = res.data;
        if (song.wikimediaPhotos.length > 0) {
          const wikiPhoto = song.wikimediaPhotos[0];
          this.setState({
            song: song,
            hasWikiPhoto: true,
            wikiPhotoUrl: wikiPhoto.url,
            wikiPhotoAttribution: wikiPhoto.attribution
          });
        } else {
          axios.get(FLICKR_PHOTO_DETAIL + song.flickrPhotos[0])
            .then(res => {
              const photo = res.data.photo;
              axios.get(FLICKR_USER_DETAIL + photo.owner.nsid)
                .then(res => {
                  const owner = res.data.person;
                  axios.get(FLICKR_LICENCES)
                    .then(res => {
                      const licenses = res.data.licenses.license;
                      const license = licenses.find(x => x.id === photo.license);
                      const licenseName = license.name;
                      const licenseUrl = license.url;
                      const contribution = {
                        'ownerName': owner.username._content,
                        'ownerUrl': owner.photosurl._content,
                        'photoTitle': photo.title._content,
                        'photoUrl': photo.urls.url[0]._content,
                        'licenseName': licenseName,
                        'licenseUrl': licenseUrl
                      };
                      this.setState({
                        song: song,
                        photo: photo,
                        owner: owner,
                        contribution: contribution
                      });
                    })
                })
            })
        }
      });
  }

  render() {
    const song = this.state.song;
    const photo = this.state.photo;
    const contribution = this.state.contribution;
    const hasWikiPhoto = this.state.hasWikiPhoto;
    const wikiPhotoUrl = this.state.wikiPhotoUrl;
    const wikiPhotoAttribution = this.state.wikiPhotoAttribution;

    return (

{song.artist}

{song.title}

        <content className="song-text"><ReactMarkdown source={song.background} /></content>

          <iframe src={`https://open.spotify.com/embed/track/${song.spotify}`} className="spotify" width="100%" height="100%" title={song.title} frameBorder="0" allowtransparency="true" allow="encrypted-media">

          <iframe src={`https://www.youtube.com/embed/${song.youtube}?rel=0`} width="100%" height="100%" title={song.title}>

          {hasWikiPhoto ? (

{wikiPhotoAttribution}

          ) : (

                <img
                  src={`https://farm${photo.farm}.staticflickr.com/${photo.server}/${photo.id}_${photo.secret}_c.jpg`}
                  alt={photo.title}
                />

Photo by {contribution.ownerName} / {contribution.licenseName}

            )}

    );
  }
}

export default Songdetail;<commit_msg>Use YouTube embed without tracking cookies<commit_after>import React, { Component } from 'react';
import axios from "axios";
import ReactMarkdown from 'react-markdown';
import './Songdetail.css';

const API = 'https://api.voornameninliedjes.nl/songs/';
const FLICKR_PHOTO_DETAIL = 'https://api.flickr.com/services/rest/?method=flickr.photos.getInfo&api_key=9676a28e9cb321d2721e813055abb6dc&format=json&nojsoncallback=true&photo_id=';
const FLICKR_USER_DETAIL = 'https://api.flickr.com/services/rest/?method=flickr.people.getInfo&api_key=9676a28e9cb321d2721e813055abb6dc&format=json&nojsoncallback=true&user_id=';
const FLICKR_LICENCES = 'https://api.flickr.com/services/rest/?method=flickr.photos.licenses.getInfo&api_key=9676a28e9cb321d2721e813055abb6dc&format=json&nojsoncallback=true'

class Songdetail extends Component {

  constructor(props) {
    super(props);

    this.state = {
      song: '',
      photo: '',
      owner: '',
      contribution: '',
      hasWikiPhoto: false,
      wikiPhotoUrl: '',
      wikiPhotoAttribution: ''
    };
  }

  componentDidMount() {
    const songId = this.props.match.params.id;

    axios.get(API + songId)
      .then(res => {
        const song = res.data;
        if (song.wikimediaPhotos.length > 0) {
          const wikiPhoto = song.wikimediaPhotos[0];
          this.setState({
            song: song,
            hasWikiPhoto: true,
            wikiPhotoUrl: wikiPhoto.url,
            wikiPhotoAttribution: wikiPhoto.attribution
          });
        } else {
          axios.get(FLICKR_PHOTO_DETAIL + song.flickrPhotos[0])
            .then(res => {
              const photo = res.data.photo;
              axios.get(FLICKR_USER_DETAIL + photo.owner.nsid)
                .then(res => {
                  const owner = res.data.person;
                  axios.get(FLICKR_LICENCES)
                    .then(res => {
                      const licenses = res.data.licenses.license;
                      const license = licenses.find(x => x.id === photo.license);
                      const licenseName = license.name;
                      const licenseUrl = license.url;
                      const contribution = {
                        'ownerName': owner.username._content,
                        'ownerUrl': owner.photosurl._content,
                        'photoTitle': photo.title._content,
                        'photoUrl': photo.urls.url[0]._content,
                        'licenseName': licenseName,
                        'licenseUrl': licenseUrl
                      };
                      this.setState({
                        song: song,
                        photo: photo,
                        owner: owner,
                        contribution: contribution
                      });
                    })
                })
            })
        }
      });
  }

  render() {
    const song = this.state.song;
    const photo = this.state.photo;
    const contribution = this.state.contribution;
    const hasWikiPhoto = this.state.hasWikiPhoto;
    const wikiPhotoUrl = this.state.wikiPhotoUrl;
    const wikiPhotoAttribution = this.state.wikiPhotoAttribution;

    return (

{song.artist}

{song.title}

        <content className="song-text"><ReactMarkdown source={song.background} /></content>

          <iframe src={`https://open.spotify.com/embed/track/${song.spotify}`} className="spotify" width="100%" height="100%" title={song.title} frameBorder="0" allowtransparency="true" allow="encrypted-media">

          <iframe src={`https://www.youtube-nocookie.com/embed/${song.youtube}?rel=0`} width="100%" height="100%" title={song.title}>

          {hasWikiPhoto ? (

{wikiPhotoAttribution}

          ) : (

                <img
                  src={`https://farm${photo.farm}.staticflickr.com/${photo.server}/${photo.id}_${photo.secret}_c.jpg`}
                  alt={photo.title}
                />

Photo by {contribution.ownerName} / {contribution.licenseName}

            )}

    );
  }
}

export default Songdetail;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import ePub from 'epubjs';
import getStreamHost from '../../utils/get-stream-host';
import './Epub.scss';

class Epub extends Component {

  constructor(props) {
    super(props);
    this.book = ePub();
  }

  componentWillMount() {
    // const { id } = this.props.book;
    this.book.open(this.props.src)
      .then(() => {
        console.log('OPEN');
      })
      .catch((err) => {
        console.error(err);
      });
  }

  componentDidMount() {
    this.rendition = this.book.renderTo('stage', {
      flow: this.props.flow || 'paginated',
      minSpreadWidth: 550,
      width: '100%',
      height: '100%',
      manager: ePub.ViewManagers.default,
      view: ePub.Views.iframe
    });

    this.rendition.themes.register(`${getStreamHost()}/static/epub.css`);
    this.rendition.themes.apply('book-theme');

    this.rendition.display(this.props.location || 0);

    this.rendition.on('locationChanged', (visibleLocation) => {
      this._visibleLocation = visibleLocation;

      if (this.props.onLocationChange) {
        this.props.onLocationChange(visibleLocation);
      }
    });

    this.book.ready.then(() => {
      if (this.props.onReady) this.props.onReady(this.book);
    });

    this.book.loaded.metadata.then((nav) => {
      if (this.props.onMetadataReady) this.props.onMetadataReady(nav.toc);
    });

    this.book.loaded.navigation.then((nav) => {
      if (this.props.onNavigationReady) this.props.onNavigationReady(nav.toc);
    });

    this.keyListener = (e) => {
      // Left Key
      if ((e.keyCode || e.which) === 37) {
        this.rendition.prev();
      }

      // Right Key
      if ((e.keyCode || e.which) === 39) {
        this.rendition.next();
      }
    };

    this.rendition.on('keyup', this.keyListener);
    document.addEventListener('keyup', this.keyListener, false);
  }

  componentWillUnmount() {
    this.rendition.off('keyup', this.keyListener);
    document.removeEventListener('keyup', this.keyListener, false);
  }

  componentWillUpdate(nextProps) {
    if (nextProps.location !== this.props.location) {
      this.rendition.display(nextProps.location);
    }

    if (nextProps.theme !== this.props.theme) {
      this.rendition.themes.apply(nextProps.theme);
    }

    if (nextProps.fontSize !== this.props.fontSize) {
      this.rendition.themes.fontSize(nextProps.fontSize);
    }
  }

  display(what) {
    this.rendition && this.rendition.display(what);
  }

  render() {
    return (

        <button className="epub__container__page-left" onClick={() => this.rendition.prev()} >

        </button>

        <button className="epub__container__page-right" onClick={() => this.rendition.next()} >

        </button>

    );
  }
}

export default Epub;
<commit_msg>Redisplay on resize<commit_after>import React, { Component, findDOMNode } from 'react';
import ePub from 'epubjs';
import getStreamHost from '../../utils/get-stream-host';
import './Epub.scss';

class Epub extends Component {

  constructor(props) {
    super(props);
    this.book = ePub();
  }

  componentWillMount() {
    // const { id } = this.props.book;
    this.book.open(this.props.src)
      .then(() => {
        console.log('OPEN');
      })
      .catch((err) => {
        console.error(err);
      });
  }

  componentDidMount() {
    this._start();
  }

  componentWillUnmount() {
    this._stop();
  }

  componentWillUpdate(nextProps) {
    if (nextProps.location !== this.props.location) {
      this.rendition.display(nextProps.location);
    }

    if (nextProps.theme !== this.props.theme) {
      this.rendition.themes.apply(nextProps.theme);
    }

    if (nextProps.fontSize !== this.props.fontSize) {
      this.rendition.themes.fontSize(nextProps.fontSize);
    }
  }

  display(what) {
    this.rendition && this.rendition.display(what);
  }

  _start() {
    this.rendition = this.book.renderTo('stage', {
      flow: this.props.flow || 'paginated',
      minSpreadWidth: 550,
      width: '100%',
      height: '100%',
      manager: ePub.ViewManagers.default,
      view: ePub.Views.iframe
    });

    this.rendition.themes.register(`${getStreamHost()}/static/epub.css`);
    this.rendition.themes.apply('book-theme');

    this.rendition.display(this.props.location || 0);

    this.rendition.on('locationChanged', (visibleLocation) => {
      this._visibleLocation = visibleLocation;

      if (this.props.onLocationChange) {
        this.props.onLocationChange(visibleLocation);
      }
    });

    this.book.ready.then(() => {
      if (this.props.onReady) this.props.onReady(this.book);
    });

    this.book.loaded.metadata.then((nav) => {
      if (this.props.onMetadataReady) this.props.onMetadataReady(nav.toc);
    });

    this.book.loaded.navigation.then((nav) => {
      if (this.props.onNavigationReady) this.props.onNavigationReady(nav.toc);
    });

    this.keyListener = (e) => {
      // Left Key
      if ((e.keyCode || e.which) === 37) {
        this.rendition.prev();
      }

      // Right Key
      if ((e.keyCode || e.which) === 39) {
        this.rendition.next();
      }
    };

    this.rendition.on('keyup', this.keyListener);
    document.addEventListener('keyup', this.keyListener, false);

    window.addEventListener('resize', this._onResize.bind(this), false);
  }

  _stop(){
    this.rendition.destroy();
    this.rendition.off('keyup', this.keyListener);
    document.removeEventListener('keyup', this.keyListener, false);
    window.removeEventListener('resize', this._onResize, false);
  }
  _onResize() {
    this._stop();
    clearTimeout(this.resizeTimeout);
    this.resizeTimeout = setTimeout(this._start.bind(this), 250 );
  }

  render() {
    return (

        <button className="epub__container__page-left" onClick={() => this.rendition.prev()} >

        </button>

        <button className="epub__container__page-right" onClick={() => this.rendition.next()} >

        </button>

    );
  }
}

export default Epub;
<|endoftext|>


<commit_before>const Idylle = require('idylle');

const Core = Idylle.Core;
const registry = new Core();
registry.events = Core.events;

registry.on(Core.events.init.actions,       require('./actions'));
registry.on(Core.events.init.middlewares,   require('./middlewares'));
registry.on(Core.events.init.models,        require('./models'));
registry.on(Core.events.init.routes,        require('./routes'));
registry.on(Core.events.init.settings,      require('./settings'));
registry.on(Core.events.booting,            require('./boot'));

registry.start();
module.exports = registry;

<commit_msg>removed registry.start()<commit_after>const Idylle = require('idylle');

const Core = Idylle.Core;
const registry = new Core();
registry.events = Core.events;

registry.on(Core.events.init.actions,       require('./actions'));
registry.on(Core.events.init.middlewares,   require('./middlewares'));
registry.on(Core.events.init.models,        require('./models'));
registry.on(Core.events.init.routes,        require('./routes'));
registry.on(Core.events.init.settings,      require('./settings'));
registry.on(Core.events.booting,            require('./boot'));

module.exports = registry;

<|endoftext|>


<commit_before>function unpack_data (data, out) {
    var teams = {};
    var players = {};
    data.team.forEach(function (team) {
        teams[team.team_id] = team;
        var playerList = team.player || team.squad;
        playerList.forEach(function (player) {
            players[player.player_id] = player;
        });
    });

    var match_status = data.match.match_status || "complete";

    console.log("match status: "+match_status);

    switch (match_status) {
        case "dormant":
            out.score = data.match.team1_filename+" v "+data.match.team2_filename;
            out.lead = "Match starts in "+data.match.match_clock;

            if (data.match.toss_decision && data.match.toss_decision !== "") {
                out.striker_name = teams[data.match.toss_winner_team_id].team_short_name+" won toss,";
                out.nonstriker_name = "will "+data.match.toss_decision_name;
            }
            break;

        case "complete": {
            out.score = data.match.team1_filename+" v "+data.match.team2_filename;

            if (data.match.winner_team_id == "0") {
                out.striker_name = "Match drawn";
            }
            else {
                out.striker_name = teams[data.match.winner_team_id].team_short_name+" won by";
                if (data.match.amount_name === "innings") {
                    out.nonstriker_name = "innings and "+data.match.amount+" runs";
                }
                else {
                    out.nonstriker_name = data.match.amount+" "+data.match.amount_name;
                }
            }
            break;
        }

        case "current": {
            var innings = data.live.innings;

            out.score = [
                teams[innings.batting_team_id].team_filename + " " + innings.runs,
                (innings.wickets < 10) ? "/"+innings.wickets : "",
                ((innings.event && innings.event == "declared") ? "d" : "")
            ].join('');

            out.overs = innings.overs;

            if (+data.match.scheduled_overs > 0) {
                switch (+innings.innings_number) {
                    case 1:
                        out.lead = "Run rate: "+innings.run_rate;
                        break;
                    default:
                        out.lead =
                            "Need "+(1-innings.lead)+" in "+
                            (innings.remaining_overs <= 10.0 ? innings.remaining_balls+" b" : innings.remaining_overs+" ov");
                        break;
                }
            }
            else {
                switch (+innings.innings_number) {
                    case 1:
                        out.lead = "First innings";
                        break;
                    case 4:
                        out.lead = "Target "+(innings.target);
                        break;
                    default:
                        out.lead =
                            innings.lead < 0 ? "Trail by "+(-innings.lead) :
                            innings.lead > 0 ? "Lead by "+innings.lead :
                                            "Scores level";
                }
            }

            var striker = data.live.batting.filter(function (player) { return player.live_current_name == "striker"; })[0];
            var nonstriker = data.live.batting.filter(function (player) { return player.live_current_name == "non-striker"; })[0];

            if (!striker) {
                striker = nonstriker;
                nonstriker = null;
            }

            var shorten = function (n) {
                var bits = n.split(' ');
                for (var i = 0; i < bits.length-1; i++)
                    bits[i] = bits[i].substr(0,1);
                return bits.join('.');
            };

            if (striker) {
                var striker_name = players[striker.player_id].card_short;
                if (striker_name.length > 10 && players[striker.player_id].popular_name.length > 0)
                    striker_name = players[striker.player_id].popular_name;
                if (striker_name.length > 10)
                    striker_name = shorten(striker_name);
                out.striker_name = striker_name + (nonstriker ? "*" : "");
                out.striker_stats = striker.runs+" ("+striker.balls_faced+")";
            }

            if (nonstriker) {
                var nonstriker_name = players[nonstriker.player_id].card_short;
                if (nonstriker_name.length > 10 && players[nonstriker.player_id].popular_name.length > 0)
                    nonstriker_name = players[nonstriker.player_id].popular_name;
                if (nonstriker_name.length > 10)
                    nonstriker_name = shorten(nonstriker_name);
                out.nonstriker_name = nonstriker_name;
                out.nonstriker_stats = nonstriker.runs+" ("+nonstriker.balls_faced+")";
            }

            var bowler = data.live.bowling.filter(function (player) { return player.live_current_name == "current bowler"; })[0];
            if (bowler) {
                var bowler_name = players[bowler.player_id].card_short;
                if (bowler_name.length > 10) bowler_name = players[bowler.player_id].popular_name;
                out.bowler_name = bowler_name;
                out.bowler_stats = bowler.overs+"-"+bowler.maidens+"-"+bowler.conceded+"-"+bowler.wickets;
            }

            break;
        }
    }
}

function new_out () {
    var out = {
        "score":"",
        "overs":"",
        "lead":"",
        "striker_name":"",
        "striker_stats":"",
        "nonstriker_name":"",
        "nonstriker_stats":"",
        "bowler_name":"",
        "bowler_stats":""
    };
    return out;
}

function update () {
    var out = new_out();
    var matchId = localStorage.getItem("matchId");
    if (!matchId) {
        out.striker_name = "No match selected";
        out.nonstriker_name = "in config.";
        Pebble.sendAppMessage(out);
        return;
    }
    var req = new XMLHttpRequest();
    req.open('GET', "http://www.espncricinfo.com/ci/engine/match/"+matchId+".json");
    req.onload = function(e) {
        if (req.readyState == 4) {
            if(req.status == 200) {
                console.log("got new data, updating");

                var data = JSON.parse(req.responseText);
                if (data) {
                    unpack_data(data, out);
                    console.log(JSON.stringify(out));
                    Pebble.sendAppMessage(out);
                }

            } else {
                console.log("Error");
            }
        }
    };
    req.send(null);
}

Pebble.addEventListener("ready", function (e) {
    console.log("connected, doing first update");
    update();
});

Pebble.addEventListener("appmessage", function (e) {
    console.log("tick, doing update");
    update();
});

Pebble.addEventListener("showConfiguration", function (e) {
    console.log("config requested");
    Pebble.openURL("http://eatenbyagrue.org/a/sixfour.psgi");
});

Pebble.addEventListener("webviewclosed", function (e) {
    console.log("config closed, response: "+e.response);
    if (e.response !== "CANCELLED") {
        localStorage.setItem("matchId", e.response);
        update();
    }
});
<commit_msg>reword balls remaining text<commit_after>function unpack_data (data, out) {
    var teams = {};
    var players = {};
    data.team.forEach(function (team) {
        teams[team.team_id] = team;
        var playerList = team.player || team.squad;
        playerList.forEach(function (player) {
            players[player.player_id] = player;
        });
    });

    var match_status = data.match.match_status || "complete";

    console.log("match status: "+match_status);

    switch (match_status) {
        case "dormant":
            out.score = data.match.team1_filename+" v "+data.match.team2_filename;
            out.lead = "Match starts in "+data.match.match_clock;

            if (data.match.toss_decision && data.match.toss_decision !== "") {
                out.striker_name = teams[data.match.toss_winner_team_id].team_short_name+" won toss,";
                out.nonstriker_name = "will "+data.match.toss_decision_name;
            }
            break;

        case "complete": {
            out.score = data.match.team1_filename+" v "+data.match.team2_filename;

            if (data.match.winner_team_id == "0") {
                out.striker_name = "Match drawn";
            }
            else {
                out.striker_name = teams[data.match.winner_team_id].team_short_name+" won by";
                if (data.match.amount_name === "innings") {
                    out.nonstriker_name = "innings and "+data.match.amount+" runs";
                }
                else {
                    out.nonstriker_name = data.match.amount+" "+data.match.amount_name;
                }
            }
            break;
        }

        case "current": {
            var innings = data.live.innings;

            out.score = [
                teams[innings.batting_team_id].team_filename + " " + innings.runs,
                (innings.wickets < 10) ? "/"+innings.wickets : "",
                ((innings.event && innings.event == "declared") ? "d" : "")
            ].join('');

            out.overs = innings.overs;

            if (+data.match.scheduled_overs > 0) {
                switch (+innings.innings_number) {
                    case 1:
                        out.lead = "Run rate: "+innings.run_rate;
                        break;
                    default:
                        out.lead =
                            "Need "+(1-innings.lead)+" from "+
                            (innings.remaining_overs <= 10.0 ? innings.remaining_balls : innings.remaining_overs+" ov");
                        break;
                }
            }
            else {
                switch (+innings.innings_number) {
                    case 1:
                        out.lead = "First innings";
                        break;
                    case 4:
                        out.lead = "Target "+(innings.target);
                        break;
                    default:
                        out.lead =
                            innings.lead < 0 ? "Trail by "+(-innings.lead) :
                            innings.lead > 0 ? "Lead by "+innings.lead :
                                            "Scores level";
                }
            }

            var striker = data.live.batting.filter(function (player) { return player.live_current_name == "striker"; })[0];
            var nonstriker = data.live.batting.filter(function (player) { return player.live_current_name == "non-striker"; })[0];

            if (!striker) {
                striker = nonstriker;
                nonstriker = null;
            }

            var shorten = function (n) {
                var bits = n.split(' ');
                for (var i = 0; i < bits.length-1; i++)
                    bits[i] = bits[i].substr(0,1);
                return bits.join('.');
            };

            if (striker) {
                var striker_name = players[striker.player_id].card_short;
                if (striker_name.length > 10 && players[striker.player_id].popular_name.length > 0)
                    striker_name = players[striker.player_id].popular_name;
                if (striker_name.length > 10)
                    striker_name = shorten(striker_name);
                out.striker_name = striker_name + (nonstriker ? "*" : "");
                out.striker_stats = striker.runs+" ("+striker.balls_faced+")";
            }

            if (nonstriker) {
                var nonstriker_name = players[nonstriker.player_id].card_short;
                if (nonstriker_name.length > 10 && players[nonstriker.player_id].popular_name.length > 0)
                    nonstriker_name = players[nonstriker.player_id].popular_name;
                if (nonstriker_name.length > 10)
                    nonstriker_name = shorten(nonstriker_name);
                out.nonstriker_name = nonstriker_name;
                out.nonstriker_stats = nonstriker.runs+" ("+nonstriker.balls_faced+")";
            }

            var bowler = data.live.bowling.filter(function (player) { return player.live_current_name == "current bowler"; })[0];
            if (bowler) {
                var bowler_name = players[bowler.player_id].card_short;
                if (bowler_name.length > 10) bowler_name = players[bowler.player_id].popular_name;
                out.bowler_name = bowler_name;
                out.bowler_stats = bowler.overs+"-"+bowler.maidens+"-"+bowler.conceded+"-"+bowler.wickets;
            }

            break;
        }
    }
}

function new_out () {
    var out = {
        "score":"",
        "overs":"",
        "lead":"",
        "striker_name":"",
        "striker_stats":"",
        "nonstriker_name":"",
        "nonstriker_stats":"",
        "bowler_name":"",
        "bowler_stats":""
    };
    return out;
}

function update () {
    var out = new_out();
    var matchId = localStorage.getItem("matchId");
    if (!matchId) {
        out.striker_name = "No match selected";
        out.nonstriker_name = "in config.";
        Pebble.sendAppMessage(out);
        return;
    }
    var req = new XMLHttpRequest();
    req.open('GET', "http://www.espncricinfo.com/ci/engine/match/"+matchId+".json");
    req.onload = function(e) {
        if (req.readyState == 4) {
            if(req.status == 200) {
                console.log("got new data, updating");

                var data = JSON.parse(req.responseText);
                if (data) {
                    unpack_data(data, out);
                    console.log(JSON.stringify(out));
                    Pebble.sendAppMessage(out);
                }

            } else {
                console.log("Error");
            }
        }
    };
    req.send(null);
}

Pebble.addEventListener("ready", function (e) {
    console.log("connected, doing first update");
    update();
});

Pebble.addEventListener("appmessage", function (e) {
    console.log("tick, doing update");
    update();
});

Pebble.addEventListener("showConfiguration", function (e) {
    console.log("config requested");
    Pebble.openURL("http://eatenbyagrue.org/a/sixfour.psgi");
});

Pebble.addEventListener("webviewclosed", function (e) {
    console.log("config closed, response: "+e.response);
    if (e.response !== "CANCELLED") {
        localStorage.setItem("matchId", e.response);
        update();
    }
});
<|endoftext|>


<commit_before>/**
 * Check if value is Array
 *
 * @param  {Any}     arr  Variable passed
 * @return {Boolean}      Whether if is array or not
 */
module.exports.isArray = function(arr){
	return Object.prototype.toString.call(arr) == "[object Array]";
};

/**
 * Check if a value is inside an Array
 *
 * @param  {Array} 		  arr Array where to find the value
 * @param  {String|Array} val Value to check if is in array
 * @return {Boolean}     	  Whether the value/values are found in the array
 */
module.exports.inArray = function(arr, val){
	if(this.isArray(val)){
		var matched = 0;

		for (var i = 0; i < val.length; i++) {
			if(this.inArray(arr, val[i]))
				matched++;
		}

		return matched == val.length;
	}

	return arr.indexOf(val) > -1;
};

/**
 * Check if a value is a valid JSON string
 *
 * @param  {Any}  	 json The value to check if is JSON string
 * @return {Boolean}      Wheter the value is valid JSON string
 */
module.exports.isJSON = function(json){
	if(this.isString(json)){
		try{
			JSON.parse(json);
		}
		catch(e){
			return false;
		}

		return true;
	}

	return false;
}

/**
 * Check if a value is Number
 *
 * @param  {Any}  	 int Value to check if is integer
 * @return {Boolean}     Wheter the value is number or not
 */
module.exports.isNumber = function(int){
	return Object.prototype.toString.call(int) == "[object Number]";
};

/**
 * Check if value is Object
 *
 * @param  {Any}     obj  Variable passed
 * @return {Boolean}      Whether if is object or not
 */
module.exports.isObject = function(obj){
	return Object.prototype.toString.call(obj) == "[object Object]";
};

/**
 * Check if a value exists as key object
 *
 * @param  {Object} 	  obj Object to find the keys
 * @param  {String|Array} key Key value to check if is in object
 * @return {Boolean}     	  Wheter the value is found
 */
module.exports.inKeyObject = function(obj, key){
	if(this.isArray(key)){
		var arr = [];

		for(k in obj)
			arr.push(k);

		return this.inArray(arr, key);
	};

	return obj.hasOwnProperty(key);
};

/**
 * Get all index values inside an Array/Object and returns an array
 *
 * @param  {Object|Array} obj The Array/Object to gather index values
 * @return {Array}      	  The list of all index values found
 */
module.exports.getIndexObject = Object.keys || function(obj){
	var arr = [];

	for(k in obj){
		arr.push(k);
	}

	return arr;
};

/**
 * Change the key name in an object
 *
 * @param  {Object}  obj   The object where to make the change
 * @param  {String}  oldp  The key name to change in object
 * @param  {String}  newp  The new key name to replace
 * @param  {Boolean} alter Whether alter the object itself
 * @return {Object}        If alter is present, then returns the new object
 */
module.exports.changeKeyName = function(obj, oldp, newp, alter){
	if(this.isObject(obj)){
		if(alter){
			obj[newp] = obj[oldp];
			delete obj[oldp];

			return obj;
		}

		else{
			var newobj = obj;
			newobj[newp] = obj[oldp];
			delete newobj[oldp];

			return newobj;
		}
	}
}

/**
 * Check if a value is String
 *
 * @param  {Any}  	 str Value to check if is string
 * @return {Boolean}     Wheter the value is string or not
 */
module.exports.isString = function(str){
	return Object.prototype.toString.call(str) == "[object String]";
};

/**
 * Transforms array into string
 *
 * @param  {Array}  arr Array to transform
 * @param  {String} spr Optional: value separator for each element
 * @return {String}     Array stringified
 */
module.exports.arrayToString = function(arr, spr){
	if(spr){
		return arr.join(spr);
	}

	return arr.join(" ");
}

/**
 * Iterates array or object synchronously
 *
 * @param  {Array|Object}   obj     Array/Object to make iteration
 * @param  {Function} 		cb      Function with index, value and function to continue
 * @param  {Function}       finish  Function when iteration finishes
 */
module.exports.each = function(obj, cb, finish){
	var pkg = this; //Define this for inner functions use
	var keys = pkg.getIndexObject(obj);
	var count = 0;
	var index;
	var done = false;

	function getKey(){
		if(pkg.isArray(obj)){
			index = count;
		}

		if(pkg.isObject(obj)){
			index = keys[count];
		}
	}

	function iterate(){
		if(keys.length > count){
			getKey();
			cb(index, obj[index], next);
		}

		else{
			if(finish)
				finish();

			return true;
		}
	}

	function next(){
		count++;
		iterate();
	}

	iterate();
}

/**
 * Checks if a value is falsy
 *
 * @param  {Any}     value Value to check
 * @return {Boolean}       Whether is falsy or not
 */
module.exports.isFalsy = function(value){
	if(value == false){
		return true;
	}

	if(value == null){
		return true;
	}

	else{
		return false;
	}
}<commit_msg>FIXED: isFalsy for NaN<commit_after>/**
 * Check if value is Array
 *
 * @param  {Any}     arr  Variable passed
 * @return {Boolean}      Whether if is array or not
 */
module.exports.isArray = function(arr){
	return Object.prototype.toString.call(arr) == "[object Array]";
};

/**
 * Check if a value is inside an Array
 *
 * @param  {Array} 		  arr Array where to find the value
 * @param  {String|Array} val Value to check if is in array
 * @return {Boolean}     	  Whether the value/values are found in the array
 */
module.exports.inArray = function(arr, val){
	if(this.isArray(val)){
		var matched = 0;

		for (var i = 0; i < val.length; i++) {
			if(this.inArray(arr, val[i]))
				matched++;
		}

		return matched == val.length;
	}

	return arr.indexOf(val) > -1;
};

/**
 * Check if a value is a valid JSON string
 *
 * @param  {Any}  	 json The value to check if is JSON string
 * @return {Boolean}      Wheter the value is valid JSON string
 */
module.exports.isJSON = function(json){
	if(this.isString(json)){
		try{
			JSON.parse(json);
		}
		catch(e){
			return false;
		}

		return true;
	}

	return false;
}

/**
 * Check if a value is Number
 *
 * @param  {Any}  	 int Value to check if is integer
 * @return {Boolean}     Wheter the value is number or not
 */
module.exports.isNumber = function(int){
	return Object.prototype.toString.call(int) == "[object Number]";
};

/**
 * Check if value is Object
 *
 * @param  {Any}     obj  Variable passed
 * @return {Boolean}      Whether if is object or not
 */
module.exports.isObject = function(obj){
	return Object.prototype.toString.call(obj) == "[object Object]";
};

/**
 * Check if a value exists as key object
 *
 * @param  {Object} 	  obj Object to find the keys
 * @param  {String|Array} key Key value to check if is in object
 * @return {Boolean}     	  Wheter the value is found
 */
module.exports.inKeyObject = function(obj, key){
	if(this.isArray(key)){
		var arr = [];

		for(k in obj)
			arr.push(k);

		return this.inArray(arr, key);
	};

	return obj.hasOwnProperty(key);
};

/**
 * Get all index values inside an Array/Object and returns an array
 *
 * @param  {Object|Array} obj The Array/Object to gather index values
 * @return {Array}      	  The list of all index values found
 */
module.exports.getIndexObject = Object.keys || function(obj){
	var arr = [];

	for(k in obj){
		arr.push(k);
	}

	return arr;
};

/**
 * Change the key name in an object
 *
 * @param  {Object}  obj   The object where to make the change
 * @param  {String}  oldp  The key name to change in object
 * @param  {String}  newp  The new key name to replace
 * @param  {Boolean} alter Whether alter the object itself
 * @return {Object}        If alter is present, then returns the new object
 */
module.exports.changeKeyName = function(obj, oldp, newp, alter){
	if(this.isObject(obj)){
		if(alter){
			obj[newp] = obj[oldp];
			delete obj[oldp];

			return obj;
		}

		else{
			var newobj = obj;
			newobj[newp] = obj[oldp];
			delete newobj[oldp];

			return newobj;
		}
	}
}

/**
 * Check if a value is String
 *
 * @param  {Any}  	 str Value to check if is string
 * @return {Boolean}     Wheter the value is string or not
 */
module.exports.isString = function(str){
	return Object.prototype.toString.call(str) == "[object String]";
};

/**
 * Transforms array into string
 *
 * @param  {Array}  arr Array to transform
 * @param  {String} spr Optional: value separator for each element
 * @return {String}     Array stringified
 */
module.exports.arrayToString = function(arr, spr){
	if(spr){
		return arr.join(spr);
	}

	return arr.join(" ");
}

/**
 * Iterates array or object synchronously
 *
 * @param  {Array|Object}   obj     Array/Object to make iteration
 * @param  {Function} 		cb      Function with index, value and function to continue
 * @param  {Function}       finish  Function when iteration finishes
 */
module.exports.each = function(obj, cb, finish){
	var pkg = this; //Define this for inner functions use
	var keys = pkg.getIndexObject(obj);
	var count = 0;
	var index;
	var done = false;

	function getKey(){
		if(pkg.isArray(obj)){
			index = count;
		}

		if(pkg.isObject(obj)){
			index = keys[count];
		}
	}

	function iterate(){
		if(keys.length > count){
			getKey();
			cb(index, obj[index], next);
		}

		else{
			if(finish)
				finish();

			return true;
		}
	}

	function next(){
		count++;
		iterate();
	}

	iterate();
}

/**
 * Checks if a value is falsy
 *
 * @param  {Any}     value Value to check
 * @return {Boolean}       Whether is falsy or not
 */
module.exports.isFalsy = function(value){
	if(value == false){
		return true;
	}

	else if(value == null){
		return true;
	}

	else if(this.isNumber(value) && Number.isNaN(value)){
		return true;
	}

	else{
		return false;
	}
}<|endoftext|>


<commit_before>/**
 * Created by carl.hand on 18/04/2017.
 */
import React from 'react';
import Player from './Player';
import AddRemoveButton from './AddRemoveButton';
import Stopwatch from './Stopwatch';
require('../app.css');

var Scoreboard = React.createClass({
    getInitialState: function () {
        return ({
            Players: [
                {
                    name: "Carl",
                    score: 0,
                },
                {
                    name: "Lee",
                    score: 0,
                }
            ],
            title: "Scoreboard",
            time: 20,
            startInterval: ""
        });
    },

    handleIncrement: function(index, delta) {
        var Players = [...this.state.Players];
        var newScore = Players[index].score += delta;

        this.setState({
            score: newScore
        });

        console.log("INCREMENT:");
        console.log("Player " + Players[index].name + " score is: " + Players[index].score);

        this.state.Players.map((player) => {
            console.log(player.name + " " + player.score);
        });

        if (newScore >= 5) {
            alert(Players[index].name + " is the winner");

            Players.map((player) => {
                player.score = 0;
            });
            this.resetGame();
        }
    },

    handleDecrement: function(index, delta) {
        var Players = [...this.state.Players];
        var newScore = Players[index].score;

        if (newScore > 0) {
            newScore = Players[index].score -= delta;
            this.setState({
                score: newScore
            });

            console.log("Decrement:");
            console.log("Player score is: " + Players[index].score);
        }
    },

    handleAdd: function(newName) {
        // copying the contents of our state but this.state.Players will remain the same
        var Players = [...this.state.Players];

        if (newName === "") {
            console.log("Please enter a name");
        }
        else {
            Players.push({
                name: newName,
                score: 0
            });
        }

        this.setState({
            Players: Players
        });
    },

    handleRemove: function(name) {
        var Players = [...this.state.Players];
        Players.map(function (player, index) {

            if (player.name === name) {
                Players.splice(index, 1);
            }
            else if (name === "") {
                console.log("Please enter a name");
            }
            else {
                console.log(name + " does not exist");
            }
        });

        this.setState({
            Players: Players
        });
    },

    startGame() {
        var intervalID = setInterval(function() {
            var newTime = this.state.time;
            if (newTime > 0) {
                this.setState({
                    time: newTime - 1
                });
            }
            else {
                alert("GAME OVER");
                clearInterval(intervalID);
            }
            console.log("INTERVAL ID: " + this.state.startInterval);
        }.bind(this), 1000);

        this.setState({
            startInterval: intervalID
        });
    },

    shouldStartGame() {
        if (this.state.time >= 20) {
            this.startGame();
        }
    },

    resetGame() {
        console.log(this.state.startInterval);
        clearInterval(this.state.startInterval);

        console.log(this.state.startInterval);
        this.setState({
            time: 20
        });
    },

    componentDidMount() {
        this.startGame();
    },

    componentWillUnmount() {
        clearInterval(this.state.startInterval);
    },

    render: function() {
        return (

                <Stopwatch time={this.state.time} shouldStart={this.shouldStartGame} reset={this.resetGame} />

{this.state.title}

                    {this.state.Players.map((player, index) => {
                        return <Player id={index} name={player.name} key={index} score={player.score} onIncrement={this.handleIncrement} onDecrement={this.handleDecrement} />
                    })}

                    <AddRemoveButton onAdd={this.handleAdd} onRemove={this.handleRemove} />

        );
    }
});

export default Scoreboard;<commit_msg>created a local variable for a bindActionCreator for addPlayer<commit_after>/**
 * Created by carl.hand on 18/04/2017.
 */
import React from 'react';
import Player from './Player';
import AddRemoveButton from './AddRemoveButton';
import Stopwatch from './Stopwatch';
import * as PlayerActionCreators from "../actions/player";
import bindActionCreators from "../../node_modules/redux/es/bindActionCreators";
require('../app.css');

var Scoreboard = React.createClass({
    getInitialState: function () {
        return ({
            Players: [
                {
                    name: "Carl",
                    score: 0,
                },
                {
                    name: "Lee",
                    score: 0,
                }
            ],
            title: "Scoreboard",
            time: 20,
            startInterval: ""
        });
    },

    handleIncrement: function(index, delta) {
        var Players = [...this.state.Players];
        var newScore = Players[index].score += delta;

        this.setState({
            score: newScore
        });

        console.log("INCREMENT:");
        console.log("Player " + Players[index].name + " score is: " + Players[index].score);

        this.state.Players.map((player) => {
            console.log(player.name + " " + player.score);
        });

        if (newScore >= 5) {
            alert(Players[index].name + " is the winner");

            Players.map((player) => {
                player.score = 0;
            });
            this.resetGame();
        }
    },

    handleDecrement: function(index, delta) {
        var Players = [...this.state.Players];
        var newScore = Players[index].score;

        if (newScore > 0) {
            newScore = Players[index].score -= delta;
            this.setState({
                score: newScore
            });

            console.log("Decrement:");
            console.log("Player score is: " + Players[index].score);
        }
    },

    handleAdd: function(newName) {
        // copying the contents of our state but this.state.Players will remain the same
        var Players = [...this.state.Players];

        if (newName === "") {
            console.log("Please enter a name");
        }
        else {
            Players.push({
                name: newName,
                score: 0
            });
        }

        this.setState({
            Players: Players
        });
    },

    handleRemove: function(name) {
        var Players = [...this.state.Players];
        Players.map(function (player, index) {

            if (player.name === name) {
                Players.splice(index, 1);
            }
            else if (name === "") {
                console.log("Please enter a name");
            }
            else {
                console.log(name + " does not exist");
            }
        });

        this.setState({
            Players: Players
        });
    },

    startGame() {
        var intervalID = setInterval(function() {
            var newTime = this.state.time;
            if (newTime > 0) {
                this.setState({
                    time: newTime - 1
                });
            }
            else {
                alert("GAME OVER");
                clearInterval(intervalID);
            }
            console.log("INTERVAL ID: " + this.state.startInterval);
        }.bind(this), 1000);

        this.setState({
            startInterval: intervalID
        });
    },

    shouldStartGame() {
        if (this.state.time >= 20) {
            this.startGame();
        }
    },

    resetGame() {
        console.log(this.state.startInterval);
        clearInterval(this.state.startInterval);

        console.log(this.state.startInterval);
        this.setState({
            time: 20
        });
    },

    componentDidMount() {
        this.startGame();
    },

    componentWillUnmount() {
        clearInterval(this.state.startInterval);
    },

    render: function() {
        const { dispatch, players } = this.props;
        const addPlayer = bindActionCreators(PlayerActionCreators.add, dispatch);
        // const removePlayer = bindActionCreators(PlayerActionCreators.remove, dispatch);
        // const incrementScore = bindActionCreators(PlayerActionCreators.increment, dispatch);

        return (

                <Stopwatch time={this.state.time} shouldStart={this.shouldStartGame} reset={this.resetGame} />

{this.state.title}

                    {this.state.Players.map((player, index) => {
                        return <Player id={index} name={player.name} key={index} score={player.score} onIncrement={this.handleIncrement} onDecrement={this.handleDecrement} />
                    })}

                    <AddRemoveButton onAdd={addPlayer} onRemove={this.handleRemove} />

        );
    }
});

export default Scoreboard;<|endoftext|>


<commit_before>/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
 * Licensed under the MIT License
 */
'use strict';

var d = require('../lib/dom')
  , h = require('../lib/helper')
  , instances = require('./instances')
  , updateGeometry = require('./update-geometry');

module.exports = function (element) {
  var i = instances.get(element);

  if (!i) {
    return;
  }

  // Recalcuate negative scrollLeft adjustment
  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;

  // Recalculate rail margins
  d.css(i.scrollbarXRail, 'display', 'block');
  d.css(i.scrollbarYRail, 'display', 'block');
  i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
  i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));

  // Hide scrollbars not to affect scrollWidth and scrollHeight
  d.css(i.scrollbarXRail, 'display', 'none');
  d.css(i.scrollbarYRail, 'display', 'none');

  updateGeometry(element);

  d.css(i.scrollbarXRail, 'display', '');
  d.css(i.scrollbarYRail, 'display', '');
};
<commit_msg>trigger events on update<commit_after>/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
 * Licensed under the MIT License
 */
'use strict';

var d = require('../lib/dom')
  , h = require('../lib/helper')
  , instances = require('./instances')
  , updateGeometry = require('./update-geometry')
  , updateScroll = require('./update-scroll');

module.exports = function (element) {
  var i = instances.get(element);

  if (!i) {
    return;
  }

  // Recalcuate negative scrollLeft adjustment
  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;

  // Recalculate rail margins
  d.css(i.scrollbarXRail, 'display', 'block');
  d.css(i.scrollbarYRail, 'display', 'block');
  i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
  i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));

  // Hide scrollbars not to affect scrollWidth and scrollHeight
  d.css(i.scrollbarXRail, 'display', 'none');
  d.css(i.scrollbarYRail, 'display', 'none');

  updateGeometry(element);

  // Update top/left scroll to trigger events
  updateScroll(element, 'top', element.scrollTop);
  updateScroll(element, 'left', element.scrollLeft);

  d.css(i.scrollbarXRail, 'display', '');
  d.css(i.scrollbarYRail, 'display', '');
};
<|endoftext|>


<commit_before>/**
 *
 * Menu
 *
 */
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Drawer from 'material-ui/Drawer'
import { List, ListItem, makeSelectable } from 'material-ui/List'
import Divider from 'material-ui/Divider'
import Subheader from 'material-ui/Subheader'
import { FormattedMessage } from 'react-intl'
import muiThemeable from 'material-ui/styles/muiThemeable'
import SettingsIcon from 'material-ui/svg-icons/action/settings'
import SearchIcon from 'material-ui/svg-icons/action/search'
import PrizesIcon from 'material-ui/svg-icons/action/card-membership'
import ToolsIcon from 'material-ui/svg-icons/action/build'
import AppsIcon from 'material-ui/svg-icons/navigation/apps'
import AccountIcon from 'material-ui/svg-icons/social/person-add'
import LoginIcon from 'material-ui/svg-icons/social/person'
import InfoIcon from 'material-ui/svg-icons/action/info'
import PictogramsIcon from 'material-ui/svg-icons/image/collections'
import PeopleIcon from 'material-ui/svg-icons/social/people'
import SoftwareIcon from 'material-ui/svg-icons/action/important-devices'
import MaterialsIcon from 'material-ui/svg-icons/av/library-books'
import NewsIcon from 'material-ui/svg-icons/communication/message'
import SignoutIcon from 'material-ui/svg-icons/content/block'
import ApiIcon from 'material-ui/svg-icons/communication/import-export'
import ContactMailIcon from 'material-ui/svg-icons/communication/contact-mail'
import FileUploadIcon from 'material-ui/svg-icons/file/file-upload'
import CloudDownloadIcon from 'material-ui/svg-icons/file/cloud-download'
import Div from 'components/Div'
import messages from './messages'
import styles from './styles'

const SelectableList = makeSelectable(List)

class Menu extends Component {
  static propTypes = {
    docked: PropTypes.bool.isRequired,
    location: PropTypes.object.isRequired,
    onChangeList: PropTypes.func.isRequired,
    onRequestChangeNavDrawer: PropTypes.func.isRequired,
    open: PropTypes.bool.isRequired,
    muiTheme: PropTypes.object.isRequired,
    isAuthenticated: PropTypes.bool.isRequired,
    signout: PropTypes.func.isRequired,
    isMobile: PropTypes.bool.isRequired
  }

  static contextTypes = {
    router: PropTypes.object.isRequired
  }

  state = {
    muiVersions: []
  }

  handleRequestChangeLink = (event, value) => {
    window.location = value
  }

  handleRouterChangeLink = (value) => {
    this.context.router.push(value)
  }

  handleTouchTapHeader = () => {
    this.context.router.push('/')
    this.props.onRequestChangeNavDrawer(false)
  }

  render() {
    const {
      location,
      docked,
      onRequestChangeNavDrawer,
      onChangeList,
      open,
      muiTheme,
      isAuthenticated,
      signout,
      isMobile
    } = this.props

    return (
      <Drawer
        style={styles.menu}
        docked={docked}
        open={open}
        id='menu'
        onRequestChange={onRequestChangeNavDrawer}
        // containerStyle={{zIndex: zIndex.drawer - 100}}
        // containerStyle={{ Index: 1200 }}
      >
        {
          // eslint-disable-next-line jsx-a11y/no-static-element-interactions
        }{' '}

          ARASAAC

        <SelectableList value={location.pathname} onChange={onChangeList}>
          <ListItem
            id='lstpictograms'
            primaryText={<FormattedMessage {...messages.pictograms} />}
            primaryTogglesNestedList={true}
            leftIcon={<PictogramsIcon />}
            nestedItems={[
              <ListItem
                value='/pictograms/search'
                primaryText={
                  <FormattedMessage {...messages.searchPictograms} />
                }
                leftIcon={<SearchIcon />}
              />,
              <ListItem
                value='/pictograms/catalogs'
                primaryText={<FormattedMessage {...messages.downloads} />}
                leftIcon={<CloudDownloadIcon />}
              />
            ]}
          />
          <ListItem
            id='lstmaterials'
            primaryText={<FormattedMessage {...messages.materials} />}
            primaryTogglesNestedList={true}
            leftIcon={<MaterialsIcon />}
            nestedItems={[
              <ListItem
                value='/materials/search'
                primaryText={<FormattedMessage {...messages.searchMaterials} />}
                leftIcon={<SearchIcon />}
              />,
              <ListItem
                value='/materials/upload'
                primaryText={<FormattedMessage {...messages.uploadMaterials} />}
                leftIcon={<FileUploadIcon />}
              />
            ]}
          />
          <ListItem
            id='lstonlinetools'
            primaryText={<FormattedMessage {...messages.onlineTools} />}
            primaryTogglesNestedList={true}
            leftIcon={<AppsIcon />}
            nestedItems={[
              <ListItem
                value='/onlinetools/animations-maker'
                primaryText={<FormattedMessage {...messages.animationsMaker} />}
              />,
              <ListItem
                value='/onlinetools/symbols-creator'
                primaryText={<FormattedMessage {...messages.symbolsCreator} />}
              />,
              <ListItem
                value='/onlinetools/schedule-generator'
                primaryText={
                  <FormattedMessage {...messages.scheduleGenerator} />
                }
              />,
              <ListItem
                value='/onlinetools/calendar-generator'
                primaryText={
                  <FormattedMessage {...messages.calendarGenerator} />
                }
              />,
              <ListItem
                value='/onlinetools/bingos-creator'
                primaryText={<FormattedMessage {...messages.bingo} />}
              />,
              <ListItem
                value='/onlinetools/snakes-and-ladders'
                primaryText={
                  <FormattedMessage {...messages.snakesAndLadders} />
                }
              />,
              <ListItem
                value='/onlinetools/dominos'
                primaryText={<FormattedMessage {...messages.dominos} />}
              />,
              <ListItem
                value='/onlinetools/dominos-encadenados'
                primaryText={
                  <FormattedMessage {...messages.dominosencadenados} />
                }
              />
            ]}
          />
          <ListItem
            id='lstsoftware'
            value='/software'
            primaryText={<FormattedMessage {...messages.software} />}
            leftIcon={<SoftwareIcon />}
          />
          <ListItem
            id='lstdevelopers'
            primaryText={<FormattedMessage {...messages.dev} />}
            primaryTogglesNestedList={true}
            leftIcon={<ToolsIcon />}
            nestedItems={[
              <ListItem
                value='/developers'
                primaryText={<FormattedMessage {...messages.devInfo} />}
                leftIcon={<InfoIcon />}
              />,
              <ListItem
                value='/developers/api'
                primaryText={<FormattedMessage {...messages.api} />}
                leftIcon={<ApiIcon />}
              />,
              <ListItem
                value='/developers/accounts'
                primaryText={<FormattedMessage {...messages.devAccount} />}
                leftIcon={<AccountIcon />}
              />
            ]}
          />
          <ListItem
            id='lstsettings'
            value='/settings'
            primaryText={<FormattedMessage {...messages.settings} />}
            leftIcon={<SettingsIcon />}
          />
        </SelectableList>
        <Divider />
        {isMobile && (
          <SelectableList value={location.pathname}>
            <Subheader>{<FormattedMessage {...messages.user} />}</Subheader>
            {isAuthenticated ? (

                <ListItem
                  id='lstsignout'
                  primaryText={<FormattedMessage {...messages.signout} />}
                  leftIcon={<SignoutIcon />}
                  onClick={signout}
                />

            ) : (

                <ListItem
                  id='lstlogin'
                  value='/signin'
                  primaryText={<FormattedMessage {...messages.signin} />}
                  leftIcon={<LoginIcon />}
                  onClick={() => this.handleRouterChangeLink('/signin')}
                />
                <ListItem
                  id='lstregister'
                  value='/register'
                  primaryText={<FormattedMessage {...messages.register} />}
                  leftIcon={<AccountIcon />}
                  onClick={() => this.handleRouterChangeLink('/register')}
                />

            )}
          </SelectableList>
        )}
        <Divider />
        <SelectableList value='' onChange={this.handleRequestChangeLink}>
          <Subheader>{<FormattedMessage {...messages.info} />}</Subheader>
          <ListItem
            id='lstnews'
            value='https://github.com/callemall/material-ui'
            primaryText={<FormattedMessage {...messages.news} />}
            leftIcon={<NewsIcon />}
          />
          <ListItem
            id='lstarasaacteam'
            value='/arasaac-team'
            primaryText={<FormattedMessage {...messages.whoWeAre} />}
            leftIcon={<PeopleIcon />}
          />
          <ListItem
            id='lstprizes'
            value='/prizes'
            primaryText={<FormattedMessage {...messages.prizes} />}
            leftIcon={<PrizesIcon />}
          />
          <ListItem
            value='/contact-us'
            primaryText={<FormattedMessage {...messages.contact} />}
            leftIcon={<ContactMailIcon />}
          />
        </SelectableList>
      </Drawer>
    )
  }
}

export default muiThemeable()(Menu)
<commit_msg>remove sidebar when click on user login, user create menu option<commit_after>/**
 *
 * Menu
 *
 */
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Drawer from 'material-ui/Drawer'
import { List, ListItem, makeSelectable } from 'material-ui/List'
import Divider from 'material-ui/Divider'
import Subheader from 'material-ui/Subheader'
import { FormattedMessage } from 'react-intl'
import muiThemeable from 'material-ui/styles/muiThemeable'
import SettingsIcon from 'material-ui/svg-icons/action/settings'
import SearchIcon from 'material-ui/svg-icons/action/search'
import PrizesIcon from 'material-ui/svg-icons/action/card-membership'
import ToolsIcon from 'material-ui/svg-icons/action/build'
import AppsIcon from 'material-ui/svg-icons/navigation/apps'
import AccountIcon from 'material-ui/svg-icons/social/person-add'
import LoginIcon from 'material-ui/svg-icons/social/person'
import InfoIcon from 'material-ui/svg-icons/action/info'
import PictogramsIcon from 'material-ui/svg-icons/image/collections'
import PeopleIcon from 'material-ui/svg-icons/social/people'
import SoftwareIcon from 'material-ui/svg-icons/action/important-devices'
import MaterialsIcon from 'material-ui/svg-icons/av/library-books'
import NewsIcon from 'material-ui/svg-icons/communication/message'
import SignoutIcon from 'material-ui/svg-icons/content/block'
import ApiIcon from 'material-ui/svg-icons/communication/import-export'
import ContactMailIcon from 'material-ui/svg-icons/communication/contact-mail'
import FileUploadIcon from 'material-ui/svg-icons/file/file-upload'
import CloudDownloadIcon from 'material-ui/svg-icons/file/cloud-download'
import Div from 'components/Div'
import messages from './messages'
import styles from './styles'

const SelectableList = makeSelectable(List)

class Menu extends Component {
  static propTypes = {
    docked: PropTypes.bool.isRequired,
    location: PropTypes.object.isRequired,
    onChangeList: PropTypes.func.isRequired,
    onRequestChangeNavDrawer: PropTypes.func.isRequired,
    open: PropTypes.bool.isRequired,
    muiTheme: PropTypes.object.isRequired,
    isAuthenticated: PropTypes.bool.isRequired,
    signout: PropTypes.func.isRequired,
    isMobile: PropTypes.bool.isRequired
  }

  static contextTypes = {
    router: PropTypes.object.isRequired
  }

  state = {
    muiVersions: []
  }

  handleRequestChangeLink = (event, value) => {
    window.location = value
  }

  handleRouterChangeLink = (value) => {
    this.context.router.push(value)
    this.props.onRequestChangeNavDrawer(false)
  }

  handleTouchTapHeader = () => {
    this.context.router.push('/')
    this.props.onRequestChangeNavDrawer(false)
  }

  render() {
    const {
      location,
      docked,
      onRequestChangeNavDrawer,
      onChangeList,
      open,
      muiTheme,
      isAuthenticated,
      signout,
      isMobile
    } = this.props

    return (
      <Drawer
        style={styles.menu}
        docked={docked}
        open={open}
        id='menu'
        onRequestChange={onRequestChangeNavDrawer}
        // containerStyle={{zIndex: zIndex.drawer - 100}}
        // containerStyle={{ Index: 1200 }}
      >
        {
          // eslint-disable-next-line jsx-a11y/no-static-element-interactions
        }{' '}

          ARASAAC

        <SelectableList value={location.pathname} onChange={onChangeList}>
          <ListItem
            id='lstpictograms'
            primaryText={<FormattedMessage {...messages.pictograms} />}
            primaryTogglesNestedList={true}
            leftIcon={<PictogramsIcon />}
            nestedItems={[
              <ListItem
                value='/pictograms/search'
                primaryText={
                  <FormattedMessage {...messages.searchPictograms} />
                }
                leftIcon={<SearchIcon />}
              />,
              <ListItem
                value='/pictograms/catalogs'
                primaryText={<FormattedMessage {...messages.downloads} />}
                leftIcon={<CloudDownloadIcon />}
              />
            ]}
          />
          <ListItem
            id='lstmaterials'
            primaryText={<FormattedMessage {...messages.materials} />}
            primaryTogglesNestedList={true}
            leftIcon={<MaterialsIcon />}
            nestedItems={[
              <ListItem
                value='/materials/search'
                primaryText={<FormattedMessage {...messages.searchMaterials} />}
                leftIcon={<SearchIcon />}
              />,
              <ListItem
                value='/materials/upload'
                primaryText={<FormattedMessage {...messages.uploadMaterials} />}
                leftIcon={<FileUploadIcon />}
              />
            ]}
          />
          <ListItem
            id='lstonlinetools'
            primaryText={<FormattedMessage {...messages.onlineTools} />}
            primaryTogglesNestedList={true}
            leftIcon={<AppsIcon />}
            nestedItems={[
              <ListItem
                value='/onlinetools/animations-maker'
                primaryText={<FormattedMessage {...messages.animationsMaker} />}
              />,
              <ListItem
                value='/onlinetools/symbols-creator'
                primaryText={<FormattedMessage {...messages.symbolsCreator} />}
              />,
              <ListItem
                value='/onlinetools/schedule-generator'
                primaryText={
                  <FormattedMessage {...messages.scheduleGenerator} />
                }
              />,
              <ListItem
                value='/onlinetools/calendar-generator'
                primaryText={
                  <FormattedMessage {...messages.calendarGenerator} />
                }
              />,
              <ListItem
                value='/onlinetools/bingos-creator'
                primaryText={<FormattedMessage {...messages.bingo} />}
              />,
              <ListItem
                value='/onlinetools/snakes-and-ladders'
                primaryText={
                  <FormattedMessage {...messages.snakesAndLadders} />
                }
              />,
              <ListItem
                value='/onlinetools/dominos'
                primaryText={<FormattedMessage {...messages.dominos} />}
              />,
              <ListItem
                value='/onlinetools/dominos-encadenados'
                primaryText={
                  <FormattedMessage {...messages.dominosencadenados} />
                }
              />
            ]}
          />
          <ListItem
            id='lstsoftware'
            value='/software'
            primaryText={<FormattedMessage {...messages.software} />}
            leftIcon={<SoftwareIcon />}
          />
          <ListItem
            id='lstdevelopers'
            primaryText={<FormattedMessage {...messages.dev} />}
            primaryTogglesNestedList={true}
            leftIcon={<ToolsIcon />}
            nestedItems={[
              <ListItem
                value='/developers'
                primaryText={<FormattedMessage {...messages.devInfo} />}
                leftIcon={<InfoIcon />}
              />,
              <ListItem
                value='/developers/api'
                primaryText={<FormattedMessage {...messages.api} />}
                leftIcon={<ApiIcon />}
              />,
              <ListItem
                value='/developers/accounts'
                primaryText={<FormattedMessage {...messages.devAccount} />}
                leftIcon={<AccountIcon />}
              />
            ]}
          />
          <ListItem
            id='lstsettings'
            value='/settings'
            primaryText={<FormattedMessage {...messages.settings} />}
            leftIcon={<SettingsIcon />}
          />
        </SelectableList>
        <Divider />
        {isMobile && (
          <SelectableList value={location.pathname}>
            <Subheader>{<FormattedMessage {...messages.user} />}</Subheader>
            {isAuthenticated ? (

                <ListItem
                  id='lstsignout'
                  primaryText={<FormattedMessage {...messages.signout} />}
                  leftIcon={<SignoutIcon />}
                  onClick={signout}
                />

            ) : (

                <ListItem
                  id='lstlogin'
                  value='/signin'
                  primaryText={<FormattedMessage {...messages.signin} />}
                  leftIcon={<LoginIcon />}
                  onClick={() => this.handleRouterChangeLink('/signin')}
                />
                <ListItem
                  id='lstregister'
                  value='/register'
                  primaryText={<FormattedMessage {...messages.register} />}
                  leftIcon={<AccountIcon />}
                  onClick={() => this.handleRouterChangeLink('/register')}
                />

            )}
          </SelectableList>
        )}
        <Divider />
        <SelectableList value='' onChange={this.handleRequestChangeLink}>
          <Subheader>{<FormattedMessage {...messages.info} />}</Subheader>
          <ListItem
            id='lstnews'
            value='https://github.com/callemall/material-ui'
            primaryText={<FormattedMessage {...messages.news} />}
            leftIcon={<NewsIcon />}
          />
          <ListItem
            id='lstarasaacteam'
            value='/arasaac-team'
            primaryText={<FormattedMessage {...messages.whoWeAre} />}
            leftIcon={<PeopleIcon />}
          />
          <ListItem
            id='lstprizes'
            value='/prizes'
            primaryText={<FormattedMessage {...messages.prizes} />}
            leftIcon={<PrizesIcon />}
          />
          <ListItem
            value='/contact-us'
            primaryText={<FormattedMessage {...messages.contact} />}
            leftIcon={<ContactMailIcon />}
          />
        </SelectableList>
      </Drawer>
    )
  }
}

export default muiThemeable()(Menu)
<|endoftext|>


<commit_before>module.exports = innkeeperSocketIO;

var innkeeper = require( 'innkeeper' );

function innkeeperSocketIO( settings ) {

	if( !( this instanceof innkeeperSocketIO ) )
		return new innkeeperSocketIO( settings );

	settings = settings || {};

	this.innkeeper = innkeeper( settings );
}

innkeeperSocketIO.prototype = {

	/**
	 * the reserve function will reserve a room. Reserve will return a promise which will
	 * return a room object on success.
	 *
	 * @return {Promise} [description]
	 */
	reserve: function( socket ) {

		return this.innkeeper.reserve( socket.id );
	},

	/**
	 * Using enter you can enter into a room. This method will return a promise
	 * which on succeed will return a room object. If the room does not exist the promise
	 * will fail.
	 *
	 * @param  {String} id the id of a room you want to enter. Think of it as a room number.
	 * @return {Promise} a promise will be returned which on success will return a room object
	 */
	enter: function( socket, id ) {

		return this.innkeeper.enter( socket.id, id );
	},

	/**
	 * Enter a room with a key instead of a roomid. Key's are shorter than roomid's
	 * so it is much nicer for a user on the frontend to enter with.
	 *
	 * @param  {String} key a key which will be used to enter into a room.
	 * @return {Promise} a promise will be returned which on success will return a room object
	 */
	enterWithKey: function( socket, key ) {

		return this.innkeeper.enterWithKey( socket.id, key );
	},

	/**
	 * Leave a room.
	 *
	 * @param  {String} id the id of a room you want to leave. Think of it as a room number.
	 * @return {Promise} a promise will be returned which on success will return a room object if users are still in room null if not
	 */
	leave: function( socket, id ) {

		return this.innkeeper.leave( socket.id, id );
	}
};<commit_msg>Implemented socket.io join and leave rooms<commit_after>module.exports = innkeeperSocketIO;

var innkeeper = require( 'innkeeper' );

function innkeeperSocketIO( settings ) {

	if( !( this instanceof innkeeperSocketIO ) )
		return new innkeeperSocketIO( settings );

	settings = settings || {};

	this.innkeeper = innkeeper( settings );
}

innkeeperSocketIO.prototype = {

	/**
	 * the reserve function will reserve a room. Reserve will return a promise which will
	 * return a room object on success.
	 *
	 * @return {Promise} [description]
	 */
	reserve: function( socket ) {

		return this.innkeeper.reserve( socket.id )
		.then( joinRoom.bind( this, socket ) );
	},

	/**
	 * Using enter you can enter into a room. This method will return a promise
	 * which on succeed will return a room object. If the room does not exist the promise
	 * will fail.
	 *
	 * @param  {String} id the id of a room you want to enter. Think of it as a room number.
	 * @return {Promise} a promise will be returned which on success will return a room object
	 */
	enter: function( socket, id ) {

		return this.innkeeper.enter( socket.id, id )
		.then( joinRoom.bind( this, socket ) );
	},

	/**
	 * Enter a room with a key instead of a roomid. Key's are shorter than roomid's
	 * so it is much nicer for a user on the frontend to enter with.
	 *
	 * @param  {String} key a key which will be used to enter into a room.
	 * @return {Promise} a promise will be returned which on success will return a room object
	 */
	enterWithKey: function( socket, key ) {

		return this.innkeeper.enterWithKey( socket.id, key )
		.then( joinRoom.bind( this, socket ) );
	},

	/**
	 * Leave a room.
	 *
	 * @param  {String} id the id of a room you want to leave. Think of it as a room number.
	 * @return {Promise} a promise will be returned which on success will return a room object if users are still in room null if not
	 */
	leave: function( socket, id ) {

		return this.innkeeper.leave( socket.id, id )
		.then( function( room ) {

			var disconnectListeners = socket.listeners( 'disconnect' );

			disconnectListeners.forEach( function( listener ) {

				if( listener.roomId == id ) {

					socket.removeListener( 'disconnect', listener );
				}
			});

			socket.leave( id );

			return room;
		});
	}
};

function joinRoom( socket, room ) {

	var onDisconnect = function() {

		this.leave( socket, room.id );
	}.bind( this );

	onDisconnect.roomId = room.id; // need to set this variable so if leave is called manually on disconnect the same room wont be left

	socket.on( 'disconnect', onDisconnect );

	socket.join( room.id );

	return room;
}<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'
import _ from 'lodash'
import {DEFAULT_TITLE, DEFAULT_CONTENT} from '../helpers/const'
import * as CloudUtils from '../helpers/cloud_storage'
import * as DbUtils from '../helpers/database'
import styles from '../helpers/create_login/CreateLogin.css'
import formStyles from './Form.css'

export default React.createClass({
  propTypes: {
    actions: PropTypes.object.isRequired,
    states: PropTypes.object.isRequired
  },

  getInitialState() {
    let user = CloudUtils.getCurrentUser()
    return {
      isLoading: false,
      email: user.getEmail()
    }
  },

  handleCloudSync(formData) {
    this.setState({isLoading: true})
    CloudUtils.query().then(cloudPosts => {
      let localPosts = this.props.states.posts.datasource.filter(item => {
        return item.title !== DEFAULT_TITLE || item.content !== DEFAULT_CONTENT
      })
      let remotePosts = cloudPosts.map(item => {
        return CloudUtils.purify(item)
      })
      let {local, cloud, indexes} = CloudUtils.compare(remotePosts, localPosts)
      let {insert, update, remove} = local
      if (!cloud.length && !insert.length && !update.length && !remove.length) {
        App.alert('同步结束', '本地作品已与云端记录保持一致', 'info')
        this.setState({isLoading: false})
        return Promise.resolve()
      }

      return Promise.all([
        CloudUtils.sync(cloud),
        DbUtils.bulk(local.insert, local.update, local.remove)
      ]).then(result => {
        let tips = `
          云端更新(${cloud.length})
          本地新增(${insert.length}) / 更新(${update.length}) / 删除(${remove.length})
        `
        App.alert('同步成功', tips.trim(), 'success')
        // 找到本地需要更新object_id的数据
        return Promise.all(_.keys(indexes).map(i => {
          return DbUtils.updatePost(indexes[i], {
            object_id: result[0][0].id
          }, true)
        }))
      }).then(() => {
        return DbUtils.listPosts()
      }).then(posts => {
        this.setState({isLoading: false})
        this.props.actions.postsList({posts: posts.reverse()})
      })
    }).catch(err => {
      this.setState({isLoading: false})
      console.error(err)
      App.alert('同步出错', err.message)
    })
  },

  handleLogout() {
    CloudUtils.logout()
    this.props.actions.settingsShow({
      name: 'register'
    })
  },

  render() {
    let btnClass = `${formStyles.btn} ${formStyles.btnBorderOpen} ${formStyles.btnPurple}`
    return (

violet同步帐号

                Email:
                <input type="text" value={this.state.email} readOnly />

                <button
                  onClick={this.handleCloudSync}
                  className={btnClass}
                  disabled={this.state.isLoading}
                >
                  {this.state.isLoading ? '正在同步...' : '立即同步'}
                </button>

                  注销当前帐号

    )
  }
})
<commit_msg>作品排序改漏了<commit_after>import React, {PropTypes} from 'react'
import _ from 'lodash'
import {DEFAULT_TITLE, DEFAULT_CONTENT} from '../helpers/const'
import * as CloudUtils from '../helpers/cloud_storage'
import * as DbUtils from '../helpers/database'
import styles from '../helpers/create_login/CreateLogin.css'
import formStyles from './Form.css'

export default React.createClass({
  propTypes: {
    actions: PropTypes.object.isRequired,
    states: PropTypes.object.isRequired
  },

  getInitialState() {
    let user = CloudUtils.getCurrentUser()
    return {
      isLoading: false,
      email: user.getEmail()
    }
  },

  handleCloudSync(formData) {
    this.setState({isLoading: true})
    CloudUtils.query().then(cloudPosts => {
      let localPosts = this.props.states.posts.datasource.filter(item => {
        return item.title !== DEFAULT_TITLE || item.content !== DEFAULT_CONTENT
      })
      let remotePosts = cloudPosts.map(item => {
        return CloudUtils.purify(item)
      })
      let {local, cloud, indexes} = CloudUtils.compare(remotePosts, localPosts)
      let {insert, update, remove} = local
      if (!cloud.length && !insert.length && !update.length && !remove.length) {
        App.alert('同步结束', '本地作品已与云端记录保持一致', 'info')
        this.setState({isLoading: false})
        return Promise.resolve()
      }

      return Promise.all([
        CloudUtils.sync(cloud),
        DbUtils.bulk(local.insert, local.update, local.remove)
      ]).then(result => {
        let tips = `
          云端更新(${cloud.length})
          本地新增(${insert.length}) / 更新(${update.length}) / 删除(${remove.length})
        `
        App.alert('同步成功', tips.trim(), 'success')
        // 找到本地需要更新object_id的数据
        return Promise.all(_.keys(indexes).map(i => {
          return DbUtils.updatePost(indexes[i], {
            object_id: result[0][0].id
          }, true)
        }))
      }).then(() => {
        return DbUtils.listPosts()
      }).then(posts => {
        this.setState({isLoading: false})
        this.props.actions.postsList({posts})
      })
    }).catch(err => {
      this.setState({isLoading: false})
      console.error(err)
      App.alert('同步出错', err.message)
    })
  },

  handleLogout() {
    CloudUtils.logout()
    this.props.actions.settingsShow({
      name: 'register'
    })
  },

  render() {
    let btnClass = `${formStyles.btn} ${formStyles.btnBorderOpen} ${formStyles.btnPurple}`
    return (

violet同步帐号

                Email:
                <input type="text" value={this.state.email} readOnly />

                <button
                  onClick={this.handleCloudSync}
                  className={btnClass}
                  disabled={this.state.isLoading}
                >
                  {this.state.isLoading ? '正在同步...' : '立即同步'}
                </button>

                  注销当前帐号

    )
  }
})
<|endoftext|>