Allow multiple files
This commit is contained in:
parent
6ff08b6884
commit
095a5be0b6
@ -8,6 +8,12 @@
|
|||||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#attachmentPreview {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
#attachmentPreview img {
|
#attachmentPreview img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
353
js/privatebin.js
353
js/privatebin.js
@ -2536,11 +2536,18 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
// show preview
|
// show preview
|
||||||
PasteViewer.setText($message.val());
|
PasteViewer.setText($message.val());
|
||||||
if (AttachmentViewer.hasAttachmentData()) {
|
if (AttachmentViewer.hasAttachmentData()) {
|
||||||
const attachment = AttachmentViewer.getAttachment();
|
const attachmentsData = AttachmentViewer.getAttachmentsData();
|
||||||
AttachmentViewer.handleBlobAttachmentPreview(
|
|
||||||
AttachmentViewer.getAttachmentPreview(),
|
attachmentsData.forEach(attachmentData => {
|
||||||
attachment[0], attachment[1]
|
const mimeType = AttachmentViewer.getAttachmentMimeType(attachmentData);
|
||||||
);
|
|
||||||
|
AttachmentViewer.handleBlobAttachmentPreview(
|
||||||
|
AttachmentViewer.getAttachmentPreview(),
|
||||||
|
attachmentData, mimeType
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
AttachmentViewer.showAttachment();
|
||||||
}
|
}
|
||||||
PasteViewer.run();
|
PasteViewer.run();
|
||||||
|
|
||||||
@ -2925,14 +2932,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
const AttachmentViewer = (function () {
|
const AttachmentViewer = (function () {
|
||||||
const me = {};
|
const me = {};
|
||||||
|
|
||||||
let $attachmentLink,
|
let $attachmentPreview,
|
||||||
$attachmentPreview,
|
|
||||||
$attachment,
|
$attachment,
|
||||||
attachmentData,
|
attachmentsData = [],
|
||||||
file,
|
files,
|
||||||
$fileInput,
|
$fileInput,
|
||||||
$dragAndDropFileName,
|
$dragAndDropFileNames,
|
||||||
attachmentHasPreview = false,
|
|
||||||
$dropzone;
|
$dropzone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2974,26 +2979,28 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
me.setAttachment = function(attachmentData, fileName)
|
me.setAttachment = function(attachmentData, fileName)
|
||||||
{
|
{
|
||||||
// skip, if attachments got disabled
|
// skip, if attachments got disabled
|
||||||
if (!$attachmentLink || !$attachmentPreview) return;
|
if (!$attachment || !$attachmentPreview) return;
|
||||||
|
|
||||||
// data URI format: data:[<mimeType>][;base64],<data>
|
// data URI format: data:[<mimeType>][;base64],<data>
|
||||||
|
|
||||||
|
const template = Model.getTemplate('attachment');
|
||||||
|
const attachmentLink = template.find('a');
|
||||||
|
|
||||||
// position in data URI string of where data begins
|
// position in data URI string of where data begins
|
||||||
const base64Start = attachmentData.indexOf(',') + 1;
|
const base64Start = attachmentData.indexOf(',') + 1;
|
||||||
// position in data URI string of where mimeType ends
|
|
||||||
const mimeTypeEnd = attachmentData.indexOf(';');
|
|
||||||
|
|
||||||
// extract mimeType
|
const mimeType = me.getAttachmentMimeType(attachmentData);
|
||||||
const mimeType = attachmentData.substring(5, mimeTypeEnd);
|
|
||||||
// extract data and convert to binary
|
// extract data and convert to binary
|
||||||
const rawData = attachmentData.substring(base64Start);
|
const rawData = attachmentData.substring(base64Start);
|
||||||
const decodedData = rawData.length > 0 ? atob(rawData) : '';
|
const decodedData = rawData.length > 0 ? atob(rawData) : '';
|
||||||
|
|
||||||
let blobUrl = getBlobUrl(decodedData, mimeType);
|
let blobUrl = getBlobUrl(decodedData, mimeType);
|
||||||
$attachmentLink.attr('href', blobUrl);
|
attachmentLink.attr('href', blobUrl);
|
||||||
|
|
||||||
if (typeof fileName !== 'undefined') {
|
if (typeof fileName !== 'undefined') {
|
||||||
$attachmentLink.attr('download', fileName);
|
attachmentLink.attr('download', fileName);
|
||||||
|
template.append(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sanitize SVG preview
|
// sanitize SVG preview
|
||||||
@ -3008,6 +3015,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
blobUrl = getBlobUrl(sanitizedData, mimeType);
|
blobUrl = getBlobUrl(sanitizedData, mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template.removeClass('hidden');
|
||||||
|
$attachment.append(template);
|
||||||
|
|
||||||
me.handleBlobAttachmentPreview($attachmentPreview, blobUrl, mimeType);
|
me.handleBlobAttachmentPreview($attachmentPreview, blobUrl, mimeType);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3024,7 +3034,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
|
|
||||||
$attachment.removeClass('hidden');
|
$attachment.removeClass('hidden');
|
||||||
|
|
||||||
if (attachmentHasPreview) {
|
if (me.hasAttachmentPreview()) {
|
||||||
$attachmentPreview.removeClass('hidden');
|
$attachmentPreview.removeClass('hidden');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -3045,11 +3055,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
}
|
}
|
||||||
me.hideAttachment();
|
me.hideAttachment();
|
||||||
me.hideAttachmentPreview();
|
me.hideAttachmentPreview();
|
||||||
$attachmentLink.removeAttr('href');
|
$attachment.html('');
|
||||||
$attachmentLink.removeAttr('download');
|
|
||||||
$attachmentLink.off('click');
|
|
||||||
$attachmentPreview.html('');
|
$attachmentPreview.html('');
|
||||||
$dragAndDropFileName.text('');
|
$dragAndDropFileNames.html('');
|
||||||
|
|
||||||
AttachmentViewer.removeAttachmentData();
|
AttachmentViewer.removeAttachmentData();
|
||||||
};
|
};
|
||||||
@ -3064,8 +3072,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
*/
|
*/
|
||||||
me.removeAttachmentData = function()
|
me.removeAttachmentData = function()
|
||||||
{
|
{
|
||||||
file = undefined;
|
files = undefined;
|
||||||
attachmentData = undefined;
|
attachmentsData = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3076,9 +3084,21 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
*/
|
*/
|
||||||
me.clearDragAndDrop = function()
|
me.clearDragAndDrop = function()
|
||||||
{
|
{
|
||||||
$dragAndDropFileName.text('');
|
$dragAndDropFileNames.html('');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print file names added via drag & drop
|
||||||
|
*
|
||||||
|
* @name AttachmentViewer.printDragAndDropFileNames
|
||||||
|
* @private
|
||||||
|
* @function
|
||||||
|
* @param {array} fileNames
|
||||||
|
*/
|
||||||
|
function printDragAndDropFileNames(fileNames) {
|
||||||
|
$dragAndDropFileNames.html(fileNames.join("<br>"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hides the attachment
|
* hides the attachment
|
||||||
*
|
*
|
||||||
@ -3107,6 +3127,18 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if has any attachment preview
|
||||||
|
*
|
||||||
|
* @name AttachmentViewer.hasAttachmentPreview
|
||||||
|
* @function
|
||||||
|
* @return {JQuery}
|
||||||
|
*/
|
||||||
|
me.hasAttachmentPreview = function()
|
||||||
|
{
|
||||||
|
return $attachmentPreview.children().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* checks if there is an attachment displayed
|
* checks if there is an attachment displayed
|
||||||
*
|
*
|
||||||
@ -3118,8 +3150,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
if (!$attachment.length) {
|
if (!$attachment.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const link = $attachmentLink.prop('href');
|
return [...$attachment.children()].length > 0;
|
||||||
return (typeof link !== 'undefined' && link !== '');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3139,20 +3170,38 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the attachment
|
* return the attachments
|
||||||
*
|
*
|
||||||
* @name AttachmentViewer.getAttachment
|
* @name AttachmentViewer.getAttachments
|
||||||
* @function
|
* @function
|
||||||
* @returns {array}
|
* @returns {array}
|
||||||
*/
|
*/
|
||||||
me.getAttachment = function()
|
me.getAttachments = function()
|
||||||
{
|
{
|
||||||
return [
|
return [...$attachment.find('a')].map(link => (
|
||||||
$attachmentLink.prop('href'),
|
[
|
||||||
$attachmentLink.prop('download')
|
$(link).prop('href'),
|
||||||
];
|
$(link).prop('download')
|
||||||
|
]
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get attachment mime type
|
||||||
|
*
|
||||||
|
* @name AttachmentViewer.getAttachmentMimeType
|
||||||
|
* @function
|
||||||
|
* @param {string} attachmentData - Base64 string
|
||||||
|
*/
|
||||||
|
me.getAttachmentMimeType = function(attachmentData)
|
||||||
|
{
|
||||||
|
// position in data URI string of where mimeType ends
|
||||||
|
const mimeTypeEnd = attachmentData.indexOf(';');
|
||||||
|
|
||||||
|
// extract mimeType
|
||||||
|
return attachmentData.substring(5, mimeTypeEnd);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* moves the attachment link to another element
|
* moves the attachment link to another element
|
||||||
*
|
*
|
||||||
@ -3161,27 +3210,33 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
* @name AttachmentViewer.moveAttachmentTo
|
* @name AttachmentViewer.moveAttachmentTo
|
||||||
* @function
|
* @function
|
||||||
* @param {jQuery} $element - the wrapper/container element where this should be moved to
|
* @param {jQuery} $element - the wrapper/container element where this should be moved to
|
||||||
|
* @param {array} attachment - attachment data
|
||||||
* @param {string} label - the text to show (%s will be replaced with the file name), will automatically be translated
|
* @param {string} label - the text to show (%s will be replaced with the file name), will automatically be translated
|
||||||
*/
|
*/
|
||||||
me.moveAttachmentTo = function($element, label)
|
me.moveAttachmentTo = function($element, attachment, label)
|
||||||
{
|
{
|
||||||
|
const attachmentLink = $(document.createElement('a'))
|
||||||
|
.addClass('alert-link')
|
||||||
|
.prop('href', attachment[0])
|
||||||
|
.prop('download', attachment[1]);
|
||||||
|
|
||||||
// move elemement to new place
|
// move elemement to new place
|
||||||
$attachmentLink.appendTo($element);
|
attachmentLink.appendTo($element);
|
||||||
|
|
||||||
// update text - ensuring no HTML is inserted into the text node
|
// update text - ensuring no HTML is inserted into the text node
|
||||||
I18n._($attachmentLink, label, $attachmentLink.attr('download'));
|
I18n._(attachmentLink, label, attachment[1]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read file data as data URL using the FileReader API
|
* read files data as data URL using the FileReader API
|
||||||
*
|
*
|
||||||
* @name AttachmentViewer.readFileData
|
* @name AttachmentViewer.readFileData
|
||||||
* @private
|
* @private
|
||||||
* @function
|
* @function
|
||||||
* @param {object} loadedFile (optional) loaded file object
|
* @param {FileList[]} loadedFiles (optional) loaded files array
|
||||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsDataURL()}
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsDataURL()}
|
||||||
*/
|
*/
|
||||||
function readFileData(loadedFile) {
|
function readFileData(loadedFiles) {
|
||||||
if (typeof FileReader === 'undefined') {
|
if (typeof FileReader === 'undefined') {
|
||||||
// revert loading status…
|
// revert loading status…
|
||||||
me.hideAttachment();
|
me.hideAttachment();
|
||||||
@ -3190,28 +3245,35 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileReader = new FileReader();
|
if (loadedFiles === undefined) {
|
||||||
if (loadedFile === undefined) {
|
loadedFiles = [...$fileInput[0].files];
|
||||||
loadedFile = $fileInput[0].files[0];
|
me.clearDragAndDrop();
|
||||||
$dragAndDropFileName.text('');
|
|
||||||
} else {
|
} else {
|
||||||
$dragAndDropFileName.text(loadedFile.name);
|
const fileNames = loadedFiles.map((loadedFile => loadedFile.name));
|
||||||
|
printDragAndDropFileNames(fileNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof loadedFile !== 'undefined') {
|
if (typeof loadedFiles !== 'undefined') {
|
||||||
file = loadedFile;
|
files = loadedFiles;
|
||||||
fileReader.onload = function (event) {
|
loadedFiles.forEach(loadedFile => {
|
||||||
const dataURL = event.target.result;
|
const fileReader = new FileReader();
|
||||||
attachmentData = dataURL;
|
|
||||||
|
|
||||||
if (Editor.isPreview()) {
|
fileReader.onload = function (event) {
|
||||||
me.handleAttachmentPreview($attachmentPreview, dataURL);
|
const dataURL = event.target.result;
|
||||||
$attachmentPreview.removeClass('hidden');
|
if (dataURL) {
|
||||||
}
|
attachmentsData.push(dataURL);
|
||||||
|
}
|
||||||
|
|
||||||
TopNav.highlightFileupload();
|
if (Editor.isPreview()) {
|
||||||
};
|
me.handleAttachmentPreview($attachmentPreview, dataURL);
|
||||||
fileReader.readAsDataURL(loadedFile);
|
$attachmentPreview.removeClass('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
TopNav.highlightFileupload();
|
||||||
|
};
|
||||||
|
|
||||||
|
fileReader.readAsDataURL(loadedFile);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
me.removeAttachmentData();
|
me.removeAttachmentData();
|
||||||
}
|
}
|
||||||
@ -3227,16 +3289,17 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
* @argument {string} mime type
|
* @argument {string} mime type
|
||||||
*/
|
*/
|
||||||
me.handleBlobAttachmentPreview = function ($targetElement, blobUrl, mimeType) {
|
me.handleBlobAttachmentPreview = function ($targetElement, blobUrl, mimeType) {
|
||||||
if (blobUrl) {
|
const alreadyIncludesCurrentAttachment = $targetElement.find(`[src='${blobUrl}']`).length > 0;
|
||||||
attachmentHasPreview = true;
|
|
||||||
|
if (blobUrl && !alreadyIncludesCurrentAttachment) {
|
||||||
if (mimeType.match(/^image\//i)) {
|
if (mimeType.match(/^image\//i)) {
|
||||||
$targetElement.html(
|
$targetElement.append(
|
||||||
$(document.createElement('img'))
|
$(document.createElement('img'))
|
||||||
.attr('src', blobUrl)
|
.attr('src', blobUrl)
|
||||||
.attr('class', 'img-thumbnail')
|
.attr('class', 'img-thumbnail')
|
||||||
);
|
);
|
||||||
} else if (mimeType.match(/^video\//i)) {
|
} else if (mimeType.match(/^video\//i)) {
|
||||||
$targetElement.html(
|
$targetElement.append(
|
||||||
$(document.createElement('video'))
|
$(document.createElement('video'))
|
||||||
.attr('controls', 'true')
|
.attr('controls', 'true')
|
||||||
.attr('autoplay', 'true')
|
.attr('autoplay', 'true')
|
||||||
@ -3247,7 +3310,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
.attr('src', blobUrl))
|
.attr('src', blobUrl))
|
||||||
);
|
);
|
||||||
} else if (mimeType.match(/^audio\//i)) {
|
} else if (mimeType.match(/^audio\//i)) {
|
||||||
$targetElement.html(
|
$targetElement.append(
|
||||||
$(document.createElement('audio'))
|
$(document.createElement('audio'))
|
||||||
.attr('controls', 'true')
|
.attr('controls', 'true')
|
||||||
.attr('autoplay', 'true')
|
.attr('autoplay', 'true')
|
||||||
@ -3260,15 +3323,13 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
// Fallback for browsers, that don't support the vh unit
|
// Fallback for browsers, that don't support the vh unit
|
||||||
const clientHeight = $(window).height();
|
const clientHeight = $(window).height();
|
||||||
|
|
||||||
$targetElement.html(
|
$targetElement.append(
|
||||||
$(document.createElement('embed'))
|
$(document.createElement('embed'))
|
||||||
.attr('src', blobUrl)
|
.attr('src', blobUrl)
|
||||||
.attr('type', 'application/pdf')
|
.attr('type', 'application/pdf')
|
||||||
.attr('class', 'pdfPreview')
|
.attr('class', 'pdfPreview')
|
||||||
.css('height', clientHeight)
|
.css('height', clientHeight)
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
attachmentHasPreview = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -3301,14 +3362,14 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($fileInput) {
|
if ($fileInput) {
|
||||||
const file = evt.dataTransfer.files[0];
|
const files = [...evt.dataTransfer.files];
|
||||||
//Clear the file input:
|
//Clear the file input:
|
||||||
$fileInput.wrap('<form>').closest('form').get(0).reset();
|
$fileInput.wrap('<form>').closest('form').get(0).reset();
|
||||||
$fileInput.unwrap();
|
$fileInput.unwrap();
|
||||||
//Only works in Chrome:
|
//Only works in Chrome:
|
||||||
//fileInput[0].files = e.dataTransfer.files;
|
//fileInput[0].files = e.dataTransfer.files;
|
||||||
|
|
||||||
readFileData(file);
|
readFileData(files);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3362,23 +3423,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
/**
|
/**
|
||||||
* getter for attachment data
|
* getter for attachment data
|
||||||
*
|
*
|
||||||
* @name AttachmentViewer.getAttachmentData
|
* @name AttachmentViewer.getAttachmentsData
|
||||||
* @function
|
* @function
|
||||||
* @return {jQuery}
|
* @return {string[]}
|
||||||
*/
|
*/
|
||||||
me.getAttachmentData = function () {
|
me.getAttachmentsData = function () {
|
||||||
return attachmentData;
|
return attachmentsData;
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getter for attachment link
|
|
||||||
*
|
|
||||||
* @name AttachmentViewer.getAttachmentLink
|
|
||||||
* @function
|
|
||||||
* @return {jQuery}
|
|
||||||
*/
|
|
||||||
me.getAttachmentLink = function () {
|
|
||||||
return $attachmentLink;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3393,14 +3443,14 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getter for file data, returns the file contents
|
* getter for files data, returns the file list
|
||||||
*
|
*
|
||||||
* @name AttachmentViewer.getFile
|
* @name AttachmentViewer.getFiles
|
||||||
* @function
|
* @function
|
||||||
* @return {string}
|
* @return {FileList[]}
|
||||||
*/
|
*/
|
||||||
me.getFile = function () {
|
me.getFiles = function () {
|
||||||
return file;
|
return files;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3414,9 +3464,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
me.init = function()
|
me.init = function()
|
||||||
{
|
{
|
||||||
$attachment = $('#attachment');
|
$attachment = $('#attachment');
|
||||||
$dragAndDropFileName = $('#dragAndDropFileName');
|
$dragAndDropFileNames = $('#dragAndDropFileName');
|
||||||
$dropzone = $('#dropzone');
|
$dropzone = $('#dropzone');
|
||||||
$attachmentLink = $('#attachment a') || $('<a>');
|
|
||||||
if($attachment.length) {
|
if($attachment.length) {
|
||||||
$attachmentPreview = $('#attachmentPreview');
|
$attachmentPreview = $('#attachmentPreview');
|
||||||
|
|
||||||
@ -5135,7 +5184,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
const plainText = Editor.getText(),
|
const plainText = Editor.getText(),
|
||||||
format = PasteViewer.getFormat(),
|
format = PasteViewer.getFormat(),
|
||||||
// the methods may return different values if no files are attached (null, undefined or false)
|
// the methods may return different values if no files are attached (null, undefined or false)
|
||||||
files = TopNav.getFileList() || AttachmentViewer.getFile() || AttachmentViewer.hasAttachment();
|
files = TopNav.getFileList() || AttachmentViewer.getFiles() || AttachmentViewer.hasAttachment();
|
||||||
|
|
||||||
// do not send if there is no data
|
// do not send if there is no data
|
||||||
if (plainText.length === 0 && !files) {
|
if (plainText.length === 0 && !files) {
|
||||||
@ -5175,62 +5224,64 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
PasteViewer.setFormat(format);
|
PasteViewer.setFormat(format);
|
||||||
|
|
||||||
// prepare cypher message
|
// prepare cypher message
|
||||||
let file = AttachmentViewer.getAttachmentData(),
|
let attachmentsData = AttachmentViewer.getAttachmentsData(),
|
||||||
cipherMessage = {
|
cipherMessage = {
|
||||||
'paste': plainText
|
'paste': plainText
|
||||||
};
|
};
|
||||||
if (typeof file !== 'undefined' && file !== null) {
|
if (attachmentsData.length) {
|
||||||
cipherMessage['attachment'] = file;
|
cipherMessage['attachment'] = attachmentsData;
|
||||||
cipherMessage['attachment_name'] = AttachmentViewer.getFile().name;
|
cipherMessage['attachment_name'] = AttachmentViewer.getFiles().map((fileInfo => fileInfo.name));
|
||||||
} else if (AttachmentViewer.hasAttachment()) {
|
} else if (AttachmentViewer.hasAttachment()) {
|
||||||
// fall back to cloned part
|
// fall back to cloned part
|
||||||
let attachment = AttachmentViewer.getAttachment();
|
let attachments = AttachmentViewer.getAttachments();
|
||||||
cipherMessage['attachment'] = attachment[0];
|
cipherMessage['attachment'] = attachments.map(attachment => attachment[0]);
|
||||||
cipherMessage['attachment_name'] = attachment[1];
|
cipherMessage['attachment_name'] = attachments.map(attachment => attachment[1]);
|
||||||
|
|
||||||
// we need to retrieve data from blob if browser already parsed it in memory
|
cipherMessage['attachment'] = await Promise.all(cipherMessage['attachment'].map(async (attachment) => {
|
||||||
if (typeof attachment[0] === 'string' && attachment[0].startsWith('blob:')) {
|
// we need to retrieve data from blob if browser already parsed it in memory
|
||||||
Alert.showStatus(
|
if (typeof attachment === 'string' && attachment.startsWith('blob:')) {
|
||||||
[
|
Alert.showStatus(
|
||||||
'Retrieving cloned file \'%s\' from memory...',
|
[
|
||||||
attachment[1]
|
'Retrieving cloned file \'%s\' from memory...',
|
||||||
],
|
attachment[1]
|
||||||
'copy'
|
],
|
||||||
);
|
'copy'
|
||||||
try {
|
);
|
||||||
const blobData = await $.ajax({
|
try {
|
||||||
type: 'GET',
|
const blobData = await $.ajax({
|
||||||
url: `${attachment[0]}`,
|
type: 'GET',
|
||||||
processData: false,
|
url: `${attachment}`,
|
||||||
timeout: 10000,
|
processData: false,
|
||||||
xhrFields: {
|
timeout: 10000,
|
||||||
withCredentials: false,
|
xhrFields: {
|
||||||
responseType: 'blob'
|
withCredentials: false,
|
||||||
}
|
responseType: 'blob'
|
||||||
});
|
|
||||||
if (blobData instanceof window.Blob) {
|
|
||||||
const fileReading = new Promise(function(resolve, reject) {
|
|
||||||
const fileReader = new FileReader();
|
|
||||||
fileReader.onload = function (event) {
|
|
||||||
resolve(event.target.result);
|
|
||||||
};
|
|
||||||
fileReader.onerror = function (error) {
|
|
||||||
reject(error);
|
|
||||||
}
|
}
|
||||||
fileReader.readAsDataURL(blobData);
|
|
||||||
});
|
});
|
||||||
cipherMessage['attachment'] = await fileReading;
|
if (blobData instanceof window.Blob) {
|
||||||
} else {
|
const fileReading = new Promise(function(resolve, reject) {
|
||||||
const error = 'Cannot process attachment data.';
|
const fileReader = new FileReader();
|
||||||
Alert.showError(error);
|
fileReader.onload = function (event) {
|
||||||
throw new TypeError(error);
|
resolve(event.target.result);
|
||||||
|
};
|
||||||
|
fileReader.onerror = function (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
fileReader.readAsDataURL(blobData);
|
||||||
|
});
|
||||||
|
|
||||||
|
return await fileReading;
|
||||||
|
} else {
|
||||||
|
const error = 'Cannot process attachment data.';
|
||||||
|
Alert.showError(error);
|
||||||
|
throw new TypeError(error);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
Alert.showError('Cannot retrieve attachment.');
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
Alert.showError('Cannot retrieve attachment.');
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypt message
|
// encrypt message
|
||||||
@ -5325,7 +5376,15 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
// version 2 paste
|
// version 2 paste
|
||||||
const pasteMessage = JSON.parse(pastePlain);
|
const pasteMessage = JSON.parse(pastePlain);
|
||||||
if (pasteMessage.hasOwnProperty('attachment') && pasteMessage.hasOwnProperty('attachment_name')) {
|
if (pasteMessage.hasOwnProperty('attachment') && pasteMessage.hasOwnProperty('attachment_name')) {
|
||||||
AttachmentViewer.setAttachment(pasteMessage.attachment, pasteMessage.attachment_name);
|
if (Array.isArray(pasteMessage.attachment) && Array.isArray(pasteMessage.attachment_name)) {
|
||||||
|
pasteMessage.attachment.forEach((attachment, key) => {
|
||||||
|
const attachment_name = pasteMessage.attachment_name[key];
|
||||||
|
AttachmentViewer.setAttachment(attachment, attachment_name);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Continue to process attachment parameters as strings to ensure backward compatibility
|
||||||
|
AttachmentViewer.setAttachment(pasteMessage.attachment, pasteMessage.attachment_name);
|
||||||
|
}
|
||||||
AttachmentViewer.showAttachment();
|
AttachmentViewer.showAttachment();
|
||||||
}
|
}
|
||||||
pastePlain = pasteMessage.paste;
|
pastePlain = pasteMessage.paste;
|
||||||
@ -5808,10 +5867,14 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
history.pushState({type: 'clone'}, document.title, Helper.baseUri());
|
history.pushState({type: 'clone'}, document.title, Helper.baseUri());
|
||||||
|
|
||||||
if (AttachmentViewer.hasAttachment()) {
|
if (AttachmentViewer.hasAttachment()) {
|
||||||
AttachmentViewer.moveAttachmentTo(
|
const attachments = AttachmentViewer.getAttachments();
|
||||||
TopNav.getCustomAttachment(),
|
attachments.forEach(attachment => {
|
||||||
'Cloned: \'%s\''
|
AttachmentViewer.moveAttachmentTo(
|
||||||
);
|
TopNav.getCustomAttachment(),
|
||||||
|
attachment,
|
||||||
|
'Cloned: \'%s\''
|
||||||
|
);
|
||||||
|
});
|
||||||
TopNav.hideFileSelector();
|
TopNav.hideFileSelector();
|
||||||
AttachmentViewer.hideAttachment();
|
AttachmentViewer.hideAttachment();
|
||||||
// NOTE: it also looks nice without removing the attachment
|
// NOTE: it also looks nice without removing the attachment
|
||||||
@ -5819,12 +5882,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
|||||||
AttachmentViewer.hideAttachmentPreview();
|
AttachmentViewer.hideAttachmentPreview();
|
||||||
TopNav.showCustomAttachment();
|
TopNav.showCustomAttachment();
|
||||||
|
|
||||||
// show another status message to make the user aware that the
|
// show another status messages to make the user aware that the
|
||||||
// file was cloned too!
|
// files were cloned too!
|
||||||
Alert.showStatus(
|
Alert.showStatus(
|
||||||
[
|
[
|
||||||
'The cloned file \'%s\' was attached to this paste.',
|
'The cloned file \'%s\' was attached to this paste.',
|
||||||
AttachmentViewer.getAttachment()[1]
|
attachments.map(attachment => attachment[1]).join(', '),
|
||||||
],
|
],
|
||||||
'copy'
|
'copy'
|
||||||
);
|
);
|
||||||
|
@ -27,11 +27,14 @@ describe('AttachmentViewer', function () {
|
|||||||
prefix = prefix.replace(/%(s|d)/g, '%%');
|
prefix = prefix.replace(/%(s|d)/g, '%%');
|
||||||
postfix = postfix.replace(/%(s|d)/g, '%%');
|
postfix = postfix.replace(/%(s|d)/g, '%%');
|
||||||
$('body').html(
|
$('body').html(
|
||||||
'<div id="attachment" role="alert" class="hidden alert ' +
|
'<div id="attachmentPreview" class="col-md-12 text-center hidden"></div>' +
|
||||||
'alert-info"><span class="glyphicon glyphicon-download-' +
|
'<div id="attachment" class="hidden"></div>' +
|
||||||
'alt" aria-hidden="true"></span> <a class="alert-link">' +
|
'<div id="templates">' +
|
||||||
'Download attachment</a></div><div id="attachmentPrevie' +
|
'<div id="attachmenttemplate" role="alert" class="attachment hidden alert alert-info">' +
|
||||||
'w" class="hidden"></div>'
|
'<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>' +
|
||||||
|
'<a class="alert-link">Download attachment</a>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>'
|
||||||
);
|
);
|
||||||
// mock createObjectURL for jsDOM
|
// mock createObjectURL for jsDOM
|
||||||
if (typeof window.URL.createObjectURL === 'undefined') {
|
if (typeof window.URL.createObjectURL === 'undefined') {
|
||||||
@ -44,9 +47,12 @@ describe('AttachmentViewer', function () {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
$.PrivateBin.AttachmentViewer.init();
|
$.PrivateBin.AttachmentViewer.init();
|
||||||
|
$.PrivateBin.Model.init();
|
||||||
results.push(
|
results.push(
|
||||||
!$.PrivateBin.AttachmentViewer.hasAttachment() &&
|
!$.PrivateBin.AttachmentViewer.hasAttachment() &&
|
||||||
$('#attachment').hasClass('hidden') &&
|
$('#attachment').hasClass('hidden') &&
|
||||||
|
$('#attachment').children().length === 0 &&
|
||||||
|
$('#attachmenttemplate').hasClass('hidden') &&
|
||||||
$('#attachmentPreview').hasClass('hidden')
|
$('#attachmentPreview').hasClass('hidden')
|
||||||
);
|
);
|
||||||
global.atob = common.atob;
|
global.atob = common.atob;
|
||||||
@ -55,19 +61,21 @@ describe('AttachmentViewer', function () {
|
|||||||
} else {
|
} else {
|
||||||
$.PrivateBin.AttachmentViewer.setAttachment(data);
|
$.PrivateBin.AttachmentViewer.setAttachment(data);
|
||||||
}
|
}
|
||||||
// beyond this point we will get the blob URL instead of the data
|
// // beyond this point we will get the blob URL instead of the data
|
||||||
data = window.URL.createObjectURL(data);
|
data = window.URL.createObjectURL(data);
|
||||||
const attachment = $.PrivateBin.AttachmentViewer.getAttachment();
|
const attachment = $.PrivateBin.AttachmentViewer.getAttachments();
|
||||||
results.push(
|
results.push(
|
||||||
$.PrivateBin.AttachmentViewer.hasAttachment() &&
|
$.PrivateBin.AttachmentViewer.hasAttachment() &&
|
||||||
$('#attachment').hasClass('hidden') &&
|
$('#attachment').hasClass('hidden') &&
|
||||||
|
$('#attachment').children().length > 0 &&
|
||||||
$('#attachmentPreview').hasClass('hidden') &&
|
$('#attachmentPreview').hasClass('hidden') &&
|
||||||
attachment[0] === data &&
|
attachment[0][0] === data &&
|
||||||
attachment[1] === filename
|
attachment[0][1] === filename
|
||||||
);
|
);
|
||||||
$.PrivateBin.AttachmentViewer.showAttachment();
|
$.PrivateBin.AttachmentViewer.showAttachment();
|
||||||
results.push(
|
results.push(
|
||||||
!$('#attachment').hasClass('hidden') &&
|
!$('#attachment').hasClass('hidden') &&
|
||||||
|
$('#attachment').children().length > 0 &&
|
||||||
(previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
|
(previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
|
||||||
);
|
);
|
||||||
$.PrivateBin.AttachmentViewer.hideAttachment();
|
$.PrivateBin.AttachmentViewer.hideAttachment();
|
||||||
@ -85,7 +93,7 @@ describe('AttachmentViewer', function () {
|
|||||||
(previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
|
(previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
|
||||||
);
|
);
|
||||||
let element = $('<div>');
|
let element = $('<div>');
|
||||||
$.PrivateBin.AttachmentViewer.moveAttachmentTo(element, prefix + '%s' + postfix);
|
$.PrivateBin.AttachmentViewer.moveAttachmentTo(element, attachment[0], prefix + '%s' + postfix);
|
||||||
// messageIDs with links get a relaxed treatment
|
// messageIDs with links get a relaxed treatment
|
||||||
if (prefix.indexOf('<a') === -1 && postfix.indexOf('<a') === -1) {
|
if (prefix.indexOf('<a') === -1 && postfix.indexOf('<a') === -1) {
|
||||||
result = $('<textarea>').text((prefix + filename + postfix)).text();
|
result = $('<textarea>').text((prefix + filename + postfix)).text();
|
||||||
@ -99,16 +107,17 @@ describe('AttachmentViewer', function () {
|
|||||||
}
|
}
|
||||||
if (filename.length) {
|
if (filename.length) {
|
||||||
results.push(
|
results.push(
|
||||||
element.children()[0].href === data &&
|
element.find('a')[0].href === data &&
|
||||||
element.children()[0].getAttribute('download') === filename &&
|
element.find('a')[0].getAttribute('download') === filename &&
|
||||||
element.children()[0].text === result
|
element.find('a')[0].text === result
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
results.push(element.children()[0].href === data);
|
results.push(element.find('a')[0].href === data);
|
||||||
}
|
}
|
||||||
$.PrivateBin.AttachmentViewer.removeAttachment();
|
$.PrivateBin.AttachmentViewer.removeAttachment();
|
||||||
results.push(
|
results.push(
|
||||||
$('#attachment').hasClass('hidden') &&
|
$('#attachment').hasClass('hidden') &&
|
||||||
|
$('#attachment').children().length === 0 &&
|
||||||
$('#attachmentPreview').hasClass('hidden')
|
$('#attachmentPreview').hasClass('hidden')
|
||||||
);
|
);
|
||||||
clean();
|
clean();
|
||||||
|
@ -119,7 +119,7 @@ class Configuration
|
|||||||
'js/kjua-0.9.0.js' => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==',
|
'js/kjua-0.9.0.js' => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==',
|
||||||
'js/legacy.js' => 'sha512-UxW/TOZKon83n6dk/09GsYKIyeO5LeBHokxyIq+r7KFS5KMBeIB/EM7NrkVYIezwZBaovnyNtY2d9tKFicRlXg==',
|
'js/legacy.js' => 'sha512-UxW/TOZKon83n6dk/09GsYKIyeO5LeBHokxyIq+r7KFS5KMBeIB/EM7NrkVYIezwZBaovnyNtY2d9tKFicRlXg==',
|
||||||
'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
|
'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
|
||||||
'js/privatebin.js' => 'sha512-QkOUM8rg4MI60YRwHqWmayBzCdf/e3XnbHtrX17h2nn0EcyOQNhtSq8a0dXR1hoQFHFfF+9PiT73nZ6qoogjQA==',
|
'js/privatebin.js' => 'm6RrsOsz4RgIWXDzgRghQDx6aegFCpkpqURwhfXwE/rNWhe/1rPJaLR+FXII82iTWo0n9JCzSbqrDqkYVPI50w==',
|
||||||
'js/purify-3.2.5.js' => 'sha512-eLlLLL/zYuf5JuG0x4WQm687MToqOGP9cDQHIdmOy1ZpjiY4J48BBcOM7DtZheKk1UogW920+9RslWYB4KGuuA==',
|
'js/purify-3.2.5.js' => 'sha512-eLlLLL/zYuf5JuG0x4WQm687MToqOGP9cDQHIdmOy1ZpjiY4J48BBcOM7DtZheKk1UogW920+9RslWYB4KGuuA==',
|
||||||
'js/rawinflate-0.3.js' => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==',
|
'js/rawinflate-0.3.js' => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==',
|
||||||
'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
|
'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
|
||||||
|
@ -386,7 +386,7 @@ if ($FILEUPLOAD) :
|
|||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li id="filewrap">
|
<li id="filewrap">
|
||||||
<div>
|
<div>
|
||||||
<input type="file" id="file" name="file" />
|
<input type="file" id="file" name="file" multiple />
|
||||||
</div>
|
</div>
|
||||||
<div id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></div>
|
<div id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></div>
|
||||||
</li>
|
</li>
|
||||||
@ -505,10 +505,7 @@ endif;
|
|||||||
<?php
|
<?php
|
||||||
if ($FILEUPLOAD) :
|
if ($FILEUPLOAD) :
|
||||||
?>
|
?>
|
||||||
<div id="attachment" role="alert" class="hidden alert alert-info">
|
<div id="attachment" class="hidden"></div>
|
||||||
<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
|
|
||||||
<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
|
|
||||||
</div>
|
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
@ -656,9 +653,6 @@ endif;
|
|||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</main>
|
</main>
|
||||||
<?php
|
|
||||||
if ($DISCUSSION) :
|
|
||||||
?>
|
|
||||||
<div id="serverdata" class="hidden" aria-hidden="true">
|
<div id="serverdata" class="hidden" aria-hidden="true">
|
||||||
<div id="templates">
|
<div id="templates">
|
||||||
<article id="commenttemplate" class="comment">
|
<article id="commenttemplate" class="comment">
|
||||||
@ -680,12 +674,13 @@ if ($DISCUSSION) :
|
|||||||
</div>
|
</div>
|
||||||
<button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button>
|
<button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="attachmenttemplate" role="alert" class="attachment hidden alert alert-info">
|
||||||
|
<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
|
||||||
|
<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
endif;
|
|
||||||
?>
|
|
||||||
<?php
|
|
||||||
if ($FILEUPLOAD) :
|
if ($FILEUPLOAD) :
|
||||||
?>
|
?>
|
||||||
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
||||||
|
@ -261,11 +261,11 @@ if ($FILEUPLOAD) :
|
|||||||
<ul class="dropdown-menu px-2">
|
<ul class="dropdown-menu px-2">
|
||||||
<li id="filewrap">
|
<li id="filewrap">
|
||||||
<div>
|
<div>
|
||||||
<input type="file" id="file" name="file" class="form-control" />
|
<input type="file" id="file" name="file" class="form-control" multiple />
|
||||||
</div>
|
</div>
|
||||||
<div id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></div>
|
<div id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></div>
|
||||||
</li>
|
</li>
|
||||||
<li id="customattachment" class="hidden"></li>
|
<li id="customattachment" class="hidden d-flex flex-column px-3"></li>
|
||||||
<li>
|
<li>
|
||||||
<a id="fileremovebutton" href="#" class="dropdown-item">
|
<a id="fileremovebutton" href="#" class="dropdown-item">
|
||||||
<?php echo I18n::_('Remove attachment'), PHP_EOL; ?>
|
<?php echo I18n::_('Remove attachment'), PHP_EOL; ?>
|
||||||
@ -370,10 +370,7 @@ endif;
|
|||||||
<?php
|
<?php
|
||||||
if ($FILEUPLOAD) :
|
if ($FILEUPLOAD) :
|
||||||
?>
|
?>
|
||||||
<div id="attachment" role="alert" class="hidden alert alert-info">
|
<div id="attachment" class="hidden"></div>
|
||||||
<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#download" /></svg>
|
|
||||||
<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
|
|
||||||
</div>
|
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
@ -514,9 +511,6 @@ endif;
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
<?php
|
|
||||||
if ($DISCUSSION) :
|
|
||||||
?>
|
|
||||||
<div id="serverdata" class="hidden" aria-hidden="true">
|
<div id="serverdata" class="hidden" aria-hidden="true">
|
||||||
<div id="templates">
|
<div id="templates">
|
||||||
<article id="commenttemplate" class="comment px-2 pb-3">
|
<article id="commenttemplate" class="comment px-2 pb-3">
|
||||||
@ -538,12 +532,13 @@ if ($DISCUSSION) :
|
|||||||
</div>
|
</div>
|
||||||
<button id="replybutton" class="btn btn-secondary btn-sm"><?php echo I18n::_('Post comment'); ?></button>
|
<button id="replybutton" class="btn btn-secondary btn-sm"><?php echo I18n::_('Post comment'); ?></button>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="attachmenttemplate" role="alert" class="hidden alert alert-info">
|
||||||
|
<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#download" /></svg>
|
||||||
|
<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
endif;
|
|
||||||
?>
|
|
||||||
<?php
|
|
||||||
if ($FILEUPLOAD) :
|
if ($FILEUPLOAD) :
|
||||||
?>
|
?>
|
||||||
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
||||||
|
13
tpl/page.php
13
tpl/page.php
@ -265,10 +265,10 @@ endif;
|
|||||||
<?php
|
<?php
|
||||||
if ($FILEUPLOAD):
|
if ($FILEUPLOAD):
|
||||||
?>
|
?>
|
||||||
<div id="attachment" class="hidden"><a><?php echo I18n::_('Download attachment'); ?></a></div>
|
<div id="attachment" class="hidden"></div>
|
||||||
<div id="attach" class="hidden">
|
<div id="attach" class="hidden">
|
||||||
<span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
|
<span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
|
||||||
<span id="filewrap"><?php echo I18n::_('Attach a file'); ?>: <input type="file" id="file" name="file" /></span>
|
<span id="filewrap"><?php echo I18n::_('Attach a file'); ?>: <input type="file" id="file" name="file" multiple /></span>
|
||||||
<span id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></span>
|
<span id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></span>
|
||||||
<button id="fileremovebutton"><?php echo I18n::_('Remove attachment'); ?></button>
|
<button id="fileremovebutton"><?php echo I18n::_('Remove attachment'); ?></button>
|
||||||
</div>
|
</div>
|
||||||
@ -297,9 +297,6 @@ endif;
|
|||||||
<div id="commentcontainer"></div>
|
<div id="commentcontainer"></div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<?php
|
|
||||||
if ($DISCUSSION):
|
|
||||||
?>
|
|
||||||
<div id="serverdata" class="hidden" aria-hidden="true">
|
<div id="serverdata" class="hidden" aria-hidden="true">
|
||||||
<div id="templates">
|
<div id="templates">
|
||||||
<article id="commenttemplate" class="comment">
|
<article id="commenttemplate" class="comment">
|
||||||
@ -321,12 +318,12 @@ if ($DISCUSSION):
|
|||||||
</div>
|
</div>
|
||||||
<button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button>
|
<button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="attachmenttemplate" class="attachment">
|
||||||
|
<a><?php echo I18n::_('Download attachment'); ?></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
endif;
|
|
||||||
?>
|
|
||||||
<?php
|
|
||||||
if ($FILEUPLOAD):
|
if ($FILEUPLOAD):
|
||||||
?>
|
?>
|
||||||
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user