Moved to HarpJS with Jade, Sass and CoffeeScript

This commit is contained in:
Diego Rodríguez 2015-11-30 13:34:09 -05:00
parent b3783752ae
commit 7b8e4c62ea
16 changed files with 617 additions and 346 deletions

179
app.coffee Normal file
View file

@ -0,0 +1,179 @@
client = new WebTorrent
debug = true
app = angular.module 'bTorrent', [], ['$compileProvider','$locationProvider', ($compileProvider, $locationProvider) ->
$compileProvider.aHrefSanitizationWhitelist /^\s*(https?|magnet|blob|javascript):/
$locationProvider.html5Mode(
enabled: true
requireBase: false).hashPrefix '#'
return
]
app.controller 'bTorrentCtrl', ['$scope','$http','$log','$location', ($scope, $http, $log, $location) ->
$scope.client = client
$scope.seedIt = true
dbg = (string, torrent) ->
if debug
if torrent
$log.debug '%c' + torrent.name + ' (' + torrent.infoHash + '): %c' + string, 'color: #33C3F0', 'color: #333'
else
$log.debug '%cClient: %c' + string, 'color: #33C3F0', 'color: #333'
return
updateAll = ->
$scope.$apply()
return
setInterval updateAll, 500
$scope.client.done = ->
done = true
$scope.client.torrents.forEach (torrent) ->
if !torrent.done
done = false
return
done
$scope.client.downloading = ->
downloading = true
$scope.client.torrents.forEach (torrent) ->
if torrent.done
downloading = false
return
downloading
$scope.uploadFile = ->
document.getElementById('fileUpload').click()
return
$scope.uploadFile2 = (elem) ->
$scope.client.processing = true
dbg 'Seeding ' + elem.files[0].name
$scope.client.seed elem.files, $scope.onSeed
return
$scope.fromInput = ->
if !$scope.torrentInput == ''
$scope.client.processing = true
dbg 'Adding ' + $scope.torrentInput
$scope.client.add $scope.torrentInput, $scope.onTorrent
$scope.torrentInput = ''
return
$scope.toggleTorrent = (torrent) ->
if torrent.showFiles
torrent.showFiles = false
$scope.sTorrent = null
else
$scope.client.torrents.forEach (t) ->
t.showFiles = false
return
torrent.showFiles = true
$scope.sTorrent = torrent
return
$scope.destroyedTorrent = (err) ->
if err
throw err
dbg 'Destroyed torrent'
return
$scope.onTorrent = (torrent, isSeed) ->
$scope.client.processing = false
torrent.showFiles = false
torrent.fileName = torrent.name + '.torrent'
torrent.oTorrentFileURL = torrent.torrentFileURL
if angular.isUndefined($scope.sTorrent) or $scope.sTorrent == null
$scope.sTorrent = torrent
torrent.showFiles = true
torrent.update = ->
torrent.pProgress = (100 * torrent.progress).toFixed(1)
torrent.pDownloaded = torrent.downloaded
torrent.pUploaded = torrent.uploaded
torrent.pUploadSpeed = torrent.uploadSpeed()
torrent.pDownloadSpeed = torrent.downloadSpeed()
if torrent.done
torrent.tRemaining = 'Done'
else
remaining = moment.duration(torrent.timeRemaining / 1000, 'seconds').humanize()
torrent.tRemaining = remaining[0].toUpperCase() + remaining.substr(1)
return
torrent.files.forEach (file) ->
file.pSize = file.length
file.status = 'Downloading'
file.url = 'javascript: return false;'
file.getBlobURL (err, url) ->
if err
throw err
file.url = url
if !isSeed
dbg 'Finished downloading file ' + file.name, torrent
file.status = 'Ready'
$scope.$apply()
return
if !isSeed
dbg 'Received file ' + file.name + ' metadata', torrent
return
torrent.on 'download', (chunkSize) ->
if !isSeed
dbg 'Downloaded chunk', torrent
return
torrent.on 'upload', (chunkSize) ->
dbg 'Uploaded chunk', torrent
return
torrent.on 'done', ->
if !isSeed
dbg 'Done', torrent
torrent.update()
return
torrent.on 'wire', (wire, addr) ->
dbg 'Wire ' + addr, torrent
return
setInterval torrent.update, 500
torrent.update()
return
$scope.onSeed = (torrent) ->
$scope.onTorrent torrent, true
return
if $location.hash() != ''
$scope.client.processing = true
dbg 'Adding ' + $location.hash()
client.add $location.hash(), $scope.onTorrent
return
]
app.filter 'html', ['$sce', ($sce) ->
(input) ->
$sce.trustAsHtml input
]
app.filter 'pbytes', ->
(num) ->
exponent = undefined
unit = undefined
neg = num < 0
units = [
'B'
'kB'
'MB'
'GB'
'TB'
'PB'
'EB'
'ZB'
'YB'
]
if neg
num = -num
if num < 1
return (if neg then '-' else '') + num + ' B'
exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), units.length - 1)
num = (num / 1000 ** exponent).toFixed(1) * 1
unit = units[exponent]
(if neg then '-' else '') + num + ' ' + unit

