void ChatForm::SendMessageStr(QString msg) { if (msg.isEmpty()) return; bool isAction = msg.startsWith(ACTION_PREFIX, Qt::CaseInsensitive); if (isAction) msg.remove(0, ACTION_PREFIX.length()); QList<CString> splittedMsg = Core::splitMessage(msg, TOX_MAX_MESSAGE_LENGTH); QDateTime timestamp = QDateTime::currentDateTime(); for (CString& c_msg : splittedMsg) { QString qt_msg = CString::toString(c_msg.data(), c_msg.size()); QString qt_msg_hist = qt_msg; if (isAction) qt_msg_hist = ACTION_PREFIX + qt_msg; bool status = !Settings::getInstance().getFauxOfflineMessaging(); ChatMessage::Ptr ma = addSelfMessage(qt_msg, isAction, timestamp, false); int rec; if (isAction) rec = Core::getInstance()->sendAction(f->getFriendID(), qt_msg); else rec = Core::getInstance()->sendMessage(f->getFriendID(), qt_msg); Profile* profile = Nexus::getProfile(); if (profile->isHistoryEnabled()) { auto* offMsgEngine = getOfflineMsgEngine(); profile->getHistory()->addNewMessage(f->getToxId().publicKey, qt_msg_hist, Core::getInstance()->getSelfId().publicKey, timestamp, status, Core::getInstance()->getUsername(), [offMsgEngine,rec,ma](int64_t id) { offMsgEngine->registerReceipt(rec, id, ma); }); } else { // TODO: Make faux-offline messaging work partially with the history disabled ma->markAsSent(QDateTime::currentDateTime()); } msgEdit->setLastMessage(msg); //set last message only when sending it Widget::getInstance()->updateFriendActivity(f); } }
ChatMessage::Ptr ChatMessage::createChatMessage(const QString &sender, const QString &rawMessage, MessageType type, bool isMe, const QDateTime &date) { ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage); QString text = rawMessage.toHtmlEscaped(); QString senderText = sender; const QColor actionColor = QColor("#1818FF"); // has to match the color in innerStyle.css (div.action) //smileys if (Settings::getInstance().getUseEmoticons()) text = SmileyPack::getInstance().smileyfied(text); //quotes (green text) text = detectQuotes(detectAnchors(text), type); //text styling if (Settings::getInstance().getStylePreference() != Settings::StyleType::NONE) text = detectStyle(text); switch(type) { case NORMAL: text = wrapDiv(text, "msg"); break; case ACTION: senderText = "*"; text = wrapDiv(QString("%1 %2").arg(sender.toHtmlEscaped(), text), "action"); msg->setAsAction(); break; case ALERT: text = wrapDiv(text, "alert"); break; } // Note: Eliding cannot be enabled for RichText items. (QTBUG-17207) QFont baseFont = Settings::getInstance().getChatMessageFont(); QFont authorFont = baseFont; if (isMe) authorFont.setBold(true); msg->addColumn(new Text(senderText, authorFont, true, sender, type == ACTION ? actionColor : Qt::black), ColumnFormat(NAME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right)); msg->addColumn(new Text(text, baseFont, false, ((type == ACTION) && isMe) ? QString("%1 %2").arg(sender, rawMessage) : rawMessage), ColumnFormat(1.0, ColumnFormat::VariableSize)); msg->addColumn(new Spinner(":/ui/chatArea/spinner.svg", QSize(16, 16), 360.0/1.6), ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right)); if (!date.isNull()) msg->markAsSent(date); return msg; }
void ChatForm::loadHistory(QDateTime since, bool processUndelivered) { QDateTime now = historyBaselineDate.addMSecs(-1); if (since > now) return; if (!earliestMessage.isNull()) { if (earliestMessage < since) return; if (earliestMessage < now) { now = earliestMessage; now = now.addMSecs(-1); } } auto msgs = HistoryKeeper::getInstance()->getChatHistory(HistoryKeeper::ctSingle, f->getToxID().publicKey, since, now); ToxId storedPrevId = previousId; ToxId prevId; QList<ChatLine::Ptr> historyMessages; QDate lastDate(1,0,0); for (const auto &it : msgs) { // Show the date every new day QDateTime msgDateTime = it.timestamp.toLocalTime(); QDate msgDate = msgDateTime.date(); if (msgDate > lastDate) { lastDate = msgDate; historyMessages.append(ChatMessage::createChatInfoMessage(msgDate.toString(Settings::getInstance().getDateFormat()), ChatMessage::INFO, QDateTime())); } // Show each messages ToxId authorId = ToxId(it.sender); QString authorStr = authorId.isActiveProfile() ? Core::getInstance()->getUsername() : resolveToxID(authorId); bool isAction = it.message.startsWith("/me ", Qt::CaseInsensitive); ChatMessage::Ptr msg = ChatMessage::createChatMessage(authorStr, isAction ? it.message.right(it.message.length() - 4) : it.message, isAction ? ChatMessage::ACTION : ChatMessage::NORMAL, authorId.isActiveProfile(), QDateTime()); if (!isAction && (prevId == authorId) && (prevMsgDateTime.secsTo(msgDateTime) < getChatLog()->repNameAfter) ) msg->hideSender(); prevId = authorId; prevMsgDateTime = msgDateTime; if (it.isSent || !authorId.isActiveProfile()) { msg->markAsSent(msgDateTime); } else { if (processUndelivered) { int rec; if (!isAction) rec = Core::getInstance()->sendMessage(f->getFriendID(), msg->toString()); else rec = Core::getInstance()->sendAction(f->getFriendID(), msg->toString()); getOfflineMsgEngine()->registerReceipt(rec, it.id, msg); } } historyMessages.append(msg); } previousId = storedPrevId; int savedSliderPos = chatWidget->verticalScrollBar()->maximum() - chatWidget->verticalScrollBar()->value(); earliestMessage = since; chatWidget->insertChatlineOnTop(historyMessages); savedSliderPos = chatWidget->verticalScrollBar()->maximum() - savedSliderPos; chatWidget->verticalScrollBar()->setValue(savedSliderPos); }