<commit_before>

/*  Intervalometer API

message                  args                     response
-------------------------------------------------------------------------
'load'                 program (obj)              validationResult (obj)
'start'                ---                        status (obj)
'pause'                ---                        status (obj)
'cancel'               ---                        status (obj)

'motion-step'          axis (int), steps (int)    motionStatus (obj)
'motion-move'          axis (int), speed (float)  motionStatus (obj)
'motion-stop'          axis (int)                 motionStatus (obj)
'motion-info'          ---                        motionStatus (obj)

'camera-update'        ---                        cameraStatus (obj)
'camera-set'           param (str), val (str)     cameraStatus (obj)
'camera-set-ev'        ev (float)                 cameraStatus (obj)
'camera-get'           ---                        cameraStatus (obj)
'camera-set-primary'   cameraIndex (int)          cameraStatus (obj)
'camera-capture'       options (obj)              captureResult (obj)
'camera-liveview'      enable (bool)              camera_status (obj)

event                  payload
--------------------------------------------------
'error'                message (str)
'status'               intervalometerStatus (obj)
'motion-status'        motionStatus (obj)
'camera-status'        cameraStatus (obj)
'jpeg-capture'         jpegImage (buf)
'jpeg-liveview'        jpegImage (buf)

*/

var EventEmitter = require("events").EventEmitter;
var exec = require('child_process').exec;
require('rootpath')();
var camera = require('camera/camera.js');
var db = require('system/db.js');
var nmx = require('drivers/nmx.js');
var image = require('camera/image/image.js');
var exp = require('intervalometer/exposure.js');
var intervalometer = require('intervalometer/intervalometer.js');
var interpolate = require('intervalometer/interpolate.js');
var fs = require('fs');
var async = require('async');
var TLROOT = "/root/time-lapse";
var Button = require('gpio-button');
var gpio = require('linux-gpio');
var _ = require('underscore');
var net = require('net');

var server = net.createServer(function(c) {
  // 'connection' listener
  console.log('client connected');
  c.on('data', function(data) {
  	console.log("received:", data);
    try {
      parseData(JSON.parse(data.toString()));
    } catch(e) {
      console.log("failed parsing", data, e);
    }
  });
  c.on('end', function() {
    console.log('client disconnected');
  });
  c.write('hello\r\n');
  //c.pipe(c);
});

server.on('error', function(err) {
  throw err;
});
server.listen('/tmp/intervalometer.sock',  function() {
  console.log('server bound');
});

function broadcast(data) {
    server.clients.forEach(function each(client) {
        //console.log("client:", client);
        try {
            if (client) client.send(data);
        } catch (err) {
            console.log("broadcast error:", err);
        }
    });
};

function send(event, data, client) {
  var packet = {
    type: event,
    data: data
  }
  client.write(JSON.stringify(packet));
}

function sendEvent(event, data) {
  var payload = JSON.stringify({
    type: event,
    data: data
  });
  broadcast(payload);
}

function parseData(data, client) {
  if(data && data.type) {
    var type = data.type;
    var args = data.args || {};
    var callback = (function(id, c) { return function(err, data) {
      if(id) {
        send('callback', {id:id, err:err, data:data}, c);
      }
    }})(data.id, client);

    runCommand(type, args, callback);
  }
}

function runCommand(type, args, callback) {
  switch type {
    /*case 'load':
      intervalometer.load(args, callback);
      break;
    case 'start':
      intervalometer.start(callback);
      break;
    case 'pause':
      intervalometer.pause(callback);
      break;
    case 'cancel':
      intervalometer.cancel(callback);
      break;
    case 'motion-step':
      motion.step(args.axis, args.steps, callback);
      break;
    case 'motion-move':
      motion.move(args.axis, args.speed, callback);
      break;
    case 'motion-stop':
      motion.stop(args.axis, callback);
      break;
    case 'motion-info':
      motion.info(callback);
      break;
*/
    case 'intervalometer.load':
      intervalometer.load(args.program, callback);
      break;
    case 'intervalometer.cancel':
      intervalometer.cancel(callback);
      break;
    case 'intervalometer.run':
      intervalometer.run(args.program, callback);
      break;
    case 'gps':
      intervalometer.addGpsData(args.gpsData, callback);
      break;

    case 'camera.ptp.connectSonyWifi':
      camera.ptp.connectSonyWifi(callback);
      break;
    case 'camera.ptp.lvOff':
      camera.ptp.lvOff(callback);
      break;
    case 'camera.ptp.zoom':
      camera.ptp.zoom(args.x, args.y, callback);
      break;
    case 'camera.ptp.focus':
      camera.ptp.focus(args.step, args.repeat, callback);
      break;
    case 'camera.setEv':
      camera.setEv(args.ev, args.options, callback);
      break;
    case 'camera.ptp.preview':
      camera.ptp.preview(callback);
      break;
    case 'camera.ptp.getSettings':
      camera.ptp.getSettings(function(err, data){
        callback(err, data);
        sendEvent('camera.settings', camera.ptp.settings);
      });
      break;
    case 'camera.ptp.cameraList':
      camera.ptp.cameraList(callback);
      break;
    case 'camera.ptp.switchPrimary':
      camera.ptp.switchPrimary(args.cameraObject, callback);
      break;
    case 'camera.ptp.capture':
      camera.ptp.capture(args.options, callback);
      break;
    case 'camera.ptp.runSupportTest':
      camera.ptp.runSupportTest(callback);
      break;
    case 'camera.ptp.set':
      camera.ptp.set(args.key, args.val, callback);
      break;
  }
}

intervalometer.on('status', function(data) {
  data.autoSettings = intervalometer.autoSettings;
  sendEvent('intervalometer.status', data);
});
intervalometer.on('error', function(data) {
  sendEvent('intervalometer.error', data);
});

camera.ptp.on('media', function(data) {
  sendEvent('media.present', data);
});
camera.ptp.on('media-insert', function(data) {
  sendEvent('media.insert', data);
});
camera.ptp.on('media-remove', function(data) {
  sendEvent('media.insert', data);
});
camera.ptp.on('photo', function() {
  sendEvent('camera.photo', camera.ptp.photo);
});
camera.ptp.on('settings', function(data) {
  sendEvent('camera.settings', data);
});
camera.ptp.on('connected', function(model) {
  var data = {
    connected: camera.ptp.connected,
    model: camera.ptp.model,
    count: camera.ptp.count,
    supports: camera.ptp.supports
  };
  sendEvent('camera.connected', data);
});
camera.ptp.on('exiting', function(model) {
  var data = {
    connected: camera.ptp.connected,
    model: camera.ptp.model,
    count: camera.ptp.count,
    supports: camera.ptp.supports
  };
  sendEvent('camera.exiting', data);
});
camera.ptp.on('error', function(data) {
  sendEvent('camera.error', data);
});
camera.ptp.on('status', function(data) {
  sendEvent('camera.status', data);
});
camera.ptp.on('connectionError', function(data) {
  sendEvent('camera.connectionError', data);
});
camera.ptp.on('nmxSerial', function(status) {
    if (status == "connected") {
        console.log("NMX attached");
        nmx.connect(camera.ptp.nmxDevice);
    } else {
        console.log("NMX detached");
        nmx.disconnect();
    }
});

var scanTimerHandle = null;
var scanTimerHandle2 = null;
var scanTimerHandle3 = null;
var btleScanStarting = false;

function clearScanTimeouts() {
    if(scanTimerHandle) clearTimeout(scanTimerHandle);
    if(scanTimerHandle2) clearTimeout(scanTimerHandle2);
    if(scanTimerHandle3) clearTimeout(scanTimerHandle3);
    scanTimerHandle = null;
    scanTimerHandle2 = null;
    scanTimerHandle3 = null;
}

function startScan() {
    if(btleScanStarting || updates.installing) return;
    btleScanStarting = true;
    clearScanTimeouts()
    scanTimerHandle = setTimeout(startScan, 30000);
    if (noble.state == "poweredOn") {
        scanTimerHandle2 = setTimeout(function() {
            noble.stopScanning();
        }, 500);
        scanTimerHandle3 = setTimeout(function() {
            if (noble.state == "poweredOn") {
                //console.log("Starting BLE scan...");
                noble.startScanning(nmx.btServiceIds, false, function(err){
                    console.log("BLE scan started: ", err);
                });
            }
            btleScanStarting = false;
        }, 8000);
    } else {
        btleScanStarting = false;
        if(wifi.btEnabled) {
            wifi.resetBt();
        }
    }
}
startScan();

function stopScan() {
    clearScanTimeouts();
    noble.stopScanning();
}

noble.on('stateChange', function(state) {
    console.log("BLE state changed to", state);
    if (state == "poweredOn") {
        setTimeout(function() {
            startScan()
        });
    }
});

noble.on('discover', function(peripheral) {
    //console.log('ble', peripheral);
    stopScan();
    nmx.connect(peripheral);
});

nmx.connect();

nmx.on('status', function(status) {
    if (status.connected) {
        oled.setIcon('bt', true);
        stopScan();
        ui.reload();
    } else {
        oled.setIcon('bt', false);
        ui.reload();
        wifi.resetBt(function(){
            startScan();
        });
    }
});

<commit_msg>separated core intervalometer process<commit_after>

/*  Intervalometer API

message                  args                     response
-------------------------------------------------------------------------
'load'                 program (obj)              validationResult (obj)
'start'                ---                        status (obj)
'pause'                ---                        status (obj)
'cancel'               ---                        status (obj)

'motion-step'          axis (int), steps (int)    motionStatus (obj)
'motion-move'          axis (int), speed (float)  motionStatus (obj)
'motion-stop'          axis (int)                 motionStatus (obj)
'motion-info'          ---                        motionStatus (obj)

'camera-update'        ---                        cameraStatus (obj)
'camera-set'           param (str), val (str)     cameraStatus (obj)
'camera-set-ev'        ev (float)                 cameraStatus (obj)
'camera-get'           ---                        cameraStatus (obj)
'camera-set-primary'   cameraIndex (int)          cameraStatus (obj)
'camera-capture'       options (obj)              captureResult (obj)
'camera-liveview'      enable (bool)              camera_status (obj)

event                  payload
--------------------------------------------------
'error'                message (str)
'status'               intervalometerStatus (obj)
'motion-status'        motionStatus (obj)
'camera-status'        cameraStatus (obj)
'jpeg-capture'         jpegImage (buf)
'jpeg-liveview'        jpegImage (buf)

*/

var EventEmitter = require("events").EventEmitter;
var exec = require('child_process').exec;
require('rootpath')();
var camera = require('camera/camera.js');
var db = require('system/db.js');
var nmx = require('drivers/nmx.js');
var image = require('camera/image/image.js');
var exp = require('intervalometer/exposure.js');
var intervalometer = require('intervalometer/intervalometer.js');
var interpolate = require('intervalometer/interpolate.js');
var fs = require('fs');
var async = require('async');
var TLROOT = "/root/time-lapse";
var Button = require('gpio-button');
var gpio = require('linux-gpio');
var _ = require('underscore');
var net = require('net');

var server = net.createServer(function(c) {
  // 'connection' listener
  console.log('client connected');
  c.on('data', function(data) {
  	console.log("received:", data);
    try {
      parseData(JSON.parse(data.toString()));
    } catch(e) {
      console.log("failed parsing", data, e);
    }
  });
  c.on('end', function() {
    console.log('client disconnected');
  });
  c.write('hello\r\n');
  //c.pipe(c);
});

server.on('error', function(err) {
  throw err;
});
server.listen('/tmp/intervalometer.sock',  function() {
  console.log('server bound');
});

function broadcast(data) {
    server.clients.forEach(function each(client) {
        //console.log("client:", client);
        try {
            if (client) client.send(data);
        } catch (err) {
            console.log("broadcast error:", err);
        }
    });
};

function send(event, data, client) {
  var packet = {
    type: event,
    data: data
  }
  client.write(JSON.stringify(packet));
}

function sendEvent(event, data) {
  var payload = JSON.stringify({
    type: event,
    data: data
  });
  broadcast(payload);
}

function parseData(data, client) {
  if(data && data.type) {
    var type = data.type;
    var args = data.args || {};
    var callback = (function(id, c) { return function(err, data) {
      if(id) {
        send('callback', {id:id, err:err, data:data}, c);
      }
    }})(data.id, client);

    runCommand(type, args, callback);
  }
}

function runCommand(type, args, callback) {
  switch(type) {
    /*case 'load':
      intervalometer.load(args, callback);
      break;
    case 'start':
      intervalometer.start(callback);
      break;
    case 'pause':
      intervalometer.pause(callback);
      break;
    case 'cancel':
      intervalometer.cancel(callback);
      break;
    case 'motion-step':
      motion.step(args.axis, args.steps, callback);
      break;
    case 'motion-move':
      motion.move(args.axis, args.speed, callback);
      break;
    case 'motion-stop':
      motion.stop(args.axis, callback);
      break;
    case 'motion-info':
      motion.info(callback);
      break;
*/
    case 'intervalometer.load':
      intervalometer.load(args.program, callback);
      break;
    case 'intervalometer.cancel':
      intervalometer.cancel(callback);
      break;
    case 'intervalometer.run':
      intervalometer.run(args.program, callback);
      break;
    case 'gps':
      intervalometer.addGpsData(args.gpsData, callback);
      break;

    case 'camera.ptp.connectSonyWifi':
      camera.ptp.connectSonyWifi(callback);
      break;
    case 'camera.ptp.lvOff':
      camera.ptp.lvOff(callback);
      break;
    case 'camera.ptp.zoom':
      camera.ptp.zoom(args.x, args.y, callback);
      break;
    case 'camera.ptp.focus':
      camera.ptp.focus(args.step, args.repeat, callback);
      break;
    case 'camera.setEv':
      camera.setEv(args.ev, args.options, callback);
      break;
    case 'camera.ptp.preview':
      camera.ptp.preview(callback);
      break;
    case 'camera.ptp.getSettings':
      camera.ptp.getSettings(function(err, data){
        callback(err, data);
        sendEvent('camera.settings', camera.ptp.settings);
      });
      break;
    case 'camera.ptp.cameraList':
      camera.ptp.cameraList(callback);
      break;
    case 'camera.ptp.switchPrimary':
      camera.ptp.switchPrimary(args.cameraObject, callback);
      break;
    case 'camera.ptp.capture':
      camera.ptp.capture(args.options, callback);
      break;
    case 'camera.ptp.runSupportTest':
      camera.ptp.runSupportTest(callback);
      break;
    case 'camera.ptp.set':
      camera.ptp.set(args.key, args.val, callback);
      break;
  }
}

intervalometer.on('status', function(data) {
  data.autoSettings = intervalometer.autoSettings;
  sendEvent('intervalometer.status', data);
});
intervalometer.on('error', function(data) {
  sendEvent('intervalometer.error', data);
});

camera.ptp.on('media', function(data) {
  sendEvent('media.present', data);
});
camera.ptp.on('media-insert', function(data) {
  sendEvent('media.insert', data);
});
camera.ptp.on('media-remove', function(data) {
  sendEvent('media.insert', data);
});
camera.ptp.on('photo', function() {
  sendEvent('camera.photo', camera.ptp.photo);
});
camera.ptp.on('settings', function(data) {
  sendEvent('camera.settings', data);
});
camera.ptp.on('connected', function(model) {
  var data = {
    connected: camera.ptp.connected,
    model: camera.ptp.model,
    count: camera.ptp.count,
    supports: camera.ptp.supports
  };
  sendEvent('camera.connected', data);
});
camera.ptp.on('exiting', function(model) {
  var data = {
    connected: camera.ptp.connected,
    model: camera.ptp.model,
    count: camera.ptp.count,
    supports: camera.ptp.supports
  };
  sendEvent('camera.exiting', data);
});
camera.ptp.on('error', function(data) {
  sendEvent('camera.error', data);
});
camera.ptp.on('status', function(data) {
  sendEvent('camera.status', data);
});
camera.ptp.on('connectionError', function(data) {
  sendEvent('camera.connectionError', data);
});
camera.ptp.on('nmxSerial', function(status) {
    if (status == "connected") {
        console.log("NMX attached");
        nmx.connect(camera.ptp.nmxDevice);
    } else {
        console.log("NMX detached");
        nmx.disconnect();
    }
});

var scanTimerHandle = null;
var scanTimerHandle2 = null;
var scanTimerHandle3 = null;
var btleScanStarting = false;

function clearScanTimeouts() {
    if(scanTimerHandle) clearTimeout(scanTimerHandle);
    if(scanTimerHandle2) clearTimeout(scanTimerHandle2);
    if(scanTimerHandle3) clearTimeout(scanTimerHandle3);
    scanTimerHandle = null;
    scanTimerHandle2 = null;
    scanTimerHandle3 = null;
}

function startScan() {
    if(btleScanStarting || updates.installing) return;
    btleScanStarting = true;
    clearScanTimeouts()
    scanTimerHandle = setTimeout(startScan, 30000);
    if (noble.state == "poweredOn") {
        scanTimerHandle2 = setTimeout(function() {
            noble.stopScanning();
        }, 500);
        scanTimerHandle3 = setTimeout(function() {
            if (noble.state == "poweredOn") {
                //console.log("Starting BLE scan...");
                noble.startScanning(nmx.btServiceIds, false, function(err){
                    console.log("BLE scan started: ", err);
                });
            }
            btleScanStarting = false;
        }, 8000);
    } else {
        btleScanStarting = false;
        if(wifi.btEnabled) {
            wifi.resetBt();
        }
    }
}
startScan();

function stopScan() {
    clearScanTimeouts();
    noble.stopScanning();
}

noble.on('stateChange', function(state) {
    console.log("BLE state changed to", state);
    if (state == "poweredOn") {
        setTimeout(function() {
            startScan()
        });
    }
});

noble.on('discover', function(peripheral) {
    //console.log('ble', peripheral);
    stopScan();
    nmx.connect(peripheral);
});

nmx.connect();

nmx.on('status', function(status) {
    if (status.connected) {
        oled.setIcon('bt', true);
        stopScan();
        ui.reload();
    } else {
        oled.setIcon('bt', false);
        ui.reload();
        wifi.resetBt(function(){
            startScan();
        });
    }
});

<|endoftext|>


<commit_before>import {BlockNode, TextblockNode, InlineNode, TextNode} from "./node"
import {StyleMarker} from "./style"

import {ProseMirrorError} from "../util/error"

export class SchemaError extends ProseMirrorError {}

function findKinds(type, name, schema, override) {
  function set(sub, sup) {
    if (sub in schema.kinds) {
      if (schema.kinds[sub] == sup) return
      SchemaError.raise(`Inconsistent superkinds for kind ${sub}: ${sup} and ${schema.kinds[sub]}`)
    }
    if (schema.subKind(sub, sup))
      SchemaError.raise(`Conflicting kind hierarchy through ${sub} and ${sup}`)
    schema.kinds[sub] = sup
  }

  for (let cur = type;; cur = Object.getPrototypeOf(cur)) {
    let curKind = override != null && cur == type ? override : cur.kind
    if (curKind != null) {
      let [_, kind, end] = /^(.*?)(\.)?$/.exec(curKind)
      if (kind) {
        set(name, kind)
        name = kind
      }
      if (end) {
        set(name, null)
        return
      }
    }
  }
}

export class NodeType {
  constructor(name, contains, attrs, schema) {
    this.name = name
    this.contains = contains
    this.attrs = attrs
    this.schema = schema
    this.defaultAttrs = null
    this.mustRecompute = false
    for (let attr in attrs)
      if (attrs[attr].mustRecompute) this.mustRecompute = true
  }

  get configurable() { return true }
  get isTextblock() { return false }
  get isBlock() { return false }
  get isInline() { return false }

  static get kind() { return "." }

  canContain(node) {
    return this.canContainType(node.type)
  }

  canContainType(type) {
    return this.schema.subKind(type.name, this.contains)
  }

  canContainChildren(node, liberal) {
    if (!liberal && !this.schema.subKind(node.type.contains, this.contains)) return false
    for (let i = 0; i < node.length; i++)
      if (!this.canContain(node.child(i))) return false
    return true
  }

  recomputeAttrs(attrs, content) {
    if (!this.mustRecompute) return attrs
    let copy = Object.create(null)
    for (let attr in attrs) {
      let desc = this.attrs[attr]
      copy[attr] = desc.mustRecompute ? desc.compute(this, content) : attrs[attr]
    }
    return copy
  }

  findConnection(other) {
    if (this.canContainType(other)) return []

    let seen = Object.create(null)
    let active = [{from: this, via: []}]
    while (active.length) {
      let current = active.shift()
      for (let name in this.schema.nodes) {
        let type = this.schema.nodeType(name)
        if (!(type.contains in seen) && current.from.canContainType(type)) {
          let via = current.via.concat(type)
          if (type.canContainType(other)) return via
          active.push({from: type, via: via})
          seen[type.contains] = true
        }
      }
    }
  }

  buildAttrs(attrs, content) {
    if (!attrs && this.defaultAttrs) return this.defaultAttrs
    else return buildAttrs(this.attrs, attrs, this, content)
  }

  create(attrs, content, styles) {
    return new this.instance(this, this.buildAttrs(attrs, content), content, styles)
  }

  static compile(types, schema) {
    let result = Object.create(null)
    for (let name in types) {
      let info = types[name]
      let type = info.type || SchemaError.raise("Missing node type for " + name)
      findKinds(type, name, schema, info.kind)
      let contains = "contains" in info ? info.contains : type.contains
      result[name] = new type(name, contains, info.attributes || type.attributes, schema)
    }
    for (let name in result) {
      let contains = result[name].contains
      if (contains && !(contains in schema.kinds))
        SchemaError.raise("Node type " + name + " is specified to contain non-existing kind " + contains)
    }
    if (!result.doc) SchemaError.raise("Every schema needs a 'doc' type")
    if (!result.text) SchemaError.raise("Every schema needs a 'text' type")

    for (let name in types)
      types[name].defaultAttrs = getDefaultAttrs(types[name].attrs)
    return result
  }

  static register(prop, value) {
    ;(this.prototype[prop] || (this.prototype[prop] = [])).push(value)
  }
}
NodeType.attributes = {}

export class Block extends NodeType {
  get instance() { return BlockNode }
  static get contains() { return "block" }
  static get kind() { return "block." }
  get isBlock() { return true }
}

export class Textblock extends Block {
  get instance() { return TextblockNode }
  static get contains() { return "inline" }
  get containsStyles() { return true }
  get isTextblock() { return true }

  canContain(node) {
    return super.canContain(node) && node.styles.every(s => this.canContainStyle(s))
  }

  canContainStyle(type) {
    let contains = this.containsStyles
    if (contains === true) return true
    if (contains) for (let i = 0; i < contains.length; i++)
      if (contains[i] == type.name) return true
    return false
  }
}

export class Inline extends NodeType {
  get instance() { return InlineNode }
  static get contains() { return null }
  static get kind() { return "inline." }
  get isInline() { return true }
}

export class Text extends Inline {
  get instance() { return TextNode }
}

// Attribute descriptors

export class Attribute {
  constructor(options = {}) {
    this.default = options.default
    this.compute = options.compute
    this.mustRecompute = options.mustRecompute
    this.inheritable = options.inheritable
  }
}

// Styles

export class StyleType {
  constructor(name, attrs, rank, schema) {
    this.name = name
    this.attrs = attrs
    this.rank = rank
    this.schema = schema
    let defaults = getDefaultAttrs(this.attrs)
    this.instance = defaults && new StyleMarker(this, defaults)
  }

  static get rank() { return 50 }

  create(attrs) {
    if (!attrs && this.instance) return this.instance
    return new StyleMarker(this, buildAttrs(this.attrs, attrs, this))
  }

  static getOrder(styles) {
    let sorted = []
    for (let name in styles) sorted.push({name, rank: styles[name].type.rank})
    sorted.sort((a, b) => a.rank - b.rank)
    let ranks = Object.create(null)
    for (let i = 0; i < sorted.length; i++) ranks[sorted[i].name] = i
    return ranks
  }

  static compile(styles, schema) {
    let order = this.getOrder(styles)
    let result = Object.create(null)
    for (let name in styles) {
      let info = styles[name]
      let attrs = info.attributes || info.type.attributes
      result[name] = new info.type(name, attrs, order[name], schema)
    }
    return result
  }

  static register(prop, value) {
    ;(this.prototype[prop] || (this.prototype[prop] = [])).push(value)
  }
}
StyleType.attributes = {}

// Schema specifications are data structures that specify a schema --
// a set of node types, their names, attributes, and nesting behavior.

function copyObj(obj, f) {
  let result = Object.create(null)
  for (let prop in obj) result[prop] = f ? f(obj[prop]) : obj[prop]
  return result
}

function ensureWrapped(obj) {
  return obj instanceof Function ? {type: obj} : obj
}

function overlayObj(obj, overlay) {
  let copy = copyObj(obj)
  for (let name in overlay) {
    let info = ensureWrapped(overlay[name])
    if (info == null) {
      delete copy[name]
    } else if (info.type) {
      copy[name] = info
    } else {
      let existing = copy[name] = copyObj(copy[name])
      for (let prop in info)
        existing[prop] = info[prop]
    }
  }
  return copy
}

export class SchemaSpec {
  constructor(nodes, styles) {
    this.nodes = nodes ? copyObj(nodes, ensureWrapped) : Object.create(null)
    this.styles = styles ? copyObj(styles, ensureWrapped) : Object.create(null)
  }

  updateNodes(nodes) {
    return new SchemaSpec(overlayObj(this.nodes, nodes), this.styles)
  }

  addAttribute(filter, attrName, attrInfo) {
    let copy = copyObj(this.nodes)
    for (let name in copy) {
      if (typeof filter == "string" ? filter == name :
          typeof filter == "function" ? filter(name, copy[name]) :
          filter ? filter == copy[name] : true) {
        let info = copy[name] = copyObj(copy[name])
        if (!info.attributes) info.attributes = copyObj(info.type.attributes)
        info.attributes[attrName] = attrInfo
      }
    }
    return new SchemaSpec(copy, this.styles)
  }

  updateStyles(styles) {
    return new SchemaSpec(this.nodes, overlayObj(this.styles, styles))
  }
}

// For node types where all attrs have a default value (or which don't
// have any attributes), build up a single reusable default attribute
// object, and use it for all nodes that don't specify specific
// attributes.

function getDefaultAttrs(attrs) {
  let defaults = Object.create(null)
  for (let attrName in attrs) {
    let attr = attrs[attrName]
    if (attr.default == null) return null
    defaults[attrName] = attr.default
  }
  return defaults
}

function buildAttrs(attrSpec, attrs, arg1, arg2) {
  let built = Object.create(null)
  for (let name in attrSpec) {
    let value = attrs && attrs[name]
    if (value == null) {
      let attr = attrSpec[name]
      if (attr.default != null)
        value = attr.default
      else if (attr.compute)
        value = attr.compute(arg1, arg2)
      else
        SchemaError.raise("No value supplied for attribute " + name)
    }
    built[name] = value
  }
  return built
}

/**
 * Document schema class.
 */
export class Schema {
  constructor(spec, styles) {
    if (!(spec instanceof SchemaSpec)) spec = new SchemaSpec(spec, styles)
    this.spec = spec
    this.kinds = Object.create(null)
    this.nodes = NodeType.compile(spec.nodes, this)
    this.styles = StyleType.compile(spec.styles, this)
    this.cached = Object.create(null)

    this.node = this.node.bind(this)
    this.text = this.text.bind(this)
    this.nodeFromJSON = this.nodeFromJSON.bind(this)
    this.styleFromJSON = this.styleFromJSON.bind(this)
  }

  node(type, attrs, content, styles) {
    if (typeof type == "string")
      type = this.nodeType(type)
    else if (!(type instanceof NodeType))
      SchemaError.raise("Invalid node type: " + type)
    else if (type.schema != this)
      SchemaError.raise("Node type from different schema used (" + type.name + ")")

    return type.create(attrs, content, styles)
  }

  text(text, styles) {
    return this.nodes.text.create(null, text, styles)
  }

  defaultTextblockType() {
    let cached = this.cached.defaultTextblockType
    if (cached !== undefined) return cached
    for (let name in this.nodes) {
      if (this.nodes[name].defaultTextblock)
        return this.cached.defaultTextblockType = this.nodes[name]
    }
    return this.cached.defaultTextblockType = null
  }

  style(name, attrs) {
    let spec = this.styles[name] || SchemaError.raise("No style named " + name)
    return spec.create(attrs)
  }

  nodeFromJSON(json) {
    let type = this.nodeType(json.type)
    return type.create(json.attrs,
                       json.text || (json.content && json.content.map(this.nodeFromJSON)),
                       json.styles && json.styles.map(this.styleFromJSON))
  }

  styleFromJSON(json) {
    if (typeof json == "string") return this.style(json)
    return this.style(json._, json)
  }

  nodeType(name) {
    return this.nodes[name] || SchemaError.raise("Unknown node type: " + name)
  }

  subKind(sub, sup) {
    for (;;) {
      if (sub == sup) return true
      sub = this.kinds[sub]
      if (!sub) return false
    }
  }
}
<commit_msg>Fix node compatibility test in ancestor step<commit_after>import {BlockNode, TextblockNode, InlineNode, TextNode} from "./node"
import {StyleMarker} from "./style"

import {ProseMirrorError} from "../util/error"

export class SchemaError extends ProseMirrorError {}

function findKinds(type, name, schema, override) {
  function set(sub, sup) {
    if (sub in schema.kinds) {
      if (schema.kinds[sub] == sup) return
      SchemaError.raise(`Inconsistent superkinds for kind ${sub}: ${sup} and ${schema.kinds[sub]}`)
    }
    if (schema.subKind(sub, sup))
      SchemaError.raise(`Conflicting kind hierarchy through ${sub} and ${sup}`)
    schema.kinds[sub] = sup
  }

  for (let cur = type;; cur = Object.getPrototypeOf(cur)) {
    let curKind = override != null && cur == type ? override : cur.kind
    if (curKind != null) {
      let [_, kind, end] = /^(.*?)(\.)?$/.exec(curKind)
      if (kind) {
        set(name, kind)
        name = kind
      }
      if (end) {
        set(name, null)
        return
      }
    }
  }
}

export class NodeType {
  constructor(name, contains, attrs, schema) {
    this.name = name
    this.contains = contains
    this.attrs = attrs
    this.schema = schema
    this.defaultAttrs = null
    this.mustRecompute = false
    for (let attr in attrs)
      if (attrs[attr].mustRecompute) this.mustRecompute = true
  }

  get configurable() { return true }
  get isTextblock() { return false }
  get isBlock() { return false }
  get isInline() { return false }

  static get kind() { return "." }

  canContain(node) {
    return this.canContainType(node.type)
  }

  canContainType(type) {
    return this.schema.subKind(type.name, this.contains)
  }

  canContainChildren(node, liberal, from = 0, to = node.length) {
    if (!liberal && !this.schema.subKind(node.type.contains, this.contains)) return false
    for (let i = from; i < to; i++)
      if (!this.canContain(node.child(i))) return false
    return true
  }

  recomputeAttrs(attrs, content) {
    if (!this.mustRecompute) return attrs
    let copy = Object.create(null)
    for (let attr in attrs) {
      let desc = this.attrs[attr]
      copy[attr] = desc.mustRecompute ? desc.compute(this, content) : attrs[attr]
    }
    return copy
  }

  findConnection(other) {
    if (this.canContainType(other)) return []

    let seen = Object.create(null)
    let active = [{from: this, via: []}]
    while (active.length) {
      let current = active.shift()
      for (let name in this.schema.nodes) {
        let type = this.schema.nodeType(name)
        if (!(type.contains in seen) && current.from.canContainType(type)) {
          let via = current.via.concat(type)
          if (type.canContainType(other)) return via
          active.push({from: type, via: via})
          seen[type.contains] = true
        }
      }
    }
  }

  buildAttrs(attrs, content) {
    if (!attrs && this.defaultAttrs) return this.defaultAttrs
    else return buildAttrs(this.attrs, attrs, this, content)
  }

  create(attrs, content, styles) {
    return new this.instance(this, this.buildAttrs(attrs, content), content, styles)
  }

  static compile(types, schema) {
    let result = Object.create(null)
    for (let name in types) {
      let info = types[name]
      let type = info.type || SchemaError.raise("Missing node type for " + name)
      findKinds(type, name, schema, info.kind)
      let contains = "contains" in info ? info.contains : type.contains
      result[name] = new type(name, contains, info.attributes || type.attributes, schema)
    }
    for (let name in result) {
      let contains = result[name].contains
      if (contains && !(contains in schema.kinds))
        SchemaError.raise("Node type " + name + " is specified to contain non-existing kind " + contains)
    }
    if (!result.doc) SchemaError.raise("Every schema needs a 'doc' type")
    if (!result.text) SchemaError.raise("Every schema needs a 'text' type")

    for (let name in types)
      types[name].defaultAttrs = getDefaultAttrs(types[name].attrs)
    return result
  }

  static register(prop, value) {
    ;(this.prototype[prop] || (this.prototype[prop] = [])).push(value)
  }
}
NodeType.attributes = {}

export class Block extends NodeType {
  get instance() { return BlockNode }
  static get contains() { return "block" }
  static get kind() { return "block." }
  get isBlock() { return true }
}

export class Textblock extends Block {
  get instance() { return TextblockNode }
  static get contains() { return "inline" }
  get containsStyles() { return true }
  get isTextblock() { return true }

  canContain(node) {
    return super.canContain(node) && node.styles.every(s => this.canContainStyle(s))
  }

  canContainStyle(type) {
    let contains = this.containsStyles
    if (contains === true) return true
    if (contains) for (let i = 0; i < contains.length; i++)
      if (contains[i] == type.name) return true
    return false
  }
}

export class Inline extends NodeType {
  get instance() { return InlineNode }
  static get contains() { return null }
  static get kind() { return "inline." }
  get isInline() { return true }
}

export class Text extends Inline {
  get instance() { return TextNode }
}

// Attribute descriptors

export class Attribute {
  constructor(options = {}) {
    this.default = options.default
    this.compute = options.compute
    this.mustRecompute = options.mustRecompute
    this.inheritable = options.inheritable
  }
}

