summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/static/css/style.css72
-rw-r--r--share/static/img/ajax.gifbin0 -> 847 bytes
-rw-r--r--share/static/js/receive-noscript.js2
-rw-r--r--share/static/js/receive.js218
-rw-r--r--share/templates/receive.html69
5 files changed, 226 insertions, 135 deletions
diff --git a/share/static/css/style.css b/share/static/css/style.css
index 73d3e6f9..65bafba5 100644
--- a/share/static/css/style.css
+++ b/share/static/css/style.css
@@ -9,7 +9,7 @@
body {
margin: 0;
- font-family: Helvetica;
+ font-family: Helvetica, sans-serif;
}
header {
@@ -103,58 +103,96 @@ table.file-list td:last-child {
}
.upload-wrapper {
- display: flex;
align-items: center;
justify-content: center;
min-height: 400px;
-}
-
-.upload {
text-align: center;
}
-.upload img {
+.upload-wrapper img.logo {
width: 120px;
height: 120px;
}
-.upload .upload-header {
+.upload-wrapper .upload-header {
font-size: 30px;
font-weight: normal;
color: #666666;
margin: 0 0 10px 0;
}
-.upload .upload-description {
+.upload-wrapper .upload-description {
color: #666666;
margin: 0 0 20px 0;
}
+div#uploads {
+ width: 800px;
+ max-width: 90%;
+ margin: 0 auto;
+}
+
+div#uploads .upload {
+ border: 1px solid #DDDDDD;
+ margin: 20px 0;
+ padding: 10px;
+ text-align: left;
+}
+
+div#uploads .upload .upload-filename {
+ font-weight: bold;
+ font-family: monospace;
+ font-size: 1.1em;
+ margin-bottom: 5px;
+}
+
+div#uploads .upload .upload-status {
+ color: #999999;
+ font-size: 0.9em;
+ margin-bottom: 5px;
+}
+
+div#uploads .upload input.cancel {
+ color: #f24537;
+ border: 0;
+ background: none;
+ box-shadow: none;
+ border-radius: 0px;
+ cursor: pointer;
+ font-family: sans-serif;
+ font-size: 12px;
+ text-decoration: none;
+ display: inline-block;
+ float:right;
+}
+
+div#uploads .upload progress {
+ width: 100%;
+ height: 20px;
+}
+
ul.flashes {
list-style: none;
margin: 0;
padding: 0;
- color: #cc0000;
- text-align: left;
+ width: 800px;
+ max-width: 90%;
+ margin: 0 auto;
}
ul.flashes li {
margin: 0 0 5px 0;
- padding: 10px;
+ padding: 5px;
list-style: none;
- border: 0;
- border-radius: 3px;
text-align: left;
}
li.error {
- color: #ffffff;
- background-color: #c90c0c;
+ color: #dd4040;
}
li.info {
- color: #000000;
- background-color: #a9e26c;
+ color: #3e933f;
}
.closed-wrapper {
diff --git a/share/static/img/ajax.gif b/share/static/img/ajax.gif
new file mode 100644
index 00000000..01d955aa
--- /dev/null
+++ b/share/static/img/ajax.gif
Binary files differ
diff --git a/share/static/js/receive-noscript.js b/share/static/js/receive-noscript.js
new file mode 100644
index 00000000..0f4ac1bc
--- /dev/null
+++ b/share/static/js/receive-noscript.js
@@ -0,0 +1,2 @@
+// Hide the noscript div, because our javascript is executing
+document.getElementById('noscript').style.display = 'none';
diff --git a/share/static/js/receive.js b/share/static/js/receive.js
index 45cbc9dc..0de80952 100644
--- a/share/static/js/receive.js
+++ b/share/static/js/receive.js
@@ -1,94 +1,140 @@
-// Hide the noscript div, because our javascript is executing
-document.getElementById('noscript').style.display = 'none';
-
-var form = document.getElementById('send');
-var fileSelect = document.getElementById('file-select');
-var uploadButton = document.getElementById('send-button');
-var flashes = document.getElementById('flashes');
-
-// Add a flash message
-function flash(category, message) {
- var el = document.createElement('li');
- el.innerText = message;
- el.className = category;
- flashes.appendChild(el);
-}
-
-form.onsubmit = function(event) {
- event.preventDefault();
-
- // Disable button, and update text
- uploadButton.innerHTML = 'Uploading ...';
- uploadButton.disabled = true;
- fileSelect.disabled = true;
-
- // Create form data
- var files = fileSelect.files;
- var formData = new FormData();
- for (var i = 0; i < files.length; i++) {
- var file = files[i];
- formData.append('file[]', file, file.name);
- }
-
- // Set up the request
- var ajax = new XMLHttpRequest();
-
- ajax.upload.addEventListener('progress', function(event){
- console.log('upload progress', 'uploaded '+event.loaded+' bytes / '+event.total+' bytes');
- var percent = parseInt((event.loaded / event.total) * 100, 10);
- uploadButton.innerHTML = 'Uploading '+percent+'%';
- }, false);
-
- ajax.addEventListener('load', function(event){
- console.log('upload finished', ajax.response);
- if(ajax.status == 200) {
- // Parse response
- try {
- var response = JSON.parse(ajax.response);
-
- // The 'new_body' response replaces the whole HTML document and ends
- if('new_body' in response) {
- document.body.innerHTML = response['new_body'];
- return;
+$(function(){
+ // Add a flash message
+ var flash = function(category, message) {
+ $('#flashes').append($('<li>').addClass(category).text(message));
+ };
+
+ // Add an upload
+ var new_upload_div = function(xhr, filenames) {
+ /*
+ The DOM for an upload looks something like this:
+
+ <div class="upload">
+ <div class="upload-meta">
+ <input class="cancel" type="button" value="Cancel" />
+ <div class="upload-filename">educational-video.mp4, secret-plans.pdf</div>
+ <div class="upload-status">Sending to first Tor node ...</div>
+ </div>
+ <progress value="25" max="100"></progress>
+ </div>
+ */
+ var $progress = $('<progress>').attr({ value: '0', max: 100 });
+ var $cancel_button = $('<input>').addClass('cancel').attr({ type: 'button', value: 'Cancel' });
+ var $upload_filename = $('<div>').addClass('upload-filename').text(filenames.join(', '));
+ var $upload_status = $('<div>').addClass('upload-status').text('Sending data to initial Tor node ...');
+
+ var $upload_div = $('<div>').addClass('upload')
+ .append(
+ $('<div>').addClass('upload-meta')
+ .append($cancel_button)
+ .append($upload_filename)
+ .append($upload_status)
+ )
+ .append($progress);
+
+ $cancel_button.click(function(){
+ // Abort the upload, and remove the upload div
+ xhr.abort();
+ $upload_div.remove()
+ });
+
+ return $upload_div;
+ };
+
+ // Intercept submitting the form
+ $('#send').submit(function(event){
+ event.preventDefault();
+
+ // Create form data, and list of filenames
+ var files = $('#file-select').get(0).files;
+ var filenames = [];
+ var formData = new FormData();
+ for(var i = 0; i < files.length; i++) {
+ var file = files[i];
+ filenames.push(file.name);
+ formData.append('file[]', file, file.name);
+ }
+
+ // Reset the upload form
+ $('#send').get(0).reset();
+
+ // Start upload
+ xhr = $.ajax({
+ method: 'POST',
+ url: window.location.pathname + '/upload-ajax',
+ data: formData,
+ // Tell jQuery not to process data or worry about content-type
+ cache: false,
+ contentType: false,
+ processData: false,
+ // Custom XMLHttpRequest
+ xhr: function() {
+ var xhr = $.ajaxSettings.xhr();
+ if(xhr.upload) {
+ xhr.upload.addEventListener('progress', function(event) {
+ // Update progress bar for this specific upload
+ if(event.lengthComputable) {
+ console.log('upload progress', ''+event.loaded+' bytes / '+event.total+' bytes');
+ $('progress', this.$upload_div).attr({
+ value: event.loaded,
+ max: event.total,
+ });
+ }
+
+ // If it's finished sending all data to the first Tor node, remove cancel button
+ // and update the status
+ if(event.loaded == event.total) {
+ console.log('upload progress', 'complete');
+ $('.cancel', this.$upload_div).remove();
+ $('.upload-status', this.$upload_div).html('<img src="/static/img/ajax.gif" alt="" /> Waiting for data to finish traversing Tor network ...');
+ }
+ }, false);
}
+ return xhr;
+ },
+ success: function(data, textStatus, xhr){
+ console.log('upload finished', data);
+
+ // Remove the upload div
+ xhr.$upload_div.remove();
+
+ // Parse response
+ try {
+ var response = JSON.parse(data);
- // Show error flashes
- if('error_flashes' in response) {
- for(var i=0; i<response['error_flashes'].length; i++) {
- flash('error', response['error_flashes'][i]);
+ // The 'new_body' response replaces the whole HTML document and ends
+ if('new_body' in response) {
+ $('body').html(response['new_body']);
+ return;
+ }
+
+ // Show error flashes
+ if('error_flashes' in response) {
+ for(var i=0; i<response['error_flashes'].length; i++) {
+ flash('error', response['error_flashes'][i]);
+ }
}
- }
- // Show info flashes
- if('info_flashes' in response) {
- for(var i=0; i<response['info_flashes'].length; i++) {
- flash('info', response['info_flashes'][i]);
+ // Show info flashes
+ if('info_flashes' in response) {
+ for(var i=0; i<response['info_flashes'].length; i++) {
+ flash('info', response['info_flashes'][i]);
+ }
}
+ } catch(e) {
+ console.log('invalid response');
+ flash('error', 'Invalid response from server: '+data);
}
- } catch(e) {
- console.log('invalid response', ajax.response);
- flash('error', 'Invalid response from server: '+ajax.response);
+ },
+ error: function(xhr, textStatus, errorThrown){
+ console.log('error', errorThrown);
+ flash('error', 'Error uploading: ' + errorThrown);
}
+ });
+ console.log('upload started', filenames);
- // Re-enable button, and update text
- uploadButton.innerHTML = 'Send Files';
- uploadButton.disabled = false;
- fileSelect.disabled = false;
- }
- }, false);
-
- ajax.addEventListener('error', function(event){
- console.log('error', event);
- flash('error', 'Error uploading');
- }, false);
-
- ajax.addEventListener('abort', function(event){
- console.log('abort', event);
- flash('error', 'Upload aborted');
- }, false);
-
- // Send the request
- ajax.open('POST', window.location.pathname + '/upload-ajax', true);
- ajax.send(formData);
- console.log('upload started');
-}
+ // Make the upload div
+ xhr.$upload_div = new_upload_div(xhr, filenames);
+ $('#uploads').append(xhr.$upload_div);
+ });
+});
diff --git a/share/templates/receive.html b/share/templates/receive.html
index 65aeff7a..a557a967 100644
--- a/share/templates/receive.html
+++ b/share/templates/receive.html
@@ -13,41 +13,46 @@
</header>
<div class="upload-wrapper">
- <div class="upload">
- <p><img class="logo" src="/static/img/logo_large.png" title="OnionShare"></p>
- <p class="upload-header">Send Files</p>
- <p class="upload-description">Select the files you want to send, then click "Send Files"...</p>
- <form id="send" method="post" enctype="multipart/form-data" action="{{ upload_action }}">
- <p><input type="file" id="file-select" name="file[]" multiple /></p>
- <p><button type="submit" id="send-button" class="button">Send Files</button></p>
- <div>
- <ul id="flashes" class="flashes">
- {% with messages = get_flashed_messages(with_categories=true) %}
- {% if messages %}
- {% for category, message in messages %}
- <li class="{{ category }}">{{ message }}</li>
- {% endfor %}
- {% endif %}
- {% endwith %}
- </ul>
- </div>
- </form>
-
- <!--
- We are not using a <noscript> tag because it only works when the security slider is set to
- Safest, not Safer: https://trac.torproject.org/projects/tor/ticket/29506
- -->
- <div id="noscript">
- <p>
- <strong>Warning:</strong> Due to a bug in Tor Browser and Firefox, uploads
- sometimes never finish. To upload reliably, either set your Tor Browser
- <a rel="noreferrer" target="_blank" href="https://tb-manual.torproject.org/en-US/security-slider/">security slider</a>
- to Standard or
- <a target="_blank" href="/noscript-xss-instructions">turn off your Tor Browser's NoScript XSS setting</a>.</p>
- </div>
+ <p><img class="logo" src="/static/img/logo_large.png" title="OnionShare"></p>
+ <p class="upload-header">Send Files</p>
+ <p class="upload-description">Select the files you want to send, then click "Send Files"...</p>
+
+ <form id="send" method="post" enctype="multipart/form-data" action="{{ upload_action }}">
+ <p><input type="file" id="file-select" name="file[]" multiple /></p>
+ <p><button type="submit" id="send-button" class="button">Send Files</button></p>
+ </form>
+
+ <div id="uploads"></div>
+
+ <div>
+ <ul id="flashes" class="flashes">
+ {% with messages = get_flashed_messages(with_categories=true) %}
+ {% if messages %}
+ {% for category, message in messages %}
+ <li class="{{ category }}">{{ message }}</li>
+ {% endfor %}
+ {% endif %}
+ {% endwith %}
+ </ul>
</div>
+
+ <!--
+ We are not using a <noscript> tag because it only works when the security slider is set to
+ Safest, not Safer: https://trac.torproject.org/projects/tor/ticket/29506
+ -->
+ <div id="noscript">
+ <p>
+ <strong>Warning:</strong> Due to a bug in Tor Browser and Firefox, uploads
+ sometimes never finish. To upload reliably, either set your Tor Browser
+ <a rel="noreferrer" target="_blank" href="https://tb-manual.torproject.org/en-US/security-slider/">security slider</a>
+ to Standard or
+ <a target="_blank" href="/noscript-xss-instructions">turn off your Tor Browser's NoScript XSS setting</a>.</p>
+ </div>
+ <script src="/static/js/receive-noscript.js"></script>
+
</div>
+ <script src="/static/js/jquery-3.3.1.min.js"></script>
<script src="/static/js/receive.js"></script>
</body>
</html>