<commit_before>import React from 'react';
import {connect} from 'react-redux';
import {setField, getProfileTypes, getCouncils, getDistricts} from './registerActions';

class Register extends React.Component {

    constructor() {
        super();
        this.handleChange = this.handleChange.bind(this);
    }

    componentDidMount() {
        getProfileTypes();
        getCouncils();
        getDistricts();
    };

    handleChange(field, value) {
        setField(field, value);
    }

    render() {
        return (

Welcome to Merit Badge University 2018

Registration

                                        <form>

                                                    First Name *
                                                    <input
                                                        value={this.props.firstName}
                                                        type="firstNameInputRegistration"
                                                        className="form-control"
                                                        id="firstName"
                                                        placeholder="First Name"
                                                        onChange={(event) => {
                                                            this.handleChange('firstName', event.target.value);
                                                        }}
                                                    />

                                                    Last Name *
                                                    <input
                                                        value={this.props.lastName}
                                                        type="lastNameInputRegistration"
                                                        className="form-control"
                                                        id="lastName"
                                                        placeholder="Last Name"
                                                        onChange={(event) => {
                                                            this.handleChange('lastName', event.target.value);
                                                        }}
                                                    />

                                                    Email address *
                                                    <input
                                                        value={this.props.email}
                                                        type="inputEmailRegistration"
                                                        className="form-control"
                                                        id="email"
                                                        placeholder="Email"
                                                        onChange={(event) => {
                                                            this.handleChange('email', event.target.value);
                                                        }}
                                                    />

                                                    Confirm Email address *
                                                    <input
                                                        value={this.props.emailConfirm}
                                                        type="inputEmailRegistrationConfirmation"
                                                        className="form-control"
                                                        id="emailConfirm"
                                                        placeholder="Email"
                                                        onChange={(event) => {
                                                            this.handleChange('emailConfirm', event.target.value);
                                                        }}
                                                    />

                                                    Password *
                                                    <input
                                                        value={this.props.password}
                                                        type="inputPasswordRegistration"
                                                        className="form-control"
                                                        id="password"
                                                        placeholder="Password"
                                                        onChange={(event) => {
                                                            this.handleChange('password', event.target.value);
                                                        }}
                                                    />

                                                    Confirm Password *
                                                    <input
                                                        value={this.props.passwordConfirm}
                                                        type="confirmInputPasswordRegistration"
                                                        className="form-control"
                                                        id="passwordConfirm"
                                                        placeholder="Confirm Password"
                                                        onChange={(event) => {
                                                            this.handleChange('passwordConfirm', event.target.value);
                                                        }}
                                                    />

                                                    Who are You? *
                                                    <select
                                                        value={this.props.selectedProfileType}
                                                        className="form-control form-control-lg"
                                                        id="selectedProfileType"
                                                        onChange={(event) => {
                                                            this.handleChange('selectedProfileType', event.target.value);
                                                        }}
                                                    >
                                                        {
                                                            this.props.profileTypes.map( type => <option key={type.value} value={type.value}>{type.label}</option>)
                                                        }
                                                    </select>

                                                    What Council Are You From? *
                                                    <select
                                                        value={this.props.selectedCouncil}
                                                        className="form-control form-control-lg"
                                                        id="selectedCouncil"
                                                        onChange={(event) => {
                                                            this.handleChange('selectedCouncil', event.target.value);
                                                        }}
                                                    >
                                                        {
                                                            this.props.councils.map( type => <option key={type.value} value={type.value}>{type.label}</option>)
                                                        }
                                                    </select>

                                                    Other
                                                    <input
                                                        type="otherCouncil"
                                                        className="form-control"
                                                        id="otherCouncil"
                                                        placeholder="Other"
                                                    />

                                                    What District Are You From? *
                                                    <select
                                                        value={this.props.selectedDistrict}
                                                        className="form-control form-control-lg"
                                                        id="selectedDistrict"
                                                        onChange={(event) => {
                                                            this.handleChange('selectedDistrict', event.target.value);
                                                        }}
                                                    >
                                                        {
                                                            this.props.districts.map( type => <option key={type.value} value={type.value}>{type.label}</option>)
                                                        }
                                                    </select>

                                                    Other
                                                    <input
                                                        type="otherDistrict"
                                                        className="form-control"
                                                        id="otherDistrict"
                                                        placeholder="Other"
                                                    />

                                        </form>

                                2015-17 Copyright © mbu.com

        );
    }
};

const mapStateToProps = ({register}) => {
    return register;
};

export default connect(mapStateToProps)(Register);
<commit_msg>- fixing input types<commit_after>import React from 'react';
import {connect} from 'react-redux';
import {setField, getProfileTypes, getCouncils, getDistricts} from './registerActions';

class Register extends React.Component {

    constructor() {
        super();
        this.handleChange = this.handleChange.bind(this);
    }

    componentDidMount() {
        getProfileTypes();
        getCouncils();
        getDistricts();
    };

    handleChange(field, value) {
        setField(field, value);
    }

    render() {
        return (

Welcome to Merit Badge University 2018

Registration

                                        <form>

                                                    First Name *
                                                    <input
                                                        value={this.props.firstName}
                                                        type="text"
                                                        className="form-control"
                                                        id="firstName"
                                                        placeholder="First Name"
                                                        onChange={(event) => {
                                                            this.handleChange('firstName', event.target.value);
                                                        }}
                                                    />

                                                    Last Name *
                                                    <input
                                                        value={this.props.lastName}
                                                        type="text"
                                                        className="form-control"
                                                        id="lastName"
                                                        placeholder="Last Name"
                                                        onChange={(event) => {
                                                            this.handleChange('lastName', event.target.value);
                                                        }}
                                                    />

                                                    Email address *
                                                    <input
                                                        value={this.props.email}
                                                        type="text"
                                                        className="form-control"
                                                        id="email"
                                                        placeholder="Email"
                                                        onChange={(event) => {
                                                            this.handleChange('email', event.target.value);
                                                        }}
                                                    />

                                                    Confirm Email address *
                                                    <input
                                                        value={this.props.emailConfirm}
                                                        type="text"
                                                        className="form-control"
                                                        id="emailConfirm"
                                                        placeholder="Email"
                                                        onChange={(event) => {
                                                            this.handleChange('emailConfirm', event.target.value);
                                                        }}
                                                    />

                                                    Password *
                                                    <input
                                                        value={this.props.password}
                                                        type="password"
                                                        className="form-control"
                                                        id="password"
                                                        placeholder="Password"
                                                        onChange={(event) => {
                                                            this.handleChange('password', event.target.value);
                                                        }}
                                                    />

                                                    Confirm Password *
                                                    <input
                                                        value={this.props.passwordConfirm}
                                                        type="password"
                                                        className="form-control"
                                                        id="passwordConfirm"
                                                        placeholder="Confirm Password"
                                                        onChange={(event) => {
                                                            this.handleChange('passwordConfirm', event.target.value);
                                                        }}
                                                    />

                                                    Who are You? *
                                                    <select
                                                        value={this.props.selectedProfileType}
                                                        className="form-control form-control-lg"
                                                        id="selectedProfileType"
                                                        onChange={(event) => {
                                                            this.handleChange('selectedProfileType', event.target.value);
                                                        }}
                                                    >
                                                        {
                                                            this.props.profileTypes.map( type => <option key={type.value} value={type.value}>{type.label}</option>)
                                                        }
                                                    </select>

                                                    What Council Are You From? *
                                                    <select
                                                        value={this.props.selectedCouncil}
                                                        className="form-control form-control-lg"
                                                        id="selectedCouncil"
                                                        onChange={(event) => {
                                                            this.handleChange('selectedCouncil', event.target.value);
                                                        }}
                                                    >
                                                        {
                                                            this.props.councils.map( type => <option key={type.value} value={type.value}>{type.label}</option>)
                                                        }
                                                    </select>

                                                    Other
                                                    <input
                                                        type="text"
                                                        className="form-control"
                                                        id="otherCouncil"
                                                        placeholder="Other"
                                                    />

                                                    What District Are You From? *
                                                    <select
                                                        value={this.props.selectedDistrict}
                                                        className="form-control form-control-lg"
                                                        id="selectedDistrict"
                                                        onChange={(event) => {
                                                            this.handleChange('selectedDistrict', event.target.value);
                                                        }}
                                                    >
                                                        {
                                                            this.props.districts.map( type => <option key={type.value} value={type.value}>{type.label}</option>)
                                                        }
                                                    </select>

                                                    Other
                                                    <input
                                                        type="text"
                                                        className="form-control"
                                                        id="otherDistrict"
                                                        placeholder="Other"
                                                    />

                                        </form>

                                2015-17 Copyright © mbu.com

        );
    }
};

const mapStateToProps = ({register}) => {
    return register;
};

export default connect(mapStateToProps)(Register);
<|endoftext|>


