<commit_before>/*
  # Application

  Lucidity main application

  Properties:

    * song: song position in 1/16th of a note for the current frame
    * time: current frame time reference in seconds
    * bpm:  calculated beats per minute
*/
'use strict'
const path     = require('path')
const fs       = require('fs')
const ncp      = require('ncp').ncp
const elapsed  = require('lucy-util').elapsed
const remote   = require('remote')
const live = require('lucy-live')

const Application = function() {
  this.time_ref  = elapsed()
  this.setTime(0)
  this.time_sync = null
  this.bpm       = 120
}

module.exports = Application

Application.prototype.run = function(scene) {
  this.scene = scene
  this.start()
}

Application.prototype.load = function(scene_path) {
  let self = this
  live.require(scene_path, function(mod) {
    mod.scene.ready.then(function(scene) {
      // This means that anytime we alter a scene, it will be run.
      // OK for me.
      self.run(scene)
    })
  })
}

Application.prototype.togglePause = function() {
  if (this.paused) {
    this.start()
  } else {
    this.pause()
  }
}

// Reinstall the runtime loop
Application.prototype.start = function() {
  let self = this
  setTimeout(function() {
    if (self.anim) stop()

    if (self.paused) {
      self.time_ref = elapsed() - self.paused
      self.paused = null
    }

    let anim = function() {
      if (anim == self.anim) {
        requestAnimationFrame(anim)
        self.animate()
      }
    }
    self.anim = anim
    anim()
  },100)
}

Application.prototype.stop = function() {
  this.time_ref = null
  this.anim = null
}

Application.prototype.pause = function() {
  this.paused = this.time
  this.anim   = null
}

Application.prototype.animate = function() {
  this.setTime(elapsed() - this.time_ref)
  this.scene.render(this)
  if (this.stats) {
    let el = (elapsed() - this.time) * 1000
    this.stats.innerHTML = el.toPrecision(3)
  }
}

Application.prototype.setTime = function(s) {
  if (this.time_sync) {
    let last_song = this.song
    // update song position from sync (value in 1/16th)
    let song = this.time_sync.position.value(s)

    // compute BPM
    if (song > this.song) {
      // beats/minute = 60 * beats/second = 60/4 * (delta song)/second
      this.bpm = 60 * (song - this.song) / (s - this.time) / 4
    }
    this.song = song
    this.time = s
  } else {
    this.song = this.bpm * 4 / 60 * (s - this.time)
    this.time = s
  }
}

const statPath = function(path) {
  try {
    return fs.statSync(path)
  } catch (e) {}
  return false
}

Application.prototype.setWorkPath = function(wpath) {
  wpath = path.resolve(wpath)
  if (statPath(wpath)) {
    this.work_path = path.resolve(wpath)
  } else {
    alert(`Work path '${wpath}' does not exist.`)
  }
}

Application.prototype.setScenePath = function(spath) {
  spath = path.resolve(spath)
  if (statPath(spath)) {
    this.scene_path = path.resolve(spath)
  } else {
    alert(`Scene path '${spath}' does not exist.`)
  }
}

Application.prototype.saveWorkAs = function(src, trg) {
  let self = this
  if (!self.work_path) {
    return alert('Missing work path (app.setWorkPath not called).')
  }

  if (!self.scene_path) {
    return alert('Missing scene path (app.setScenePath not called).')
  }

  let playing = !self.paused

  if (playing) self.pause()

  self.prompt("Save Work As", "Please enter scene name.", function(name) {
    // Take/update snapshot in working directory
    let target = path.resolve(self.scene_path, name)
    let copy_op = function() {
      setTimeout(function() {
        // Execute after page refresh to avoid having prompt in center of images
        self.grabImage(function() {
          // Run Async

          // FIXME: Create folder name s001, s002, s003 and set name in s001/info.json ?
          //        Or ensure valid path for all platforms ?
          //        Or just try creating folder and see if it fails ?
          let source = self.work_path
          let target = path.resolve(self.scene_path, name)

            ncp(source, target, function(err) {
              if (err) {
                alert(`Could not create scene (${err}).`)
              }
            })
        })
        if (playing) self.start()
      }, 50)
    }
    if (statPath(target)) {
      self.confirm('Folder exists', `A scene with name '${name}' already exists. Overwrite ?`, copy_op, function() {
        if (playing) self.start()
      })
    } else {
      copy_op()
    }
  }, function() {
    if (playing) self.start()
  })
}

Application.prototype.grabImage = function(clbk) {
  if (!this.work_path) {
    return alert('Missing work path (app.setWorkPath not called).')
  }
  let imagepath = path.join(this.work_path, 'snapshot.png')
  remote.getCurrentWindow().capturePage(function(image) {
    let buffer = image.toPng()
    // The image is a remote object, write in main process to avoid corruption
    // in remote call.
    remote.require('fs').writeFile(imagepath, buffer, function(err) {
      if (err) {
        console.log(err)
      } else {
        clbk(imagepath)
      }
    })
  })
}

Application.prototype.webGLRenderer = function() {
  if (this.renderer) return this.renderer
}

Application.prototype.openDialog = function(title, message, onOK, onCancel, showCancel, showField) {
  this.dialog =
    { title:      title
    , message:    message
    , onOK:       onOK
    , onCancel:   onCancel
    , showCancel: showCancel
    , showField:  showField
    }
  if (showCancel) {
    document.getElementById('dialog-btn-cancel').style.display = 'block'
  } else {
    document.getElementById('dialog-btn-cancel').style.display = 'none'
  }
  document.getElementById('dialog').style.display = 'block';
  document.getElementById('dialog-title').innerHTML   = title
  document.getElementById('dialog-message').innerHTML = message
  let form = document.getElementById('dialog-form')
  if (showField) {
    form.style.display = 'block'
    let fld = document.getElementById('dialog-fld')
    fld.value = ''
    fld.focus()
  } else {
    form.style.display = 'none'
    let btn = document.getElementById('dialog-btn-ok')
    btn.focus()
  }
}

Application.prototype.closeDialog = function(clbk, value) {
  this.dialog = null
  document.getElementById('dialog').style.display = 'none'
  if (clbk) clbk(value)
}

Application.prototype.btnCancel = function() {
  if (this.dialog) {
    this.closeDialog(this.dialog.onCancel)
  }
}

Application.prototype.btnOK = function() {
  if (this.dialog && this.dialog.onOK) {
    if (this.dialog.showField) {
      let v = document.getElementById('dialog-fld').value
      this.closeDialog(this.dialog.onOK, v)
    } else {
      this.closeDialog(this.dialog.onOK)
    }
  }
}

Application.prototype.alert = function(a, b) {
  let title, msg
  if (typeof(b) == 'string') {
    title = a
    msg   = b
  } else {
    title = 'Alert'
    msg   = a
  }
  this.openDialog(title, msg)
}

Application.prototype.prompt = function(a, b, c, d) {
  let title, msg, onOK, onCancel
  if (typeof(b) == 'string') {
    title    = a
    msg      = b
    onOK     = c
    onCancel = d
  } else {
    title = 'Prompt'
    msg      = a
    onOK     = b
    onCancel = c
  }
  this.openDialog(title, msg, onOK, onCancel, true, true)
}

Application.prototype.confirm = function(a, b, c, d) {
  let title, msg, onOK, onCancel
  if (typeof(b) == 'string') {
    title    = a
    msg      = b
    onOK     = c
    onCancel = d
  } else {
    title = 'Confirm'
    msg      = a
    onOK     = b
    onCancel = c
  }
  this.openDialog(title, msg, onOK, onCancel, true)
}

Application.prototype.init = function(url) {
  //
  //
  const app  = require('app')
  const Menu = require('menu')
  const MenuItem      = require('menu-item')
  const BrowserWindow = require('browser-window')

  require('crash-reporter').start()

  // main Window
  var mainWindow = null

  // Quit on all windows close
  app.on('window-all-closed', function() { app.quit() })

  app.on('ready', function() {
    mainWindow = new BrowserWindow({width:800, height:600})
    mainWindow.loadUrl(url)

    mainWindow.on('closed', function() {
      // Dereference window object. Not really needed since we quit in this app.
      mainWindow = null
    })

    var template = [{
        label: 'Seven',
        submenu: [{
          label: 'About Seven',
          selector: 'orderFrontStandardAboutPanel:'
        }, {
          type: 'separator'
        }, {
          label: 'Services',
          submenu: []
        }, {
          type: 'separator'
        }, {
          label: 'Hide Electron',
          accelerator: 'Command+H',
          selector: 'hide:'
        }, {
          label: 'Hide Others',
          accelerator: 'Command+Shift+H',
          selector: 'hideOtherApplications:'
        }, {
          label: 'Show All',
          selector: 'unhideAllApplications:'
        }, {
          type: 'separator'
        }, {
          label: 'Quit',
          accelerator: 'Command+Q',
          click: function() {
            app.quit();
          }
        }, ]
      // }, {
      // 	label: 'Edit',
      // 	submenu: [{
      // 		label: 'Undo',
      // 		accelerator: 'Command+Z',
      // 		selector: 'undo:'
      // 	}, {
      // 		label: 'Redo',
      // 		accelerator: 'Shift+Command+Z',
      // 		selector: 'redo:'
      // 	}, {
      // 		type: 'separator'
      // 	}, {
      // 		label: 'Cut',
      // 		accelerator: 'Command+X',
      // 		selector: 'cut:'
      // 	}, {
      // 		label: 'Copy',
      // 		accelerator: 'Command+C',
      // 		selector: 'copy:'
      // 	}, {
      // 		label: 'Paste',
      // 		accelerator: 'Command+V',
      // 		selector: 'paste:'
      // 	}, {
      // 		label: 'Select All',
      // 		accelerator: 'Command+A',
      // 		selector: 'selectAll:'
      // 	}, ]
      }, {
        label: 'View',
        submenu: [{
          label: 'Reload',
          accelerator: 'Command+R',
          click: function() {
            mainWindow.restart();
          }
        }, {
          label: 'Toggle Full Screen',
          accelerator: 'Ctrl+Command+F',
          click: function() {
            mainWindow.setFullScreen(!mainWindow.isFullScreen());
          }
        }, {
          label: 'Toggle Developer Tools',
          accelerator: 'Alt+Command+I',
          click: function() {
            mainWindow.toggleDevTools();
          }
        }, ]
      }, {
        label: 'Window',
        submenu: [{
          label: 'Minimize',
          accelerator: 'Command+M',
          selector: 'performMiniaturize:'
        }, {
          label: 'Close',
          accelerator: 'Command+W',
          selector: 'performClose:'
        }, {
          type: 'separator'
        }, {
          label: 'Bring All to Front',
          selector: 'arrangeInFront:'
        }, ]
      }, {
        label: 'Help',
        submenu: [{
          label: 'Learn More',
          click: function() {
            require('shell').openExternal('http://electron.atom.io')
          }
        }, {
          label: 'Documentation',
          click: function() {
            require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme')
          }
        }, {
          label: 'Community Discussions',
          click: function() {
            require('shell').openExternal('https://discuss.atom.io/c/electron')
          }
        }, {
          label: 'Search Issues',
          click: function() {
            require('shell').openExternal('https://github.com/atom/electron/issues')
          }
        }]
      }];

      let menu = Menu.buildFromTemplate(template);
      Menu.setApplicationMenu(menu);

  })

}
<commit_msg>Fixed save as with weird names, storing time ref with folder.<commit_after>/*
  # Application

  Lucidity main application

  Properties:

    * song: song position in 1/16th of a note for the current frame
    * time: current frame time reference in seconds
    * bpm:  calculated beats per minute
*/
'use strict'
const path     = require('path')
const fs       = require('fs')
const ncp      = require('ncp').ncp
const elapsed  = require('lucy-util').elapsed
const remote   = require('remote')
const live = require('lucy-live')