// Styles

export class StyleType {
  constructor(name, attrs, rank, schema) {
    this.name = name
    this.attrs = attrs
    this.rank = rank
    this.schema = schema
    let defaults = getDefaultAttrs(this.attrs)
    this.instance = defaults && new StyleMarker(this, defaults)
  }

  static get rank() { return 50 }

  create(attrs) {
    if (!attrs && this.instance) return this.instance
    return new StyleMarker(this, buildAttrs(this.attrs, attrs, this))
  }

  static getOrder(styles) {
    let sorted = []
    for (let name in styles) sorted.push({name, rank: styles[name].type.rank})
    sorted.sort((a, b) => a.rank - b.rank)
    let ranks = Object.create(null)
    for (let i = 0; i < sorted.length; i++) ranks[sorted[i].name] = i
    return ranks
  }

  static compile(styles, schema) {
    let order = this.getOrder(styles)
    let result = Object.create(null)
    for (let name in styles) {
      let info = styles[name]
      let attrs = info.attributes || info.type.attributes
      result[name] = new info.type(name, attrs, order[name], schema)
    }
    return result
  }

  static register(prop, value) {
    ;(this.prototype[prop] || (this.prototype[prop] = [])).push(value)
  }
}
StyleType.attributes = {}

// Schema specifications are data structures that specify a schema --
// a set of node types, their names, attributes, and nesting behavior.

function copyObj(obj, f) {
  let result = Object.create(null)
  for (let prop in obj) result[prop] = f ? f(obj[prop]) : obj[prop]
  return result
}

function ensureWrapped(obj) {
  return obj instanceof Function ? {type: obj} : obj
}

function overlayObj(obj, overlay) {
  let copy = copyObj(obj)
  for (let name in overlay) {
    let info = ensureWrapped(overlay[name])
    if (info == null) {
      delete copy[name]
    } else if (info.type) {
      copy[name] = info
    } else {
      let existing = copy[name] = copyObj(copy[name])
      for (let prop in info)
        existing[prop] = info[prop]
    }
  }
  return copy
}

export class SchemaSpec {
  constructor(nodes, styles) {
    this.nodes = nodes ? copyObj(nodes, ensureWrapped) : Object.create(null)
    this.styles = styles ? copyObj(styles, ensureWrapped) : Object.create(null)
  }

  updateNodes(nodes) {
    return new SchemaSpec(overlayObj(this.nodes, nodes), this.styles)
  }

  addAttribute(filter, attrName, attrInfo) {
    let copy = copyObj(this.nodes)
    for (let name in copy) {
      if (typeof filter == "string" ? filter == name :
          typeof filter == "function" ? filter(name, copy[name]) :
          filter ? filter == copy[name] : true) {
        let info = copy[name] = copyObj(copy[name])
        if (!info.attributes) info.attributes = copyObj(info.type.attributes)
        info.attributes[attrName] = attrInfo
      }
    }
    return new SchemaSpec(copy, this.styles)
  }

  updateStyles(styles) {
    return new SchemaSpec(this.nodes, overlayObj(this.styles, styles))
  }
}

// For node types where all attrs have a default value (or which don't
// have any attributes), build up a single reusable default attribute
// object, and use it for all nodes that don't specify specific
// attributes.

function getDefaultAttrs(attrs) {
  let defaults = Object.create(null)
  for (let attrName in attrs) {
    let attr = attrs[attrName]
    if (attr.default == null) return null
    defaults[attrName] = attr.default
  }
  return defaults
}

function buildAttrs(attrSpec, attrs, arg1, arg2) {
  let built = Object.create(null)
  for (let name in attrSpec) {
    let value = attrs && attrs[name]
    if (value == null) {
      let attr = attrSpec[name]
      if (attr.default != null)
        value = attr.default
      else if (attr.compute)
        value = attr.compute(arg1, arg2)
      else
        SchemaError.raise("No value supplied for attribute " + name)
    }
    built[name] = value
  }
  return built
}

/**
 * Document schema class.
 */
export class Schema {
  constructor(spec, styles) {
    if (!(spec instanceof SchemaSpec)) spec = new SchemaSpec(spec, styles)
    this.spec = spec
    this.kinds = Object.create(null)
    this.nodes = NodeType.compile(spec.nodes, this)
    this.styles = StyleType.compile(spec.styles, this)
    this.cached = Object.create(null)

    this.node = this.node.bind(this)
    this.text = this.text.bind(this)
    this.nodeFromJSON = this.nodeFromJSON.bind(this)
    this.styleFromJSON = this.styleFromJSON.bind(this)
  }

  node(type, attrs, content, styles) {
    if (typeof type == "string")
      type = this.nodeType(type)
    else if (!(type instanceof NodeType))
      SchemaError.raise("Invalid node type: " + type)
    else if (type.schema != this)
      SchemaError.raise("Node type from different schema used (" + type.name + ")")

    return type.create(attrs, content, styles)
  }

  text(text, styles) {
    return this.nodes.text.create(null, text, styles)
  }

  defaultTextblockType() {
    let cached = this.cached.defaultTextblockType
    if (cached !== undefined) return cached
    for (let name in this.nodes) {
      if (this.nodes[name].defaultTextblock)
        return this.cached.defaultTextblockType = this.nodes[name]
    }
    return this.cached.defaultTextblockType = null
  }

  style(name, attrs) {
    let spec = this.styles[name] || SchemaError.raise("No style named " + name)
    return spec.create(attrs)
  }

  nodeFromJSON(json) {
    let type = this.nodeType(json.type)
    return type.create(json.attrs,
                       json.text || (json.content && json.content.map(this.nodeFromJSON)),
                       json.styles && json.styles.map(this.styleFromJSON))
  }

  styleFromJSON(json) {
    if (typeof json == "string") return this.style(json)
    return this.style(json._, json)
  }

  nodeType(name) {
    return this.nodes[name] || SchemaError.raise("Unknown node type: " + name)
  }

  subKind(sub, sup) {
    for (;;) {
      if (sub == sup) return true
      sub = this.kinds[sub]
      if (!sub) return false
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  TouchableHighlight,
  View,
  TextInput,
  ListView,
} = React;

if (!window.navigator.userAgent) {
  window.navigator.userAgent = "react-native";
}
var io = require('socket.io-client/socket.io');

var socket = io.connect('http://react-native-webrtc.herokuapp.com', {transports: ['websocket']});

var WebRTC = require('react-native-webrtc');
var {
  RTCPeerConnection,
  RTCMediaStream,
  RTCIceCandidate,
  RTCSessionDescription,
  RTCView,
  RTCSetting,
  MediaStreamTrack,
  getUserMedia,
} = WebRTC;

var configuration = {"iceServers": [{"url": "stun:stun.l.google.com:19302"}]};

var pcPeers = {};
var localStream;

function getLocalStream(isFront, callback) {
  MediaStreamTrack.getSources(sourceInfos => {
    console.log(sourceInfos);
    var videoSourceId;
    for (var i = 0; i < sourceInfos.length; i++) {
      var sourceInfo = sourceInfos[i];
      if(sourceInfo.kind == "video" && sourceInfo.facing == (isFront ? "front" : "back")) {
        videoSourceId = sourceInfo.id;
      }
    }
    getUserMedia({
      "audio": true,
      "video": {
        optional: [{sourceId: videoSourceId}]
      }
    }, function (stream) {
      console.log('dddd', stream);
      callback(stream);
    }, logError);
  });
}

function join(roomID) {
  socket.emit('join', roomID, function(socketIds){
    console.log('join', socketIds);
    for (var i in socketIds) {
      var socketId = socketIds[i];
      createPC(socketId, true);
    }
  });
}

function createPC(socketId, isOffer) {
  var pc = new RTCPeerConnection(configuration);
  pcPeers[socketId] = pc;

  pc.onicecandidate = function (event) {
    console.log('onicecandidate', event.candidate);
    if (event.candidate) {
      socket.emit('exchange', {'to': socketId, 'candidate': event.candidate });
    }
  };

  function createOffer() {
    pc.createOffer(function(desc) {
      console.log('createOffer', desc);
      pc.setLocalDescription(desc, function () {
        console.log('setLocalDescription', pc.localDescription);
        socket.emit('exchange', {'to': socketId, 'sdp': pc.localDescription });
      }, logError);
    }, logError);
  }

  pc.onnegotiationneeded = function () {
    console.log('onnegotiationneeded');
    if (isOffer) {
      createOffer();
    }
  }

  pc.oniceconnectionstatechange = function(event) {
    console.log('oniceconnectionstatechange', event.target.iceConnectionState);
    if (event.target.iceConnectionState === 'completed') {
      setTimeout(() => {
        getStats();
      }, 1000);
    }
    if (event.target.iceConnectionState === 'connected') {
      createDataChannel();
    }
  };
  pc.onsignalingstatechange = function(event) {
    console.log('onsignalingstatechange', event.target.signalingState);
  };

  pc.onaddstream = function (event) {
    console.log('onaddstream', event.stream);
    container.setState({info: 'One peer join!'});
    peerConnected();

    var remoteList = container.state.remoteList;
    remoteList[socketId] = event.stream.toURL();
    container.setState({ remoteList: remoteList });
  };
  pc.onremovestream = function (event) {
    console.log('onremovestream', event.stream);
  };

  pc.addStream(localStream);
  function createDataChannel() {
    if (pc.textDataChannel) {
      return;
    }
    var dataChannel = pc.createDataChannel("text");

    dataChannel.onerror = function (error) {
      console.log("dataChannel.onerror", error);
    };

    dataChannel.onmessage = function (event) {
      console.log("dataChannel.onmessage:", event.data);
      container.receiveTextData({user: socketId, message: event.data});
    };

    dataChannel.onopen = function () {
      console.log('dataChannel.onopen');
      container.setState({textRoomConnected: true});
    };

    dataChannel.onclose = function () {
      console.log("dataChannel.onclose");
    };

    pc.textDataChannel = dataChannel;
  }
  return pc;
}

function exchange(data) {
  var fromId = data.from;
  var pc;
  if (fromId in pcPeers) {
    pc = pcPeers[fromId];
  } else {
    pc = createPC(fromId, false);
  }

  if (data.sdp) {
    console.log('exchange sdp', data);
    pc.setRemoteDescription(new RTCSessionDescription(data.sdp), function () {
      if (pc.remoteDescription.type == "offer")
        pc.createAnswer(function(desc) {
          console.log('createAnswer', desc);
          pc.setLocalDescription(desc, function () {
            console.log('setLocalDescription', pc.localDescription);
            socket.emit('exchange', {'to': fromId, 'sdp': pc.localDescription });
          }, logError);
        }, logError);
    }, logError);
  } else {
    console.log('exchange candidate', data);
    pc.addIceCandidate(new RTCIceCandidate(data.candidate));
  }
}

function leave(socketId) {
  console.log('leave', socketId);
  var pc = pcPeers[socketId];
  var viewIndex = pc.viewIndex;
  pc.close();
  delete pcPeers[socketId];

  var remoteList = container.state.remoteList;
  delete remoteList[socketId]
  container.setState({ remoteList: remoteList });
  container.setState({info: 'One peer leave!'});
}

socket.on('exchange', function(data){
  exchange(data);
});
socket.on('leave', function(socketId){
  leave(socketId);
});

socket.on('connect', function(data) {
  console.log('connect');
  getLocalStream(true, function(stream) {
    localStream = stream;
    container.setState({selfViewSrc: stream.toURL()});
    container.setState({status: 'ready', info: 'Please enter or create room ID'});
  });
});

function logError(error) {
  console.log("logError", error);
}

function mapHash(hash, func) {
  var array = [];
  for (var key in hash) {
    var obj = hash[key];
    array.push(func(obj, key));
  }
  return array;
}

function peerConnected() {
  RTCSetting.setAudioOutput('speaker');
  RTCSetting.setKeepScreenOn(true);
  RTCSetting.setProximityScreenOff(true);
}

function getStats() {
  var pc = pcPeers[Object.keys(pcPeers)[0]];
  if (pc.getRemoteStreams()[0] && pc.getRemoteStreams()[0].getAudioTracks()[0]) {
    var track = pc.getRemoteStreams()[0].getAudioTracks()[0];
    console.log('track', track);
    pc.getStats(track, function(report) {
      console.log('getStats report', report);
    }, logError);
  }
}

var container;

var RCTWebRTCDemo = React.createClass({
  getInitialState: function() {
    this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => true});
    return {
      info: 'Initializing',
      status: 'init',
      roomID: '',
      isFront: true,
      selfViewSrc: null,
      remoteList: {},
      textRoomConnected: false,
      textRoomData: [],
      textRoomValue: '',
    };
  },
  componentDidMount: function() {
    container = this;
  },
  _press(event) {
    this.refs.roomID.blur();
    this.setState({status: 'connect', info: 'Connecting'});
    join(this.state.roomID);
  },
  _switchVideoType() {
    var isFront = !this.state.isFront;
    this.setState({isFront});
    getLocalStream(isFront, function(stream) {
      if (localStream) {
        for (var id in pcPeers) {
          var pc = pcPeers[id];
          pc && pc.removeStream(localStream);
        }
        localStream.release();
      }
      localStream = stream;
      container.setState({selfViewSrc: stream.toURL()});

      for (var id in pcPeers) {
        var pc = pcPeers[id];
        pc && pc.addStream(localStream);
      }
    });
  },
  receiveTextData(data) {
    var textRoomData = this.state.textRoomData.slice();
    textRoomData.push(data);
    this.setState({textRoomData, textRoomValue: ''});
  },
  _textRoomPress() {
    var textRoomData = this.state.textRoomData.slice();
    textRoomData.push({user: 'Me', message: this.state.textRoomValue});
    for (var key in pcPeers) {
      var pc = pcPeers[key];
      pc.textDataChannel.send(this.state.textRoomValue);
    }
    this.setState({textRoomData, textRoomValue: ''});
  },
  _renderTextRoom() {
    return (
      <View style={styles.listViewContainer}>
        <ListView
          dataSource={this.ds.cloneWithRows(this.state.textRoomData)}
          renderRow={rowData => <Text>{`${rowData.user}: ${rowData.message}`}</Text>}
          />
        <TextInput
          style={{width: 200, height: 30, borderColor: 'gray', borderWidth: 1}}
          onChangeText={value => this.setState({textRoomValue: value})}
          value={this.state.textRoomValue}
        />
        <TouchableHighlight
          onPress={this._textRoomPress}>
          <Text>Send</Text>
        </TouchableHighlight>
      </View>
    );
  },
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          {this.state.info}
        </Text>
        {this.state.textRoomConnected && this._renderTextRoom()}
        <View style={{flexDirection: 'row'}}>
          <Text>
            {this.state.isFront ? "Use front camera" : "Use back camera"}
          </Text>
          <TouchableHighlight
            style={{borderWidth: 1, borderColor: 'black'}}
            onPress={this._switchVideoType}>
            <Text>Switch camera</Text>
          </TouchableHighlight>
        </View>
        { this.state.status == 'ready' ?
          (<View>
            <TextInput
              ref='roomID'
              autoCorrect={false}
              style={{width: 200, height: 40, borderColor: 'gray', borderWidth: 1}}
              onChangeText={(text) => this.setState({roomID: text})}
              value={this.state.roomID}
            />
            <TouchableHighlight
              onPress={this._press}>
              <Text>Enter room</Text>
            </TouchableHighlight>
          </View>) : null
        }
        <RTCView streamURL={this.state.selfViewSrc} style={styles.selfView}/>
        {
          mapHash(this.state.remoteList, function(remote, index) {
            return <RTCView key={index} streamURL={remote} style={styles.remoteView}/>
          })
        }
      </View>
    );
  }
});