<commit_before>(() => {
  "use strict";

  var EventEmitter = require('events').EventEmitter;

  var Adapter = class {

    get view() {
      return this._el;
    }

    set view(v) {
      if (v === this._el) return;
      if (v) {
        this.stop();
      }
      this._el = v;
    }

    get rows() {
      return this._rows;
    }

    set rows(v) {
      this._rows = v;
    }

    get position() {
      return this._pos;
    }

    set position(v) {
      this._pos = Math.min(this._length, v);
    }

    get length() {
      return this._length;
    }

    set length(v) {
      this._length = v;
      this._pos = Math.min(this._pos, v);
      this._event.emit("observe", "length", this._length);
      this._event.emit("observe", "position", this._pos);
    }

    get playing() {
      return this._playing;
    }

    on(listener) {
      this._event.on("observe", listener);
    }

    off(listener) {
      this._event.removeEventListener("observe", listener);
    }

    constructor() {
      this._el = null;
      this._comments = [];
      this._rows = 12;
      this._pos = 0;
      this._length = 0;
      this._playing = false;
      this._oldDate = 0;
      this._event = new EventEmitter();
      this._drawCb = (() => {
        if (!this._playing) return;
        var now = Date.now();
        this._pos = Math.min(this._length, this._pos + now - this._oldDate);
        this._event.emit("observe", "position", this._pos);
        this.draw();
        this._oldDate = now;
        if (this._pos >= this._length) {
          this.stop();
        } else {
          window.requestAnimationFrame(this._drawCb);
        }
      }).bind(this);

      // draw関連
      this._delay = 4000;
      this._map = new WeakMap();
      this._queue = [];
    }

    add(c) {
      var self = this;
      this._comments.push({
        text: c.text,
        vpos: c.vpos,
        color: c.color,
        size: c.size,
        position: c.position,
        get visible() {
          return this.vpos <= self._pos && self._pos <= this.vpos + self._delay;
        },
        get ratio() {
          return (self._pos - this.vpos) / self._delay;
        }
      });
    }

    start() {
      if (this._playing || this._pos >= this._length)
        return;
      this._playing = true;
      this._oldDate = Date.now();
      this._drawCb();
    }

    stop() {
      this._playing = false;
    }

    draw() {
      // コメントの位置決定ロジック

      const comments = this._comments,
            el = this._el,
            views = el.comments,
            width = el.width,
            map = this._map,
            queue = this._queue;

      const x = (c, v) => {
        v.x = (width + v.width) * (1 - c.ratio) - v.width;
      };

      const y = () => {
        return Math.random() * 300;
      };

      comments.some(c => {
        var v;

        // コメントデータに関連付けられているビューを探す

        if ((v = map.get(c))) {

          // 既にビューに関連付けられている

          if (c.visible) {

            // 引き続き表示されるのでnakaに限り動かすだけでOK

            if (!c.position) x(c, v);

          } else {

            // コメントが表示されなくなったので関連付けを解除

            map.delete(c);
            let i = queue.indexOf(v);
            if (i >= 0) queue.splice(i, 1);
            v.clear();

            console.log("cleared");

          }

        } else if (c.visible) {

          // 新しく表示されるコメント

          // 空いているビューを探す
          views.some(view => {
            return !view.tag && (v = view);
          });

          if (!v) {
            // 空いているビューが無ければ表示中の最古のコメントを消す
            v = queue.pop(v);
            v.clear();
          }
          map.set(c, v);
          queue.unshift(v);

          v.text = c.text;
          v.color = c.color;
          v.size = c.size;
          v.visible = true;
          // ビューが使用中であることを示すフラグ
          v.tag = true;

          v.y = y();
          x(c, v);
        }
      });
    }

    _getFontSize() {
      return 36;
    }

  };

  window.JikkyoViewer.Adapter = Adapter;
})();
<commit_msg>Improve comment view<commit_after>(() => {
  "use strict";

  var EventEmitter = require('events').EventEmitter;

  var Adapter = class {

    get view() {
      return this._el;
    }

    set view(v) {
      if (v === this._el) return;
      if (v) {
        this.stop();
      }
      this._el = v;
    }

    get rows() {
      return this._rows;
    }

    set rows(v) {
      this._rows = v;
    }

    get position() {
      return this._pos;
    }

    set position(v) {
      this._pos = Math.min(this._length, v);
    }

    get length() {
      return this._length;
    }

    set length(v) {
      this._length = v;
      this._pos = Math.min(this._pos, v);
      this._event.emit("observe", "length", this._length);
      this._event.emit("observe", "position", this._pos);
    }

    get playing() {
      return this._playing;
    }

    on(listener) {
      this._event.on("observe", listener);
    }

    off(listener) {
      this._event.removeEventListener("observe", listener);
    }

    constructor() {
      this._el = null;
      this._comments = [];
      this._rows = 12;
      this._pos = 0;
      this._length = 0;
      this._playing = false;
      this._oldDate = 0;
      this._event = new EventEmitter();
      this._drawCb = (() => {
        if (this._playing) {
          var now = Date.now();
          this._pos = Math.min(this._length, this._pos + now - this._oldDate);
          this._event.emit("observe", "position", this._pos);
          this.draw();
          this._oldDate = now;
          if (this._pos >= this._length) {
            this.stop();
          } else {
            window.requestAnimationFrame(this._drawCb);
          }
        } else {
          this.draw();
        }
      }).bind(this);

      window.addEventListener("resize", this._drawCb);

      // draw関連
      this._delay = 4000;
      this._map = new WeakMap();
      this._queue = [];
    }

    add(c) {
      var self = this;
      this._comments.push({
        text: c.text,
        vpos: c.vpos,
        color: c.color,
        size: c.size,
        position: c.position,
        get visible() {
          return this.vpos <= self._pos && self._pos <= this.vpos + self._delay;
        },
        get ratio() {
          return (self._pos - this.vpos) / self._delay;
        }
      });
    }

    start() {
      if (this._playing || this._pos >= this._length)
        return;
      this._playing = true;
      this._oldDate = Date.now();
      this._drawCb();
    }

    stop() {
      this._playing = false;
    }

    draw() {
      // コメントの位置決定ロジック

      const comments = this._comments,
            el = this._el,
            views = el.comments,
            width = el.width,
            map = this._map,
            queue = this._queue;

      const x = (c, v) => {
        return (width + v.width) * (1 - c.ratio) - v.width;
      };

      const y = () => {
        return 100; // WIP
      };

      comments.some(c => {
        var v = map.get(c);

        // コメントデータに関連付けられているビューを探す

        if (v && v.tag) {

          // 既にビューに関連付けられている

          if (c.visible) {

            // 引き続き表示されるので動かすだけでOK

            v.x = x(c, v);

          } else {

            // コメントが表示されなくなったので関連付けを解除

            map.delete(c);
            let i = queue.indexOf(v);
            if (i >= 0) queue.splice(i, 1);
            v.clear();

          }

        } else if (c.visible) {

          // 新しく表示されるコメント

          // 空いているビューを探す
          views.some(view => {
            return !view.tag && (v = view);
          });

          if (!v) {
            // 空いているビューが無ければ表示中の最古のコメントを消す
            v = queue.pop(v);
            if (v) {
              map.delete(v.tag);
              v.clear();
            }
          }

          map.set(c, v);
          queue.unshift(v);
          v.text = c.text;
          v.color = c.color;
          v.size = c.size;
          v.visible = true;
          v.tag = c;

          v.x = x(c, v);
          v.y = y();
        }
      });
    }

    _getFontSize() {
      return 36;
    }

  };

  window.JikkyoViewer.Adapter = Adapter;
})();
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types'
import SelectField from 'react-md/lib/SelectFields';
import Radio from 'react-md/lib/SelectionControls/Radio';
import Divider from 'react-md/lib/Dividers';
import axios from 'axios'
import { API_ROOT } from '../middleware/api';

class AddAttribute extends Component {
  constructor(props) {
    super(props);
    this.state = {
      relation: '',
      attribute: '',
      attributes: []
    };
    this.setRelation = this.setRelation.bind(this);
    this.setAttribute = this.setAttribute.bind(this);
    this._handleInlineChange = this._handleInlineChange.bind(this);
  }
  setRelation(newValue, newActiveIndex, event) {
    console.log(newValue, newActiveIndex, event);
    const relation = newValue;
    this.setState({ relation })
    // With the relation type chosen, we can query the backend
    console.log(relation)

    axios.get(API_ROOT + `get_attribute_values/type/` + relation)
      .then(res => {
        const attributes = res.data;
        this.setState({ attributes });
      });
  }
  setAttribute(newValue, newActiveIndex, event) {
    console.log(newValue, newActiveIndex, event);
    const attribute = newValue;
    this.setState({ attribute })
  }
  _handleInlineChange(e) {
   // Basically how the `SelectionControlGroup` works
   this.setState({ inlineValue: e.target.value });
 }
  render(){
    const { inlineValue } = this.state;
    return (

        <fieldset onChange={this._handleInlineChange}>
          <legend className="md-subheading-1">Select Attribute:</legend>
          <SelectField
            id="relations"
            label="Relations"
            placeholder="Select a Relation"
            position={SelectField.Positions.BELOW}
            menuItems={this.props.relations}
            className="md-cell"
            helpOnFocus
            helpText="Relations are descriptors about specific attributes."
            onChange={this.setRelation}
            required
          />
          <SelectField
            id="attributes"
            label="Attributes"
            placeholder="Select an Attribute"
            position={SelectField.Positions.BELOW}
            menuItems={this.state.attributes}
            className="md-cell"
            helpOnFocus
            helpText="An attribute is a specific instance of a relation type. For example, O157 is an attribute of relation O-Type."
            onChange={this.setAttribute}
            required
          />
        </fieldset>
        <fieldset onChange={this._handleInlineChange}>
          <legend className="md-subheading-1">Link Attributes:</legend>
          <Radio
            id="inlineRadio1"
            inline
            name="inlineRadios"
            value="A"
            label="AND"
            checked={inlineValue === 'A'}
          />
          <Radio
            id="inlineRadio2"
            inline
            name="inlineRadios"
            value="B"
            label="OR"
            checked={inlineValue === 'B'}
          />
        </fieldset>
        <Divider />

    )
  }
}

export default AddAttribute;
<commit_msg>ADD: switch for negation<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types'
import SelectField from 'react-md/lib/SelectFields';
import Radio from 'react-md/lib/SelectionControls/Radio';
import Switch from 'react-md/lib/SelectionControls/Switch';
import Divider from 'react-md/lib/Dividers';
import axios from 'axios'
import { API_ROOT } from '../middleware/api';