const Application = function() {
  this.time_ref  = elapsed()
  this.setTime(0)
  this.time_sync = null
  this.bpm       = 120
}

module.exports = Application

Application.prototype.run = function(scene) {
  this.scene = scene
  this.start()
}

Application.prototype.load = function(scene_path) {
  let self = this
  let info_path = path.join(scene_path, 'snapshot.json')
  let info = {time: self.time}

  if (statPath(info_path)) {
    info = require(info_path)
  }

  live.require(scene_path, function(mod) {
    mod.scene.ready.then(function(scene) {
      // This means that anytime we alter a scene, it will be run.
      // OK for me.
      // Reset time to snapshot
      self.paused = info.time
      self.run(scene)
    })
  })
}

Application.prototype.togglePause = function() {
  if (this.paused) {
    this.start()
  } else {
    this.pause()
  }
}

// Reinstall the runtime loop
Application.prototype.start = function() {
  let self = this

  if (self.paused) {
    self.time_ref = elapsed() - self.paused
    self.paused = null
    return
  }

  if (self.anim) stop()

  let anim = function() {
    if (anim == self.anim) {
      requestAnimationFrame(anim)
      self.animate()
    }
  }
  self.anim = anim
  anim()
}

Application.prototype.stop = function() {
  this.time_ref = null
  this.anim = null
}

Application.prototype.pause = function() {
  this.paused = this.time
}

Application.prototype.animate = function() {
  if (!this.paused) {
    this.setTime(elapsed() - this.time_ref)
  }
  this.scene.render(this)
  if (this.stats) {
    let el = (elapsed() - this.time) * 1000
    this.stats.innerHTML = el.toPrecision(3)
  }
}

Application.prototype.setTime = function(s) {
  if (this.time_sync) {
    let last_song = this.song
    // update song position from sync (value in 1/16th)
    let song = this.time_sync.position.value(s)

    // compute BPM
    if (song > this.song) {
      // beats/minute = 60 * beats/second = 60/4 * (delta song)/second
      this.bpm = 60 * (song - this.song) / (s - this.time) / 4
    }
    this.song = song
    this.time = s
  } else {
    this.song = this.bpm * 4 / 60 * (s - this.time)
    this.time = s
  }
}

const statPath = function(path) {
  try {
    return fs.statSync(path)
  } catch (e) {}
  return false
}

Application.prototype.setWorkPath = function(wpath) {
  wpath = path.resolve(wpath)
  if (statPath(wpath)) {
    this.work_path = path.resolve(wpath)
  } else {
    alert(`Work path '${wpath}' does not exist.`)
  }
}

Application.prototype.setScenePath = function(spath) {
  spath = path.resolve(spath)
  if (statPath(spath)) {
    this.scene_path = path.resolve(spath)
  } else {
    alert(`Scene path '${spath}' does not exist.`)
  }
}

Application.prototype.saveWorkAs = function(src, trg) {
  let self = this
  if (!self.work_path) {
    return alert('Missing work path (app.setWorkPath not called).')
  }

  if (!self.scene_path) {
    return alert('Missing scene path (app.setScenePath not called).')
  }

  let playing = !self.paused

  if (playing) self.pause()

  self.prompt("Save Work As", "Please enter scene name.", function(name) {
    name = encodeURIComponent(name.replace(' ', '-'))
    // Take/update snapshot in working directory
    let target = path.resolve(self.scene_path, name)
    let copy_op = function() {
      setTimeout(function() {
        // Execute after page refresh to avoid having prompt in center of images
        self.grabImage(function() {
          // Run Async

          // FIXME: Create folder name s001, s002, s003 and set name in s001/info.json ?
          //        Or ensure valid path for all platforms ?
          //        Or just try creating folder and see if it fails ?
          let source = self.work_path
          let target = path.resolve(self.scene_path, name)

            ncp(source, target, function(err) {
              if (err) {
                alert(`Could not create scene (${err}).`)
              }
            })
        })
        if (playing) {
          setTimeout(function() {
            // avoid flicker
            self.start()
          }, 80)
        }
      }, 50)
    }
    if (statPath(target)) {
      self.confirm('Folder exists', `A scene with name '${name}' already exists. Overwrite ?`, copy_op, function() {
        if (playing) self.start()
      })
    } else {
      copy_op()
    }
  }, function() {
    if (playing) self.start()
  })
}

Application.prototype.grabImage = function(clbk) {
  let self = this
  if (!self.work_path) {
    return alert('Missing work path (app.setWorkPath not called).')
  }
  let imagepath = path.join(self.work_path, 'snapshot.png')
  remote.getCurrentWindow().capturePage(function(image) {
    let buffer = image.toPng()
    // The image is a remote object, write in main process to avoid corruption
    // in remote call.
    remote.require('fs').writeFile(imagepath, buffer, function(err) {
      if (err) {
        console.log(err)
      } else {
        // snapshot created, update info.json file
        // TODO: could add other uniforms/params.
        let info = JSON.stringify(
          { time: self.time
          }
        )
        fs.writeFile(path.join(self.work_path, 'snapshot.json'), info, function(err) {
          if (!err) {
            clbk(imagepath)
          } else {
            console.log(err)
          }
        })
      }
    })
  })
}

Application.prototype.webGLRenderer = function() {
  if (this.renderer) return this.renderer
}

Application.prototype.openDialog = function(title, message, onOK, onCancel, showCancel, showField) {
  this.dialog =
    { title:      title
    , message:    message
    , onOK:       onOK
    , onCancel:   onCancel
    , showCancel: showCancel
    , showField:  showField
    }
  if (showCancel) {
    document.getElementById('dialog-btn-cancel').style.display = 'block'
  } else {
    document.getElementById('dialog-btn-cancel').style.display = 'none'
  }
  document.getElementById('dialog').style.display = 'block';
  document.getElementById('dialog-title').innerHTML   = title
  document.getElementById('dialog-message').innerHTML = message
  let form = document.getElementById('dialog-form')
  if (showField) {
    form.style.display = 'block'
    let fld = document.getElementById('dialog-fld')
    fld.value = ''
    fld.focus()
  } else {
    form.style.display = 'none'
    let btn = document.getElementById('dialog-btn-ok')
    btn.focus()
  }
}

Application.prototype.closeDialog = function(clbk, value) {
  this.dialog = null
  document.getElementById('dialog').style.display = 'none'
  if (clbk) clbk(value)
}

Application.prototype.btnCancel = function() {
  if (this.dialog) {
    this.closeDialog(this.dialog.onCancel)
  }
}

Application.prototype.btnOK = function() {
  if (this.dialog && this.dialog.onOK) {
    if (this.dialog.showField) {
      let v = document.getElementById('dialog-fld').value
      this.closeDialog(this.dialog.onOK, v)
    } else {
      this.closeDialog(this.dialog.onOK)
    }
  }
}

Application.prototype.alert = function(a, b) {
  let title, msg
  if (typeof(b) == 'string') {
    title = a
    msg   = b
  } else {
    title = 'Alert'
    msg   = a
  }
  this.openDialog(title, msg)
}

Application.prototype.prompt = function(a, b, c, d) {
  let title, msg, onOK, onCancel
  if (typeof(b) == 'string') {
    title    = a
    msg      = b
    onOK     = c
    onCancel = d
  } else {
    title = 'Prompt'
    msg      = a
    onOK     = b
    onCancel = c
  }
  this.openDialog(title, msg, onOK, onCancel, true, true)
}

Application.prototype.confirm = function(a, b, c, d) {
  let title, msg, onOK, onCancel
  if (typeof(b) == 'string') {
    title    = a
    msg      = b
    onOK     = c
    onCancel = d
  } else {
    title = 'Confirm'
    msg      = a
    onOK     = b
    onCancel = c
  }
  this.openDialog(title, msg, onOK, onCancel, true)
}

Application.prototype.init = function(url) {
  //
  //
  const app  = require('app')
  const Menu = require('menu')
  const MenuItem      = require('menu-item')
  const BrowserWindow = require('browser-window')

  require('crash-reporter').start()

  // main Window
  var mainWindow = null

  // Quit on all windows close
  app.on('window-all-closed', function() { app.quit() })

  app.on('ready', function() {
    mainWindow = new BrowserWindow({width:800, height:600})
    mainWindow.loadUrl(url)

    mainWindow.on('closed', function() {
      // Dereference window object. Not really needed since we quit in this app.
      mainWindow = null
    })

    var template = [{
        label: 'Seven',
        submenu: [{
          label: 'About Seven',
          selector: 'orderFrontStandardAboutPanel:'
        }, {
          type: 'separator'
        }, {
          label: 'Services',
          submenu: []
        }, {
          type: 'separator'
        }, {
          label: 'Hide Electron',
          accelerator: 'Command+H',
          selector: 'hide:'
        }, {
          label: 'Hide Others',
          accelerator: 'Command+Shift+H',
          selector: 'hideOtherApplications:'
        }, {
          label: 'Show All',
          selector: 'unhideAllApplications:'
        }, {
          type: 'separator'
        }, {
          label: 'Quit',
          accelerator: 'Command+Q',
          click: function() {
            app.quit();
          }
        }, ]
      // }, {
      // 	label: 'Edit',
      // 	submenu: [{
      // 		label: 'Undo',
      // 		accelerator: 'Command+Z',
      // 		selector: 'undo:'
      // 	}, {
      // 		label: 'Redo',
      // 		accelerator: 'Shift+Command+Z',
      // 		selector: 'redo:'
      // 	}, {
      // 		type: 'separator'
      // 	}, {
      // 		label: 'Cut',
      // 		accelerator: 'Command+X',
      // 		selector: 'cut:'
      // 	}, {
      // 		label: 'Copy',
      // 		accelerator: 'Command+C',
      // 		selector: 'copy:'
      // 	}, {
      // 		label: 'Paste',
      // 		accelerator: 'Command+V',
      // 		selector: 'paste:'
      // 	}, {
      // 		label: 'Select All',
      // 		accelerator: 'Command+A',
      // 		selector: 'selectAll:'
      // 	}, ]
      }, {
        label: 'View',
        submenu: [{
          label: 'Reload',
          accelerator: 'Command+R',
          click: function() {
            mainWindow.restart();
          }
        }, {
          label: 'Toggle Full Screen',
          accelerator: 'Ctrl+Command+F',
          click: function() {
            mainWindow.setFullScreen(!mainWindow.isFullScreen());
          }
        }, {
          label: 'Toggle Developer Tools',
          accelerator: 'Alt+Command+I',
          click: function() {
            mainWindow.toggleDevTools();
          }
        }, ]
      }, {
        label: 'Window',
        submenu: [{
          label: 'Minimize',
          accelerator: 'Command+M',
          selector: 'performMiniaturize:'
        }, {
          label: 'Close',
          accelerator: 'Command+W',
          selector: 'performClose:'
        }, {
          type: 'separator'
        }, {
          label: 'Bring All to Front',
          selector: 'arrangeInFront:'
        }, ]
      }, {
        label: 'Help',
        submenu: [{
          label: 'Learn More',
          click: function() {
            require('shell').openExternal('http://electron.atom.io')
          }
        }, {
          label: 'Documentation',
          click: function() {
            require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme')
          }
        }, {
          label: 'Community Discussions',
          click: function() {
            require('shell').openExternal('https://discuss.atom.io/c/electron')
          }
        }, {
          label: 'Search Issues',
          click: function() {
            require('shell').openExternal('https://github.com/atom/electron/issues')
          }
        }]
      }];

      let menu = Menu.buildFromTemplate(template);
      Menu.setApplicationMenu(menu);

  })

}
<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var path = require('path');
var RoomName='';
var UserName='';

