Skip to content

Commit

Permalink
refactor(chatform): Remove message handling logic from gui path
Browse files Browse the repository at this point in the history
Functional changes
* Offline messages are still sent when the chat log is cleared
* Spinner now does not wait for history to be complete, just a receipt
  from our friend
* Export chat and load chat history are now available in group chats
* Merged save chat log and export chat log
  * Note that we lost the info messages in the process

NonFunctional Changes
* FileTransferWidget slots only called for correct file
* Settings::getEnableGroupChatsColor now embedded in
GenericChatForm::colorizeNames
  * Settings::setEnableGroupChatscolor now emits signal connected to
GenericChatForm::setColorizedNames to keep state in sync
* Chatlog history not reloaded on setPassword()
  * I am pretty sure this had no purpose
* Removed a lot of responsibility from ChatForm
  * History moved to ChatHistory implementation of IChatLog
  * OfflineMsgEngine moved to FriendMessageDispatcher
  * Export chat and load chat history moved to GenericChatLog
    * Backed by IChatLog so can be used generically
  * Message processing moved to FriendMessageDispatcher
  * The action of sending files to coreFile is still handled by
  ChatForm, but displaying of the sent messages is done through IChatLog
  -> GenericChatForm
  * Search moved to ChatHistory/SessionChatLog
  * All insertion of chat log elements should be handled by
  GenericChatForm now
* Removed overlapping responsibilities from GroupChatForm
  * Search and message sending goes through ichatlog/messagedispatcher
  too
  * Lots of search functionality pushed down into IChatLog
* Some of the file logic was moved into Widget. This is mostly to avoid
  scope increase of this PR even further.
* History APIs removed that were no longer used
  • Loading branch information
sphaerophoria committed Jun 21, 2019
1 parent e607e6e commit ed514d7
Show file tree
Hide file tree
Showing 20 changed files with 661 additions and 1,459 deletions.
2 changes: 1 addition & 1 deletion src/chatlog/chatmessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QSt
authorFont.setBold(true);

QColor color = Style::getColor(Style::MainText);
if (colorizeName && Settings::getInstance().getEnableGroupChatsColor()) {
if (colorizeName) {
QByteArray hash = QCryptographicHash::hash((sender.toUtf8()), QCryptographicHash::Sha256);
quint8 *data = (quint8*)hash.data();

Expand Down
90 changes: 3 additions & 87 deletions src/chatlog/content/filetransferwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,6 @@ FileTransferWidget::FileTransferWidget(QWidget* parent, ToxFile file)

CoreFile* coreFile = Core::getInstance()->getCoreFile();

connect(coreFile, &CoreFile::fileTransferInfo, this,
&FileTransferWidget::onFileTransferInfo);
connect(coreFile, &CoreFile::fileTransferAccepted, this,
&FileTransferWidget::onFileTransferAccepted);
connect(coreFile, &CoreFile::fileTransferCancelled, this,
&FileTransferWidget::onFileTransferCancelled);
connect(coreFile, &CoreFile::fileTransferPaused, this,
&FileTransferWidget::onFileTransferPaused);
connect(coreFile, &CoreFile::fileTransferFinished, this,
&FileTransferWidget::onFileTransferFinished);
connect(coreFile, &CoreFile::fileTransferRemotePausedUnpaused, this,
&FileTransferWidget::fileTransferRemotePausedUnpaused);
connect(coreFile, &CoreFile::fileTransferBrokenUnbroken, this,
&FileTransferWidget::fileTransferBrokenUnbroken);
connect(ui->leftButton, &QPushButton::clicked, this, &FileTransferWidget::onLeftButtonClicked);
connect(ui->rightButton, &QPushButton::clicked, this, &FileTransferWidget::onRightButtonClicked);
connect(ui->previewButton, &QPushButton::clicked, this,
Expand Down Expand Up @@ -133,30 +119,9 @@ bool FileTransferWidget::tryRemoveFile(const QString& filepath)
return writable;
}

void FileTransferWidget::autoAcceptTransfer(const QString& path)
void FileTransferWidget::onFileTransferUpdate(ToxFile file)
{
QString filepath;
int number = 0;

QString suffix = QFileInfo(fileInfo.fileName).completeSuffix();
QString base = QFileInfo(fileInfo.fileName).baseName();

do {
filepath = QString("%1/%2%3.%4")
.arg(path, base,
number > 0 ? QString(" (%1)").arg(QString::number(number)) : QString(),
suffix);
++number;
} while (QFileInfo(filepath).exists());

// Do not automatically accept the file-transfer if the path is not writable.
// The user can still accept it manually.
if (tryRemoveFile(filepath)) {
CoreFile* coreFile = Core::getInstance()->getCoreFile();
coreFile->acceptFileRecvRequest(fileInfo.friendId, fileInfo.fileNum, filepath);
} else {
qWarning() << "Cannot write to " << filepath;
}
updateWidget(file);
}

bool FileTransferWidget::isActive() const
Expand Down Expand Up @@ -265,53 +230,6 @@ void FileTransferWidget::paintEvent(QPaintEvent*)
}
}