class AddAttribute extends Component {
  constructor(props) {
    super(props);
    this.state = {
      relation: '',
      attribute: '',
      attributes: [],
      negated: false
    };
    this.setRelation = this.setRelation.bind(this);
    this.setAttribute = this.setAttribute.bind(this);
    this._handleInlineChange = this._handleInlineChange.bind(this);
  }
  setRelation(newValue, newActiveIndex, event) {
    console.log(newValue, newActiveIndex, event);
    const relation = newValue;
    this.setState({ relation })
    // With the relation type chosen, we can query the backend
    console.log(relation)

    axios.get(API_ROOT + `get_attribute_values/type/` + relation)
      .then(res => {
        const attributes = res.data;
        this.setState({ attributes });
      });
  }
  setAttribute(newValue, newActiveIndex, event) {
    console.log(newValue, newActiveIndex, event);
    const attribute = newValue;
    this.setState({ attribute })
  }
  _handleInlineChange(e) {
   // Basically how the `SelectionControlGroup` works
   this.setState({ inlineValue: e.target.value });
 }
 _handleChangeNegated = (negated) => {
    this.setState({ negated });
  };
  render(){
    const { inlineValue, negated } = this.state;
    return (

        <fieldset>
          <fieldset>
            <legend className="md-subheading-1">Negation:</legend>
            <Switch id="switch3" name="controlledSwitch" label="Negate" checked={negated} onChange={this._handleChangeNegated} />
          </fieldset>
          <legend className="md-subheading-1">Define a relation:</legend>
          <fieldset>
            <legend className="md-subheading-1">Select Attribute:</legend>
            <SelectField
              id="relations"
              label="Relations"
              placeholder="Select a Relation"
              position={SelectField.Positions.BELOW}
              menuItems={this.props.relations}
              className="md-cell"
              helpOnFocus
              helpText="Relations are descriptors about specific attributes."
              onChange={this.setRelation}
              required
            />
            <SelectField
              id="attributes"
              label="Attributes"
              placeholder="Select an Attribute"
              position={SelectField.Positions.BELOW}
              menuItems={this.state.attributes}
              className="md-cell"
              helpOnFocus
              helpText="An attribute is a specific instance of a relation type. For example, O157 is an attribute of relation O-Type."
              onChange={this.setAttribute}
              required
            />
          </fieldset>
          <fieldset onChange={this._handleInlineChange}>
            <legend className="md-subheading-1">Linked By:</legend>
            <Radio
              id="inlineRadio1"
              inline
              name="inlineRadios"
              value="A"
              label="AND"
              checked={inlineValue === 'A'}
            />
            <Radio
              id="inlineRadio2"
              inline
              name="inlineRadios"
              value="B"
              label="OR"
              checked={inlineValue === 'B'}
            />
          </fieldset>
          <Divider />
        </fieldset>

    )
  }
}

export default AddAttribute;
<|endoftext|>


<commit_before>const {remote} = require('electron')
const {h, Component} = require('preact')
const helper = require('../modules/helper')
const setting = remote.require('./setting')

let winrateGraphHeight = setting.get('view.winrategraph_height')

class WinrateGraph extends Component {
    constructor() {
        super()

        this.handleMouseDown = evt => {
            this.mouseDown = true
            document.dispatchEvent(new MouseEvent('mousemove', evt))
        }
    }

    shouldComponentUpdate({width, currentIndex, data}) {
        return width !== this.props.width
            || currentIndex !== this.props.currentIndex
            || data[currentIndex] !== this.props.data[currentIndex]
    }

    componentDidMount() {
        document.addEventListener('mousemove', evt => {
            if (!this.mouseDown) return

            let rect = this.element.getBoundingClientRect()
            let percent = (evt.clientX - rect.left) / rect.width
            let {width, data, onCurrentIndexChange = helper.noop} = this.props
            let index = Math.max(Math.min(Math.round(width * percent), data.length - 1), 0)

            if (index !== this.props.currentIndex) onCurrentIndexChange({index})
        })

        document.addEventListener('mouseup', () => {
            this.mouseDown = false
        })
    }

    render({width, currentIndex, data}) {
        return h('section',
            {
                ref: el => this.element = el,
                id: 'winrategraph',
                style: {height: winrateGraphHeight},
                onMouseDown: this.handleMouseDown
            },

            h('svg',
                {
                    viewBox: `0 0 ${width} 100`,
                    preserveAspectRatio: 'none',
                    style: {height: '100%', width: '100%'}
                },

                // Draw background

                h('defs', {},
                    h('linearGradient', {id: 'bgGradient', x1: 0, y1: 0, x2: 0, y2: 1},
                        h('stop', {
                            offset: '0%',
                            'stop-color': 'white',
                            'stop-opacity': 0.7
                        }),
                        h('stop', {
                            offset: '100%',
                            'stop-color': 'white',
                            'stop-opacity': 0.1
                        })
                    ),

                    h('clipPath', {id: 'clipGradient'},
                        h('path', {
                            fill: 'black',
                            'stroke-width': 0,
                            d: (() => {
                                let instructions = data.map((x, i) => {
                                    if (x == null) return i === 0 ? [i, 50] : null
                                    return [i, x]
                                }).filter(x => x != null)

                                if (instructions.length === 0) return ''

                                return `M ${instructions[0][0]},100 `
                                    + instructions.map(x => `L ${x.join(',')}`).join(' ')
                                    + ` L ${instructions.slice(-1)[0][0]},100 Z`
                            })()
                        })
                    )
                ),

                h('rect', {
                    x: 0,
                    y: 0,
                    width,
                    height: 100,
                    fill: 'url(#bgGradient)',
                    'clip-path': 'url(#clipGradient)'
                }),

                // Draw guiding lines

                h('line', {
                    x1: 0,
                    y1: 50,
                    x2: width,
                    y2: 50,
                    stroke: '#aaa',
                    'stroke-width': 1,
                    'stroke-dasharray': 2,
                    'vector-effect': 'non-scaling-stroke'
                }),

                [...Array(width)].map((_, i) => {
                    if (i === 0 || i % 50 !== 0) return

                    return h('line', {
                        x1: i,
                        y1: 0,
                        x2: i,
                        y2: 100,
                        stroke: '#aaa',
                        'stroke-width': 1,
                        'stroke-dasharray': 2,
                        'vector-effect': 'non-scaling-stroke'
                    })
                }),

                // Current position marker

                h('line', {
                    x1: currentIndex,
                    y1: 0,
                    x2: currentIndex,
                    y2: 100,
                    stroke: '#0082F0',
                    'stroke-width': 2,
                    'vector-effect': 'non-scaling-stroke'
                }),

                // Draw data lines

                h('path', {
                    stroke: '#eee',
                    fill: 'none',
                    'stroke-width': 2,
                    'vector-effect': 'non-scaling-stroke',

                    d: data.map((x, i) => {
                        if (x == null) return ''

                        let command = i === 0 || data[i - 1] == null ? 'M' : 'L'
                        return `${command} ${i},${x}`
                    }).join(' ')
                }),

                h('path', {
                    stroke: '#ccc',
                    fill: 'none',
                    'stroke-width': 2,
                    'stroke-dasharray': 2,
                    'vector-effect': 'non-scaling-stroke',

                    d: data.map((x, i) => {
                        if (i === 0) return 'M 0,50'

                        if (x == null && data[i - 1] != null)
                            return `M ${i - 1},${data[i - 1]}`

                        if (x != null && data[i - 1] == null)
                            return `L ${i},${x}`

                        return ''
                    }).join(' ')
                })
            ),

            // Draw marker

            data[currentIndex] && h('div', {
                class: 'marker',
                style: {
                    left: `${currentIndex * 100 / width}%`,
                    top: `${data[currentIndex]}%`
                },
                title: `White winrate: ${Math.round((100 - data[currentIndex]) * 100) / 100}%`
            })
        )
    }
}

module.exports = WinrateGraph
<commit_msg>Add diff graph to winrate graph<commit_after>const {remote} = require('electron')
const {h, Component} = require('preact')
const helper = require('../modules/helper')
const setting = remote.require('./setting')

let winrateGraphHeight = setting.get('view.winrategraph_height')

class WinrateGraph extends Component {
    constructor() {
        super()

        this.handleMouseDown = evt => {
            this.mouseDown = true
            document.dispatchEvent(new MouseEvent('mousemove', evt))
        }
    }

    shouldComponentUpdate({width, currentIndex, data}) {
        return width !== this.props.width
            || currentIndex !== this.props.currentIndex
            || data[currentIndex] !== this.props.data[currentIndex]
    }

    componentDidMount() {
        document.addEventListener('mousemove', evt => {
            if (!this.mouseDown) return

            let rect = this.element.getBoundingClientRect()
            let percent = (evt.clientX - rect.left) / rect.width
            let {width, data, onCurrentIndexChange = helper.noop} = this.props
            let index = Math.max(Math.min(Math.round(width * percent), data.length - 1), 0)

            if (index !== this.props.currentIndex) onCurrentIndexChange({index})
        })

        document.addEventListener('mouseup', () => {
            this.mouseDown = false
        })
    }