app.use(express.static(path.join(__dirname, 'public')));

var server = app.listen(3000, function() {
    console.log("server started on port 3000");
});

var io = require('socket.io').listen(server);

app.get('/', function(req, res){
  res.sendfile('index.html');
});

io.sockets.on('connection', function (socket) {
	 UserName = socket.handshake.query.UserName;
	 io.to(RoomName).emit('joined', UserName);

     socket.on('findFriends', function (gps) {
    		 RoomName = gps.Lat.toFixed(2) + " " + gps.Lon.toFixed(2);

         //check if room exists
         var foundRoom = FindRoomInRange(gps.Lat.toFixed(2),gps.Lon.toFixed(2))
         console.log("Found Room name is:"+foundRoom);
         if(foundRoom != '')
         {
            console.log('Joining existing room')
    		    socket.join(foundRoom);
         }
         else //no room close enough, create
         {
          console.log('Creating new room')
          socket.join(RoomName);
         }

    		 socket.emit('title', RoomName);
     });

    socket.on('message', function(data) {
        io.to(RoomName).emit('message',data);
    });

    socket.on('leave', function(data) {
       	socket.leave(RoomName);
       	io.to(RoomName).emit('left',data);
       	socket.emit('selfLeft');
    })
 });

function FindRoomInRange(mylat,mylon)
{
    var existingRooms = io.sockets.adapter.rooms;
    var roomNameFound='';
    if(existingRooms.length < 1)
    {
        return roomNameFound;
    }

   Object.keys(existingRooms).forEach(function(roomName){

       var roomTokens = roomName.split(" ");

        if(!isNaN(parseFloat(roomTokens[0])) && !isNaN(parseFloat(roomTokens[1])))
        {
          if(Math.abs(parseFloat(roomTokens[0]).toFixed(2) - mylat) < .03 && Math.abs(parseFloat(roomTokens[1]).toFixed(2) - mylon) < .03)
          {
            roomNameFound = roomName;
          }
        }
    });

    return roomNameFound;
}
<commit_msg>fixing room title<commit_after>var express = require('express');
var app = express();
var path = require('path');
var CurrentRoomName='';
var UserName='';

app.use(express.static(path.join(__dirname, 'public')));

var server = app.listen(3000, function() {
    console.log("server started on port 3000");
});

var io = require('socket.io').listen(server);

app.get('/', function(req, res){
  res.sendfile('index.html');
});

io.sockets.on('connection', function (socket) {
	 UserName = socket.handshake.query.UserName;

     socket.on('findFriends', function (gps) {
    		 CurrentRoomName = gps.Lat.toFixed(2) + " " + gps.Lon.toFixed(2);

         //check if room exists
         var foundRoom = FindRoomInRange(gps.Lat.toFixed(2),gps.Lon.toFixed(2))
         if(foundRoom != '')
         {
    		    socket.join(foundRoom);
            CurrentRoomName = foundRoom;

         }
         else //no room close enough, create
         {
            socket.join(CurrentRoomName);
         }

         io.to(CurrentRoomName).emit('joined', UserName);
         socket.emit('title', CurrentRoomName);

     });

    socket.on('message', function(data) {
        io.to(CurrentRoomName).emit('message',data);
    });

    socket.on('leave', function(data) {
       console.log('leaving '+CurrentRoomName);
       	socket.leave(CurrentRoomName); //leave room
       	io.to(CurrentRoomName).emit('left',data); //tell everyone i left
       	socket.emit('selfLeft'); //let myself know i left
    })
 });

function FindRoomInRange(mylat,mylon)
{
    var existingRooms = io.sockets.adapter.rooms;
    var roomNameFound='';
    if(existingRooms.length < 1)
    {
        return roomNameFound;
    }

   Object.keys(existingRooms).forEach(function(roomName){

       var roomTokens = roomName.split(" ");

        if(!isNaN(parseFloat(roomTokens[0])) && !isNaN(parseFloat(roomTokens[1])))
        {
          if(Math.abs(parseFloat(roomTokens[0]).toFixed(2) - mylat) < .03 && Math.abs(parseFloat(roomTokens[1]).toFixed(2) - mylon) < .03)
          {
            roomNameFound = roomName;
          }
        }
    });

    return roomNameFound;
}
<|endoftext|>


<commit_before>const {Dispatcher} = require("flux");

const StreamingClient = require("@anyware/streaming-client");
const {SculptureStore, SculptureActionCreator} = require("@anyware/game-logic");

const PanelView = require('./views/panel-view');
const DiskView = require('./views/disk-view');

const SerialManager = require('./serial/serial-manager');

export default class SculptureApp {
  constructor(config) {
    this.config = config;

    this.dispatcher = new Dispatcher();
    this.dispatcher.register((payload) => {
      this._log(`Sent action: ${JSON.stringify(payload)}`);
    });

    this.client = null;

    this.panelView = null;
    this.diskView = null;

    const serialIdentity = this.config.HARDWARE_USERNAME_MAPPINGS[config.username];
    this.serialManager = new SerialManager(serialIdentity);
    this.serialManager.on(SerialManager.EVENT_COMMAND, (commandName, commandArgs) => {
      console.log(`COMMAND '${commandName}': ${JSON.stringify(commandArgs)}`);
    });

    this.sculpture = new SculptureStore(this.dispatcher, this.config);
    this.sculpture.on(SculptureStore.EVENT_CHANGE, (changes) => {
      this._log(`Sent state update: ${JSON.stringify(changes)}`);

      this.client.sendStateUpdate(changes);
    });

    this.sculptureActionCreator = new SculptureActionCreator(this.dispatcher);

    this._setupViews();
  }

  /**
   * Connects to the streaming server and sets up the rest of the application
   */
  connectAndSetup(options) {
    this._connectionOptions = options;
    this._setupStreamingClient();
  }

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

  _error(message) {
    console.error(message);
  }

  _setupViews() {
    this.panelView = new PanelView(this.sculpture, this.dispatcher, this.serialManager);
    this.diskView = new DiskView(this.sculpture, this.dispatcher, this.serialManager);
  }

  _setupStreamingClient() {
    if (this.client) {
      this.client.close();
    }

    this._log(`Using username ${this._connectionOptions.username}`);

    this.client = new StreamingClient(this._connectionOptions);

    this.client.on(StreamingClient.EVENT_CONNECT, this._onConnectionStatusChange.bind(this));
    this.client.on(StreamingClient.EVENT_DISCONNECT, this._onConnectionStatusChange.bind(this));

    this.client.on(StreamingClient.EVENT_ERROR, this._error.bind(this));

    this.client.once(StreamingClient.EVENT_CONNECT, () => {
      // Temporarily here until the full game transitions are implemented
      if (!this.sculpture.isPlayingMoleGame) {
        //TODO: Hack! BAD
        setTimeout(() => {
          this._log("Starting simon game...");
          this.sculpture.startSimonGame();
        }, 4000);
      }
    });

    this.client.on(StreamingClient.EVENT_STATE_UPDATE, this._onStateUpdate.bind(this));
  }

  _onConnectionStatusChange() {
    this._log(`Client Connected: ${this.client.connected}`);
  }

  _onStateUpdate(update, metadata) {
    update.metadata = metadata;

    this._log(`Got state update: ${JSON.stringify(update)}`);

    this.sculptureActionCreator.sendMergeState(update);
  }
}

<commit_msg>Fixed one reference to config instead of this.config<commit_after>const {Dispatcher} = require("flux");

const StreamingClient = require("@anyware/streaming-client");
const {SculptureStore, SculptureActionCreator} = require("@anyware/game-logic");

const PanelView = require('./views/panel-view');
const DiskView = require('./views/disk-view');

const SerialManager = require('./serial/serial-manager');

export default class SculptureApp {
  constructor(config) {
    this.config = config;

    this.dispatcher = new Dispatcher();
    this.dispatcher.register((payload) => {
      this._log(`Sent action: ${JSON.stringify(payload)}`);
    });

    this.client = null;

    this.panelView = null;
    this.diskView = null;

    const serialIdentity = this.config.HARDWARE_USERNAME_MAPPINGS[this.config.username];
    this.serialManager = new SerialManager(serialIdentity);
    this.serialManager.on(SerialManager.EVENT_COMMAND, (commandName, commandArgs) => {
      console.log(`COMMAND '${commandName}': ${JSON.stringify(commandArgs)}`);
    });

    this.sculpture = new SculptureStore(this.dispatcher, this.config);
    this.sculpture.on(SculptureStore.EVENT_CHANGE, (changes) => {
      this._log(`Sent state update: ${JSON.stringify(changes)}`);

      this.client.sendStateUpdate(changes);
    });

    this.sculptureActionCreator = new SculptureActionCreator(this.dispatcher);

    this._setupViews();
  }

  /**
   * Connects to the streaming server and sets up the rest of the application
   */
  connectAndSetup(options) {
    this._connectionOptions = options;
    this._setupStreamingClient();
  }

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

  _error(message) {
    console.error(message);
  }

  _setupViews() {
    this.panelView = new PanelView(this.sculpture, this.dispatcher, this.serialManager);
    this.diskView = new DiskView(this.sculpture, this.dispatcher, this.serialManager);
  }

  _setupStreamingClient() {
    if (this.client) {
      this.client.close();
    }

    this._log(`Using username ${this._connectionOptions.username}`);

    this.client = new StreamingClient(this._connectionOptions);

    this.client.on(StreamingClient.EVENT_CONNECT, this._onConnectionStatusChange.bind(this));
    this.client.on(StreamingClient.EVENT_DISCONNECT, this._onConnectionStatusChange.bind(this));

    this.client.on(StreamingClient.EVENT_ERROR, this._error.bind(this));

    this.client.once(StreamingClient.EVENT_CONNECT, () => {
      // Temporarily here until the full game transitions are implemented
      if (!this.sculpture.isPlayingMoleGame) {
        //TODO: Hack! BAD
        setTimeout(() => {
          this._log("Starting simon game...");
          this.sculpture.startSimonGame();
        }, 4000);
      }
    });

    this.client.on(StreamingClient.EVENT_STATE_UPDATE, this._onStateUpdate.bind(this));
  }

  _onConnectionStatusChange() {
    this._log(`Client Connected: ${this.client.connected}`);
  }

