Merge pull request #588 from micahflee/ux-update
Major user experience update
|
@ -2,6 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Error 404</title>
|
||||
<link href="data:image/x-icon;base64,{{favicon_b64}}" rel="icon" type="image/x-icon" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #FFC4D5;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>OnionShare</title>
|
||||
<link href="data:image/x-icon;base64,{{favicon_b64}}" rel="icon" type="image/x-icon" />
|
||||
<style>
|
||||
body {
|
||||
background-color: #222222;
|
||||
|
@ -15,4 +16,4 @@
|
|||
<body>
|
||||
<p>OnionShare download in progress</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -2,106 +2,207 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>OnionShare</title>
|
||||
<link href="data:image/x-icon;base64,{{favicon_b64}}" rel="icon" type="image/x-icon" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #222222;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
font-family: sans-serif;
|
||||
padding: 5em 1em;
|
||||
}
|
||||
.button {
|
||||
-moz-box-shadow:inset 0px 1px 0px 0px #cae3fc;
|
||||
-webkit-box-shadow:inset 0px 1px 0px 0px #cae3fc;
|
||||
box-shadow:inset 0px 1px 0px 0px #cae3fc;
|
||||
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #79bbff), color-stop(1, #4197ee) );
|
||||
background:-moz-linear-gradient( center top, #79bbff 5%, #4197ee 100% );
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#79bbff', endColorstr='#4197ee');
|
||||
background-color:#79bbff;
|
||||
-webkit-border-top-left-radius:12px;
|
||||
-moz-border-radius-topleft:12px;
|
||||
border-top-left-radius:12px;
|
||||
-webkit-border-top-right-radius:12px;
|
||||
-moz-border-radius-topright:12px;
|
||||
border-top-right-radius:12px;
|
||||
-webkit-border-bottom-right-radius:12px;
|
||||
-moz-border-radius-bottomright:12px;
|
||||
border-bottom-right-radius:12px;
|
||||
-webkit-border-bottom-left-radius:12px;
|
||||
-moz-border-radius-bottomleft:12px;
|
||||
border-bottom-left-radius:12px;
|
||||
text-indent:0;
|
||||
border:1px solid #469df5;
|
||||
display:inline-block;
|
||||
color:#ffffff;
|
||||
font-size:29px;
|
||||
font-weight:bold;
|
||||
font-style:normal;
|
||||
height:50px;
|
||||
line-height:50px;
|
||||
text-decoration:none;
|
||||
text-align:center;
|
||||
text-shadow:1px 1px 0px #287ace;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.button:hover {
|
||||
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #4197ee), color-stop(1, #79bbff) );
|
||||
background:-moz-linear-gradient( center top, #4197ee 5%, #79bbff 100% );
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#4197ee', endColorstr='#79bbff');
|
||||
background-color:#4197ee;
|
||||
}.button:active {
|
||||
position:relative;
|
||||
top:1px;
|
||||
}
|
||||
.clearfix:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
line-height: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.download-size {
|
||||
color: #999999;
|
||||
}
|
||||
.download-description {
|
||||
padding: 10px;
|
||||
}
|
||||
.file-list {
|
||||
margin: 50px auto 0 auto;
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
background-color: #333333;
|
||||
}
|
||||
.file-list th {
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #999999;
|
||||
}
|
||||
.file-list td {
|
||||
padding: 5px;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Helvetica;
|
||||
}
|
||||
|
||||
header {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
background: #fcfcfc;
|
||||
background: -webkit-linear-gradient(top, #fcfcfc 0%, #f2f2f2 100%);
|
||||
padding: 0.8rem;
|
||||
}
|
||||
|
||||
header .logo {
|
||||
vertical-align: middle;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
display: inline-block;
|
||||
margin: 0 0 0 0.5rem;
|
||||
vertical-align: middle;
|
||||
font-weight: normal;
|
||||
font-size: 1.5rem;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
header .right {
|
||||
float: right;
|
||||
font-size: .75rem;
|
||||
}
|
||||
|
||||
header .right ul li {
|
||||
display: inline;
|
||||
margin: 0 0 0 .5rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
header .button {
|
||||
color: #ffffff;
|
||||
background-color: #4e064f;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
margin-left: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
table.file-list {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.file-list th {
|
||||
text-align: left;
|
||||
text-transform: uppercase;
|
||||
font-weight: normal;
|
||||
color: #666666;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
table.file-list tr {
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
table.file-list td {
|
||||
white-space: nowrap;
|
||||
padding: 0.5rem 10rem 0.5rem 0.8rem;
|
||||
}
|
||||
|
||||
table.file-list td img {
|
||||
vertical-align: middle;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
table.file-list td:last-child {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<meta name="onionshare-filename" content="{{ filename }}">
|
||||
<meta name="onionshare-filesize" content="{{ filesize }}">
|
||||
</head>
|
||||
<body>
|
||||
<p><a class="button" href='/{{ slug }}/download'>{{ filename }} ▼</a></p>
|
||||
<p class="download-size"><strong title="{{ filesize }} bytes">{{ filesize_human }} (compressed)</strong></p>
|
||||
<p class="download-description">This zip file contains the following contents:</p>
|
||||
<table class="file-list">
|
||||
|
||||
<header class="clearfix">
|
||||
<div class="right">
|
||||
<ul>
|
||||
<li>Total size: <strong>{{ filesize_human }}</strong> (compressed)</li>
|
||||
<li><a class="button" href='/{{ slug }}/download'>Download Files</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<img class="logo" src="data:image/png;base64,{{logo_b64}}" title="OnionShare">
|
||||
<h1>OnionShare</h1>
|
||||
</header>
|
||||
|
||||
<table class="file-list" id="file-list">
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
<th onclick="sortTable(0)">Filename</th>
|
||||
<th onclick="sortTable(1)">Size</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{% for info in file_info.dirs %}
|
||||
<tr>
|
||||
<td><img width="30" height="30" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3ggbFCQXOpwjbQAAAM5JREFUSMftlksOwyAMRDFCbNjkDL1kz9K75Cq9AZF3kYIM7oqoP/KpcFK1mRUrnsbW2Fbq0N+JiPhZRMS1OZAfzLzocwCAGmC9V2Vhjduarj8CzynGqIwxsDl4SXV267E4uFTN33X8deCxDyV1XXeRYJo1UUDEa9M0pxoRK+b4HiqRcz3nVAJKRK+TSxqaGbrkNKUkBn0oNSK2+T0MA1dau9NzO4QwuvPen1lAxQtEsq/vNpSWhvZ9v/3IRMTWOQezkyuEoKy14tfHoU11A6Mr5AxrpuMVAAAAAElFTkSuQmCC" /></td>
|
||||
<td>{{ info.basename }}</td>
|
||||
<td>
|
||||
<img width="30" height="30" title="" alt="" src="data:image/png;base64,{{ folder_b64 }}" />
|
||||
{{ info.basename }}
|
||||
</td>
|
||||
<td>{{ info.size_human }}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% for info in file_info.files %}
|
||||
<tr>
|
||||
<td><img width="30" height="30" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3ggbFCQqYvRvfAAAAJFJREFUSMftlUkOwCAIAEWJ//+uIUivtYmtG7VN8KYHRhlA5zYtuB6klCTG2BcEAHrBeN4ws3jvX3lxQZmFiogMgVesVrhKXlvgakKf4KqVdAdXL+Ea3O8aILh0GnUMEhjtw9mLbUv1tx33fgItynBVoN+k2hybY3Nsjg08Bs45q4GYuQ4OIQARLYcSkUPEoiUP4j5IFasKOnUAAAAASUVORK5CYII=" /></td>
|
||||
<td>{{ info.basename }}</td>
|
||||
<td>
|
||||
<img width="30" height="30" title="" alt="" src="data:image/png;base64,{{ file_b64 }}" />
|
||||
{{ info.basename }}
|
||||
</td>
|
||||
<td>{{ info.size_human }}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<script>
|
||||
// Function to convert human-readable sizes back to bytes, for sorting
|
||||
function unhumanize(text) {
|
||||
var powers = {'b': 0, 'k': 1, 'm': 2, 'g': 3, 't': 4};
|
||||
var regex = /(\d+(?:\.\d+)?)\s?(B|K|M|G|T)?/i;
|
||||
var res = regex.exec(text);
|
||||
if(res[2] === undefined) {
|
||||
// Account for alphabetical words (file/dir names)
|
||||
return text;
|
||||
} else {
|
||||
return res[1] * Math.pow(1024, powers[res[2].toLowerCase()]);
|
||||
}
|
||||
}
|
||||
function sortTable(n) {
|
||||
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
|
||||
table = document.getElementById("file-list");
|
||||
switching = true;
|
||||
// Set the sorting direction to ascending:
|
||||
dir = "asc";
|
||||
/* Make a loop that will continue until
|
||||
no switching has been done: */
|
||||
while (switching) {
|
||||
// Start by saying: no switching is done:
|
||||
switching = false;
|
||||
rows = table.getElementsByTagName("TR");
|
||||
/* Loop through all table rows (except the
|
||||
first, which contains table headers): */
|
||||
for (i = 1; i < (rows.length - 1); i++) {
|
||||
// Start by saying there should be no switching:
|
||||
shouldSwitch = false;
|
||||
/* Get the two elements you want to compare,
|
||||
one from current row and one from the next: */
|
||||
x = rows[i].getElementsByTagName("TD")[n];
|
||||
y = rows[i + 1].getElementsByTagName("TD")[n];
|
||||
/* Check if the two rows should switch place,
|
||||
based on the direction, asc or desc: */
|
||||
if (dir == "asc") {
|
||||
if (unhumanize(x.innerHTML.toLowerCase()) > unhumanize(y.innerHTML.toLowerCase())) {
|
||||
// If so, mark as a switch and break the loop:
|
||||
shouldSwitch= true;
|
||||
break;
|
||||
}
|
||||
} else if (dir == "desc") {
|
||||
if (unhumanize(x.innerHTML.toLowerCase()) < unhumanize(y.innerHTML.toLowerCase())) {
|
||||
// If so, mark as a switch and break the loop:
|
||||
shouldSwitch= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldSwitch) {
|
||||
/* If a switch has been marked, make the switch
|
||||
and mark that a switch has been done: */
|
||||
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
|
||||
switching = true;
|
||||
// Each time a switch is done, increase this count by 1:
|
||||
switchcount ++;
|
||||
} else {
|
||||
/* If no switching has been done AND the direction is "asc",
|
||||
set the direction to "desc" and run the while loop again. */
|
||||
if (switchcount == 0 && dir == "asc") {
|
||||
dir = "desc";
|
||||
switching = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
BIN
share/images/download_completed.png
Normal file
After Width: | Height: | Size: 646 B |
BIN
share/images/download_completed_none.png
Normal file
After Width: | Height: | Size: 437 B |
BIN
share/images/download_in_progress.png
Normal file
After Width: | Height: | Size: 638 B |
BIN
share/images/download_in_progress_none.png
Normal file
After Width: | Height: | Size: 412 B |
Before Width: | Height: | Size: 2 KiB |
BIN
share/images/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
share/images/file_delete.png
Normal file
After Width: | Height: | Size: 182 B |
BIN
share/images/info.png
Normal file
After Width: | Height: | Size: 435 B |
BIN
share/images/logo_transparent.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 347 B |
Before Width: | Height: | Size: 286 B After Width: | Height: | Size: 342 B |
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 349 B |
Before Width: | Height: | Size: 513 B |
BIN
share/images/web_file.png
Normal file
After Width: | Height: | Size: 251 B |
BIN
share/images/web_folder.png
Normal file
After Width: | Height: | Size: 338 B |
|
@ -5,17 +5,17 @@
|
|||
"wait_for_hs_trying": "Trying...",
|
||||
"wait_for_hs_nope": "Not ready yet.",
|
||||
"wait_for_hs_yup": "Ready!",
|
||||
"give_this_url": "Give this URL to the person you're sending the file to:",
|
||||
"give_this_url_stealth": "Give this URL and HidServAuth line to the person you're sending the file to:",
|
||||
"ctrlc_to_stop": "Press Ctrl-C to stop server",
|
||||
"give_this_url": "Give this address to the person you're sending the file to:",
|
||||
"give_this_url_stealth": "Give this address and HidServAuth line to the person you're sending the file to:",
|
||||
"ctrlc_to_stop": "Press Ctrl-C to stop server",
|
||||
"not_a_file": "{0:s} is not a valid file.",
|
||||
"not_a_readable_file": "{0:s} is not a readable file.",
|
||||
"no_available_port": "Could not start the Onion service as there was no available port.",
|
||||
"download_page_loaded": "Download page loaded",
|
||||
"other_page_loaded": "URL loaded",
|
||||
"close_on_timeout": "Closing automatically because timeout was reached",
|
||||
"closing_automatically": "Closing automatically because download finished",
|
||||
"timeout_download_still_running": "Waiting for download to complete before auto-stopping",
|
||||
"other_page_loaded": "Address loaded",
|
||||
"close_on_timeout": "Stopped because timer expired",
|
||||
"closing_automatically": "Stopped because download finished",
|
||||
"timeout_download_still_running": "Waiting for download to complete",
|
||||
"large_filesize": "Warning: Sending large files could take hours",
|
||||
"error_tails_invalid_port": "Invalid value, port must be an integer",
|
||||
"error_tails_unknown_root": "Unknown error with Tails root process",
|
||||
|
@ -34,21 +34,25 @@
|
|||
"help_debug": "Log application errors to stdout, and log web errors to disk",
|
||||
"help_filename": "List of files or folders to share",
|
||||
"help_config": "Path to a custom JSON config file (optional)",
|
||||
"gui_drag_and_drop": "Drag and drop\nfiles here",
|
||||
"gui_drag_and_drop": "Drag and drop files and folders\nto start sharing",
|
||||
"gui_add": "Add",
|
||||
"gui_delete": "Delete",
|
||||
"gui_choose_items": "Choose",
|
||||
"gui_start_server": "Start Sharing",
|
||||
"gui_stop_server": "Stop Sharing",
|
||||
"gui_copy_url": "Copy URL",
|
||||
"gui_stop_server_shutdown_timeout": "Stop Sharing ({}s remaining)",
|
||||
"gui_stop_server_shutdown_timeout_tooltip": "Share will stop automatically at {}",
|
||||
"gui_copy_url": "Copy Address",
|
||||
"gui_copy_hidservauth": "Copy HidServAuth",
|
||||
"gui_downloads": "Downloads:",
|
||||
"gui_canceled": "Canceled",
|
||||
"gui_copied_url": "Copied URL to clipboard",
|
||||
"gui_copied_hidservauth": "Copied HidServAuth line to clipboard",
|
||||
"gui_copied_url_title": "Copied OnionShare address",
|
||||
"gui_copied_url": "The OnionShare address has been copied to clipboard",
|
||||
"gui_copied_hidservauth_title": "Copied HidServAuth",
|
||||
"gui_copied_hidservauth": "The HidServAuth line has been copied to clipboard",
|
||||
"gui_starting_server1": "Starting Tor onion service...",
|
||||
"gui_starting_server2": "Crunching files...",
|
||||
"gui_please_wait": "Please wait...",
|
||||
"gui_please_wait": "Starting... Click to cancel",
|
||||
"error_hs_dir_cannot_create": "Cannot create onion service dir {0:s}",
|
||||
"error_hs_dir_not_writable": "onion service dir {0:s} is not writable",
|
||||
"using_ephemeral": "Starting ephemeral Tor onion service and awaiting publication",
|
||||
|
@ -56,10 +60,11 @@
|
|||
"gui_download_progress_starting": "{0:s}, %p% (Computing ETA)",
|
||||
"gui_download_progress_eta": "{0:s}, ETA: {1:s}, %p%",
|
||||
"version_string": "Onionshare {0:s} | https://onionshare.org/",
|
||||
"gui_quit_warning": "Are you sure you want to quit?\nThe URL you are sharing won't exist anymore.",
|
||||
"gui_quit_title": "Transfer in Progress",
|
||||
"gui_quit_warning": "You're in the process of sending files. Are you sure you want to quit OnionShare?",
|
||||
"gui_quit_warning_quit": "Quit",
|
||||
"gui_quit_warning_dont_quit": "Don't Quit",
|
||||
"error_rate_limit": "An attacker might be trying to guess your URL. To prevent this, OnionShare has automatically stopped the server. To share the files you must start it again and share the new URL.",
|
||||
"gui_quit_warning_dont_quit": "Cancel",
|
||||
"error_rate_limit": "An attacker might be trying to guess your address. To prevent this, OnionShare has automatically stopped the server. To share the files you must start it again and share the new address.",
|
||||
"zip_progress_bar_format": "Crunching files: %p%",
|
||||
"error_stealth_not_supported": "To create stealth onion services, you need at least Tor 0.2.9.1-alpha (or Tor Browser 6.5) and at least python3-stem 1.5.0.",
|
||||
"error_ephemeral_not_supported": "OnionShare requires at least Tor 0.2.7.1 and at least python3-stem 1.4.0.",
|
||||
|
@ -105,7 +110,7 @@
|
|||
"gui_settings_button_save": "Save",
|
||||
"gui_settings_button_cancel": "Cancel",
|
||||
"gui_settings_button_help": "Help",
|
||||
"gui_settings_shutdown_timeout_choice": "Set auto-stop timer?",
|
||||
"gui_settings_shutdown_timeout_checkbox": "Use auto-stop timer",
|
||||
"gui_settings_shutdown_timeout": "Stop the share at:",
|
||||
"settings_saved": "Settings saved to {}",
|
||||
"settings_error_unknown": "Can't connect to Tor controller because the settings don't make sense.",
|
||||
|
@ -135,6 +140,17 @@
|
|||
"gui_server_started_after_timeout": "The server started after your chosen auto-timeout.\nPlease start a new share.",
|
||||
"gui_server_timeout_expired": "The chosen timeout has already expired.\nPlease update the timeout and then you may start sharing.",
|
||||
"share_via_onionshare": "Share via OnionShare",
|
||||
"gui_save_private_key_checkbox": "Use a persistent URL\n(unchecking will delete any saved URL)",
|
||||
"persistent_url_in_use": "This share is using a persistent URL"
|
||||
"gui_save_private_key_checkbox": "Use a persistent address\n(unchecking will delete any saved address)",
|
||||
"gui_url_description": "<b>Anyone</b> with this link can <b>download</b> your files using <b>Tor Browser</b>: <img src={} />",
|
||||
"gui_url_label_persistent": "This share will not stop automatically unless a timer is set.<br><br>Every share will have the same address (to use one-time addresses, disable persistence in the Settings)",
|
||||
"gui_url_label_stay_open": "This share will not stop automatically unless a timer is set.",
|
||||
"gui_url_label_onetime": "This share will stop after the first download",
|
||||
"gui_url_label_onetime_and_persistent": "This share will stop after the first download<br><br>Every share will have the same address (to use one-time addresses, disable persistence in the Settings)",
|
||||
"gui_status_indicator_stopped": "Ready to Share",
|
||||
"gui_status_indicator_working": "Starting...",
|
||||
"gui_status_indicator_started": "Sharing",
|
||||
"gui_file_info": "{} Files, {}",
|
||||
"gui_file_info_single": "{} File, {}",
|
||||
"info_in_progress_downloads_tooltip": "{} download(s) in progress",
|
||||
"info_completed_downloads_tooltip": "{} download(s) completed"
|
||||
}
|
||||
|
|