    render({width, currentIndex, data}) {
        let dataDiff = data.map((x, i) => i === 0 || x == null || data[i - 1] == null ? null : x - data[i - 1])
        let dataDiffMax = Math.max(...dataDiff.map(Math.abs), 25)

        return h('section',
            {
                ref: el => this.element = el,
                id: 'winrategraph',
                style: {height: winrateGraphHeight},
                onMouseDown: this.handleMouseDown
            },

            h('svg',
                {
                    viewBox: `0 0 ${width} 100`,
                    preserveAspectRatio: 'none',
                    style: {height: '100%', width: '100%'}
                },

                // Draw background

                h('defs', {},
                    h('linearGradient', {id: 'bgGradient', x1: 0, y1: 0, x2: 0, y2: 1},
                        h('stop', {
                            offset: '0%',
                            'stop-color': 'white',
                            'stop-opacity': 0.7
                        }),
                        h('stop', {
                            offset: '100%',
                            'stop-color': 'white',
                            'stop-opacity': 0.1
                        })
                    ),

                    h('clipPath', {id: 'clipGradient'},
                        h('path', {
                            fill: 'black',
                            'stroke-width': 0,
                            d: (() => {
                                let instructions = data.map((x, i) => {
                                    if (x == null) return i === 0 ? [i, 50] : null
                                    return [i, x]
                                }).filter(x => x != null)

                                if (instructions.length === 0) return ''

                                return `M ${instructions[0][0]},100 `
                                    + instructions.map(x => `L ${x.join(',')}`).join(' ')
                                    + ` L ${instructions.slice(-1)[0][0]},100 Z`
                            })()
                        })
                    )
                ),

                h('rect', {
                    x: 0,
                    y: 0,
                    width,
                    height: 100,
                    fill: 'url(#bgGradient)',
                    'clip-path': 'url(#clipGradient)'
                }),

                // Draw guiding lines

                h('line', {
                    x1: 0,
                    y1: 50,
                    x2: width,
                    y2: 50,
                    stroke: '#aaa',
                    'stroke-width': 1,
                    'stroke-dasharray': 2,
                    'vector-effect': 'non-scaling-stroke'
                }),

                [...Array(width)].map((_, i) => {
                    if (i === 0 || i % 50 !== 0) return

                    return h('line', {
                        x1: i,
                        y1: 0,
                        x2: i,
                        y2: 100,
                        stroke: '#aaa',
                        'stroke-width': 1,
                        'stroke-dasharray': 2,
                        'vector-effect': 'non-scaling-stroke'
                    })
                }),

                // Current position marker

                h('line', {
                    x1: currentIndex,
                    y1: 0,
                    x2: currentIndex,
                    y2: 100,
                    stroke: '#0082F0',
                    'stroke-width': 2,
                    'vector-effect': 'non-scaling-stroke'
                }),

                // Draw differential bar graph

                h('path', {
                    fill: 'none',
                    stroke: '#F76047',
                    'stroke-width': 1,

                    d: dataDiff.map((x, i) => {
                        if (x == null || Math.abs(x) <= 3) return ''

                        return `M ${i},50 l 0,${x * 50 / dataDiffMax}`
                    }).join(' ')
                }),

                // Draw data lines

                h('path', {
                    fill: 'none',
                    stroke: '#eee',
                    'stroke-width': 2,
                    'vector-effect': 'non-scaling-stroke',

                    d: data.map((x, i) => {
                        if (x == null) return ''

                        let command = i === 0 || data[i - 1] == null ? 'M' : 'L'
                        return `${command} ${i},${x}`
                    }).join(' ')
                }),

                h('path', {
                    fill: 'none',
                    stroke: '#ccc',
                    'stroke-width': 2,
                    'stroke-dasharray': 2,
                    'vector-effect': 'non-scaling-stroke',

                    d: data.map((x, i) => {
                        if (i === 0) return 'M 0,50'

                        if (x == null && data[i - 1] != null)
                            return `M ${i - 1},${data[i - 1]}`

                        if (x != null && data[i - 1] == null)
                            return `L ${i},${x}`

                        return ''
                    }).join(' ')
                })
            ),

            // Draw marker

            data[currentIndex] && h('div', {
                class: 'marker',
                style: {
                    left: `${currentIndex * 100 / width}%`,
                    top: `${data[currentIndex]}%`
                },
                title: `White winrate: ${
                    Math.round((100 - data[currentIndex]) * 100) / 100
                }%${
                    data[currentIndex - 1] == null ? '' : ` (${
                        dataDiff[currentIndex] >= 0 ? '' : '+'
                    }${
                        -Math.round(dataDiff[currentIndex] * 100) / 100
                    })`
                }`
            })
        )
    }
}

module.exports = WinrateGraph
<|endoftext|>


<commit_before>import omit from 'lodash.omit';
import pick from 'lodash.pick';

const boxProps = [
  'alignContent',
  'alignItems',
  'alignSelf',
  'borderWidth',
  'borderBottomWidth',
  'borderColor',
  'borderLeftWidth',
  'borderRightWidth',
  'borderTint',
  'borderTopWidth',
  'boxSizing',
  'children',
  'className',
  'display',
  'element',
  'flex',
  'flexBasis',
  'flexDirection',
  'flexGrow',
  'flexShrink',
  'flexWrap',
  'justifyContent',
  'margin',
  'marginHorizontal',
  'marginVertical',
  'marginBottom',
  'marginLeft',
  'marginRight',
  'marginTop',
  'order',
  'overflow',
  'overflowX',
  'overflowY',
  'padding',
  'paddingHorizontal',
  'paddingVertical',
  'paddingBottom',
  'paddingLeft',
  'paddingRight',
  'paddingTop',
  'textAlign',
];

const omitBoxProps = props => omit(props, boxProps);
const pickBoxProps = props => pick(props, boxProps);

export default boxProps;
export { omitBoxProps, pickBoxProps };
<commit_msg>Remove children from the boxProps list<commit_after>import omit from 'lodash.omit';
import pick from 'lodash.pick';

const boxProps = [
  'alignContent',
  'alignItems',
  'alignSelf',
  'borderWidth',
  'borderBottomWidth',
  'borderColor',
  'borderLeftWidth',
  'borderRightWidth',
  'borderTint',
  'borderTopWidth',
  'boxSizing',
  'className',
  'display',
  'element',
  'flex',
  'flexBasis',
  'flexDirection',
  'flexGrow',
  'flexShrink',
  'flexWrap',
  'justifyContent',
  'margin',
  'marginHorizontal',
  'marginVertical',
  'marginBottom',
  'marginLeft',
  'marginRight',
  'marginTop',
  'order',
  'overflow',
  'overflowX',
  'overflowY',
  'padding',
  'paddingHorizontal',
  'paddingVertical',
  'paddingBottom',
  'paddingLeft',
  'paddingRight',
  'paddingTop',
  'textAlign',
];

const omitBoxProps = props => omit(props, boxProps);
const pickBoxProps = props => pick(props, boxProps);

export default boxProps;
export { omitBoxProps, pickBoxProps };
<|endoftext|>


<commit_before>import React from 'react';
import VideoList from './video_list';

const VideoDetail = ({video, videoId}) => {
  if (!video) {
    return
Loading...

  }

  videoId = video.id.videoId;
  console.log(videoId);
  const url = "https://www.youtube.com/embed/" + videoId + "?vq=hd1080?rel=0;&autoplay=1&loop=1&playlist=" + videoId;
  const externalUrl = "https://www.youtube.com/watch?v=" + videoId;
  // console.log(url);
  return (

          {video.snippet.title}

          {video.snippet.channelTitle}

{video.snippet.description}

  );
};

export default VideoDetail;
<commit_msg>Edited video detail<commit_after>import React from 'react';
import VideoList from './video_list';

const VideoDetail = ({video, videoId}) => {
  if (!video) {
    return
Loading...

  }

  videoId = video.id.videoId;
  console.log(videoId);
  const url = "https://www.youtube.com/embed/" + videoId + "?vq=hd1080?rel=0;&autoplay=1&loop=1&playlist=" + videoId;
  const externalUrl = "https://www.youtube.com/watch?v=" + videoId;
  // console.log(url);
  return (

          {video.snippet.title}

          {video.snippet.channelTitle}

{video.snippet.description}

  );
};

export default VideoDetail;
<|endoftext|>


<commit_before>
/*
The MIT License (MIT)

Copyright (c) 2014 Rob Christian

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/*

Semi-colons are just FUD. If your minifier can't handle this code, switch to one that is JS-compliant.

*/