192
app.js
View file

@ -1,192 +0,0 @@
var client = new WebTorrent({
rtcConfig: {
"iceServers": [{
"url": "stun:23.21.150.121",
"urls": "stun:23.21.150.121"
}, {
"url": "turn:global.turn.twilio.com:3478?transport=udp",
"username": "00bb844e6c2a07d4ed3e22a6edd6da6a715714a7c3eb118dc20246e5e0cc50c1",
"credential": "Wv1IxOBVhm4CGqoWYQWQ0X4Ia0Va7p2SOENv/S7M9Vg=",
"urls": "turn:global.turn.twilio.com:3478?transport=udp"
}]
}
});
var debug = true;
var prettyBytes = function (num) {
var exponent;
var unit;
var neg = num < 0;
var units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
if (neg) {
num = -num;
}
if (num < 1) {
return (neg ? '-' : '') + num + ' B';
}
exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), units.length - 1);
num = (num / Math.pow(1000, exponent)).toFixed(1) * 1;
unit = units[exponent];
return (neg ? '-' : '') + num + ' ' + unit;
};
angular.module('bTorrent', [], function ($compileProvider, $locationProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|magnet|blob|javascript):/);
$locationProvider.html5Mode({
enabled: true,
requireBase: false
}).hashPrefix('#');
}).controller('bTorrentCtrl', function ($scope, $http, $log, $location) {
$scope.client = client;
$scope.seedIt = true;
var dbg = function (string, torrent) {
if (debug) {
if (torrent)
$log.debug("%c" + torrent.name + " (" + torrent.infoHash + "): %c" + string, 'color: #33C3F0', 'color: #333');
else
$log.debug("%cClient: %c" + string, 'color: #33C3F0', 'color: #333');
}
};
var updateAll = function () {
$scope.$apply();
};
setInterval(updateAll, 500);
$scope.client.done = function () {
var done = true;
$scope.client.torrents.forEach(function (torrent) {
if (!torrent.done) {
done = false;
}
});
return done;
};
$scope.client.downloading = function () {
var downloading = true;
$scope.client.torrents.forEach(function (torrent) {
if (torrent.done) {
downloading = false;
}
});
return downloading;
};
$scope.uploadFile = function () {
document.getElementById("fileUpload").click();
};
$scope.uploadFile2 = function (elem) {
$scope.client.processing = true;
dbg("Seeding " + elem.files[0].name);
$scope.client.seed(elem.files, $scope.onSeed);
};
$scope.fromInput = function () {
if (!$scope.torrentInput == "") {
$scope.client.processing = true;
dbg("Adding " + $scope.torrentInput);
$scope.client.add($scope.torrentInput, $scope.onTorrent);
$scope.torrentInput = "";
}
};
$scope.toggleTorrent = function (torrent) {
if (torrent.showFiles) {
torrent.showFiles = false;
$scope.sTorrent = null;
} else {
$scope.client.torrents.forEach(function (t) {
t.showFiles = false;
});
torrent.showFiles = true;
$scope.sTorrent = torrent;
}
};
$scope.destroyedTorrent = function (err) {
if (err) throw err;
dbg("Destroyed torrent");
};
$scope.onTorrent = function (torrent, isSeed) {
$scope.client.processing = false;
torrent.showFiles = false;
torrent.pSize = prettyBytes(torrent.length);
torrent.fileName = torrent.name + '.torrent';
torrent.oTorrentFileURL = torrent.torrentFileURL;
if (angular.isUndefined($scope.sTorrent) || $scope.sTorrent === null) {
$scope.sTorrent = torrent;
torrent.showFiles = true;
}
torrent.update = function () {
torrent.pProgress = (100 * torrent.progress).toFixed(1);
torrent.pDownloaded = prettyBytes(torrent.downloaded);
torrent.pUploaded = prettyBytes(torrent.uploaded);
torrent.pUploadSpeed = prettyBytes(torrent.uploadSpeed());
torrent.pDownloadSpeed = prettyBytes(torrent.downloadSpeed());
if (torrent.done) {
torrent.tRemaining = 'Done'
} else {
var remaining = moment.duration(torrent.timeRemaining / 1000, 'seconds').humanize();
torrent.tRemaining = remaining[0].toUpperCase() + remaining.substr(1);
}
};
torrent.files.forEach(function (file) {
file.pSize = prettyBytes(file.length);
file.status = "Downloading";
file.url = 'javascript: return false;';
file.getBlobURL(function (err, url) {
if (err) throw err;
file.url = url;
if(!isSeed) dbg("Finished downloading file " + file.name, torrent);
file.status = "Ready";
$scope.$apply();
});
if(!isSeed) dbg("Received file " + file.name + " metadata", torrent);
});
torrent.on('download', function (chunkSize) {
if(!isSeed) dbg("Downloaded chunk", torrent);
});
torrent.on('upload', function (chunkSize) {
dbg("Uploaded chunk", torrent);
});
torrent.on('done', function () {
if(!isSeed) dbg("Done", torrent);
torrent.update();
});
torrent.on('wire', function (wire, addr) {
dbg("Wire " + addr, torrent);
});
setInterval(torrent.update, 500);
torrent.update();
};
$scope.onSeed = function(torrent) {
$scope.onTorrent(torrent, true);
};
if ($location.hash() != '') {
$scope.client.processing = true;
dbg("Adding " + $location.hash());
client.add($location.hash(), $scope.onTorrent);
}
}).filter('html', function ($sce) {
return function (input) {
return $sce.trustAsHtml(input);
}
});