  _onStateUpdate(update, metadata) {
    update.metadata = metadata;

    this._log(`Got state update: ${JSON.stringify(update)}`);

    this.sculptureActionCreator.sendMergeState(update);
  }
}

<|endoftext|>


<commit_before>/**
 * express-to-koa
 * @author iswujixiang@gmail.com
 */

const compose   = require('koa-compose');
const express   = require('express');
const {init}    = require('express/lib/middleware/init');
const debug     = require('debug')('koa-to-express:e2k');

const app       = express();
const {request, reponse} = app;

module.exports  = middlewares => {
    if (Array.isArray(middlewares)) {
        return compose(middlewares.map(e2k));
    }

    if (middlewares.length === 4) {
        throw new Error('e2k do not support error-handler now');
    }

    debug(`converted express middleware: ${middlewares.name || '[anonymous]'}`);

    return (ctx, next) => {

        const {req, res, query} = ctx;

        if (!req.query) req.query = query; // express's query middleware

        if (!(req.__proto__ === request && res.__proto__ === reponse)) {
            init(app)(req, res, function () {
                // do nothing
            });
        }
        return new Promise((resolve, reject) => {
            try {
                res
                    .status(200)
                    .on('finish', resolve);
                middlewares(req, res, err => {
                    if (!err) {
                        return resolve('next');
                    }
                    reject(err);
                });
            } catch (err) {
                reject(err);
            }
        }).then(_next => {
            if (_next) {
                res.status(404);
                return next();
            }
        });
    };
};
<commit_msg>fix: the time to reset the res status and init the app's req and res<commit_after>/**
 * express-to-koa
 * @author iswujixiang@gmail.com
 */

const compose   = require('koa-compose');
const express   = require('express');
const {init}    = require('express/lib/middleware/init');
const debug     = require('debug')('koa-to-express:e2k');

const app       = express();

const e2k       = middlewares => {
    if (Array.isArray(middlewares)) {
        return compose(middlewares.map(e2k));
    }

    /* istanbul ignore if */
    if (middlewares.length === 4) {
        throw new Error('e2k do not support error-handler now');
    }

    debug(`converted express middleware: ${middlewares.name || '[anonymous]'}`);

    return (ctx, next) => {

        const {req, res, query} = ctx;

        if (!req.query) req.query = query; // express's query middleware

        if (req.res !== res) {
            init(app)(req, res, () => {
                // do nothing
            });
        }
        return new Promise((resolve, reject) => {
            try {
                if (!ctx.response._explicitStatus) {
                    res.status(200); //response OK, set status back to 200
                }
                res.on('finish', resolve);

                middlewares(req, res, err => {
                    if (err) {
                        return reject(err);
                    }
                    resolve('next');
                });
            } catch (err) {
                reject(err);
            }
        }).then(_next => {
            if (_next) {
                res.status(404);
                return next();
            }
        });
    };
};

module.exports = e2k;
<|endoftext|>


<commit_before>const helper = require('think-helper');
const assert = require('assert');
const Cookies = require('cookies');
const url = require('url');

const PARAM = Symbol('context-param');
const POST = Symbol('context-post');
const FILE = Symbol('context-file');
const COOKIE_STORE = Symbol('cookie-store');
const path = require('path');
const fs = require('fs');
const onFinished = require('on-finished');
const destroy = require('destroy');

/**
 * extend context
 */
module.exports = {
  /**
   * get userAgent header
   */
  get userAgent() {
    return this.header['user-agent'];
  },
  /**
   * is get request
   */
  get isGet() {
    return this.method === 'GET';
  },
  /**
   * is post request
   */
  get isPost() {
    return this.method === 'POST';
  },
  /**
   * is command line invoke
   */
  get isCli() {
    return this.method === 'CLI';
  },
  /**
   * get referer header
   */
  referer(onlyHost) {
    return this.referrer(onlyHost);
  },
  /**
   * get referer header
   */
  referrer(onlyHost) {
    const referrer = this.header['referer'];
    if (!referrer || !onlyHost) return referrer;
    return url.parse(referrer).hostname;
  },
  /**
   * is method
   */
  isMethod(method) {
    return this.method === method.toUpperCase();
  },
  /**
   * is ajax request
   */
  isAjax(method) {
    if (method && !this.isMethod(method)) return false;
    return this.header['x-requested-with'] === 'XMLHttpRequest';
  },
  /**
   * is jsonp request
   */
  isJsonp(callbackField = this.config('jsonpCallbackField')) {
    return !!this.param(callbackField);
  },
  /**
   * send jsonp data
   */
  jsonp(data, callbackField = this.config('jsonpCallbackField')) {
    let field = this.param(callbackField);
    // remove unsafe chars
    field = (field || '').replace(/[^\w.]/g, '');
    if (field) {
      data = `${field}(${JSON.stringify(data)})`;
    }
    this.type = this.config('jsonContentType');
    this.body = data;
    return false;
  },
  /**
   * send json data
   */
  json(data) {
    this.type = this.config('jsonContentType');
    this.body = data;
    return false;
  },
  /**
   * send success data
   */
  success(data = '', message = '') {
    const obj = {
      [this.config('errnoField')]: 0,
      [this.config('errmsgField')]: message,
      data
    };
    this.type = this.config('jsonContentType');
    this.body = obj;
    return false;
  },
  /**
   * send fail data
   */
  fail(errno, errmsg = '', data = '') {
    let obj;
    if (helper.isObject(errno)) {
      obj = errno;
    } else {
      if (/^[A-Z_]+$/.test(errno)) {
        const messages = think.app.validators.messages || {};
        const msg = messages[errno];
        if (think.isArray(msg)) {
          [errno, errmsg] = msg;
        }
      }
      if (!think.isNumber(errno)) {
        [data, errmsg, errno] = [errmsg, errno, this.config('defaultErrno')];
      }
      obj = {
        [this.config('errnoField')]: errno,
        [this.config('errmsgField')]: errmsg
      };
      if (data) {
        obj.data = data;
      }
    }
    this.type = this.config('jsonContentType');
    this.body = obj;
    return false;
  },
  /**
   * set expires header
   */
  expires(time) {
    time = helper.ms(time);
    const date = new Date(Date.now() + time);
    this.set('Cache-Control', `max-age=${time}`);
    this.set('Expires', date.toUTCString());
  },
  /**
   * get or set configs
   * @param {String} name
   * @param {Mixed} value
   * @param {String} m
   */
  config(name, value, m = this.module) {
    return think.config(name, value, m);
  },
  /**
   * get or set query data
   * `query` or `get` is already used in koa
   * @param {String} name
   * @param {Mixed} value
   */
  param(name, value) {
    if (!this[PARAM]) {
      this[PARAM] = Object.assign({}, this.query);
      this.app.emit('filterParam', this[PARAM]);
    }
    if (!name) return this[PARAM];
    if (helper.isObject(name)) {
      this[PARAM] = Object.assign(this[PARAM], name);
      return this;
    }
    assert(name && helper.isString(name), 'param.name must be a string');
    if (value === undefined) {
      // this.param('a,b')
      if (name.indexOf(',') > -1) {
        const value = {};
        name.split(',').forEach(item => {
          value[item] = this[PARAM][item];
        });
        return value;
      }
      return this[PARAM][name];
    }
    this[PARAM][name] = value;
    return this;
  },
  /**
   * get or set post data
   * @param {String} name
   * @param {Mixed} value
   */
  post(name, value) {
    if (!this[POST]) {
      this[POST] = Object.assign({}, this.request.body && this.request.body.post);
      this.app.emit('filterParam', this[POST]);
    }
    if (!name) return this[POST];
    if (helper.isObject(name)) {
      this[POST] = Object.assign(this[POST], name);
      return this;
    }
    if (value === undefined) {
      // this.param('a,b')
      if (name.indexOf(',') > -1) {
        const value = {};
        name.split(',').forEach(item => {
          value[item] = this[POST][item];
        });
        return value;
      }
      return this[POST][name];
    }
    this[POST][name] = value;
    return this;
  },
  /**
   * get or set file data
   * @param {String} name
   * @param {Mixed} value
   */
  file(name, value) {
    if (!this[FILE]) {
      this[FILE] = Object.assign({}, this.request.body && this.request.body.file);
    }
    if (!name) return this[FILE];
    if (helper.isObject(name)) {
      this[FILE] = Object.assign(this[FILE], name);
      return this;
    }
    if (value === undefined) {
      return this[FILE][name];
    }
    this[FILE][name] = value;
    return this;
  },
  /**
   * get or set cookie
   * @param {String} name
   * @param {String} value
   * @param {Object} options
   */
  cookie(name, value, options = {}) {
    assert(name && helper.isString(name), 'cookie.name must be a string');
    options = Object.assign({}, this.config('cookie'), options);
    const instance = new Cookies(this.req, this.res, {
      keys: options.keys,
      secure: this.req.secure
    });

    if (!this[COOKIE_STORE]) this[COOKIE_STORE] = {};

    // get cookie
    if (value === undefined) {
      if (this[COOKIE_STORE][name] !== undefined) return this[COOKIE_STORE][name];
      return instance.get(name, options);
    }
    // remove cookie
    if (value === null) {
      delete this[COOKIE_STORE][name];
      // If the value is omitted, an outbound header with an expired date is used to delete the cookie.
      // https://github.com/pillarjs/cookies#cookiesset-name--value---options--
      return instance.set(name, undefined, options);
    }
    assert(helper.isString(value), 'cookie value must be a string');
    // http://browsercookielimits.squawky.net/
    if (value.length >= 4094) {
      this.app.emit('cookieLimit', {name, value, ctx: this});
    }
    this[COOKIE_STORE][name] = value;
    // set cookie
    return instance.set(name, value, options);
  },
  /**
   * get service
   * @param {String} name
   * @param {String} m
   */
  service(...args) {
    return think.service(...args);
  },
  /**
   * download
   * @param {String} filepath
   * @param {String} filename
   */
  download(filepath, filename = path.basename(filepath)) {
    assert(filepath, 'filepath can not be empty');
    const contentType = this.response.get('Content-Type');
    if (!contentType) {
      this.type = path.extname(filename);
    }
    const contentDisposition = this.response.get('Content-Disposition');
    if (!contentDisposition) {
      this.attachment(filename);
    }
    const stream = fs.createReadStream(filepath);
    this.body = stream;
    onFinished(this.res, () => {
      destroy(stream);
    });
    return false;
  }
};
<commit_msg>Fix jsonp content-type, fix #868<commit_after>const helper = require('think-helper');
const assert = require('assert');
const Cookies = require('cookies');
const url = require('url');

const PARAM = Symbol('context-param');
const POST = Symbol('context-post');
const FILE = Symbol('context-file');
const COOKIE_STORE = Symbol('cookie-store');
const path = require('path');
const fs = require('fs');
const onFinished = require('on-finished');
const destroy = require('destroy');

/**
 * extend context
 */