;(function(){

  /*  Private Class Data  */

  var DEFINE = Object.defineProperty
  var OVERRIDE = function(object, method_name, method){
    DEFINE(object, method_name, { enumerable:false, configurable:false, value:method })
  }
  var _property_manipulator_
  var PROPERTY_MANIPULATOR = function(obj){
    if (! obj) return _property_manipulator_
    else _property_manipulator_ = obj
    return PROPERTY_MANIPULATOR
  }

  var _bindables = []
  var _events = new MicroEvent()

  /*  Bindable Classes  */

  function Bindable(data){
    if (typeOf(data) === 'Array')
      return new BindableArray(data)
    else if (familyOf(data) === 'complex')
      return new BindableObject(data)
  }

  function bind(){ //console.log('BIND', arguments)
    var setter_cb, property, parent, opts

    opts = Array.prototype.slice.call(arguments)

    if (opts.length === 3) {
      parent = opts[0]
      property = opts[1]
      setter_cb = opts[2]

      parent[property] = PROPERTY_MANIPULATOR({
        fetch:function(id){ _events.bind(id,setter_cb) }
      })
    }

    else if (typeOf(opts[0] === 'Array')) {
      setter_cb = opts[1]
      // opts[0]._array_events_ = PROPERTY_MANIPULATOR({
      //   fetch:function(id){ _events.bind(id,setter_cb) }
      // })
      _events.bind(opts[0]._id,setter_cb)
    }

  }

  function unbind(setter_cb){
    _events.unbind(setter_cb)
  }

  function recompute(data){
    if (familyOf(data) === 'complex')
      this.constructor.apply(this,data)
    return this
  }

  function BindableObject(data){ console.log(data)
    Object.keys(data).map(function(prop){
      this._new_property_ = [prop, data[prop]]
    }.bind(this))
  }
  DEFINE(BindableObject.prototype, 'bind', { enumerable:false, configurable:false, value:bind })
  DEFINE(BindableObject.prototype, 'unbind', { enumerable:false, configurable:false, value:unbind })
  DEFINE(BindableObject.prototype, 'recompute', { enumerable:false, configurable:false, value:recompute })
  DEFINE(BindableObject.prototype, 'onChange', { enumerable:false, configurable:false,
    value:function(props, cb){
      if (typeOf(props) !== 'Array') return
      props.forEach(function(prop){ bind(this,prop,cb) }.bind(this))
    }
  })
  DEFINE(BindableObject.prototype, '_new_property_', { enumerable:false, configurable:false,
    set:function(){ addProperty.apply(this, arguments) }
  })

  function BindableArray(array){
    var self = []

    DEFINE(self, '_id', { enumerable:false, configurable:false, value:+Math.random().toString().split('.')[1] })
    DEFINE(self, '_timeout', { enumerable:false, configurable:false, value:60 })
    DEFINE(self, 'bind', { enumerable:false, configurable:false, value:bind })
    DEFINE(self, 'unbind', { enumerable:false, configurable:false, value:unbind })
    DEFINE(self, 'recompute', { enumerable:false, configurable:false, value:recompute })
    DEFINE(self, '_new_property_', { enumerable:false, configurable:false,
      set:function(){ addProperty.apply(self, arguments) }
    })
    DEFINE(self, '_array_events_', { enumerable:false, configurable:false,
      set:function(manipulator){
        if (manipulator === PROPERTY_MANIPULATOR && PROPERTY_MANIPULATOR().fetch)
          PROPERTY_MANIPULATOR().fetch(self._id)
      }
    })
    OVERRIDE(self, 'push', function(obj){

      self._new_property_ = [self.length, obj]
      debounce(self._timeout, 'push'+self._id, function(){
        _events.trigger(self._id, [self.length-1, self[self.length-1]], 'push')
        console.log( 'emit: push'+self._id )
      })

    })
    OVERRIDE(self, 'pop', function(){

      var r = self[self.length-1]
      self.length = self.length-1
      debounce(self._timeout, 'pop'+self._id, function(){
        _events.trigger(self._id, r, 'pop')
        console.log( 'emit: pop'+self._id )
      })
      return r

    })
    OVERRIDE(self, 'shift', function(){

      var r = self[0]
      Object.keys(self).map(function(idx){
        self[+idx] = self[+idx+1]
        self[+idx] = PROPERTY_MANIPULATOR({
          fetch:function(id){ self[+idx] = PROPERTY_MANIPULATOR({id:id}) }
        })
      })
      self.length = self.length-1
      debounce(self._timeout, 'shift'+self._id, function(){
        _events.trigger(self._id, r, 'shift')
        console.log( 'emit: shift'+self._id )
      })
      return r

    })
    OVERRIDE(self, 'unshift', function(obj){

      Object.keys(self).reverse().map(function(idx){
        console.log(+idx+1, +idx)
        self._new_property_ = [+idx+1, self[+idx]]
        self[+idx] = PROPERTY_MANIPULATOR({
          fetch:function(id){ self[+idx+1] = PROPERTY_MANIPULATOR({id:id}) }
        })
      })
      self._new_property_ = [0, obj]
      debounce(self._timeout, 'unshift'+self._id, function(){
        _events.trigger(self._id, self, 'unshift')
        console.log( 'emit: unshift'+self._id )
      })
      return self.length

    })
    OVERRIDE(self, 'splice', function(){

      debounce(self._timeout, 'splice'+self._id, function(){
        _events.trigger(self._id, self, 'splice')
        console.log( 'emit: splice'+self._id )
      })
      Array.prototype.splice.apply(self, arguments)

    })
    OVERRIDE(self, 'slice', function(){

      Array.prototype.slice.apply(self, arguments)
      debounce(self._timeout, 'slice'+self._id, function(){
        _events.trigger(self._id, self, 'slice')
        console.log( 'emit: slice'+self._id )
      })

    })
    OVERRIDE(self, 'reverse', function(idx1, idx2){ // This works, but it's not optimized yet.

      for (var l=0; l < Math.floor(self.length/2); l++) {
        // Method 1 is this.
        var r = self.length-1 - l
        self[r] = PROPERTY_MANIPULATOR({ fetch:function(r_id){
          self[l] = PROPERTY_MANIPULATOR({ fetch:function(l_id){
            self[r] = PROPERTY_MANIPULATOR({id:l_id})
            self[l] = PROPERTY_MANIPULATOR({id:r_id})
          }})
        }})
        // Method 2 would be something like this.
        // Array.prototype.push.call(self, self[ length ])
        // Array.prototype.splice.call(self, length, 1)
      }
      Array.prototype.reverse.call(self)
      debounce(self._timeout, 'reverse'+self._id, function(){
        _events.trigger(self._id, self, 'reverse')
        console.log( 'emit: reverse'+self._id )
      })
      return self

    })
    OVERRIDE(self, 'concat', function(arr){

      // This method is not implemented according to the standard, as it modifies the object it's being called upon.
      // In the future we'll aim to fix this, making it conform to the standard.

      if (typeOf(arr) === 'Array' && arr.length) {
        Object.keys(arr).map(function(key){
          self._new_property_ = [self.length, arr[key]]
        })
      }
      debounce(self._timeout, 'concat'+self._id, function(){
        _events.trigger(self._id, self, 'concat')
        console.log( 'emit: concat'+self._id )
      })
      return self

    })
    Object.keys(array).map(function(idx){
      self._new_property_ = [+idx, array[+idx]]
    })
    return self

  }

  function addProperty(args){
    var _val, _id, key, val
    _id = +Math.random().toString().split('.')[1]

    if (typeOf(args) === 'Array') {
      key = args[0]
      val = args[1]
    } else {
      console.log('Abort! Bad property assignment:',args)
      return
    }
    // console.log('addProperty', key, val)

    DEFINE(this, key, {
      enumerable: true
    , configurable: true
    , get: function(){ return _val }
    , set: function(value){
        if (value === PROPERTY_MANIPULATOR && PROPERTY_MANIPULATOR().fetch) {
          PROPERTY_MANIPULATOR().fetch(_id)
        }
        // else if (value === PROPERTY_MANIPULATOR && PROPERTY_MANIPULATOR().updated) {
        //   // if (typeOf(_val) === 'complex') _val = PROPERTY_MANIPULATOR({updated:true})
        //   // else _events.trigger(_id, _val)
        // }
        else if (value === PROPERTY_MANIPULATOR && PROPERTY_MANIPULATOR().id) {
          _id = PROPERTY_MANIPULATOR().id
        }
        else if (familyOf(value) === 'complex') {
          _val = new Bindable(value)
          _events.trigger(_id, _val)
        }
        else {
          _val = value
          _events.trigger(_id, _val)
        }
      }
    })
    this[key] = val
  }

  /* Takes a form DOM object and a Binding object, and does the rest for you. */

  function bindForm(form, bindable){

    ;[].forEach.call(form.querySelectorAll('input'), function(field){

      if (field.name in bindable) {
        fieldManager(function(input_handler, output_handler){

          field.addEventListener('input', function(ev){
            var do_it = function(){ bindable[field.name] = ev.target.value }
            input_handler( do_it )
          })

          bindable.bind(bindable, field.name, function(val){
            var do_it = function(){ field.value = val }
            output_handler( do_it )
          })

        })

        field.value = bindable[field.name]
      }

    })
  }

  /* Inverts control: Prevents inputs from receiving updates while they are the sender. */

  function fieldManager(receive_handlers){
    var _sent_by_me = false

    function input_handler(do_it){
      _sent_by_me = true
      do_it()
    }
    function output_handler(do_it){
      _sent_by_me ? _sent_by_me = false : do_it()
    }
    receive_handlers( input_handler, output_handler )
  }

  /* Our entry point for creating bindable objects, keeps a reference to the object created. */

  function NewBindable(data){
    var bindable = new Bindable(data)
    _bindables.push(bindable)
    return bindable
  }

  /*  HELPERS  */

  function familyOf(thing){
    var type = typeOf(thing)
    if (type) {
      return ({
        Date: 'simple'
      , String: 'simple'
      , Number: 'simple'
      , Boolean: 'simple'
      , Function: 'simple'
      , RegExp: 'simple'
      , Array: 'complex'
      , Object: 'complex'
      , HTMLElement: 'complex'
      , 'undefined': 'falsey'
      , 'null': 'falsey'
      })[type] || 'complex'
      // })[type] || (/^HTML\w*Element$/g.test(type) ? 'HTMLElement' : 'complex')
    } else {
      return false
    }
  }

  function typeOf(thing){
    if (typeof thing === 'number') return isNaN(thing) ? 'NaN' : 'Number'
    else if (thing instanceof HTMLElement) return 'HTMLElement'
    else return (thing !== null && thing !== undefined && thing.constructor) ? thing.constructor.name : '' + thing
  }

  var debounce
  ;(function(){
    var bounced = {}
    debounce = function(t, id, cb){
      clearTimeout( bounced[id] )
      bounced[id] = setTimeout(cb, t)
    }
  })()

  NewBindable.fieldManager = fieldManager
  NewBindable.bindForm = bindForm
  NewBindable.unbind = unbind
  NewBindable.bind = bind

  DEFINE(NewBindable, 'bindables', {get:function(){return _bindables}, enumerable:true})
  DEFINE(NewBindable, 'PROPERTY_MANIPULATOR', {value:PROPERTY_MANIPULATOR, writeable:false})

  if (typeof module !== 'undefined' && module.hasOwnProperty('exports')) {
    module.exports = NewBindable
  } else {
    window.Connected  = NewBindable
    window.Bindable   = Bindable
    window.familyOf   = familyOf
    window.typeOf     = typeOf
  }

})()
<commit_msg>Add support for IE 10 (at least 10).<commit_after>
/*
The MIT License (MIT)

Copyright (c) 2014 Rob Christian

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/*

Semi-colons are just FUD. If your minifier can't handle this code, switch to one that is JS-compliant.

*/