View file

@ -1,99 +0,0 @@
<!DOCTYPE html>
<html ng-app="bTorrent" lang="en">
<head>
<base href="">
<meta charset="UTF-8">
<title>βTorrent: Browser WebTorrent Client</title>
<meta name="description" content="βTorrent: Browser WebTorrent Client">
<meta name="keywords" content="βTorrent, btorrent, client, webtorrent, browser, torrent">
<meta name="author" content="Diego Rodríguez Baquero - DiegoRBaquero">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.jsdelivr.net/g/webtorrent@0.62,momentjs@2.10,angularjs@1.4"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/g/normalize@3.0,skeleton@2.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/fontawesome/4.5/css/font-awesome.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>βTorrent<span class="version"> v0.4.1</span></h1>
</header>
<div class="container" ng-controller="bTorrentCtrl" ng-cloak>
<div class="row">
<div class="twelve columns">
<div class="row">
<div class="five columns"><input type="text" class="u-full-width" placeholder="magnet link or hash" id="torrentInput" ng-model="torrentInput"></div>
<div class="two columns"><button class="button-primary" ng-click="fromInput()"><i class="fa fa-download"></i> Download</button></div>
<div class="five columns u-pull-right">
<input type="file" style="display: none;" id="fileUpload" onchange="angular.element(this).scope().uploadFile2(this)">
<label class="u-pull-right">
<button class="button-primary" ng-click="uploadFile()" ><i class="fa fa-upload"></i> Seed a file</button>
</label>
</div>
</div>
<table class="u-full-width">
<thead>
<tr>
<th>Name</th>
<th ng-hide="client.done()">Downloaded</th>
<th ng-hide="client.done()">Remaining</th>
<th ng-hide="client.downloading()">Uploaded</th>
<th>Peers</th>
<th>Share</th>
<th>Actions</th>
</tr>
</thead>
<tbody ng-hide="client.torrents.length">
<tr>
<td colspan="100" class="center">Add a torrent o seed a file!</td>
</tr>
</tbody>
<tbody ng-repeat="torrent in client.torrents" ng-if="torrent.name">
<tr class="torrentRow" ng-class="{selectedTorrent: torrent.showFiles}">
<td><div><i class="fa fa-cloud-download" ng-hide="torrent.done"></i><i class="fa fa-check" ng-show="torrent.done"></i> {{torrent.name}}</div><span class="subInfo">{{torrent.pSize}} in <a href="#" onclick="return false;" ng-click="toggleTorrent(torrent)">{{torrent.files.length}} files</a></span></td>
<td ng-hide="client.done()">{{torrent.pDownloaded}} <span class="subInfo">({{torrent.pProgress}}%)</span><br /><span class="subInfo">@ {{torrent.pDownloadSpeed}}/s</span></td>
<td ng-hide="client.done()">{{torrent.tRemaining}}</td>
<td ng-hide="client.downloading()">{{torrent.pUploaded}}<br /><span class="subInfo">@ {{torrent.pUploadSpeed}}/s</span></td>
<td>{{torrent.swarm.wires.length}}</td>
<td>
<a href="#{{torrent.infoHash}}" target="_blank">βTorrent</a>
| <a href="{{torrent.magnetURI}}" target="_blank">Magnet URI</a>
| <a href="{{torrent.oTorrentFileURL}}" target="_blank" download="{{torrent.fileName}}">.torrent</a>
<br><span class="subInfo"><i class="fa fa-hashtag"></i>{{torrent.infoHash}}</span>
</td>
<td><i class="fa fa-times" ng-click="client.remove(torrent, destroyedTorrent)"></i></td>
</tr>
<tr ng-show="torrent.showFiles">
<td class="files" colspan="100">
<div class="row">
<div class="two columns center"><i class="fa fa-file"></i> <strong>Files:</strong></div>
<div class="ten columns fix-height">
<ul class="no-margin">
<li ng-repeat="file in torrent.files">
<span ng-hide="file.done">{{file.status}}: {{file.name}}</span><a href="{{file.url}}" download="{{file.name}}" target="_blank" ng-show="file.done">{{file.name}}</a> <span class="subInfo">{{file.pSize}}</span>
</li>
</ul>
</div>
</div>
</td>
</tr>
</tbody>
<tbody ng-show="client.processing">
<tr>
<td colspan="100" class="center">Please wait a few seconds!</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<footer>
Made in Bogotá, Colombia by <a href="http://diegorbaquero.com">DiegoRBaquero</a><br><small><a href="https://webtorrent.io">WebTorrent</a> is powered by JavaScript and WebRTC. Works in Chrome, Firefox, and Opera (desktop and Android).</small></p>
</footer>
<script src="app.js"></script>
</body>
</html>

