feat: add upload helper module for drag&drop, paste, closes #6388

fix chat input not getting focused
isekai-main
Barış Soner Uşaklı 3 years ago
parent 6ba25557b3
commit cf5c096806

@ -173,3 +173,12 @@
padding: 1rem;
}
}
.imagedrop {
position: absolute;
text-align: center;
font-size: 24px;
color: @gray-light;
width: 100%;
display: none;
}

@ -14,11 +14,12 @@ define('forum/chats', [
'alerts',
'chat',
'api',
'uploadHelpers',
], function (
components, translator, mousetrap,
recentChats, search, messages,
autocomplete, hooks, bootbox, alerts, chatModule,
api
api, uploadHelpers
) {
const Chats = {
initialised: false,
@ -69,12 +70,35 @@ define('forum/chats', [
Chats.addCharactersLeftHandler($('[component="chat/main-wrapper"]'));
Chats.addIPHandler($('[component="chat/main-wrapper"]'));
Chats.createAutoComplete($('[component="chat/input"]'));
Chats.addUploadHandler({
dragDropAreaEl: $('.chats-full'),
pasteEl: $('[component="chat/input"]'),
uploadFormEl: $('[component="chat/upload"]'),
inputEl: $('[component="chat/input"]'),
});
$('[data-action="close"]').on('click', function () {
Chats.switchChat();
});
};
Chats.addUploadHandler = function (options) {
uploadHelpers.init({
dragDropAreaEl: options.dragDropAreaEl,
pasteEl: options.pasteEl,
uploadFormEl: options.uploadFormEl,
route: '/api/post/upload', // using same route as post uploads
callback: function (uploads) {
const inputEl = options.inputEl;
let text = inputEl.val();
uploads.forEach((upload) => {
text = text + (text ? '\n' : '') + (upload.isImage ? '!' : '') + `[${upload.filename}](${upload.url})`;
});
inputEl.val(text);
},
});
};
Chats.addIPHandler = function (container) {
container.on('click', '.chat-ip-button', function () {
const ipEl = $(this).parent();

@ -89,8 +89,8 @@ define('alerts', ['translator', 'components', 'hooks'], function (translator, co
}
function updateAlert(alert, params) {
alert.find('strong').html(params.title);
alert.find('p').html(params.message);
alert.find('strong').translateHtml(params.title);
alert.find('p').translateHtml(params.message);
alert.attr('class', 'alert alert-dismissable alert-' + params.type + ' clearfix');
clearTimeout(parseInt(alert.attr('timeoutId'), 10));
@ -98,12 +98,7 @@ define('alerts', ['translator', 'components', 'hooks'], function (translator, co
startTimeout(alert, params);
}
alert.children().fadeOut(100);
translator.translate(alert.html(), function (translatedHTML) {
alert.children().fadeIn(100);
alert.html(translatedHTML);
hooks.fire('action:alert.update', { alert, params });
});
// Handle changes in the clickfn
alert.off('click').removeClass('pointer');

@ -196,7 +196,9 @@ define('chat', [
module.createModal = function (data, callback) {
callback = callback || function () {};
require(['scrollStop', 'forum/chats', 'forum/chats/messages'], function (scrollStop, Chats, ChatsMessages) {
require([
'scrollStop', 'forum/chats', 'forum/chats/messages',
], function (scrollStop, Chats, ChatsMessages) {
app.parseAndTranslate('chat', data, function (chatModal) {
if (module.modalExists(data.roomId)) {
return callback(module.getModal(data.roomId));
@ -233,7 +235,7 @@ define('chat', [
taskbar.updateActive(uuid);
},
stop: function () {
chatModal.find('#chat-message-input').focus();
module.focusInput(chatModal);
},
distance: 10,
handle: '.modal-header',
@ -297,6 +299,14 @@ define('chat', [
Chats.addCharactersLeftHandler(chatModal);
Chats.addIPHandler(chatModal);
Chats.addUploadHandler({
dragDropAreaEl: chatModal.find('.modal-content'),
pasteEl: chatModal,
uploadFormEl: chatModal.find('[component="chat/upload"]'),
inputEl: chatModal.find('[component="chat/input"]'),
});
ChatsMessages.addSocketListeners();
taskbar.push('chat', chatModal.attr('data-uuid'), {
@ -318,7 +328,9 @@ define('chat', [
};
module.focusInput = function (chatModal) {
setTimeout(function () {
chatModal.find('[component="chat/input"]').focus();
}, 20);
};
module.close = function (chatModal) {

@ -0,0 +1,199 @@
'use strict';
define('uploadHelpers', ['alerts'], function (alerts) {
const uploadHelpers = {};
uploadHelpers.init = function (options) {
const formEl = options.uploadFormEl;
if (!formEl.length) {
return;
}
formEl.attr('action', config.relative_path + options.route);
if (options.dragDropAreaEl) {
uploadHelpers.handleDragDrop({
container: options.dragDropAreaEl,
callback: function (upload) {
uploadHelpers.ajaxSubmit({
uploadForm: formEl,
upload: upload,
callback: options.callback,
});
},
});
}
if (options.pasteEl) {
uploadHelpers.handlePaste({
container: options.pasteEl,
callback: function (upload) {
uploadHelpers.ajaxSubmit({
uploadForm: formEl,
upload: upload,
callback: options.callback,
});
},
});
}
};
uploadHelpers.handleDragDrop = function (options) {
let draggingDocument = false;
const postContainer = options.container;
const drop = options.container.find('.imagedrop');
postContainer.on('dragenter', function onDragEnter() {
if (draggingDocument) {
return;
}
drop.css('top', '0px');
drop.css('height', postContainer.height() + 'px');
drop.css('line-height', postContainer.height() + 'px');
drop.show();
drop.on('dragleave', function () {
drop.hide();
drop.off('dragleave');
});
});
drop.on('drop', function onDragDrop(e) {
e.preventDefault();
const files = e.originalEvent.dataTransfer.files;
if (files.length) {
let formData;
if (window.FormData) {
formData = new FormData();
for (var i = 0; i < files.length; ++i) {
formData.append('files[]', files[i], files[i].name);
}
}
options.callback({
files: files,
formData: formData,
});
}
drop.hide();
return false;
});
function cancel(e) {
e.preventDefault();
return false;
}
$(document)
.off('dragstart')
.on('dragstart', function () {
draggingDocument = true;
})
.off('dragend')
.on('dragend', function () {
draggingDocument = false;
});
drop.on('dragover', cancel);
drop.on('dragenter', cancel);
};
uploadHelpers.handlePaste = function (options) {
const container = options.container;
container.on('paste', function (event) {
const items = (event.clipboardData || event.originalEvent.clipboardData || {}).items;
const files = [];
const fileNames = [];
let formData = null;
if (window.FormData) {
formData = new FormData();
}
[].forEach.call(items, function (item) {
const file = item.getAsFile();
if (file) {
const fileName = utils.generateUUID() + '-' + file.name;
if (formData) {
formData.append('files[]', file, fileName);
}
files.push(file);
fileNames.push(fileName);
}
});
if (files.length) {
options.callback({
files: files,
fileNames: fileNames,
formData: formData,
});
}
});
};
uploadHelpers.ajaxSubmit = function (options) {
const files = [...options.upload.files];
for (let i = 0; i < files.length; ++i) {
const isImage = files[i].type.match(/image./);
if ((isImage && !app.user.privileges['upload:post:image']) || (!isImage && !app.user.privileges['upload:post:file'])) {
return alerts.error('[[error:no-privileges]]');
}
if (files[i].size > parseInt(config.maximumFileSize, 10) * 1024) {
options.uploadForm[0].reset();
return alerts.error('[[error:file-too-big, ' + config.maximumFileSize + ']]');
}
}
const alert_id = Date.now();
options.uploadForm.off('submit').on('submit', function () {
$(this).ajaxSubmit({
headers: {
'x-csrf-token': config.csrf_token,
},
resetForm: true,
clearForm: true,
formData: options.upload.formData,
error: function (xhr) {
let errorMsg = (xhr.responseJSON &&
(xhr.responseJSON.error || (xhr.responseJSON.status && xhr.responseJSON.status.message))) ||
'[[error:parse-error]]';
if (xhr && xhr.status === 413) {
errorMsg = xhr.statusText || 'Request Entity Too Large';
}
alerts.error(errorMsg);
alerts.remove(alert_id);
},
uploadProgress: function (event, position, total, percent) {
alerts.alert({
alert_id: alert_id,
message: '[[modules:composer.uploading, ' + percent + '%]]',
});
},
success: function (res) {
const uploads = res.response.images;
if (uploads && uploads.length) {
for (var i = 0; i < uploads.length; ++i) {
uploads[i].filename = files[i].name;
uploads[i].isImage = /image./.test(files[i].type);
}
}
options.callback(uploads);
},
complete: function () {
options.uploadForm[0].reset();
setTimeout(alerts.remove, 100, alert_id);
},
});
return false;
});
options.uploadForm.submit();
};
return uploadHelpers;
});
Loading…
Cancel
Save