;(function(){

  /*  Private Class Data  */

  var DEFINE = Object.defineProperty
  var OVERRIDE = function(object, method_name, method){
    DEFINE(object, method_name, { enumerable:false, configurable:false, value:method })
  }
  var _property_manipulator_
  var PROPERTY_MANIPULATOR = function(obj){
    if (! obj) return _property_manipulator_
    else _property_manipulator_ = obj
    return PROPERTY_MANIPULATOR
  }

  var _bindables = []
  var _events = new MicroEvent()

  /*  Bindable Classes  */

  function Bindable(data){
    if (typeOf(data) === 'Array')
      return new BindableArray(data)
    else if (familyOf(data) === 'complex')
      return new BindableObject(data)
  }

  function bind(){ //console.log('BIND', arguments)
    var setter_cb, property, parent, opts

    opts = Array.prototype.slice.call(arguments)

    if (opts.length === 3) {
      parent = opts[0]
      property = opts[1]
      setter_cb = opts[2]

      parent[property] = PROPERTY_MANIPULATOR({
        fetch:function(id){ _events.bind(id,setter_cb) }
      })
    }

    else if (typeOf(opts[0] === 'Array')) {
      setter_cb = opts[1]
      // opts[0]._array_events_ = PROPERTY_MANIPULATOR({
      //   fetch:function(id){ _events.bind(id,setter_cb) }
      // })
      _events.bind(opts[0]._id,setter_cb)
    }

  }

  function unbind(setter_cb){
    _events.unbind(setter_cb)
  }

  function recompute(data){
    if (familyOf(data) === 'complex')
      this.constructor.apply(this,data)
    return this
  }

  function BindableObject(data){ console.log(data)
    Object.keys(data).map(function(prop){
      this._new_property_ = [prop, data[prop]]
    }.bind(this))
  }
  DEFINE(BindableObject.prototype, 'bind', { enumerable:false, configurable:false, value:bind })
  DEFINE(BindableObject.prototype, 'unbind', { enumerable:false, configurable:false, value:unbind })
  DEFINE(BindableObject.prototype, 'recompute', { enumerable:false, configurable:false, value:recompute })
  DEFINE(BindableObject.prototype, 'onChange', { enumerable:false, configurable:false,
    value:function(props, cb){
      if (typeOf(props) !== 'Array') return
      props.forEach(function(prop){ bind(this,prop,cb) }.bind(this))
    }
  })
  DEFINE(BindableObject.prototype, '_new_property_', { enumerable:false, configurable:false,
    set:function(){ addProperty.apply(this, arguments) }
  })

  function BindableArray(array){
    var self = []

    DEFINE(self, '_id', { enumerable:false, configurable:false, value:+Math.random().toString().split('.')[1] })
    DEFINE(self, '_timeout', { enumerable:false, configurable:false, value:60 })
    DEFINE(self, 'bind', { enumerable:false, configurable:false, value:bind })
    DEFINE(self, 'unbind', { enumerable:false, configurable:false, value:unbind })
    DEFINE(self, 'recompute', { enumerable:false, configurable:false, value:recompute })
    DEFINE(self, '_new_property_', { enumerable:false, configurable:false,
      set:function(){ addProperty.apply(self, arguments) }
    })
    DEFINE(self, '_array_events_', { enumerable:false, configurable:false,
      set:function(manipulator){
        if (manipulator === PROPERTY_MANIPULATOR && PROPERTY_MANIPULATOR().fetch)
          PROPERTY_MANIPULATOR().fetch(self._id)
      }
    })
    OVERRIDE(self, 'push', function(obj){

      self._new_property_ = [self.length, obj]
      debounce(self._timeout, 'push'+self._id, function(){
        _events.trigger(self._id, [self.length-1, self[self.length-1]], 'push')
        console.log( 'emit: push'+self._id )
      })

    })
    OVERRIDE(self, 'pop', function(){

      var r = self[self.length-1]
      self.length = self.length-1
      debounce(self._timeout, 'pop'+self._id, function(){
        _events.trigger(self._id, r, 'pop')
        console.log( 'emit: pop'+self._id )
      })
      return r

    })
    OVERRIDE(self, 'shift', function(){

      var r = self[0]
      Object.keys(self).map(function(idx){
        self[+idx] = self[+idx+1]
        self[+idx] = PROPERTY_MANIPULATOR({
          fetch:function(id){ self[+idx] = PROPERTY_MANIPULATOR({id:id}) }
        })
      })
      self.length = self.length-1
      debounce(self._timeout, 'shift'+self._id, function(){
        _events.trigger(self._id, r, 'shift')
        console.log( 'emit: shift'+self._id )
      })
      return r

    })
    OVERRIDE(self, 'unshift', function(obj){

      Object.keys(self).reverse().map(function(idx){
        console.log(+idx+1, +idx)
        self._new_property_ = [+idx+1, self[+idx]]
        self[+idx] = PROPERTY_MANIPULATOR({
          fetch:function(id){ self[+idx+1] = PROPERTY_MANIPULATOR({id:id}) }
        })
      })
      self._new_property_ = [0, obj]
      debounce(self._timeout, 'unshift'+self._id, function(){
        _events.trigger(self._id, self, 'unshift')
        console.log( 'emit: unshift'+self._id )
      })
      return self.length

    })
    OVERRIDE(self, 'splice', function(){

      debounce(self._timeout, 'splice'+self._id, function(){
        _events.trigger(self._id, self, 'splice')
        console.log( 'emit: splice'+self._id )
      })
      Array.prototype.splice.apply(self, arguments)

    })
    OVERRIDE(self, 'slice', function(){

      Array.prototype.slice.apply(self, arguments)
      debounce(self._timeout, 'slice'+self._id, function(){
        _events.trigger(self._id, self, 'slice')
        console.log( 'emit: slice'+self._id )
      })

    })
    OVERRIDE(self, 'reverse', function(idx1, idx2){ // This works, but it's not optimized yet.

      for (var l=0; l < Math.floor(self.length/2); l++) {
        // Method 1 is this.
        var r = self.length-1 - l
        self[r] = PROPERTY_MANIPULATOR({ fetch:function(r_id){
          self[l] = PROPERTY_MANIPULATOR({ fetch:function(l_id){
            self[r] = PROPERTY_MANIPULATOR({id:l_id})
            self[l] = PROPERTY_MANIPULATOR({id:r_id})
          }})
        }})
        // Method 2 would be something like this.
        // Array.prototype.push.call(self, self[ length ])
        // Array.prototype.splice.call(self, length, 1)
      }
      Array.prototype.reverse.call(self)
      debounce(self._timeout, 'reverse'+self._id, function(){
        _events.trigger(self._id, self, 'reverse')
        console.log( 'emit: reverse'+self._id )
      })
      return self

    })
    OVERRIDE(self, 'concat', function(arr){

      // This method is not implemented according to the standard, as it modifies the object it's being called upon.
      // In the future we'll aim to fix this, making it conform to the standard.

      if (typeOf(arr) === 'Array' && arr.length) {
        Object.keys(arr).map(function(key){
          self._new_property_ = [self.length, arr[key]]
        })
      }
      debounce(self._timeout, 'concat'+self._id, function(){
        _events.trigger(self._id, self, 'concat')
        console.log( 'emit: concat'+self._id )
      })
      return self

    })
    Object.keys(array).map(function(idx){
      self._new_property_ = [+idx, array[+idx]]
    })
    return self

  }

  function addProperty(args){
    var _val, _id, key, val
    _id = +Math.random().toString().split('.')[1]

    if (typeOf(args) === 'Array') {
      key = args[0]
      val = args[1]
    } else {
      console.log('Abort! Bad property assignment:',args)
      return
    }
    // console.log('addProperty', key, val)

    DEFINE(this, key, {
      enumerable: true
    , configurable: true
    , get: function(){ return _val }
    , set: function(value){
        if (value === PROPERTY_MANIPULATOR && PROPERTY_MANIPULATOR().fetch) {
          PROPERTY_MANIPULATOR().fetch(_id)
        }
        // else if (value === PROPERTY_MANIPULATOR && PROPERTY_MANIPULATOR().updated) {
        //   // if (typeOf(_val) === 'complex') _val = PROPERTY_MANIPULATOR({updated:true})
        //   // else _events.trigger(_id, _val)
        // }
        else if (value === PROPERTY_MANIPULATOR && PROPERTY_MANIPULATOR().id) {
          _id = PROPERTY_MANIPULATOR().id
        }
        else if (familyOf(value) === 'complex') {
          _val = new Bindable(value)
          _events.trigger(_id, _val)
        }
        else {
          _val = value
          _events.trigger(_id, _val)
        }
      }
    })
    this[key] = val
  }

  /* Takes a form DOM object and a Binding object, and does the rest for you. */

  function bindForm(form, bindable){

    ;[].forEach.call(form.querySelectorAll('input'), function(field){

      if (field.name in bindable) {
        fieldManager(function(input_handler, output_handler){

          field.addEventListener('input', function(ev){
            var do_it = function(){ bindable[field.name] = ev.target.value }
            input_handler( do_it )
          })

          bindable.bind(bindable, field.name, function(val){
            var do_it = function(){ field.value = val }
            output_handler( do_it )
          })

        })

        field.value = bindable[field.name]
      }

    })
  }

  /* Inverts control: Prevents inputs from receiving updates while they are the sender. */

  function fieldManager(receive_handlers){
    var _sent_by_me = false

    function input_handler(do_it){
      _sent_by_me = true
      do_it()
    }
    function output_handler(do_it){
      _sent_by_me ? _sent_by_me = false : do_it()
    }
    receive_handlers( input_handler, output_handler )
  }

  /* Our entry point for creating bindable objects, keeps a reference to the object created. */

  function NewBindable(data){
    var bindable = new Bindable(data)
    _bindables.push(bindable)
    return bindable
  }

  /*  HELPERS  */

  function familyOf(thing){
    var type = typeOf(thing)
    if (type) {
      return ({
        Date: 'simple'
      , String: 'simple'
      , Number: 'simple'
      , Boolean: 'simple'
      , Function: 'simple'
      , RegExp: 'simple'
      , Array: 'complex'
      , Object: 'complex'
      , HTMLElement: 'complex'
      , 'undefined': 'falsey'
      , 'null': 'falsey'
      })[type] || 'complex'
      // })[type] || (/^HTML\w*Element$/g.test(type) ? 'HTMLElement' : 'complex')
    } else {
      return false
    }
  }

  function typeOf(thing){
    if (typeof thing === 'number') return isNaN(thing) ? 'NaN' : 'Number'
    else if (thing instanceof HTMLElement) return 'HTMLElement'
    else return (thing !== null && thing !== undefined && thing.constructor) ? getObjectClass(thing) : '' + thing
  }

  function getObjectClass(obj) {
    if (obj && obj.constructor && obj.constructor.toString) {
      var arr = obj.constructor.toString().match(/function\s+(\w+)/)

      if (arr && arr.length == 2) return arr[1]
    }
    return undefined
  }

  var debounce
  ;(function(){
    var bounced = {}
    debounce = function(t, id, cb){
      clearTimeout( bounced[id] )
      bounced[id] = setTimeout(cb, t)
    }
  })()

  NewBindable.fieldManager = fieldManager
  NewBindable.bindForm = bindForm
  NewBindable.unbind = unbind
  NewBindable.bind = bind

  DEFINE(NewBindable, 'bindables', {get:function(){return _bindables}, enumerable:true})
  DEFINE(NewBindable, 'PROPERTY_MANIPULATOR', {value:PROPERTY_MANIPULATOR, writeable:false})

  if (typeof module !== 'undefined' && module.hasOwnProperty('exports')) {
    module.exports = NewBindable
  } else {
    window.Connected  = NewBindable
    window.Bindable   = Bindable
    window.familyOf   = familyOf
    window.typeOf     = typeOf
  }

})()
<|endoftext|>