104
index.jade Normal file
View file

@ -0,0 +1,104 @@
doctype html
html(ng-app='bTorrent', lang='en')
head
base(href='')
meta(charset='UTF-8')
title βTorrent: Browser WebTorrent Client
meta(name='description', content='βTorrent: Browser WebTorrent Client')
meta(name='keywords', content='βTorrent, btorrent, client, webtorrent, browser, torrent')
meta(name='author', content='Diego Rodríguez Baquero - DiegoRBaquero')
meta(name='viewport', content='width=device-width, initial-scale=1')
script(src='https://cdn.jsdelivr.net/g/webtorrent@0.62,momentjs@2.10,angularjs@1.4')
link(rel='stylesheet', href='https://cdn.jsdelivr.net/g/normalize@3.0,skeleton@2.0')
link(rel='stylesheet', href='https://cdn.jsdelivr.net/fontawesome/4.5/css/font-awesome.min.css')
link(rel='stylesheet', href='style.css')
body
header
h1
| βTorrent
span.version v0.4.1
.container(ng-controller='bTorrentCtrl', ng-cloak='')
.row
.twelve.columns
.row
.five.columns
input#torrentInput.u-full-width(type='text', placeholder='magnet link or hash', ng-model='torrentInput')
.two.columns
button.button-primary(ng-click='fromInput()')
i.fa.fa-download
| Download
.five.columns.u-pull-right
input#fileUpload(type='file', style='display: none;', onchange='angular.element(this).scope().uploadFile2(this)')
label.u-pull-right
button.button-primary(ng-click='uploadFile()')
i.fa.fa-upload
| Seed a file
table.u-full-width
thead
tr
th Name
th(ng-hide='client.done()') Downloaded
th(ng-hide='client.done()') Remaining
th(ng-hide='client.downloading()') Uploaded
th Peers
th Share
th Actions
tbody(ng-hide='client.torrents.length')
tr
td.center(colspan='100') Add a torrent o seed a file!
tbody(ng-repeat='torrent in client.torrents', ng-if='torrent.name')
tr.torrentRow(ng-class='{selectedTorrent: torrent.showFiles}')
td
div
i.fa.fa-cloud-download(ng-hide='torrent.done')
i.fa.fa-check(ng-show='torrent.done')
| {{torrent.name}}
span.subInfo
| {{torrent.length | pbytes}} in
a(href='#', onclick='return false;', ng-click='toggleTorrent(torrent)') {{torrent.files.length}} files
td(ng-hide='client.done()')
| {{torrent.downloaded | pbytes}}
span.subInfo ({{torrent.pProgress}}%)
br
span.subInfo @ {{torrent.downloadSpeed() | pbytes}}/s
td(ng-hide='client.done()') {{torrent.tRemaining}}
td(ng-hide='client.downloading()') {{torrent.uploaded | pbytes}}
br
span.subInfo @ {{torrent.uploadSpeed() | pbytes}}/s
td {{torrent.swarm.wires.length}}
td
a(href='#{{torrent.infoHash}}', target='_blank') βTorrent
|
a(href='{{torrent.magnetURI}}', target='_blank') Magnet URI
|
a(href='{{torrent.oTorrentFileURL}}', target='_blank', download='{{torrent.fileName}}') .torrent
br
span.subInfo
i.fa.fa-hashtag
| {{torrent.infoHash}}
td
i.fa.fa-times(ng-click='client.remove(torrent, destroyedTorrent)')
tr(ng-show='torrent.showFiles')
td.files(colspan='100')
.row
.two.columns.center
i.fa.fa-file
strong Files:
.ten.columns.fix-height
ul.no-margin
li(ng-repeat='file in torrent.files')
span(ng-hide='file.done') {{file.status}}: {{file.name}}
a(href='{{file.url}}', download='{{file.name}}', target='_blank', ng-show='file.done') {{file.name}}
span.subInfo {{file.length | pbytes}}
tbody(ng-show='client.processing')
tr
td.center(colspan='100') Please wait a few seconds!
footer
| Made in Bogotá, Colombia by
a(href='http://diegorbaquero.com') DiegoRBaquero
br
small
a(href='https://webtorrent.io') WebTorrent
| is powered by JavaScript and WebRTC. Works in Chrome, Firefox, and Opera (desktop and Android).
p
script(src='app.js')

