Allow message type edition

This commit is contained in:
2021-09-17 23:45:28 +02:00
parent 0968a8481a
commit 07200af13e
6 changed files with 241 additions and 112 deletions

View File

@@ -1902,12 +1902,11 @@ class Databap extends PhpObject
return $iConnId;
}
public function addChatMessage($sMessage, $sChanName)
{
private function parseChatMessage($sMessage, $sChanName) {
$sMessage = htmlspecialchars($sMessage);
$sType = self::MESSAGE_USER;
$bSuccess = true;
$sDesc = '';
if(mb_substr($sMessage, 0, 1) == '/')
{
if(mb_substr($sMessage, 0, 4) == '/me ')
@@ -2076,11 +2075,19 @@ class Databap extends PhpObject
$sType = self::MESSAGE_PRIVATE;
}
return array('message'=>$sMessage, 'type'=>$sType, 'chan_name'=>$sChanName, 'success'=>$bSuccess);
}
public function addChatMessage($sMessage, $sChanName)
{
$sDesc = '';
$asMessage = $this->parseChatMessage($sMessage, $sChanName);
//Storing message
if($bSuccess)
if($asMessage['success'])
{
$sChanId = $this->getChanId($sChanName);
$bSuccess = $this->addMessage($sMessage, $sType, $sChanId);
$sChanId = $this->getChanId($asMessage['chan_name']);
$bSuccess = $this->addMessage($asMessage['message'], $asMessage['type'], $sChanId);
if(!$bSuccess) $sDesc = self::FAIL_INSERT;
}
@@ -2091,9 +2098,19 @@ class Databap extends PhpObject
{
$bSuccess = false;
$sDesc = '';
$asRefMsg = $this->oMySql->selectRow(self::MSG_TABLE, $iRefMsgId);
if(($asRefMsg['type'] == self::MESSAGE_USER || $asRefMsg['type'] == self::MESSAGE_PRIVATE) && $asRefMsg[$this->oMySql::getId(self::USER_TABLE)] == $this->getUserId()) {
$bSuccess = $this->addMessage($sMessage, $asRefMsg['type'], $asRefMsg['id_channel'], $this->getUserId(), $iRefMsgId);
$iChanId = $asRefMsg[MySqlManager::getId(self::CHAN_TABLE)];
$sChanName = $this->oMySql->selectValue(self::CHAN_TABLE, MySqlManager::getText(self::CHAN_TABLE), $iChanId);
$asNewMsg = $this->parseChatMessage($sMessage, $sChanName);
if(
($asRefMsg['type'] == self::MESSAGE_USER || $asRefMsg['type'] == self::MESSAGE_PRIVATE)
&&
($asNewMsg['type'] == self::MESSAGE_USER || $asNewMsg['type'] == self::MESSAGE_PRIVATE)
&&
$asRefMsg[$this->oMySql::getId(self::USER_TABLE)] == $this->getUserId()
) {
$bSuccess = $this->addMessage($sMessage, $asNewMsg['type'], $iChanId, $this->getUserId(), $iRefMsgId);
}
else $sDesc = 'Wrong user ID';

52
jquery/common.js vendored
View File

@@ -753,4 +753,56 @@ function utf8_encode(argString)
}
return utftext;
}
function getCaretPosition(editableDiv) {
var caretPos = 0, sel, range;
if(window.getSelection) {
sel = window.getSelection();
if(sel.rangeCount) {
range = sel.getRangeAt(0);
if(range.commonAncestorContainer.parentNode == editableDiv) {
caretPos = range.endOffset;
}
}
}
else if(document.selection && document.selection.createRange) {
range = document.selection.createRange();
if (range.parentElement() == editableDiv) {
var tempEl = document.createElement("span");
editableDiv.insertBefore(tempEl, editableDiv.firstChild);
var tempRange = range.duplicate();
tempRange.moveToElementText(tempEl);
tempRange.setEndPoint("EndToEnd", range);
caretPos = tempRange.text.length;
}
}
return caretPos;
}
function setCaretPosition(el, pos) {
// Loop through all child nodes
for(var node of el.childNodes) {
if(node.nodeType == 3){ // we have a text node
if(node.length >= pos) {
// finally add our range
var range = document.createRange(), sel = window.getSelection();
range.setStart(node,pos);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
return -1; // we are done
}
else {
pos -= node.length;
}
}
else {
pos = setCaretPosition(node,pos);
if(pos == -1) {
return -1; // no need to finish the for loop
}
}
}
return pos; // needed because of recursion stuff
}

View File

@@ -88,17 +88,19 @@ databap.pageInit = function()
self.tmp('news_period', 10*60*1000);
self.tmp('get_news', false);
self.tmp('last_message_id', '0');
self.tmp('messages', 'object');
self.tmp('scrolling', 'boolean');
databap.tmp('tab_info', 'object');
//Main elements
$MsgInput = databap.getMainElem('#message');
$MsgInputBox = databap.getMainElem('#chat_input');
$MsgBox = databap.getMainElem('#chat_messages');
//Bind message box key events
databap.getMainElem('#chat_form').submit(function(e){e.preventDefault();});
$MsgInput.bind('keydown', function(e){if(e.which == 9)e.preventDefault();});
$MsgInput.keyup(function(e){keyController(e);});
$MsgInput.keyup(keyController);
//Loading the chat
self.initScrollBar('#chat_container', '#chat_messages_box', '#chat_messages');
@@ -466,8 +468,8 @@ function switchChan(sChanKeyName)
$('#'+databap.consts.chanPrefix+sChanKeyName).addClass('active').removeClass('clickable');
//Show current channel messages
databap.getMainElem('#chat_messages').find('p').hide();
databap.getMainElem('#chat_messages').find('p.class_'+sChanKeyName+', p.class_'+databap.consts.all_chan_id).show();
$MsgBox.find('p').hide();
$MsgBox.find('p.class_'+sChanKeyName+', p.class_'+databap.consts.all_chan_id).show();
//Update scrollbar
databap.updateScrollBar(self.tmp('scrolling')?'relative':'bottom');
@@ -563,7 +565,7 @@ function quitChan(sChanKeyName)
if(sChanName == currentChan()) switchChan(Object.keys(databap.vars.chans_list)[1]);
//Delete messages
databap.getMainElem('#chat_messages').find('p.class_'+sChanKeyName).remove();
$MsgBox.find('p.class_'+sChanKeyName).remove();
}
else databap.addFailIcon('Ceci est le dernier chan');
}
@@ -603,48 +605,49 @@ function postMessage(sMsg)
return bSuccess;
}
function keyController(e)
function keyController(e, elem)
{
let $This = $(elem || this); console.log($This);
let sType = $This.is('input')?'input':'regular';
if(e.keyCode != 9) databap.tmp('tab_info', {}); //See case 9, tab
switch(e.keyCode)
{
case 13 : //enter
var chat_message = $MsgInput.val();
var chat_message = $This.val();
var bSuccess = true;
if(chat_message.substr(0, 7) == '/join #') joinChan(chat_message.substr(7));
else if(chat_message.substr(0, 7) == '/quit #') quitChan(getChanKeyName(chat_message.substr(7)));
else if(chat_message == '/help') displayHelp();
else if(chat_message.substr(0, 8) == '/invite ') invite($.trim(chat_message.substr(8)), currentChan());
else if(chat_message != '' && $MsgInput.data('orig_msg_id')) editMessage($MsgInput.data('orig_msg_id'), chat_message);
else if(chat_message != '' && $This.data('orig_msg_id')) editMessage($This.data('orig_msg_id'), chat_message);
else if(chat_message != '') bSuccess = postMessage();
if(bSuccess)
{
$MsgInput.val('');
$This.val('');
}
break;
case 27 : //echap
$MsgInput.val('');
$MsgInput.data('orig_msg_id', '');
$This.val('');
$This.data('orig_msg_id', '');
break;
case 38 : //arrow up
var $LastMsg = databap.getMainElem('#chat_messages').find('p.U[data-id-user='+databap.vars.user_id+'], p.P[data-id-user='+databap.vars.user_id+']').last();
if($MsgInput.val()=='' && $LastMsg.length)
var $LastMsg = $MsgBox.find('p.U[data-id-user='+databap.vars.user_id+'], p.P[data-id-user='+databap.vars.user_id+']').last();
if($This.val()=='' && $LastMsg.length)
{
$MsgInput.val($LastMsg.data('orig_msg'));
$MsgInput.data('orig_msg_id', $LastMsg.data('id'));
$This.val($LastMsg.data('orig_msg'));
$This.data('orig_msg_id', $LastMsg.data('id'));
}
break;
case 40 : //arrow down
if($MsgInput.data('orig_msg_id'))
if($This.data('orig_msg_id'))
{
$MsgInput.val('');
$MsgInput.data('orig_msg_id', '');
$This.val('');
$This.data('orig_msg_id', '');
}
break;
case 9 : //tab
$This = databap.getMainElem('#message');
var sChatMsg = $This.val();
var sChatMsg = (sType=='input')?$This.val():$This.text();
var iChatMsgLen = sChatMsg.length;
if(!e.altKey && iChatMsgLen>0)
@@ -663,7 +666,7 @@ function keyController(e)
else
{
//Find word in chat message input box
iCurPos = $This.getCursorPosition();
iCurPos = (sType=='input')?$This.getCursorPosition():getCaretPosition($This[0]);
iFirstPos = sChatMsg.substr(0, iCurPos).lastIndexOf(' ') + 1;
iOffset = sChatMsg.substr(iFirstPos).indexOf(' ');
sWord = sChatMsg.substr(iFirstPos, (iOffset==-1)?iChatMsgLen:iOffset);
@@ -713,8 +716,16 @@ function keyController(e)
var sAfterWord = sChatMsg.substr(iFirstPos+sWordLen);
var sSafeNickName = asSafeUserList[iIndex];
var sNickName = asUserList[sSafeNickName];
$This.val(sBeforeWord+sNickName+sAfterWord);
$This.setCursorPosition((sBeforeWord+sNickName).length);
var sText = sBeforeWord+sNickName+sAfterWord;
var sCaretPos = (sBeforeWord+sNickName).length;
if(sType=='input'){
$This.val(sText);
$This.setCursorPosition(sCaretPos);
}
else {
$This.text(sText);
setCaretPosition($This[0], sCaretPos);
}
//Save value for tab-loops
if(bLooping) databap.tmp(['tab_info', 'safe_nickname'], sSafeNickName); //not saving index in case of user list refresh
@@ -764,7 +775,7 @@ function refresh_chat(bReset)
if(bReset)
{
self.tmp('last_message_id', 0);
databap.getMainElem('#chat_messages').empty();
$MsgBox.empty();
}
databap.getInfo
(
@@ -822,36 +833,25 @@ function refresh_chat(bReset)
}
}
function addMessage(message_info, bReset)
function getMessage(message_info, bReset)
{
bReset = bReset || false;
message_info.nickname = message_info.nickname || '';
var sChanKeyName = message_info.id_chan;
var sMsgPrefix = '<a class="user clickable" title="Ecrire un PM &agrave; '+message_info.nickname+'">'+message_info.nickname+'</a><span class="console"></span>';
var msg_body = '';
var sUnreadChanName, iUnreadCount;
var bSystemMsg = false;
var bImage = false;
var sNotif = '';
switch(message_info.msg_class)
{
case databap.consts.msg_types.user:
if(message_info.id_message_ref) { //edit user message
let $Msg = databap.getMainElem('#chat_messages').find('p[data-id='+message_info.id_message_ref+']');
$Msg.find('.msg_txt').text(message_info.message);
$Msg.find('.status').show().text('modifié');
$Msg.data('orig_msg', message_info.message);
}
else {
msg_body = sMsgPrefix+'<span class="msg_txt text'+(message_info.id_user==databap.vars.user_id?' editable':'')+'">'+message_info.message+'</span>';
sNotif = message_info.nickname+' : '+message_info.message;
}
msg_body = sMsgPrefix+'<span class="msg_txt text'+(message_info.id_user==databap.vars.user_id?' editable':'')+'">'+message_info.message+'</span>';
break;
case databap.consts.msg_types.news:
databap.tmp('get_news', true);
msg_body = '<span class="text action">'+message_info.nickname+' a une news : <span class="news"><i class="fa fa-30 fa-c-news"></i> '+message_info.message+' <i class="fa fa-30 fa-c-news"></i></span></span>';
sNotif = message_info.nickname+' a une news : '+message_info.message;
break;
case databap.consts.msg_types.add.code:
var url = databap.getInternalLink('code', message_info.message);
@@ -876,17 +876,7 @@ function addMessage(message_info, bReset)
var slicePos = message_info.message.indexOf(' ');
var msgTargetUser = message_info.message.substr(1, slicePos - 1);
var msg = message_info.message.slice(slicePos + 1);
if(message_info.id_message_ref) { //edit user message
let $Msg = databap.getMainElem('#chat_messages').find('p[data-id='+message_info.id_message_ref+']');
$Msg.find('.highlight').text(msgTargetUser);
$Msg.find('.msg_txt').text(msg);
$Msg.find('.status').show().text('modifié');
$Msg.data('orig_msg', message_info.message);
}
else {
msg_body = '<a class="user clickable" title="Ecrire un PM &agrave; '+message_info.nickname+'">'+message_info.nickname+'</a><span class="console"> <span class="highlight">'+msgTargetUser+'</span></span><span class="msg_txt text'+(message_info.id_user==databap.vars.user_id?' editable':'')+'">'+msg+'</span>';
sNotif = message_info.nickname+' @'+msgTargetUser+' : '+msg;
}
msg_body = '<a class="user clickable" title="Ecrire un PM &agrave; '+message_info.nickname+'">'+message_info.nickname+'</a><span class="console"><span class="highlight">'+msgTargetUser+'</span></span><span class="msg_txt text'+(message_info.id_user==databap.vars.user_id?' editable':'')+'">'+msg+'</span>';
break;
case databap.consts.msg_types.nick:
msg_body = '<span class="text">'+message_info.message+' (<a href="'+databap.getInternalLink('profil', message_info.id_user)+'" target="_blank"><i class="fa fa-c-profile fa-inline"></i>'+message_info.name+'</a>)</span>';
@@ -895,7 +885,6 @@ function addMessage(message_info, bReset)
case databap.consts.msg_types.conn:
updateUsersList = true;
msg_body = (!self.vars2('opt_console'))?'':'<span class="text action">'+message_info.nickname+' '+message_info.message+'</span>';
bSystemMsg = true;
break;
case databap.consts.msg_types.img:
message_info.message = {url:message_info.message[3], title:'Source : '+message_info.message[3], url_img:message_info.message[0], width:message_info.message[1], height:message_info.message[2]};
@@ -903,19 +892,16 @@ function addMessage(message_info, bReset)
var msg = '<a href="'+message_info.message.url+'" target="_blank" title="'+message_info.message.title+'"><img src="'+message_info.message.url_img+'" width="'+message_info.message.width+'" height="'+message_info.message.height+'" class="proxy" /></a>';
msg_body = sMsgPrefix+'<span class="text">'+msg+'</span>';
bImage = true;
sNotif = message_info.nickname+' a posté une image';
break;
case databap.consts.msg_types.reboot:
if(!bReset)
{
msg_body = '<span class="text action">'+message_info.message+'</span>';
setTimeout(databap.refresh, databap.consts.reboot_delay*1000);
bSystemMsg = true;
}
break;
case databap.consts.msg_types.invite:
if(!bReset) joinChan(sChanKeyName, false, [], false);
bSystemMsg = true;
break;
case databap.consts.msg_types.article:
var url = databap.getInternalLink('a', message_info.message);
@@ -959,42 +945,97 @@ function addMessage(message_info, bReset)
$Msg.find('a').addClass('img_box').append($Banner);
}
if(message_info.edited) {
}
//Adding message to channel panel
$Message = $('<p>', {'class':message_info.msg_class+' class_'+sChanKeyName+' hide round_right', 'data-id':message_info.id, 'data-id-user':message_info.id_user})
.data('orig_msg', message_info.message)
.append($('<span>', {'class':'time'}).text(((message_info.date==databap.consts.cur_date)?'':message_info.date+' - ')+message_info.time))
.append($Msg)
.append($('<span>', {'class':'status'}));
.append($('<span>', {'class':'status'}).text('modifié'));
$Message.find('.chan_link').click(function(){joinChan($(this).find('.chan_text').text());});
$Message.find('.user').click(setPm);
databap.getMainElem('#chat_messages').append($Message);
//Edit own message
$Message.find('.editable').hover(toggleEditButton).click(onMessageEditClick);
//Unread messages
if(!bReset && !bSystemMsg /* && message_info.id_user!=databap.vars.user_id */)
{
sUnreadChanName = getChanName(message_info.id_chan);
iUnreadCount = (databap.tmp(['unread_msg', sUnreadChanName]) || 0) + 1;
databap.tmp(['unread_msg', sUnreadChanName], iUnreadCount);
if(message_info.edited) $Message.find('.status').show();
}
else $Message = null;
//Desktop Notification
if(!databap.vars.focus && sNotif != '' && Push.Permission.has()) {
Push.create('Databap - '+message_info.nickname, {
body: sNotif,
icon: databap.consts.app_image_folder+(databap.tmp(['logos', message_info.id_user]) || 'logo_25.png'),
timeout: 4000,
onClick: function () {
window.focus();
this.close();
}
});
}
databap.tmp(['messages', message_info.id], message_info);
return $Message;
}
function getNotif(message_info) {
let sNotif = '';
switch(message_info.msg_class)
{
case databap.consts.msg_types.user:
sNotif = message_info.nickname+' : '+message_info.message;
break;
case databap.consts.msg_types.news:
sNotif = message_info.nickname+' a une news : '+message_info.message;
break;
case databap.consts.msg_types['private']:
var slicePos = message_info.message.indexOf(' ');
sNotif = message_info.nickname+' @'+message_info.message.substr(1, slicePos - 1)+' : '+message_info.message.slice(slicePos + 1);
break;
case databap.consts.msg_types.img:
case databap.consts.msg_types['9gag']:
sNotif = message_info.nickname+' a posté une image';
break;
}
return sNotif;
}
function addMessage(message_info, bReset) {
let bNotif = false;
if(message_info.id_message_ref) {
let oOrigMsg = databap.tmp(['messages', message_info.id_message_ref]);
if(oOrigMsg) {
oOrigMsg.message = message_info.message;
oOrigMsg.msg_class = message_info.msg_class;
oOrigMsg.edited = true;
$MsgBox.find('p[data-id='+message_info.id_message_ref+']').after(getMessage(oOrigMsg)).remove();
}
}
else {
let $Message = getMessage(message_info, bReset);
let bSystemMsg = ($.inArray(message_info.msg_class, [databap.consts.msg_types.conn, databap.consts.msg_types.reboot, databap.consts.msg_types.invite]) >= 0);
if($Message) {
$MsgBox.append($Message);
//Move to bottom if user is typing
if(message_info.id_user===databap.vars.user_id) self.tmp('scrolling', false);
//Unread messages
if(!bReset && !bSystemMsg)
{
sUnreadChanName = getChanName(message_info.id_chan);
iUnreadCount = (databap.tmp(['unread_msg', sUnreadChanName]) || 0) + 1;
databap.tmp(['unread_msg', sUnreadChanName], iUnreadCount);
}
//Move to bottom if user is typing
if(message_info.id_user===databap.vars.user_id) self.tmp('scrolling', false);
bNotif = true;
}
}
//Desktop Notification
let sNotif = getNotif(message_info);
if(bNotif && !databap.vars.focus && sNotif != '' && Push.Permission.has()) {
Push.create('Databap - '+message_info.nickname, {
body: sNotif,
icon: databap.consts.app_image_folder+(databap.tmp(['logos', message_info.id_user]) || 'logo_25.png'),
timeout: 4000,
onClick: function () {
window.focus();
this.close();
}
});
}
}
@@ -1009,38 +1050,55 @@ function toggleEditButton()
function onMessageEditClick()
{
let $Editable = $(this);
$Editable.prop('contenteditable', 'true').focus();
let $Message = $Editable.parents('p');
let bPrivate = $Message.hasClass('P');
let sDisplayedMsg = $Editable.text();
let sOriginalMsg = $Message.data('orig_msg');
if($Editable.data('backup') == null)
{
let $Message = $Editable.parents('p');
let sPreContent = '';
if($Message.hasClass('P')) sPreContent = '@'+$Message.find('.highlight').text()+' ';
$Editable
.prop('contenteditable', 'true')
.data('disp_msg', sDisplayedMsg)
.focus();
if(sDisplayedMsg != sOriginalMsg) {
let iCaretPos = getCaretPosition($Editable[0]);
$Editable.text(sOriginalMsg);
setCaretPosition($Editable[0], iCaretPos + sOriginalMsg.indexOf(sDisplayedMsg));
}
if(bPrivate) $Message.find('.console').hide();
$Editable
.data('backup', $Editable.text())
.data('pre', sPreContent)
.on('focusout keydown', function(e) {
let $This = $(this);
if(e.type == 'focusout' || e.which == 13) {
e.preventDefault();
var sOldMsg = $This.data('backup');
var sNewMsg = $This.text();
$Editable
.off('focusout keydown keyup')
.keyup(function(e) {
if(e.keyCode == 9) {
e.preventDefault();
keyController(e, this);
console.log('shoot');
}
})
.on('focusout keydown', function(e) {
let $This = $(this);
if(e.type == 'focusout' || e.which == 13) {
e.preventDefault();
let $Message = $Editable.parents('p');
let sOldMsg = $Message.data('orig_msg');
let sNewMsg = $This.text();
if(sOldMsg != sNewMsg) {
$This.data('backup', sNewMsg);
$This.prop('contenteditable', 'false');
editMessage($This.parents('p').data('id'), $This.data('pre')+sNewMsg, function(){$This.data('backup', sOldMsg);});
}
if(sOldMsg != sNewMsg) {
$This.prop('contenteditable', 'false');
editMessage($This.parents('p').data('id'), sNewMsg);
}
});
}
else {
$This.text($This.data('disp_msg'));
$Message.find('.console').show();
}
}
else if(e.keyCode == 9) e.preventDefault();
});
}
function editMessage(iMsgId, sNewMsg, fOnError)
function editMessage(iMsgId, sNewMsg)
{
fOnError = fOnError || function(){};
databap.getInfo
(
'edit_message',
@@ -1053,7 +1111,6 @@ function editMessage(iMsgId, sNewMsg, fOnError)
'json',
function(textStatus)
{
fOnError();
databap.showError(textStatus);
}
);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -740,6 +740,9 @@
text-decoration:none;
font-style:normal;
}
#chat_messages p.P span.console {
margin-left:5px;
}
#chat_messages p span.time {
color:$col_hover_1;
font-size:$size_small;