var styles = StyleSheet.create({
  selfView: {
    width: 200,
    height: 150,
  },
  remoteView: {
    width: 200,
    height: 150,
  },
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  listViewContainer: {
    height: 150,
  },
});

AppRegistry.registerComponent('RCTWebRTCDemo', () => RCTWebRTCDemo);
<commit_msg>remove RTCSetting<commit_after>'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  TouchableHighlight,
  View,
  TextInput,
  ListView,
} = React;

if (!window.navigator.userAgent) {
  window.navigator.userAgent = "react-native";
}
var io = require('socket.io-client/socket.io');

var socket = io.connect('http://react-native-webrtc.herokuapp.com', {transports: ['websocket']});

var WebRTC = require('react-native-webrtc');
var {
  RTCPeerConnection,
  RTCMediaStream,
  RTCIceCandidate,
  RTCSessionDescription,
  RTCView,
  MediaStreamTrack,
  getUserMedia,
} = WebRTC;

var configuration = {"iceServers": [{"url": "stun:stun.l.google.com:19302"}]};

var pcPeers = {};
var localStream;

function getLocalStream(isFront, callback) {
  MediaStreamTrack.getSources(sourceInfos => {
    console.log(sourceInfos);
    var videoSourceId;
    for (var i = 0; i < sourceInfos.length; i++) {
      var sourceInfo = sourceInfos[i];
      if(sourceInfo.kind == "video" && sourceInfo.facing == (isFront ? "front" : "back")) {
        videoSourceId = sourceInfo.id;
      }
    }
    getUserMedia({
      "audio": true,
      "video": {
        optional: [{sourceId: videoSourceId}]
      }
    }, function (stream) {
      console.log('dddd', stream);
      callback(stream);
    }, logError);
  });
}

function join(roomID) {
  socket.emit('join', roomID, function(socketIds){
    console.log('join', socketIds);
    for (var i in socketIds) {
      var socketId = socketIds[i];
      createPC(socketId, true);
    }
  });
}

function createPC(socketId, isOffer) {
  var pc = new RTCPeerConnection(configuration);
  pcPeers[socketId] = pc;

  pc.onicecandidate = function (event) {
    console.log('onicecandidate', event.candidate);
    if (event.candidate) {
      socket.emit('exchange', {'to': socketId, 'candidate': event.candidate });
    }
  };

  function createOffer() {
    pc.createOffer(function(desc) {
      console.log('createOffer', desc);
      pc.setLocalDescription(desc, function () {
        console.log('setLocalDescription', pc.localDescription);
        socket.emit('exchange', {'to': socketId, 'sdp': pc.localDescription });
      }, logError);
    }, logError);
  }

  pc.onnegotiationneeded = function () {
    console.log('onnegotiationneeded');
    if (isOffer) {
      createOffer();
    }
  }

  pc.oniceconnectionstatechange = function(event) {
    console.log('oniceconnectionstatechange', event.target.iceConnectionState);
    if (event.target.iceConnectionState === 'completed') {
      setTimeout(() => {
        getStats();
      }, 1000);
    }
    if (event.target.iceConnectionState === 'connected') {
      createDataChannel();
    }
  };
  pc.onsignalingstatechange = function(event) {
    console.log('onsignalingstatechange', event.target.signalingState);
  };

  pc.onaddstream = function (event) {
    console.log('onaddstream', event.stream);
    container.setState({info: 'One peer join!'});

    var remoteList = container.state.remoteList;
    remoteList[socketId] = event.stream.toURL();
    container.setState({ remoteList: remoteList });
  };
  pc.onremovestream = function (event) {
    console.log('onremovestream', event.stream);
  };

  pc.addStream(localStream);
  function createDataChannel() {
    if (pc.textDataChannel) {
      return;
    }
    var dataChannel = pc.createDataChannel("text");

    dataChannel.onerror = function (error) {
      console.log("dataChannel.onerror", error);
    };

    dataChannel.onmessage = function (event) {
      console.log("dataChannel.onmessage:", event.data);
      container.receiveTextData({user: socketId, message: event.data});
    };

    dataChannel.onopen = function () {
      console.log('dataChannel.onopen');
      container.setState({textRoomConnected: true});
    };

    dataChannel.onclose = function () {
      console.log("dataChannel.onclose");
    };

    pc.textDataChannel = dataChannel;
  }
  return pc;
}

function exchange(data) {
  var fromId = data.from;
  var pc;
  if (fromId in pcPeers) {
    pc = pcPeers[fromId];
  } else {
    pc = createPC(fromId, false);
  }

  if (data.sdp) {
    console.log('exchange sdp', data);
    pc.setRemoteDescription(new RTCSessionDescription(data.sdp), function () {
      if (pc.remoteDescription.type == "offer")
        pc.createAnswer(function(desc) {
          console.log('createAnswer', desc);
          pc.setLocalDescription(desc, function () {
            console.log('setLocalDescription', pc.localDescription);
            socket.emit('exchange', {'to': fromId, 'sdp': pc.localDescription });
          }, logError);
        }, logError);
    }, logError);
  } else {
    console.log('exchange candidate', data);
    pc.addIceCandidate(new RTCIceCandidate(data.candidate));
  }
}

function leave(socketId) {
  console.log('leave', socketId);
  var pc = pcPeers[socketId];
  var viewIndex = pc.viewIndex;
  pc.close();
  delete pcPeers[socketId];

  var remoteList = container.state.remoteList;
  delete remoteList[socketId]
  container.setState({ remoteList: remoteList });
  container.setState({info: 'One peer leave!'});
}

socket.on('exchange', function(data){
  exchange(data);
});
socket.on('leave', function(socketId){
  leave(socketId);
});

socket.on('connect', function(data) {
  console.log('connect');
  getLocalStream(true, function(stream) {
    localStream = stream;
    container.setState({selfViewSrc: stream.toURL()});
    container.setState({status: 'ready', info: 'Please enter or create room ID'});
  });
});

function logError(error) {
  console.log("logError", error);
}

function mapHash(hash, func) {
  var array = [];
  for (var key in hash) {
    var obj = hash[key];
    array.push(func(obj, key));
  }
  return array;
}

function getStats() {
  var pc = pcPeers[Object.keys(pcPeers)[0]];
  if (pc.getRemoteStreams()[0] && pc.getRemoteStreams()[0].getAudioTracks()[0]) {
    var track = pc.getRemoteStreams()[0].getAudioTracks()[0];
    console.log('track', track);
    pc.getStats(track, function(report) {
      console.log('getStats report', report);
    }, logError);
  }
}

var container;