<commit_before>import konnector, {
  getConnectionStatus,
  hasError,
  hasRunningConnection,
  hasRunConnection
} from './konnector'

// constant
export const CREATE_CONNECTION = 'CREATE_CONNECTION'
export const UPDATE_CONNECTION_RUNNING_STATUS = 'UPDATE_CONNECTION_RUNNING_STATUS'
export const UPDATE_CONNECTION_ERROR = 'UPDATE_CONNECTION_ERROR'

// reducers

const reducer = (state = {}, action) => {
  switch (action.type) {
    case CREATE_CONNECTION:
    case UPDATE_CONNECTION_ERROR:
    case UPDATE_CONNECTION_RUNNING_STATUS:
      if (!action.konnector || !action.konnector.slug) throw new Error('Missing konnector slug')
      return { ...state, [action.konnector.slug]: konnector(state[action.konnector.slug], action) }
    default:
      return state
  }
}

export default reducer

// action creators sync
export const createConnection = (konnector, account, folder) => ({
  type: CREATE_CONNECTION,
  konnector,
  account,
  folder
})

export const updateConnectionError = (konnector, account, error) => ({
  type: UPDATE_CONNECTION_ERROR,
  konnector,
  account,
  error
})

export const updateConnectionRunningStatus = (konnector, account, isRunning = false) => ({
  type: UPDATE_CONNECTION_RUNNING_STATUS,
  konnector,
  account,
  isRunning
})

// selectors
const getKonnectorIconURL = (registry, slug) => {
  const url = `assets/icons/konnectors/${slug}.svg`
  let icon = null
  try {
    icon = require(url)
  } catch (error) {
    console.warn(`Cannot get icon ${url}: ${error.message}`)
  }
  return icon
}

const queueStatuses = {
  done: 'loaded',
  error: 'failed',
  running: 'loading'
}

export const getQueue = (state, konnectorsRegistry) => {
  return Object.keys(state).reduce((runningConnections, key) => {
    const konnector = state[key]
    const label = konnectorsRegistry[key] && konnectorsRegistry[key].name
    const connectionStatus = getConnectionStatus(state[key])
    const status = queueStatuses[connectionStatus] || connectionStatus
    const icon = getKonnectorIconURL(konnectorsRegistry, key)
    if (hasRunningConnection(konnector) || hasRunConnection(konnector)) {
      runningConnections.push({
        label,
        status,
        icon
      })
    }
    return runningConnections
  }, [])
}

export const getRun = (state) => {
  return Object.keys(state).reduce((numRunConnections, slug) => {
    const konnector = state[slug]
    return (hasRunConnection(konnector) && !hasRunningConnection(konnector))
      ? numRunConnections + 1
        : numRunConnections
  }, 0)
}

export const getSuccessfulRun = (state) => {
  return Object.keys(state).reduce((numRunConnections, slug) => {
    const konnector = state[slug]
    return (hasRunConnection(konnector) && !hasError(konnector))
      ? numRunConnections + 1
        : numRunConnections
  }, 0)
}
<commit_msg>fix: konnector icons in queue :ambulance::lipstick:<commit_after>import konnector, {
  getConnectionStatus,
  hasError,
  hasRunningConnection,
  hasRunConnection
} from './konnector'

// constant
export const CREATE_CONNECTION = 'CREATE_CONNECTION'
export const UPDATE_CONNECTION_RUNNING_STATUS = 'UPDATE_CONNECTION_RUNNING_STATUS'
export const UPDATE_CONNECTION_ERROR = 'UPDATE_CONNECTION_ERROR'

// reducers

const reducer = (state = {}, action) => {
  switch (action.type) {
    case CREATE_CONNECTION:
    case UPDATE_CONNECTION_ERROR:
    case UPDATE_CONNECTION_RUNNING_STATUS:
      if (!action.konnector || !action.konnector.slug) throw new Error('Missing konnector slug')
      return { ...state, [action.konnector.slug]: konnector(state[action.konnector.slug], action) }
    default:
      return state
  }
}

export default reducer

// action creators sync
export const createConnection = (konnector, account, folder) => ({
  type: CREATE_CONNECTION,
  konnector,
  account,
  folder
})

export const updateConnectionError = (konnector, account, error) => ({
  type: UPDATE_CONNECTION_ERROR,
  konnector,
  account,
  error
})

export const updateConnectionRunningStatus = (konnector, account, isRunning = false) => ({
  type: UPDATE_CONNECTION_RUNNING_STATUS,
  konnector,
  account,
  isRunning
})

// selectors
const getKonnectorIconURL = (registry, slug) => {
  let icon = null
  try {
    icon = require(`../../assets/icons/konnectors/${slug}.svg`)
  } catch (error) {
    console.warn(`Cannot get icon ${slug}: ${error.message}`)
  }
  return icon
}

const queueStatuses = {
  done: 'loaded',
  error: 'failed',
  running: 'loading'
}

export const getQueue = (state, konnectorsRegistry) => {
  return Object.keys(state).reduce((runningConnections, key) => {
    const konnector = state[key]
    const label = konnectorsRegistry[key] && konnectorsRegistry[key].name
    const connectionStatus = getConnectionStatus(state[key])
    const status = queueStatuses[connectionStatus] || connectionStatus
    const icon = getKonnectorIconURL(konnectorsRegistry, key)
    if (hasRunningConnection(konnector) || hasRunConnection(konnector)) {
      runningConnections.push({
        label,
        status,
        icon
      })
    }
    return runningConnections
  }, [])
}

export const getRun = (state) => {
  return Object.keys(state).reduce((numRunConnections, slug) => {
    const konnector = state[slug]
    return (hasRunConnection(konnector) && !hasRunningConnection(konnector))
      ? numRunConnections + 1
        : numRunConnections
  }, 0)
}

export const getSuccessfulRun = (state) => {
  return Object.keys(state).reduce((numRunConnections, slug) => {
    const konnector = state[slug]
    return (hasRunConnection(konnector) && !hasError(konnector))
      ? numRunConnections + 1
        : numRunConnections
  }, 0)
}
<|endoftext|>


<commit_before>'use strict';

angular.module('frapontillo.ex.filters')
  .filter('default', function() {
    return function(input, value) {
      if (input !== null && input !== undefined && (input !== '' || angular.isNumber(input))) {
        return input;
      }
      return value || '';
    };
  }
);<commit_msg>Also check for NaN in "default" filter<commit_after>'use strict';

angular.module('frapontillo.ex.filters')
  .filter('default', function() {
    return function(input, value) {
      if (!isNaN(input) && input !== null && input !== undefined && (input !== '' || angular.isNumber(input))) {
        return input;
      }
      return value || '';
    };
  }
);
<|endoftext|>


<commit_before>/*jslint browser:true */
/*jshint browser:true, jquery:true */

(function ($) {
    'use strict';

    $.lazyLoadXT.selector += ',video,iframe[data-src]';

    $(document).on('lazyshow', 'video', function () {
        var $this = $(this);
        $this
            .attr('poster', $this.attr('data-poster'))
            .removeAttr('data-poster')
            .children()
            .each(function () {
                if (/source|track/i.test(this.tagName)) {
                    var $child = $(this);
                    $child
                        .attr('src', $child.attr('data-src'))
                        .removeAttr('data-src');
                }
            });
        // reload video
        this.load();
    });

}(window.jQuery || window.Zepto));
<commit_msg>$.lazyLoadXT.videoPoster for data-poster attribute; $.lazyLoadXT.srcAttr for data-src attribute<commit_after>/*jslint browser:true */
/*jshint browser:true, jquery:true */

(function ($) {
    'use strict';

    $.lazyLoadXT.selector += ',video,iframe[data-src]';
    $.lazyLoadXT.videoPoster = 'data-poster';

    $(document).on('lazyshow', 'video', function () {
        var $this = $(this),
            srcPoster = $.lazyLoadXT.videoPoster,
            srcAttr = $.lazyLoadXT.srcAttr,
            isFuncSrcAttr = $.isFunction(srcAttr);

        $this
            .attr('poster', $this.attr(srcPoster))
            .children()
            .each(function () {
                if (/source|track/i.test(this.tagName)) {
                    var $child = $(this);
                    $child.attr('src', isFuncSrcAttr ? srcAttr($child) : $child.attr(srcAttr));
                }
            });

        // reload video
        this.load();
    });

}(window.jQuery || window.Zepto));
<|endoftext|>