View file

@ -1,55 +0,0 @@
body {
height: 100%;
width: 100%;
}
header, footer, .center {
text-align: center;
}
th, td {
padding-left: 10px;
padding-right: 10px;
max-width: 200px;
overflow: scroll;
white-space: nowrap;
}
.version {
color: #ccc;
font-size: 0.3em;
}
.torrentRow {
line-height: 1.2;
border-bottom: 0;
}
.subInfo {
color: #bbbbbb;
font-size: 0.7em;
}
.column, .columns {
margin-left: 1%;
}
.files {
padding-top: 1px;
padding-bottom: 1px;
}
.fix-height {
max-height: 24px;
}
.no-margin {
margin: 0;
}
.selectedTorrent {
background: rgb(100,100,100);
background: rgba(100,100,100,.06);
}

42
style.sass Normal file
View file

@ -0,0 +1,42 @@
body
height: 100%
width: 100%
header, footer, .center
text-align: center
th, td
padding-left: 10px
padding-right: 10px
max-width: 200px
overflow: scroll
white-space: nowrap
.version
color: #ccc
font-size: 0.3em
.torrentRow
line-height: 1.2
border-bottom: 0
.subInfo
color: #bbbbbb
font-size: 0.7em
.column, .columns
margin-left: 1%
.files
padding-top: 1px
padding-bottom: 1px
.fix-height
max-height: 24px
.no-margin
margin: 0
.selectedTorrent
background: rgb(100, 100, 100)
background: rgba(100, 100, 100, 0.06)

1
www/.idea/.name Normal file
View file

@ -0,0 +1 @@
btorrent-web

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
www/.idea/encodings.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

13
www/.idea/misc.xml Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
</project>

8
www/.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/btorrent-web.iml" filepath="$PROJECT_DIR$/.idea/btorrent-web.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions" suppressed-tasks="Jade;Sass;CoffeeScript" />
</project>

249
www/.idea/workspace.xml Normal file
View file