var RCTWebRTCDemo = React.createClass({
  getInitialState: function() {
    this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => true});
    return {
      info: 'Initializing',
      status: 'init',
      roomID: '',
      isFront: true,
      selfViewSrc: null,
      remoteList: {},
      textRoomConnected: false,
      textRoomData: [],
      textRoomValue: '',
    };
  },
  componentDidMount: function() {
    container = this;
  },
  _press(event) {
    this.refs.roomID.blur();
    this.setState({status: 'connect', info: 'Connecting'});
    join(this.state.roomID);
  },
  _switchVideoType() {
    var isFront = !this.state.isFront;
    this.setState({isFront});
    getLocalStream(isFront, function(stream) {
      if (localStream) {
        for (var id in pcPeers) {
          var pc = pcPeers[id];
          pc && pc.removeStream(localStream);
        }
        localStream.release();
      }
      localStream = stream;
      container.setState({selfViewSrc: stream.toURL()});

      for (var id in pcPeers) {
        var pc = pcPeers[id];
        pc && pc.addStream(localStream);
      }
    });
  },
  receiveTextData(data) {
    var textRoomData = this.state.textRoomData.slice();
    textRoomData.push(data);
    this.setState({textRoomData, textRoomValue: ''});
  },
  _textRoomPress() {
    if (!this.state.textRoomValue) {
      return
    }
    var textRoomData = this.state.textRoomData.slice();
    textRoomData.push({user: 'Me', message: this.state.textRoomValue});
    for (var key in pcPeers) {
      var pc = pcPeers[key];
      pc.textDataChannel.send(this.state.textRoomValue);
    }
    this.setState({textRoomData, textRoomValue: ''});
  },
  _renderTextRoom() {
    return (
      <View style={styles.listViewContainer}>
        <ListView
          dataSource={this.ds.cloneWithRows(this.state.textRoomData)}
          renderRow={rowData => <Text>{`${rowData.user}: ${rowData.message}`}</Text>}
          />
        <TextInput
          style={{width: 200, height: 30, borderColor: 'gray', borderWidth: 1}}
          onChangeText={value => this.setState({textRoomValue: value})}
          value={this.state.textRoomValue}
        />
        <TouchableHighlight
          onPress={this._textRoomPress}>
          <Text>Send</Text>
        </TouchableHighlight>
      </View>
    );
  },
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          {this.state.info}
        </Text>
        {this.state.textRoomConnected && this._renderTextRoom()}
        <View style={{flexDirection: 'row'}}>
          <Text>
            {this.state.isFront ? "Use front camera" : "Use back camera"}
          </Text>
          <TouchableHighlight
            style={{borderWidth: 1, borderColor: 'black'}}
            onPress={this._switchVideoType}>
            <Text>Switch camera</Text>
          </TouchableHighlight>
        </View>
        { this.state.status == 'ready' ?
          (<View>
            <TextInput
              ref='roomID'
              autoCorrect={false}
              style={{width: 200, height: 40, borderColor: 'gray', borderWidth: 1}}
              onChangeText={(text) => this.setState({roomID: text})}
              value={this.state.roomID}
            />
            <TouchableHighlight
              onPress={this._press}>
              <Text>Enter room</Text>
            </TouchableHighlight>
          </View>) : null
        }
        <RTCView streamURL={this.state.selfViewSrc} style={styles.selfView}/>
        {
          mapHash(this.state.remoteList, function(remote, index) {
            return <RTCView key={index} streamURL={remote} style={styles.remoteView}/>
          })
        }
      </View>
    );
  }
});

var styles = StyleSheet.create({
  selfView: {
    width: 200,
    height: 150,
  },
  remoteView: {
    width: 200,
    height: 150,
  },
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  listViewContainer: {
    height: 150,
  },
});

AppRegistry.registerComponent('RCTWebRTCDemo', () => RCTWebRTCDemo);
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react'
import Helmet from 'react-helmet'
import CSSModules from 'react-css-modules'

import withData from 'hocs/withData'
import withPage from 'hocs/withPage'
import { fetchData1 } from 'modules/post/postActions'

import ErrorPage from 'noxt/app/pages/ErrorPage'

import styles from 'styles/pages/Homepage.scss'

@withData(({ post, error }) => ({ post, error }), [ fetchData1 ])
@withPage()
@CSSModules(styles)
class HomePage extends Component {
  render () {
    const { post, error } = this.props
    if (error !== false) {
      return <ErrorPage status={error.status} message={error.message} />
    }
    return (

        <Helmet
          title="Home"
          meta={[
            {
              name: 'description',
              content: 'This is homepage.'
            }
          ]}
        />
        HomePage

{post.login}

    )
  }
}

HomePage.propTypes = {
  post: PropTypes.shape({
    login: PropTypes.string.isRequired
  }),
  error: PropTypes.shape({
    status: PropTypes.string.isRequired,
    message: PropTypes.string.isRequired
  })
}

export default HomePage
<commit_msg>disable unused code<commit_after>import React, {Component, PropTypes} from 'react'
import Helmet from 'react-helmet'
import CSSModules from 'react-css-modules'

import withData from 'hocs/withData'
import withPage from 'hocs/withPage'
import { fetchData1 } from 'modules/post/postActions'

import ErrorPage from 'noxt/app/pages/ErrorPage'

// import styles from 'styles/pages/Homepage.scss'

// @withData(({ post, error }) => ({ post, error }), [ fetchData1 ])
// @withPage()
// @CSSModules(styles)
class HomePage extends Component {
  render () {
    const { post, error } = this.props
    if (error !== false) {
      return <ErrorPage status={error.status} message={error.message} />
    }
    return (

        <Helmet
          title="Home"
          meta={[
            {
              name: 'description',
              content: 'This is homepage.'
            }
          ]}
        />
        HomePage

{post.login}

    )
  }
}

HomePage.propTypes = {
  post: PropTypes.shape({
    login: PropTypes.string.isRequired
  }),
  error: PropTypes.shape({
    status: PropTypes.string.isRequired,
    message: PropTypes.string.isRequired
  })
}

export default HomePage
<|endoftext|>


<commit_before>const {app, Menu, Tray, clipboard} = require('electron')
const autostart = require('node-autostart')
const ping  = require('ping')

let tray = null
let contextMenu = null
let intervalID = null
let startOnLogin = null

let pingHistory = []
let pingingEnabled = true

let averageLatency = 'No Returned Pings'

const config = {};
config.pingInterval = 5000
config.server = 'www.google.com'
config.maxPingsToKeep = 20

const goodLatencyThreshold = 100
const questionableLatencyThreshold = 500

const goodLatencyIcon = 'images/running-good@2x.png'
const questionableLatencyIcon = 'images/running-questionable@2x.png'
const badLatencyIcon = 'images/running-bad@2x.png'
const pausedIcon = 'images/paused@2x.png'

app.dock.hide()

app.on('ready', () => {
  tray = new Tray(questionableLatencyIcon)
  tray.setToolTip('am-i-connected')

  getAutostartStatus()

  pingEveryInterval()
})

function averageLatencyMenuItem() {
  return {label: 'Average Latency: ' + averageLatency, enabled: false};
}

function copyPingHistoryMenuItem() {
  return {label: 'Copy Ping History', click: function () {
    clipboardString = ''
    for (let ping of pingHistory)
      clipboardString += ping.label + '\n'
    clipboard.writeText(clipboardString)
  }};
}

function pingHistoryMenuItem() {
  return {label: 'Ping History', submenu: pingHistory}
}

function separator() {
  return {type: 'separator'}
}

function displayServerMenuItem() {
  return {label: 'Server: ' + config.server, enabled: false};
}

function switchServerMenuItem() {
  return {label: 'Switch to Server on Clipboard', click: function () {
    config.server = clipboard.readText()
    pingHistory = []
    averageLatency = 'No Returned Pings'
    tray.setImage(questionableLatencyIcon)
    buildMenu()
  }}
}

function pauseMenuItem() {
  return {label: pingingEnabled ? 'Pause' : 'Unpause', click: function () {
    if (pingingEnabled) {
      pingingEnabled = false
      tray.setImage(pausedIcon)
      clearInterval(intervalID)
    } else {
      pingingEnabled = true
      pingEveryInterval()
    }
    buildMenu()
  }}
}

function startOnLoginMenuItem() {
  return {label: (startOnLogin ? 'Disable' : 'Enable') + ' Start on Login', click: function () {
    if (startOnLogin) {
      autostart.disableAutostart('thisApp').then(() => {
        startOnLogin = false
      }).catch((error) => {
        console.error(error)
      })
    } else {
      autostart.enableAutostart('thisApp', 'node start', process.cwd()).then(() => {
        startOnLogin = true
      }).catch((error) => {
        console.error(error)
      })
    }
    startOnLogin = startOnLogin ? false : true
    buildMenu()
  }}
}

function quitMenuItem() {
  return {label: 'Quit', role: 'quit'}
}

function buildMenu () {
  contextMenu = Menu.buildFromTemplate([
    averageLatencyMenuItem(),
    copyPingHistoryMenuItem(),
    pingHistoryMenuItem(),
    separator(),

    displayServerMenuItem(),
    switchServerMenuItem(),
    separator(),

    pauseMenuItem(),
    startOnLoginMenuItem(),
    separator(),

    quitMenuItem()
  ])
  tray.setContextMenu(contextMenu)
}

// Excludes unreturned pings
function calculateAverageLatency() {
  let pingSum = 0
  let numReturnedPings = 0
  for (let ping of pingHistory) {
    if (typeof parseInt(ping.label) === 'number') {
      pingSum += parseInt(ping.label)
      numReturnedPings++
    }
  }
  averageLatency = numReturnedPings > 0 ? (pingSum / numReturnedPings).toFixed() + ' ms'  : 'No Returned Pings'
  return averageLatency;
}

function updateAverageLatency () {
  const averageLatency = calculateAverageLatency();

  latencyIsGood = parseInt(averageLatency) < goodLatencyThreshold
  latencyisQuestionable = parseInt(averageLatency) < questionableLatencyThreshold
  if (latencyIsGood) {
    tray.setImage(goodLatencyIcon)
  } else if (latencyisQuestionable) {
    tray.setImage(questionableLatencyIcon)
  } else {
    tray.setImage(badLatencyIcon)
  }
}

function pingEveryInterval () {
  intervalID = setInterval(doThePing, config.pingInterval)
}

function doThePing() {
  ping.promise.probe(config.server, {min_reply: 1}).then(function(pingResponse) {
    putResponseIntoHistory(pingResponse);

    updateAverageLatency();

    buildMenu();
  })
}

function putResponseIntoHistory(pingResponse) {
  pingHistory.push({label: pingResponse.time.toFixed().toString()})
  if (pingHistory.length > config.maxPingsToKeep)
    pingHistory.splice(0, pingHistory.length - config.maxPingsToKeep)
}

function getAutostartStatus() {
  autostart.isAutostartEnabled('thisApp').then((isEnabled) => {
    startOnLogin = isEnabled
    buildMenu()
  }).catch((error) => {
    console.error(error)
    buildMenu()
  })
}
<commit_msg>(m) whitespace<commit_after>const {app, Menu, Tray, clipboard} = require('electron')
const autostart = require('node-autostart')
const ping  = require('ping')

let tray = null
let contextMenu = null
let intervalID = null
let startOnLogin = null

let pingHistory = []
let pingingEnabled = true

let averageLatency = 'No Returned Pings'

const config = {};
config.pingInterval = 5000
config.server = 'www.google.com'
config.maxPingsToKeep = 20

const goodLatencyThreshold = 100
const questionableLatencyThreshold = 500

const goodLatencyIcon = 'images/running-good@2x.png'
const questionableLatencyIcon = 'images/running-questionable@2x.png'
const badLatencyIcon = 'images/running-bad@2x.png'
const pausedIcon = 'images/paused@2x.png'

app.dock.hide()

app.on('ready', () => {
  tray = new Tray(questionableLatencyIcon)
  tray.setToolTip('am-i-connected')

  getAutostartStatus()

  pingEveryInterval()
})

function averageLatencyMenuItem() {
  return {label: 'Average Latency: ' + averageLatency, enabled: false};
}

function copyPingHistoryMenuItem() {
  return {label: 'Copy Ping History', click: function () {
    clipboardString = ''
    for (let ping of pingHistory)
      clipboardString += ping.label + '\n'
    clipboard.writeText(clipboardString)
  }};
}