module.exports = {
  /**
   * get userAgent header
   */
  get userAgent() {
    return this.header['user-agent'];
  },
  /**
   * is get request
   */
  get isGet() {
    return this.method === 'GET';
  },
  /**
   * is post request
   */
  get isPost() {
    return this.method === 'POST';
  },
  /**
   * is command line invoke
   */
  get isCli() {
    return this.method === 'CLI';
  },
  /**
   * get referer header
   */
  referer(onlyHost) {
    return this.referrer(onlyHost);
  },
  /**
   * get referer header
   */
  referrer(onlyHost) {
    const referrer = this.header['referer'];
    if (!referrer || !onlyHost) return referrer;
    return url.parse(referrer).hostname;
  },
  /**
   * is method
   */
  isMethod(method) {
    return this.method === method.toUpperCase();
  },
  /**
   * is ajax request
   */
  isAjax(method) {
    if (method && !this.isMethod(method)) return false;
    return this.header['x-requested-with'] === 'XMLHttpRequest';
  },
  /**
   * is jsonp request
   */
  isJsonp(callbackField = this.config('jsonpCallbackField')) {
    return !!this.param(callbackField);
  },
  /**
   * send jsonp data
   */
  jsonp(data, callbackField = this.config('jsonpCallbackField')) {
    let field = this.param(callbackField);
    // remove unsafe chars
    field = (field || '').replace(/[^\w.]/g, '');
    if (field) {
      data = `${field}(${JSON.stringify(data)})`;
    }
    this.type = 'application/javascript';
    this.body = data;
    return false;
  },
  /**
   * send json data
   */
  json(data) {
    this.type = this.config('jsonContentType');
    this.body = data;
    return false;
  },
  /**
   * send success data
   */
  success(data = '', message = '') {
    const obj = {
      [this.config('errnoField')]: 0,
      [this.config('errmsgField')]: message,
      data
    };
    this.type = this.config('jsonContentType');
    this.body = obj;
    return false;
  },
  /**
   * send fail data
   */
  fail(errno, errmsg = '', data = '') {
    let obj;
    if (helper.isObject(errno)) {
      obj = errno;
    } else {
      if (/^[A-Z_]+$/.test(errno)) {
        const messages = think.app.validators.messages || {};
        const msg = messages[errno];
        if (think.isArray(msg)) {
          [errno, errmsg] = msg;
        }
      }
      if (!think.isNumber(errno)) {
        [data, errmsg, errno] = [errmsg, errno, this.config('defaultErrno')];
      }
      obj = {
        [this.config('errnoField')]: errno,
        [this.config('errmsgField')]: errmsg
      };
      if (data) {
        obj.data = data;
      }
    }
    this.type = this.config('jsonContentType');
    this.body = obj;
    return false;
  },
  /**
   * set expires header
   */
  expires(time) {
    time = helper.ms(time);
    const date = new Date(Date.now() + time);
    this.set('Cache-Control', `max-age=${time}`);
    this.set('Expires', date.toUTCString());
  },
  /**
   * get or set configs
   * @param {String} name
   * @param {Mixed} value
   * @param {String} m
   */
  config(name, value, m = this.module) {
    return think.config(name, value, m);
  },
  /**
   * get or set query data
   * `query` or `get` is already used in koa
   * @param {String} name
   * @param {Mixed} value
   */
  param(name, value) {
    if (!this[PARAM]) {
      this[PARAM] = Object.assign({}, this.query);
      this.app.emit('filterParam', this[PARAM]);
    }
    if (!name) return this[PARAM];
    if (helper.isObject(name)) {
      this[PARAM] = Object.assign(this[PARAM], name);
      return this;
    }
    assert(name && helper.isString(name), 'param.name must be a string');
    if (value === undefined) {
      // this.param('a,b')
      if (name.indexOf(',') > -1) {
        const value = {};
        name.split(',').forEach(item => {
          value[item] = this[PARAM][item];
        });
        return value;
      }
      return this[PARAM][name];
    }
    this[PARAM][name] = value;
    return this;
  },
  /**
   * get or set post data
   * @param {String} name
   * @param {Mixed} value
   */
  post(name, value) {
    if (!this[POST]) {
      this[POST] = Object.assign({}, this.request.body && this.request.body.post);
      this.app.emit('filterParam', this[POST]);
    }
    if (!name) return this[POST];
    if (helper.isObject(name)) {
      this[POST] = Object.assign(this[POST], name);
      return this;
    }
    if (value === undefined) {
      // this.param('a,b')
      if (name.indexOf(',') > -1) {
        const value = {};
        name.split(',').forEach(item => {
          value[item] = this[POST][item];
        });
        return value;
      }
      return this[POST][name];
    }
    this[POST][name] = value;
    return this;
  },
  /**
   * get or set file data
   * @param {String} name
   * @param {Mixed} value
   */
  file(name, value) {
    if (!this[FILE]) {
      this[FILE] = Object.assign({}, this.request.body && this.request.body.file);
    }
    if (!name) return this[FILE];
    if (helper.isObject(name)) {
      this[FILE] = Object.assign(this[FILE], name);
      return this;
    }
    if (value === undefined) {
      return this[FILE][name];
    }
    this[FILE][name] = value;
    return this;
  },
  /**
   * get or set cookie
   * @param {String} name
   * @param {String} value
   * @param {Object} options
   */
  cookie(name, value, options = {}) {
    assert(name && helper.isString(name), 'cookie.name must be a string');
    options = Object.assign({}, this.config('cookie'), options);
    const instance = new Cookies(this.req, this.res, {
      keys: options.keys,
      secure: this.req.secure
    });

    if (!this[COOKIE_STORE]) this[COOKIE_STORE] = {};

    // get cookie
    if (value === undefined) {
      if (this[COOKIE_STORE][name] !== undefined) return this[COOKIE_STORE][name];
      return instance.get(name, options);
    }
    // remove cookie
    if (value === null) {
      delete this[COOKIE_STORE][name];
      // If the value is omitted, an outbound header with an expired date is used to delete the cookie.
      // https://github.com/pillarjs/cookies#cookiesset-name--value---options--
      return instance.set(name, undefined, options);
    }
    assert(helper.isString(value), 'cookie value must be a string');
    // http://browsercookielimits.squawky.net/
    if (value.length >= 4094) {
      this.app.emit('cookieLimit', {name, value, ctx: this});
    }
    this[COOKIE_STORE][name] = value;
    // set cookie
    return instance.set(name, value, options);
  },
  /**
   * get service
   * @param {String} name
   * @param {String} m
   */
  service(...args) {
    return think.service(...args);
  },
  /**
   * download
   * @param {String} filepath
   * @param {String} filename
   */
  download(filepath, filename = path.basename(filepath)) {
    assert(filepath, 'filepath can not be empty');
    const contentType = this.response.get('Content-Type');
    if (!contentType) {
      this.type = path.extname(filename);
    }
    const contentDisposition = this.response.get('Content-Disposition');
    if (!contentDisposition) {
      this.attachment(filename);
    }
    const stream = fs.createReadStream(filepath);
    this.body = stream;
    onFinished(this.res, () => {
      destroy(stream);
    });
    return false;
  }
};
<|endoftext|>


<commit_before>/**
 * app.js
 *
 * @chill- High are the mountains, thick are the shade trees, and under an old pine I sit quietly and contentedly in my monkish home:
 * Perfect tranquility and rustic simplicity rules here. - Yoka Daishi
 *
 *
 * @description- This file is the first thing happens to badlee.
 * we combine redux and our react app with navigator and start Badlee app.
 * Here, we go!
 *
 * @author- heartit pirates were here.
 */

"use strict";

/**
 * Imp[o]rts Guide :-
 * 1. Backhandler : Detect hardware button presses for back navigation
 */
import React, { Component } from "react";
import { View, StyleSheet, BackHandler, StatusBar } from "react-native";
import { Root } from "native-base";
import { Navigator } from "react-native-deprecated-custom-components";
import { connect, Provider } from "react-redux";
import { makeStore } from "./badlee__redux/store";
import * as actionCreators from "./badlee__redux/action_creators";

import Init from "./containers/Init";

/**
 * Navigator handles the transition between different scenes in your app.
 * Transition back and unmount the current scene.
 * @description- on backpress button in mobile, show previous route
 */
BackHandler.addEventListener("hardwareBackPress", function() {
  // If scopeNavigator and it has routes information
  if (scopeNavigator && scopeNavigator.getCurrentRoutes().length > 1) {
    // unmount current screen and go to previous scene
    scopeNavigator.pop();
    return true;
  }
  return false;
});

class BadleeApp extends Component {
  /**
   * Function that navigator uses to render the scene for a given route.
   * @param {*} route
   * @param {*} navigator
   */
  renderScene(route, navigator) {
    let params = {};
    let Component = route.component;

    if (route.params) {
      params = route.params;
    }

    if (route.component) {
      return (
        <View style={styles.main}>
          <StatusBar hidden={route.statusBarHidden} />
          <Component
            navigator={navigator}
            style={styles.content}
            params={params}
          />
        </View>
      );
    }
  }

  render() {
    return (
      <Root>
        <Provider store={store}>
          <View style={{ flex: 1 }}>
            <StatusBar backgroundColor="#500655" barStyle="light-content" />
            <Navigator
              ref={nav => {
                scopeNavigator = nav;
              }}
              initialRoute={{ component: Init }}
              configureScene={() => {
                return Navigator.SceneConfigs.FloatFromRight;
              }}
              renderScene={this.renderScene.bind(this)}
            />
          </View>
        </Provider>
      </Root>
    );
  }
}

let store = makeStore();
let scopeNavigator;
let styles = StyleSheet.create({
  main: {
    backgroundColor: "#FFF",
    flex: 1,
    flexDirection: "column"
  }
});

export default BadleeApp;
<commit_msg>App.js minor fixes<commit_after>/**
 * @name- app.js
 *
 * @chill- High are the mountains, thick are the shade trees, and under an old pine I sit quietly and contentedly in my monkish home:
 * Perfect tranquility and rustic simplicity rules here. - Yoka Daishi
 *
 *
 * @description- This file is the first thing happens to badlee.
 * we combine redux and our react app with navigator and start Badlee app.
 * Here, we go!
 *
 * @author- heartit pirates were here.
 */

"use strict";

import React, { Component } from "react";
import { View, StyleSheet, BackHandler, StatusBar } from "react-native";
import { connect, Provider } from "react-redux";
import { Navigator } from "react-native-deprecated-custom-components";
import { Root } from "native-base";
import { makeStore } from "./badlee__redux/store";
import * as actionCreators from "./badlee__redux/action_creators";

import Init from "./containers/Init";

/**
 * Navigator handles the transition between different scenes in your app.
 * Transition back and unmount the current scene.
 * @description- on backpress button in mobile, show previous route
 */
BackHandler.addEventListener("hardwareBackPress", function() {
  // If scopeNavigator and it has routes information
  if (scopeNavigator && scopeNavigator.getCurrentRoutes().length > 1) {
    // unmount current screen and go to previous scene
    scopeNavigator.pop();
    return true;
  }
  return false;
});

class BadleeApp extends Component {
  /**
   * Function that navigator uses to render the scene for a given route.
   * @param {*} route
   * @param {*} navigator
   */
  renderScene(route, navigator) {
    let params = {};
    let Component = route.component;

    if (route.params) {
      params = route.params;
    }

    if (route.component) {
      return (
        <View style={styles.main}>
          <StatusBar hidden={route.statusBarHidden} />
          <Component
            navigator={navigator}
            style={styles.content}
            params={params}
          />
        </View>
      );
    }
  }