@ -0,0 +1,249 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="b4fff367-e330-4d8e-a0e3-6d8302538c50" name="Default" comment="" />
<ignored path="btorrent-web.iws" />
<ignored path=".idea/workspace.xml" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
<component name="CreatePatchCommitExecutor">
<option name="PATCH_PATH" value="" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
<component name="FavoritesManager">
<favorites_list name="btorrent-web" />
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="index.jade" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/index.jade">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="-0.6435986">
<caret line="15" column="14" selection-start-line="15" selection-start-column="14" selection-end-line="15" selection-end-column="14" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="app.coffee" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app.coffee">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="156" column="6" selection-start-line="156" selection-start-column="6" selection-end-line="156" selection-end-column="6" />
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/style.sass" />
<option value="$PROJECT_DIR$/app.coffee" />
<option value="$PROJECT_DIR$/index.jade" />
</list>
</option>
</component>
<component name="JsBuildToolGruntFileManager" detection-done="true" />
<component name="JsBuildToolPackageJson" detection-done="true" />
<component name="JsGulpfileManager">
<detection-done>true</detection-done>
</component>
<component name="ProjectFrameBounds">
<option name="y" value="23" />
<option name="width" value="1680" />
<option name="height" value="991" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
<manualOrder />
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="Scratches" />
<pane id="Scope" />
<pane id="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="btorrent-web" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="btorrent-web" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="btorrent-web" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="HbShouldOpenHtmlAsHb" value="" />
<property name="js-jscs-nodeInterpreter" value="/usr/local/bin/node" />
</component>
<component name="RunManager">
<configuration default="true" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application">
<method />
</configuration>
<configuration default="true" type="DartUnitRunConfigurationType" factoryName="DartUnit">
<method />
</configuration>
<configuration default="true" type="JavaScriptTestRunnerKarma" factoryName="Karma" config-file="">
<envs />
<method />
</configuration>
<configuration default="true" type="JavascriptDebugType" factoryName="JavaScript Debug">
<method />
</configuration>
<configuration default="true" type="NodeJSConfigurationType" factoryName="Node.js" working-dir="">
<method />
</configuration>
<configuration default="true" type="cucumber.js" factoryName="Cucumber.js">
<option name="cucumberJsArguments" value="" />
<option name="executablePath" />
<option name="filePath" />
<method />
</configuration>
<configuration default="true" type="js.build_tools.gulp" factoryName="Gulp.js">
<method />
</configuration>
<configuration default="true" type="js.build_tools.npm" factoryName="npm">
<command value="run-script" />
<scripts />
<envs />
<method />
</configuration>
<configuration default="true" type="mocha-javascript-test-runner" factoryName="Mocha">
<node-options />
<working-directory>$PROJECT_DIR$</working-directory>
<pass-parent-env>true</pass-parent-env>
<envs />
<ui>bdd</ui>
<extra-mocha-options />
<test-kind>DIRECTORY</test-kind>
<test-directory />
<recursive>false</recursive>
<method />
</configuration>
</component>
<component name="ShelveChangesManager" show_recycled="false" />
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="b4fff367-e330-4d8e-a0e3-6d8302538c50" name="Default" comment="" />
<created>1448905387131</created>
<option name="number" value="Default" />
<updated>1448905387131</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="0" y="23" width="1680" height="991" extended-state="6" />
<editor active="true" />
<layout>
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
</layout>
</component>
<component name="Vcs.Log.UiProperties">
<option name="RECENTLY_FILTERED_USER_GROUPS">
<collection />
</option>
<option name="RECENTLY_FILTERED_BRANCH_GROUPS">
<collection />
</option>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager />
<watches-manager />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/style.sass">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.70689654">
<caret line="41" column="39" selection-start-line="41" selection-start-column="39" selection-end-line="41" selection-end-column="39" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/404.jade">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app.coffee">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="156" column="6" selection-start-line="156" selection-start-column="6" selection-end-line="156" selection-end-column="6" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/index.jade">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="-0.6435986">
<caret line="15" column="14" selection-start-line="15" selection-start-column="14" selection-end-line="15" selection-end-column="14" />
<folding />
</state>
</provider>
</entry>
</component>
</project>

1
www/app.js Normal file
View file