<commit_before>define([
  'summernote/base/core/func',
  'summernote/base/core/list',
  'summernote/base/core/dom',
  'summernote/base/core/range',
  'summernote/base/core/key'
], function (func, list, dom, range, key) {
  var AutLink = function (context) {
    var self = this;

    var linkPattern = /^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+-]+@)(.+)$/i;
    var $note = context.layoutInfo.note;

    this.events = {
      'summernote.keyup': function (we, e) {
        self.handleKeyup(e);
      },
      'summernote.keydown': function (we, e) {
        self.handleKeydown(e);
      }
    };

    this.initialize = function () {
      this.lastWordRange = null;
      dom.attachEvents($note, this.events);
    };

    this.destroy = function () {
      this.lastWordRange = null;
      dom.detachEvents($note, this.events);
    };

    this.replace = function () {
      if (!this.lastWordRange) {
        return;
      }

      var keyword = this.lastWordRange.toString();

      if (linkPattern.test(keyword)) {
        var node = this.nodeFromKeyword(keyword);

        this.lastWordRange.insertNode(node);
        this.lastWordRange = null;
        context.invoke('editor.focus');
      }

    };

    this.nodeFromKeyword = function (keyword) {
      return $('<a />').html(keyword).attr('href', keyword)[0];
    };

    this.handleKeydown = function (e) {
      if (list.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {
        var wordRange = context.invoke('editor.createRange').getWordRange();
        this.lastWordRange = wordRange;
      }
    };

    this.handleKeyup = function (e) {
      if (list.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {
        this.replace();
      }
    };
  };

  return AutLink;
});
<commit_msg>fixed invalid name<commit_after>define([
  'summernote/base/core/func',
  'summernote/base/core/list',
  'summernote/base/core/dom',
  'summernote/base/core/range',
  'summernote/base/core/key'
], function (func, list, dom, range, key) {
  var AutoLink = function (context) {
    var self = this;

    var linkPattern = /^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+-]+@)(.+)$/i;
    var $note = context.layoutInfo.note;

    this.events = {
      'summernote.keyup': function (we, e) {
        self.handleKeyup(e);
      },
      'summernote.keydown': function (we, e) {
        self.handleKeydown(e);
      }
    };

    this.initialize = function () {
      this.lastWordRange = null;
      dom.attachEvents($note, this.events);
    };

    this.destroy = function () {
      this.lastWordRange = null;
      dom.detachEvents($note, this.events);
    };

    this.replace = function () {
      if (!this.lastWordRange) {
        return;
      }

      var keyword = this.lastWordRange.toString();

      if (linkPattern.test(keyword)) {
        var node = this.nodeFromKeyword(keyword);

        this.lastWordRange.insertNode(node);
        this.lastWordRange = null;
        context.invoke('editor.focus');
      }

    };

    this.nodeFromKeyword = function (keyword) {
      return $('<a />').html(keyword).attr('href', keyword)[0];
    };

    this.handleKeydown = function (e) {
      if (list.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {
        var wordRange = context.invoke('editor.createRange').getWordRange();
        this.lastWordRange = wordRange;
      }
    };

    this.handleKeyup = function (e) {
      if (list.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {
        this.replace();
      }
    };
  };

  return AutoLink;
});
<|endoftext|>


<commit_before>'use strict';

angular.module('copayApp.controllers').controller('tabHomeController',
  function($rootScope, $timeout, $scope, $state, $ionicScrollDelegate, lodash, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, $window) {
    $scope.externalServices = {};
    $scope.bitpayCardEnabled = true; // TODO
    $scope.openTxpModal = txpModalService.open;
    $scope.version = $window.version;
    $scope.name = $window.appConfig.nameCase;

    configService.whenAvailable(function() {
      var config = configService.getSync();
      var isWindowsPhoneApp = platformInfo.isWP && isCordova;
      $scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp;
      $scope.coinbaseEnabled = config.coinbase.enabled && !isWindowsPhoneApp;
    });

    $scope.openWallet = function(wallet) {
      if (!wallet.isComplete()) {
        return $state.go('tabs.copayers', {
          walletId: wallet.credentials.walletId
        });
      }

      $state.go('tabs.details', {
        walletId: wallet.credentials.walletId
      });
    };

    function updateTxps() {
      profileService.getTxps({
        limit: 3
      }, function(err, txps, n) {
        if (err) $log.error(err);
        $scope.txps = txps;
        $scope.txpsN = n;
        $ionicScrollDelegate.resize();

        $timeout(function() {
          $scope.$apply();
        }, 1);
      })
    };

    $scope.updateAllWallets = function() {
      $scope.wallets = profileService.getWallets();
      if (lodash.isEmpty($scope.wallets)) return;

      var i = $scope.wallets.length;
      var j = 0;
      var timeSpan = 60 * 60 * 24 * 7;
      var notifications = [];

      lodash.each($scope.wallets, function(wallet) {
        walletService.getStatus(wallet, {}, function(err, status) {
          if (err) {
            console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO
          } else {
            wallet.status = status;
          }
          if (++j == i) {
            updateTxps();
          }
        });
      });

      $scope.fetchingNotifications = true;
      profileService.getNotifications({
        limit: 3
      }, function(err, n) {
        if (err) {
          console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO
          return;
        }
        $scope.fetchingNotifications = false;
        $scope.notifications = n;
        $ionicScrollDelegate.resize();

        $timeout(function() {
          $scope.$apply();
        }, 1);

      })
    };

    $scope.updateWallet = function(wallet) {
      $log.debug('Updating wallet:' + wallet.name)
      walletService.getStatus(wallet, {}, function(err, status) {
        if (err) {
          $log.error(err); //TODO
          return;
        }
        wallet.status = status;

        $scope.fetchingNotifications = true;
        profileService.getNotifications({
          limit: 3
        }, function(err, notifications) {
          $scope.fetchingNotifications = false;
          if (err) {
            console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO
            return;
          }
          $scope.notifications = notifications;

          updateTxps();
        })
      });
    };

    $scope.nextStep = function() {
      lodash.each(['AmazonGiftCards', 'BitpayCard', 'BuyAndSell'], function(service) {
        storageService.getNextStep(service, function(err, value) {
          $scope.externalServices[service] = value ? true : false;
          $ionicScrollDelegate.resize();
        });
      });
    };

    var listeners = [
      $rootScope.$on('bwsEvent', function(e, walletId, type, n) {
        var wallet = profileService.getWallet(walletId);
        $scope.updateWallet(wallet);
      }),
      $rootScope.$on('Local/TxAction', function(e, walletId) {
        $log.debug('Got action for wallet ' + walletId);
        var wallet = profileService.getWallet(walletId);
        $scope.updateWallet(wallet);
      }),
    ];

    $scope.$on('$destroy', function() {
      lodash.each(listeners, function(x) {
        x();
      });
    });
  });
<commit_msg>fix variable<commit_after>'use strict';

angular.module('copayApp.controllers').controller('tabHomeController',
  function($rootScope, $timeout, $scope, $state, $ionicScrollDelegate, lodash, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, $window) {
    $scope.externalServices = {};
    $scope.bitpayCardEnabled = true; // TODO
    $scope.openTxpModal = txpModalService.open;
    $scope.version = $window.version;
    $scope.name = $window.appConfig.nameCase;

    configService.whenAvailable(function() {
      var config = configService.getSync();
      var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova;
      $scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp;
      $scope.coinbaseEnabled = config.coinbase.enabled && !isWindowsPhoneApp;
    });

    $scope.openWallet = function(wallet) {
      if (!wallet.isComplete()) {
        return $state.go('tabs.copayers', {
          walletId: wallet.credentials.walletId
        });
      }

      $state.go('tabs.details', {
        walletId: wallet.credentials.walletId
      });
    };

    function updateTxps() {
      profileService.getTxps({
        limit: 3
      }, function(err, txps, n) {
        if (err) $log.error(err);
        $scope.txps = txps;
        $scope.txpsN = n;
        $ionicScrollDelegate.resize();

        $timeout(function() {
          $scope.$apply();
        }, 1);
      })
    };

    $scope.updateAllWallets = function() {
      $scope.wallets = profileService.getWallets();
      if (lodash.isEmpty($scope.wallets)) return;

      var i = $scope.wallets.length;
      var j = 0;
      var timeSpan = 60 * 60 * 24 * 7;
      var notifications = [];

      lodash.each($scope.wallets, function(wallet) {
        walletService.getStatus(wallet, {}, function(err, status) {
          if (err) {
            console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO
          } else {
            wallet.status = status;
          }
          if (++j == i) {
            updateTxps();
          }
        });
      });

      $scope.fetchingNotifications = true;
      profileService.getNotifications({
        limit: 3
      }, function(err, n) {
        if (err) {
          console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO
          return;
        }
        $scope.fetchingNotifications = false;
        $scope.notifications = n;
        $ionicScrollDelegate.resize();

        $timeout(function() {
          $scope.$apply();
        }, 1);

      })
    };

    $scope.updateWallet = function(wallet) {
      $log.debug('Updating wallet:' + wallet.name)
      walletService.getStatus(wallet, {}, function(err, status) {
        if (err) {
          $log.error(err); //TODO
          return;
        }
        wallet.status = status;

        $scope.fetchingNotifications = true;
        profileService.getNotifications({
          limit: 3
        }, function(err, notifications) {
          $scope.fetchingNotifications = false;
          if (err) {
            console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO
            return;
          }
          $scope.notifications = notifications;

          updateTxps();
        })
      });
    };

    $scope.nextStep = function() {
      lodash.each(['AmazonGiftCards', 'BitpayCard', 'BuyAndSell'], function(service) {
        storageService.getNextStep(service, function(err, value) {
          $scope.externalServices[service] = value ? true : false;
          $ionicScrollDelegate.resize();
        });
      });
    };

    var listeners = [
      $rootScope.$on('bwsEvent', function(e, walletId, type, n) {
        var wallet = profileService.getWallet(walletId);
        $scope.updateWallet(wallet);
      }),
      $rootScope.$on('Local/TxAction', function(e, walletId) {
        $log.debug('Got action for wallet ' + walletId);
        var wallet = profileService.getWallet(walletId);
        $scope.updateWallet(wallet);
      }),
    ];

    $scope.$on('$destroy', function() {
      lodash.each(listeners, function(x) {
        x();
      });
    });
  });
<|endoftext|>