  render() {
    return (
      <Root>
        <Provider store={store}>
          <View style={{ flex: 1 }}>
            <StatusBar backgroundColor="#500655" barStyle="light-content" />
            <Navigator
              ref={nav => {
                scopeNavigator = nav;
              }}
              initialRoute={{ component: Init }}
              configureScene={() => {
                return Navigator.SceneConfigs.FloatFromRight;
              }}
              renderScene={this.renderScene.bind(this)}
            />
          </View>
        </Provider>
      </Root>
    );
  }
}

let store = makeStore();
let scopeNavigator;
let styles = StyleSheet.create({
  main: {
    backgroundColor: "#FFF",
    flex: 1,
    flexDirection: "column"
  }
});

export default BadleeApp;
<|endoftext|>


<commit_before>/**
 * app.js
 */
(function (spiderOakApp, window, undefined) {
  "use strict";
  var console = window.console || {};
  console.log = console.log || function(){};
  var Backbone    = window.Backbone,
      _           = window._,
      $           = window.$,
      store       = window.store;
  $.ajaxSettings = _.extend($.ajaxSettings, {
    timeout: 180000, // two minutes
    // timeout: 3000, // three seconds
    error: function(collection, response, options) {
      console.log("Default error handler thrown:");
      // might leave us in a strange state, but better then an endless hang...
      spiderOakApp.dialogView.hide();
      console.log(JSON.stringify(response.statusText));
      spiderOakApp.dialogView.showNotify({
        title: " Error",
        subtitle: "An error occurred.",
        duration: 3000
      });
    }
  });

  // Fix for lack of detach in Zepto...
  $.fn.detach = $.fn.remove;

  // Considering changing the template settings as the ERB defaults are annoying
  // _.templateSettings = {
  //   evaluate:    /\{\{#([\s\S]+?)=\}\}/g,      // {{# console.log("blah") }}
  //   interpolate: /\{\{[^#\{]([\s\S]+?)[^\}]\}\}/g, // {{ title }}
  //   escape:      /\{\{\{([\s\S]+?)\}\}\}/g     // {{{ title }}}
  // };

  _.extend(spiderOakApp, {
    // @TODO: Establish distinct config file and fetch settings from it.
    // Retained values will be held in local storage, and local changes
    // will supercede these default values.
    config: {
      server: {value: "spideroak.com", retain: 1}
    },
    initialize: function() {
      // Stub out iScroll where -webkit-overflow-scrolling:touch is supported
      if (window.Modernizr.overflowscrolling) {
        window.iScroll = function(options) {
          // ...
        };

        window.iScroll.prototype.refresh = function() {
          // ...
        };

        window.iScroll.prototype.destroy = function() {
          // ...
        };
      }
      else {
        // Set some limits for Android 2.x
        spiderOakApp.maxEntries = 100;
      }

      spiderOakApp.settings = new spiderOakApp.SettingsCollection();
      spiderOakApp.accountModel = new spiderOakApp.AccountModel();
      spiderOakApp.menuSheetView = new spiderOakApp.MenuSheetView({
        model: spiderOakApp.accountModel
      }).render();
      // Instantiate the favorites and populate from localStorage
      // trailing slash of weirdness
      var favorites = window.store.get("favorites-");
      favorites = favorites || [];
      spiderOakApp.favoritesCollection =
        new spiderOakApp.FavoritesCollection(favorites);
      var favoritesConfirmationAccepted =
        store.get("favoritesConfirmationAccepted") || false;
      spiderOakApp.accountModel.set("favoritesConfirmationAccepted",
                                    favoritesConfirmationAccepted);
      spiderOakApp.recentsCollection = new spiderOakApp.RecentsCollection();

      // Benefit of the doubt
      this.networkAvailable = true;

      this.version = "0.0.0"; // lame default
      $.ajax({
        url: "./config.xml",
        dataType: "xml",
        success: function(config){
          this.version = $(config).find("widget").attr("version") || "";
        }.bind(this)
      });

      // Start listening for important app-level events
      document.addEventListener("deviceready", this.onDeviceReady, false);
      document.addEventListener("loginSuccess", this.onLoginSuccess, false);
      document.addEventListener("logoutSuccess", this.onLogoutSuccess, false);
      document.addEventListener("resume", this.onResume, false);
      document.addEventListener("offline", this.setOffline, false);
      document.addEventListener("online", this.setOnline, false);
      // Hax for Android 2.x not groking :active
      $(document).on("touchstart", "a", function(event) {
        var $this = $(this);
        $this.addClass("active");
      });
      $(document).on("touchend", "a", function(event) {
        var $this = $(this);
        $this.removeClass("active");
      });
      $(document).on("touchmove", "a", function(event) {
        var $this = $(this);
        $this.removeClass("active");
      });

      // Dragging open the menu
      var touch = {};
      var pxMultiplier = 1;
      var threshold = 80;
      $(document).on("touchstart", "#nav", function(event){
        touch.x1 = event.touches[0].pageX;
        touch.y1 = event.touches[0].pageY;
      });
      $(document).on("touchmove", "#nav", function(event) {
        window.inAction = true;
        if (event.touches.length == 1 ) {
          touch.dx = event.touches[0].pageX - touch.x1; // right, left
          // touch.dy = event.touches[0].pageY - touch.y1; // up, down

          var d = touch.dx * pxMultiplier;
          var pos;
          if (!$("#main").hasClass("open") && touch.dx > 0) {
            pos = (d < 270) ? d : 270;
            $("#main")
              .css({ '-webkit-transform':'translate3d(' + pos + 'px,0,0)' });
          }
          else if ($("#main").hasClass("open") && touch.dx < 0) {
            if ($("#main").hasClass("open")) {
              pos = ((270 - Math.abs(d)) > 0) ? (270 - Math.abs(d)) : 0;
              $("#main")
                .css({ '-webkit-transform':'translate3d(' + pos + 'px,0,0)' });
            }
          }
        }
      });
      $(document).on("touchend touchcancel", "#nav", function(event) {
        if (window.inAction) {
          var d = touch.dx * pxMultiplier;
          if (touch.dx > 0 && !$("#main").hasClass("open")) {
            if (touch.dx > threshold) {
              spiderOakApp.mainView.openMenu();
            }
            else {
              spiderOakApp.mainView.closeMenu();
            }
          }
          else if (touch.dx < 0 && $("#main").hasClass("open")) {
            if (Math.abs(d) > threshold) {
              spiderOakApp.mainView.closeMenu();
            }
            else {
              spiderOakApp.mainView.openMenu();
            }
          }
          touch.dx = 0;
          window.inAction = false;
        }
      });

      // 1. check remember me state, if on...
      // 2. spiderOakApp.dialogView.showWait();
      // 3. spiderOakApp.loginView.dismiss();
      // 4. <get the user data from AccountManager plugin>
      // 5. spiderOakApp.accountModel =
      //        new spiderOakApp.AccountModel(<serialised AccountModel>);
      // 6. spiderOakApp.accountModel
      //        .basicAuthManager.setAccountBasicAuth(<username>, <password>);
      // 7. spiderOakApp.onLoginSuccess();
      var rememberedAccount =
        spiderOakApp.settings.getOrDefault("rememberedAccount");
      if (rememberedAccount) {
        var rememberedAccountModel = JSON.parse(rememberedAccount);
        var credentials = atob(rememberedAccountModel
          .basicAuthCredentials.split(" ")[1]).split(":");
        spiderOakApp.dialogView.showWait();
        spiderOakApp.accountModel =
          new spiderOakApp.AccountModel(rememberedAccountModel);
        spiderOakApp.accountModel.basicAuthManager
          .setAccountBasicAuth(credentials[0], credentials[1]);
        spiderOakApp.onLoginSuccess();
        spiderOakApp.loginView.dismiss();
        $(".splash").hide();
        spiderOakApp.dialogView.hide();
        return;
      }
      $(".splash").hide();

      if (!window.store.get("favoritesMigrationHasRun") && $.os.android) {
        spiderOakApp.migrateFavorites();
      }

    },
    backDisabled: true,
    onDeviceReady: function() {
      document.addEventListener(
        "backbutton",
        spiderOakApp.onBackKeyDown,
        false
      );
      document.addEventListener(
        "menubutton",
        spiderOakApp.onMenuKeyDown,
        false
      );
      // @FIXME: This seems cludgey
      if (window.cssLoaded) navigator.splashscreen.hide();
      // @TODO: Instantiate any plugins
      spiderOakApp.fileViewer = window.cordova &&
        window.cordova.require("cordova/plugin/fileviewerplugin");
    },
    setOnline: function(event) {
      if (!this.networkAvailable) {
        spiderOakApp.menuSheetView.render(true);
      }
      this.networkAvailable = true;
    },
    setOffline: function(event) {
      this.networkAvailable = false;
      var onConfirm = function() {
        // modally block the UI
      };
      navigator.notification.confirm(
        "Sorry. You should still be able to access your favorites, but " +
          "Logging in and access to files or folders requires " +
          "a network connection.",
        onConfirm,
        'Network error',
        'OK'
      );
      spiderOakApp.dialogView.hide(); // In case one is up, say login..
    },
    onResume: function(event) {
      // ...
    },
    onLoginSuccess: function() {
      spiderOakApp.menuSheetView.render();
      spiderOakApp.storageBarModel = new spiderOakApp.StorageBarModel();
      spiderOakApp.storageBarModel.url =
        spiderOakApp.accountModel.get("storageRootURL");
      var favoritesConfirmationAccepted =
        store.get("favoritesConfirmationAccepted-" +
        spiderOakApp.accountModel.get("b32username")) || false;
      spiderOakApp.accountModel.set("favoritesConfirmationAccepted",
                                    favoritesConfirmationAccepted);
      spiderOakApp.storageBarView = new spiderOakApp.StorageBarView({
        model: spiderOakApp.storageBarModel
      });
      // Instantiate the favorites and populate from localStorage
      var favorites = window.store.get(
        "favorites-" + spiderOakApp.accountModel.get("b32username")
      );
      favorites = favorites || [];
      spiderOakApp.favoritesCollection =
        new spiderOakApp.FavoritesCollection(favorites);

      // Fresh new recents collection
      spiderOakApp.recentsCollection = new spiderOakApp.RecentsCollection();
      spiderOakApp.dialogView.hide();
    },
    onLogoutSuccess: function() {
      if (spiderOakApp.navigator.viewsStack.length > 0) {
        spiderOakApp.navigator.popAll(spiderOakApp.noEffect);
      }
      spiderOakApp.mainView.setTitle("SpiderOak");

      // Instantiate the favorites and populate from localStorage
      // trailing slash of weirdness
      var favorites = window.store.get("favorites-");
      favorites = favorites || [];
      spiderOakApp.favoritesCollection.reset(favorites);

      spiderOakApp.recentsCollection.reset();
      if (spiderOakApp.storageBarView) {
        spiderOakApp.storageBarView.empty();
      }
      if (spiderOakApp.shareRoomsCollection) {
        spiderOakApp.shareRoomsCollection.reset();
      }
      if (spiderOakApp.publicShareRoomsCollection) {
        spiderOakApp.publicShareRoomsCollection.reset();
      }
      // And finally, pop up the LoginView
      spiderOakApp.mainView.closeMenu();
      spiderOakApp.loginView.show();
    },
    onBackKeyDown: function(event) {
      event.preventDefault();
      if ($(".modal").is(":visible") ||
          $(".learn-about-spideroak").is(":visible")) {
        return;
      }
      // @FIXME: Extend this logic a bit... it's a bit simplistic
      if ($("#main").hasClass("open")) {
        spiderOakApp.mainView.closeMenu();
        return;
      }
      if ($(".nav .back-btn").is(":visible")) {
        spiderOakApp.navigator.popView(spiderOakApp.defaultEffect);
        return;
      }
      navigator.app.exitApp();
    },
    onMenuKeyDown: function(event) {
      if ($("#main").hasClass("open")) {
        spiderOakApp.mainView.closeMenu();
      }
      else {
        spiderOakApp.mainView.openMenu();
      }
    },
    downloader: new window.FileDownloadHelper(),
    navigator: new window.BackStack.StackNavigator({el:'#subviews'}),
    noEffect: new window.BackStack.NoEffect(),
    fadeEffect: new window.BackStack.FadeEffect(),
    defaultEffect: (($.os.android) ? new window.BackStack.NoEffect() : null),
    b32nibbler: new window.Nibbler({dataBits: 8,
                                    codeBits: 5,
                                    keyString:
                                      "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
                                    pad: ""
                                   })
  });

  /*
   * How a model in our framework determines its' composite URL.
   *
   * The URL is a concatenation of model and collection url elements.  Any
   * prevailing elements that are functions are evaluated, as methods on
   * the object from which they were obtained, for their result.
   *
   * - A head part is taken in this order of precedence:
   *   - the model's .get("urlBase")
   *   - or the model's urlBase attribute
   *   - or the containing collection's .urlBase
   *   - or the containing collection's .url
   * - The url part is taken from the model's .get("url").
   *
   * @this{model}
   # @param {boolen} bare - when set, strip any query string
   */
  Backbone.Model.prototype.composedUrl = function(bare) {
    var urlTail = this.get("url");
    var collection = this.collection;
    var urlHead = this.get("urlBase") || this.urlBase;
    var urlHeadObject = urlHead && this;
    if (! urlHead && collection) {
      urlHead = (collection.get("urlBase") ||
                  collection.urlBase ||
                  collection.url ||
                  "");
      urlHeadObject = urlHead && collection;
    }
    if (typeof urlHead === "function") {
      urlHead = urlHead.call(urlHeadObject);
    }
    if (typeof urlTail === "function") {
      urlTail = urlTail.call(this);
    }
    if (bare) {
      urlHead = urlHead && urlHead.split("?")[0];
      urlTail = urlTail && urlTail.split("?")[0];
    }
    var result = (urlHead || "") + (urlTail || "");
    return result;
  };

  if (! window.cordova || window.cordova.cordovaAbsent) {
    /* Polyfill for file downloader functionality. */
    // This enables, eg, creating favorites.  You still can't view files...
    // We can't do this in cordova polyfills, because it depends on
    // spiderOakApp object existing.
    window.LocalFileSystem = {PERSISTENT: null,
                              TEMPORARY: null};
    spiderOakApp.downloader.downloadFile = function (downloadOptions,
                                                     successCallback,
                                                     errorCallback) {
      spiderOakApp.dialogView.showWait({
        title: "Debugging mode: Dowloading Inhibited"
      });
      var dummyFileEntry = {fullPath: "/sdcard" + downloadOptions.to,
                            name: downloadOptions.fileName};
      return successCallback(dummyFileEntry);
    };
  }

})(window.spiderOakApp = window.spiderOakApp || {}, window);

