diff --git a/res/io.github.qtox.qTox.appdata.xml b/res/io.github.qtox.qTox.appdata.xml
index e901f29b0..69335fd36 100644
--- a/res/io.github.qtox.qTox.appdata.xml
+++ b/res/io.github.qtox.qTox.appdata.xml
@@ -63,6 +63,10 @@
https://qtox.github.io
barrdetwix@gmail.com
qTox
+
+ intense
+ intense
+
diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp
index b2d90f005..81d10cb8c 100644
--- a/src/core/corefile.cpp
+++ b/src/core/corefile.cpp
@@ -95,9 +95,9 @@ void CoreFile::sendAvatarFile(uint32_t friendId, const QByteArray& data)
uint8_t *file_id = nullptr;
uint8_t *file_name = nullptr;
size_t nameLength = 0;
+ uint8_t avatarHash[TOX_HASH_LENGTH];
if (!data.isEmpty()) {
static_assert(TOX_HASH_LENGTH <= TOX_FILE_ID_LENGTH, "TOX_HASH_LENGTH > TOX_FILE_ID_LENGTH!");
- uint8_t avatarHash[TOX_HASH_LENGTH];
tox_hash(avatarHash, (uint8_t*)data.data(), data.size());
filesize = data.size();
file_id = avatarHash;
diff --git a/src/model/chatroom/friendchatroom.cpp b/src/model/chatroom/friendchatroom.cpp
index 79f06a63f..d97d4d148 100644
--- a/src/model/chatroom/friendchatroom.cpp
+++ b/src/model/chatroom/friendchatroom.cpp
@@ -22,6 +22,7 @@
#include "src/model/dialogs/idialogsmanager.h"
#include "src/model/friend.h"
#include "src/model/group.h"
+#include "src/model/status.h"
#include "src/persistence/settings.h"
#include "src/widget/contentdialog.h"
@@ -67,7 +68,7 @@ void FriendChatroom::setActive(bool _active)
bool FriendChatroom::canBeInvited() const
{
- return frnd->isOnline();
+ return Status::isOnline(frnd->getStatus());
}
int FriendChatroom::getCircleId() const
diff --git a/src/model/chatroom/groupchatroom.cpp b/src/model/chatroom/groupchatroom.cpp
index 3efeb8669..3c8327948 100644
--- a/src/model/chatroom/groupchatroom.cpp
+++ b/src/model/chatroom/groupchatroom.cpp
@@ -25,6 +25,7 @@
#include "src/model/dialogs/idialogsmanager.h"
#include "src/model/friend.h"
#include "src/model/group.h"
+#include "src/model/status.h"
#include "src/persistence/settings.h"
GroupChatroom::GroupChatroom(Group* group, IDialogsManager* dialogsManager)
@@ -64,7 +65,7 @@ void GroupChatroom::inviteFriend(const ToxPk& pk)
const Friend* frnd = FriendList::findFriend(pk);
const auto friendId = frnd->getId();
const auto groupId = group->getId();
- const auto canInvite = frnd->isOnline();
+ const auto canInvite = Status::isOnline(frnd->getStatus());
if (canInvite) {
Core::getInstance()->groupInviteFriend(friendId, groupId);
diff --git a/src/model/friend.cpp b/src/model/friend.cpp
index 08f80dadf..c34058e18 100644
--- a/src/model/friend.cpp
+++ b/src/model/friend.cpp
@@ -152,8 +152,15 @@ bool Friend::getEventFlag() const
void Friend::setStatus(Status::Status s)
{
if (friendStatus != s) {
+ auto oldStatus = friendStatus;
friendStatus = s;
emit statusChanged(friendPk, friendStatus);
+ if (!Status::isOnline(oldStatus) && Status::isOnline(friendStatus)) {
+ emit onlineOfflineChanged(friendPk, true);
+ } else if (Status::isOnline(oldStatus) && !Status::isOnline(friendStatus)) {
+ emit onlineOfflineChanged(friendPk, false);
+ }
+
}
}
@@ -162,11 +169,6 @@ Status::Status Friend::getStatus() const
return friendStatus;
}
-bool Friend::isOnline() const
-{
- return friendStatus != Status::Status::Offline && friendStatus != Status::Status::Blocked;
-}
-
bool Friend::useHistory() const
{
return true;
diff --git a/src/model/friend.h b/src/model/friend.h
index 7cc6bf7cf..46f1c08d8 100644
--- a/src/model/friend.h
+++ b/src/model/friend.h
@@ -53,14 +53,13 @@ public:
void setStatus(Status::Status s);
Status::Status getStatus() const;
- bool isOnline() const;
-
bool useHistory() const final;
signals:
void nameChanged(const ToxPk& friendId, const QString& name);
void aliasChanged(const ToxPk& friendId, QString alias);
void statusChanged(const ToxPk& friendId, Status::Status status);
+ void onlineOfflineChanged(const ToxPk& friendId, bool isOnline);
void statusMessageChanged(const ToxPk& friendId, const QString& message);
void loadChatHistory();
diff --git a/src/model/friendmessagedispatcher.cpp b/src/model/friendmessagedispatcher.cpp
index 803b4645c..9a7a10cc6 100644
--- a/src/model/friendmessagedispatcher.cpp
+++ b/src/model/friendmessagedispatcher.cpp
@@ -19,6 +19,7 @@
#include "friendmessagedispatcher.h"
#include "src/persistence/settings.h"
+#include "src/model/status.h"
namespace {
@@ -49,7 +50,7 @@ FriendMessageDispatcher::FriendMessageDispatcher(Friend& f_, MessageProcessor pr
, offlineMsgEngine(&f_, &messageSender_)
, processor(std::move(processor_))
{
- connect(&f, &Friend::statusChanged, this, &FriendMessageDispatcher::onFriendStatusChange);
+ connect(&f, &Friend::onlineOfflineChanged, this, &FriendMessageDispatcher::onFriendOnlineOfflineChanged);
}
/**
@@ -69,7 +70,7 @@ FriendMessageDispatcher::sendMessage(bool isAction, const QString& content)
bool messageSent = false;
- if (f.isOnline()) {
+ if (Status::isOnline(f.getStatus())) {
messageSent = sendMessageToCore(messageSender, f, message, receipt);
}
@@ -107,9 +108,9 @@ void FriendMessageDispatcher::onReceiptReceived(ReceiptNum receipt)
* @brief Handles status change for friend
* @note Parameters just to fit slot api
*/
-void FriendMessageDispatcher::onFriendStatusChange(const ToxPk&, Status::Status)
+void FriendMessageDispatcher::onFriendOnlineOfflineChanged(const ToxPk&, bool isOnline)
{
- if (f.isOnline()) {
+ if (isOnline) {
offlineMsgEngine.deliverOfflineMsgs();
}
}
diff --git a/src/model/friendmessagedispatcher.h b/src/model/friendmessagedispatcher.h
index 74b210916..63efe5e13 100644
--- a/src/model/friendmessagedispatcher.h
+++ b/src/model/friendmessagedispatcher.h
@@ -44,7 +44,7 @@ public:
void onReceiptReceived(ReceiptNum receipt);
void clearOutgoingMessages();
private slots:
- void onFriendStatusChange(const ToxPk& key, Status::Status status);
+ void onFriendOnlineOfflineChanged(const ToxPk& key, bool isOnline);
private:
Friend& f;
diff --git a/src/model/status.cpp b/src/model/status.cpp
index 292ad97c3..50220126a 100644
--- a/src/model/status.cpp
+++ b/src/model/status.cpp
@@ -75,4 +75,9 @@ namespace Status
return ":/img/status/" + statusSuffix + eventSuffix + ".svg";
}
}
+
+ bool isOnline(Status status)
+ {
+ return status != Status::Offline && status != Status::Blocked;
+ }
} // namespace Status
diff --git a/src/model/status.h b/src/model/status.h
index b80c014cf..5ee11664e 100644
--- a/src/model/status.h
+++ b/src/model/status.h
@@ -38,6 +38,7 @@ namespace Status
QString getIconPath(Status status, bool event = false);
QString getTitle(Status status);
QString getAssetSuffix(Status status);
+ bool isOnline(Status status);
}
#endif // STATUS_H
diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp
index 4822b0274..d641e8cbd 100644
--- a/src/persistence/history.cpp
+++ b/src/persistence/history.cpp
@@ -195,10 +195,11 @@ bool dbSchema3to4(RawDatabase& db)
/**
* @brief Upgrade the db schema
+* @return True if the schema upgrade succeded, false otherwise
* @note On future alterations of the database all you have to do is bump the SCHEMA_VERSION
* variable and add another case to the switch statement below. Make sure to fall through on each case.
*/
-void dbSchemaUpgrade(std::shared_ptr& db)
+bool dbSchemaUpgrade(std::shared_ptr& db)
{
int64_t databaseSchemaVersion;
@@ -206,19 +207,17 @@ void dbSchemaUpgrade(std::shared_ptr& db)
databaseSchemaVersion = row[0].toLongLong();
}))) {
qCritical() << "History failed to read user_version";
- db.reset();
- return;
+ return false;
}
if (databaseSchemaVersion > SCHEMA_VERSION) {
qWarning().nospace() << "Database version (" << databaseSchemaVersion <<
") is newer than we currently support (" << SCHEMA_VERSION << "). Please upgrade qTox";
// We don't know what future versions have done, we have to disable db access until we re-upgrade
- db.reset();
- return;
+ return false;
} else if (databaseSchemaVersion == SCHEMA_VERSION) {
// No work to do
- return;
+ return true;
}
switch (databaseSchemaVersion) {
@@ -231,22 +230,19 @@ void dbSchemaUpgrade(std::shared_ptr& db)
const bool newDb = isNewDb(db, success);
if (!success) {
qCritical() << "Failed to create current db schema";
- db.reset();
- return;
+ return false;
}
if (newDb) {
if (!createCurrentSchema(*db)) {
qCritical() << "Failed to create current db schema";
- db.reset();
- return;
+ return false;
}
qDebug() << "Database created at schema version" << SCHEMA_VERSION;
break; // new db is the only case where we don't incrementally upgrade through each version
} else {
if (!dbSchema0to1(*db)) {
qCritical() << "Failed to upgrade db to schema version 1, aborting";
- db.reset();
- return;
+ return false;
}
qDebug() << "Database upgraded incrementally to schema version 1";
}
@@ -255,23 +251,20 @@ void dbSchemaUpgrade(std::shared_ptr& db)
case 1:
if (!dbSchema1to2(*db)) {
qCritical() << "Failed to upgrade db to schema version 2, aborting";
- db.reset();
- return;
+ return false;
}
qDebug() << "Database upgraded incrementally to schema version 2";
//fallthrough
case 2:
if (!dbSchema2to3(*db)) {
qCritical() << "Failed to upgrade db to schema version 3, aborting";
- db.reset();
- return;
+ return false;
}
qDebug() << "Database upgraded incrementally to schema version 3";
case 3:
if (!dbSchema3to4(*db)) {
qCritical() << "Failed to upgrade db to schema version 4, aborting";
- db.reset();
- return;
+ return false;
}
qDebug() << "Database upgraded incrementally to schema version 4";
// etc.
@@ -279,6 +272,8 @@ void dbSchemaUpgrade(std::shared_ptr& db)
qInfo() << "Database upgrade finished (databaseSchemaVersion" << databaseSchemaVersion
<< "->" << SCHEMA_VERSION << ")";
}
+
+ return true;
}
MessageState getMessageState(bool isPending, bool isBroken)
@@ -318,18 +313,19 @@ FileDbInsertionData::FileDbInsertionData()
* @brief Prepares the database to work with the history.
* @param db This database will be prepared for use with the history.
*/
-History::History(std::shared_ptr db)
- : db(db)
+History::History(std::shared_ptr db_)
+ : db(db_)
{
if (!isValid()) {
qWarning() << "Database not open, init failed";
return;
}
- dbSchemaUpgrade(db);
+ const auto upgradeSucceeded = dbSchemaUpgrade(db);
// dbSchemaUpgrade may have put us in an invalid state
- if (!isValid()) {
+ if (!upgradeSucceeded) {
+ db.reset();
return;
}
@@ -370,6 +366,10 @@ bool History::isValid()
*/
bool History::historyExists(const ToxPk& friendPk)
{
+ if (historyAccessBlocked()) {
+ return false;
+ }
+
return !getMessagesForFriend(friendPk, 0, 1).empty();
}
@@ -588,6 +588,10 @@ void History::addNewFileMessage(const QString& friendPk, const QString& fileId,
const QString& fileName, const QString& filePath, int64_t size,
const QString& sender, const QDateTime& time, QString const& dispName)
{
+ if (historyAccessBlocked()) {
+ return;
+ }
+
// This is an incredibly far from an optimal way of implementing this,
// but given the frequency that people are going to be initiating a file
// transfer we can probably live with it.
@@ -644,11 +648,7 @@ void History::addNewMessage(const QString& friendPk, const QString& message, con
const QDateTime& time, bool isDelivered, QString dispName,
const std::function& insertIdCallback)
{
- if (!Settings::getInstance().getEnableLogging()) {
- qWarning() << "Blocked a message from being added to database while history is disabled";
- return;
- }
- if (!isValid()) {
+ if (historyAccessBlocked()) {
return;
}
@@ -659,6 +659,10 @@ void History::addNewMessage(const QString& friendPk, const QString& message, con
void History::setFileFinished(const QString& fileId, bool success, const QString& filePath,
const QByteArray& fileHash)
{
+ if (historyAccessBlocked()) {
+ return;
+ }
+
auto& fileInfo = fileInfos[fileId];
if (fileInfo.fileId.get() == -1) {
fileInfo.finished = true;
@@ -674,11 +678,19 @@ void History::setFileFinished(const QString& fileId, bool success, const QString
size_t History::getNumMessagesForFriend(const ToxPk& friendPk)
{
+ if (historyAccessBlocked()) {
+ return 0;
+ }
+
return getNumMessagesForFriendBeforeDate(friendPk, QDateTime());
}
size_t History::getNumMessagesForFriendBeforeDate(const ToxPk& friendPk, const QDateTime& date)
{
+ if (historyAccessBlocked()) {
+ return 0;
+ }
+
QString queryText = QString("SELECT COUNT(history.id) "
"FROM history "
"JOIN peers chat ON chat_id = chat.id "
@@ -704,6 +716,10 @@ size_t History::getNumMessagesForFriendBeforeDate(const ToxPk& friendPk, const Q
QList History::getMessagesForFriend(const ToxPk& friendPk, size_t firstIdx,
size_t lastIdx)
{
+ if (historyAccessBlocked()) {
+ return {};
+ }
+
QList messages;
// Don't forget to update the rowCallback if you change the selected columns!
@@ -763,6 +779,10 @@ QList History::getMessagesForFriend(const ToxPk& friendPk,
QList History::getUndeliveredMessagesForFriend(const ToxPk& friendPk)
{
+ if (historyAccessBlocked()) {
+ return {};
+ }
+
auto queryText =
QString("SELECT history.id, faux_offline_pending.id, timestamp, chat.public_key, "
"aliases.display_name, sender.public_key, message, broken_messages.id "
@@ -809,6 +829,10 @@ QList History::getUndeliveredMessagesForFriend(const ToxPk
QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from,
QString phrase, const ParameterSearch& parameter)
{
+ if (historyAccessBlocked()) {
+ return QDateTime();
+ }
+
QDateTime result;
auto rowCallback = [&result](const QVector& row) {
result = QDateTime::fromMSecsSinceEpoch(row[0].toLongLong());
@@ -903,6 +927,10 @@ QList History::getNumMessagesForFriendBeforeDateBoundaries(con
const QDate& from,
size_t maxNum)
{
+ if (historyAccessBlocked()) {
+ return {};
+ }
+
auto friendPkString = friendPk.toString();
// No guarantee that this is the most efficient way to do this...
@@ -954,9 +982,29 @@ QList History::getNumMessagesForFriendBeforeDateBoundaries(con
*/
void History::markAsDelivered(RowId messageId)
{
- if (!isValid()) {
+ if (historyAccessBlocked()) {
return;
}
db->execLater(QString("DELETE FROM faux_offline_pending WHERE id=%1;").arg(messageId.get()));
}
+
+/**
+* @brief Determines if history access should be blocked
+* @return True if history should not be accessed
+*/
+bool History::historyAccessBlocked()
+{
+ if (!Settings::getInstance().getEnableLogging()) {
+ assert(false);
+ qCritical() << "Blocked history access while history is disabled";
+ return true;
+ }
+
+ if (!isValid()) {
+ return true;
+ }
+
+ return false;
+
+}
diff --git a/src/persistence/history.h b/src/persistence/history.h
index 9c5b10cba..b2b04cfc4 100644
--- a/src/persistence/history.h
+++ b/src/persistence/history.h
@@ -201,6 +201,7 @@ private slots:
void onFileInserted(RowId dbId, QString fileId);
private:
+ bool historyAccessBlocked();
static RawDatabase::Query generateFileFinished(RowId fileId, bool success,
const QString& filePath, const QByteArray& fileHash);
std::shared_ptr db;
diff --git a/src/persistence/offlinemsgengine.cpp b/src/persistence/offlinemsgengine.cpp
index b1cff673b..6026145bf 100644
--- a/src/persistence/offlinemsgengine.cpp
+++ b/src/persistence/offlinemsgengine.cpp
@@ -23,6 +23,7 @@
#include "src/nexus.h"
#include "src/persistence/profile.h"
#include "src/persistence/settings.h"
+#include "src/model/status.h"
#include
#include
#include
@@ -91,7 +92,7 @@ void OfflineMsgEngine::deliverOfflineMsgs()
{
QMutexLocker ml(&mutex);
- if (!f->isOnline()) {
+ if (!Status::isOnline(f->getStatus())) {
return;
}
@@ -138,8 +139,8 @@ void OfflineMsgEngine::removeAllMessages()
void OfflineMsgEngine::completeMessage(QMap::iterator msgIt)
{
msgIt->completionFn();
- sentMessages.erase(msgIt);
receivedReceipts.removeOne(msgIt.key());
+ sentMessages.erase(msgIt);
}
void OfflineMsgEngine::checkForCompleteMessages(ReceiptNum receipt)
diff --git a/src/widget/about/aboutfriendform.cpp b/src/widget/about/aboutfriendform.cpp
index 9a1d36cc0..0ac94de13 100644
--- a/src/widget/about/aboutfriendform.cpp
+++ b/src/widget/about/aboutfriendform.cpp
@@ -92,7 +92,7 @@ void AboutFriendForm::onAutoAcceptDirClicked()
void AboutFriendForm::onAutoAcceptDirChanged(const QString& path)
{
- const bool enabled = path.isNull();
+ const bool enabled = !path.isNull();
ui->autoacceptfile->setChecked(enabled);
ui->selectSaveDir->setEnabled(enabled);
ui->selectSaveDir->setText(enabled ? path : tr("Auto-accept for this contact is disabled"));
diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp
index 992f7e234..acd2997db 100644
--- a/src/widget/form/chatform.cpp
+++ b/src/widget/form/chatform.cpp
@@ -404,7 +404,7 @@ void ChatForm::updateCallButtons()
CoreAV* av = Core::getInstance()->getAv();
const bool audio = av->isCallActive(f);
const bool video = av->isCallVideoEnabled(f);
- const bool online = f->isOnline();
+ const bool online = Status::isOnline(f->getStatus());
headWidget->updateCallButtons(online, audio, video);
updateMuteMicButton();
updateMuteVolButton();
@@ -431,7 +431,7 @@ void ChatForm::onFriendStatusChanged(uint32_t friendId, Status::Status status)
return;
}
- if (!f->isOnline()) {
+ if (!Status::isOnline(f->getStatus())) {
// Hide the "is typing" message when a friend goes offline
setFriendTyping(false);
}
diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp
index dfd35cc6e..2d332fefb 100644
--- a/src/widget/form/genericchatform.cpp
+++ b/src/widget/form/genericchatform.cpp
@@ -980,6 +980,10 @@ void GenericChatForm::searchInBegin(const QString& phrase, const ParameterSearch
return;
}
+ if (messages.size() == 0) {
+ return;
+ }
+
if (chatLog.getNextIdx() == messages.rbegin()->first + 1) {
disableSearchText();
} else {
diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp
index 58e23b027..454afbb92 100644
--- a/src/widget/form/groupchatform.cpp
+++ b/src/widget/form/groupchatform.cpp
@@ -307,7 +307,7 @@ void GroupChatForm::dropEvent(QDropEvent* ev)
int friendId = frnd->getId();
int groupId = group->getId();
- if (frnd->isOnline()) {
+ if (Status::isOnline(frnd->getStatus())) {
Core::getInstance()->groupInviteFriend(friendId, groupId);
}
}
diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp
index 761d84749..956ab0fd8 100644
--- a/src/widget/widget.cpp
+++ b/src/widget/widget.cpp
@@ -1228,7 +1228,7 @@ void Widget::onFriendStatusChanged(int friendId, Status::Status status)
FriendWidget* widget = friendWidgets[f->getPublicKey()];
if (isActualChange) {
- if (!f->isOnline()) {
+ if (!Status::isOnline(f->getStatus())) {
contactListWidget->moveWidget(widget, Status::Status::Online);
} else if (status == Status::Status::Offline) {
contactListWidget->moveWidget(widget, Status::Status::Offline);
diff --git a/test/persistence/offlinemsgengine_test.cpp b/test/persistence/offlinemsgengine_test.cpp
index 22dcdf848..5a421d07c 100644
--- a/test/persistence/offlinemsgengine_test.cpp
+++ b/test/persistence/offlinemsgengine_test.cpp
@@ -19,6 +19,7 @@
#include "src/core/core.h"
#include "src/model/friend.h"
+#include "src/model/status.h"
#include "src/persistence/offlinemsgengine.h"
#include
@@ -35,7 +36,7 @@ public:
}
bool sendMessage(uint32_t friendId, const QString& message, ReceiptNum& receipt) override
{
- if (f->isOnline()) {
+ if (Status::isOnline(f->getStatus())) {
receipt.get() = receiptNum++;
if (!dropReceipts) {
msgs.push_back(message);
@@ -45,7 +46,7 @@ public:
} else {
numMessagesFailed++;
}
- return f->isOnline();
+ return Status::isOnline(f->getStatus());
}
signals: