|
|
|
@ -8,164 +8,170 @@ |
|
|
|
|
#include <algorithm> |
|
|
|
|
|
|
|
|
|
RoomDirectoryModel::RoomDirectoryModel(QObject *parent, const std::string &s) |
|
|
|
|
: QAbstractListModel(parent) |
|
|
|
|
, server_(s) |
|
|
|
|
, canFetchMore_(true) |
|
|
|
|
: QAbstractListModel(parent) |
|
|
|
|
, server_(s) |
|
|
|
|
, canFetchMore_(true) |
|
|
|
|
{ |
|
|
|
|
connect(this, &RoomDirectoryModel::fetchedRoomsBatch, this, &RoomDirectoryModel::displayRooms, Qt::QueuedConnection);
|
|
|
|
|
connect(this, |
|
|
|
|
&RoomDirectoryModel::fetchedRoomsBatch, |
|
|
|
|
this, |
|
|
|
|
&RoomDirectoryModel::displayRooms, |
|
|
|
|
Qt::QueuedConnection); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QHash<int, QByteArray> |
|
|
|
|
RoomDirectoryModel::roleNames() const |
|
|
|
|
{ |
|
|
|
|
return { |
|
|
|
|
{Roles::Name, "name"}, |
|
|
|
|
{Roles::Id, "roomid"}, |
|
|
|
|
{Roles::AvatarUrl, "avatarUrl"}, |
|
|
|
|
{Roles::Topic, "topic"}, |
|
|
|
|
{Roles::MemberCount, "numMembers"}, |
|
|
|
|
{Roles::Previewable, "canPreview"},}; |
|
|
|
|
return { |
|
|
|
|
{Roles::Name, "name"}, |
|
|
|
|
{Roles::Id, "roomid"}, |
|
|
|
|
{Roles::AvatarUrl, "avatarUrl"}, |
|
|
|
|
{Roles::Topic, "topic"}, |
|
|
|
|
{Roles::MemberCount, "numMembers"}, |
|
|
|
|
{Roles::Previewable, "canPreview"}, |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
RoomDirectoryModel::resetDisplayedData() |
|
|
|
|
{ |
|
|
|
|
beginResetModel(); |
|
|
|
|
beginResetModel(); |
|
|
|
|
|
|
|
|
|
prevBatch_ = ""; |
|
|
|
|
nextBatch_ = ""; |
|
|
|
|
canFetchMore_ = true; |
|
|
|
|
prevBatch_ = ""; |
|
|
|
|
nextBatch_ = ""; |
|
|
|
|
canFetchMore_ = true; |
|
|
|
|
|
|
|
|
|
beginRemoveRows(QModelIndex(), 0 , static_cast<int> (publicRoomsData_.size())); |
|
|
|
|
publicRoomsData_.clear(); |
|
|
|
|
endRemoveRows(); |
|
|
|
|
beginRemoveRows(QModelIndex(), 0, static_cast<int>(publicRoomsData_.size())); |
|
|
|
|
publicRoomsData_.clear(); |
|
|
|
|
endRemoveRows(); |
|
|
|
|
|
|
|
|
|
endResetModel(); |
|
|
|
|
endResetModel(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
RoomDirectoryModel::setMatrixServer(const QString &s) |
|
|
|
|
{ |
|
|
|
|
server_ = s.toStdString(); |
|
|
|
|
server_ = s.toStdString(); |
|
|
|
|
|
|
|
|
|
nhlog::ui()->debug("Received matrix server: {}", server_); |
|
|
|
|
nhlog::ui()->debug("Received matrix server: {}", server_); |
|
|
|
|
|
|
|
|
|
resetDisplayedData(); |
|
|
|
|
resetDisplayedData(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
RoomDirectoryModel::setSearchTerm(const QString &f) |
|
|
|
|
{ |
|
|
|
|
userSearchString_ = f.toStdString(); |
|
|
|
|
userSearchString_ = f.toStdString(); |
|
|
|
|
|
|
|
|
|
nhlog::ui()->debug("Received user query: {}", userSearchString_); |
|
|
|
|
nhlog::ui()->debug("Received user query: {}", userSearchString_); |
|
|
|
|
|
|
|
|
|
resetDisplayedData(); |
|
|
|
|
resetDisplayedData(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<std::string> |
|
|
|
|
RoomDirectoryModel::getViasForRoom(const std::vector<std::string> &aliases) |
|
|
|
|
{ |
|
|
|
|
std::vector<std::string> vias; |
|
|
|
|
std::vector<std::string> vias; |
|
|
|
|
|
|
|
|
|
vias.reserve(aliases.size()); |
|
|
|
|
vias.reserve(aliases.size()); |
|
|
|
|
|
|
|
|
|
std::transform(aliases.begin(), aliases.end(),
|
|
|
|
|
std::back_inserter(vias), [](const auto &alias) { |
|
|
|
|
const auto roomAliasDelimiter = ":"; |
|
|
|
|
return alias.substr(alias.find(roomAliasDelimiter) + 1); |
|
|
|
|
}); |
|
|
|
|
std::transform( |
|
|
|
|
aliases.begin(), aliases.end(), std::back_inserter(vias), [](const auto &alias) { |
|
|
|
|
const auto roomAliasDelimiter = ":"; |
|
|
|
|
return alias.substr(alias.find(roomAliasDelimiter) + 1); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return vias; |
|
|
|
|
return vias; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
RoomDirectoryModel::joinRoom(const int &index) |
|
|
|
|
{ |
|
|
|
|
if (index >= 0 && static_cast<size_t> (index) < publicRoomsData_.size()) |
|
|
|
|
{ |
|
|
|
|
const auto &chunk = publicRoomsData_[index]; |
|
|
|
|
nhlog::ui()->debug("'Joining room {}", chunk.room_id); |
|
|
|
|
ChatPage::instance()->joinRoomVia(chunk.room_id, getViasForRoom(chunk.aliases)); |
|
|
|
|
} |
|
|
|
|
if (index >= 0 && static_cast<size_t>(index) < publicRoomsData_.size()) { |
|
|
|
|
const auto &chunk = publicRoomsData_[index]; |
|
|
|
|
nhlog::ui()->debug("'Joining room {}", chunk.room_id); |
|
|
|
|
ChatPage::instance()->joinRoomVia(chunk.room_id, getViasForRoom(chunk.aliases)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QVariant |
|
|
|
|
RoomDirectoryModel::data(const QModelIndex &index, int role) const |
|
|
|
|
{ |
|
|
|
|
if (hasIndex(index.row(), index.column(), index.parent()))
|
|
|
|
|
{ |
|
|
|
|
const auto &room_chunk = publicRoomsData_[index.row()];
|
|
|
|
|
switch (role) |
|
|
|
|
{ |
|
|
|
|
case Roles::Name: |
|
|
|
|
return QString::fromStdString(room_chunk.name);
|
|
|
|
|
case Roles::Id: |
|
|
|
|
return QString::fromStdString(room_chunk.room_id); |
|
|
|
|
case Roles::AvatarUrl: |
|
|
|
|
return QString::fromStdString(room_chunk.avatar_url); |
|
|
|
|
case Roles::Topic: |
|
|
|
|
return QString::fromStdString(room_chunk.topic); |
|
|
|
|
case Roles::MemberCount: |
|
|
|
|
return QVariant::fromValue(room_chunk.num_joined_members); |
|
|
|
|
case Roles::Previewable: |
|
|
|
|
return QVariant::fromValue(room_chunk.world_readable); |
|
|
|
|
if (hasIndex(index.row(), index.column(), index.parent())) { |
|
|
|
|
const auto &room_chunk = publicRoomsData_[index.row()]; |
|
|
|
|
switch (role) { |
|
|
|
|
case Roles::Name: |
|
|
|
|
return QString::fromStdString(room_chunk.name); |
|
|
|
|
case Roles::Id: |
|
|
|
|
return QString::fromStdString(room_chunk.room_id); |
|
|
|
|
case Roles::AvatarUrl: |
|
|
|
|
return QString::fromStdString(room_chunk.avatar_url); |
|
|
|
|
case Roles::Topic: |
|
|
|
|
return QString::fromStdString(room_chunk.topic); |
|
|
|
|
case Roles::MemberCount: |
|
|
|
|
return QVariant::fromValue(room_chunk.num_joined_members); |
|
|
|
|
case Roles::Previewable: |
|
|
|
|
return QVariant::fromValue(room_chunk.world_readable); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return {}; |
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
RoomDirectoryModel::fetchMore(const QModelIndex &) |
|
|
|
|
{ |
|
|
|
|
nhlog::net()->debug("Fetching more rooms from mtxclient..."); |
|
|
|
|
nhlog::net()->debug("Prev batch: {} | Next batch: {}", prevBatch_, nextBatch_); |
|
|
|
|
|
|
|
|
|
mtx::requests::PublicRooms req; |
|
|
|
|
req.limit = limit_; |
|
|
|
|
req.since = prevBatch_; |
|
|
|
|
req.filter.generic_search_term = userSearchString_; |
|
|
|
|
// req.third_party_instance_id = third_party_instance_id;
|
|
|
|
|
auto requested_server = server_; |
|
|
|
|
|
|
|
|
|
http::client()->post_public_rooms(req, [requested_server, this, req] |
|
|
|
|
(const mtx::responses::PublicRooms &res,
|
|
|
|
|
mtx::http::RequestErr err)
|
|
|
|
|
{ |
|
|
|
|
if (err) { |
|
|
|
|
nhlog::net()->error |
|
|
|
|
("Failed to retrieve rooms from mtxclient - {} - {} - {}", |
|
|
|
|
mtx::errors::to_string(err->matrix_error.errcode), |
|
|
|
|
err->matrix_error.error, |
|
|
|
|
err->parse_error); |
|
|
|
|
} else if ( req.filter.generic_search_term == this->userSearchString_ |
|
|
|
|
&& req.since == this->prevBatch_ |
|
|
|
|
&& requested_server == this->server_) { |
|
|
|
|
nhlog::net()->debug("signalling chunk to GUI thread"); |
|
|
|
|
emit fetchedRoomsBatch(res.chunk, res.prev_batch, res.next_batch);
|
|
|
|
|
} |
|
|
|
|
}, requested_server); |
|
|
|
|
nhlog::net()->debug("Fetching more rooms from mtxclient..."); |
|
|
|
|
nhlog::net()->debug("Prev batch: {} | Next batch: {}", prevBatch_, nextBatch_); |
|
|
|
|
|
|
|
|
|
mtx::requests::PublicRooms req; |
|
|
|
|
req.limit = limit_; |
|
|
|
|
req.since = prevBatch_; |
|
|
|
|
req.filter.generic_search_term = userSearchString_; |
|
|
|
|
// req.third_party_instance_id = third_party_instance_id;
|
|
|
|
|
auto requested_server = server_; |
|
|
|
|
|
|
|
|
|
http::client()->post_public_rooms( |
|
|
|
|
req, |
|
|
|
|
[requested_server, this, req](const mtx::responses::PublicRooms &res, |
|
|
|
|
mtx::http::RequestErr err) { |
|
|
|
|
if (err) { |
|
|
|
|
nhlog::net()->error( |
|
|
|
|
"Failed to retrieve rooms from mtxclient - {} - {} - {}", |
|
|
|
|
mtx::errors::to_string(err->matrix_error.errcode), |
|
|
|
|
err->matrix_error.error, |
|
|
|
|
err->parse_error); |
|
|
|
|
} else if (req.filter.generic_search_term == this->userSearchString_ && |
|
|
|
|
req.since == this->prevBatch_ && requested_server == this->server_) { |
|
|
|
|
nhlog::net()->debug("signalling chunk to GUI thread"); |
|
|
|
|
emit fetchedRoomsBatch(res.chunk, res.prev_batch, res.next_batch); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
requested_server); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
RoomDirectoryModel::displayRooms(std::vector<mtx::responses::PublicRoomsChunk> fetched_rooms, |
|
|
|
|
const std::string &prev_batch, const std::string &next_batch) |
|
|
|
|
const std::string &prev_batch, |
|
|
|
|
const std::string &next_batch) |
|
|
|
|
{ |
|
|
|
|
nhlog::net()->debug("Prev batch: {} | Next batch: {}", prevBatch_, nextBatch_); |
|
|
|
|
nhlog::net()->debug("NP batch: {} | NN batch: {}", prev_batch, next_batch); |
|
|
|
|
nhlog::net()->debug("Prev batch: {} | Next batch: {}", prevBatch_, nextBatch_); |
|
|
|
|
nhlog::net()->debug("NP batch: {} | NN batch: {}", prev_batch, next_batch); |
|
|
|
|
|
|
|
|
|
if (fetched_rooms.empty()) { |
|
|
|
|
nhlog::net()->error("mtxclient helper thread yielded empty chunk!"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (fetched_rooms.empty()) { |
|
|
|
|
nhlog::net()->error("mtxclient helper thread yielded empty chunk!"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
beginInsertRows(QModelIndex(), static_cast<int> (publicRoomsData_.size()), static_cast<int> (publicRoomsData_.size() + fetched_rooms.size()) - 1); |
|
|
|
|
this->publicRoomsData_.insert(this->publicRoomsData_.end(), fetched_rooms.begin(), fetched_rooms.end()); |
|
|
|
|
endInsertRows(); |
|
|
|
|
beginInsertRows(QModelIndex(), |
|
|
|
|
static_cast<int>(publicRoomsData_.size()), |
|
|
|
|
static_cast<int>(publicRoomsData_.size() + fetched_rooms.size()) - 1); |
|
|
|
|
this->publicRoomsData_.insert( |
|
|
|
|
this->publicRoomsData_.end(), fetched_rooms.begin(), fetched_rooms.end()); |
|
|
|
|
endInsertRows(); |
|
|
|
|
|
|
|
|
|
if (next_batch.empty()) { |
|
|
|
|
canFetchMore_ = false; |
|
|
|
|
} |
|
|
|
|
if (next_batch.empty()) { |
|
|
|
|
canFetchMore_ = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
prevBatch_ = std::exchange(nextBatch_, next_batch); |
|
|
|
|
prevBatch_ = std::exchange(nextBatch_, next_batch); |
|
|
|
|
} |