@ -0,0 +1 @@
var app,client,debug;client=new WebTorrent;debug=true;app=angular.module("bTorrent",[],["$compileProvider","$locationProvider",function(e,n){e.aHrefSanitizationWhitelist(/^\s*(https?|magnet|blob|javascript):/);n.html5Mode({enabled:true,requireBase:false}).hashPrefix("#")}]);app.controller("bTorrentCtrl",["$scope","$http","$log","$location",function(e,n,t,o){var r,i;e.client=client;e.seedIt=true;r=function(e,n){if(debug){if(n){t.debug("%c"+n.name+" ("+n.infoHash+"): %c"+e,"color: #33C3F0","color: #333")}else{t.debug("%cClient: %c"+e,"color: #33C3F0","color: #333")}}};i=function(){e.$apply()};setInterval(i,500);e.client.done=function(){var n;n=true;e.client.torrents.forEach(function(e){if(!e.done){n=false}});return n};e.client.downloading=function(){var n;n=true;e.client.torrents.forEach(function(e){if(e.done){n=false}});return n};e.uploadFile=function(){document.getElementById("fileUpload").click()};e.uploadFile2=function(n){e.client.processing=true;r("Seeding "+n.files[0].name);e.client.seed(n.files,e.onSeed)};e.fromInput=function(){if(!e.torrentInput===""){e.client.processing=true;r("Adding "+e.torrentInput);e.client.add(e.torrentInput,e.onTorrent);e.torrentInput=""}};e.toggleTorrent=function(n){if(n.showFiles){n.showFiles=false;e.sTorrent=null}else{e.client.torrents.forEach(function(e){e.showFiles=false});n.showFiles=true;e.sTorrent=n}};e.destroyedTorrent=function(e){if(e){throw e}r("Destroyed torrent")};e.onTorrent=function(n,t){e.client.processing=false;n.showFiles=false;n.fileName=n.name+".torrent";n.oTorrentFileURL=n.torrentFileURL;if(angular.isUndefined(e.sTorrent)||e.sTorrent===null){e.sTorrent=n;n.showFiles=true}n.update=function(){var e;n.pProgress=(100*n.progress).toFixed(1);n.pDownloaded=n.downloaded;n.pUploaded=n.uploaded;n.pUploadSpeed=n.uploadSpeed();n.pDownloadSpeed=n.downloadSpeed();if(n.done){n.tRemaining="Done"}else{e=moment.duration(n.timeRemaining/1e3,"seconds").humanize();n.tRemaining=e[0].toUpperCase()+e.substr(1)}};n.files.forEach(function(o){o.pSize=o.length;o.status="Downloading";o.url="javascript: return false;";o.getBlobURL(function(i,l){if(i){throw i}o.url=l;if(!t){r("Finished downloading file "+o.name,n)}o.status="Ready";e.$apply()});if(!t){r("Received file "+o.name+" metadata",n)}});n.on("download",function(e){if(!t){r("Downloaded chunk",n)}});n.on("upload",function(e){r("Uploaded chunk",n)});n.on("done",function(){if(!t){r("Done",n)}n.update()});n.on("wire",function(e,t){r("Wire "+t,n)});setInterval(n.update,500);n.update()};e.onSeed=function(n){e.onTorrent(n,true)};if(o.hash()!==""){e.client.processing=true;r("Adding "+o.hash());client.add(o.hash(),e.onTorrent)}}]);app.filter("html",["$sce",function(e){return function(n){return e.trustAsHtml(n)}}]);app.filter("pbytes",function(){return function(e){var n,t,o,r;n=void 0;o=void 0;t=e<0;r=["B","kB","MB","GB","TB","PB","EB","ZB","YB"];if(t){e=-e}if(e<1){return(t?"-":"")+e+" B"}n=Math.min(Math.floor(Math.log(e)/Math.log(1e3)),r.length-1);e=(e/Math.pow(1e3,n)).toFixed(1)*1;o=r[n];return(t?"-":"")+e+" "+o}});

1
www/index.html Normal file
View file