function pingHistoryMenuItem() {
  return {label: 'Ping History', submenu: pingHistory}
}

function separator() {
  return {type: 'separator'}
}

function displayServerMenuItem() {
  return {label: 'Server: ' + config.server, enabled: false};
}

function switchServerMenuItem() {
  return {label: 'Switch to Server on Clipboard', click: function () {
    config.server = clipboard.readText()
    pingHistory = []
    averageLatency = 'No Returned Pings'
    tray.setImage(questionableLatencyIcon)
    buildMenu()
  }}
}

function pauseMenuItem() {
  return {label: pingingEnabled ? 'Pause' : 'Unpause', click: function () {
    if (pingingEnabled) {
      pingingEnabled = false
      tray.setImage(pausedIcon)
      clearInterval(intervalID)
    } else {
      pingingEnabled = true
      pingEveryInterval()
    }
    buildMenu()
  }}
}

function startOnLoginMenuItem() {
  return {label: (startOnLogin ? 'Disable' : 'Enable') + ' Start on Login', click: function () {
    if (startOnLogin) {
      autostart.disableAutostart('thisApp').then(() => {
        startOnLogin = false
      }).catch((error) => {
        console.error(error)
      })
    } else {
      autostart.enableAutostart('thisApp', 'node start', process.cwd()).then(() => {
        startOnLogin = true
      }).catch((error) => {
        console.error(error)
      })
    }
    startOnLogin = startOnLogin ? false : true
    buildMenu()
  }}
}

function quitMenuItem() {
  return {label: 'Quit', role: 'quit'}
}

function buildMenu () {
  contextMenu = Menu.buildFromTemplate([
    averageLatencyMenuItem(),
    copyPingHistoryMenuItem(),
    pingHistoryMenuItem(),
    separator(),

    displayServerMenuItem(),
    switchServerMenuItem(),
    separator(),

    pauseMenuItem(),
    startOnLoginMenuItem(),
    separator(),

    quitMenuItem()
  ])
  tray.setContextMenu(contextMenu)
}

// Excludes unreturned pings
function calculateAverageLatency() {
  let pingSum = 0
  let numReturnedPings = 0
  for (let ping of pingHistory) {
    if (typeof parseInt(ping.label) === 'number') {
      pingSum += parseInt(ping.label)
      numReturnedPings++
    }
  }
  averageLatency = numReturnedPings > 0 ? (pingSum / numReturnedPings).toFixed() + ' ms'  : 'No Returned Pings'
  return averageLatency;
}

function updateAverageLatency () {
  const averageLatency = calculateAverageLatency();

  latencyIsGood = parseInt(averageLatency) < goodLatencyThreshold
  latencyisQuestionable = parseInt(averageLatency) < questionableLatencyThreshold
  if (latencyIsGood) {
    tray.setImage(goodLatencyIcon)
  } else if (latencyisQuestionable) {
    tray.setImage(questionableLatencyIcon)
  } else {
    tray.setImage(badLatencyIcon)
  }
}

function pingEveryInterval () {
  intervalID = setInterval(doThePing, config.pingInterval)
}

function doThePing() {
  ping.promise.probe(config.server, {min_reply: 1}).then(function(pingResponse) {
    putResponseIntoHistory(pingResponse);
    updateAverageLatency();
    buildMenu();
  })
}

function putResponseIntoHistory(pingResponse) {
  pingHistory.push({label: pingResponse.time.toFixed().toString()})
  if (pingHistory.length > config.maxPingsToKeep)
    pingHistory.splice(0, pingHistory.length - config.maxPingsToKeep)
}

function getAutostartStatus() {
  autostart.isAutostartEnabled('thisApp').then((isEnabled) => {
    startOnLogin = isEnabled
    buildMenu()
  }).catch((error) => {
    console.error(error)
    buildMenu()
  })
}
<|endoftext|>


<commit_before>var out;

