Browse Source

Added progress and error tiles, and more options available in settings screen

master
Teknikode 3 years ago
parent
commit
43269b15d0
7 changed files with 168 additions and 54 deletions
  1. 41
    1
      css/popup.css
  2. 16
    5
      scripts/background.js
  3. 2
    1
      scripts/options.js
  4. 68
    15
      scripts/popup.js
  5. 30
    20
      scripts/upload.js
  6. 4
    0
      views/options.html
  7. 7
    12
      views/popup.html

+ 41
- 1
css/popup.css View File

@@ -1,5 +1,5 @@
body {
width: 300px;
width: 325px;
font-size: 12px;
background: #fefefe;
color: #333;
@@ -80,7 +80,47 @@ body {
border-right: 1px solid #e7e7e7;
}

.item-panel .item-details .item-hidden {
display: hidden;
}

.item-panel .item-details .item-actions .btn {
font-size: 16px;
margin-left: 5px;
}

.item-panel .item-progress {
white-space: nowrap;
}

.item-panel .item-progress .progress-bar {
height: 15px;
position: relative;
background: #555;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
border-radius: 15px;
margin: 5px;
box-shadow: inset 0 -1px 1px rgba(9255,255,255,0.3);
}

.item-panel .item-progress .progress-bar > span {
display: block;
height: 100%;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
background-color: rgb(43,194,83);
background-image: linear-gradient(
center bottom,
rgb(43,194,83) 37%,
rgb(84,240,84) 69%
);
box-shadow:
inset 0 2px 9px rgba(255,255,255,0.3),
inset 0 -2px 6px rgba(0,0,0,0.4);
position: relative;
overflow: hidden;
text-align: center;
}

+ 16
- 5
scripts/background.js View File

@@ -95,8 +95,8 @@ function processMessage(msg, sender, sendResponse) {
case 'add-item': //
console.log('Added ' + msg.type + ' Item: ' + msg.value);
break;
case 'del-item':
delProcessItem(msg.id);
case 'clear-item':
clearProcessItem(msg.id);
returnVal = true;
break;
case 'get-item':
@@ -134,13 +134,24 @@ function addProcessItem(type, data) {
// Create a new object for this process and add it to the main list
var item = { id: processedItemTotal, type: type, data: data };
itemList.push(item);
var id = itemList.push(item);
// Update Badge
updateBadge();
return id;
}

function updateProcessItem(id, type, data) {
itemList.forEach(function(item) {
if (item.id === id) {
item.type = type;
item.data = data;
}
});
}

function getProcessItem(id) {
function getProcessItem(id) {
// Get the item from the master list
var foundItem = itemList.find(function(item) {
return item.id === id;
@@ -148,7 +159,7 @@ function getProcessItem(id) {
return foundItem;
}

function delProcessItem(id) {
function clearProcessItem(id) {
// Remove the item from the master list
itemList = itemList.filter(function(item) {
return item.id !== id;

+ 2
- 1
scripts/options.js View File

@@ -8,7 +8,7 @@ function saveOptions(e) {
},
uploads: {
encrypt: document.querySelector('#encrypt').checked,
genDelKey: false,
genDelKey: document.querySelector('#genDelKey').checked,
keySize: 256,
blockSize: 128,
chunkSize: 1000
@@ -20,6 +20,7 @@ function setCurrentChoice(result) {
document.querySelector("#username").value = result.auth.username;
document.querySelector("#authToken").value = result.auth.authToken;
document.querySelector('#encrypt').checked = result.uploads.encrypt;
document.querySelector('#genDelKey').checked = result.uploads.genDelKey;
}

function restoreOptions() {

+ 68
- 15
scripts/popup.js View File

@@ -30,7 +30,6 @@ $(document).ready(function () {
cmd: 'upload-files',
files: fileList
});
sendingFiles.then(fillItems, onError);
});
});

@@ -40,6 +39,16 @@ var sendingMessage = browser.runtime.sendMessage({
});
sendingMessage.then(fillItems, onError);

// Refresh the view every 500 ms
window.setInterval(refreshView, 100);

function refreshView() {
var refreshMsg = browser.runtime.sendMessage({
cmd: 'get-all-items'
});
refreshMsg.then(fillItems, onError);
}

function fillItems(items) {
if (items == null || items.length == 0) {
// no items available
@@ -59,12 +68,13 @@ function fillItem(item) {
// It already exists, so let's update it
itemDiv = $('#process-item-' + item.id);
}
else {
else {
// Create a new one depending on the type
switch (item.type) {
case 'shorten':
case 'paste':
case 'upload':
case 'upload':
case 'progress':
// Setup a new itemDiv
itemDiv = $('#process-item-template').clone();
itemDiv.attr('id', 'process-item-' + item.id);
@@ -77,17 +87,12 @@ function fillItem(item) {
openItem(item.id);
});
itemDiv.find('#close').click(function () {
clearItem(item.id);
itemDiv.find('#delete').click(function () {
deleteItem(item.id);
});
break;
case 'progress':
// Setup a new itemDiv
itemDiv = $('#process-item-progress-template').clone();
itemDiv.attr('id', 'process-item-' + item.id);
itemDiv.find('#close').click(function () {
cancelItem(item.id);
clearItem(item.id);
});
break;
case 'error':
@@ -105,6 +110,38 @@ function fillItem(item) {
$('#process-list').prepend(itemDiv);
}
// Hide/show div's based on info
switch (item.type) {
case 'shorten':
case 'paste':
itemDiv.find('#item-details').show();
itemDiv.find('#item-progress').hide();
itemDiv.find('#delete').hide();
itemDiv.find('#item-error').hide();
break;
case 'upload':
itemDiv.find('#item-details').show();
itemDiv.find('#item-progress').hide();
if (item.data.genDelKey) {
itemDiv.find('#delete').show();
}
else {
itemDiv.find('#delete').hide();
}
itemDiv.find('#item-error').hide();
break;
case 'progress':
itemDiv.find('#item-details').hide();
itemDiv.find('#item-progress').show();
itemDiv.find('#item-error').hide();
break;
case 'error':
itemDiv.find('#item-details').hide();
itemDiv.find('#item-progress').hide();
itemDiv.find('#item-error').show();
break;
}
// Add the data info depending on the type
switch (item.type) {
case 'shorten':
@@ -125,14 +162,21 @@ function fillItem(item) {
if (item.data.encrypted) {
fullUrl = fullUrl + '#' + key;
}
if (item.data.genDelKey) {
itemDiv.find('#deleteUrl').html(item.data.url + '/' + item.data.deletionKey);
}
itemDiv.find('#url').html(fullUrl);
break;
case 'progress':
itemDiv.find('#title').html('Processing ' + item.type + '...');
itemDiv.find('#progress').html(item.data.progress);
itemDiv.find('#item-details').hide();
itemDiv.find('#item-progress').show();
itemDiv.find('#delete').hide();
itemDiv.find('#title').html('Processing ' + item.data.type + '...');
itemDiv.find('#progress-fill').css('width', item.data.progress + '%');
itemDiv.find('#progress-fill').html(item.data.progress + '% ' + item.data.message);
break;
case 'error':
itemDiv.find('#title').html('Error');
itemDiv.find('#title').html(item.data.title);
itemDiv.find('#error').html(item.data.message);
break;
}
@@ -146,7 +190,7 @@ function cancelItem(id) {
}

function clearItem(id) {
var msg = browser.runtime.sendMessage({ cmd: 'del-item', id: id });
var msg = browser.runtime.sendMessage({ cmd: 'clear-item', id: id });
msg.then(function() {
$('#process-item-' + id).remove();
}, onError);
@@ -162,6 +206,15 @@ function copyItem(id) {
copyTextToClipboard(itemDiv.find('#url').html());
}

function deleteItem(id) {
var itemDiv = $('#process-item-' + id);
browser.tabs.create({ url: itemDiv.find('#deleteUrl').html() });
var msg = browser.runtime.sendMessage({ cmd: 'clear-item', id: id });
msg.then(function() {
$('#process-item-' + id).remove();
}, onError);
}

function copyTextToClipboard(text) {
var copyFrom = document.createElement("textarea");
copyFrom.textContent = text;

+ 30
- 20
scripts/upload.js View File

@@ -1,4 +1,7 @@
function uploadFromUrl(contentUrl) {
function uploadFromUrl(contentUrl) {
// Add the initial item
var itemId = addProcessItem('progress', { type: 'upload', progress: 0, message: 'Loaded' });
// Download the file
var xhr = new XMLHttpRequest();
xhr.open('GET', contentUrl);
@@ -7,24 +10,25 @@ function uploadFromUrl(contentUrl) {
// Get the current settings before encrypting
getSettings(function(settings) {
// Encrypt the downloaded file
encryptFile(xhr.response, xhr.response.type, settings, uploadFile);
encryptFile(xhr.response, xhr.response.type, settings, itemId, uploadFile);
});
};
xhr.onerror = function(err) {
updateProcessItem(itemId, 'error', { title: 'Upload Error', message: err });
onError("Upload Error: " + err);
};
xhr.onprogress = function (data) {
if (data.lengthComputable) {
var percentComplete = parseInt(((data.loaded / data.total) * 100), 10);
// display loaded progress
console.log("Download Progress: " + percentComplete + '% Downloaded');
updateProcessItem(itemId, 'progress', { type: 'upload', progress: percentComplete, message: 'Downloaded' });
}
}
xhr.send();
}

// Function to encrypt a file, overide the file's data attribute with the encrypted value, and then call a callback function if supplied
function encryptFile(fileBlob, contentType, settings, callback) {
function encryptFile(fileBlob, contentType, settings, itemId, callback) {
var encScriptSrc = browser.extension.getURL('scripts/EncryptionWorker.js');
var aesScriptSrc = browser.extension.getURL('scripts/Crypto-js/crypto-js.min.js');
@@ -40,7 +44,7 @@ function encryptFile(fileBlob, contentType, settings, callback) {

// Encrypt on the server side if they ask for it
if (!settings.uploads.encrypt) {
callback(e.target.result, keyStr, ivStr, contentType, settings);
callback(e.target.result, keyStr, ivStr, contentType, settings, itemId);
}
else {
var worker = new Worker(encScriptSrc);
@@ -50,12 +54,12 @@ function encryptFile(fileBlob, contentType, settings, callback) {
case 'progress':
var percentComplete = Math.round(e.data.processed * 100 / e.data.total);
// Display encryption progress
console.log("Upload Progress: " + percentComplete + '% Encrypted');
updateProcessItem(itemId, 'progress', { type: 'upload', progress: percentComplete, message: 'Encrypted' });
break;
case 'finish':
if (callback != null) {
// Finish
callback(e.data.buffer, keyStr, ivStr, contentType, settings);
callback(e.data.buffer, keyStr, ivStr, contentType, settings, itemId);
}
break;
}
@@ -63,6 +67,7 @@ function encryptFile(fileBlob, contentType, settings, callback) {

worker.onerror = function (err) {
// An error occured
updateProcessItem(itemId, 'error', { title: 'Upload Encryption Error', message: err.message });
onError("Upload Encryption Error: " + err.message);
}

@@ -85,7 +90,7 @@ function encryptFile(fileBlob, contentType, settings, callback) {
if (data.lengthComputable) {
var percentComplete = parseInt(((data.loaded / data.total) * 100), 10);
// display loaded progress
console.log("Upload Progress: " + percentComplete + '% Loaded');
updateProcessItem(itemId, 'progress', { type: 'upload', progress: percentComplete, message: 'Loaded' });
}
}

@@ -93,7 +98,7 @@ function encryptFile(fileBlob, contentType, settings, callback) {
reader.readAsArrayBuffer(fileBlob);
}

function uploadFile(data, key, iv, contentType, settings)
function uploadFile(data, key, iv, contentType, settings, itemId)
{
// Get the upload url
var uploadAPI = "https://api.teknik.io/v1/Upload";
@@ -118,10 +123,10 @@ function uploadFile(data, key, iv, contentType, settings)

// Send the form data and report the results
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress.bind(null), false);
xhr.addEventListener("load", uploadComplete.bind(null, key, settings.uploads.encrypt), false);
xhr.addEventListener("error", uploadFailed.bind(null), false);
xhr.addEventListener("abort", uploadCanceled.bind(null), false);
xhr.upload.addEventListener("progress", uploadProgress.bind(null, itemId), false);
xhr.addEventListener("load", uploadComplete.bind(null, itemId, key, settings.uploads.encrypt, settings.uploads.genDelKey), false);
xhr.addEventListener("error", uploadFailed.bind(null, itemId), false);
xhr.addEventListener("abort", uploadCanceled.bind(null, itemId), false);
xhr.open("POST", uploadAPI);
// If they have basic auth settings, use them
if (settings.auth && settings.auth.username !== '' && settings.auth.authToken !== '') {
@@ -130,14 +135,14 @@ function uploadFile(data, key, iv, contentType, settings)
xhr.send(fd);
}

function uploadProgress(evt) {
function uploadProgress(itemId, evt) {
if (evt.lengthComputable) {
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
console.log("Upload Progress: " + percentComplete + '% Uploaded');
updateProcessItem(itemId, 'progress', { type: 'upload', progress: percentComplete, message: 'Uploaded' });
}
}

function uploadComplete(key, encrypted, evt) {
function uploadComplete(itemId, key, encrypted, genDelKey, evt) {
obj = JSON.parse(evt.target.responseText);
if (obj.result != null) {
// Add the saveKey to the results
@@ -148,11 +153,14 @@ function uploadComplete(key, encrypted, evt) {
obj.result.key = key;
}
obj.result.genDelKey = genDelKey;
// Add the completed item
addProcessItem('upload', obj.result);
updateProcessItem(itemId, 'upload', obj.result);
}
else
{
updateProcessItem(itemId, 'error', { title: 'Upload Error', message: 'Unable to Upload File' });
if (obj.error != null) {
onError("Upload Error: " + obj.error.message);
}
@@ -162,10 +170,12 @@ function uploadComplete(key, encrypted, evt) {
}
}

function uploadFailed(evt) {
onError('Upload Error: Upload Failed');
function uploadFailed(itemId, evt) {
updateProcessItem(itemId, 'error', { title: 'Upload Error', message: evt });
onError('Upload Error: ' + evt);
}

function uploadCanceled(evt) {
function uploadCanceled(itemId, evt) {
updateProcessItem(itemId, 'error', { title: 'Upload Error', message: 'Upload Canceled' });
onError('Upload Error: Upload Canceled');
}

+ 4
- 0
views/options.html View File

@@ -24,6 +24,10 @@
<br />
Encrypt Uploads: <input type="checkbox" id="encrypt" />
<br />
<br />
Generate Deletion Key: <input type="checkbox" id="genDelKey" />
<br />
<br />
<button type="submit">Save</button>

+ 7
- 12
views/popup.html View File

@@ -33,26 +33,21 @@
<span class="btn item-panel-close" id="close"><i class="fa fa-times-circle"></i></span>
<div class="clear"></div>
</div>
<div class="item-details">
<div class="item-details" id="item-details">
<div class="item-actions">
<span class="btn" id="copy"><i class="fa fa-clipboard"></i></span>
<span class="btn" id="open"><i class="fa fa-external-link"></i></span>
<span class="btn" id="delete"><i class="fa fa-trash"></i></span>
</div>
<div class="item-content" id="url"></div>
<div class="clear"></div>
</div>
</div>
<!-- In Progress Template -->
<div class="item-panel" id="process-item-progress-template">
<div class="item-title">
<div class="title-text" id="title"></div>
<span class="btn item-panel-close" id="close"><i class="fa fa-ban"></i></span>
<div class="clear"></div>
</div>
<div class="item-details">
<div class="item-content" id="progress"></div>
<div class="item-progress" id="item-progress">
<div class="progress-bar" id="progress-bar">
<span class="progress-fill" id="progress-fill"></span>
</div>
</div>
<div class="item-hidden" id="deleteUrl"></div>
</div>
<!-- Error Template -->

Loading…
Cancel
Save