/* Function.bind polyfill */

if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // closest thing possible to the ECMAScript 5 internal IsCallable function
      throw new TypeError("Function.prototype.bind - " +
        "what is trying to be bound is not callable");
    }

    var aArgs = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        FNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof FNOP && oThis ? this : oThis,
                          aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    FNOP.prototype = this.prototype;
    fBound.prototype = new FNOP();

    return fBound;
  };
}
<commit_msg>We can now create and remove favorites without the cordova file downloader, eg in the desktop browser.  The file's contents is not downloaded, but we can exercise the rest of the favorites system.<commit_after>/**
 * app.js
 */
(function (spiderOakApp, window, undefined) {
  "use strict";
  var console = window.console || {};
  console.log = console.log || function(){};
  var Backbone    = window.Backbone,
      _           = window._,
      $           = window.$,
      store       = window.store;
  $.ajaxSettings = _.extend($.ajaxSettings, {
    timeout: 180000, // two minutes
    // timeout: 3000, // three seconds
    error: function(collection, response, options) {
      console.log("Default error handler thrown:");
      // might leave us in a strange state, but better then an endless hang...
      spiderOakApp.dialogView.hide();
      console.log(JSON.stringify(response.statusText));
      spiderOakApp.dialogView.showNotify({
        title: " Error",
        subtitle: "An error occurred.",
        duration: 3000
      });
    }
  });

  // Fix for lack of detach in Zepto...
  $.fn.detach = $.fn.remove;

  // Considering changing the template settings as the ERB defaults are annoying
  // _.templateSettings = {
  //   evaluate:    /\{\{#([\s\S]+?)=\}\}/g,      // {{# console.log("blah") }}
  //   interpolate: /\{\{[^#\{]([\s\S]+?)[^\}]\}\}/g, // {{ title }}
  //   escape:      /\{\{\{([\s\S]+?)\}\}\}/g     // {{{ title }}}
  // };

  _.extend(spiderOakApp, {
    // @TODO: Establish distinct config file and fetch settings from it.
    // Retained values will be held in local storage, and local changes
    // will supercede these default values.
    config: {
      server: {value: "spideroak.com", retain: 1}
    },
    initialize: function() {
      // Stub out iScroll where -webkit-overflow-scrolling:touch is supported
      if (window.Modernizr.overflowscrolling) {
        window.iScroll = function(options) {
          // ...
        };

        window.iScroll.prototype.refresh = function() {
          // ...
        };

        window.iScroll.prototype.destroy = function() {
          // ...
        };
      }
      else {
        // Set some limits for Android 2.x
        spiderOakApp.maxEntries = 100;
      }

      spiderOakApp.settings = new spiderOakApp.SettingsCollection();
      spiderOakApp.accountModel = new spiderOakApp.AccountModel();
      spiderOakApp.menuSheetView = new spiderOakApp.MenuSheetView({
        model: spiderOakApp.accountModel
      }).render();
      // Instantiate the favorites and populate from localStorage
      // trailing slash of weirdness
      var favorites = window.store.get("favorites-");
      favorites = favorites || [];
      spiderOakApp.favoritesCollection =
        new spiderOakApp.FavoritesCollection(favorites);
      var favoritesConfirmationAccepted =
        store.get("favoritesConfirmationAccepted") || false;
      spiderOakApp.accountModel.set("favoritesConfirmationAccepted",
                                    favoritesConfirmationAccepted);
      spiderOakApp.recentsCollection = new spiderOakApp.RecentsCollection();

      // Benefit of the doubt
      this.networkAvailable = true;

      this.version = "0.0.0"; // lame default
      $.ajax({
        url: "./config.xml",
        dataType: "xml",
        success: function(config){
          this.version = $(config).find("widget").attr("version") || "";
        }.bind(this)
      });

      // Start listening for important app-level events
      document.addEventListener("deviceready", this.onDeviceReady, false);
      document.addEventListener("loginSuccess", this.onLoginSuccess, false);
      document.addEventListener("logoutSuccess", this.onLogoutSuccess, false);
      document.addEventListener("resume", this.onResume, false);
      document.addEventListener("offline", this.setOffline, false);
      document.addEventListener("online", this.setOnline, false);
      // Hax for Android 2.x not groking :active
      $(document).on("touchstart", "a", function(event) {
        var $this = $(this);
        $this.addClass("active");
      });
      $(document).on("touchend", "a", function(event) {
        var $this = $(this);
        $this.removeClass("active");
      });
      $(document).on("touchmove", "a", function(event) {
        var $this = $(this);
        $this.removeClass("active");
      });

      // Dragging open the menu
      var touch = {};
      var pxMultiplier = 1;
      var threshold = 80;
      $(document).on("touchstart", "#nav", function(event){
        touch.x1 = event.touches[0].pageX;
        touch.y1 = event.touches[0].pageY;
      });
      $(document).on("touchmove", "#nav", function(event) {
        window.inAction = true;
        if (event.touches.length == 1 ) {
          touch.dx = event.touches[0].pageX - touch.x1; // right, left
          // touch.dy = event.touches[0].pageY - touch.y1; // up, down

          var d = touch.dx * pxMultiplier;
          var pos;
          if (!$("#main").hasClass("open") && touch.dx > 0) {
            pos = (d < 270) ? d : 270;
            $("#main")
              .css({ '-webkit-transform':'translate3d(' + pos + 'px,0,0)' });
          }
          else if ($("#main").hasClass("open") && touch.dx < 0) {
            if ($("#main").hasClass("open")) {
              pos = ((270 - Math.abs(d)) > 0) ? (270 - Math.abs(d)) : 0;
              $("#main")
                .css({ '-webkit-transform':'translate3d(' + pos + 'px,0,0)' });
            }
          }
        }
      });
      $(document).on("touchend touchcancel", "#nav", function(event) {
        if (window.inAction) {
          var d = touch.dx * pxMultiplier;
          if (touch.dx > 0 && !$("#main").hasClass("open")) {
            if (touch.dx > threshold) {
              spiderOakApp.mainView.openMenu();
            }
            else {
              spiderOakApp.mainView.closeMenu();
            }
          }
          else if (touch.dx < 0 && $("#main").hasClass("open")) {
            if (Math.abs(d) > threshold) {
              spiderOakApp.mainView.closeMenu();
            }
            else {
              spiderOakApp.mainView.openMenu();
            }
          }
          touch.dx = 0;
          window.inAction = false;
        }
      });

      // 1. check remember me state, if on...
      // 2. spiderOakApp.dialogView.showWait();
      // 3. spiderOakApp.loginView.dismiss();
      // 4. <get the user data from AccountManager plugin>
      // 5. spiderOakApp.accountModel =
      //        new spiderOakApp.AccountModel(<serialised AccountModel>);
      // 6. spiderOakApp.accountModel
      //        .basicAuthManager.setAccountBasicAuth(<username>, <password>);
      // 7. spiderOakApp.onLoginSuccess();
      var rememberedAccount =
        spiderOakApp.settings.getOrDefault("rememberedAccount");
      if (rememberedAccount) {
        var rememberedAccountModel = JSON.parse(rememberedAccount);
        var credentials = atob(rememberedAccountModel
          .basicAuthCredentials.split(" ")[1]).split(":");
        spiderOakApp.dialogView.showWait();
        spiderOakApp.accountModel =
          new spiderOakApp.AccountModel(rememberedAccountModel);
        spiderOakApp.accountModel.basicAuthManager
          .setAccountBasicAuth(credentials[0], credentials[1]);
        spiderOakApp.onLoginSuccess();
        spiderOakApp.loginView.dismiss();
        $(".splash").hide();
        spiderOakApp.dialogView.hide();
        return;
      }
      $(".splash").hide();

      if (!window.store.get("favoritesMigrationHasRun") && $.os.android) {
        spiderOakApp.migrateFavorites();
      }

    },
    backDisabled: true,
    onDeviceReady: function() {
      document.addEventListener(
        "backbutton",
        spiderOakApp.onBackKeyDown,
        false
      );
      document.addEventListener(
        "menubutton",
        spiderOakApp.onMenuKeyDown,
        false
      );
      // @FIXME: This seems cludgey
      if (window.cssLoaded) navigator.splashscreen.hide();
      // @TODO: Instantiate any plugins
      spiderOakApp.fileViewer = window.cordova &&
        window.cordova.require("cordova/plugin/fileviewerplugin");
    },
    setOnline: function(event) {
      if (!this.networkAvailable) {
        spiderOakApp.menuSheetView.render(true);
      }
      this.networkAvailable = true;
    },
    setOffline: function(event) {
      this.networkAvailable = false;
      var onConfirm = function() {
        // modally block the UI
      };
      navigator.notification.confirm(
        "Sorry. You should still be able to access your favorites, but " +
          "Logging in and access to files or folders requires " +
          "a network connection.",
        onConfirm,
        'Network error',
        'OK'
      );
      spiderOakApp.dialogView.hide(); // In case one is up, say login..
    },
    onResume: function(event) {
      // ...
    },
    onLoginSuccess: function() {
      spiderOakApp.menuSheetView.render();
      spiderOakApp.storageBarModel = new spiderOakApp.StorageBarModel();
      spiderOakApp.storageBarModel.url =
        spiderOakApp.accountModel.get("storageRootURL");
      var favoritesConfirmationAccepted =
        store.get("favoritesConfirmationAccepted-" +
        spiderOakApp.accountModel.get("b32username")) || false;
      spiderOakApp.accountModel.set("favoritesConfirmationAccepted",
                                    favoritesConfirmationAccepted);
      spiderOakApp.storageBarView = new spiderOakApp.StorageBarView({
        model: spiderOakApp.storageBarModel
      });
      // Instantiate the favorites and populate from localStorage
      var favorites = window.store.get(
        "favorites-" + spiderOakApp.accountModel.get("b32username")
      );
      favorites = favorites || [];
      spiderOakApp.favoritesCollection =
        new spiderOakApp.FavoritesCollection(favorites);

      // Fresh new recents collection
      spiderOakApp.recentsCollection = new spiderOakApp.RecentsCollection();
      spiderOakApp.dialogView.hide();
    },
    onLogoutSuccess: function() {
      if (spiderOakApp.navigator.viewsStack.length > 0) {
        spiderOakApp.navigator.popAll(spiderOakApp.noEffect);
      }
      spiderOakApp.mainView.setTitle("SpiderOak");

      // Instantiate the favorites and populate from localStorage
      // trailing slash of weirdness
      var favorites = window.store.get("favorites-");
      favorites = favorites || [];
      spiderOakApp.favoritesCollection.reset(favorites);

      spiderOakApp.recentsCollection.reset();
      if (spiderOakApp.storageBarView) {
        spiderOakApp.storageBarView.empty();
      }
      if (spiderOakApp.shareRoomsCollection) {
        spiderOakApp.shareRoomsCollection.reset();
      }
      if (spiderOakApp.publicShareRoomsCollection) {
        spiderOakApp.publicShareRoomsCollection.reset();
      }
      // And finally, pop up the LoginView
      spiderOakApp.mainView.closeMenu();
      spiderOakApp.loginView.show();
    },
    onBackKeyDown: function(event) {
      event.preventDefault();
      if ($(".modal").is(":visible") ||
          $(".learn-about-spideroak").is(":visible")) {
        return;
      }
      // @FIXME: Extend this logic a bit... it's a bit simplistic
      if ($("#main").hasClass("open")) {
        spiderOakApp.mainView.closeMenu();
        return;
      }
      if ($(".nav .back-btn").is(":visible")) {
        spiderOakApp.navigator.popView(spiderOakApp.defaultEffect);
        return;
      }
      navigator.app.exitApp();
    },
    onMenuKeyDown: function(event) {
      if ($("#main").hasClass("open")) {
        spiderOakApp.mainView.closeMenu();
      }
      else {
        spiderOakApp.mainView.openMenu();
      }
    },
    downloader: new window.FileDownloadHelper(),
    navigator: new window.BackStack.StackNavigator({el:'#subviews'}),
    noEffect: new window.BackStack.NoEffect(),
    fadeEffect: new window.BackStack.FadeEffect(),
    defaultEffect: (($.os.android) ? new window.BackStack.NoEffect() : null),
    b32nibbler: new window.Nibbler({dataBits: 8,
                                    codeBits: 5,
                                    keyString:
                                      "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
                                    pad: ""
                                   })
  });

  /*
   * How a model in our framework determines its' composite URL.
   *
   * The URL is a concatenation of model and collection url elements.  Any
   * prevailing elements that are functions are evaluated, as methods on
   * the object from which they were obtained, for their result.
   *
   * - A head part is taken in this order of precedence:
   *   - the model's .get("urlBase")
   *   - or the model's urlBase attribute
   *   - or the containing collection's .urlBase
   *   - or the containing collection's .url
   * - The url part is taken from the model's .get("url").
   *
   * @this{model}
   # @param {boolen} bare - when set, strip any query string
   */
  Backbone.Model.prototype.composedUrl = function(bare) {
    var urlTail = this.get("url");
    var collection = this.collection;
    var urlHead = this.get("urlBase") || this.urlBase;
    var urlHeadObject = urlHead && this;
    if (! urlHead && collection) {
      urlHead = (collection.get("urlBase") ||
                  collection.urlBase ||
                  collection.url ||
                  "");
      urlHeadObject = urlHead && collection;
    }
    if (typeof urlHead === "function") {
      urlHead = urlHead.call(urlHeadObject);
    }
    if (typeof urlTail === "function") {
      urlTail = urlTail.call(this);
    }
    if (bare) {
      urlHead = urlHead && urlHead.split("?")[0];
      urlTail = urlTail && urlTail.split("?")[0];
    }
    var result = (urlHead || "") + (urlTail || "");
    return result;
  };

  if (! window.cordova || window.cordova.cordovaAbsent) {
    /* Polyfill for file downloader functionality. */
    // This enables, eg, creating favorites.  You still can't view files...
    // We can't do this in cordova polyfills, because it depends on
    // spiderOakApp object existing.
    if (! window.LocalFileSystem) {
      window.LocalFileSystem = {TEMPORARY: 0,
                                PERSISTENT: 1};
    }
    if (! window.requestFileSystem) {
      window.requestFileSystem = function (options, something,
                                           gotFS, notGotFS) {
        // Call the gotFS(filesystem) success callback
        return gotFS({
          // ... on a pseudo-filesystem object with a 'root' element:
          root: {
            // ... with a 'getFile' method:
            getFile: function (path, options, gotFile, notGotFile) {
              // ... that applies a gotFile success callback:
              return gotFile({
                // ... to a pseudo-fileEntry object with a 'remove' method:
                remove: function (removed, notRemoved) {
                  // ... that calls its' removed callback:
                  return removed();
                }
              });
            }}
        });
      };
    }
    if (! window.FileTransfer) {
      spiderOakApp.downloader.downloadFile = function (downloadOptions,
                                                       successCallback,
                                                       errorCallback) {
        console.log("fake downloadFile");
        spiderOakApp.dialogView.showWait({
          title: "Debugging mode: Contents not dowloaded"
        });
        var dummyFileEntry = {fullPath: "/sdcard" + downloadOptions.to,
                              name: downloadOptions.fileName};
        return successCallback(dummyFileEntry);
      };
    }
  }

})(window.spiderOakApp = window.spiderOakApp || {}, window);

/* Function.bind polyfill */

if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // closest thing possible to the ECMAScript 5 internal IsCallable function
      throw new TypeError("Function.prototype.bind - " +
        "what is trying to be bound is not callable");
    }

    var aArgs = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        FNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof FNOP && oThis ? this : oThis,
                          aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    FNOP.prototype = this.prototype;
    fBound.prototype = new FNOP();

    return fBound;
  };
}
<|endoftext|>


<commit_before>var path = require('path');

var CollectionError = require(path.join(__dirname, '..', 'CollectionError'));

module.exports = function (logger, di, apiClasses, createFunctions) {

    var original = {
        di: di,
        Error: CollectionError,
        apiClasses: apiClasses,
        createFunctions: createFunctions,
        api: {}
    };

    logger.debug('create proxy to api object');

    var proxy = new Proxy(original, {

        get: function (target, name/*, receiver*/) {

            // typeof name === 'symbol'
            if (typeof name !== 'string') {
                return target;
            }

            name = String(name);

            if (['then', 'catch'].indexOf(name) > -1) {
                return null;
            }

            if (!target.apiClasses[name]) {
                throw new target.Error(target.Error.CODES.UNKNOWN_API).bind({name: name});
            }

            if (!target.api[name]) {

                var createFn = target.createFunctions.default;

                if (typeof target.createFunctions[name] === 'function') {
                    createFn = target.createFunctions[name];
                }

                target.api[name] = createFn(target.di, target.apiClasses[name]);
            }

            return target.api[name];

        },

        // has: function (target, name) {
        //     console.log(name);
        //     if (target.apiClasses[name]) {
        //         return true;
        //     }
        //
        //     return false;
        // },

        ownKeys: function (target) {
            return Object.keys(target.apiClasses);
        },

        isExtensible: function () {
            return false;
        },

        preventExtensions: function () {
            return false;
        },

        defineProperty: function () {
            return false;
        },

        deleteProperty: function () {
            return false;
        }

    });

    logger.debug('api proxy created');

    return proxy;

};
<commit_msg>chg: dev: cleanup<commit_after>var path = require('path');

var CollectionError = require(path.join(__dirname, '..', 'CollectionError'));

module.exports = function (logger, di, apiClasses, createFunctions) {

    var original = {
        di: di,
        Error: CollectionError,
        apiClasses: apiClasses,
        createFunctions: createFunctions,
        api: {}
    };

    logger.debug('create proxy to api object');

    var proxy = new Proxy(original, {

        get: function (target, name/*, receiver*/) {

            // typeof name === 'symbol'
            if (typeof name !== 'string') {
                return target;
            }

            name = String(name);

            if (['then', 'catch'].indexOf(name) > -1) {
                return null;
            }

            if (!target.apiClasses[name]) {
                throw new target.Error(target.Error.CODES.UNKNOWN_API).bind({name: name});
            }

            if (!target.api[name]) {

                var createFn = target.createFunctions.default;

                if (typeof target.createFunctions[name] === 'function') {
                    createFn = target.createFunctions[name];
                }

                target.api[name] = createFn(target.di, target.apiClasses[name]);
            }

            return target.api[name];

        },

        // has: function (target, name) {
        //     if (target.apiClasses[name]) {
        //         return true;
        //     }
        //
        //     return false;
        // },

        ownKeys: function (target) {
            return Object.keys(target.apiClasses);
        },

        isExtensible: function () {
            return false;
        },

        preventExtensions: function () {
            return false;
        },

        defineProperty: function () {
            return false;
        },

        deleteProperty: function () {
            return false;
        }

    });

    logger.debug('api proxy created');

    return proxy;

};
<|endoftext|>