$( document ).ready(function() {
	$( "form#wiki" ).submit(function( event ) {
		event.preventDefault();
		var start_article = $(this).find("input[type=text]").val();
		console.log( "Start: ", start_article );
		getWikiSentence(start_article);
	});

	/* Returns the query URL for the Wikipedia API of a given page */
	function wikiApiUrl(page) {
		var wiki_api_base = "https://en.wikipedia.org/w/api.php?"
		params = {
			action: "parse",
			format: "json",
			page: page,
			redirects: 1,
			prop: "text",
			section: 0,
			disablelimitreport: 1,
			disableeditsection: 1,
			disabletoc: 1,
			noimages: 1
		}
		/* "callback=?" makes jquery pick a custom name for the callback.
		JQuery then knows to set the datatype to JSONP.
		The server wraps the requested JSON in a function call with the callback's name.*/
		return wiki_api_base + $.param(params) + "&callback=?";
	}

	/* Returns a parsed structure queryable with JQuery from an HTML string */
	function parseToDOM(html_string) {
		return $($.parseHTML('
' + html_string + '
'));
	}

	var done = [];
	function getWikiSentence(page_title){
		query_url = wikiApiUrl(page_title);
		console.log(query_url);
		$.getJSON( query_url )
			.done(function(data) {
				console.log("GET success");
				out = parseToDOM(data.parse.text["*"]);

				out.children('p').children('sup').remove();
				// The box showing coordinates is part of the main html
				out.children('p').find('span#coordinates').remove();
				html = '';
				out.children('p').each(function() { html += $(this).html() + ' '; });
				var divider = '.';
				split = html.split(divider);
				if ( split.length == 1 ) {
					divider = ').';
					split = html.split(divider);
					if ( split.length == 1 ) {
						console.log('No link at the end of a sentence found.')
						return
					}
				}
				console.log(split[0]);
				var sentence = parseToDOM(split[0] + divider);
				var last_a = sentence.children('a:last');

				var next_entry = last_a.attr('href').split('/wiki/')[1];
				var next_entry_title = last_a.attr('title');
				console.log('Next: ', next_entry_title);
				$('#articles').append($('
').text(sentence.text()));
				if ( done.indexOf(next_entry) > -1 ) {
					console.log('Repition detected.')
					return
				}
				done.push(next_entry);
				getWikiSentence(next_entry_title);
			})
			.fail(function() {
				console.log("Error: ", query);
			});
	}
});

<commit_msg>Reset on new query.<commit_after>var out;

$( document ).ready(function() {
	var pageids = [];
	$( "form#wiki" ).submit(function( event ) {
		event.preventDefault();
		var start_article = $(this).find("input[type=text]").val();
		console.log( "Start: ", start_article );
		pageids = [];
		$('#articles').empty();
		getWikiSentence(start_article);
	});

	/* Returns the query URL for the Wikipedia API of a given page */
	function wikiApiUrl(page) {
		var wiki_api_base = "https://en.wikipedia.org/w/api.php?"
		params = {
			action: "parse",
			format: "json",
			page: page,
			redirects: 1,
			prop: "text",
			section: 0,
			disablelimitreport: 1,
			disableeditsection: 1,
			disabletoc: 1,
			noimages: 1
		}
		/* "callback=?" makes jquery pick a custom name for the callback.
		JQuery then knows to set the datatype to JSONP.
		The server wraps the requested JSON in a function call with the callback's name.*/
		return wiki_api_base + $.param(params) + "&callback=?";
	}

	/* Returns a parsed structure queryable with JQuery from an HTML string */
	function parseToDOM(html_string) {
		return $($.parseHTML('
' + html_string + '
'));
	}

	function getWikiSentence(page_title){
		query_url = wikiApiUrl(page_title);
		console.log(query_url);
		$.getJSON( query_url )
			.done(function(data) {
				console.log("GET success");
				out = parseToDOM(data.parse.text["*"]);

				out.children('p').children('sup').remove();
				// The box showing coordinates is part of the main html
				out.children('p').find('span#coordinates').remove();
				html = '';
				out.children('p').each(function() { html += $(this).html() + ' '; });
				var divider = '.';
				split = html.split(divider);
				if ( split.length == 1 ) {
					divider = ').';
					split = html.split(divider);
					if ( split.length == 1 ) {
						console.log('No link at the end of a sentence found.')
						return
					}
				}
				console.log(split[0]);
				var sentence = parseToDOM(split[0] + divider);
				var last_a = sentence.children('a:last');

				var next_entry = last_a.attr('href').split('/wiki/')[1];
				var next_entry_title = last_a.attr('title');
				console.log('Next: ', next_entry_title);
				$('#articles').append($('
').text(sentence.text()));
				var current_pageid = data.parse.pageid;
				if ( pageids.indexOf(current_pageid) > -1 ) {
					console.log('Repition detected.')
					return
				}
				pageids.push(current_pageid);
				getWikiSentence(next_entry_title);
			})
			.fail(function() {
				console.log("Error: ", query);
			});
	}
});

<|endoftext|>


<commit_before>'use strict';

const queries = require('./database/queries');
const render = require('./render');
const bluebird = require('bluebird');
const bcrypt = require('bcryptjs');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

async function registerUser(req, res) {
  try {
    const hash = await bluebird.promisify(bcrypt.hash)(req.body.password, 10);
    logger.debug('Successsful password hash', hash);
    const insertResult = await queries.insertUser(req.body.username, req.body.email, hash);
    logger.info('Successsful registration', req.body.username, req.body.email);
    req.login({email: req.body.email}, err => {
      if (err) {
        logger.error('Could not auth registered user', err);
        return res.status(200).json({}); // Sweep it under the rug
      }
      res.status(200).json({});
    });
  } catch (err) {
    logger.error('Registration error', err);
    res.status(500).json({err: 'internal error'});
  }
}

passport.use(new LocalStrategy({
  usernameField: 'email',
  passwordField: 'password'
}, async (email, password, done) => {
  try {
    const query = await queries.getUser(email);
    if (query.rowCount === 0) {
      logger.info('No such email', email);
      return done(null, false, {message: 'no such email'});
    }
    // There can only be one row because emails are unique
    const user = query.rows[0];
    const doesMatch = await bcrypt.compare(password, user.hash);
    if (doesMatch) {
      logger.debug('Passwords match', email);
      done(null, user);
    } else {
      logger.info('Passwords don\'t match');
      done(null, false, {message: 'bad password'});
    }
  } catch (err) {
    if (err.kind === 'pg-query') {
      logger.error('Cannot find user', err);
      done(null, false, {message: 'bad email'});
    } else {
      logger.error('Unknown error', err);
      done(err);
    }
  }
}));

function authenticateUser(req, res, next) {
  return passport.authenticate('local', (err, user, info) => {
    if (err) {
      logger.error('Auth err', err);
      return res.status(500).json({err: 'internal error'});
    }
    if (!user) {
      logger.info('Login attempt failed', user, info.message);
      res.status(401);
      return res.json({err: info.message});
    }
    req.login(user, err => {
      if (err) {
        logger.error('Login error', err);
        return next(err);
      }
      logger.debug('Login success', user);
      res.status(200).json({});
    });
  })(req, res, next);
}

passport.serializeUser((user, done) => {
  done(null, user.email);
});

passport.deserializeUser(async (email, done) => {
  try {
    const user = await queries.getUser(email);
    done(null, user.rows[0]);
  } catch (e) {
    logger.error('Cannot find user email', email, e);
    done(e, null);
  }
});

module.exports = {
  registerUser,
  authenticateUser
};
<commit_msg>Fix redundancy<commit_after>'use strict';

const queries = require('./database/queries');
const render = require('./render');
const bluebird = require('bluebird');
const bcrypt = require('bcryptjs');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

async function registerUser(req, res) {
  try {
    const hash = await bluebird.promisify(bcrypt.hash)(req.body.password, 10);
    logger.debug('Successsful password hash', hash);
    const insertResult = await queries.insertUser(req.body.username, req.body.email, hash);
    logger.info('Successsful registration', req.body.username, req.body.email);
    req.login({email: req.body.email}, err => {
      if (err) {
        logger.error('Could not auth registered user', err);
        return res.status(200).json({}); // Sweep it under the rug
      }
      res.status(200).json({});
    });
  } catch (err) {
    logger.error('Registration error', err);
    res.status(500).json({err: 'internal error'});
  }
}

passport.use(new LocalStrategy({
  usernameField: 'email',
  passwordField: 'password'
}, async (email, password, done) => {
  try {
    const query = await queries.getUser(email);
    if (query.rowCount === 0) {
      logger.info('No such email', email);
      return done(null, false, {message: 'no such email'});
    }
    // There can only be one row because emails are unique
    const user = query.rows[0];
    const doesMatch = await bcrypt.compare(password, user.hash);
    if (doesMatch) {
      logger.debug('Passwords match', email);
      done(null, user);
    } else {
      logger.info('Passwords don\'t match');
      done(null, false, {message: 'bad password'});
    }
  } catch (err) {
    if (err.kind === 'pg-query') {
      logger.error('Cannot find user', err);
      done(null, false, {message: 'bad email'});
    } else {
      logger.error('Unknown error', err);
      done(err);
    }
  }
}));

function authenticateUser(req, res, next) {
  return passport.authenticate('local', (err, user, info) => {
    if (err) {
      logger.error('Auth err', err);
      return res.status(500).json({err: 'internal error'});
    }
    if (!user) {
      logger.info('Login attempt failed', user, info.message);
      return res.status(401).json({err: info.message});
    }
    req.login(user, err => {
      if (err) {
        logger.error('Login error', err);
        return next(err);
      }
      logger.debug('Login success', user);
      res.status(200).json({});
    });
  })(req, res, next);
}

passport.serializeUser((user, done) => {
  done(null, user.email);
});

passport.deserializeUser(async (email, done) => {
  try {
    const user = await queries.getUser(email);
    done(null, user.rows[0]);
  } catch (e) {
    logger.error('Cannot find user email', email, e);
    done(e, null);
  }
});

module.exports = {
  registerUser,
  authenticateUser
};
<|endoftext|>


<commit_before>var fs = require('fs')
var path = require('path')
var mkdirp = require('mkdirp')

var noop = function() {}

var read = function(file, offset, length, cb) {
  var buf = new Buffer(length)
  fs.open(file, 'r', function(err, fd) {
    if (err) return cb(err)
    fs.read(fd, buf, 0, length, offset, function(err, bytes, buf){
      fs.close(fd, function() {
        cb(err, buf)
      })
    })
  })
}

module.exports = function(folder) {
  if (!folder) folder = '.'
  return function(torrent) {
    folder = path.join(folder, torrent.infoHash)
    mkdirp.sync(folder)

    var that = {}
    var max = Array(Math.ceil(Math.log(torrent.pieces.length)/Math.log(10))+1).join('0')

    var pad = function(n) {
      n += ''
      if (n.length < max) return max.slice(n.length) + n
      return n
    }

    var toName = function(i) {
      return path.join(folder, pad(i))
    }

    that.read = function(index, range, cb) {
      if (typeof range === 'function') return that.read(index, null, range)
      if (!range) range = {}

      if (index >= torrent.pieces.length) return cb(new Error('Invalid piece'))

      var name = toName(index)
      var offset = range.offset || 0
      var length = range.length

      if (length !== undefined) return read(name, offset, length, cb)

      fs.stat(name, function(err, stat) {
        if (err) return cb(err)
        read(name, offset, stat.size - offset, cb)
      })
    }

    that.write = function(index, buf, cb) {
      fs.writeFile(toName(index), buf, cb || noop)
    }

    that.remove = function(cb) {
      if (!cb) cb = noop
      fs.readdir(folder, function(_, files) {
        if (!files) return cb()

        files = files.filter(function(file) {
          return /^\d+\.piece$/.test(file)
        })

        var loop = function() {
          var file = files.shift()
          if (!file) return cb()
          fs.unlink(path.join(folder, file), loop)
        }

        loop()
      })
    }

    return that
  }
}<commit_msg>fix some bugs<commit_after>var fs = require('fs')
var path = require('path')
var mkdirp = require('mkdirp')

var noop = function() {}

var read = function(file, offset, length, cb) {
  var buf = new Buffer(length)
  fs.open(file, 'r', function(err, fd) {
    if (err) return cb(err)
    fs.read(fd, buf, 0, length, offset, function(err, bytes, buf){
      fs.close(fd, function() {
        cb(err, buf)
      })
    })
  })
}

module.exports = function(folder) {
  if (!folder) folder = '.'
  return function(torrent) {
    folder = path.join(folder, torrent.infoHash)
    mkdirp.sync(folder)

    var that = {}
    var max = Array(Math.ceil(Math.log(torrent.pieces.length)/Math.log(10))+1).join('0')

    var pad = function(n) {
      n += ''
      if (n.length < max.length) return max.slice(n.length) + n
      return n
    }

    var toName = function(i) {
      return path.join(folder, pad(i)+'.piece')
    }

    that.read = function(index, range, cb) {
      if (typeof range === 'function') return that.read(index, null, range)
      if (!range) range = {}

      if (index >= torrent.pieces.length) return cb(new Error('Invalid piece'))

      var name = toName(index)
      var offset = range.offset || 0
      var length = range.length

      if (length !== undefined) return read(name, offset, length, cb)

      fs.stat(name, function(err, stat) {
        if (err) return cb(err)
        read(name, offset, stat.size - offset, cb)
      })
    }

    that.write = function(index, buf, cb) {
      fs.writeFile(toName(index), buf, cb || noop)
    }

    that.remove = function(cb) {
      if (!cb) cb = noop
      fs.readdir(folder, function(_, files) {
        if (!files) return cb()

        files = files.filter(function(file) {
          return /^\d+\.piece$/.test(file)
        })

        var loop = function() {
          var file = files.shift()
          if (!file) return cb()
          fs.unlink(path.join(folder, file), loop)
        }

        loop()
      })
    }

    return that
  }
}<|endoftext|>


<commit_before>/* @flow */

import React, { PropTypes } from 'react'
import {
  StyleSheet,
  View,
  TouchableHighlight,
  RecyclerViewBackedScrollView,
  ListView,
  Text,
} from 'react-native'

const styles = StyleSheet.create({
  row: {
    flexDirection: 'row',
    justifyContent: 'center',
    padding: 10,
    backgroundColor: '#F6F6F6',
  },
  separator: {
    height: 1,
    backgroundColor: '#CCCCCC',
  },
  text: {
    flex: 1,
  },
})

export default React.createClass({
  propTypes: {
    isFetching: PropTypes.bool,
    patientList: PropTypes.arrayOf(PropTypes.shape({
      _id: PropTypes.string.isRequired,
    })).isRequired,
    onPatientSelect: PropTypes.func.isRequired,
  },

  getInitialState() {
    let ds = new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2
    })

    return {
      ds: ds.cloneWithRows(this.props.patientList || []),
    }
  },

  componentWillMount() {
    this.props.fetchPatientList()
  },

  componentWillReceiveProps(nextProps: Object) {
    if (nextProps.patientList !== this.props.patientList) {
      this.setState({
        ds: this.state.ds.cloneWithRows(nextProps.patientList || [])
      })
    }
  },

  _renderRow(rowData: Object, sectionID: number, rowID: number, highlightRow: (sectionID: number, rowID: number) => void) {
    return (
      <TouchableHighlight onPress={() => {
        this.props.onPatientSelect(rowData._id)
        highlightRow(sectionID, rowID);
      }}>
        <View>
          <View style={styles.row}>
            <Text style={styles.text}>
              {rowData.name}
            </Text>
          </View>
        </View>
      </TouchableHighlight>
    )
  },

  render() {
    const {
      isFetching,
    } = this.props

    if (isFetching) {
      return <Text>Fetching patient list...</Text>
    }

    return (
      <ListView
        dataSource={this.state.ds}
        renderRow={this._renderRow}
        renderScrollComponent={props => <RecyclerViewBackedScrollView {...props} />}
        renderSeparator={(sectionID, rowID) => <View key={`${sectionID}-${rowID}`} style={styles.separator} />}
        enableEmptySections={true}
      />
    )
  },
})
<commit_msg>(refs #23) Add change listener to PatientList on native app<commit_after>/* @flow */

import React, { PropTypes } from 'react'
import {
  StyleSheet,
  View,
  TouchableHighlight,
  RecyclerViewBackedScrollView,
  ListView,
  Text,
} from 'react-native'

const styles = StyleSheet.create({
  row: {
    flexDirection: 'row',
    justifyContent: 'center',
    padding: 10,
    backgroundColor: '#F6F6F6',
  },
  separator: {
    height: 1,
    backgroundColor: '#CCCCCC',
  },
  text: {
    flex: 1,
  },
})

export default React.createClass({
  propTypes: {
    isFetching: PropTypes.bool,
    patientList: PropTypes.arrayOf(PropTypes.shape({
      _id: PropTypes.string.isRequired,
    })).isRequired,
    onPatientSelect: PropTypes.func.isRequired,
  },

  getInitialState() {
    let ds = new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2
    })

    return {
      ds: ds.cloneWithRows(this.props.patientList || []),
    }
  },

  componentWillMount() {
    this.props.fetchPatientList()
    const change = this.props.subscribeChange()
    this.setState({change: change})
  },

  componentWillUnmount() {
    if (this.state.change) {
      this.state.change.cancel()
      this.setState({change: null})
    }
  },

  componentWillReceiveProps(nextProps: Object) {
    if (nextProps.patientList !== this.props.patientList) {
      this.setState({
        ds: this.state.ds.cloneWithRows(nextProps.patientList || [])
      })
    }
  },

  _renderRow(rowData: Object, sectionID: number, rowID: number, highlightRow: (sectionID: number, rowID: number) => void) {
    return (
      <TouchableHighlight onPress={() => {
        this.props.onPatientSelect(rowData._id)
        highlightRow(sectionID, rowID);
      }}>
        <View>
          <View style={styles.row}>
            <Text style={styles.text}>
              {rowData.name}
            </Text>
          </View>
        </View>
      </TouchableHighlight>
    )
  },

  render() {
    const {
      isFetching,
    } = this.props

    if (isFetching) {
      return <Text>Fetching patient list...</Text>
    }

    return (
      <ListView
        dataSource={this.state.ds}
        renderRow={this._renderRow}
        renderScrollComponent={props => <RecyclerViewBackedScrollView {...props} />}
        renderSeparator={(sectionID, rowID) => <View key={`${sectionID}-${rowID}`} style={styles.separator} />}
        enableEmptySections={true}
      />
    )
  },
})
<|endoftext|>


<commit_before>export {
  default
} from 'https://www.lactame.com//lib/molecular-formula/0.32.0/molecular-formula.js';
// } from 'http://localhost:9898/cheminfo-js/molecular-formula/dist/molecular-formula.js';
<commit_msg>chore: update molecular-formula to 0.33.0<commit_after>export {
  default
} from 'https://www.lactame.com//lib/molecular-formula/0.33.0/molecular-formula.js';
// } from 'http://localhost:9898/cheminfo-js/molecular-formula/dist/molecular-formula.js';
<|endoftext|>