diff --git a/CMakeLists.txt b/CMakeLists.txt
index ac07562f..ef57e213 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -420,6 +420,8 @@ set(SRC_FILES
src/dock/Dock.cpp
src/dock/Dock.h
+ src/AliasEditModel.cpp
+ src/AliasEditModel.h
src/AvatarProvider.cpp
src/AvatarProvider.h
src/BlurhashProvider.cpp
@@ -579,7 +581,7 @@ if(USE_BUNDLED_MTXCLIENT)
FetchContent_Declare(
MatrixClient
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
- GIT_TAG e93779692fcc00de136234dd48d0af354717b0a1
+ GIT_TAG 842e10c4ae36aba23a20849e766f0c54b19fd4b6
)
set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
diff --git a/io.github.NhekoReborn.Nheko.yaml b/io.github.NhekoReborn.Nheko.yaml
index db3ecbed..3d7b7d39 100644
--- a/io.github.NhekoReborn.Nheko.yaml
+++ b/io.github.NhekoReborn.Nheko.yaml
@@ -203,7 +203,7 @@ modules:
buildsystem: cmake-ninja
name: mtxclient
sources:
- - commit: e93779692fcc00de136234dd48d0af354717b0a1
+ - commit: 842e10c4ae36aba23a20849e766f0c54b19fd4b6
#tag: v0.7.0
type: git
url: https://github.com/Nheko-Reborn/mtxclient.git
diff --git a/resources/icons/ui/building-shop.svg b/resources/icons/ui/building-shop.svg
new file mode 100644
index 00000000..32e1d9d9
--- /dev/null
+++ b/resources/icons/ui/building-shop.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/resources/icons/ui/room-directory.svg b/resources/icons/ui/room-directory.svg
new file mode 100644
index 00000000..30820243
--- /dev/null
+++ b/resources/icons/ui/room-directory.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml
index f3509f06..a86ca725 100644
--- a/resources/qml/RoomList.qml
+++ b/resources/qml/RoomList.qml
@@ -750,7 +750,7 @@ Page {
hoverEnabled: true
width: 22
height: 22
- image: ":/icons/icons/ui/speech-bubbles.svg"
+ image: ":/icons/icons/ui/room-directory.svg"
ToolTip.visible: hovered
ToolTip.delay: Nheko.tooltipDelay
ToolTip.text: qsTr("Room directory")
diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index 1ea26742..7cc41db9 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -55,13 +55,28 @@ Pane {
}
- function showPLEditor(settings) {
- var dialog = plEditor.createObject(timelineRoot, {
- "roomSettings": settings
- });
- dialog.show();
- destroyOnClose(dialog);
+ function showAliasEditor(settings) {
+ var dialog = aliasEditor.createObject(timelineRoot, {
+ "roomSettings": settings
+ });
+ dialog.show();
+ destroyOnClose(dialog);
+ }
+
+ Component {
+ id: aliasEditor
+
+ AliasEditor {
}
+ }
+
+ function showPLEditor(settings) {
+ var dialog = plEditor.createObject(timelineRoot, {
+ "roomSettings": settings
+ });
+ dialog.show();
+ destroyOnClose(dialog);
+ }
Component {
id: plEditor
diff --git a/resources/qml/dialogs/AliasEditor.qml b/resources/qml/dialogs/AliasEditor.qml
new file mode 100644
index 00000000..0d7b73fd
--- /dev/null
+++ b/resources/qml/dialogs/AliasEditor.qml
@@ -0,0 +1,172 @@
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import ".."
+import "../components"
+import QtQuick 2.12
+import QtQuick.Controls 2.5
+import QtQuick.Layouts 1.3
+import im.nheko 1.0
+
+
+ApplicationWindow {
+ id: aliasEditorW
+
+ property var roomSettings
+ property var editingModel: Nheko.editAliases(roomSettings.roomId)
+
+ modality: Qt.NonModal
+ flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
+ minimumWidth: 300
+ minimumHeight: 400
+ height: 600
+ width: 500
+
+ title: qsTr("Aliases to %1").arg(roomSettings.roomName);
+
+ // Shortcut {
+ // sequence: StandardKey.Cancel
+ // onActivated: dbb.rejected()
+ // }
+
+ ColumnLayout {
+ anchors.margins: Nheko.paddingMedium
+ anchors.fill: parent
+ spacing: 0
+
+
+ MatrixText {
+ text: qsTr("List of aliases to this room. Usually you can only add aliases on your server. You can have one canonical alias and many alternate aliases.")
+ font.pixelSize: Math.floor(fontMetrics.font.pixelSize * 1.1)
+ Layout.fillWidth: true
+ Layout.fillHeight: false
+ color: Nheko.colors.text
+ Layout.bottomMargin: Nheko.paddingMedium
+ }
+
+ ListView {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ id: view
+
+ clip: true
+
+ ScrollHelper {
+ flickable: parent
+ anchors.fill: parent
+ }
+
+ model: editingModel
+ spacing: 4
+ cacheBuffer: 50
+
+ delegate: RowLayout {
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ Text {
+ Layout.fillWidth: true
+ text: model.name
+ color: model.isPublished ? Nheko.colors.text : Nheko.theme.error
+ textFormat: Text.PlainText
+ }
+
+ ImageButton {
+ Layout.alignment: Qt.AlignRight
+ Layout.margins: 2
+ image: ":/icons/icons/ui/star.svg"
+ hoverEnabled: true
+ buttonTextColor: model.isCanonical ? Nheko.colors.highlight : Nheko.colors.text
+ highlightColor: editingModel.canAdvertize ? Nheko.colors.highlight : buttonTextColor
+
+ ToolTip.visible: hovered
+ ToolTip.text: model.isCanonical ? qsTr("Primary alias") : qsTr("Make primary alias")
+
+ onClicked: editingModel.makeCanonical(model.index)
+ }
+
+ ImageButton {
+ Layout.alignment: Qt.AlignRight
+ Layout.margins: 2
+ image: ":/icons/icons/ui/building-shop.svg"
+ hoverEnabled: true
+ buttonTextColor: model.isAdvertized ? Nheko.colors.highlight : Nheko.colors.text
+ highlightColor: editingModel.canAdvertize ? Nheko.colors.highlight : buttonTextColor
+
+ ToolTip.visible: hovered
+ ToolTip.text: qsTr("Advertise as an alias in this room")
+
+ onClicked: editingModel.toggleAdvertize(model.index)
+ }
+
+ ImageButton {
+ Layout.alignment: Qt.AlignRight
+ Layout.margins: 2
+ image: ":/icons/icons/ui/room-directory.svg"
+ hoverEnabled: true
+ buttonTextColor: model.isPublished ? Nheko.colors.highlight : Nheko.colors.text
+
+ ToolTip.visible: hovered
+ ToolTip.text: qsTr("Publish in room directory")
+
+ onClicked: editingModel.togglePublish(model.index)
+ }
+
+ ImageButton {
+ Layout.alignment: Qt.AlignRight
+ Layout.margins: 2
+ image: ":/icons/icons/ui/dismiss.svg"
+ hoverEnabled: true
+
+ ToolTip.visible: hovered
+ ToolTip.text: qsTr("Remove this alias")
+
+ onClicked: editingModel.deleteAlias(model.index)
+ }
+ }
+ }
+
+ RowLayout {
+ spacing: Nheko.paddingMedium
+ Layout.fillWidth: true
+
+ TextField {
+ id: newAliasVal
+
+ Layout.fillWidth: true
+
+ placeholderText: qsTr("#new-alias:server.tld")
+
+ Keys.onPressed: {
+ if (event.matches(StandardKey.InsertParagraphSeparator)) {
+ editingModel.addAlias(newAliasVal.text);
+ newAliasVal.clear();
+ }
+ }
+ }
+
+ Button {
+ text: qsTr("Add")
+ Layout.preferredWidth: 100
+ onClicked: {
+ editingModel.addAlias(newAliasVal.text);
+ newAliasVal.clear();
+ }
+ }
+ }
+ }
+
+ footer: DialogButtonBox {
+ id: dbb
+
+ standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
+ onAccepted: {
+ editingModel.commit();
+ aliasEditorW.close();
+ }
+ onRejected: aliasEditorW.close();
+ }
+
+}
diff --git a/resources/qml/dialogs/RoomSettings.qml b/resources/qml/dialogs/RoomSettings.qml
index 2818a79a..431c9dd6 100644
--- a/resources/qml/dialogs/RoomSettings.qml
+++ b/resources/qml/dialogs/RoomSettings.qml
@@ -352,6 +352,18 @@ ApplicationWindow {
Layout.alignment: Qt.AlignRight
}
+ Label {
+ text: qsTr("Addresses")
+ color: Nheko.colors.text
+ }
+
+ Button {
+ text: qsTr("Configure")
+ ToolTip.text: qsTr("View and change the addresses/aliases of this room")
+ onClicked: timelineRoot.showAliasEditor(roomSettings)
+ Layout.alignment: Qt.AlignRight
+ }
+
Label {
text: qsTr("Sticker & Emote Settings")
color: Nheko.colors.text
diff --git a/resources/res.qrc b/resources/res.qrc
index 6e3023ea..3ec24238 100644
--- a/resources/res.qrc
+++ b/resources/res.qrc
@@ -4,6 +4,7 @@
icons/ui/angle-arrow-left.svg
icons/ui/attach.svg
icons/ui/ban.svg
+ icons/ui/building-shop.svg
icons/ui/chat.svg
icons/ui/checkmark.svg
icons/ui/clock.svg
@@ -36,6 +37,7 @@
icons/ui/reply.svg
icons/ui/ribbon.svg
icons/ui/ribbon_star.svg
+ icons/ui/room-directory.svg
icons/ui/round-remove-button.svg
icons/ui/screen-share.svg
icons/ui/search.svg
@@ -147,6 +149,7 @@
qml/device-verification/NewVerificationRequest.qml
qml/device-verification/Success.qml
qml/device-verification/Waiting.qml
+ qml/dialogs/AliasEditor.qml
qml/dialogs/CreateDirect.qml
qml/dialogs/CreateRoom.qml
qml/dialogs/HiddenEventsDialog.qml
diff --git a/src/AliasEditModel.cpp b/src/AliasEditModel.cpp
new file mode 100644
index 00000000..1ca7f5e6
--- /dev/null
+++ b/src/AliasEditModel.cpp
@@ -0,0 +1,336 @@
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "AliasEditModel.h"
+
+#include
+
+#include
+
+#include
+
+#include "Cache.h"
+#include "Cache_p.h"
+#include "ChatPage.h"
+#include "Logging.h"
+#include "MatrixClient.h"
+#include "timeline/Permissions.h"
+#include "timeline/TimelineModel.h"
+
+AliasEditingModel::AliasEditingModel(const std::string &rid, QObject *parent)
+ : QAbstractListModel(parent)
+ , room_id(rid)
+ , aliasEvent(cache::client()
+ ->getStateEvent(room_id)
+ .value_or(mtx::events::StateEvent{})
+ .content)
+ , canSendStateEvent(
+ Permissions(QString::fromStdString(rid)).canChange(qml_mtx_events::CanonicalAlias))
+{
+ std::set seen_aliases;
+
+ if (!aliasEvent.alias.empty()) {
+ aliases.push_back(Entry{aliasEvent.alias, true, true, false});
+ seen_aliases.insert(aliasEvent.alias);
+ }
+
+ for (const auto &alias : aliasEvent.alt_aliases) {
+ if (!seen_aliases.count(alias)) {
+ aliases.push_back(Entry{aliasEvent.alias, false, true, false});
+ seen_aliases.insert(aliasEvent.alias);
+ }
+ }
+
+ for (const auto &alias : aliases) {
+ fetchAliasesStatus(alias.alias);
+ }
+ fetchPublishedAliases();
+}
+
+void
+AliasEditingModel::fetchPublishedAliases()
+{
+ auto job = QSharedPointer::create();
+ connect(job.data(),
+ &FetchPublishedAliasesJob::advertizedAliasesFetched,
+ this,
+ &AliasEditingModel::updatePublishedAliases);
+ http::client()->list_room_aliases(
+ room_id, [job](const mtx::responses::Aliases &aliasesFetched, mtx::http::RequestErr) {
+ emit job->advertizedAliasesFetched(std::move(aliasesFetched.aliases));
+ });
+}
+
+void
+AliasEditingModel::fetchAliasesStatus(const std::string &alias)
+{
+ auto job = QSharedPointer::create();
+ connect(
+ job.data(), &FetchPublishedAliasesJob::aliasFetched, this, &AliasEditingModel::updateAlias);
+ http::client()->resolve_room_alias(
+ alias, [job, alias](const mtx::responses::RoomId &roomIdFetched, mtx::http::RequestErr e) {
+ if (!e)
+ emit job->aliasFetched(alias, std::move(roomIdFetched.room_id));
+ });
+}
+
+QHash
+AliasEditingModel::roleNames() const
+{
+ return {
+ {Name, "name"},
+ {IsPublished, "isPublished"},
+ {IsCanonical, "isCanonical"},
+ {IsAdvertized, "isAdvertized"},
+ };
+}
+
+QVariant
+AliasEditingModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || index.row() >= aliases.size())
+ return {};
+
+ const auto &entry = aliases.at(index.row());
+
+ switch (role) {
+ case Name:
+ return QString::fromStdString(entry.alias);
+ case IsPublished:
+ return entry.published;
+ case IsCanonical:
+ return entry.canonical;
+ case IsAdvertized:
+ return entry.advertized;
+ }
+
+ return {};
+}
+
+bool
+AliasEditingModel::deleteAlias(int row)
+{
+ if (row < 0 || row >= aliases.size() || aliases.at(row).alias.empty())
+ return false;
+
+ auto alias = aliases.at(row);
+
+ beginRemoveRows(QModelIndex(), row, row);
+ aliases.remove(row);
+ endRemoveRows();
+
+ if (alias.published)
+ http::client()->delete_room_alias(alias.alias, [alias](mtx::http::RequestErr e) {
+ if (e) {
+ nhlog::net()->error("Failed to delete {}: {}", alias.alias, *e);
+ ChatPage::instance()->showNotification(
+ tr("Failed to unpublish alias %1: %2")
+ .arg(QString::fromStdString(alias.alias),
+ QString::fromStdString(e->matrix_error.error)));
+ }
+ });
+
+ if (aliasEvent.alias == alias.alias)
+ aliasEvent.alias.clear();
+
+ for (size_t i = 0; i < aliasEvent.alt_aliases.size(); i++) {
+ if (aliasEvent.alt_aliases[i] == alias.alias) {
+ aliasEvent.alt_aliases.erase(aliasEvent.alt_aliases.begin() + i);
+ break;
+ }
+ }
+
+ return true;
+}
+
+void
+AliasEditingModel::addAlias(QString newAlias)
+{
+ const auto aliasStr = newAlias.toStdString();
+ for (const auto &e : aliases) {
+ if (e.alias == aliasStr) {
+ return;
+ }
+ }
+
+ beginInsertRows(QModelIndex(), aliases.length(), aliases.length());
+ if (aliasEvent.alias.empty())
+ aliasEvent.alias = aliasStr;
+ else
+ aliasEvent.alt_aliases.push_back(aliasStr);
+ aliases.push_back(
+ Entry{aliasStr, aliasEvent.alias.empty() && canSendStateEvent, canSendStateEvent, false});
+ endInsertRows();
+
+ auto job = QSharedPointer::create();
+ connect(
+ job.data(), &FetchPublishedAliasesJob::aliasFetched, this, &AliasEditingModel::updateAlias);
+ auto room = room_id;
+ http::client()->add_room_alias(
+ aliasStr, room_id, [job, aliasStr, room](mtx::http::RequestErr e) {
+ if (e) {
+ nhlog::net()->error("Failed to publish {}: {}", aliasStr, *e);
+ ChatPage::instance()->showNotification(
+ tr("Failed to unpublish alias %1: %2")
+ .arg(QString::fromStdString(aliasStr),
+ QString::fromStdString(e->matrix_error.error)));
+ emit job->aliasFetched(aliasStr, "");
+ } else {
+ emit job->aliasFetched(aliasStr, room);
+ }
+ });
+}
+
+void
+AliasEditingModel::makeCanonical(int row)
+{
+ if (!canSendStateEvent || row < 0 || row >= aliases.size() || aliases.at(row).alias.empty())
+ return;
+
+ auto moveAlias = aliases.at(row).alias;
+
+ if (!aliasEvent.alias.empty()) {
+ for (qsizetype i = 0; i < aliases.size(); i++) {
+ if (moveAlias == aliases[i].alias) {
+ if (aliases[i].canonical) {
+ aliases[i].canonical = false;
+ aliasEvent.alt_aliases.push_back(aliasEvent.alias);
+ emit dataChanged(index(i), index(i), {IsCanonical});
+ }
+ break;
+ }
+ }
+ }
+
+ aliasEvent.alias = moveAlias;
+ for (auto i = aliasEvent.alt_aliases.begin(); i != aliasEvent.alt_aliases.end(); ++i) {
+ if (*i == moveAlias) {
+ aliasEvent.alt_aliases.erase(i);
+ break;
+ }
+ }
+ aliases[row].canonical = true;
+ aliases[row].advertized = true;
+ emit dataChanged(index(row), index(row), {IsCanonical, IsAdvertized});
+}
+
+void
+AliasEditingModel::togglePublish(int row)
+{
+ if (row < 0 || row >= aliases.size() || aliases.at(row).alias.empty())
+ return;
+ auto aliasStr = aliases[row].alias;
+
+ auto job = QSharedPointer::create();
+ connect(
+ job.data(), &FetchPublishedAliasesJob::aliasFetched, this, &AliasEditingModel::updateAlias);
+ auto room = room_id;
+ if (!aliases[row].published)
+ http::client()->add_room_alias(
+ aliasStr, room_id, [job, aliasStr, room](mtx::http::RequestErr e) {
+ if (e) {
+ nhlog::net()->error("Failed to publish {}: {}", aliasStr, *e);
+ ChatPage::instance()->showNotification(
+ tr("Failed to unpublish alias %1: %2")
+ .arg(QString::fromStdString(aliasStr),
+ QString::fromStdString(e->matrix_error.error)));
+ emit job->aliasFetched(aliasStr, "");
+ } else {
+ emit job->aliasFetched(aliasStr, room);
+ }
+ });
+ else
+ http::client()->delete_room_alias(aliasStr, [job, aliasStr, room](mtx::http::RequestErr e) {
+ if (e) {
+ nhlog::net()->error("Failed to unpublish {}: {}", aliasStr, *e);
+ ChatPage::instance()->showNotification(
+ tr("Failed to unpublish alias %1: %2")
+ .arg(QString::fromStdString(aliasStr),
+ QString::fromStdString(e->matrix_error.error)));
+ emit job->aliasFetched(aliasStr, room);
+ } else {
+ emit job->aliasFetched(aliasStr, "");
+ }
+ });
+}
+
+void
+AliasEditingModel::toggleAdvertize(int row)
+{
+ if (!canSendStateEvent || row < 0 || row >= aliases.size() || aliases.at(row).alias.empty())
+ return;
+
+ auto &moveAlias = aliases[row];
+ if (aliasEvent.alias == moveAlias.alias) {
+ moveAlias.canonical = false;
+ moveAlias.advertized = false;
+ aliasEvent.alias.clear();
+ emit dataChanged(index(row), index(row), {IsAdvertized, IsCanonical});
+ } else if (moveAlias.advertized) {
+ for (auto i = aliasEvent.alt_aliases.begin(); i != aliasEvent.alt_aliases.end(); ++i) {
+ if (*i == moveAlias.alias) {
+ aliasEvent.alt_aliases.erase(i);
+ moveAlias.advertized = false;
+ emit dataChanged(index(row), index(row), {IsAdvertized});
+ break;
+ }
+ }
+ } else {
+ aliasEvent.alt_aliases.push_back(moveAlias.alias);
+ moveAlias.advertized = true;
+ emit dataChanged(index(row), index(row), {IsAdvertized});
+ }
+}
+
+void
+AliasEditingModel::updateAlias(std::string alias, std::string target)
+{
+ for (qsizetype i = 0; i < aliases.size(); i++) {
+ auto &e = aliases[i];
+ if (e.alias == alias) {
+ e.published = (target == room_id);
+ emit dataChanged(index(i), index(i), {IsPublished});
+ }
+ }
+}
+
+void
+AliasEditingModel::updatePublishedAliases(std::vector advAliases)
+{
+ for (const auto &advAlias : advAliases) {
+ bool found = false;
+ for (qsizetype i = 0; i < aliases.size(); i++) {
+ auto &alias = aliases[i];
+ if (alias.alias == advAlias) {
+ alias.published = true;
+ emit dataChanged(index(i), index(i), {IsPublished});
+ found = true;
+ break;
+ }
+
+ if (!found) {
+ beginInsertRows(QModelIndex(), aliases.size(), aliases.size());
+ aliases.push_back(Entry{advAlias, false, false, true});
+ endInsertRows();
+ }
+ }
+ }
+}
+
+void
+AliasEditingModel::commit()
+{
+ if (!canSendStateEvent)
+ return;
+
+ http::client()->send_state_event(
+ room_id, aliasEvent, [](const mtx::responses::EventId &, mtx::http::RequestErr e) {
+ if (e) {
+ nhlog::net()->error("Failed to send Alias event: {}", *e);
+ ChatPage::instance()->showNotification(
+ tr("Failed to update aliases: %1")
+ .arg(QString::fromStdString(e->matrix_error.error)));
+ }
+ });
+}
diff --git a/src/AliasEditModel.h b/src/AliasEditModel.h
new file mode 100644
index 00000000..4fccf9ce
--- /dev/null
+++ b/src/AliasEditModel.h
@@ -0,0 +1,79 @@
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include
+#include
+
+#include
+
+#include "CacheStructs.h"
+
+class FetchPublishedAliasesJob : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit FetchPublishedAliasesJob(QObject *p = nullptr)
+ : QObject(p)
+ {}
+
+signals:
+ void aliasFetched(std::string alias, std::string target);
+ void advertizedAliasesFetched(std::vector aliases);
+};
+
+class AliasEditingModel : public QAbstractListModel
+{
+ Q_OBJECT
+ Q_PROPERTY(bool canAdvertize READ canAdvertize CONSTANT)
+
+public:
+ enum Roles
+ {
+ Name,
+ IsPublished,
+ IsCanonical,
+ IsAdvertized,
+ };
+
+ explicit AliasEditingModel(const std::string &room_id_, QObject *parent = nullptr);
+
+ QHash roleNames() const override;
+ int rowCount(const QModelIndex &) const override { return static_cast(aliases.size()); }
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+ bool canAdvertize() const { return canSendStateEvent; }
+
+ Q_INVOKABLE bool deleteAlias(int row);
+ Q_INVOKABLE void addAlias(QString newAlias);
+ Q_INVOKABLE void makeCanonical(int row);
+ Q_INVOKABLE void togglePublish(int row);
+ Q_INVOKABLE void toggleAdvertize(int row);
+ Q_INVOKABLE void commit();
+
+private slots:
+ void updateAlias(std::string alias, std::string target);
+ void updatePublishedAliases(std::vector aliases);
+
+private:
+ void fetchAliasesStatus(const std::string &alias);
+ void fetchPublishedAliases();
+
+ struct Entry
+ {
+ ~Entry() = default;
+
+ std::string alias;
+ bool canonical = false;
+ bool advertized = false;
+ bool published = false;
+ };
+
+ std::string room_id;
+ QVector aliases;
+ mtx::events::state::CanonicalAlias aliasEvent;
+ bool canSendStateEvent = false;
+};
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index f031c80f..d2e28277 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -10,6 +10,7 @@
#include
#include
+#include "AliasEditModel.h"
#include "BlurhashProvider.h"
#include "Cache.h"
#include "Cache_p.h"
@@ -179,6 +180,13 @@ MainWindow::registerQmlTypes()
qmlRegisterType("im.nheko", 1, 0, "Login");
qmlRegisterType("im.nheko", 1, 0, "Registration");
qmlRegisterType("im.nheko", 1, 0, "HiddenEvents");
+ qmlRegisterUncreatableType(
+ "im.nheko",
+ 1,
+ 0,
+ "AliasEditingModel",
+ QStringLiteral("Please use editAliases to create the models"));
+
qmlRegisterUncreatableType(
"im.nheko",
1,
diff --git a/src/ui/NhekoGlobalObject.h b/src/ui/NhekoGlobalObject.h
index bd141f35..f9de489d 100644
--- a/src/ui/NhekoGlobalObject.h
+++ b/src/ui/NhekoGlobalObject.h
@@ -9,6 +9,7 @@
#include
#include
+#include "AliasEditModel.h"
#include "PowerlevelsEditModels.h"
#include "Theme.h"
#include "UserProfile.h"
@@ -59,6 +60,10 @@ public:
{
return new PowerlevelEditingModels(room_id_);
}
+ Q_INVOKABLE AliasEditingModel *editAliases(QString room_id_) const
+ {
+ return new AliasEditingModel(room_id_.toStdString());
+ }
public slots:
void updateUserProfile();