mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
feat: #7096, improve chat editing
use a new template for editing chats, remove the data-mid on the chat inputEl
This commit is contained in:
@@ -100,10 +100,10 @@
|
||||
"nodebb-plugin-ntfy": "1.0.15",
|
||||
"nodebb-plugin-spam-be-gone": "2.0.6",
|
||||
"nodebb-rewards-essentials": "0.2.3",
|
||||
"nodebb-theme-harmony": "1.0.4",
|
||||
"nodebb-theme-harmony": "1.0.5",
|
||||
"nodebb-theme-lavender": "7.0.9",
|
||||
"nodebb-theme-peace": "2.0.19",
|
||||
"nodebb-theme-persona": "13.0.56",
|
||||
"nodebb-theme-peace": "2.0.20",
|
||||
"nodebb-theme-persona": "13.0.57",
|
||||
"nodebb-widget-essentials": "7.0.11",
|
||||
"nodemailer": "6.9.1",
|
||||
"nprogress": "0.2.0",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
"save_changes": "Save Changes",
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
"close": "Close",
|
||||
|
||||
"pagination": "Pagination",
|
||||
|
||||
@@ -379,7 +379,7 @@ define('forum/chats', [
|
||||
});
|
||||
};
|
||||
|
||||
Chats.createAutoComplete = function (roomId, element) {
|
||||
Chats.createAutoComplete = function (roomId, element, options = {}) {
|
||||
if (!element.length) {
|
||||
return;
|
||||
}
|
||||
@@ -395,12 +395,17 @@ define('forum/chats', [
|
||||
},
|
||||
placement: 'top',
|
||||
className: `chat-autocomplete-dropdown-${roomId} dropdown-menu textcomplete-dropdown`,
|
||||
...options,
|
||||
},
|
||||
};
|
||||
|
||||
$(window).trigger('chat:autocomplete:init', data);
|
||||
if (data.strategies.length) {
|
||||
Chats.activeAutocomplete[roomId] = autocomplete.setup(data);
|
||||
const autocompleteEl = autocomplete.setup(data);
|
||||
if (roomId) {
|
||||
Chats.activeAutocomplete[roomId] = autocompleteEl;
|
||||
}
|
||||
return autocompleteEl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,22 +9,19 @@ define('forum/chats/messages', [
|
||||
|
||||
messages.sendMessage = async function (roomId, inputEl) {
|
||||
let message = inputEl.val();
|
||||
let mid = inputEl.attr('data-mid');
|
||||
|
||||
if (!message.trim().length) {
|
||||
return;
|
||||
}
|
||||
const chatContent = inputEl.parents(`[component="chat/messages"][data-roomid="${roomId}"]`);
|
||||
inputEl.val('').trigger('input');
|
||||
inputEl.removeAttr('data-mid');
|
||||
|
||||
messages.updateRemainingLength(inputEl.parent());
|
||||
messages.updateTextAreaHeight(chatContent);
|
||||
const payload = { roomId, message, mid };
|
||||
({ roomId, message, mid } = await hooks.fire('filter:chat.send', payload));
|
||||
const payload = { roomId, message };
|
||||
({ roomId, message } = await hooks.fire('filter:chat.send', payload));
|
||||
|
||||
if (!mid) {
|
||||
api.post(`/chats/${roomId}`, { message }).then(() => {
|
||||
hooks.fire('action:chat.sent', { roomId, message, mid });
|
||||
hooks.fire('action:chat.sent', { roomId, message });
|
||||
}).catch((err) => {
|
||||
inputEl.val(message).trigger('input');
|
||||
messages.updateRemainingLength(inputEl.parent());
|
||||
@@ -40,16 +37,6 @@ define('forum/chats/messages', [
|
||||
timeout: 10000,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
api.put(`/chats/${roomId}/messages/${mid}`, { message }).then(() => {
|
||||
hooks.fire('action:chat.edited', { roomId, message, mid });
|
||||
}).catch((err) => {
|
||||
inputEl.val(message).trigger('input');
|
||||
inputEl.attr('data-mid', mid);
|
||||
messages.updateRemainingLength(inputEl.parent());
|
||||
return alerts.error(err);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
messages.updateRemainingLength = function (parent) {
|
||||
@@ -76,6 +63,15 @@ define('forum/chats/messages', [
|
||||
});
|
||||
};
|
||||
|
||||
function autoresizeTextArea(textarea) {
|
||||
const scrollHeight = textarea.prop('scrollHeight');
|
||||
textarea.css({ height: scrollHeight + 'px' });
|
||||
textarea.on('input', function () {
|
||||
textarea.css({ height: 0 });
|
||||
textarea.css({ height: textarea.prop('scrollHeight') + 'px' });
|
||||
});
|
||||
}
|
||||
|
||||
messages.appendChatMessage = function (chatContentEl, data) {
|
||||
const lastSpeaker = parseInt(chatContentEl.find('.chat-message').last().attr('data-uid'), 10);
|
||||
const lasttimestamp = parseInt(chatContentEl.find('.chat-message').last().attr('data-timestamp'), 10);
|
||||
@@ -145,24 +141,63 @@ define('forum/chats/messages', [
|
||||
.toggleClass('hidden', isAtBottom);
|
||||
};
|
||||
|
||||
messages.prepEdit = function (inputEl, messageId, roomId) {
|
||||
socket.emit('modules.chats.getRaw', { mid: messageId, roomId: roomId }, function (err, raw) {
|
||||
if (err) {
|
||||
return alerts.error(err);
|
||||
messages.prepEdit = async function (inputEl, mid, roomId) {
|
||||
const raw = await socket.emit('modules.chats.getRaw', { mid: mid, roomId: roomId });
|
||||
const editEl = await app.parseAndTranslate('partials/chats/edit-message', {
|
||||
rawContent: raw,
|
||||
});
|
||||
const messageBody = $(`[data-roomid="${roomId}"] [data-mid="${mid}"] [component="chat/message/body"]`);
|
||||
const messageControls = $(`[data-roomid="${roomId}"] [data-mid="${mid}"] [component="chat/message/controls"]`);
|
||||
const chatContent = messageBody.parents('.chat-content');
|
||||
|
||||
messageBody.addClass('hidden');
|
||||
messageControls.addClass('hidden');
|
||||
editEl.insertAfter(messageBody);
|
||||
|
||||
const textarea = editEl.find('textarea');
|
||||
|
||||
textarea.focus().putCursorAtEnd();
|
||||
autoresizeTextArea(textarea);
|
||||
|
||||
if (messages.isAtBottom(chatContent)) {
|
||||
messages.scrollToBottom(chatContent);
|
||||
}
|
||||
// Populate the input field with the raw message content
|
||||
if (inputEl.val().length === 0) {
|
||||
// By setting the `data-mid` attribute, I tell the chat code that I am editing a
|
||||
// message, instead of posting a new one.
|
||||
inputEl.attr('data-mid', messageId).addClass('editing');
|
||||
inputEl.val(raw).trigger('input').focus();
|
||||
|
||||
const chats = await app.require('forum/chats');
|
||||
const autoCompleteEl = chats.createAutoComplete(0, textarea, {
|
||||
placement: 'bottom',
|
||||
});
|
||||
|
||||
function finishEdit() {
|
||||
messageBody.removeClass('hidden');
|
||||
messageControls.removeClass('hidden');
|
||||
editEl.remove();
|
||||
if (autoCompleteEl) {
|
||||
autoCompleteEl.destroy();
|
||||
}
|
||||
}
|
||||
editEl.find('[data-action="cancel"]').on('click', finishEdit);
|
||||
|
||||
editEl.find('[data-action="save"]').on('click', function () {
|
||||
const message = textarea.val();
|
||||
if (!message.trim().length) {
|
||||
return;
|
||||
}
|
||||
api.put(`/chats/${roomId}/messages/${mid}`, { message }).then(() => {
|
||||
finishEdit();
|
||||
hooks.fire('action:chat.edited', { roomId, message, mid });
|
||||
}).catch((err) => {
|
||||
textarea.val(message).trigger('input');
|
||||
alerts.error(err);
|
||||
});
|
||||
});
|
||||
|
||||
hooks.fire('action:chat.prepEdit', {
|
||||
inputEl: inputEl,
|
||||
messageId: messageId,
|
||||
messageId: mid,
|
||||
roomId: roomId,
|
||||
});
|
||||
}
|
||||
editEl: editEl,
|
||||
messageBody: messageBody,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
7
src/views/partials/chats/edit-message.tpl
Normal file
7
src/views/partials/chats/edit-message.tpl
Normal file
@@ -0,0 +1,7 @@
|
||||
<div class="d-flex flex-column gap-1 mb-1">
|
||||
<textarea class="form-control w-100 p-2 overflow-hidden" style="height: 32px; max-height: 30vh; resize: none;">{rawContent}</textarea>
|
||||
<div class="align-self-end d-flex gap-2 bottom-0 end-0">
|
||||
<button class="btn btn-sm btn-outline-secondary" data-action="cancel">[[global:cancel]]</button>
|
||||
<button class="btn btn-sm btn-success" data-action="save">[[global:save]]</button>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user