void FileTransferWidget::onFileTransferInfo(ToxFile file)
{
updateWidget(file);
}

void FileTransferWidget::onFileTransferAccepted(ToxFile file)
{
updateWidget(file);
}

void FileTransferWidget::onFileTransferCancelled(ToxFile file)
{
updateWidget(file);
}

void FileTransferWidget::onFileTransferPaused(ToxFile file)
{
updateWidget(file);
}

void FileTransferWidget::onFileTransferResumed(ToxFile file)
{
updateWidget(file);
}

void FileTransferWidget::onFileTransferFinished(ToxFile file)
{
updateWidget(file);
}

void FileTransferWidget::fileTransferRemotePausedUnpaused(ToxFile file, bool paused)
{
if (paused) {
onFileTransferPaused(file);
} else {
onFileTransferResumed(file);
}
}

void FileTransferWidget::fileTransferBrokenUnbroken(ToxFile file, bool broken)
{
// TODO: Handle broken transfer differently once we have resuming code
if (broken) {
onFileTransferCancelled(file);
}
}

QString FileTransferWidget::getHumanReadableSize(qint64 size)
{
static const char* suffix[] = {"B", "kiB", "MiB", "GiB", "TiB"};
Expand Down Expand Up @@ -737,9 +655,7 @@ void FileTransferWidget::applyTransformation(const int orientation, QImage& imag

void FileTransferWidget::updateWidget(ToxFile const& file)
{
if (fileInfo != file) {
return;
}
assert(file == fileInfo);

fileInfo = file;

Expand Down
11 changes: 1 addition & 10 deletions src/chatlog/content/filetransferwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,10 @@ class FileTransferWidget : public QWidget
public:
explicit FileTransferWidget(QWidget* parent, ToxFile file);
virtual ~FileTransferWidget();
void autoAcceptTransfer(const QString& path);
bool isActive() const;
static QString getHumanReadableSize(qint64 size);

protected slots:
void onFileTransferInfo(ToxFile file);
void onFileTransferAccepted(ToxFile file);
void onFileTransferCancelled(ToxFile file);
void onFileTransferPaused(ToxFile file);
void onFileTransferResumed(ToxFile file);
void onFileTransferFinished(ToxFile file);
void fileTransferRemotePausedUnpaused(ToxFile file, bool paused);
void fileTransferBrokenUnbroken(ToxFile file, bool broken);
void onFileTransferUpdate(ToxFile file);

protected:
void updateWidgetColor(ToxFile const& file);
Expand Down
2 changes: 1 addition & 1 deletion src/model/about/aboutfriend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ bool AboutFriend::isHistoryExistence()
History* const history = Nexus::getProfile()->getHistory();
if (history) {
const ToxPk pk = f->getPublicKey();
return history->isHistoryExistence(pk.toString());
return history->historyExists(pk);
}

return false;
Expand Down
1 change: 1 addition & 0 deletions src/nexus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ void Nexus::showMainGUI()
connect(core, &Core::friendStatusMessageChanged, widget, &Widget::onFriendStatusMessageChanged);
connect(core, &Core::friendRequestReceived, widget, &Widget::onFriendRequestReceived);
connect(core, &Core::friendMessageReceived, widget, &Widget::onFriendMessageReceived);
connect(core, &Core::receiptRecieved, widget, &Widget::onReceiptReceived);
connect(core, &Core::groupInviteReceived, widget, &Widget::onGroupInviteReceived);
connect(core, &Core::groupMessageReceived, widget, &Widget::onGroupMessageReceived);
connect(core, &Core::groupPeerlistChanged, widget, &Widget::onGroupPeerlistChanged);
Expand Down
173 changes: 3 additions & 170 deletions src/persistence/history.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ bool History::isValid()
* @param friendPk
* @return True if has, false otherwise.
*/
bool History::isHistoryExistence(const QString& friendPk)
bool History::historyExists(const ToxPk& friendPk)
{
return !getChatHistoryDefaultNum(friendPk).isEmpty();
return !getMessagesForFriend(friendPk, 0, 1).empty();
}

/**
Expand Down Expand Up @@ -521,78 +521,6 @@ void History::setFileFinished(const QString& fileId, bool success, const QString
fileInfos.remove(fileId);
}

/**
* @brief Fetches chat messages from the database.
* @param friendPk Friend publick key to fetch.
* @param from Start of period to fetch.
* @param to End of period to fetch.
* @return List of messages.
*/
QList<History::HistMessage> History::getChatHistoryFromDate(const QString& friendPk,
const QDateTime& from, const QDateTime& to)
{
if (!isValid()) {
return {};
}
return getChatHistory(friendPk, from, to, 0);
}

/**
* @brief Fetches the latest set amount of messages from the database.
* @param friendPk Friend public key to fetch.
* @return List of messages.
*/
QList<History::HistMessage> History::getChatHistoryDefaultNum(const QString& friendPk)
{
if (!isValid()) {
return {};
}
return getChatHistory(friendPk, QDateTime::fromMSecsSinceEpoch(0), QDateTime::currentDateTime(),
NUM_MESSAGES_DEFAULT);
}


/**
* @brief Fetches chat messages counts for each day from the database.
* @param friendPk Friend public key to fetch.
* @param from Start of period to fetch.
* @param to End of period to fetch.
* @return List of structs containing days offset and message count for that day.
*/
QList<History::DateMessages> History::getChatHistoryCounts(const ToxPk& friendPk, const QDate& from,
const QDate& to)
{
if (!isValid()) {
return {};
}
QDateTime fromTime(from);
QDateTime toTime(to);

QList<DateMessages> counts;

auto rowCallback = [&counts](const QVector<QVariant>& row) {
DateMessages app;
app.count = row[0].toUInt();
app.offsetDays = row[1].toUInt();
counts.append(app);
};

QString queryText =
QString("SELECT COUNT(history.id), ((timestamp / 1000 / 60 / 60 / 24) - %4 ) AS day "
"FROM history "
"JOIN peers chat ON chat_id = chat.id "
"WHERE timestamp BETWEEN %1 AND %2 AND chat.public_key='%3'"
"GROUP BY day;")
.arg(fromTime.toMSecsSinceEpoch())
.arg(toTime.toMSecsSinceEpoch())
.arg(friendPk.toString())
.arg(QDateTime::fromMSecsSinceEpoch(0).daysTo(fromTime));

db->execNow({queryText, rowCallback});

return counts;
}

size_t History::getNumMessagesForFriend(const ToxPk& friendPk)
{
return getNumMessagesForFriendBeforeDate(friendPk,
Expand Down Expand Up @@ -857,31 +785,6 @@ QList<History::DateIdx> History::getNumMessagesForFriendBeforeDateBoundaries(con
return dateIdxs;
}

/**
* @brief get start date of correspondence
* @param friendPk Friend public key
* @return start date of correspondence
*/
QDateTime History::getStartDateChatHistory(const QString& friendPk)
{
QDateTime result;
auto rowCallback = [&result](const QVector<QVariant>& row) {
result = QDateTime::fromMSecsSinceEpoch(row[0].toLongLong());
};

QString queryText =
QStringLiteral("SELECT timestamp "
"FROM history "
"LEFT JOIN faux_offline_pending ON history.id = faux_offline_pending.id "
"JOIN peers chat ON chat_id = chat.id "
"WHERE chat.public_key='%1' ORDER BY timestamp ASC LIMIT 1;")
.arg(friendPk);

db->execNow({queryText, rowCallback});

return result;
}

/**
* @brief Marks a message as sent.
* Removing message from the faux-offline pending messages list.
Expand All @@ -895,74 +798,4 @@ void History::markAsSent(RowId messageId)
}

db->execLater(QString("DELETE FROM faux_offline_pending WHERE id=%1;").arg(messageId.get()));
}


/**
* @brief Fetches chat messages from the database.
* @param friendPk Friend publick key to fetch.
* @param from Start of period to fetch.
* @param to End of period to fetch.
* @param numMessages max number of messages to fetch.
* @return List of messages.
*/
QList<History::HistMessage> History::getChatHistory(const QString& friendPk, const QDateTime& from,
const QDateTime& to, int numMessages)
{
QList<HistMessage> messages;

auto rowCallback = [&messages](const QVector<QVariant>& row) {
// dispName and message could have null bytes, QString::fromUtf8
// truncates on null bytes so we strip them
auto id = RowId{row[0].toLongLong()};
auto isOfflineMessage = row[1].isNull();
auto timestamp = QDateTime::fromMSecsSinceEpoch(row[2].toLongLong());
auto friend_key = row[3].toString();
auto display_name = QString::fromUtf8(row[4].toByteArray().replace('\0', ""));
auto sender_key = row[5].toString();
if (row[7].isNull()) {
messages +=
{id, isOfflineMessage, timestamp, friend_key, display_name, sender_key, row[6].toString()};
} else {
ToxFile file;
file.fileKind = TOX_FILE_KIND_DATA;
file.resumeFileId = row[7].toString().toUtf8();
file.filePath = row[8].toString();
file.fileName = row[9].toString();
file.filesize = row[10].toLongLong();
file.direction = static_cast<ToxFile::FileDirection>(row[11].toLongLong());
file.status = static_cast<ToxFile::FileStatus>(row[12].toInt());
messages +=
{id, isOfflineMessage, timestamp, friend_key, display_name, sender_key, file};
}
};

// Don't forget to update the rowCallback if you change the selected columns!
QString queryText =
QString("SELECT history.id, faux_offline_pending.id, timestamp, "
"chat.public_key, aliases.display_name, sender.public_key, "
"message, file_transfers.file_restart_id, "
"file_transfers.file_path, file_transfers.file_name, "
"file_transfers.file_size, file_transfers.direction, "
"file_transfers.file_state FROM history "
"LEFT JOIN faux_offline_pending ON history.id = faux_offline_pending.id "
"JOIN peers chat ON history.chat_id = chat.id "
"JOIN aliases ON sender_alias = aliases.id "
"JOIN peers sender ON aliases.owner = sender.id "
"LEFT JOIN file_transfers ON history.file_id = file_transfers.id "
"WHERE timestamp BETWEEN %1 AND %2 AND chat.public_key='%3'")
.arg(from.toMSecsSinceEpoch())
.arg(to.toMSecsSinceEpoch())
.arg(friendPk);
if (numMessages) {
queryText =
"SELECT * FROM (" + queryText
+ QString(" ORDER BY history.id DESC limit %1) AS T1 ORDER BY T1.id ASC;").arg(numMessages);
} else {
queryText = queryText + ";";
}

db->execNow({queryText, rowCallback});

return messages;
}
}
Loading

0 comments on commit ed514d7

Please sign in to comment.