summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-06-09 16:03:14 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-06-09 16:03:14 +0300
commitb89257a34b2a98b737f4ae544f7e436b9000b240 (patch)
tree81d7f355721541afbd91dc9a085abbb4666f3565 /src
parent1366b01790631ba1134a4dfd03d939b4b40360b8 (diff)
Migrate to mtxclient for the http calls
Diffstat (limited to 'src')
-rw-r--r--src/AvatarProvider.cc50
-rw-r--r--src/Cache.cc112
-rw-r--r--src/ChatPage.cc884
-rw-r--r--src/CommunitiesList.cc61
-rw-r--r--src/Logging.cpp50
-rw-r--r--src/LoginPage.cc69
-rw-r--r--src/MainWindow.cc54
-rw-r--r--src/MatrixClient.cc1371
-rw-r--r--src/RegisterPage.cc130
-rw-r--r--src/RoomList.cc54
-rw-r--r--src/TextInputWidget.cc2
-rw-r--r--src/dialogs/ReCaptcha.cpp15
-rw-r--r--src/dialogs/RoomSettings.cpp80
-rw-r--r--src/main.cc46
-rw-r--r--src/timeline/TimelineItem.cc20
-rw-r--r--src/timeline/TimelineView.cc217
-rw-r--r--src/timeline/TimelineViewManager.cc35
-rw-r--r--src/timeline/widgets/AudioItem.cc32
-rw-r--r--src/timeline/widgets/FileItem.cc44
-rw-r--r--src/timeline/widgets/ImageItem.cc140
-rw-r--r--src/timeline/widgets/VideoItem.cc16
21 files changed, 1400 insertions, 2082 deletions
diff --git a/src/AvatarProvider.cc b/src/AvatarProvider.cc
index 49e52a82..ad095023 100644
--- a/src/AvatarProvider.cc
+++ b/src/AvatarProvider.cc
@@ -16,17 +16,17 @@
*/
#include <QBuffer>
-#include <QtConcurrent>
+#include <memory>
#include "AvatarProvider.h"
#include "Cache.h"
+#include "Logging.hpp"
#include "MatrixClient.h"
+namespace AvatarProvider {
+
void
-AvatarProvider::resolve(const QString &room_id,
- const QString &user_id,
- QObject *receiver,
- std::function<void(QImage)> callback)
+resolve(const QString &room_id, const QString &user_id, QObject *receiver, AvatarCallback callback)
{
const auto key = QString("%1 %2").arg(room_id).arg(user_id);
const auto avatarUrl = Cache::avatarUrl(room_id, user_id);
@@ -43,24 +43,30 @@ AvatarProvider::resolve(const QString &room_id,
return;
}
- auto proxy = http::client()->fetchUserAvatar(avatarUrl);
+ auto proxy = std::make_shared<AvatarProxy>();
+ QObject::connect(proxy.get(),
+ &AvatarProxy::avatarDownloaded,
+ receiver,
+ [callback](const QByteArray &data) { callback(QImage::fromData(data)); });
- if (proxy.isNull())
- return;
+ mtx::http::ThumbOpts opts;
+ opts.mxc_url = avatarUrl.toStdString();
- connect(proxy.data(),
- &DownloadMediaProxy::avatarDownloaded,
- receiver,
- [user_id, proxy, callback, avatarUrl](const QImage &img) {
- proxy->deleteLater();
- QtConcurrent::run([img, avatarUrl]() {
- QByteArray data;
- QBuffer buffer(&data);
- buffer.open(QIODevice::WriteOnly);
- img.save(&buffer, "PNG");
+ http::v2::client()->get_thumbnail(
+ opts,
+ [opts, proxy = std::move(proxy)](const std::string &res, mtx::http::RequestErr err) {
+ if (err) {
+ log::net()->warn("failed to download avatar: {} - ({} {})",
+ opts.mxc_url,
+ mtx::errors::to_string(err->matrix_error.errcode),
+ err->matrix_error.error);
+ return;
+ }
- cache::client()->saveImage(avatarUrl, data);
- });
- callback(img);
- });
+ cache::client()->saveImage(opts.mxc_url, res);
+
+ auto data = QByteArray(res.data(), res.size());
+ emit proxy->avatarDownloaded(data);
+ });
+}
}
diff --git a/src/Cache.cc b/src/Cache.cc
index c055ab05..2a555425 100644
--- a/src/Cache.cc
+++ b/src/Cache.cc
@@ -19,7 +19,6 @@
#include <stdexcept>
#include <QByteArray>
-#include <QDebug>
#include <QFile>
#include <QHash>
#include <QStandardPaths>
@@ -27,6 +26,7 @@
#include <variant.hpp>
#include "Cache.h"
+#include "Logging.hpp"
#include "Utils.h"
//! Should be changed when a breaking change occurs in the cache format.
@@ -62,6 +62,14 @@ namespace cache {
void
init(const QString &user_id)
{
+ qRegisterMetaType<SearchResult>();
+ qRegisterMetaType<QVector<SearchResult>>();
+ qRegisterMetaType<RoomMember>();
+ qRegisterMetaType<RoomSearchResult>();
+ qRegisterMetaType<RoomInfo>();
+ qRegisterMetaType<QMap<QString, RoomInfo>>();
+ qRegisterMetaType<std::map<QString, RoomInfo>>();
+
if (!instance_)
instance_ = std::make_unique<Cache>(user_id);
}
@@ -88,7 +96,7 @@ Cache::Cache(const QString &userId, QObject *parent)
void
Cache::setup()
{
- qDebug() << "Setting up cache";
+ log::db()->debug("setting up cache");
auto statePath = QString("%1/%2/state")
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
@@ -105,7 +113,7 @@ Cache::setup()
env_.set_max_dbs(1024UL);
if (isInitial) {
- qDebug() << "First time initializing LMDB";
+ log::db()->info("initializing LMDB");
if (!QDir().mkpath(statePath)) {
throw std::runtime_error(
@@ -121,7 +129,7 @@ Cache::setup()
std::string(e.what()));
}
- qWarning() << "Resetting cache due to LMDB version mismatch:" << e.what();
+ log::db()->warn("resetting cache due to LMDB version mismatch: {}", e.what());
QDir stateDir(statePath);
@@ -142,29 +150,34 @@ Cache::setup()
readReceiptsDb_ = lmdb::dbi::open(txn, READ_RECEIPTS_DB, MDB_CREATE);
notificationsDb_ = lmdb::dbi::open(txn, NOTIFICATIONS_DB, MDB_CREATE);
txn.commit();
-
- qRegisterMetaType<RoomInfo>();
}
void
-Cache::saveImage(const QString &url, const QByteArray &image)
+Cache::saveImage(const std::string &url, const std::string &img_data)
{
- auto key = url.toUtf8();
+ if (url.empty() || img_data.empty())
+ return;
try {
auto txn = lmdb::txn::begin(env_);
lmdb::dbi_put(txn,
mediaDb_,
- lmdb::val(key.data(), key.size()),
- lmdb::val(image.data(), image.size()));
+ lmdb::val(url.data(), url.size()),
+ lmdb::val(img_data.data(), img_data.size()));
txn.commit();
} catch (const lmdb::error &e) {
- qCritical() << "saveImage:" << e.what();
+ log::db()->critical("saveImage: {}", e.what());
}
}
+void
+Cache::saveImage(const QString &url, const QByteArray &image)
+{
+ saveImage(url.toStdString(), std::string(image.constData(), image.length()));
+}
+
QByteArray
Cache::image(lmdb::txn &txn, const std::string &url) const
{
@@ -180,7 +193,7 @@ Cache::image(lmdb::txn &txn, const std::string &url) const
return QByteArray(image.data(), image.size());
} catch (const lmdb::error &e) {
- qCritical() << "image:" << e.what() << QString::fromStdString(url);
+ log::db()->critical("image: {}, {}", e.what(), url);
}
return QByteArray();
@@ -208,7 +221,7 @@ Cache::image(const QString &url) const
return QByteArray(image.data(), image.size());
} catch (const lmdb::error &e) {
- qCritical() << "image:" << e.what() << url;
+ log::db()->critical("image: {} {}", e.what(), url.toStdString());
}
return QByteArray();
@@ -271,7 +284,7 @@ Cache::isInitialized() const
return res;
}
-QString
+std::string
Cache::nextBatchToken() const
{
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
@@ -281,13 +294,13 @@ Cache::nextBatchToken() const
txn.commit();
- return QString::fromUtf8(token.data(), token.size());
+ return std::string(token.data(), token.size());
}
void
Cache::deleteData()
{
- qInfo() << "Deleting cache data";
+ log::db()->info("deleting data");
if (!cacheDirectory_.isEmpty())
QDir(cacheDirectory_).removeRecursively();
@@ -309,8 +322,9 @@ Cache::isFormatValid()
std::string stored_version(current_version.data(), current_version.size());
if (stored_version != CURRENT_CACHE_FORMAT_VERSION) {
- qWarning() << "Stored format version" << QString::fromStdString(stored_version);
- qWarning() << "There are breaking changes in the cache format.";
+ log::db()->warn("breaking changes in the cache format. stored: {}, current: {}",
+ stored_version,
+ CURRENT_CACHE_FORMAT_VERSION);
return false;
}
@@ -360,7 +374,7 @@ Cache::readReceipts(const QString &event_id, const QString &room_id)
}
} catch (const lmdb::error &e) {
- qCritical() << "readReceipts:" << e.what();
+ log::db()->critical("readReceipts: {}", e.what());
}
return receipts;
@@ -410,7 +424,7 @@ Cache::updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Recei
lmdb::val(merged_receipts.data(), merged_receipts.size()));
} catch (const lmdb::error &e) {
- qCritical() << "updateReadReceipts:" << e.what();
+ log::db()->critical("updateReadReceipts: {}", e.what());
}
}
}
@@ -568,9 +582,9 @@ Cache::singleRoomInfo(const std::string &room_id)
return tmp;
} catch (const json::exception &e) {
- qWarning()
- << "failed to parse room info:" << QString::fromStdString(room_id)
- << QString::fromStdString(std::string(data.data(), data.size()));
+ log::db()->warn("failed to parse room info: room_id ({}), {}",
+ room_id,
+ std::string(data.data(), data.size()));
}
}
@@ -600,9 +614,9 @@ Cache::getRoomInfo(const std::vector<std::string> &rooms)
room_info.emplace(QString::fromStdString(room), std::move(tmp));
} catch (const json::exception &e) {
- qWarning()
- << "failed to parse room info:" << QString::fromStdString(room)
- << QString::fromStdString(std::string(data.data(), data.size()));
+ log::db()->warn("failed to parse room info: room_id ({}), {}",
+ room,
+ std::string(data.data(), data.size()));
}
} else {
// Check if the room is an invite.
@@ -615,10 +629,10 @@ Cache::getRoomInfo(const std::vector<std::string> &rooms)
room_info.emplace(QString::fromStdString(room),
std::move(tmp));
} catch (const json::exception &e) {
- qWarning() << "failed to parse room info for invite:"
- << QString::fromStdString(room)
- << QString::fromStdString(
- std::string(data.data(), data.size()));
+ log::db()->warn(
+ "failed to parse room info for invite: room_id ({}), {}",
+ room,
+ std::string(data.data(), data.size()));
}
}
}
@@ -703,7 +717,7 @@ Cache::getRoomAvatarUrl(lmdb::txn &txn,
return QString::fromStdString(msg.content.url);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse m.room.avatar event: {}", e.what());
}
}
@@ -726,7 +740,7 @@ Cache::getRoomAvatarUrl(lmdb::txn &txn,
cursor.close();
return QString::fromStdString(m.avatar_url);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse member info: {}", e.what());
}
}
@@ -753,7 +767,7 @@ Cache::getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
if (!msg.content.name.empty())
return QString::fromStdString(msg.content.name);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse m.room.name event: {}", e.what());
}
}
@@ -768,7 +782,8 @@ Cache::getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
if (!msg.content.alias.empty())
return QString::fromStdString(msg.content.alias);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse m.room.canonical_alias event: {}",
+ e.what());
}
}
@@ -784,7 +799,7 @@ Cache::getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
try {
members.emplace(user_id, json::parse(member_data));
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse member info: {}", e.what());
}
ii++;
@@ -828,7 +843,7 @@ Cache::getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb)
json::parse(std::string(event.data(), event.size()));
return msg.content.join_rule;
} catch (const json::exception &e) {
- qWarning() << e.what();
+ log::db()->warn("failed to parse m.room.join_rule event: {}", e.what());
}
}
return JoinRule::Knock;
@@ -850,7 +865,7 @@ Cache::getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb)
json::parse(std::string(event.data(), event.size()));
return msg.content.guest_access == AccessState::CanJoin;
} catch (const json::exception &e) {
- qWarning() << e.what();
+ log::db()->warn("failed to parse m.room.guest_access event: {}", e.what());
}
}
return false;
@@ -874,7 +889,7 @@ Cache::getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb)
if (!msg.content.topic.empty())
return QString::fromStdString(msg.content.topic);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse m.room.topic event: {}", e.what());
}
}
@@ -897,7 +912,7 @@ Cache::getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &members
json::parse(std::string(event.data(), event.size()));
return QString::fromStdString(msg.content.name);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse m.room.name event: {}", e.what());
}
}
@@ -914,7 +929,7 @@ Cache::getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &members
return QString::fromStdString(tmp.name);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse member info: {}", e.what());
}
}
@@ -939,7 +954,7 @@ Cache::getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &me
json::parse(std::string(event.data(), event.size()));
return QString::fromStdString(msg.content.url);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse m.room.avatar event: {}", e.what());
}
}
@@ -956,7 +971,7 @@ Cache::getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &me
return QString::fromStdString(tmp.avatar_url);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse member info: {}", e.what());
}
}
@@ -981,7 +996,7 @@ Cache::getInviteRoomTopic(lmdb::txn &txn, lmdb::dbi &db)
json::parse(std::string(event.data(), event.size()));
return QString::fromStdString(msg.content.topic);
} catch (const json::exception &e) {
- qWarning() << QString::fromStdString(e.what());
+ log::db()->warn("failed to parse m.room.topic event: {}", e.what());
}
}
@@ -1017,8 +1032,9 @@ Cache::getRoomAvatar(const std::string &room_id)
return QImage();
}
} catch (const json::exception &e) {
- qWarning() << "failed to parse room info" << e.what()
- << QString::fromStdString(std::string(response.data(), response.size()));
+ log::db()->warn("failed to parse room info: {}, {}",
+ e.what(),
+ std::string(response.data(), response.size()));
}
if (!lmdb::dbi_get(txn, mediaDb_, lmdb::val(media_url), response)) {
@@ -1054,7 +1070,7 @@ void
Cache::populateMembers()
{
auto rooms = joinedRooms();
- qDebug() << "loading" << rooms.size() << "rooms";
+ log::db()->info("loading {} rooms", rooms.size());
auto txn = lmdb::txn::begin(env_);
@@ -1182,7 +1198,7 @@ Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_
QString::fromStdString(tmp.name),
QImage::fromData(image(txn, tmp.avatar_url))});
} catch (const json::exception &e) {
- qWarning() << e.what();
+ log::db()->warn("{}", e.what());
}
currentIndex += 1;
@@ -1253,7 +1269,7 @@ Cache::hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes
std::min(min_event_level,
(uint16_t)msg.content.state_level(to_string(ty)));
} catch (const json::exception &e) {
- qWarning() << "hasEnoughPowerLevel: " << e.what();
+ log::db()->warn("failed to parse m.room.power_levels event: {}", e.what());
}
}
diff --git a/src/ChatPage.cc b/src/ChatPage.cc
index 9ae860fb..64ce69d6 100644
--- a/src/ChatPage.cc
+++ b/src/ChatPage.cc
@@ -16,13 +16,13 @@
*/
#include <QApplication>
-#include <QDebug>
#include <QSettings>
#include <QtConcurrent>
#include "AvatarProvider.h"
#include "Cache.h"
#include "ChatPage.h"
+#include "Logging.hpp"
#include "MainWindow.h"
#include "MatrixClient.h"
#include "OverlayModal.h"
@@ -43,13 +43,12 @@
#include "dialogs/ReadReceipts.h"
#include "timeline/TimelineViewManager.h"
-constexpr int SYNC_RETRY_TIMEOUT = 40 * 1000;
-constexpr int INITIAL_SYNC_RETRY_TIMEOUT = 240 * 1000;
-
-ChatPage *ChatPage::instance_ = nullptr;
+ChatPage *ChatPage::instance_ = nullptr;
+constexpr int CHECK_CONNECTIVITY_INTERVAL = 15'000;
ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
: QWidget(parent)
+ , isConnected_(true)
, userSettings_{userSettings}
{
setObjectName("chatPage");
@@ -78,13 +77,12 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
sidebarActions_ = new SideBarActions(this);
connect(
sidebarActions_, &SideBarActions::showSettings, this, &ChatPage::showUserSettingsPage);
- connect(
- sidebarActions_, &SideBarActions::joinRoom, http::client(), &MatrixClient::joinRoom);
- connect(
- sidebarActions_, &SideBarActions::createRoom, http::client(), &MatrixClient::createRoom);
+ connect(sidebarActions_, &SideBarActions::joinRoom, this, &ChatPage::joinRoom);
+ connect(sidebarActions_, &SideBarActions::createRoom, this, &ChatPage::createRoom);
user_info_widget_ = new UserInfoWidget(sideBar_);
room_list_ = new RoomList(userSettings_, sideBar_);
+ connect(room_list_, &RoomList::joinRoom, this, &ChatPage::joinRoom);
sideBarLayout_->addWidget(user_info_widget_);
sideBarLayout_->addWidget(room_list_);
@@ -107,6 +105,11 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
contentLayout_->addWidget(top_bar_);
contentLayout_->addWidget(view_manager_);
+ connect(this,
+ &ChatPage::removeTimelineEvent,
+ view_manager_,
+ &TimelineViewManager::removeTimelineEvent);
+
// Splitter
splitter->addWidget(sideBar_);
splitter->addWidget(content_);
@@ -120,16 +123,81 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
typingRefresher_ = new QTimer(this);
typingRefresher_->setInterval(TYPING_REFRESH_TIMEOUT);
+ connect(this, &ChatPage::connectionLost, this, [this]() {
+ log::net()->info("connectivity lost");
+ isConnected_ = false;
+ http::v2::client()->shutdown();
+ text_input_->disableInput();
+ });
+ connect(this, &ChatPage::connectionRestored, this, [this]() {
+ log::net()->info("trying to re-connect");
+ text_input_->enableInput();
+ isConnected_ = true;
+
+ // Drop all pending connections.
+ http::v2::client()->shutdown();
+ trySync();
+ });
+
+ connectivityTimer_.setInterval(CHECK_CONNECTIVITY_INTERVAL);
+ connect(&connectivityTimer_, &QTimer::timeout, this, [=]() {
+ if (http::v2::client()->access_token().empty()) {
+ connectivityTimer_.stop();
+ return;
+ }
+
+ http::v2::client()->versions(
+ [this](const mtx::responses::Versions &, mtx::http::RequestErr err) {
+ if (err) {
+ emit connectionLost();
+ return;
+ }
+
+ if (!isConnected_)
+ emit connectionRestored();
+ });
+ });
+
+ connect(this, &ChatPage::loggedOut, this, &ChatPage::logout);
connect(user_info_widget_, &UserInfoWidget::logout, this, [this]() {
- http::client()->logout();
+ http::v2::client()->logout([this](const mtx::responses::Logout &,
+ mtx::http::RequestErr err) {
+ if (err) {
+ // TODO: handle special errors
+ emit contentLoaded();
+ log::net()->warn("failed to logout: {} - {}",
+ mtx::errors::to_string(err->matrix_error.errcode),
+ err->matrix_error.error);
+ return;
+ }
+
+ emit loggedOut();
+ });
+
emit showOverlayProgressBar();
});
- connect(http::client(), &MatrixClient::loggedOut, this, &ChatPage::logout);
connect(top_bar_, &TopRoomBar::inviteUsers, this, [this](QStringList users) {
+ const auto room_id = current_room_.toStdString();
+
for (int ii = 0; ii < users.size(); ++ii) {
- QTimer::singleShot(ii * 1000, this, [this, ii, users]() {
- http::client()->inviteUser(current_room_, users.at(ii));
+ QTimer::singleShot(ii * 500, this, [this, room_id, ii, users]() {
+ const auto user = users.at(ii);
+
+ http::v2::client()->invite_user(
+ room_id,
+ user.toStdString(),
+ [this, user](const mtx::responses::RoomInvite &,
+ mtx::http::RequestErr err) {
+ if (err) {
+ emit showNotification(
+ QString("Failed to invite user: %1").arg(user));
+ return;
+ }
+
+ emit showNotification(
+ QString("Invited user: %1").arg(user));
+ });
});
}
});
@@ -155,36 +223,30 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
connect(room_list_, &RoomList::acceptInvite, this, [this](const QString &room_id) {
view_manager_->addRoom(room_id);
- http::client()->joinRoom(room_id);
+ joinRoom(room_id);
room_list_->removeRoom(room_id, currentRoom() == room_id);
});
connect(room_list_, &RoomList::declineInvite, this, [this](const QString &room_id) {
- http::client()->leaveRoom(room_id);
+ leaveRoom(room_id);
room_list_->removeRoom(room_id, currentRoom() == room_id);
});
- connect(text_input_, &TextInputWidget::startedTyping, this, [this]() {
- if (!userSettings_->isTypingNotificationsEnabled())
- return;
-
- typingRefresher_->start();
- http::client()->sendTypingNotification(current_room_);
- });
-
+ connect(
+ text_input_, &TextInputWidget::startedTyping, this, &ChatPage::sendTypingNotifications);
+ connect(typingRefresher_, &QTimer::timeout, this, &ChatPage::sendTypingNotifications);
connect(text_input_, &TextInputWidget::stoppedTyping, this, [this]() {
if (!userSettings_->isTypingNotificationsEnabled())
return;
typingRefresher_->stop();
- http::client()->removeTypingNotification(current_room_);
- });
-
- connect(typingRefresher_, &QTimer::timeout, this, [this]() {
- if (!userSettings_->isTypingNotificationsEnabled())
- return;
-
- http::client()->sendTypingNotification(current_room_);
+ http::v2::client()->stop_typing(
+ current_room_.toStdString(), [](mtx::http::RequestErr err) {
+ if (err) {
+ log::net()->warn("failed to stop typing notifications: {}",
+ err->matrix_error.error);
+ }
+ });
});
connect(view_manager_,
@@ -207,142 +269,242 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
view_manager_,
SLOT(queueEmoteMessage(const QString &)));
- connect(text_input_,
- &TextInputWidget::sendJoinRoomRequest,
- http::client(),
- &MatrixClient::joinRoom);
+ connect(text_input_, &TextInputWidget::sendJoinRoomRequest, this, &ChatPage::joinRoom);
connect(text_input_,
&TextInputWidget::uploadImage,
this,
- [this](QSharedPointer<QIODevice> data, const QString &fn) {
- http::client()->uploadImage(current_room_, fn, data);
+ [this](QSharedPointer<QIODevice> dev, const QString &fn) {
+ QMimeDatabase db;
+ QMimeType mime = db.mimeTypeForData(dev.data());
+
+ if (!dev->open(QIODevice::ReadOnly)) {
+ emit uploadFailed(
+ QString("Error while reading media: %1").arg(dev->errorString()));
+ return;
+ }
+
+ auto bin = dev->readAll();
+ auto payload = std::string(bin.data(), bin.size());
+
+ http::v2::client()->upload(
+ payload,
+ mime.name().toStdString(),
+ QFileInfo(fn).fileName().toStdString(),
+ [this,
+ room_id = current_room_,
+ filename = fn,
+ mime = mime.name(),
+ size = payload.size()](const mtx::responses::ContentURI &res,
+ mtx::http::RequestErr err) {
+ if (err) {
+ emit uploadFailed(
+ tr("Failed to upload im