├── vendor
└── .gitkeep
├── app
├── components
│ ├── .gitkeep
│ ├── radial-progress-indicator.js
│ ├── instance-holder.js
│ ├── action-bar.js
│ ├── profile-pic.js
│ ├── reveal-modal.js
│ ├── file-select-drop.js
│ └── thumbnail-slider.js
├── helpers
│ ├── .gitkeep
│ └── extension-mapping.js
├── models
│ ├── .gitkeep
│ └── user.js
├── routes
│ ├── .gitkeep
│ ├── signin.js
│ ├── signup.js
│ ├── users.js
│ ├── about.js
│ ├── people.js
│ ├── profile.js
│ ├── home
│ │ └── sidebar.js
│ ├── application.js
│ ├── notifications.js
│ ├── people
│ │ ├── find.js
│ │ └── detail.js
│ └── home.js
├── controllers
│ ├── .gitkeep
│ ├── users.js
│ ├── signin.js
│ ├── application.js
│ ├── header-nav.js
│ ├── home.js
│ ├── people
│ │ ├── find.js
│ │ └── detail.js
│ ├── profile.js
│ ├── home
│ │ ├── sidebar.js
│ │ └── dropzone.js
│ ├── notifications.js
│ └── signup.js
├── templates
│ ├── components
│ │ ├── .gitkeep
│ │ ├── radial-progress-indicator.hbs
│ │ ├── instance-holder.hbs
│ │ ├── file-select-drop.hbs
│ │ ├── profile-pic.hbs
│ │ ├── action-bar.hbs
│ │ ├── reveal-modal.hbs
│ │ └── thumbnail-slider.hbs
│ ├── people.hbs
│ ├── users.hbs
│ ├── about.hbs
│ ├── application.hbs
│ ├── people
│ │ ├── find.hbs
│ │ └── detail.hbs
│ ├── signin.hbs
│ ├── home
│ │ ├── dropzone.hbs
│ │ └── sidebar.hbs
│ ├── notifications.hbs
│ ├── header-nav.hbs
│ ├── home.hbs
│ ├── profile.hbs
│ └── signup.hbs
├── styles
│ ├── mixins.scss
│ ├── pages
│ │ ├── notifications.scss
│ │ ├── signin.scss
│ │ ├── about.scss
│ │ ├── profile.scss
│ │ ├── signup.scss
│ │ ├── people.scss
│ │ └── home.scss
│ ├── bootstrap-variables.scss
│ ├── app.scss
│ └── components
│ │ ├── reveal-modal.scss
│ │ └── radial-progress-indicator.scss
├── adapters
│ └── application.js
├── app.js
├── router.js
├── mixins
│ ├── pretty-bytes.js
│ └── signin-user.js
├── services
│ ├── blob.js
│ ├── webtorrent.js
│ ├── file.js
│ ├── users.js
│ ├── ips.js
│ ├── webrtc.js
│ └── webrtc-v1.js
├── index.html
├── utils
│ ├── context-menu.js
│ └── window-menu.js
└── transitions.js
├── tests
├── unit
│ ├── .gitkeep
│ ├── routes
│ │ ├── signin-test.js
│ │ ├── signup-test.js
│ │ ├── users-test.js
│ │ ├── profile-test.js
│ │ ├── application-test.js
│ │ └── notifications-test.js
│ ├── models
│ │ └── user-test.js
│ ├── controllers
│ │ ├── signin-test.js
│ │ ├── signup-test.js
│ │ ├── users-test.js
│ │ └── application-test.js
│ └── mixins
│ │ ├── signin-user-test.js
│ │ └── pretty-bytes-test.js
├── .eslintrc.js
├── package.json
├── test-helper.js
├── helpers
│ ├── resolver.js
│ └── start-app.js
├── integration
│ └── components
│ │ ├── profile-pic-test.js
│ │ ├── reveal-modal-test.js
│ │ └── instance-holder-test.js
├── electron.js
├── .jshintrc
└── index.html
├── .watchmanconfig
├── .eslintrc
├── public
├── robots.txt
├── images
│ ├── favicon.ico
│ ├── icons
│ │ ├── doc.png
│ │ ├── pdf.png
│ │ ├── ppt.png
│ │ ├── txt.png
│ │ ├── movie.png
│ │ ├── music.png
│ │ ├── photo.png
│ │ ├── contacts.png
│ │ ├── network.png
│ │ ├── search.png
│ │ ├── unknown.png
│ │ ├── compressed.png
│ │ └── photoshop.png
│ ├── dummy
│ │ ├── ajain.png
│ │ ├── suganthi.png
│ │ └── szymon.jpeg
│ ├── placeholder_profile.png
│ ├── logo
│ │ ├── p2pdrop-logo-128.png
│ │ ├── p2pdrop-logo-256.png
│ │ ├── p2pdrop-logo-32.png
│ │ ├── p2pdrop-logo-512.png
│ │ ├── p2pdrop-logo-64.png
│ │ ├── p2pdrop-logo-green-128.png
│ │ ├── p2pdrop-logo-green-256.png
│ │ ├── p2pdrop-logo-green-512.png
│ │ ├── p2pdrop-logo-white-128.png
│ │ ├── p2pdrop-logo-white-256.png
│ │ └── p2pdrop-logo-white-512.png
│ └── apple-touch-icon-precomposed.png
└── crossdomain.xml
├── .bowerrc
├── assets
├── icons
│ ├── ghost.ico
│ ├── ghost.icns
│ ├── ghost2.icns
│ ├── ghost2.ico
│ ├── ghost-osx.png
│ ├── Ghost-Icons.sketch
│ └── ghost-windows.png
├── dmg
│ └── background.png
├── icons_1
│ ├── p2pdrop.icns
│ ├── p2pdrop.ico
│ ├── p2pdrop-osx.png
│ └── p2pdrop-windows.png
└── win
│ └── installer-dev.gif
├── testem.json
├── .eslintrc.js
├── .ember-cli
├── .gitignore
├── .travis.yml
├── .jshintrc
├── .editorconfig
├── _appdmg.json
├── .sass-lint.yml
├── bower.json
├── electron.js
├── main
├── load-error
│ └── error.html
├── squirrel.js
├── window-state.js
├── entry.js
└── preload.js
├── ember-cli-build.js
├── package.json
├── config
└── environment.js
└── README.md
/vendor/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/routes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/components/radial-progress-indicator.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp"]
3 | }
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./config/eslint.js"
3 | }
4 |
--------------------------------------------------------------------------------
/app/templates/components/radial-progress-indicator.hbs:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components",
3 | "analytics": false
4 | }
5 |
--------------------------------------------------------------------------------
/app/templates/components/instance-holder.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/assets/icons/ghost.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons/ghost.ico
--------------------------------------------------------------------------------
/tests/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | 'embertest': true
4 | }
5 | };
6 |
--------------------------------------------------------------------------------
/tests/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-electron-test",
3 | "main": "electron.js"
4 | }
5 |
--------------------------------------------------------------------------------
/assets/icons/ghost.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons/ghost.icns
--------------------------------------------------------------------------------
/assets/icons/ghost2.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons/ghost2.icns
--------------------------------------------------------------------------------
/assets/icons/ghost2.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons/ghost2.ico
--------------------------------------------------------------------------------
/app/routes/signin.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | });
5 |
--------------------------------------------------------------------------------
/app/routes/signup.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | });
5 |
--------------------------------------------------------------------------------
/assets/dmg/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/dmg/background.png
--------------------------------------------------------------------------------
/assets/icons/ghost-osx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons/ghost-osx.png
--------------------------------------------------------------------------------
/assets/icons_1/p2pdrop.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons_1/p2pdrop.icns
--------------------------------------------------------------------------------
/assets/icons_1/p2pdrop.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons_1/p2pdrop.ico
--------------------------------------------------------------------------------
/public/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/favicon.ico
--------------------------------------------------------------------------------
/public/images/icons/doc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/doc.png
--------------------------------------------------------------------------------
/public/images/icons/pdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/pdf.png
--------------------------------------------------------------------------------
/public/images/icons/ppt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/ppt.png
--------------------------------------------------------------------------------
/public/images/icons/txt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/txt.png
--------------------------------------------------------------------------------
/assets/win/installer-dev.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/win/installer-dev.gif
--------------------------------------------------------------------------------
/public/images/dummy/ajain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/dummy/ajain.png
--------------------------------------------------------------------------------
/public/images/icons/movie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/movie.png
--------------------------------------------------------------------------------
/public/images/icons/music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/music.png
--------------------------------------------------------------------------------
/public/images/icons/photo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/photo.png
--------------------------------------------------------------------------------
/app/styles/mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin max-height($max) {
2 | @media (max-height: $max){
3 | @content;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/assets/icons/Ghost-Icons.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons/Ghost-Icons.sketch
--------------------------------------------------------------------------------
/assets/icons/ghost-windows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons/ghost-windows.png
--------------------------------------------------------------------------------
/assets/icons_1/p2pdrop-osx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons_1/p2pdrop-osx.png
--------------------------------------------------------------------------------
/public/images/dummy/suganthi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/dummy/suganthi.png
--------------------------------------------------------------------------------
/public/images/dummy/szymon.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/dummy/szymon.jpeg
--------------------------------------------------------------------------------
/public/images/icons/contacts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/contacts.png
--------------------------------------------------------------------------------
/public/images/icons/network.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/network.png
--------------------------------------------------------------------------------
/public/images/icons/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/search.png
--------------------------------------------------------------------------------
/public/images/icons/unknown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/unknown.png
--------------------------------------------------------------------------------
/app/templates/people.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{liquid-outlet}}
4 |
5 |
--------------------------------------------------------------------------------
/assets/icons_1/p2pdrop-windows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/assets/icons_1/p2pdrop-windows.png
--------------------------------------------------------------------------------
/public/images/icons/compressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/compressed.png
--------------------------------------------------------------------------------
/public/images/icons/photoshop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/icons/photoshop.png
--------------------------------------------------------------------------------
/public/images/placeholder_profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/placeholder_profile.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-128.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-256.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-32.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-512.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-64.png
--------------------------------------------------------------------------------
/public/images/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-green-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-green-128.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-green-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-green-256.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-green-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-green-512.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-white-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-white-128.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-white-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-white-256.png
--------------------------------------------------------------------------------
/public/images/logo/p2pdrop-logo-white-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajainvivek/P2PDrop/HEAD/public/images/logo/p2pdrop-logo-white-512.png
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import resolver from './helpers/resolver';
2 | import {
3 | setResolver
4 | } from 'ember-qunit';
5 |
6 | setResolver(resolver);
7 |
--------------------------------------------------------------------------------
/app/routes/users.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | const {Route} = Ember;
3 |
4 | export default Route.extend({
5 | model(){
6 | return this.store.findAll('user');
7 | }
8 | });
9 |
--------------------------------------------------------------------------------
/app/routes/about.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
3 |
4 | export default Ember.Route.extend(AuthenticatedRouteMixin, {
5 | });
6 |
--------------------------------------------------------------------------------
/app/routes/people.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
3 |
4 | export default Ember.Route.extend(AuthenticatedRouteMixin, {
5 | });
6 |
--------------------------------------------------------------------------------
/app/routes/profile.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
3 |
4 | export default Ember.Route.extend(AuthenticatedRouteMixin, {
5 | });
6 |
--------------------------------------------------------------------------------
/app/adapters/application.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import FirebaseAdapter from 'emberfire/adapters/firebase';
3 |
4 | const { inject } = Ember;
5 |
6 | export default FirebaseAdapter.extend({
7 | firebase: inject.service()
8 | });
9 |
--------------------------------------------------------------------------------
/testem.json:
--------------------------------------------------------------------------------
1 | {
2 | "framework": "qunit",
3 | "test_page": "tests/index.html?hidepassed",
4 | "disable_watching": true,
5 | "launch_in_ci": [
6 | "PhantomJS"
7 | ],
8 | "launch_in_dev": [
9 | "PhantomJS",
10 | "Chrome"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/app/styles/pages/notifications.scss:
--------------------------------------------------------------------------------
1 | #notification {
2 | width: 80%;
3 | margin: 0px auto;
4 | padding: 10px;
5 | background: #fafafa;
6 | border: 1px solid #ebebeb;
7 | box-shadow: rgba(0,0,0,0.14902) 0px 1px 1px 0px,rgba(0,0,0,0.09804) 0px 1px 2px 0px;
8 | }
9 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: "babel-eslint",
4 | parserOptions: {
5 | ecmaVersion: 6,
6 | sourceType: 'module'
7 | },
8 | extends: 'eslint:recommended',
9 | env: {
10 | 'browser': true
11 | },
12 | rules: {
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/.ember-cli:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | Ember CLI sends analytics information by default. The data is completely
4 | anonymous, but there are times when you might want to disable this behavior.
5 |
6 | Setting `disableAnalytics` to true will prevent any data from being sent.
7 | */
8 | "disableAnalytics": false
9 | }
10 |
--------------------------------------------------------------------------------
/tests/helpers/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember/resolver';
2 | import config from '../../config/environment';
3 |
4 | var resolver = Resolver.create();
5 |
6 | resolver.namespace = {
7 | modulePrefix: config.modulePrefix,
8 | podModulePrefix: config.podModulePrefix
9 | };
10 |
11 | export default resolver;
12 |
--------------------------------------------------------------------------------
/app/templates/components/file-select-drop.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 | /bower_components
10 |
11 | # misc
12 | /.sass-cache
13 | /connect.lock
14 | /coverage/*
15 | /libpeerconnection.log
16 | npm-debug.log
17 | testem.log
18 | /.idea
19 |
--------------------------------------------------------------------------------
/app/routes/home/sidebar.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
3 |
4 | const {
5 | Route,
6 | inject
7 | } = Ember;
8 |
9 | export default Route.extend(AuthenticatedRouteMixin, {
10 | setupController: function(controller, model, queryParams) {
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/app/templates/components/profile-pic.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
CHANGE
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tests/unit/routes/signin-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('route:signin', 'Unit | Route | signin', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | test('it exists', function(assert) {
9 | var route = this.subject();
10 | assert.ok(route);
11 | });
12 |
--------------------------------------------------------------------------------
/tests/unit/routes/signup-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('route:signup', 'Unit | Route | signup', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | test('it exists', function(assert) {
9 | var route = this.subject();
10 | assert.ok(route);
11 | });
12 |
--------------------------------------------------------------------------------
/tests/unit/routes/users-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('route:users', 'Unit | Route | users', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | test('it exists', function(assert) {
9 | var route = this.subject();
10 | assert.ok(route);
11 | });
12 |
--------------------------------------------------------------------------------
/tests/unit/routes/profile-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('route:profile', 'Unit | Route | profile', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | test('it exists', function(assert) {
9 | var route = this.subject();
10 | assert.ok(route);
11 | });
12 |
--------------------------------------------------------------------------------
/tests/unit/routes/application-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('route:application', 'Unit | Route | application', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | test('it exists', function(assert) {
9 | var route = this.subject();
10 | assert.ok(route);
11 | });
12 |
--------------------------------------------------------------------------------
/app/models/user.js:
--------------------------------------------------------------------------------
1 | import DS from 'ember-data';
2 | const {
3 | attr,
4 | hasMany,
5 | Model
6 | } = DS;
7 |
8 | export default Model.extend({
9 | profilePic: attr(),
10 | name: attr('string'),
11 | online: attr('string'),
12 | gender: attr('string'),
13 | email: attr('string'),
14 | friends: attr(),
15 | networks: attr(),
16 | isVerified: attr()
17 | });
18 |
--------------------------------------------------------------------------------
/tests/unit/models/user-test.js:
--------------------------------------------------------------------------------
1 | import { moduleForModel, test } from 'ember-qunit';
2 |
3 | moduleForModel('user', 'Unit | Model | user', {
4 | // Specify the other units that are required for this test.
5 | needs: []
6 | });
7 |
8 | test('it exists', function(assert) {
9 | var model = this.subject();
10 | // var store = this.store();
11 | assert.ok(!!model);
12 | });
13 |
--------------------------------------------------------------------------------
/tests/unit/routes/notifications-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('route:notifications', 'Unit | Route | notifications', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | test('it exists', function(assert) {
9 | var route = this.subject();
10 | assert.ok(route);
11 | });
12 |
--------------------------------------------------------------------------------
/app/routes/application.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import ApplicationRouteMixin from 'simple-auth/mixins/application-route-mixin';
3 | const {
4 | Route,
5 | RSVP
6 | } = Ember;
7 |
8 | export default Route.extend(
9 | ApplicationRouteMixin, {
10 | model(){
11 | return RSVP.hash({
12 | users: this.store.findAll('user')
13 | });
14 | }
15 | }
16 | );
17 |
--------------------------------------------------------------------------------
/tests/unit/controllers/signin-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('controller:signin', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | // Replace this with your real tests.
9 | test('it exists', function(assert) {
10 | var controller = this.subject();
11 | assert.ok(controller);
12 | });
13 |
--------------------------------------------------------------------------------
/tests/unit/controllers/signup-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('controller:signup', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | // Replace this with your real tests.
9 | test('it exists', function(assert) {
10 | var controller = this.subject();
11 | assert.ok(controller);
12 | });
13 |
--------------------------------------------------------------------------------
/tests/unit/controllers/users-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('controller:users', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | // Replace this with your real tests.
9 | test('it exists', function(assert) {
10 | var controller = this.subject();
11 | assert.ok(controller);
12 | });
13 |
--------------------------------------------------------------------------------
/tests/unit/controllers/application-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('controller:application', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['controller:foo']
6 | });
7 |
8 | // Replace this with your real tests.
9 | test('it exists', function(assert) {
10 | var controller = this.subject();
11 | assert.ok(controller);
12 | });
13 |
--------------------------------------------------------------------------------
/app/templates/components/action-bar.hbs:
--------------------------------------------------------------------------------
1 | {{#liquid-if isFileSelected class="action-bar"}}
2 |
6 | {{else}}
7 |
8 |
{{localIp}}
9 |
10 | {{/liquid-if}}
11 |
--------------------------------------------------------------------------------
/app/routes/notifications.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
3 |
4 | export default Ember.Route.extend(AuthenticatedRouteMixin, {
5 | setupController: function (controller, model, queryParams) {
6 | controller.getPendingApprovals().then(function (data) {
7 | controller.set("pendingApprovals", data);
8 | });
9 | }
10 | });
11 |
--------------------------------------------------------------------------------
/app/routes/people/find.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
3 |
4 | const {
5 | Route,
6 | inject
7 | } = Ember;
8 |
9 | export default Route.extend(AuthenticatedRouteMixin, {
10 | users : inject.service("users"),
11 | setupController: function(controller, model, queryParams) {
12 | controller.fetchUsers();
13 | }
14 | });
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: node_js
3 | node_js:
4 | - "0.12"
5 |
6 | sudo: false
7 |
8 | cache:
9 | directories:
10 | - node_modules
11 |
12 | before_install:
13 | - export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
14 | - "npm config set spin false"
15 | - "npm install -g npm@^2"
16 |
17 | install:
18 | - npm install -g bower
19 | - npm install
20 | - bower install
21 |
22 | script:
23 | - npm test
24 |
--------------------------------------------------------------------------------
/app/components/instance-holder.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from '../config/environment';
3 | import contextMenu from '../utils/context-menu';
4 | import windowMenu from '../utils/window-menu';
5 |
6 | export default Ember.Component.extend({
7 | setup : function () {
8 | if (config.isDesktop) {
9 | contextMenu.setup();
10 | windowMenu.setup();
11 | }
12 | }.on("didInsertElement")
13 | });
14 |
--------------------------------------------------------------------------------
/tests/unit/mixins/signin-user-test.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import SigninUserMixin from '../../../mixins/signin-user';
3 | import { module, test } from 'qunit';
4 |
5 | module('Unit | Mixin | signin user');
6 |
7 | // Replace this with your real tests.
8 | test('it works', function(assert) {
9 | var SigninUserObject = Ember.Object.extend(SigninUserMixin);
10 | var subject = SigninUserObject.create();
11 | assert.ok(subject);
12 | });
13 |
--------------------------------------------------------------------------------
/tests/unit/mixins/pretty-bytes-test.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import PrettyBytesMixin from '../../../mixins/pretty-bytes';
3 | import { module, test } from 'qunit';
4 |
5 | module('Unit | Mixin | pretty bytes');
6 |
7 | // Replace this with your real tests.
8 | test('it works', function(assert) {
9 | var PrettyBytesObject = Ember.Object.extend(PrettyBytesMixin);
10 | var subject = PrettyBytesObject.create();
11 | assert.ok(subject);
12 | });
13 |
--------------------------------------------------------------------------------
/app/app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resolver from 'ember/resolver';
3 | import loadInitializers from 'ember/load-initializers';
4 | import config from './config/environment';
5 |
6 | var App;
7 |
8 | Ember.MODEL_FACTORY_INJECTIONS = true;
9 |
10 | App = Ember.Application.extend({
11 | modulePrefix: config.modulePrefix,
12 | podModulePrefix: config.podModulePrefix,
13 | Resolver: Resolver
14 | });
15 |
16 | loadInitializers(App, config.modulePrefix);
17 |
18 | export default App;
19 |
--------------------------------------------------------------------------------
/app/styles/pages/signin.scss:
--------------------------------------------------------------------------------
1 | .signin-wrapper {
2 | width: 380px;
3 | margin: 0px auto;
4 | padding: 10px;
5 | background: #fafafa;
6 | border: 1px solid #ebebeb;
7 | box-shadow: rgba(0,0,0,0.14902) 0px 1px 1px 0px,rgba(0,0,0,0.09804) 0px 1px 2px 0px;
8 |
9 | .center {
10 | margin: 0px auto;
11 | text-align: center;
12 | display: table;
13 | }
14 |
15 | .btn-width {
16 | width: 300px;
17 | }
18 |
19 | md-input-container.md-default-theme > md-icon {
20 | color: rgba(0, 0, 0, 0.54);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/helpers/start-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Application from '../../app';
3 | import config from '../../config/environment';
4 |
5 | export default function startApp(attrs) {
6 | var application;
7 |
8 | var attributes = Ember.merge({}, config.APP);
9 | attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;
10 |
11 | Ember.run(function() {
12 | application = Application.create(attributes);
13 | application.setupForTesting();
14 | application.injectTestHelpers();
15 | });
16 |
17 | return application;
18 | }
19 |
--------------------------------------------------------------------------------
/app/templates/users.hbs:
--------------------------------------------------------------------------------
1 |
2 |
Online Users
3 |
4 | {{#each onlineUsers as |user|}}
5 | {{user-display user=user}}
6 | {{else}}
7 | There's no users online right now.
8 | {{/each}}
9 |
10 |
11 |
Offline Users
12 |
13 | {{#each offlineUsers as |user|}}
14 | {{user-display user=user}}
15 | {{else}}
16 | There's no users offline right now.
17 | {{/each}}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/router.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from './config/environment';
3 | import googlePageview from './mixins/google-pageview';
4 |
5 | var Router = Ember.Router.extend(googlePageview, {
6 | location: config.locationType
7 | });
8 |
9 | Router.map(function() {
10 | this.route('home');
11 | this.route('about');
12 | this.route('people', function () {
13 | this.route('find');
14 | this.route('detail');
15 | });
16 | this.route('users');
17 | this.route('signup');
18 | this.route('signin', {path : "/"});
19 | this.route('notifications');
20 | this.route('profile');
21 | });
22 |
23 | export default Router;
24 |
--------------------------------------------------------------------------------
/public/crossdomain.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "-Promise"
6 | ],
7 | "browser": true,
8 | "boss": true,
9 | "curly": true,
10 | "debug": false,
11 | "devel": true,
12 | "eqeqeq": true,
13 | "evil": true,
14 | "forin": false,
15 | "immed": false,
16 | "laxbreak": false,
17 | "newcap": true,
18 | "noarg": true,
19 | "noempty": false,
20 | "nonew": false,
21 | "nomen": false,
22 | "onevar": false,
23 | "plusplus": false,
24 | "regexp": false,
25 | "undef": true,
26 | "sub": true,
27 | "strict": false,
28 | "white": false,
29 | "eqnull": true,
30 | "esnext": true,
31 | "unused": true
32 | }
33 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 | indent_style = space
14 | indent_size = 2
15 |
16 | [*.js]
17 | indent_style = space
18 | indent_size = 2
19 |
20 | [*.hbs]
21 | insert_final_newline = false
22 | indent_style = space
23 | indent_size = 2
24 |
25 | [*.css]
26 | indent_style = space
27 | indent_size = 2
28 |
29 | [*.html]
30 | indent_style = space
31 | indent_size = 2
32 |
33 | [*.{diff,md}]
34 | trim_trailing_whitespace = false
35 |
--------------------------------------------------------------------------------
/app/templates/about.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | P2PDrop
6 |
7 |
8 | Version 0.1.1
9 |
10 |
11 | Official free Peer to Peer File Sharing Application.
12 |
13 |
14 | This application is licensed under MIT , source code is available on Github
15 |
16 |
17 |
20 |
21 |
--------------------------------------------------------------------------------
/_appdmg.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Ghost",
3 | "background": "assets/dmg/background.png",
4 | "icon": "assets/icons/p2pdrop.icns",
5 | "icon-size": 80,
6 | "contents": [
7 | {
8 | "x": 448,
9 | "y": 344,
10 | "type": "link",
11 | "path": "/Applications"
12 | },
13 | {
14 | "x": 192,
15 | "y": 344,
16 | "type": "file",
17 | "path": "electron-builds/p2pdrop-darwin-x64/p2pdrop.app"
18 | },
19 | {
20 | "x": 512,
21 | "y": 128,
22 | "type": "file",
23 | "path": "electron-builds/p2pdrop-darwin-x64/LICENSES.chromium.html"
24 | }
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/.sass-lint.yml:
--------------------------------------------------------------------------------
1 | # Rule Configuration
2 | rules:
3 | extends-before-mixins: 2
4 | extends-before-declarations: 2
5 | placeholder-in-extend: 2
6 | mixins-before-declarations:
7 | - 2
8 | -
9 | exclude:
10 | - breakpoint
11 | - mq
12 |
13 | no-warn: 1
14 | no-debug: 1
15 | no-ids: 2
16 | no-important: 2
17 | hex-notation:
18 | - 2
19 | -
20 | style: uppercase
21 | indentation:
22 | - 2
23 | -
24 | size: 2
25 | property-sort-order:
26 | - 1
27 | -
28 | order:
29 | - display
30 | - margin
31 | ignore-custom-properties: true
32 | variable-for-property:
33 | - 2
34 | -
35 | properties:
36 | - margin
37 | - content
38 |
--------------------------------------------------------------------------------
/app/styles/bootstrap-variables.scss:
--------------------------------------------------------------------------------
1 | $drop-blue: #04A9EB;
2 | $drop-grey: #EDEDED;
3 | $drop-dark-grey: #9d9d9d;
4 | $drop-light-grey: #F5F5F5;
5 | $drop-white: #FFFFFF;
6 | $drop-green: #76bd27;
7 |
8 | $primary: "blue";
9 |
10 | $sidebar-padding: 300px;
11 |
12 | /** Navbar Styles ****/
13 | $navbar-default-bg: $drop-blue;
14 | $navbar-default-color: $drop-white;
15 | $navbar-border-radius: 0px;
16 | $navbar-default-color: $drop-white;
17 | $navbar-default-brand-color: $drop-white;
18 | $navbar-default-toggle-border-color: $drop-white;
19 | $nav-tabs-border-color: $drop-white;
20 | $navbar-default-toggle-icon-bar-bg: $drop-white;
21 | $navbar-margin-bottom: 0px;
22 | $navbar-default-brand-hover-bg: rgba(0, 0, 0, 0.4);
23 | $navbar-default-border: $drop-blue;
24 |
--------------------------------------------------------------------------------
/app/routes/people/detail.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
3 |
4 | const {
5 | Route,
6 | inject
7 | } = Ember;
8 |
9 | export default Route.extend(AuthenticatedRouteMixin, {
10 | users : inject.service("users"),
11 | setupController: function(controller, model, queryParams) {
12 | let user = this.get("users").getUser(queryParams.queryParams.email);
13 | if (user) {
14 | controller.set("user", user);
15 | controller.set("isAvailable", false);
16 | controller.set("isPending", false);
17 | controller.set("isConnected", false);
18 | controller.checkStatus();
19 | } else {
20 | controller.traverseBack();
21 | }
22 | }
23 | });
24 |
--------------------------------------------------------------------------------
/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{#if currentUser}}
3 | {{render 'header-nav'}}
4 | {{else}}
5 |
11 | {{/if}}
12 |
13 |
14 | {{#if currentUser}}
15 | {{liquid-outlet class="p2pdrop-liquid-wrapper"}}
16 | {{else}}
17 | {{liquid-outlet}}
18 | {{/if}}
19 |
20 |
21 |
22 | {{ember-notify messageStyle='foundation-5'}}
23 | {{ember-cli-spinner id="app-spinner" type="double-bounce" height="60px" width="60px" color="blue" bgColor="rgba(230, 230, 230, 0.5)"}}
24 | {{instance-holder}}
25 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "p2pdrop",
3 | "dependencies": {
4 | "ember": "1.13.7",
5 | "ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3",
6 | "ember-cli-test-loader": "ember-cli-test-loader#0.1.3",
7 | "ember-data": "1.13.8",
8 | "ember-load-initializers": "ember-cli/ember-load-initializers#0.1.5",
9 | "ember-qunit": "0.4.9",
10 | "ember-qunit-notifications": "0.0.7",
11 | "ember-resolver": "~0.1.18",
12 | "jquery": "^1.11.3",
13 | "loader.js": "ember-cli/loader.js#3.2.1",
14 | "qunit": "~1.18.0",
15 | "moment": ">= 2.8.0",
16 | "moment-timezone": ">= 0.1.0",
17 | "bootstrap-sass": "~3.3.6",
18 | "firebase": "^2.1.0",
19 | "ember-simple-auth": "0.8.0",
20 | "hammerjs": "~2.0.6",
21 | "matchMedia": "0.2.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/components/action-bar.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | var inject = Ember.inject;
3 |
4 | export default Ember.Component.extend({
5 | isFileSelected: false,
6 | name: "",
7 | url: "",
8 | ips: inject.service(),
9 | localIp: "",
10 | didInsertElement : function () {
11 | var self = this;
12 | this.set("actionContext", this);
13 | this.get("ips").getLocalIps().then(function (data) {
14 | console.log(data);
15 | self.set("localIp", data[0]);
16 | });
17 | },
18 | notifyFileSelect : function (data) {
19 | this.set("isFileSelected", true);
20 | this.set("name", data.name);
21 | this.set("url", data.url);
22 | },
23 | resetSelected : function (boolean) {
24 | this.set("isFileSelected", boolean);
25 | },
26 | actions: {
27 |
28 | }
29 | });
30 |
--------------------------------------------------------------------------------
/app/templates/components/reveal-modal.hbs:
--------------------------------------------------------------------------------
1 | {{#if showModalDialog}}
2 | {{#liquid-tether
3 | to="modal-dialog"
4 | target="document.body"
5 | targetModifier="visible"
6 | attachment="middle center"
7 | tetherClass="modal-dialog"
8 | overlayClass="modal-backdrop"}}
9 |
10 |
13 |
14 |
15 | {{yield}}
16 |
17 |
18 |
22 |
23 | {{/liquid-tether}}
24 | {{/if}}
25 |
--------------------------------------------------------------------------------
/tests/integration/components/profile-pic-test.js:
--------------------------------------------------------------------------------
1 | import { moduleForComponent, test } from 'ember-qunit';
2 | import hbs from 'htmlbars-inline-precompile';
3 |
4 | moduleForComponent('profile-pic', 'Integration | Component | profile pic', {
5 | integration: true
6 | });
7 |
8 | test('it renders', function(assert) {
9 | assert.expect(2);
10 |
11 | // Set any properties with this.set('myProperty', 'value');
12 | // Handle any actions with this.on('myAction', function(val) { ... });
13 |
14 | this.render(hbs`{{profile-pic}}`);
15 |
16 | assert.equal(this.$().text().trim(), '');
17 |
18 | // Template block usage:
19 | this.render(hbs`
20 | {{#profile-pic}}
21 | template block text
22 | {{/profile-pic}}
23 | `);
24 |
25 | assert.equal(this.$().text().trim(), 'template block text');
26 | });
27 |
--------------------------------------------------------------------------------
/tests/integration/components/reveal-modal-test.js:
--------------------------------------------------------------------------------
1 | import { moduleForComponent, test } from 'ember-qunit';
2 | import hbs from 'htmlbars-inline-precompile';
3 |
4 | moduleForComponent('reveal-modal', 'Integration | Component | reveal modal', {
5 | integration: true
6 | });
7 |
8 | test('it renders', function(assert) {
9 | assert.expect(2);
10 |
11 | // Set any properties with this.set('myProperty', 'value');
12 | // Handle any actions with this.on('myAction', function(val) { ... });
13 |
14 | this.render(hbs`{{reveal-modal}}`);
15 |
16 | assert.equal(this.$().text().trim(), '');
17 |
18 | // Template block usage:
19 | this.render(hbs`
20 | {{#reveal-modal}}
21 | template block text
22 | {{/reveal-modal}}
23 | `);
24 |
25 | assert.equal(this.$().text().trim(), 'template block text');
26 | });
27 |
--------------------------------------------------------------------------------
/app/mixins/pretty-bytes.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | const {
4 | Mixin
5 | } = Ember;
6 |
7 | export default Mixin.create({
8 | prettyBytes : function (num) {
9 | if (typeof num !== 'number') {
10 | throw new TypeError('Expected a number, got ' + typeof num);
11 | }
12 |
13 | var exponent;
14 | var unit;
15 | var neg = num < 0;
16 | var units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
17 |
18 | if (neg) {
19 | num = -num;
20 | }
21 |
22 | if (num < 1) {
23 | return (neg ? '-' : '') + num + ' B';
24 | }
25 |
26 | exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), units.length - 1);
27 | num = Number((num / Math.pow(1000, exponent)).toFixed(2));
28 | unit = units[exponent];
29 |
30 | return (neg ? '-' : '') + num + ' ' + unit;
31 | }
32 | });
33 |
--------------------------------------------------------------------------------
/app/templates/people/find.hbs:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | {{#each filteredUsers as |user|}}
14 |
15 |
16 |
17 | {{user.name}}
18 |
19 |
20 | {{/each}}
21 |
22 |
--------------------------------------------------------------------------------
/app/controllers/users.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | const {
3 | Controller,
4 | computed,
5 | inject
6 | } = Ember;
7 |
8 | const { alias } = computed;
9 |
10 | export default Controller.extend({
11 | application: inject.controller(),
12 | currentUser: alias('application.currentUser'),
13 | users: alias('application.model'),
14 |
15 | onlineUsers: computed('model.@each.online', function(){
16 | let onlineUsers = this.get('model').filter( (user) => {
17 | return user.get('online') === 'true';
18 | });
19 | return onlineUsers.sortBy('name');
20 | }),
21 |
22 | offlineUsers: computed('model.@each.online', function(){
23 | let offlineUsers = this.get('model').filter( (user) => {
24 | return user.get('online') !== 'true';
25 | });
26 | return offlineUsers.sortBy('name');
27 | })
28 | });
29 |
--------------------------------------------------------------------------------
/tests/integration/components/instance-holder-test.js:
--------------------------------------------------------------------------------
1 | import { moduleForComponent, test } from 'ember-qunit';
2 | import hbs from 'htmlbars-inline-precompile';
3 |
4 | moduleForComponent('instance-holder', 'Integration | Component | instance holder', {
5 | integration: true
6 | });
7 |
8 | test('it renders', function(assert) {
9 | assert.expect(2);
10 |
11 | // Set any properties with this.set('myProperty', 'value');
12 | // Handle any actions with this.on('myAction', function(val) { ... });
13 |
14 | this.render(hbs`{{instance-holder}}`);
15 |
16 | assert.equal(this.$().text().trim(), '');
17 |
18 | // Template block usage:
19 | this.render(hbs`
20 | {{#instance-holder}}
21 | template block text
22 | {{/instance-holder}}
23 | `);
24 |
25 | assert.equal(this.$().text().trim(), 'template block text');
26 | });
27 |
--------------------------------------------------------------------------------
/app/styles/pages/about.scss:
--------------------------------------------------------------------------------
1 | /******** About Styles ********/
2 | #about {
3 | height: 100%;
4 | width: 100%;
5 |
6 | .about-content {
7 | width: 400px;
8 | height: 400px;
9 | position: absolute;
10 | top:0;
11 | bottom: 0;
12 | left: 0;
13 | right: 0;
14 | margin: auto;
15 | text-align: center;
16 |
17 | .logo {
18 | margin: 0px auto;
19 | display: block;
20 | }
21 |
22 | h1 {
23 | margin: 10px 0px;
24 | }
25 |
26 | .highlight {
27 | color: $drop-blue;
28 | font-size: 14px;
29 | }
30 | }
31 | .bottom-right {
32 | position: absolute;
33 | bottom: 50px;
34 | right: 50px;
35 | text-decoration: none;
36 | color: $drop-dark-grey;
37 |
38 | .highlight {
39 | color: $drop-green;
40 | font-size: 20px;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/templates/signin.hbs:
--------------------------------------------------------------------------------
1 | {{#paper-card class="md-whiteframe-z1 signin-wrapper"}}
2 | {{#paper-card-content}}
3 |
14 | {{/paper-card-content}}
15 | {{/paper-card}}
16 |
--------------------------------------------------------------------------------
/tests/electron.js:
--------------------------------------------------------------------------------
1 | /* jshint undef: false */
2 |
3 | var BrowserWindow = require('browser-window');
4 | var app = require('app');
5 | var mainWindow = null;
6 |
7 | app.on('window-all-closed', function onWindowAllClosed() {
8 | if (process.platform !== 'darwin') {
9 | app.quit();
10 | }
11 | });
12 |
13 | app.on('ready', function onReady() {
14 | mainWindow = new BrowserWindow({
15 | width: 800,
16 | height: 600
17 | });
18 |
19 | delete mainWindow.module;
20 |
21 | if (process.env.EMBER_ENV === 'test') {
22 | mainWindow.loadUrl('file://' + __dirname + '/index.html');
23 | } else {
24 | mainWindow.loadUrl('file://' + __dirname + '/dist/index.html');
25 | }
26 |
27 | mainWindow.on('closed', function onClosed() {
28 | mainWindow = null;
29 | });
30 | });
31 |
32 | /* jshint undef: true */
33 |
--------------------------------------------------------------------------------
/app/controllers/signin.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import LoginUser from '../mixins/signin-user';
3 | const {
4 | Controller,
5 | inject
6 | } = Ember;
7 |
8 | export default Controller.extend(
9 | LoginUser, {
10 | spinner: inject.service("spinner"),
11 | emailValidation: {
12 | 'errorMessage': 'Please provide email in a valid format',
13 | 'isError': (inputValue) => {
14 | var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
15 | return !emailPattern.test(inputValue);
16 | }
17 | },
18 | actions: {
19 | signin(e) {
20 | e.preventDefault();
21 | this.get('spinner').show('app-spinner');
22 | this.authenticateUser(this.get('email'), this.get('password'));
23 | },
24 | goToSignUp() {
25 | this.transitionToRoute("signup");
26 | }
27 | }
28 | });
29 |
--------------------------------------------------------------------------------
/app/services/blob.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Service.extend({
4 | b64toBlob: function (b64Data, contentType, sliceSize) {
5 | contentType = contentType || '';
6 | sliceSize = sliceSize || 512;
7 |
8 | var byteCharacters = atob(b64Data);
9 | var byteArrays = [];
10 |
11 | for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
12 | var slice = byteCharacters.slice(offset, offset + sliceSize);
13 |
14 | var byteNumbers = new Array(slice.length);
15 | for (var i = 0; i < slice.length; i++) {
16 | byteNumbers[i] = slice.charCodeAt(i);
17 | }
18 |
19 | var byteArray = new Uint8Array(byteNumbers);
20 |
21 | byteArrays.push(byteArray);
22 | }
23 |
24 | var blob = new Blob(byteArrays, {type: contentType});
25 | return blob;
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/app/templates/components/thumbnail-slider.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{#each files as |file|}}
3 |
4 |
5 | {{paper-icon "clear" size="sm" class="delete-icon-btn"}}
6 |
7 | {{#if file.isDownloading}}
8 |
9 |
10 |
11 | {{liquid-bind file.progress}}
12 |
13 |
14 |
15 | {{/if}}
16 |
17 |
18 |
{{file.name}}
19 |
20 |
21 | {{/each}}
22 |
23 |
--------------------------------------------------------------------------------
/app/templates/home/dropzone.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{thumbnail-slider class="thumbnail-slider-wrapper" thumbnailContext=thumbnailContext fileChange=(action "changeSelectedFile") resetSelected=(action "resetSelected")}}
3 |
4 |
5 |
8 |
9 |
10 |
11 | {{file-select-drop class="dropzone-widget" onFileSelect=(action "sendFile") triggerFileSelect=(action "triggerFileSelect")}}
12 | {{action-bar class="action-bar-wrapper" actionContext=actionContext}}
13 |
14 | {{#reveal-modal rightBtnText="Download" leftBtnText="Cancel" title="Notification" self=modalContext}}
15 | {{senderName}} has shared you a file.
16 | {{/reveal-modal}}
17 |
--------------------------------------------------------------------------------
/app/mixins/signin-user.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | const {
3 | Mixin,
4 | inject
5 | } = Ember;
6 |
7 | export default Mixin.create({
8 | notify: inject.service('notify'),
9 | spinner: inject.service('spinner'),
10 | home: inject.controller('home'),
11 | authenticateUser(email, password, callback) {
12 | let self = this;
13 | this.get('session').authenticate('authenticator:firebase', {
14 | 'email': email,
15 | 'password': password
16 | }).then( () => {
17 | if (typeof callback === "function") {
18 | callback(function (guid) {
19 | self.get('spinner').hide('app-spinner');
20 | self.transitionToRoute('home');
21 | self.get('home').setVerification(guid);
22 | });
23 | } else {
24 | self.get('spinner').hide('app-spinner');
25 | self.transitionToRoute('home');
26 | }
27 |
28 | }, (error) => {
29 | self.get('spinner').hide('app-spinner');
30 | self.get('notify').alert(error.toString());
31 | });
32 | }
33 | });
34 |
--------------------------------------------------------------------------------
/electron.js:
--------------------------------------------------------------------------------
1 | var BrowserWindow = require('browser-window');
2 | var app = require('app');
3 | var mainWindow = null;
4 |
5 | app.on('window-all-closed', function onWindowAllClosed() {
6 | if (process.platform !== 'darwin') {
7 | app.quit();
8 | }
9 | });
10 |
11 | app.on('ready', function onReady() {
12 | mainWindow = new BrowserWindow({
13 | width: 800,
14 | height: 600
15 | });
16 |
17 | delete mainWindow.module;
18 |
19 | // If you want to open up dev tools programmatically, call
20 | // mainWindow.openDevTools();
21 |
22 | // By default, we'll open the Ember App by directly going to the
23 | // file system.
24 | //
25 | // Please ensure that you have set the locationType option in the
26 | // config/environment.js file to 'hash'. For more information,
27 | // please consult the ember-electron readme.
28 | mainWindow.loadURL('file://' + __dirname + '/dist/index.html');
29 |
30 | mainWindow.on('closed', function onClosed() {
31 | mainWindow = null;
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/tests/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "location",
6 | "setTimeout",
7 | "$",
8 | "-Promise",
9 | "define",
10 | "console",
11 | "visit",
12 | "exists",
13 | "fillIn",
14 | "click",
15 | "keyEvent",
16 | "triggerEvent",
17 | "find",
18 | "findWithAssert",
19 | "wait",
20 | "DS",
21 | "andThen",
22 | "currentURL",
23 | "currentPath",
24 | "currentRouteName"
25 | ],
26 | "node": false,
27 | "browser": false,
28 | "boss": true,
29 | "curly": true,
30 | "debug": false,
31 | "devel": false,
32 | "eqeqeq": true,
33 | "evil": true,
34 | "forin": false,
35 | "immed": false,
36 | "laxbreak": false,
37 | "newcap": true,
38 | "noarg": true,
39 | "noempty": false,
40 | "nonew": false,
41 | "nomen": false,
42 | "onevar": false,
43 | "plusplus": false,
44 | "regexp": false,
45 | "undef": true,
46 | "sub": true,
47 | "strict": false,
48 | "white": false,
49 | "eqnull": true,
50 | "esnext": true,
51 | "unused": true
52 | }
53 |
--------------------------------------------------------------------------------
/app/services/webtorrent.js:
--------------------------------------------------------------------------------
1 | /**** WebTorrent Service Layer ******/
2 |
3 | import Ember from "ember";
4 |
5 | const {
6 | Service,
7 | RSVP
8 | } = Ember;
9 |
10 | export default Service.extend({
11 | torrentClient : function () {
12 | if (!this.get("client")) {
13 | this.set("client", new WebTorrent());
14 | }
15 | return this.get("client");
16 | },
17 | download : function (data, callback) {
18 | let client = this.torrentClient();
19 |
20 | return new RSVP.Promise(function (resolve, reject) {
21 | client.add(data.magnetURI, function (torrent) {
22 | // Got torrent metadata!
23 | console.log('Client is downloading:', torrent.infoHash)
24 | callback(torrent, data.name);
25 | resolve(torrent.files);
26 | });
27 | });
28 | },
29 | seed : function (files) {
30 | var client = this.torrentClient();
31 |
32 | return new RSVP.Promise(function (resolve, reject) {
33 | client.seed(files, function (torrent) {
34 | console.log('Client is seeding:', torrent.infoHash);
35 | resolve(torrent);
36 | });
37 | });
38 | }
39 | });
40 |
--------------------------------------------------------------------------------
/app/templates/notifications.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{#if isPendingApprovals}}
3 | {{#paper-list}}
4 | {{#paper-subheader class="md-no-sticky"}}Pending Approvals{{/paper-subheader}}
5 |
6 | {{#each pendingApprovals as |pendingApproval|}}
7 | {{#paper-item}}
8 | {{paper-icon "thumbs-up-down"}}
9 |
{{pendingApproval.name}}
10 |
11 | {{#paper-button raised=true primary=true }}Approve{{/paper-button}}
12 |
13 |
14 | {{#paper-button raised=true warn=true}}Reject{{/paper-button}}
15 |
16 | {{/paper-item}}
17 | {{/each}}
18 |
19 | {{/paper-list}}
20 | {{else}}
21 | {{#paper-list}}
22 | {{#paper-subheader class="md-no-sticky"}}Pending Approvals{{/paper-subheader}}
23 | {{#paper-item}}
24 |
None
25 | {{/paper-item}}
26 | {{/paper-list}}
27 | {{/if}}
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | P2PDrop Tests
7 |
8 |
9 |
10 | {{content-for 'head'}}
11 | {{content-for 'test-head'}}
12 |
13 |
14 |
15 |
16 |
17 | {{content-for 'head-footer'}}
18 | {{content-for 'test-head-footer'}}
19 |
20 |
21 |
22 | {{content-for 'body'}}
23 | {{content-for 'test-body'}}
24 |
25 |
26 |
27 |
28 |
29 |
30 | {{content-for 'body-footer'}}
31 | {{content-for 'test-body-footer'}}
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/routes/home.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
3 | import config from '../config/environment';
4 |
5 | const {
6 | Route,
7 | inject
8 | } = Ember;
9 |
10 | export default Route.extend(AuthenticatedRouteMixin, {
11 | ips : inject.service("ips"),
12 | users : inject.service("users"),
13 | setupController : function (controller, model, queryParams) {
14 | let self = this;
15 | const uid = this.get('session.secure.uid');
16 | //on complete state change the state of btn
17 | let onComplete = function (error) {
18 | if (error) {
19 | console.log('Synchronization failed');
20 | } else {
21 | console.log('Synchronized');
22 | }
23 | };
24 | //Inject users network ip
25 | this.get("ips").getLocalIps().then(function (data) {
26 | let userRef = new Firebase(config.firebase + '/users/' + uid + "/networks");
27 |
28 | self.get("users").getCurrentUser(uid).then(function (currentUser) {
29 | userRef.set(data[1], onComplete);
30 | });
31 |
32 | });
33 | }
34 | });
35 |
--------------------------------------------------------------------------------
/app/controllers/application.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from '../config/environment';
3 | const {
4 | Controller,
5 | computed,
6 | inject
7 | } = Ember;
8 |
9 | export default Controller.extend({
10 | ips : inject.service("ips"),
11 | users : inject.service("users"),
12 | init : function () {
13 | if (this.get("currentUser")) {
14 | this.transitionToRoute("home");
15 | }
16 | },
17 |
18 | currentUser: computed('session.secure.uid', function(){
19 | const uid = this.get('session.secure.uid');
20 | if (uid !== undefined) {
21 | this.setUpPresenceCheck(uid);
22 | return this.store.find('user', uid);
23 | } else {
24 | return null;
25 | }
26 | }),
27 |
28 | setUpPresenceCheck(uid){
29 | const isConnected = new Firebase(config.firebase + '/.info/connected');
30 | isConnected.on('value', function(snapshot){
31 | if (snapshot.val()){
32 | let userRef = new Firebase(config.firebase + '/users/' + uid + '/online');
33 | userRef.onDisconnect().set(Firebase.ServerValue.TIMESTAMP);
34 | userRef.set(true);
35 | }
36 | });
37 | }
38 | });
39 |
--------------------------------------------------------------------------------
/app/helpers/extension-mapping.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import _ from 'lodash';
3 |
4 | export default Ember.Helper.helper(function(params, hash) {
5 | let fileName = params[0];
6 | let extension = fileName.replace(/^.*\./, '');
7 | let extensionMap = [{
8 | key: "photo",
9 | value: ["jpeg", "jpg", "png", "gif"]
10 | }, {
11 | key: "pdf",
12 | value: ["pdf"]
13 | }, {
14 | key: "txt",
15 | value: ["txt"]
16 | }, {
17 | key: "doc",
18 | value: ["doc", "docx"]
19 | }, {
20 | key: "photoshop",
21 | value: ["psd"]
22 | }, {
23 | key: "movie",
24 | value: ["mpeg4", "mpeg", "mp4", "avi"]
25 | }, {
26 | key: "ppt",
27 | value: ["ppt"]
28 | }, {
29 | key: "music",
30 | value: ["mp3", "ogg"]
31 | }, {
32 | key: "compressed",
33 | value: ["zip", "rar", "7z"]
34 | }];
35 |
36 | let type = _.filter(extensionMap, _.matches({ value: [extension]}));
37 | let typeName;
38 |
39 | if (type.length) {//if exists
40 | typeName = type[0].key;
41 | } else {
42 | typeName = 'unknown';
43 | }
44 |
45 | return typeName;
46 | });
47 |
--------------------------------------------------------------------------------
/app/templates/header-nav.hbs:
--------------------------------------------------------------------------------
1 |
26 |
--------------------------------------------------------------------------------
/app/components/profile-pic.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | const {
3 | Component,
4 | inject
5 | } = Ember;
6 |
7 | export default Component.extend({
8 | imgur: inject.service(),
9 | file: inject.service(),
10 | spinner: inject.service('spinner'),
11 | profilePic : {
12 | link : 'https://i.imgur.com/DAgl4rz.png'
13 | },
14 | didInsertElement: function () {
15 | $("body").on("click", "#imgSelector", function (evt) {
16 | evt.stopPropagation();
17 | });
18 | },
19 | actions: {
20 | //Trigger File Select
21 | triggerFileSelect(){
22 | $("#imgSelector").trigger("click");
23 | },
24 | //Upload Image
25 | uploadImage(){
26 | event.stopPropagation();
27 | let self = this;
28 | this.get('spinner').show('app-spinner');
29 | this.get("file").read(event).then(function (imageData) {
30 | self.get('imgur').imagePost(imageData[0].result.split(',')[1]).then((result) => {
31 | self.get('spinner').hide('app-spinner');
32 | self.sendAction("imageUploaded", result.data);
33 | }).catch((result) => {
34 | console.error(result);
35 | });
36 | });
37 | }
38 | }
39 | });
40 |
--------------------------------------------------------------------------------
/main/load-error/error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | P2PDrop failed to load
5 |
17 |
18 |
19 |
20 |
21 |
22 |
😦
23 |
Loading the P2PDrop failed.
24 |
No error details.
25 |
26 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/ember-cli-build.js:
--------------------------------------------------------------------------------
1 | /* global require, module */
2 | var EmberApp = require('ember-cli/lib/broccoli/ember-app');
3 |
4 | module.exports = function(defaults) {
5 | var app = new EmberApp(defaults, {
6 | fingerprint: {
7 | enabled: false
8 | },
9 | sassLint: {
10 | configPath: '.sass-lint.yml',
11 | shouldThrowExceptions: true,
12 | shouldLog: false
13 | }
14 | });
15 |
16 | app.import('vendor/simplewebrtc-v2.js');
17 | app.import('vendor/webtorrent.min.js');
18 | app.import('bower_components/firebase/firebase.js');
19 | //app.import('vendor/webrtc/adapter.js');
20 |
21 | // Use `app.import` to add additional libraries to the generated
22 | // output files.
23 | //
24 | // If you need to use different assets in different
25 | // environments, specify an object as the first parameter. That
26 | // object's keys should be the environment name and the values
27 | // should be the asset to use in that environment.
28 | //
29 | // If the library that you are including contains AMD or ES6
30 | // modules that you would like to import into your application
31 | // please specify an object with the list of modules as keys
32 | // along with the exports of each module as its value.
33 |
34 | return app.toTree();
35 | };
36 |
--------------------------------------------------------------------------------
/app/templates/home.hbs:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | {{render 'home/dropzone'}}
7 |
8 | {{#if isNotVerified}}
9 | {{#liquid-tether
10 | to="modal-dialog"
11 | target="document.body"
12 | targetModifier="visible"
13 | attachment="middle center"
14 | tetherClass="modal-dialog"
15 | overlayClass="modal-backdrop"}}
16 | {{#paper-card class="md-whiteframe-z1 signin-wrapper"}}
17 | {{#paper-card-content}}
18 |
28 | {{/paper-card-content}}
29 | {{/paper-card}}
30 | {{/liquid-tether}}
31 | {{/if}}
32 |
33 |
--------------------------------------------------------------------------------
/app/components/reveal-modal.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | const { Component } = Ember;
4 |
5 | export default Component.extend({
6 | showModalDialog : false,
7 | title : "",
8 | leftBtnText : "",
9 | rightBtnText : "",
10 | callback : function () {},
11 | self : {},
12 | setSelf : function () {
13 | let self = this;
14 | let context = this.get("self");
15 | if (!Ember.isEmpty(context)) { //To ensure the DOM doesnt get rendered
16 | this.set("self", {
17 | open : self.open.bind(self),
18 | close : self.close.bind(self),
19 | toggle : self.toggle.bind(self)
20 | });
21 | }
22 | }.on("didInsertElement"),
23 | open : function (callback) {
24 | this.set("showModalDialog", true);
25 | if (typeof callback === "function") {
26 | this.set("callback", callback);
27 | }
28 | },
29 | close : function () {
30 | this.set("showModalDialog", false);
31 | },
32 | toggle : function () {
33 | let showModalDialog = this.get("showModalDialog");
34 | this.set("showModalDialog", !showModalDialog);
35 | },
36 | actions: {
37 | open() {
38 | this.open();
39 | },
40 | close() {
41 | this.close();
42 | },
43 | callback() {
44 | this.callback();
45 | this.close();
46 | }
47 | }
48 | });
49 |
--------------------------------------------------------------------------------
/app/templates/profile.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{profile-pic profilePic=profilePic imageUploaded=(action 'setProfilePic')}}
4 |
5 |
29 |
30 | {{#paper-button raised=true action="update"}}Update{{/paper-button}}
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/styles/pages/profile.scss:
--------------------------------------------------------------------------------
1 | #profile {
2 | width: 80%;
3 | margin: 0px auto;
4 | padding: 10px;
5 | background: #fafafa;
6 | border: 1px solid #ebebeb;
7 | box-shadow: rgba(0,0,0,0.14902) 0px 1px 1px 0px,rgba(0,0,0,0.09804) 0px 1px 2px 0px;
8 |
9 | .center {
10 | margin: 0px auto;
11 | text-align: center;
12 | display: table;
13 | }
14 |
15 | .profile-pic {
16 | margin: 10px;
17 |
18 | img {
19 | border: 1px solid $drop-green;
20 | }
21 |
22 | h4 {
23 | background: #ccc;
24 | padding: 3px;
25 | }
26 |
27 | input {
28 | display: none;
29 | }
30 | }
31 |
32 | .form-wrapper {
33 |
34 | .label-text {
35 | margin-left: 12px;
36 | color: rgba(0, 0, 0, 0.26);
37 | font-weight: bold;
38 | }
39 |
40 | md-input-container.md-default-theme > md-icon {
41 | color: rgba(0, 0, 0, 0.54);
42 | }
43 |
44 | .misc {
45 | margin-bottom: 26px;
46 |
47 | .right {
48 | float: left;
49 | margin: 5px 0;
50 | }
51 |
52 | .left {
53 | margin-left: 35px;
54 | border-bottom: 1px solid #ccc;
55 | text-shadow: none;
56 | color: rgba(0, 0, 0, 0.26);
57 | font-weight: bold;
58 | .paper-switch {
59 | margin: 5px !important;
60 | }
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/app/styles/pages/signup.scss:
--------------------------------------------------------------------------------
1 | #signup {
2 | width: 80%;
3 | margin: 0px auto;
4 | padding: 10px;
5 | background: #fafafa;
6 | border: 1px solid #ebebeb;
7 | box-shadow: rgba(0,0,0,0.14902) 0px 1px 1px 0px,rgba(0,0,0,0.09804) 0px 1px 2px 0px;
8 |
9 | .center {
10 | margin: 0px auto;
11 | text-align: center;
12 | display: table;
13 | }
14 |
15 | .profile-pic {
16 | margin: 10px;
17 |
18 | img {
19 | border: 1px solid $drop-green;
20 | }
21 |
22 | h4 {
23 | background: #ccc;
24 | padding: 3px;
25 | }
26 |
27 | input {
28 | display: none;
29 | }
30 | }
31 |
32 | .form-wrapper {
33 |
34 | .label-text {
35 | margin-left: 12px;
36 | color: rgba(0, 0, 0, 0.26);
37 | font-weight: bold;
38 | }
39 |
40 | md-input-container.md-default-theme > md-icon {
41 | color: rgba(0, 0, 0, 0.54);
42 | }
43 |
44 | .misc {
45 | margin-bottom: 26px;
46 |
47 | .right {
48 | float: left;
49 | margin: 5px 0;
50 | }
51 |
52 | .left {
53 | margin-left: 35px;
54 | border-bottom: 1px solid #ccc;
55 | text-shadow: none;
56 | color: rgba(0, 0, 0, 0.26);
57 | font-weight: bold;
58 | .paper-switch {
59 | margin: 5px !important;
60 | }
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/main/squirrel.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /**
3 | * This file is responsible for handling Squirrel events.
4 | * ⚠ Remember: It needs to load ASAP, execute ASAP, exit ASAP! ⚠
5 | */
6 |
7 | const path = require('path');
8 | const spawn = require('child_process').spawn;
9 | const app = require('app');
10 |
11 | function run(args, done) {
12 | let updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe');
13 |
14 | spawn(updateExe, args, {
15 | detached: true
16 | }).on('close', done);
17 | };
18 |
19 | const check = function() {
20 | if (process.platform === 'win32') {
21 | let cmd = process.argv[1];
22 | let target = path.basename(process.execPath);
23 |
24 | if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
25 | run(['--createShortcut=' + target + ''], app.quit);
26 | return true;
27 | }
28 |
29 | if (cmd === '--squirrel-uninstall') {
30 | run(['--removeShortcut=' + target + ''], app.quit);
31 | return true;
32 | }
33 |
34 | if (cmd === '--squirrel-obsolete') {
35 | app.quit();
36 | return true;
37 | }
38 |
39 | if (cmd === '--squirrel-updated') {
40 | app.quit();
41 | return true;
42 | }
43 | }
44 | return false;
45 | };
46 |
47 | module.exports = check;
48 |
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | P2PDrop - Securely share files between peers
7 |
8 |
9 |
10 |
11 | {{content-for 'head'}}
12 |
13 |
14 |
15 |
16 | {{content-for 'head-footer'}}
17 |
18 |
19 |
31 | {{content-for 'body'}}
32 |
33 |
34 |
35 |
36 |
37 | {{content-for 'body-footer'}}
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/services/file.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import _ from 'lodash/lodash';
3 |
4 | export default Ember.Service.extend({
5 | getFiles : function (evt) {
6 | evt.stopPropagation();
7 | evt.preventDefault();
8 |
9 | var files = evt.target.files || evt.dataTransfer.files; // FileList object
10 |
11 | // files is a FileList of File objects. List some properties.
12 | var output = [];
13 | for (var i = 0, f; f = files[i]; i++) {
14 | output.push({
15 | name : escape(f.name),
16 | type : f.type || 'n/a',
17 | size : f.size,
18 | lastModifiedDate : f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
19 | file: f
20 | });
21 | }
22 | return output;
23 | },
24 |
25 | read : function (evt) {
26 | var reader = new FileReader();
27 | var files = this.getFiles(evt);
28 |
29 | return new Ember.RSVP.Promise(function (resolve, reject) {
30 | _.each(files, function (item, index) {
31 | // Closure to capture the file information.
32 | reader.onload = (function(file) {
33 | return function(e) {
34 | item.result = e.target.result;
35 | if (index === files.length - 1) {
36 | resolve(files);
37 | }
38 | };
39 | })(item.file);
40 |
41 | // Read in the image file as a data URL.
42 | reader.readAsDataURL(item.file);
43 | });
44 | });
45 | }
46 | });
47 |
--------------------------------------------------------------------------------
/app/services/users.js:
--------------------------------------------------------------------------------
1 | import Ember from "ember";
2 | import _object from 'lodash/object';
3 | import _collection from 'lodash/collection';
4 | import config from '../config/environment';
5 |
6 | const {
7 | Service,
8 | inject
9 | } = Ember;
10 |
11 | export default Service.extend({
12 | users : [],
13 | setUsers : function (users) {
14 | this.set("users", users);
15 | },
16 | getUsers : function () {
17 | return this.get("users");
18 | },
19 | getUser : function (email) {
20 | let users = this.get("users");
21 | let user = _collection.filter(users, {
22 | email : email
23 | })[0];
24 | return user;
25 | },
26 | getCurrentUser : function (uid) {
27 | let userRef = new Firebase(config.firebase + '/users/' + uid);
28 | let self = this;
29 |
30 | return new Promise(function (resolve, reject) {
31 | userRef.once("value", function(snapshot) {
32 | let user = snapshot.val();
33 | resolve(user);
34 | });
35 | });
36 | },
37 | sendVerificationCode : function (uid, email) {
38 | return new Promise(function (resolve, reject) {
39 | $.ajax({
40 | method: "POST",
41 | url: config.emailServer,
42 | dataType: "json",
43 | data: { uid : uid, email: email },
44 | success: function (data) {
45 | resolve(data);
46 | },
47 | fail: function (error) {
48 | reject(error);
49 | }
50 | });
51 | });
52 | }
53 | });
54 |
--------------------------------------------------------------------------------
/app/components/file-select-drop.js:
--------------------------------------------------------------------------------
1 | import Ember from "ember";
2 | const {
3 | Component,
4 | inject
5 | } = Ember;
6 |
7 | export default Component.extend({
8 | file: inject.service(),
9 | didInsertElement: function () {
10 | $("#p2p-files").on("click", function (evt) {
11 | evt.stopPropagation();
12 | });
13 | },
14 | actions : {
15 | //Trigger File Select
16 | triggerFileSelect: function () {
17 | this.sendAction("triggerFileSelect", function () {
18 | $("#p2p-files").trigger("click");
19 | });
20 | },
21 | //Handle File Select Event
22 | onFileSelect : function () {
23 | event.stopPropagation();
24 | let self = this;
25 | this.get("file").read(event).then(function (data) {
26 | self.sendAction("onFileSelect", data);
27 | });
28 | },
29 | //On Drag Over
30 | onDragOver : function () {
31 | event.preventDefault();
32 | event.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
33 | $(".dropzone-content").css({
34 | border: "2px dashed #04A9EB"
35 | });
36 | },
37 | //On Drag Leave
38 | onDragLeave : function () {
39 | $(".dropzone-content").css({
40 | border: "2px dashed #CCC"
41 | });
42 | },
43 | //On Drop Of File
44 | onDrop : function () {
45 | event.preventDefault();
46 | let self = this;
47 |
48 | $(".dropzone-content").css({
49 | border: "2px dashed #CCC"
50 | });
51 |
52 | this.get("file").read(event).then(function (data) {
53 | self.sendAction("onFileSelect", data);
54 | });
55 | }
56 | }
57 | });
58 |
--------------------------------------------------------------------------------
/app/templates/people/detail.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{link-to 'Back' 'people.find' class="back-btn"}}
4 |
5 |
6 |
7 |
8 |
{{user.name}}
9 |
10 |
11 |
54 |
55 |
--------------------------------------------------------------------------------
/app/utils/context-menu.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Handles the contextmenu event for the whole window, checking if
3 | * an input element has been selected - if so, a cut/copy/paste
4 | * menu will be opened
5 | *
6 | * @param e - MouseEvent
7 | */
8 | function handleContextMenu(e) {
9 | let {remote} = requireNode('electron');
10 | let {BrowserWindow, Menu} = remote;
11 | let template = [{
12 | label: 'Undo',
13 | role: 'undo'
14 | }, {
15 | label: 'Redo',
16 | role: 'redo'
17 | }, {
18 | type: 'separator'
19 | }, {
20 | label: 'Cut',
21 | role: 'cut'
22 | }, {
23 | label: 'Copy',
24 | role: 'copy'
25 | }, {
26 | label: 'Paste',
27 | role: 'paste'
28 | }, {
29 | label: 'Paste and Match Style',
30 | click: () => BrowserWindow.getFocusedWindow().webContents.pasteAndMatchStyle()
31 | }, {
32 | label: 'Select All',
33 | role: 'selectall'
34 | }];
35 |
36 | e.preventDefault();
37 | e.stopPropagation();
38 |
39 | let node = e.target;
40 | let editorMenu = Menu.buildFromTemplate(template);
41 |
42 | while (node) {
43 | if (node.nodeName.match(/^(input|textarea)$/i) || node.isContentEditable) {
44 | editorMenu.popup(remote.getCurrentWindow());
45 | break;
46 | }
47 |
48 | node = node.parentNode;
49 | }
50 |
51 | /**
52 | * We cannot, with pure JavaScript, confirm that this event handler works.
53 | * A little hack to ensure that this method becomes testable.
54 | */
55 | if (window && window.QUnit && editorMenu) {
56 | window.CONTEXTMENU_OPENED = true;
57 | }
58 | }
59 |
60 | /**
61 | * Creates the conextmenu event listener
62 | *
63 | * @export
64 | */
65 | export function setup() {
66 | window.addEventListener('contextmenu', handleContextMenu);
67 | };
68 |
--------------------------------------------------------------------------------
/app/templates/signup.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{profile-pic profilePic=profilePic imageUploaded=(action 'setProfilePic')}}
4 |
5 |
39 |
40 | {{#paper-button raised=true action="signup"}}Sign Up{{/paper-button}}
41 |
OR
42 |
43 | {{#paper-button raised=true action="goToLogin" class="btn-width" primary=true}}Login{{/paper-button}}
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/transitions.js:
--------------------------------------------------------------------------------
1 | import { target, onOpenTether } from 'liquid-tether';
2 |
3 | const options = {
4 | duration: 500,
5 | easing: 'easeInOutQuint'
6 | };
7 |
8 | export default function () {
9 | let duration = 500;
10 |
11 | this.transition(
12 | this.fromRoute('signin'),
13 | this.toRoute('signup'),
14 | this.use('toLeft', {duration: duration/2}),
15 | this.reverse('toRight', {duration: duration/2})
16 | );
17 |
18 | this.transition(
19 | this.fromRoute('home'),
20 | this.toRoute('about'),
21 | this.use('fade', {duration: duration/2}),
22 | this.reverse('fade', {duration: duration/2})
23 | );
24 |
25 | this.transition(
26 | this.fromRoute('home'),
27 | this.toRoute('people'),
28 | this.use('fade', {duration: duration/2}),
29 | this.reverse('fade', {duration: duration/2})
30 | );
31 |
32 | this.transition(
33 | this.fromRoute('people'),
34 | this.toRoute('about'),
35 | this.use('fade', {duration: duration/2}),
36 | this.reverse('fade', {duration: duration/2})
37 | );
38 |
39 | this.transition(
40 | this.fromRoute('people.find'),
41 | this.toRoute('people.detail'),
42 | this.useAndReverse('explode', {
43 | matchBy: 'data-profile-email',
44 | use: ['fly-to', {duration}]
45 | },{
46 | use: "fade"
47 | })
48 | );
49 |
50 | this.transition(
51 | this.hasClass('action-bar'),
52 | this.toValue(true),
53 | this.use('toUp', {duration}),
54 | this.reverse('toDown', {duration})
55 | );
56 |
57 | this.transition(
58 | this.hasClass('slide'),
59 | this.toValue(true),
60 | this.use('toLeft', {duration}),
61 | this.reverse('toRight', {duration})
62 | );
63 |
64 | this.transition(
65 | this.childOf('#liquid-bind-progress'),
66 | this.use('toUp')
67 | );
68 |
69 | /**** Liquid Tether Modal Transition ****/
70 | this.transition(
71 | target('modal-dialog'),
72 | onOpenTether(),
73 | this.use('tether', ['to-up', options]),
74 | this.reverse('tether', ['to-down', options])
75 | );
76 |
77 |
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/main/window-state.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const electron = require('electron');
3 | const winStateKeeper = require('electron-window-state');
4 |
5 | /**
6 | * This file provides basic window state management
7 | */
8 |
9 | /**
10 | * Builds an returns an object consisting of two objects, with the following keys:
11 | * usableState: an object describing how to layout the app window given screen real estate
12 | * stateKeeper: an object that keeps track of window state change events.
13 | */
14 | function fetchWindowState() {
15 | const screen = electron.screen;
16 | const defaultWidth = 1000;
17 | const defaultHeight = 800;
18 |
19 | // Instantiate the state keeper with a default state.
20 | const stateKeeper = winStateKeeper({
21 | defaultWidth: defaultWidth,
22 | defaultHeight: defaultHeight
23 | });
24 |
25 | // Get the display nearest to the window's saved position, if it exists.
26 | const nearestDisplay = screen.getDisplayNearestPoint({
27 | x: stateKeeper.x,
28 | y: stateKeeper.y
29 | });
30 |
31 | // Get the usable screen area.
32 | const displaySize = nearestDisplay.workAreaSize;
33 |
34 | // Build an object consisting of window offset, usable width/height, and
35 | // usable minWidth/minHeight.
36 | // We want to avoid the following situations:
37 | // 1. the *minimum* width/height larger than the usable screen estate
38 | // 2. the window width/height larger than the usable screen real estate.
39 | const usableState = {
40 | x: stateKeeper.x,
41 | y: stateKeeper.y,
42 | width: displaySize.width < stateKeeper.width ? displaySize.width : stateKeeper.width,
43 | height: displaySize.height < stateKeeper.height ? displaySize.height : stateKeeper.height,
44 | minWidth: displaySize.width < defaultWidth ? displaySize.width : defaultWidth,
45 | minHeight: displaySize.height < defaultHeight ? displaySize.height : defaultHeight
46 | };
47 |
48 | return {
49 | usableState: usableState,
50 | stateKeeper: stateKeeper
51 | };
52 | };
53 |
54 | module.exports = fetchWindowState;
55 |
--------------------------------------------------------------------------------
/app/controllers/header-nav.js:
--------------------------------------------------------------------------------
1 | import Ember from "ember";
2 | import config from '../config/environment';
3 |
4 | const {
5 | Controller,
6 | inject
7 | } = Ember;
8 |
9 | export default Controller.extend({
10 | session: inject.service('session'),
11 | spinner: inject.service('spinner'),
12 | pendingApprovals: 0,
13 | isPendingApprovals: false,
14 | init : function () {
15 | let self = this;
16 | this.get("session").on('invalidationSucceeded', function() { //TODO: Not Routing On Desktop App
17 | window.location.reload();
18 | });
19 | this.getPendingApprovals().then(function (data) {
20 | if (data.length > 0) {
21 | self.set("pendingApprovals", data.length);
22 | self.set("isPendingApprovals", true);
23 | } else {
24 | self.set("pendingApprovals", data.length);
25 | self.set("isPendingApprovals", false);
26 | }
27 | });
28 | },
29 | getPendingApprovals : function () {
30 | const uid = this.get('session.secure.uid');
31 | let userRef = new Firebase(config.firebase + '/users/' + uid);
32 | let self = this;
33 |
34 | return new Promise(function (resolve, reject) {
35 | userRef.on("value", function(snapshot) {
36 | let user = snapshot.val();
37 | let friends = user.friends || {};
38 | let pending = friends.pending || [];
39 | if (user.friends && user.friends.pending && user.friends.pending.length) {
40 | self.set("pendingApprovals", pending.length);
41 | self.set("isPendingApprovals", true);
42 | } else {
43 | self.set("isPendingApprovals", false);
44 | }
45 | resolve(pending);
46 | });
47 | });
48 | },
49 | actions: {
50 | logout: function() {
51 | this.get("spinner").show("app-spinner");
52 | this.get('session').invalidate().then(function() {
53 | this.get("spinner").hide("app-spinner");
54 | this.transitionToRoute('signin');
55 | if (config.isDesktop) { //Refresh for desktop application
56 | window.location.reload(false);
57 | }
58 | }.bind(this));
59 | }
60 | }
61 | });
62 |
--------------------------------------------------------------------------------
/app/templates/home/sidebar.hbs:
--------------------------------------------------------------------------------
1 |
55 |
--------------------------------------------------------------------------------
/app/controllers/home.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from '../config/environment';
3 |
4 | const {
5 | Controller,
6 | inject
7 | } = Ember;
8 |
9 | export default Controller.extend({
10 | users: inject.service('users'),
11 | spinner: inject.service('spinner'),
12 | notify: inject.service('notify'),
13 | isNotVerified : false,
14 | verificationCode : null,
15 | code: null,
16 | init : function () {
17 | this.setVerification();
18 | },
19 | setVerification: function (guid) {
20 | const uid = this.get('session.secure.uid');
21 | let self = this;
22 | this.get("users").getCurrentUser(uid).then(function (currentUser) {
23 | self.set("isNotVerified", !currentUser.isVerified);
24 | self.set("verificationCode", currentUser.verificationCode || guid);
25 | });
26 | },
27 | actions: {
28 | verify(e) {
29 | e.preventDefault();
30 | const uid = this.get('session.secure.uid');
31 | let self = this;
32 | let isVerifiedRef = new Firebase(config.firebase + '/users/' + uid + '/isVerified');
33 | let verificationCode = this.get('verificationCode');
34 | let code = this.get('code');
35 |
36 | if (verificationCode && (verificationCode === code)) {
37 | isVerifiedRef.set(true, function (error) {
38 | if (error) {
39 | console.log('Synchronization failed');
40 | } else {
41 | self.set("isNotVerified", false);
42 | console.log('Synchronization succeeded');
43 | }
44 | });
45 | }
46 | },
47 | resend() {
48 | const uid = this.get('session.secure.uid');
49 | let self = this;
50 | self.get('spinner').show('app-spinner');
51 | this.get("users").sendVerificationCode(uid).then(function (data) {
52 | if (data.status === "success") {
53 | self.set("verificationCode", data.guid);
54 | self.get('notify').info("Verification mail sent!");
55 | } else {
56 | self.get('notify').info("Verification mail not sent!");
57 | }
58 | self.get('spinner').hide('app-spinner');
59 | }, function () {
60 | self.get('notify').info("Verification mail not sent!");
61 | self.get('spinner').hide('app-spinner');
62 | });
63 | }
64 | }
65 | });
66 |
--------------------------------------------------------------------------------
/main/entry.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const electron = require('electron');
4 | const fetchWindowState = require('./window-state');
5 | const app = electron.app;
6 | const BrowserWindow = electron.BrowserWindow;
7 | const emberAppLocation = `file://${__dirname}/../dist/index.html`;
8 |
9 |
10 | // Before we do anything else, handle Squirrel Events
11 | if (require('./squirrel')()) {
12 | return;
13 | }
14 |
15 | let mainWindow = null;
16 |
17 | app.on('ready', function onReady() {
18 | let windowState, usableState, stateKeeper;
19 |
20 | // Greetings
21 | console.log('Welcome to P2PDrop 👻');
22 |
23 | // Instantiate the window with the existing size and position.
24 | try {
25 | windowState = fetchWindowState();
26 | usableState = windowState.usableState;
27 | stateKeeper = windowState.stateKeeper;
28 |
29 | mainWindow = new BrowserWindow(
30 | Object.assign(usableState, {show: false})
31 | );
32 | } catch (error) {
33 | // Window state keeper failed, let's still open a window
34 | console.log(error);
35 | mainWindow = new BrowserWindow({
36 | show: false,
37 | height: 600,
38 | width: 800
39 | });
40 | }
41 |
42 | delete mainWindow.module;
43 |
44 | // Letting the state keeper listen to window resizing and window moving
45 | // event, and save them accordingly.
46 | if (stateKeeper) {
47 | stateKeeper.manage(mainWindow);
48 | }
49 |
50 | // If you want to open up dev tools programmatically, call
51 | // mainWindow.openDevTools();
52 | mainWindow.loadURL(emberAppLocation);
53 |
54 | // If a loading operation goes wrong, we'll send Electron back to
55 | // Ember App entry point
56 | mainWindow.webContents.on('did-fail-load', () => mainWindow.loadURL(emberAppLocation));
57 | mainWindow.webContents.on('did-finish-load', () => mainWindow.show());
58 |
59 | // Chromium drag and drop events tend to navigate the app away, making the
60 | // app impossible to use without restarting. These events should be prevented.
61 | mainWindow.webContents.on('will-navigate', (event) => event.preventDefault());
62 |
63 | mainWindow.on('closed', () => app.quit());
64 | });
65 |
--------------------------------------------------------------------------------
/app/controllers/people/find.js:
--------------------------------------------------------------------------------
1 | import Ember from "ember";
2 | import config from '../../config/environment';
3 | import _object from 'lodash/object';
4 | import _collection from 'lodash/collection';
5 | import _array from 'lodash/array';
6 |
7 | const {
8 | Controller,
9 | inject
10 | } = Ember;
11 |
12 | export default Controller.extend({
13 | session: inject.service('session'),
14 | users : inject.service('users'),
15 | filteredUsers : [],
16 | name : "",
17 | //Get Users
18 | fetchUsers : function () {
19 | let self = this;
20 | const uid = this.get('session.secure.uid');
21 |
22 | this.get("users").getCurrentUser(uid).then(function (user) {
23 | let email = user.email;
24 | new Firebase(config.firebase + "users").orderByChild('name')
25 | .on('value', function(snap){
26 | let usersList = snap.val();
27 | let users = _object.transform(usersList, function(memo, val, key) {
28 | if (val.name && val.email !== email) {
29 | memo.push(val);
30 | }
31 | }, []);
32 | self.get("users").setUsers(users);
33 | self.set("filteredUsers", _collection.sample(users, 10));
34 | });
35 | });
36 | }.on("init"),
37 | //Search Query
38 | searchQuery(query) {
39 | let users = this.get("users").getUsers();
40 | let chars = query.toLowerCase();
41 | let filteredName = _collection.filter(users, function (user) {
42 | let name = user.name.toLowerCase();
43 | if (name.search(chars) >= 0) {
44 | user.index = user.name.search(chars);
45 | return true;
46 | } else {
47 | return false;
48 | }
49 | });
50 | let filteredEmail = _collection.filter(users, function (user) {
51 | let name = user.email.toLowerCase();
52 | if (name.search(chars) >= 0) {
53 | user.index = user.name.search(chars);
54 | return true;
55 | } else {
56 | return false;
57 | }
58 | });
59 | let filtered = _array.union(filteredName, filteredEmail);
60 | let ordered = _collection.sortBy(filtered, ['index']);
61 | return ordered;
62 | },
63 | postKey: function(){
64 | let users = this.searchQuery(this.get('name'));
65 | this.set("filteredUsers", _array.take(users, 10));
66 | }.observes('name'),
67 | actions: {
68 | goToDetail(user) {
69 | this.transitionToRoute("people.detail", { queryParams: { email: user.email }});
70 | }
71 | }
72 | });
73 |
--------------------------------------------------------------------------------
/app/styles/app.scss:
--------------------------------------------------------------------------------
1 | @import "bootstrap-variables";
2 | @import "bootstrap";
3 | @import "ember-paper";
4 | @import "hover";
5 | @import "mixins";
6 | @import "components/reveal-modal.scss";
7 | @import "pages/home";
8 | @import "pages/about";
9 | @import "pages/people";
10 | @import "pages/signup";
11 | @import "pages/signin";
12 | @import "pages/profile";
13 | @import "pages/notifications";
14 |
15 | /** Override Styles **/
16 |
17 | html, body {
18 | background: $drop-grey;
19 | height: 100%;
20 | width: 100%;
21 | position: relative;
22 | }
23 |
24 | h1, h2, h3, h4 {
25 | padding: 0px;
26 | margin: 0px;
27 | }
28 |
29 | .container-fluid {
30 | padding-left: 0px;
31 | padding-right: 0px;
32 | }
33 |
34 | .navbar-brand {
35 | background: rgba(0, 0, 0, 0.2);
36 | padding: 8px 15px;
37 | }
38 |
39 | .navbar-default .navbar-nav > li > a {
40 | color: $drop-white;
41 | }
42 |
43 | .navbar-default .navbar-nav > li > a:hover {
44 | color: $drop-grey;
45 | }
46 |
47 | .navbar-toggle:hover, .navbar-toggle:focus {
48 | background-color: rgba(0, 0, 0, 0.2) !important;
49 | }
50 | /********************/
51 |
52 | /**** Hero Wrapper *******/
53 |
54 | .align-left {
55 | text-align: left !important;
56 | }
57 |
58 | .align-right {
59 | text-align: right !important;
60 | }
61 |
62 | .align-center {
63 | text-align: center !important;
64 | }
65 |
66 | .header {
67 | position: absolute;
68 | top: 0px;
69 | left: 0px;
70 | width: 100%;
71 | z-index: 999;
72 | }
73 |
74 | .p2pdrop-liquid-wrapper {
75 | position: absolute;
76 | height: 100%;
77 | width: 100%;
78 | padding-top: 52px;
79 | }
80 |
81 | .hero-wrapper {
82 | background: $drop-grey;
83 | }
84 |
85 | .form-wrapper {
86 | margin: 20px auto;
87 | width: 80%;
88 | }
89 |
90 | .fill-width {
91 | width: 100%;
92 | }
93 |
94 | .header-banner {
95 | margin: 10px auto;
96 | display: table;
97 | color: $drop-dark-grey;
98 |
99 | h4 {
100 | margin-top: 10px;
101 | margin-left: -12px;
102 | }
103 | }
104 |
105 | .alert-box.alert {
106 | background-color: #f04124;
107 | border-color: #de2d0f;
108 | color: #FFF;
109 | }
110 |
111 | .alert-box.info {
112 | background-color: #a0d3e8;
113 | border-color: #74bfdd;
114 | color: #4f4f4f;
115 | }
116 |
117 |
118 | .badge.red {
119 | background: #fa623f;
120 | border-color: #fa5a35;
121 | background-image: -webkit-linear-gradient(top, #fc9f8a, #fa623f);
122 | background-image: -moz-linear-gradient(top, #fc9f8a, #fa623f);
123 | background-image: -o-linear-gradient(top, #fc9f8a, #fa623f);
124 | background-image: linear-gradient(to bottom, #fc9f8a, #fa623f);
125 | position: absolute;
126 | top: 0px;
127 | left: 39px;
128 | }
129 |
130 | /************************/
131 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "p2pdrop",
3 | "version": "0.0.1",
4 | "description": "Small description for p2pdrop goes here",
5 | "private": true,
6 | "directories": {
7 | "doc": "doc",
8 | "test": "tests"
9 | },
10 | "scripts": {
11 | "build": "ember build",
12 | "start": "ember server",
13 | "test": "ember test"
14 | },
15 | "repository": "",
16 | "engines": {
17 | "node": ">= 0.10.0"
18 | },
19 | "author": "",
20 | "license": "MIT",
21 | "devDependencies": {
22 | "babel-eslint": "^6.0.4",
23 | "broccoli-asset-rev": "^2.1.2",
24 | "broccoli-manifest": "0.0.7",
25 | "broccoli-serviceworker": "0.1.0",
26 | "ember-cli": "1.13.8",
27 | "ember-cli-app-version": "0.5.0",
28 | "ember-cli-babel": "^5.1.3",
29 | "ember-cli-bootstrap-sassy": "0.5.1",
30 | "ember-cli-content-security-policy": "0.4.0",
31 | "ember-cli-dependency-checker": "^1.0.1",
32 | "ember-cli-eslint": "1.4.0",
33 | "ember-cli-github-pages": "0.0.8",
34 | "ember-cli-google-analytics": "^1.5.0",
35 | "ember-cli-htmlbars": "0.7.9",
36 | "ember-cli-htmlbars-inline-precompile": "^0.2.0",
37 | "ember-cli-ic-ajax": "0.2.1",
38 | "ember-cli-inject-live-reload": "^1.3.1",
39 | "ember-cli-moment-shim": "0.7.1",
40 | "ember-cli-notifications": "2.1.4",
41 | "ember-cli-qunit": "^1.0.0",
42 | "ember-cli-release": "0.2.3",
43 | "ember-cli-sass": "5.3.0",
44 | "ember-cli-sass-lint": "1.0.1",
45 | "ember-cli-simple-auth": "0.8.0",
46 | "ember-cli-simple-auth-firebase": "1.0.5",
47 | "ember-cli-spinner": "0.0.7",
48 | "ember-cli-sri": "^1.0.3",
49 | "ember-cli-uglify": "^1.2.0",
50 | "ember-data": "1.13.8",
51 | "ember-disable-proxy-controllers": "^1.0.0",
52 | "ember-export-application-global": "^1.0.3",
53 | "ember-imgur": "0.1.0",
54 | "ember-lodash": "0.0.6",
55 | "ember-moment": "4.1.0",
56 | "ember-notify": "5.0.2",
57 | "ember-paper": "0.2.11",
58 | "ember-watson": "0.7.0",
59 | "emberfire": "1.6.4",
60 | "eslint": "^2.10.2",
61 | "liquid-fire": "0.22.0",
62 | "liquid-tether": "1.0.0"
63 | },
64 | "ember-electron": {
65 | "copy-files": [
66 | "package.json",
67 | "main/*"
68 | ],
69 | "name": "P2PDrop",
70 | "app-bundle-id": "com.chaicode.p2pdrop",
71 | "app-category-type": null,
72 | "app-copyright": "Copyright (c) 2016 Chaicode",
73 | "helper-bundle-id": null,
74 | "icon": "assets/icons/ghost",
75 | "overwrite": true,
76 | "sign": null,
77 | "osx-sign": {
78 | "identity": "Ajain Vivek"
79 | },
80 | "version-string": {
81 | "CompanyName": "Chaicode",
82 | "FileDescription": "P2PDROP for Desktops",
83 | "ProductName": "P2PDrop",
84 | "InternalName": "Chaicode"
85 | },
86 | "version": "0.37.7"
87 | },
88 | "main": "main/entry.js",
89 | "dependencies": {
90 | "electron-prebuilt": "^0.37.7",
91 | "electron-rebuild": "^1.1.3",
92 | "ember-electron": "^1.4.1",
93 | "electron-window-state": "^2.0.0"
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/app/services/ips.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Service.extend({
4 | getLocalIps : function () {
5 | return new Ember.RSVP.Promise(function (resolve, reject) {
6 | var ip_dups = {};
7 |
8 | //compatibility for firefox and chrome
9 | var RTCPeerConnection = window.RTCPeerConnection
10 | || window.mozRTCPeerConnection
11 | || window.webkitRTCPeerConnection;
12 | var useWebKit = !!window.webkitRTCPeerConnection;
13 |
14 | //bypass naive webrtc blocking using an iframe
15 | if(!RTCPeerConnection){
16 | //NOTE: you need to have an iframe in the page right above the script tag
17 | //
18 | //
19 | //