@ -0,0 +1 @@
<!DOCTYPE html><html ng-app="bTorrent" lang="en"><head><base href=""><meta charset="UTF-8"><title>βTorrent: Browser WebTorrent Client</title><meta name="description" content="βTorrent: Browser WebTorrent Client"><meta name="keywords" content="βTorrent, btorrent, client, webtorrent, browser, torrent"><meta name="author" content="Diego Rodríguez Baquero - DiegoRBaquero"><meta name="viewport" content="width=device-width, initial-scale=1"><script src="https://cdn.jsdelivr.net/g/webtorrent@0.62,momentjs@2.10,angularjs@1.4"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/g/normalize@3.0,skeleton@2.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/fontawesome/4.5/css/font-awesome.min.css"><link rel="stylesheet" href="style.css"></head><body><header><h1>βTorrent<span class="version"> v0.4.1</span></h1></header><div ng-controller="bTorrentCtrl" ng-cloak="" class="container"><div class="row"><div class="twelve columns"><div class="row"><div class="five columns"><input id="torrentInput" type="text" placeholder="magnet link or hash" ng-model="torrentInput" class="u-full-width"></div><div class="two columns"><button ng-click="fromInput()" class="button-primary"><i class="fa fa-download"></i> Download</button></div><div class="five columns u-pull-right"><input id="fileUpload" type="file" style="display: none;" onchange="angular.element(this).scope().uploadFile2(this)"><label class="u-pull-right"><button ng-click="uploadFile()" class="button-primary"><i class="fa fa-upload"></i> Seed a file</button></label></div></div><table class="u-full-width"><thead><tr><th>Name</th><th ng-hide="client.done()">Downloaded</th><th ng-hide="client.done()">Remaining</th><th ng-hide="client.downloading()">Uploaded</th><th>Peers</th><th>Share</th><th>Actions</th></tr></thead><tbody ng-hide="client.torrents.length"><tr><td colspan="100" class="center">Add a torrent o seed a file!</td></tr></tbody><tbody ng-repeat="torrent in client.torrents" ng-if="torrent.name"><tr ng-class="{selectedTorrent: torrent.showFiles}" class="torrentRow"><td><div><i ng-hide="torrent.done" class="fa fa-cloud-download"></i><i ng-show="torrent.done" class="fa fa-check"></i> {{torrent.name}}</div><span class="subInfo">{{torrent.length | pbytes}} in <a href="#" onclick="return false;" ng-click="toggleTorrent(torrent)">{{torrent.files.length}} files</a></span></td><td ng-hide="client.done()">{{torrent.downloaded | pbytes}}<span class="subInfo">({{torrent.pProgress}}%)</span><br><span class="subInfo">@ {{torrent.downloadSpeed() | pbytes}}/s</span></td><td ng-hide="client.done()">{{torrent.tRemaining}}</td><td ng-hide="client.downloading()">{{torrent.uploaded | pbytes}}<br><span class="subInfo">@ {{torrent.uploadSpeed() | pbytes}}/s</span></td><td>{{torrent.swarm.wires.length}}</td><td><a href="#{{torrent.infoHash}}" target="_blank">βTorrent</a> <a href="{{torrent.magnetURI}}" target="_blank">Magnet URI</a> <a href="{{torrent.oTorrentFileURL}}" target="_blank" download="{{torrent.fileName}}">.torrent</a><br><span class="subInfo"><i class="fa fa-hashtag"></i>{{torrent.infoHash}}</span></td><td><i ng-click="client.remove(torrent, destroyedTorrent)" class="fa fa-times"></i></td></tr><tr ng-show="torrent.showFiles"><td colspan="100" class="files"><div class="row"><div class="two columns center"><i class="fa fa-file"></i><strong>Files:</strong></div><div class="ten columns fix-height"><ul class="no-margin"><li ng-repeat="file in torrent.files"><span ng-hide="file.done">{{file.status}}: {{file.name}}</span><a href="{{file.url}}" download="{{file.name}}" target="_blank" ng-show="file.done">{{file.name}}</a><span class="subInfo"> {{file.length | pbytes}}</span></li></ul></div></div></td></tr></tbody><tbody ng-show="client.processing"><tr><td colspan="100" class="center">Please wait a few seconds!</td></tr></tbody></table></div></div></div><footer>Made in Bogotá, Colombia by<a href="http://diegorbaquero.com">DiegoRBaquero</a><br><small><a href="https://webtorrent.io">WebTorrent</a> is powered by JavaScript and WebRTC. Works in Chrome, Firefox, and Opera (desktop and Android).</small><p></p></footer><script src="app.js"></script></body></html>

1
www/style.css Normal file
View file

@ -0,0 +1 @@
body{height:100%;width:100%}header,footer,.center{text-align:center}th,td{padding-left:10px;padding-right:10px;max-width:200px;overflow:scroll;white-space:nowrap}.version{color:#ccc;font-size:0.3em}.torrentRow{line-height:1.2;border-bottom:0}.subInfo{color:#bbb;font-size:0.7em}.column,.columns{margin-left:1%}.files{padding-top:1px;padding-bottom:1px}.fix-height{max-height:24px}.no-margin{margin:0}.selectedTorrent{background:#646464;background:rgba(100,100,100,0.06)}