Compare commits
38 Commits
work/adapt
...
v24.04.80
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eeddf99ca5 | ||
|
|
09a35b1a7e | ||
|
|
533182ec55 | ||
|
|
70a8842f00 | ||
|
|
ab33d1ca88 | ||
|
|
9e45f22e09 | ||
|
|
6a627dfff0 | ||
|
|
a9f05a7f63 | ||
|
|
4dfd4b68eb | ||
|
|
3786710d81 | ||
|
|
3967b27352 | ||
|
|
714ea8413c | ||
|
|
4097addae9 | ||
|
|
e9ac9deb40 | ||
|
|
3b858ab7d5 | ||
|
|
08807797a5 | ||
|
|
923839d6c7 | ||
|
|
3d4a1d22b0 | ||
|
|
5aa7f499c0 | ||
|
|
40c3519737 | ||
|
|
6ec9cc2475 | ||
|
|
eba34b19ad | ||
|
|
8517636485 | ||
|
|
4a96dae57d | ||
|
|
09f433be45 | ||
|
|
b9901a9167 | ||
|
|
8b27d99d82 | ||
|
|
6b53c4d7b1 | ||
|
|
bd28a7f66d | ||
|
|
0d1c09696d | ||
|
|
aeb4013d26 | ||
|
|
08a7e324aa | ||
|
|
9202a4525f | ||
|
|
bfc756fb35 | ||
|
|
2a735ff1cc | ||
|
|
551092a1b4 | ||
|
|
ddd12688aa | ||
|
|
71767c4172 |
@@ -110,7 +110,7 @@
|
|||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/quotient-im/libQuotient.git",
|
"url": "https://github.com/quotient-im/libQuotient.git",
|
||||||
"branch": "dev",
|
"branch": "0.8.x",
|
||||||
"disable-submodules": true
|
"disable-submodules": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
# KDE Applications version, managed by release script.
|
# KDE Applications version, managed by release script.
|
||||||
set(RELEASE_SERVICE_VERSION_MAJOR "24")
|
set(RELEASE_SERVICE_VERSION_MAJOR "24")
|
||||||
set(RELEASE_SERVICE_VERSION_MINOR "04")
|
set(RELEASE_SERVICE_VERSION_MINOR "04")
|
||||||
set(RELEASE_SERVICE_VERSION_MICRO "70")
|
set(RELEASE_SERVICE_VERSION_MICRO "80")
|
||||||
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||||
|
|
||||||
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
|
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
|
||||||
|
|||||||
407
po/ar/neochat.po
407
po/ar/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
405
po/az/neochat.po
405
po/az/neochat.po
File diff suppressed because it is too large
Load Diff
397
po/ca/neochat.po
397
po/ca/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
400
po/cs/neochat.po
400
po/cs/neochat.po
File diff suppressed because it is too large
Load Diff
398
po/da/neochat.po
398
po/da/neochat.po
File diff suppressed because it is too large
Load Diff
407
po/de/neochat.po
407
po/de/neochat.po
File diff suppressed because it is too large
Load Diff
407
po/el/neochat.po
407
po/el/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
403
po/eo/neochat.po
403
po/eo/neochat.po
File diff suppressed because it is too large
Load Diff
399
po/es/neochat.po
399
po/es/neochat.po
File diff suppressed because it is too large
Load Diff
403
po/eu/neochat.po
403
po/eu/neochat.po
File diff suppressed because it is too large
Load Diff
402
po/fi/neochat.po
402
po/fi/neochat.po
File diff suppressed because it is too large
Load Diff
407
po/fr/neochat.po
407
po/fr/neochat.po
File diff suppressed because it is too large
Load Diff
402
po/hu/neochat.po
402
po/hu/neochat.po
File diff suppressed because it is too large
Load Diff
405
po/ia/neochat.po
405
po/ia/neochat.po
File diff suppressed because it is too large
Load Diff
407
po/id/neochat.po
407
po/id/neochat.po
File diff suppressed because it is too large
Load Diff
400
po/ie/neochat.po
400
po/ie/neochat.po
File diff suppressed because it is too large
Load Diff
456
po/it/neochat.po
456
po/it/neochat.po
File diff suppressed because it is too large
Load Diff
392
po/ja/neochat.po
392
po/ja/neochat.po
File diff suppressed because it is too large
Load Diff
403
po/ka/neochat.po
403
po/ka/neochat.po
File diff suppressed because it is too large
Load Diff
402
po/ko/neochat.po
402
po/ko/neochat.po
File diff suppressed because it is too large
Load Diff
392
po/lt/neochat.po
392
po/lt/neochat.po
File diff suppressed because it is too large
Load Diff
402
po/lv/neochat.po
402
po/lv/neochat.po
File diff suppressed because it is too large
Load Diff
403
po/nl/neochat.po
403
po/nl/neochat.po
File diff suppressed because it is too large
Load Diff
407
po/nn/neochat.po
407
po/nn/neochat.po
File diff suppressed because it is too large
Load Diff
405
po/pa/neochat.po
405
po/pa/neochat.po
File diff suppressed because it is too large
Load Diff
403
po/pl/neochat.po
403
po/pl/neochat.po
File diff suppressed because it is too large
Load Diff
407
po/pt/neochat.po
407
po/pt/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
402
po/ru/neochat.po
402
po/ru/neochat.po
File diff suppressed because it is too large
Load Diff
406
po/sk/neochat.po
406
po/sk/neochat.po
File diff suppressed because it is too large
Load Diff
399
po/sl/neochat.po
399
po/sl/neochat.po
File diff suppressed because it is too large
Load Diff
407
po/sv/neochat.po
407
po/sv/neochat.po
File diff suppressed because it is too large
Load Diff
450
po/ta/neochat.po
450
po/ta/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
405
po/tr/neochat.po
405
po/tr/neochat.po
File diff suppressed because it is too large
Load Diff
403
po/uk/neochat.po
403
po/uk/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -204,7 +204,6 @@ qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN
|
|||||||
qml/InviteUserPage.qml
|
qml/InviteUserPage.qml
|
||||||
qml/ImageEditorPage.qml
|
qml/ImageEditorPage.qml
|
||||||
qml/NeochatMaximizeComponent.qml
|
qml/NeochatMaximizeComponent.qml
|
||||||
qml/FancyEffectsContainer.qml
|
|
||||||
qml/TypingPane.qml
|
qml/TypingPane.qml
|
||||||
qml/QuickSwitcher.qml
|
qml/QuickSwitcher.qml
|
||||||
qml/HoverActions.qml
|
qml/HoverActions.qml
|
||||||
@@ -281,9 +280,6 @@ qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN
|
|||||||
qml/ConfirmLeaveDialog.qml
|
qml/ConfirmLeaveDialog.qml
|
||||||
qml/CodeMaximizeComponent.qml
|
qml/CodeMaximizeComponent.qml
|
||||||
qml/EditStateDialog.qml
|
qml/EditStateDialog.qml
|
||||||
RESOURCES
|
|
||||||
qml/confetti.png
|
|
||||||
qml/glowdot.png
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(settings)
|
add_subdirectory(settings)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "models/actionsmodel.h"
|
#include "models/actionsmodel.h"
|
||||||
#include "neochatconfig.h"
|
#include "neochatconfig.h"
|
||||||
#include "texthandler.h"
|
#include "texthandler.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
@@ -145,6 +146,26 @@ void ActionsHandler::handleMessage(const QString &text, QString handledText, Cha
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We want to add back the <mx-reply> if it's in the original message but not in the edit, to preserve the reply.
|
||||||
|
for (auto it = m_room->messageEvents().crbegin(); it != m_room->messageEvents().crend(); it++) {
|
||||||
|
if (const auto event = eventCast<const RoomMessageEvent>(&**it)) {
|
||||||
|
if (event->senderId() == m_room->localUser()->id() && event->hasTextContent()) {
|
||||||
|
QString originalString;
|
||||||
|
if (event->content()) {
|
||||||
|
originalString = static_cast<const Quotient::EventContent::TextContent *>(event->content())->body;
|
||||||
|
} else {
|
||||||
|
originalString = event->plainBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QRegularExpression exp(TextRegex::removeRichReply);
|
||||||
|
const auto match = exp.match(originalString);
|
||||||
|
if (match.hasCaptured(0) && !handledText.contains(TextRegex::removeRichReply)) {
|
||||||
|
handledText.prepend(match.captured(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_room->postMessage(text, handledText, messageType, chatBarCache->replyId(), chatBarCache->editId(), chatBarCache->threadId());
|
m_room->postMessage(text, handledText, messageType, chatBarCache->replyId(), chatBarCache->editId(), chatBarCache->threadId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include <Quotient/accountregistry.h>
|
#include <Quotient/accountregistry.h>
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/csapi/logout.h>
|
#include <Quotient/csapi/logout.h>
|
||||||
#include <Quotient/csapi/notifications.h>
|
#include <Quotient/csapi/notifications.h>
|
||||||
#include <Quotient/eventstats.h>
|
#include <Quotient/eventstats.h>
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ private:
|
|||||||
|
|
||||||
Quotient::AccountRegistry m_accountRegistry;
|
Quotient::AccountRegistry m_accountRegistry;
|
||||||
QStringList m_accountsLoading;
|
QStringList m_accountsLoading;
|
||||||
QMap<QString, QPointer<Quotient::Connection>> m_connectionsLoading;
|
QMap<QString, QPointer<NeoChatConnection>> m_connectionsLoading;
|
||||||
QString m_endpoint;
|
QString m_endpoint;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
|||||||
@@ -15,6 +15,12 @@ FormCard.FormCardPage {
|
|||||||
FormCard.FormCard {
|
FormCard.FormCard {
|
||||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
FormCard.FormCheckDelegate {
|
||||||
|
text: i18nc("@option:check", "Show hidden events in the timeline")
|
||||||
|
checked: Config.showAllEvents
|
||||||
|
|
||||||
|
onToggled: Config.showAllEvents = checked
|
||||||
|
}
|
||||||
FormCard.FormCheckDelegate {
|
FormCard.FormCheckDelegate {
|
||||||
id: roomAccountDataVisibleCheck
|
id: roomAccountDataVisibleCheck
|
||||||
text: i18nc("@option:check Enable the matrix 'threads' feature", "Always allow device verification")
|
text: i18nc("@option:check Enable the matrix 'threads' feature", "Always allow device verification")
|
||||||
@@ -23,5 +29,14 @@ FormCard.FormCardPage {
|
|||||||
|
|
||||||
onToggled: Config.alwaysVerifyDevice = checked
|
onToggled: Config.alwaysVerifyDevice = checked
|
||||||
}
|
}
|
||||||
|
FormCard.FormCheckDelegate {
|
||||||
|
text: i18nc("@option:check", "Show focus in window header")
|
||||||
|
checked: Config.windowTitleFocus
|
||||||
|
|
||||||
|
onToggled: {
|
||||||
|
Config.windowTitleFocus = checked;
|
||||||
|
Config.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,10 @@ ColumnLayout {
|
|||||||
text: i18n("Room")
|
text: i18n("Room")
|
||||||
textRole: "escapedDisplayName"
|
textRole: "escapedDisplayName"
|
||||||
valueRole: "roomId"
|
valueRole: "roomId"
|
||||||
displayText: RoomManager.roomListModel.data(RoomManager.roomListModel.index(currentIndex, 0), RoomListModel.DisplayNameRole)
|
displayText: RoomManager.roomListModel.data(RoomManager.roomListModel.index(currentIndex, 0), RoomListModel.EscapedDisplayNameRole)
|
||||||
model: RoomManager.roomListModel
|
model: RoomManager.roomListModel
|
||||||
currentIndex: 0
|
currentIndex: 0
|
||||||
|
displayMode: FormCard.FormComboBoxDelegate.Page
|
||||||
Component.onCompleted: currentIndex = RoomManager.roomListModel.rowForRoom(root.room)
|
Component.onCompleted: currentIndex = RoomManager.roomListModel.rowForRoom(root.room)
|
||||||
onCurrentValueChanged: root.room = RoomManager.roomListModel.roomByAliasOrId(roomComboBox.currentValue)
|
onCurrentValueChanged: root.room = RoomManager.roomListModel.roomByAliasOrId(roomComboBox.currentValue)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ public:
|
|||||||
* @brief Defines the room list categories a room can be assigned.
|
* @brief Defines the room list categories a room can be assigned.
|
||||||
*/
|
*/
|
||||||
enum Types {
|
enum Types {
|
||||||
Search = 0, /**< So we can show a search delegate if needed, e.g. collapsed mode. */
|
|
||||||
Invited, /**< The user has been invited to the room. */
|
Invited, /**< The user has been invited to the room. */
|
||||||
Favorite, /**< The room is set as a favourite. */
|
Favorite, /**< The room is set as a favourite. */
|
||||||
Direct, /**< The room is a direct chat. */
|
Direct, /**< The room is a direct chat. */
|
||||||
@@ -68,8 +67,6 @@ public:
|
|||||||
return i18n("Low priority");
|
return i18n("Low priority");
|
||||||
case NeoChatRoomType::Space:
|
case NeoChatRoomType::Space:
|
||||||
return i18n("Spaces");
|
return i18n("Spaces");
|
||||||
case NeoChatRoomType::Search:
|
|
||||||
return i18n("Search");
|
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -89,8 +86,6 @@ public:
|
|||||||
return QStringLiteral("object-order-lower");
|
return QStringLiteral("object-order-lower");
|
||||||
case NeoChatRoomType::Space:
|
case NeoChatRoomType::Space:
|
||||||
return QStringLiteral("group");
|
return QStringLiteral("group");
|
||||||
case NeoChatRoomType::Search:
|
|
||||||
return QStringLiteral("search");
|
|
||||||
default:
|
default:
|
||||||
return QStringLiteral("tools-report-bug");
|
return QStringLiteral("tools-report-bug");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "login.h"
|
#include "login.h"
|
||||||
|
|
||||||
#include <Quotient/accountregistry.h>
|
#include <Quotient/accountregistry.h>
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/qt_connection_util.h>
|
#include <Quotient/qt_connection_util.h>
|
||||||
|
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
@@ -54,7 +53,7 @@ void LoginHelper::init()
|
|||||||
m_connection = new NeoChatConnection();
|
m_connection = new NeoChatConnection();
|
||||||
}
|
}
|
||||||
m_connection->resolveServer(m_matrixId);
|
m_connection->resolveServer(m_matrixId);
|
||||||
connectSingleShot(m_connection, &Connection::loginFlowsChanged, this, [this]() {
|
connectSingleShot(m_connection.get(), &Connection::loginFlowsChanged, this, [this]() {
|
||||||
setHomeserverReachable(true);
|
setHomeserverReachable(true);
|
||||||
m_testing = false;
|
m_testing = false;
|
||||||
Q_EMIT testingChanged();
|
Q_EMIT testingChanged();
|
||||||
@@ -100,7 +99,7 @@ void LoginHelper::init()
|
|||||||
Q_EMIT Controller::instance().errorOccured(i18n("Network Error"), std::move(error));
|
Q_EMIT Controller::instance().errorOccured(i18n("Network Error"), std::move(error));
|
||||||
});
|
});
|
||||||
|
|
||||||
connectSingleShot(m_connection, &Connection::syncDone, this, [this]() {
|
connectSingleShot(m_connection.get(), &Connection::syncDone, this, [this]() {
|
||||||
Q_EMIT loaded();
|
Q_EMIT loaded();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -182,7 +181,7 @@ QUrl LoginHelper::ssoUrl() const
|
|||||||
void LoginHelper::loginWithSso()
|
void LoginHelper::loginWithSso()
|
||||||
{
|
{
|
||||||
m_connection->resolveServer(m_matrixId);
|
m_connection->resolveServer(m_matrixId);
|
||||||
connectSingleShot(m_connection, &Connection::loginFlowsChanged, this, [this]() {
|
connectSingleShot(m_connection.get(), &Connection::loginFlowsChanged, this, [this]() {
|
||||||
SsoSession *session = m_connection->prepareForSso(m_deviceName);
|
SsoSession *session = m_connection->prepareForSso(m_deviceName);
|
||||||
m_ssoUrl = session->ssoUrl();
|
m_ssoUrl = session->ssoUrl();
|
||||||
Q_EMIT ssoUrlChanged();
|
Q_EMIT ssoUrlChanged();
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ private:
|
|||||||
QString m_deviceName;
|
QString m_deviceName;
|
||||||
bool m_supportsSso = false;
|
bool m_supportsSso = false;
|
||||||
bool m_supportsPassword = false;
|
bool m_supportsPassword = false;
|
||||||
NeoChatConnection *m_connection = nullptr;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
QUrl m_ssoUrl;
|
QUrl m_ssoUrl;
|
||||||
bool m_testing = false;
|
bool m_testing = false;
|
||||||
bool m_isLoggingIn = false;
|
bool m_isLoggingIn = false;
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
#include "neochatconnection.h"
|
#include "neochatconnection.h"
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
ThumbnailResponse::ThumbnailResponse(QString id, QSize size, NeoChatConnection *connection)
|
ThumbnailResponse::ThumbnailResponse(QString id, QSize size, NeoChatConnection *connection)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ private:
|
|||||||
QSize requestedSize;
|
QSize requestedSize;
|
||||||
const QString localFile;
|
const QString localFile;
|
||||||
Quotient::MediaThumbnailJob *job = nullptr;
|
Quotient::MediaThumbnailJob *job = nullptr;
|
||||||
NeoChatConnection *m_connection;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
|
|
||||||
QImage image;
|
QImage image;
|
||||||
QString errorStr;
|
QString errorStr;
|
||||||
@@ -75,6 +75,6 @@ public:
|
|||||||
QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override;
|
QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NeoChatConnection *m_connection = nullptr;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
MatrixImageProvider() = default;
|
MatrixImageProvider() = default;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <Quotient/events/eventcontent.h>
|
#include <Quotient/events/eventcontent.h>
|
||||||
#include <qcoro/qcorosignal.h>
|
#include <qcoro/qcorosignal.h>
|
||||||
|
|
||||||
|
#include "neochatconnection.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
AccountEmoticonModel::AccountEmoticonModel(QObject *parent)
|
AccountEmoticonModel::AccountEmoticonModel(QObject *parent)
|
||||||
@@ -77,12 +79,12 @@ QHash<int, QByteArray> AccountEmoticonModel::roleNames() const
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection *AccountEmoticonModel::connection() const
|
NeoChatConnection *AccountEmoticonModel::connection() const
|
||||||
{
|
{
|
||||||
return m_connection;
|
return m_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountEmoticonModel::setConnection(Connection *connection)
|
void AccountEmoticonModel::setConnection(NeoChatConnection *connection)
|
||||||
{
|
{
|
||||||
if (m_connection) {
|
if (m_connection) {
|
||||||
disconnect(m_connection, nullptr, this, nullptr);
|
disconnect(m_connection, nullptr, this, nullptr);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
class NeoChatConnection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class AccountEmoticonModel
|
* @class AccountEmoticonModel
|
||||||
@@ -29,7 +29,7 @@ class AccountEmoticonModel : public QAbstractListModel
|
|||||||
/**
|
/**
|
||||||
* @brief The connection to get emoticons from.
|
* @brief The connection to get emoticons from.
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(Quotient::Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
|
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
@@ -63,8 +63,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
[[nodiscard]] Quotient::Connection *connection() const;
|
[[nodiscard]] NeoChatConnection *connection() const;
|
||||||
void setConnection(Quotient::Connection *connection);
|
void setConnection(NeoChatConnection *connection);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deletes the emoticon at the given index.
|
* @brief Deletes the emoticon at the given index.
|
||||||
@@ -96,7 +96,7 @@ Q_SIGNALS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<Quotient::ImagePackEventContent> m_images;
|
std::optional<Quotient::ImagePackEventContent> m_images;
|
||||||
QPointer<Quotient::Connection> m_connection;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
QCoro::Task<void> doSetEmoticonImage(int index, QUrl source);
|
QCoro::Task<void> doSetEmoticonImage(int index, QUrl source);
|
||||||
QCoro::Task<void> doAddEmoticon(QUrl source, QString shortcode, QString description, QString type);
|
QCoro::Task<void> doAddEmoticon(QUrl source, QString shortcode, QString description, QString type);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "actionsmodel.h"
|
#include "actionsmodel.h"
|
||||||
|
|
||||||
#include "chatbarcache.h"
|
#include "chatbarcache.h"
|
||||||
|
#include "neochatconnection.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
#include "roommanager.h"
|
#include "roommanager.h"
|
||||||
#include <Quotient/events/roommemberevent.h>
|
#include <Quotient/events/roommemberevent.h>
|
||||||
@@ -260,7 +261,7 @@ QList<ActionsModel::Action> actions{
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("Knocking room <roomname>.", "Knocking room %1.", text));
|
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("Knocking room <roomname>.", "Knocking room %1.", text));
|
||||||
auto connection = room->connection();
|
auto connection = dynamic_cast<NeoChatConnection *>(room->connection());
|
||||||
const auto knownServer = roomName.mid(roomName.indexOf(":"_ls) + 1);
|
const auto knownServer = roomName.mid(roomName.indexOf(":"_ls) + 1);
|
||||||
if (parts.length() >= 2) {
|
if (parts.length() >= 2) {
|
||||||
RoomManager::instance().knockRoom(connection, roomName, parts[1], QStringList{knownServer});
|
RoomManager::instance().knockRoom(connection, roomName, parts[1], QStringList{knownServer});
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ Q_SIGNALS:
|
|||||||
private:
|
private:
|
||||||
explicit CustomEmojiModel(QObject *parent = nullptr);
|
explicit CustomEmojiModel(QObject *parent = nullptr);
|
||||||
QList<CustomEmoji> m_emojis;
|
QList<CustomEmoji> m_emojis;
|
||||||
NeoChatConnection *m_connection = nullptr;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
|
|
||||||
void fetchEmojis();
|
void fetchEmojis();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
#include "customemojimodel.h"
|
#include "customemojimodel.h"
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <connection.h>
|
|
||||||
|
class NeoChatConnection;
|
||||||
|
|
||||||
struct CustomEmoji {
|
struct CustomEmoji {
|
||||||
QString name; // with :semicolons:
|
QString name; // with :semicolons:
|
||||||
@@ -14,6 +15,6 @@ struct CustomEmoji {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct CustomEmojiModel::Private {
|
struct CustomEmojiModel::Private {
|
||||||
Quotient::Connection *conn = nullptr;
|
QPointer<NeoChatConnection> connection;
|
||||||
QList<CustomEmoji> emojies;
|
QList<CustomEmoji> emojies;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,9 +11,10 @@
|
|||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
#include <Quotient/csapi/device_management.h>
|
#include <Quotient/csapi/device_management.h>
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/user.h>
|
#include <Quotient/user.h>
|
||||||
|
|
||||||
|
#include "neochatconnection.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
DevicesModel::DevicesModel(QObject *parent)
|
DevicesModel::DevicesModel(QObject *parent)
|
||||||
@@ -152,12 +153,12 @@ void DevicesModel::setName(const QString &deviceId, const QString &name)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection *DevicesModel::connection() const
|
NeoChatConnection *DevicesModel::connection() const
|
||||||
{
|
{
|
||||||
return m_connection;
|
return m_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevicesModel::setConnection(Connection *connection)
|
void DevicesModel::setConnection(NeoChatConnection *connection)
|
||||||
{
|
{
|
||||||
if (m_connection) {
|
if (m_connection) {
|
||||||
disconnect(m_connection, nullptr, this, nullptr);
|
disconnect(m_connection, nullptr, this, nullptr);
|
||||||
|
|||||||
@@ -9,10 +9,7 @@
|
|||||||
|
|
||||||
#include <Quotient/csapi/definitions/client_device.h>
|
#include <Quotient/csapi/definitions/client_device.h>
|
||||||
|
|
||||||
namespace Quotient
|
class NeoChatConnection;
|
||||||
{
|
|
||||||
class Connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class DevicesModel
|
* @class DevicesModel
|
||||||
@@ -31,7 +28,7 @@ class DevicesModel : public QAbstractListModel
|
|||||||
/**
|
/**
|
||||||
* @brief The current connection that the model is getting its devices from.
|
* @brief The current connection that the model is getting its devices from.
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(Quotient::Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged REQUIRED)
|
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged REQUIRED)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -88,9 +85,8 @@ public:
|
|||||||
|
|
||||||
explicit DevicesModel(QObject *parent = nullptr);
|
explicit DevicesModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
[[nodiscard]] NeoChatConnection *connection() const;
|
||||||
[[nodiscard]] Quotient::Connection *connection() const;
|
void setConnection(NeoChatConnection *connection);
|
||||||
void setConnection(Quotient::Connection *connection);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void connectionChanged();
|
void connectionChanged();
|
||||||
@@ -99,5 +95,5 @@ Q_SIGNALS:
|
|||||||
private:
|
private:
|
||||||
void fetchDevices();
|
void fetchDevices();
|
||||||
QList<Quotient::Device> m_devices;
|
QList<Quotient::Device> m_devices;
|
||||||
QPointer<Quotient::Connection> m_connection;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -246,70 +246,86 @@ void MessageContentModel::updateComponents(bool isEditing)
|
|||||||
if (eventCast<const Quotient::RoomMessageEvent>(m_event)
|
if (eventCast<const Quotient::RoomMessageEvent>(m_event)
|
||||||
&& eventCast<const Quotient::RoomMessageEvent>(m_event)->rawMsgtype() == QStringLiteral("m.key.verification.request")) {
|
&& eventCast<const Quotient::RoomMessageEvent>(m_event)->rawMsgtype() == QStringLiteral("m.key.verification.request")) {
|
||||||
m_components += MessageComponent{MessageComponentType::Verification, QString(), {}};
|
m_components += MessageComponent{MessageComponentType::Verification, QString(), {}};
|
||||||
} else {
|
endResetModel();
|
||||||
EventHandler eventHandler(m_room, m_event);
|
return;
|
||||||
if (eventHandler.hasReply()) {
|
}
|
||||||
if (m_room->findInTimeline(eventHandler.getReplyId()) == m_room->historyEdge()) {
|
|
||||||
m_components += MessageComponent{MessageComponentType::ReplyLoad, QString(), {}};
|
|
||||||
m_room->loadReply(m_event->id(), eventHandler.getReplyId());
|
|
||||||
} else {
|
|
||||||
m_components += MessageComponent{MessageComponentType::Reply, QString(), {}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isEditing) {
|
if (m_event->isRedacted()) {
|
||||||
m_components += MessageComponent{MessageComponentType::Edit, QString(), {}};
|
m_components += MessageComponent{MessageComponentType::Text, QString(), {}};
|
||||||
} else if (m_event->isRedacted()) {
|
endResetModel();
|
||||||
m_components += MessageComponent{MessageComponentType::Text, QString(), {}};
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandler eventHandler(m_room, m_event);
|
||||||
|
if (eventHandler.hasReply()) {
|
||||||
|
if (m_room->findInTimeline(eventHandler.getReplyId()) == m_room->historyEdge()) {
|
||||||
|
m_components += MessageComponent{MessageComponentType::ReplyLoad, QString(), {}};
|
||||||
|
m_room->loadReply(m_event->id(), eventHandler.getReplyId());
|
||||||
} else {
|
} else {
|
||||||
if (eventHandler.messageComponentType() == MessageComponentType::Text) {
|
m_components += MessageComponent{MessageComponentType::Reply, QString(), {}};
|
||||||
const auto event = eventCast<const Quotient::RoomMessageEvent>(m_event);
|
|
||||||
auto body = EventHandler::rawMessageBody(*event);
|
|
||||||
m_components.append(TextHandler().textComponents(body, EventHandler::messageBodyInputFormat(*event), m_room, event, event->isReplaced()));
|
|
||||||
} else if (eventHandler.messageComponentType() == MessageComponentType::File) {
|
|
||||||
m_components += MessageComponent{MessageComponentType::File, QString(), {}};
|
|
||||||
if (m_emptyItinerary) {
|
|
||||||
auto fileTransferInfo = fileInfo();
|
|
||||||
|
|
||||||
#ifndef Q_OS_ANDROID
|
|
||||||
KSyntaxHighlighting::Repository repository;
|
|
||||||
const auto definitionForFile = repository.definitionForFileName(fileTransferInfo.localPath.toString());
|
|
||||||
if (definitionForFile.isValid() || QFileInfo(fileTransferInfo.localPath.path()).suffix() == QStringLiteral("txt")) {
|
|
||||||
QFile file(fileTransferInfo.localPath.path());
|
|
||||||
file.open(QIODevice::ReadOnly);
|
|
||||||
m_components += MessageComponent{MessageComponentType::Code,
|
|
||||||
QString::fromStdString(file.readAll().toStdString()),
|
|
||||||
{{QStringLiteral("class"), definitionForFile.name()}}};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (FileType::instance().fileHasImage(fileTransferInfo.localPath)) {
|
|
||||||
QImageReader reader(fileTransferInfo.localPath.path());
|
|
||||||
m_components += MessageComponent{MessageComponentType::Pdf, QString(), {{QStringLiteral("size"), reader.size()}}};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
updateItineraryModel();
|
|
||||||
if (m_itineraryModel != nullptr) {
|
|
||||||
m_components += MessageComponent{MessageComponentType::Itinerary, QString(), {}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_components += MessageComponent{eventHandler.messageComponentType(), QString(), {}};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_linkPreviewer != nullptr) {
|
if (isEditing) {
|
||||||
if (m_linkPreviewer->loaded()) {
|
m_components += MessageComponent{MessageComponentType::Edit, QString(), {}};
|
||||||
m_components += MessageComponent{MessageComponentType::LinkPreview, QString(), {}};
|
} else {
|
||||||
} else {
|
m_components.append(componentsForType(eventHandler.messageComponentType()));
|
||||||
m_components += MessageComponent{MessageComponentType::LinkPreviewLoad, QString(), {}};
|
}
|
||||||
}
|
|
||||||
|
if (m_linkPreviewer != nullptr) {
|
||||||
|
if (m_linkPreviewer->loaded()) {
|
||||||
|
m_components += MessageComponent{MessageComponentType::LinkPreview, QString(), {}};
|
||||||
|
} else {
|
||||||
|
m_components += MessageComponent{MessageComponentType::LinkPreviewLoad, QString(), {}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<MessageComponent> MessageContentModel::componentsForType(MessageComponentType::Type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case MessageComponentType::Text: {
|
||||||
|
const auto event = eventCast<const Quotient::RoomMessageEvent>(m_event);
|
||||||
|
auto body = EventHandler::rawMessageBody(*event);
|
||||||
|
return TextHandler().textComponents(body, EventHandler::messageBodyInputFormat(*event), m_room, event, event->isReplaced());
|
||||||
|
}
|
||||||
|
case MessageComponentType::File: {
|
||||||
|
QList<MessageComponent> components;
|
||||||
|
components += MessageComponent{MessageComponentType::File, QString(), {}};
|
||||||
|
if (m_emptyItinerary) {
|
||||||
|
auto fileTransferInfo = fileInfo();
|
||||||
|
|
||||||
|
#ifndef Q_OS_ANDROID
|
||||||
|
KSyntaxHighlighting::Repository repository;
|
||||||
|
const auto definitionForFile = repository.definitionForFileName(fileTransferInfo.localPath.toString());
|
||||||
|
if (definitionForFile.isValid() || QFileInfo(fileTransferInfo.localPath.path()).suffix() == QStringLiteral("txt")) {
|
||||||
|
QFile file(fileTransferInfo.localPath.path());
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
components += MessageComponent{MessageComponentType::Code,
|
||||||
|
QString::fromStdString(file.readAll().toStdString()),
|
||||||
|
{{QStringLiteral("class"), definitionForFile.name()}}};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (FileType::instance().fileHasImage(fileTransferInfo.localPath)) {
|
||||||
|
QImageReader reader(fileTransferInfo.localPath.path());
|
||||||
|
components += MessageComponent{MessageComponentType::Pdf, QString(), {{QStringLiteral("size"), reader.size()}}};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateItineraryModel();
|
||||||
|
if (m_itineraryModel != nullptr) {
|
||||||
|
components += MessageComponent{MessageComponentType::Itinerary, QString(), {}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return {MessageComponent{type, QString(), {}}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MessageContentModel::updateLinkPreviewer()
|
void MessageContentModel::updateLinkPreviewer()
|
||||||
{
|
{
|
||||||
if (m_room == nullptr || m_event == nullptr) {
|
if (m_room == nullptr || m_event == nullptr) {
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ private:
|
|||||||
QPointer<LinkPreviewer> m_linkPreviewer;
|
QPointer<LinkPreviewer> m_linkPreviewer;
|
||||||
ItineraryModel *m_itineraryModel = nullptr;
|
ItineraryModel *m_itineraryModel = nullptr;
|
||||||
|
|
||||||
|
QList<MessageComponent> componentsForType(MessageComponentType::Type type);
|
||||||
|
|
||||||
void updateLinkPreviewer();
|
void updateLinkPreviewer();
|
||||||
void updateItineraryModel();
|
void updateItineraryModel();
|
||||||
bool m_emptyItinerary = false;
|
bool m_emptyItinerary = false;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include "neochatconfig.h"
|
#include "neochatconfig.h"
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/csapi/rooms.h>
|
#include <Quotient/csapi/rooms.h>
|
||||||
#include <Quotient/events/redactionevent.h>
|
#include <Quotient/events/redactionevent.h>
|
||||||
#include <Quotient/events/roommessageevent.h>
|
#include <Quotient/events/roommessageevent.h>
|
||||||
@@ -117,34 +116,6 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
|||||||
|
|
||||||
if (message != nullptr) {
|
if (message != nullptr) {
|
||||||
createEventObjects(message);
|
createEventObjects(message);
|
||||||
if (NeoChatConfig::self()->showFancyEffects()) {
|
|
||||||
QString planBody = message->plainBody();
|
|
||||||
// snowflake
|
|
||||||
const QString snowlakeEmoji = QString::fromUtf8("\xE2\x9D\x84");
|
|
||||||
if (planBody.contains(snowlakeEmoji)) {
|
|
||||||
Q_EMIT fancyEffectsReasonFound(QStringLiteral("snowflake"));
|
|
||||||
}
|
|
||||||
// fireworks
|
|
||||||
const QString fireworksEmoji = QString::fromUtf8("\xF0\x9F\x8E\x86");
|
|
||||||
if (planBody.contains(fireworksEmoji)) {
|
|
||||||
Q_EMIT fancyEffectsReasonFound(QStringLiteral("fireworks"));
|
|
||||||
}
|
|
||||||
// sparkler
|
|
||||||
const QString sparklerEmoji = QString::fromUtf8("\xF0\x9F\x8E\x87");
|
|
||||||
if (planBody.contains(sparklerEmoji)) {
|
|
||||||
Q_EMIT fancyEffectsReasonFound(QStringLiteral("fireworks"));
|
|
||||||
}
|
|
||||||
// party pooper
|
|
||||||
const QString partyEmoji = QString::fromUtf8("\xF0\x9F\x8E\x89");
|
|
||||||
if (planBody.contains(partyEmoji)) {
|
|
||||||
Q_EMIT fancyEffectsReasonFound(QStringLiteral("confetti"));
|
|
||||||
}
|
|
||||||
// confetti ball
|
|
||||||
const QString confettiEmoji = QString::fromUtf8("\xF0\x9F\x8E\x8A");
|
|
||||||
if (planBody.contains(confettiEmoji)) {
|
|
||||||
Q_EMIT fancyEffectsReasonFound(QStringLiteral("confetti"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (event->is<PollStartEvent>()) {
|
if (event->is<PollStartEvent>()) {
|
||||||
m_currentRoom->createPollHandler(eventCast<const PollStartEvent>(event.get()));
|
m_currentRoom->createPollHandler(eventCast<const PollStartEvent>(event.get()));
|
||||||
|
|||||||
@@ -140,5 +140,4 @@ private:
|
|||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void roomChanged();
|
void roomChanged();
|
||||||
void fancyEffectsReasonFound(const QString &fancyEffect);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ MessageFilterModel::MessageFilterModel(QObject *parent, TimelineModel *sourceMod
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MessageFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
bool MessageFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||||
|
{
|
||||||
|
if (NeoChatConfig::self()->showAllEvents()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return eventIsVisible(sourceRow, sourceParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageFilterModel::eventIsVisible(int sourceRow, const QModelIndex &sourceParent) const
|
||||||
{
|
{
|
||||||
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||||
|
|
||||||
@@ -59,9 +67,8 @@ bool MessageFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour
|
|||||||
// Don't show state events that are not the first in a consecutive group on the
|
// Don't show state events that are not the first in a consecutive group on the
|
||||||
// same day as they will be grouped as a single delegate.
|
// same day as they will be grouped as a single delegate.
|
||||||
const bool notLastRow = sourceRow < sourceModel()->rowCount() - 1;
|
const bool notLastRow = sourceRow < sourceModel()->rowCount() - 1;
|
||||||
const bool previousEventIsState = notLastRow
|
const bool previousEventIsState =
|
||||||
? sourceModel()->data(sourceModel()->index(sourceRow + 1, 0), MessageEventModel::DelegateTypeRole) == DelegateType::State
|
notLastRow ? sourceModel()->data(sourceModel()->index(sourceRow + 1, 0), MessageEventModel::DelegateTypeRole) == DelegateType::State : false;
|
||||||
: false;
|
|
||||||
const bool newDay = sourceModel()->data(sourceModel()->index(sourceRow, 0), MessageEventModel::ShowSectionRole).toBool();
|
const bool newDay = sourceModel()->data(sourceModel()->index(sourceRow, 0), MessageEventModel::ShowSectionRole).toBool();
|
||||||
if (eventType == DelegateType::State && notLastRow && previousEventIsState && !newDay) {
|
if (eventType == DelegateType::State && notLastRow && previousEventIsState && !newDay) {
|
||||||
return false;
|
return false;
|
||||||
@@ -72,7 +79,11 @@ bool MessageFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour
|
|||||||
|
|
||||||
QVariant MessageFilterModel::data(const QModelIndex &index, int role) const
|
QVariant MessageFilterModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (role == AggregateDisplayRole) {
|
if (role == MessageEventModel::DelegateTypeRole && NeoChatConfig::self()->showAllEvents()) {
|
||||||
|
if (!eventIsVisible(index.row(), index.parent())) {
|
||||||
|
return DelegateType::Other;
|
||||||
|
}
|
||||||
|
} else if (role == AggregateDisplayRole) {
|
||||||
return aggregateEventToString(mapToSource(index).row());
|
return aggregateEventToString(mapToSource(index).row());
|
||||||
} else if (role == StateEventsRole) {
|
} else if (role == StateEventsRole) {
|
||||||
return stateEventsList(mapToSource(index).row());
|
return stateEventsList(mapToSource(index).row());
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ public:
|
|||||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool eventIsVisible(int sourceRow, const QModelIndex &sourceParent) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Aggregation of the text of consecutive state events starting at row.
|
* @brief Aggregation of the text of consecutive state events starting at row.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "notificationsmodel.h"
|
#include "notificationsmodel.h"
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/events/event.h>
|
#include <Quotient/events/event.h>
|
||||||
#include <Quotient/uri.h>
|
#include <Quotient/uri.h>
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
#include "publicroomlistmodel.h"
|
#include "publicroomlistmodel.h"
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
#include "neochatconnection.h"
|
||||||
|
|
||||||
#include "publicroomlist_logging.h"
|
#include "publicroomlist_logging.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
@@ -14,14 +13,14 @@ PublicRoomListModel::PublicRoomListModel(QObject *parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Quotient::Connection *PublicRoomListModel::connection() const
|
NeoChatConnection *PublicRoomListModel::connection() const
|
||||||
{
|
{
|
||||||
return m_connection;
|
return m_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PublicRoomListModel::setConnection(Connection *conn)
|
void PublicRoomListModel::setConnection(NeoChatConnection *connection)
|
||||||
{
|
{
|
||||||
if (m_connection == conn) {
|
if (m_connection == connection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +37,7 @@ void PublicRoomListModel::setConnection(Connection *conn)
|
|||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
||||||
m_connection = conn;
|
m_connection = connection;
|
||||||
|
|
||||||
if (job) {
|
if (job) {
|
||||||
job->abandon();
|
job->abandon();
|
||||||
|
|||||||
@@ -9,10 +9,7 @@
|
|||||||
|
|
||||||
#include <Quotient/csapi/list_public_rooms.h>
|
#include <Quotient/csapi/list_public_rooms.h>
|
||||||
|
|
||||||
namespace Quotient
|
class NeoChatConnection;
|
||||||
{
|
|
||||||
class Connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class PublicRoomListModel
|
* @class PublicRoomListModel
|
||||||
@@ -33,7 +30,7 @@ class PublicRoomListModel : public QAbstractListModel
|
|||||||
/**
|
/**
|
||||||
* @brief The current connection that the model is getting its rooms from.
|
* @brief The current connection that the model is getting its rooms from.
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(Quotient::Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
|
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The server to get the public room list from.
|
* @brief The server to get the public room list from.
|
||||||
@@ -95,8 +92,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
[[nodiscard]] Quotient::Connection *connection() const;
|
[[nodiscard]] NeoChatConnection *connection() const;
|
||||||
void setConnection(Quotient::Connection *conn);
|
void setConnection(NeoChatConnection *connection);
|
||||||
|
|
||||||
[[nodiscard]] QString server() const;
|
[[nodiscard]] QString server() const;
|
||||||
void setServer(const QString &value);
|
void setServer(const QString &value);
|
||||||
@@ -117,7 +114,7 @@ public:
|
|||||||
Q_INVOKABLE void search(int limit = 50);
|
Q_INVOKABLE void search(int limit = 50);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointer<Quotient::Connection> m_connection = nullptr;
|
QPointer<NeoChatConnection> m_connection = nullptr;
|
||||||
QString m_server;
|
QString m_server;
|
||||||
QString m_searchText;
|
QString m_searchText;
|
||||||
bool m_showOnlySpaces = false;
|
bool m_showOnlySpaces = false;
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/converters.h>
|
#include <Quotient/converters.h>
|
||||||
#include <Quotient/csapi/definitions/push_ruleset.h>
|
#include <Quotient/csapi/definitions/push_ruleset.h>
|
||||||
#include <Quotient/csapi/pushrules.h>
|
#include <Quotient/csapi/pushrules.h>
|
||||||
#include <Quotient/jobs/basejob.h>
|
#include <Quotient/jobs/basejob.h>
|
||||||
|
|
||||||
#include "neochatconfig.h"
|
#include "neochatconfig.h"
|
||||||
|
#include "neochatconnection.h"
|
||||||
|
|
||||||
#include <KLazyLocalizedString>
|
#include <KLazyLocalizedString>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ void PushRuleModel::setConnection(NeoChatConnection *connection)
|
|||||||
Q_EMIT connectionChanged();
|
Q_EMIT connectionChanged();
|
||||||
|
|
||||||
if (m_connection) {
|
if (m_connection) {
|
||||||
connect(m_connection, &Quotient::Connection::accountDataChanged, this, &PushRuleModel::updateNotificationRules);
|
connect(m_connection, &NeoChatConnection::accountDataChanged, this, &PushRuleModel::updateNotificationRules);
|
||||||
updateNotificationRules(QStringLiteral("m.push_rules"));
|
updateNotificationRules(QStringLiteral("m.push_rules"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ private Q_SLOTS:
|
|||||||
private:
|
private:
|
||||||
PushRuleAction::Action m_defaultKeywordAction;
|
PushRuleAction::Action m_defaultKeywordAction;
|
||||||
QList<Rule> m_rules;
|
QList<Rule> m_rules;
|
||||||
NeoChatConnection *m_connection;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
|
|
||||||
void setRules(QList<Quotient::PushRule> rules, PushRuleKind::Kind kind);
|
void setRules(QList<Quotient::PushRule> rules, PushRuleKind::Kind kind);
|
||||||
|
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ RoomListModel::RoomListModel(QObject *parent)
|
|||||||
|
|
||||||
RoomListModel::~RoomListModel() = default;
|
RoomListModel::~RoomListModel() = default;
|
||||||
|
|
||||||
Quotient::Connection *RoomListModel::connection() const
|
NeoChatConnection *RoomListModel::connection() const
|
||||||
{
|
{
|
||||||
return m_connection;
|
return m_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomListModel::setConnection(Connection *connection)
|
void RoomListModel::setConnection(NeoChatConnection *connection)
|
||||||
{
|
{
|
||||||
if (connection == m_connection) {
|
if (connection == m_connection) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -12,10 +12,11 @@ class NeoChatRoom;
|
|||||||
|
|
||||||
namespace Quotient
|
namespace Quotient
|
||||||
{
|
{
|
||||||
class Connection;
|
|
||||||
class Room;
|
class Room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NeoChatConnection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class RoomListModel
|
* @class RoomListModel
|
||||||
*
|
*
|
||||||
@@ -29,7 +30,7 @@ class RoomListModel : public QAbstractListModel
|
|||||||
/**
|
/**
|
||||||
* @brief The current connection that the model is getting its rooms from.
|
* @brief The current connection that the model is getting its rooms from.
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(Quotient::Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
|
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -60,8 +61,8 @@ public:
|
|||||||
explicit RoomListModel(QObject *parent = nullptr);
|
explicit RoomListModel(QObject *parent = nullptr);
|
||||||
~RoomListModel() override;
|
~RoomListModel() override;
|
||||||
|
|
||||||
[[nodiscard]] Quotient::Connection *connection() const;
|
[[nodiscard]] NeoChatConnection *connection() const;
|
||||||
void setConnection(Quotient::Connection *connection);
|
void setConnection(NeoChatConnection *connection);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the given role value at the given index.
|
* @brief Get the given role value at the given index.
|
||||||
@@ -109,7 +110,7 @@ private Q_SLOTS:
|
|||||||
void refresh(NeoChatRoom *room, const QList<int> &roles = {});
|
void refresh(NeoChatRoom *room, const QList<int> &roles = {});
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Quotient::Connection *m_connection = nullptr;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
QList<NeoChatRoom *> m_rooms;
|
QList<NeoChatRoom *> m_rooms;
|
||||||
|
|
||||||
QString m_activeSpaceId;
|
QString m_activeSpaceId;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "roomtreemodel.h"
|
#include "roomtreemodel.h"
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/room.h>
|
#include <Quotient/room.h>
|
||||||
|
|
||||||
#include "eventhandler.h"
|
#include "eventhandler.h"
|
||||||
@@ -300,9 +299,6 @@ QVariant RoomTreeModel::data(const QModelIndex &index, int role) const
|
|||||||
return NeoChatRoomType::typeName(index.row());
|
return NeoChatRoomType::typeName(index.row());
|
||||||
}
|
}
|
||||||
if (role == DelegateTypeRole) {
|
if (role == DelegateTypeRole) {
|
||||||
if (index.row() == NeoChatRoomType::Search) {
|
|
||||||
return QStringLiteral("search");
|
|
||||||
}
|
|
||||||
if (index.row() == NeoChatRoomType::AddDirect) {
|
if (index.row() == NeoChatRoomType::AddDirect) {
|
||||||
return QStringLiteral("addDirect");
|
return QStringLiteral("addDirect");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/events/stickerevent.h>
|
#include <Quotient/events/stickerevent.h>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#include "serverlistmodel.h"
|
#include "serverlistmodel.h"
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include <KConfig>
|
#include <KConfig>
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ Q_SIGNALS:
|
|||||||
private:
|
private:
|
||||||
QList<Server> m_servers;
|
QList<Server> m_servers;
|
||||||
QPointer<Quotient::QueryPublicRoomsJob> m_checkServerJob = nullptr;
|
QPointer<Quotient::QueryPublicRoomsJob> m_checkServerJob = nullptr;
|
||||||
NeoChatConnection *m_connection = nullptr;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "roomlistmodel.h"
|
#include "roomlistmodel.h"
|
||||||
|
|
||||||
|
#include "neochatconnection.h"
|
||||||
|
|
||||||
SortFilterRoomListModel::SortFilterRoomListModel(RoomListModel *sourceModel, QObject *parent)
|
SortFilterRoomListModel::SortFilterRoomListModel(RoomListModel *sourceModel, QObject *parent)
|
||||||
: QSortFilterProxyModel(parent)
|
: QSortFilterProxyModel(parent)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -129,10 +129,6 @@ QString SortFilterRoomTreeModel::filterText() const
|
|||||||
bool SortFilterRoomTreeModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
bool SortFilterRoomTreeModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||||
{
|
{
|
||||||
if (!source_parent.isValid()) {
|
if (!source_parent.isValid()) {
|
||||||
if (sourceModel()->data(sourceModel()->index(source_row, 0), RoomTreeModel::CategoryRole).toInt() == NeoChatRoomType::Search
|
|
||||||
&& NeoChatConfig::collapsed()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (sourceModel()->data(sourceModel()->index(source_row, 0), RoomTreeModel::CategoryRole).toInt() == NeoChatRoomType::AddDirect
|
if (sourceModel()->data(sourceModel()->index(source_row, 0), RoomTreeModel::CategoryRole).toInt() == NeoChatRoomType::AddDirect
|
||||||
&& m_mode == DirectChats) {
|
&& m_mode == DirectChats) {
|
||||||
return true;
|
return true;
|
||||||
@@ -205,4 +201,14 @@ void SortFilterRoomTreeModel::setMode(SortFilterRoomTreeModel::Mode mode)
|
|||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QModelIndex SortFilterRoomTreeModel::currentRoomIndex() const
|
||||||
|
{
|
||||||
|
const auto roomModel = dynamic_cast<RoomTreeModel *>(sourceModel());
|
||||||
|
if (roomModel == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapFromSource(roomModel->indexForRoom(RoomManager::instance().currentRoom()));
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_sortfilterroomtreemodel.cpp"
|
#include "moc_sortfilterroomtreemodel.cpp"
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ public:
|
|||||||
Mode mode() const;
|
Mode mode() const;
|
||||||
void setMode(Mode mode);
|
void setMode(Mode mode);
|
||||||
|
|
||||||
|
Q_INVOKABLE QModelIndex currentRoomIndex() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief Returns true if the value of source_left is less than source_right.
|
* @brief Returns true if the value of source_left is less than source_right.
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "spacechildrenmodel.h"
|
#include "spacechildrenmodel.h"
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/jobs/basejob.h>
|
#include <Quotient/jobs/basejob.h>
|
||||||
#include <Quotient/room.h>
|
#include <Quotient/room.h>
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ void SpaceChildrenModel::setSpace(NeoChatRoom *space)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto connection = m_space->connection();
|
auto connection = m_space->connection();
|
||||||
connect(connection, &Quotient::Connection::loadedRoomState, this, [this](Quotient::Room *room) {
|
connect(connection, &NeoChatConnection::loadedRoomState, this, [this](Quotient::Room *room) {
|
||||||
if (m_pendingChildren.contains(room->name())) {
|
if (m_pendingChildren.contains(room->name())) {
|
||||||
m_pendingChildren.removeAll(room->name());
|
m_pendingChildren.removeAll(room->name());
|
||||||
refreshModel();
|
refreshModel();
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
||||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
#include <Quotient/csapi/space_hierarchy.h>
|
#include <Quotient/csapi/space_hierarchy.h>
|
||||||
#include <Quotient/events/stateevent.h>
|
#include <Quotient/events/stateevent.h>
|
||||||
|
|
||||||
@@ -149,7 +151,7 @@ public:
|
|||||||
bool isSuggested() const;
|
bool isSuggested() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NeoChatConnection *m_connection;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
std::vector<std::unique_ptr<SpaceTreeItem>> m_children;
|
std::vector<std::unique_ptr<SpaceTreeItem>> m_children;
|
||||||
SpaceTreeItem *m_parentItem;
|
SpaceTreeItem *m_parentItem;
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
#include "userdirectorylistmodel.h"
|
#include "userdirectorylistmodel.h"
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/room.h>
|
#include <Quotient/room.h>
|
||||||
|
|
||||||
|
#include "neochatconnection.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
UserDirectoryListModel::UserDirectoryListModel(QObject *parent)
|
UserDirectoryListModel::UserDirectoryListModel(QObject *parent)
|
||||||
@@ -13,14 +14,14 @@ UserDirectoryListModel::UserDirectoryListModel(QObject *parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Quotient::Connection *UserDirectoryListModel::connection() const
|
NeoChatConnection *UserDirectoryListModel::connection() const
|
||||||
{
|
{
|
||||||
return m_connection;
|
return m_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserDirectoryListModel::setConnection(Connection *conn)
|
void UserDirectoryListModel::setConnection(NeoChatConnection *connection)
|
||||||
{
|
{
|
||||||
if (m_connection == conn) {
|
if (m_connection == connection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ void UserDirectoryListModel::setConnection(Connection *conn)
|
|||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
||||||
m_connection = conn;
|
m_connection = connection;
|
||||||
Q_EMIT connectionChanged();
|
Q_EMIT connectionChanged();
|
||||||
|
|
||||||
if (m_job) {
|
if (m_job) {
|
||||||
|
|||||||
@@ -9,10 +9,7 @@
|
|||||||
|
|
||||||
#include <Quotient/csapi/users.h>
|
#include <Quotient/csapi/users.h>
|
||||||
|
|
||||||
namespace Quotient
|
class NeoChatConnection;
|
||||||
{
|
|
||||||
class Connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class UserDirectoryListModel
|
* @class UserDirectoryListModel
|
||||||
@@ -32,7 +29,7 @@ class UserDirectoryListModel : public QAbstractListModel
|
|||||||
/**
|
/**
|
||||||
* @brief The current connection that the model is getting users from.
|
* @brief The current connection that the model is getting users from.
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(Quotient::Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
|
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The text to search the public room list for.
|
* @brief The text to search the public room list for.
|
||||||
@@ -57,8 +54,8 @@ public:
|
|||||||
|
|
||||||
explicit UserDirectoryListModel(QObject *parent = nullptr);
|
explicit UserDirectoryListModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
[[nodiscard]] Quotient::Connection *connection() const;
|
[[nodiscard]] NeoChatConnection *connection() const;
|
||||||
void setConnection(Quotient::Connection *conn);
|
void setConnection(NeoChatConnection *connection);
|
||||||
|
|
||||||
[[nodiscard]] QString searchText() const;
|
[[nodiscard]] QString searchText() const;
|
||||||
void setSearchText(const QString &searchText);
|
void setSearchText(const QString &searchText);
|
||||||
@@ -99,7 +96,7 @@ Q_SIGNALS:
|
|||||||
void searchingChanged();
|
void searchingChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Quotient::Connection *m_connection = nullptr;
|
QPointer<NeoChatConnection> m_connection;
|
||||||
QString m_searchText;
|
QString m_searchText;
|
||||||
|
|
||||||
bool attempted = false;
|
bool attempted = false;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
#include <Quotient/events/roompowerlevelsevent.h>
|
#include <Quotient/events/roompowerlevelsevent.h>
|
||||||
|
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
|
|||||||
@@ -100,10 +100,6 @@
|
|||||||
<label>Minimize to system tray on startup</label>
|
<label>Minimize to system tray on startup</label>
|
||||||
<default>false</default>
|
<default>false</default>
|
||||||
</entry>
|
</entry>
|
||||||
<entry name="ShowFancyEffects" type="bool">
|
|
||||||
<label>Show Fancy Effects</label>
|
|
||||||
<default>true</default>
|
|
||||||
</entry>
|
|
||||||
<entry name="MediaMaxWidth" type="int">
|
<entry name="MediaMaxWidth" type="int">
|
||||||
<label>The maximum width any media item in the timeline can be.</label>
|
<label>The maximum width any media item in the timeline can be.</label>
|
||||||
<default>540</default>
|
<default>540</default>
|
||||||
@@ -161,10 +157,18 @@
|
|||||||
</entry>
|
</entry>
|
||||||
</group>
|
</group>
|
||||||
<group name="Debug">
|
<group name="Debug">
|
||||||
|
<entry name="ShowAllEvents" type="bool">
|
||||||
|
<label>Don't hide any events in the timeline</label>
|
||||||
|
<default>false</default>
|
||||||
|
</entry>
|
||||||
<entry name="AlwaysVerifyDevice" type="bool">
|
<entry name="AlwaysVerifyDevice" type="bool">
|
||||||
<label>Always allow device verification</label>
|
<label>Always allow device verification</label>
|
||||||
<default>false</default>
|
<default>false</default>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry name="WindowTitleFocus" type="bool">
|
||||||
|
<label>Show the current focus item in the window title</label>
|
||||||
|
<default>false</default>
|
||||||
|
</entry>
|
||||||
</group>
|
</group>
|
||||||
<group name="FeatureFlags">
|
<group name="FeatureFlags">
|
||||||
<entry name="Threads" type="bool">
|
<entry name="Threads" type="bool">
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"Name[nl]": "Tobias Fella",
|
"Name[nl]": "Tobias Fella",
|
||||||
"Name[pl]": "Tobias Fella",
|
"Name[pl]": "Tobias Fella",
|
||||||
"Name[sl]": "Tobias Fella",
|
"Name[sl]": "Tobias Fella",
|
||||||
|
"Name[ta]": "டோபியாஸ் ஃபெல்லா",
|
||||||
"Name[tr]": "Tobias Fella",
|
"Name[tr]": "Tobias Fella",
|
||||||
"Name[uk]": "Tobias Fella",
|
"Name[uk]": "Tobias Fella",
|
||||||
"Name[x-test]": "xxTobias Fellaxx",
|
"Name[x-test]": "xxTobias Fellaxx",
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
"Description[nl]": "Delen via NeoChat",
|
"Description[nl]": "Delen via NeoChat",
|
||||||
"Description[pl]": "Udostępnij przez NeoChat",
|
"Description[pl]": "Udostępnij przez NeoChat",
|
||||||
"Description[sl]": "Deli prek NeoChat",
|
"Description[sl]": "Deli prek NeoChat",
|
||||||
|
"Description[ta]": "நியோச்சாட் மூலம் பகிர்",
|
||||||
"Description[tr]": "NeoChat ile Paylaş",
|
"Description[tr]": "NeoChat ile Paylaş",
|
||||||
"Description[uk]": "Оприлюднити за допомогою NeoChat",
|
"Description[uk]": "Оприлюднити за допомогою NeoChat",
|
||||||
"Description[x-test]": "xxShare via NeoChatxx",
|
"Description[x-test]": "xxShare via NeoChatxx",
|
||||||
@@ -63,6 +65,7 @@
|
|||||||
"Name[nl]": "NeoChat",
|
"Name[nl]": "NeoChat",
|
||||||
"Name[pl]": "NeoChat",
|
"Name[pl]": "NeoChat",
|
||||||
"Name[sl]": "NeoChat",
|
"Name[sl]": "NeoChat",
|
||||||
|
"Name[ta]": "நியோச்சாட்",
|
||||||
"Name[tr]": "NeoChat",
|
"Name[tr]": "NeoChat",
|
||||||
"Name[uk]": "NeoChat",
|
"Name[uk]": "NeoChat",
|
||||||
"Name[x-test]": "xxNeoChatxx",
|
"Name[x-test]": "xxNeoChatxx",
|
||||||
|
|||||||
@@ -278,6 +278,8 @@ QQC2.Control {
|
|||||||
Keys.onTabPressed: {
|
Keys.onTabPressed: {
|
||||||
if (completionMenu.visible) {
|
if (completionMenu.visible) {
|
||||||
completionMenu.complete();
|
completionMenu.complete();
|
||||||
|
} else {
|
||||||
|
contextDrawer.handle.children[0].forceActiveFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keys.onPressed: event => {
|
Keys.onPressed: event => {
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ QQC2.ItemDelegate {
|
|||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: root.checked ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor
|
color: root.checked ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor
|
||||||
radius: Kirigami.Units.smallSpacing
|
radius: Kirigami.Units.cornerRadius
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
radius: Kirigami.Units.smallSpacing
|
radius: Kirigami.Units.cornerRadius
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Kirigami.Theme.highlightColor
|
color: Kirigami.Theme.highlightColor
|
||||||
opacity: root.hovered && !root.pressed ? 0.2 : 0
|
opacity: root.hovered && !root.pressed ? 0.2 : 0
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ QQC2.Popup {
|
|||||||
background: Kirigami.ShadowedRectangle {
|
background: Kirigami.ShadowedRectangle {
|
||||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||||
color: Kirigami.Theme.backgroundColor
|
color: Kirigami.Theme.backgroundColor
|
||||||
radius: Kirigami.Units.mediumSpacing
|
radius: Kirigami.Units.cornerRadius
|
||||||
shadow {
|
shadow {
|
||||||
size: Kirigami.Units.largeSpacing
|
size: Kirigami.Units.largeSpacing
|
||||||
color: Qt.rgba(0.0, 0.0, 0.0, 0.3)
|
color: Qt.rgba(0.0, 0.0, 0.0, 0.3)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ QQC2.Popup {
|
|||||||
onOpened: x = Math.min(parent.mapFromGlobal(QQC2.Overlay.overlay.width - root.width, 0).x, -(width - parent.width) / 2)
|
onOpened: x = Math.min(parent.mapFromGlobal(QQC2.Overlay.overlay.width - root.width, 0).x, -(width - parent.width) / 2)
|
||||||
background: Kirigami.ShadowedRectangle {
|
background: Kirigami.ShadowedRectangle {
|
||||||
color: Kirigami.Theme.backgroundColor
|
color: Kirigami.Theme.backgroundColor
|
||||||
radius: Kirigami.Units.mediumSpacing
|
radius: Kirigami.Units.cornerRadius
|
||||||
shadow {
|
shadow {
|
||||||
size: Kirigami.Units.largeSpacing
|
size: Kirigami.Units.largeSpacing
|
||||||
color: Qt.rgba(0.0, 0.0, 0.0, 0.3)
|
color: Qt.rgba(0.0, 0.0, 0.0, 0.3)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ RowLayout {
|
|||||||
property bool collapsed: false
|
property bool collapsed: false
|
||||||
required property NeoChatConnection connection
|
required property NeoChatConnection connection
|
||||||
|
|
||||||
property alias roomSearchFieldFocussed: roomSearchField.activeFocus
|
signal search
|
||||||
|
|
||||||
property Kirigami.Action exploreAction: Kirigami.Action {
|
property Kirigami.Action exploreAction: Kirigami.Action {
|
||||||
text: i18n("Explore rooms")
|
text: i18n("Explore rooms")
|
||||||
@@ -83,15 +83,30 @@ RowLayout {
|
|||||||
*/
|
*/
|
||||||
signal textChanged(string newText)
|
signal textChanged(string newText)
|
||||||
|
|
||||||
Kirigami.SearchField {
|
Item {
|
||||||
id: roomSearchField
|
Layout.preferredWidth: Kirigami.Units.largeSpacing
|
||||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
}
|
||||||
Layout.bottomMargin: Kirigami.Units.smallSpacing
|
|
||||||
|
Kirigami.Heading {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredWidth: root.desiredWidth ? root.desiredWidth - menuButton.width - root.spacing : -1
|
|
||||||
visible: !root.collapsed
|
visible: !root.collapsed
|
||||||
onTextChanged: root.textChanged(text)
|
text: i18nc("@title", "Rooms")
|
||||||
KeyNavigation.tab: treeView
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: root.collapsed
|
||||||
|
}
|
||||||
|
|
||||||
|
QQC2.ToolButton {
|
||||||
|
id: searchButton
|
||||||
|
display: QQC2.AbstractButton.IconOnly
|
||||||
|
onClicked: root.search();
|
||||||
|
icon.name: "search"
|
||||||
|
text: i18nc("@action", "Search Room")
|
||||||
|
Shortcut {
|
||||||
|
sequence: "Ctrl+F"
|
||||||
|
onActivated: searchButton.clicked()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QQC2.ToolButton {
|
QQC2.ToolButton {
|
||||||
@@ -100,8 +115,8 @@ RowLayout {
|
|||||||
display: QQC2.AbstractButton.IconOnly
|
display: QQC2.AbstractButton.IconOnly
|
||||||
checkable: true
|
checkable: true
|
||||||
action: Kirigami.Action {
|
action: Kirigami.Action {
|
||||||
text: i18n("Create rooms and chats")
|
text: i18nc("@action:button", "Show Menu")
|
||||||
icon.name: "irc-join-channel"
|
icon.name: "application-menu-symbolic"
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (Kirigami.isMobile) {
|
if (Kirigami.isMobile) {
|
||||||
const menu = mobileMenu.createObject();
|
const menu = mobileMenu.createObject();
|
||||||
|
|||||||
@@ -1,304 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru>
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import QtQuick.Particles
|
|
||||||
|
|
||||||
import org.kde.kirigami as Kirigami
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
property bool enabled: false
|
|
||||||
property int effectInterval: Kirigami.Units.veryLongDuration * 10
|
|
||||||
property color darkSnowColor: "grey"
|
|
||||||
property bool isThemeDark: Kirigami.Theme.backgroundColor.hslLightness <= darkSnowColor.hslLightness
|
|
||||||
|
|
||||||
function showConfettiEffect() {
|
|
||||||
confettiTimer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showSnowEffect() {
|
|
||||||
snowTimer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showFireworksEffect() {
|
|
||||||
fireworksTimer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Confetti
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: confettiTimer
|
|
||||||
interval: root.effectInterval
|
|
||||||
running: false
|
|
||||||
repeat: false
|
|
||||||
triggeredOnStart: true
|
|
||||||
onTriggered: {
|
|
||||||
if (root.enabled) {
|
|
||||||
confettiSystem.running = !confettiSystem.running;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticleSystem {
|
|
||||||
id: confettiSystem
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
running: false
|
|
||||||
onRunningChanged: {
|
|
||||||
if (running) {
|
|
||||||
opacity = 1;
|
|
||||||
} else {
|
|
||||||
opacity = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
SequentialAnimation {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Kirigami.Units.longDuration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageParticle {
|
|
||||||
source: "qrc:/qt/qml/org/kde/neochat/qml/confetti.png"
|
|
||||||
entryEffect: ImageParticle.Scale
|
|
||||||
rotationVariation: 360
|
|
||||||
rotationVelocity: 90
|
|
||||||
color: Qt.hsla(Math.random(), 0.5, 0.6, 1)
|
|
||||||
colorVariation: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Emitter {
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
top: parent.top
|
|
||||||
}
|
|
||||||
|
|
||||||
sizeVariation: Kirigami.Units.iconSizes.small / 2
|
|
||||||
lifeSpan: Kirigami.Units.veryLongDuration * 10
|
|
||||||
size: Kirigami.Units.iconSizes.small
|
|
||||||
|
|
||||||
velocity: AngleDirection {
|
|
||||||
angle: 90
|
|
||||||
angleVariation: 42
|
|
||||||
magnitude: 500
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Snow
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: snowTimer
|
|
||||||
interval: root.effectInterval
|
|
||||||
running: false
|
|
||||||
repeat: false
|
|
||||||
triggeredOnStart: true
|
|
||||||
onTriggered: {
|
|
||||||
if (root.enabled) {
|
|
||||||
snowSystem.running = !snowSystem.running;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticleSystem {
|
|
||||||
id: snowSystem
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
running: false
|
|
||||||
onRunningChanged: {
|
|
||||||
if (running) {
|
|
||||||
opacity = 1;
|
|
||||||
} else {
|
|
||||||
opacity = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
SequentialAnimation {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Kirigami.Units.longDuration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemParticle {
|
|
||||||
delegate: Rectangle {
|
|
||||||
width: 10
|
|
||||||
height: width
|
|
||||||
radius: width
|
|
||||||
color: root.isThemeDark ? "white" : darkSnowColor
|
|
||||||
scale: Math.random()
|
|
||||||
opacity: Math.random()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Emitter {
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
top: parent.top
|
|
||||||
}
|
|
||||||
|
|
||||||
sizeVariation: Kirigami.Units.iconSizes.medium
|
|
||||||
lifeSpan: Kirigami.Units.veryLongDuration * 10
|
|
||||||
size: Kirigami.Units.iconSizes.large
|
|
||||||
emitRate: 42
|
|
||||||
|
|
||||||
velocity: AngleDirection {
|
|
||||||
angle: 90
|
|
||||||
angleVariation: 10
|
|
||||||
magnitude: 300
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fireworks
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: fireworksTimer
|
|
||||||
interval: root.effectInterval
|
|
||||||
running: false
|
|
||||||
repeat: false
|
|
||||||
triggeredOnStart: true
|
|
||||||
onTriggered: {
|
|
||||||
if (root.enabled) {
|
|
||||||
fireworksInternalTimer.running = !fireworksInternalTimer.running;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: fireworksInternalTimer
|
|
||||||
interval: 300
|
|
||||||
triggeredOnStart: true
|
|
||||||
running: false
|
|
||||||
repeat: true
|
|
||||||
onTriggered: {
|
|
||||||
var x = Math.random() * parent.width;
|
|
||||||
var y = Math.random() * parent.height;
|
|
||||||
customEmit(x, y);
|
|
||||||
customEmit(x, y);
|
|
||||||
customEmit(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticleSystem {
|
|
||||||
id: fireworksSystem
|
|
||||||
anchors.fill: parent
|
|
||||||
running: fireworksInternalTimer.running
|
|
||||||
onRunningChanged: {
|
|
||||||
if (running) {
|
|
||||||
opacity = 1;
|
|
||||||
} else {
|
|
||||||
opacity = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
SequentialAnimation {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Kirigami.Units.longDuration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageParticle {
|
|
||||||
id: fireworksParticleA
|
|
||||||
system: fireworksSystem
|
|
||||||
source: "qrc:/qt/qml/org/kde/neochat/qml/glowdot.png"
|
|
||||||
alphaVariation: root.isThemeDark ? 0.1 : 0.1
|
|
||||||
alpha: root.isThemeDark ? 0.5 : 1
|
|
||||||
groups: ["a"]
|
|
||||||
opacity: fireworksSystem.opacity
|
|
||||||
entryEffect: ImageParticle.Scale
|
|
||||||
rotationVariation: 360
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageParticle {
|
|
||||||
system: fireworksSystem
|
|
||||||
source: "qrc:/qt/qml/org/kde/neochat/qml/glowdot.png"
|
|
||||||
color: root.isThemeDark ? "white" : "gold"
|
|
||||||
alphaVariation: root.isThemeDark ? 0.1 : 0.1
|
|
||||||
alpha: root.isThemeDark ? 0.5 : 1
|
|
||||||
groups: ["light"]
|
|
||||||
opacity: fireworksSystem.opacity
|
|
||||||
entryEffect: ImageParticle.Scale
|
|
||||||
rotationVariation: 360
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageParticle {
|
|
||||||
id: fireworksParticleB
|
|
||||||
system: fireworksSystem
|
|
||||||
source: "qrc:/qt/qml/org/kde/neochat/qml/glowdot.png"
|
|
||||||
alphaVariation: root.isThemeDark ? 0.1 : 0.1
|
|
||||||
alpha: root.isThemeDark ? 0.5 : 1
|
|
||||||
groups: ["b"]
|
|
||||||
opacity: fireworksSystem.opacity
|
|
||||||
entryEffect: ImageParticle.Scale
|
|
||||||
rotationVariation: 360
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: emitterComp
|
|
||||||
Emitter {
|
|
||||||
id: container
|
|
||||||
property int life: 23
|
|
||||||
property real targetX: 0
|
|
||||||
property real targetY: 0
|
|
||||||
width: 1
|
|
||||||
height: 1
|
|
||||||
system: fireworksSystem
|
|
||||||
size: 16
|
|
||||||
endSize: 8
|
|
||||||
sizeVariation: 5
|
|
||||||
Timer {
|
|
||||||
interval: life
|
|
||||||
running: true
|
|
||||||
onTriggered: {
|
|
||||||
container.destroy();
|
|
||||||
var randomHue = Math.random();
|
|
||||||
var lightness = root.isThemeDark ? 0.8 : 0.7;
|
|
||||||
fireworksParticleA.color = Qt.hsla(randomHue, 0.8, lightness, 1);
|
|
||||||
fireworksParticleB.color = Qt.hsla(1 - randomHue, 0.8, lightness, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
velocity: AngleDirection {
|
|
||||||
angleVariation: 360
|
|
||||||
magnitude: 200
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function customEmit(x, y) {
|
|
||||||
var currentSize = Math.round(Math.random() * 200) + 40;
|
|
||||||
var currentLifeSpan = Math.round(Math.random() * 1000) + 100;
|
|
||||||
for (var i = 0; i < 8; i++) {
|
|
||||||
var obj = emitterComp.createObject(parent);
|
|
||||||
obj.x = x;
|
|
||||||
obj.y = y;
|
|
||||||
obj.targetX = Math.random() * currentSize - currentSize / 2 + obj.x;
|
|
||||||
obj.targetY = Math.random() * currentSize - currentSize / 2 + obj.y;
|
|
||||||
obj.life = Math.round(Math.random() * 23) + 150;
|
|
||||||
obj.emitRate = Math.round(Math.random() * 32) + 5;
|
|
||||||
obj.lifeSpan = currentLifeSpan;
|
|
||||||
const group = Math.round(Math.random() * 3);
|
|
||||||
switch (group) {
|
|
||||||
case 0:
|
|
||||||
obj.group = "light";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
obj.group = "a";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
obj.group = "b";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,6 +16,8 @@ Kirigami.ApplicationWindow {
|
|||||||
|
|
||||||
property NeoChatConnection connection: Controller.activeConnection
|
property NeoChatConnection connection: Controller.activeConnection
|
||||||
|
|
||||||
|
title: Config.windowTitleFocus ? activeFocusItem + " " + (activeFocusItem ? activeFocusItem.Accessible.name : "") : "NeoChat"
|
||||||
|
|
||||||
minimumWidth: Kirigami.Units.gridUnit * 20
|
minimumWidth: Kirigami.Units.gridUnit * 20
|
||||||
minimumHeight: Kirigami.Units.gridUnit * 15
|
minimumHeight: Kirigami.Units.gridUnit * 15
|
||||||
|
|
||||||
@@ -96,12 +98,9 @@ Kirigami.ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
QuickSwitcher {
|
||||||
id: quickView
|
id: quickSwitcher
|
||||||
active: !Kirigami.Settings.isMobile
|
connection: root.connection
|
||||||
sourceComponent: QuickSwitcher {
|
|
||||||
connection: root.connection
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -160,8 +159,11 @@ Kirigami.ApplicationWindow {
|
|||||||
|
|
||||||
connection: root.connection
|
connection: root.connection
|
||||||
|
|
||||||
handleOpenIcon.source: "arrow-right"
|
handleClosedIcon.source: "documentinfo-symbolic"
|
||||||
handleClosedIcon.source: "arrow-left"
|
handleClosedToolTip: i18nc("@action:button", "Show Room Information")
|
||||||
|
|
||||||
|
// Default icon is fine, only need to override the tooltip text
|
||||||
|
handleOpenToolTip: i18nc("@action:button", "Close Room Information Drawer")
|
||||||
|
|
||||||
// Connect to the onClicked function of the RoomDrawer handle button
|
// Connect to the onClicked function of the RoomDrawer handle button
|
||||||
Connections {
|
Connections {
|
||||||
@@ -221,6 +223,8 @@ Kirigami.ApplicationWindow {
|
|||||||
RoomListPage {
|
RoomListPage {
|
||||||
id: roomList
|
id: roomList
|
||||||
|
|
||||||
|
onSearch: quickSwitcher.open()
|
||||||
|
|
||||||
connection: root.connection
|
connection: root.connection
|
||||||
|
|
||||||
Shortcut {
|
Shortcut {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import QtQuick.Controls as QQC2
|
|||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
|
||||||
import org.kde.kirigami as Kirigami
|
import org.kde.kirigami as Kirigami
|
||||||
|
import org.kde.kirigamiaddons.components
|
||||||
import org.kde.kitemmodels
|
import org.kde.kitemmodels
|
||||||
|
|
||||||
import org.kde.neochat
|
import org.kde.neochat
|
||||||
@@ -19,10 +20,10 @@ QQC2.Dialog {
|
|||||||
width: Math.min(700, parent.width)
|
width: Math.min(700, parent.width)
|
||||||
height: 400
|
height: 400
|
||||||
|
|
||||||
leftPadding: 0
|
leftPadding: Kirigami.Units.smallSpacing
|
||||||
rightPadding: 0
|
rightPadding: Kirigami.Units.smallSpacing
|
||||||
bottomPadding: 1
|
bottomPadding: Kirigami.Units.smallSpacing
|
||||||
topPadding: 0
|
topPadding: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
anchors.centerIn: applicationWindow().overlay
|
anchors.centerIn: applicationWindow().overlay
|
||||||
|
|
||||||
@@ -40,53 +41,60 @@ QQC2.Dialog {
|
|||||||
roomList.currentIndex = 0;
|
roomList.currentIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
header: Kirigami.SearchField {
|
background: DialogRoundedBackground {}
|
||||||
id: searchField
|
|
||||||
Keys.onDownPressed: {
|
contentItem: ColumnLayout {
|
||||||
roomList.forceActiveFocus();
|
Kirigami.SearchField {
|
||||||
if (roomList.currentIndex < roomList.count - 1) {
|
id: searchField
|
||||||
roomList.currentIndex++;
|
Layout.fillWidth: true
|
||||||
} else {
|
Keys.onDownPressed: {
|
||||||
roomList.currentIndex = 0;
|
roomList.forceActiveFocus();
|
||||||
|
if (roomList.currentIndex < roomList.count - 1) {
|
||||||
|
roomList.currentIndex++;
|
||||||
|
} else {
|
||||||
|
roomList.currentIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Keys.onUpPressed: {
|
||||||
Keys.onUpPressed: {
|
if (roomList.currentIndex === 0) {
|
||||||
if (roomList.currentIndex === 0) {
|
roomList.currentIndex = roomList.count - 1;
|
||||||
roomList.currentIndex = roomList.count - 1;
|
} else {
|
||||||
} else {
|
roomList.currentIndex--;
|
||||||
roomList.currentIndex--;
|
}
|
||||||
}
|
}
|
||||||
|
Keys.onEnterPressed: {
|
||||||
|
RoomManager.resolveResource(roomList.currentItem.currentRoom.id);
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
RoomManager.resolveResource(roomList.currentItem.currentRoom.id);
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
|
focusSequence: ""
|
||||||
|
onTextChanged: RoomManager.sortFilterRoomListModel.filterText = text
|
||||||
}
|
}
|
||||||
Keys.onEnterPressed: {
|
|
||||||
RoomManager.resolveResource(roomList.currentItem.currentRoom.id);
|
|
||||||
root.close();
|
|
||||||
}
|
|
||||||
Keys.onReturnPressed: {
|
|
||||||
RoomManager.resolveResource(roomList.currentItem.currentRoom.id);
|
|
||||||
root.close();
|
|
||||||
}
|
|
||||||
focusSequence: ""
|
|
||||||
onTextChanged: RoomManager.sortFilterRoomListModel.filterText = text
|
|
||||||
}
|
|
||||||
|
|
||||||
QQC2.ScrollView {
|
QQC2.ScrollView {
|
||||||
anchors.fill: parent
|
clip: true
|
||||||
clip: true
|
|
||||||
|
|
||||||
Keys.forwardTo: searchField
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
ListView {
|
|
||||||
id: roomList
|
|
||||||
|
|
||||||
currentIndex: 0
|
|
||||||
highlightMoveDuration: 200
|
|
||||||
Keys.forwardTo: searchField
|
Keys.forwardTo: searchField
|
||||||
keyNavigationEnabled: true
|
|
||||||
model: RoomManager.sortFilterRoomListModel
|
|
||||||
|
|
||||||
delegate: RoomDelegate {
|
ListView {
|
||||||
connection: root.connection
|
id: roomList
|
||||||
onClicked: root.close()
|
|
||||||
|
currentIndex: 0
|
||||||
|
highlightMoveDuration: 200
|
||||||
|
Keys.forwardTo: searchField
|
||||||
|
keyNavigationEnabled: true
|
||||||
|
model: RoomManager.sortFilterRoomListModel
|
||||||
|
|
||||||
|
delegate: RoomDelegate {
|
||||||
|
connection: root.connection
|
||||||
|
onClicked: root.close()
|
||||||
|
showConfigure: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ Delegates.RoundedItemDelegate {
|
|||||||
required property string subtitleText
|
required property string subtitleText
|
||||||
required property string displayName
|
required property string displayName
|
||||||
|
|
||||||
|
property bool showConfigure: true
|
||||||
|
|
||||||
property bool collapsed: false
|
property bool collapsed: false
|
||||||
|
|
||||||
readonly property bool hasNotifications: contextNotificationCount > 0
|
readonly property bool hasNotifications: contextNotificationCount > 0
|
||||||
@@ -130,7 +132,7 @@ Delegates.RoundedItemDelegate {
|
|||||||
|
|
||||||
QQC2.Button {
|
QQC2.Button {
|
||||||
id: configButton
|
id: configButton
|
||||||
visible: root.hovered && !Kirigami.Settings.isMobile && !Config.compactRoomList && !root.collapsed
|
visible: root.hovered && !Kirigami.Settings.isMobile && !Config.compactRoomList && !root.collapsed && root.showConfigure
|
||||||
text: i18n("Configure room")
|
text: i18n("Configure room")
|
||||||
display: QQC2.Button.IconOnly
|
display: QQC2.Button.IconOnly
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ Kirigami.OverlayDrawer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onOpened: forceActiveFocus()
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ QQC2.ScrollView {
|
|||||||
visible: !root.room.isSpace
|
visible: !root.room.isSpace
|
||||||
icon.name: "search"
|
icon.name: "search"
|
||||||
text: i18n("Search in this room")
|
text: i18n("Search in this room")
|
||||||
|
activeFocusOnTab: true
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
@@ -96,6 +97,8 @@ QQC2.ScrollView {
|
|||||||
|
|
||||||
onClicked: root.room.isFavourite ? root.room.removeTag("m.favourite") : root.room.addTag("m.favourite", 1.0)
|
onClicked: root.room.isFavourite ? root.room.removeTag("m.favourite") : root.room.addTag("m.favourite", 1.0)
|
||||||
|
|
||||||
|
activeFocusOnTab: true
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +107,7 @@ QQC2.ScrollView {
|
|||||||
visible: !root.room.isSpace
|
visible: !root.room.isSpace
|
||||||
icon.name: "map-flat"
|
icon.name: "map-flat"
|
||||||
text: i18n("Show locations for this room")
|
text: i18n("Show locations for this room")
|
||||||
|
activeFocusOnTab: true
|
||||||
|
|
||||||
onClicked: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'LocationsPage'), {
|
onClicked: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'LocationsPage'), {
|
||||||
room: root.room
|
room: root.room
|
||||||
@@ -118,6 +122,7 @@ QQC2.ScrollView {
|
|||||||
id: leaveButton
|
id: leaveButton
|
||||||
icon.name: "arrow-left"
|
icon.name: "arrow-left"
|
||||||
text: i18nc("@action:button", "Leave this room")
|
text: i18nc("@action:button", "Leave this room")
|
||||||
|
activeFocusOnTab: true
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
@@ -193,11 +198,12 @@ QQC2.ScrollView {
|
|||||||
model: root.room.isDirectChat() ? 0 : sortedMessageEventModel
|
model: root.room.isDirectChat() ? 0 : sortedMessageEventModel
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
activeFocusOnTab: true
|
focus: true
|
||||||
|
|
||||||
delegate: Delegates.RoundedItemDelegate {
|
delegate: Delegates.RoundedItemDelegate {
|
||||||
id: userDelegate
|
id: userDelegate
|
||||||
|
|
||||||
|
required property int index
|
||||||
required property string name
|
required property string name
|
||||||
required property string userId
|
required property string userId
|
||||||
required property string avatar
|
required property string avatar
|
||||||
@@ -208,6 +214,9 @@ QQC2.ScrollView {
|
|||||||
|
|
||||||
text: name
|
text: name
|
||||||
|
|
||||||
|
KeyNavigation.tab: navigationBar.tabGroup.checkedButton
|
||||||
|
KeyNavigation.backtab: index === 0 ? userList.headerItem.userListSearchField : null
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
userDelegate.highlighted = true;
|
userDelegate.highlighted = true;
|
||||||
RoomManager.resolveResource(userDelegate.userId, "mention");
|
RoomManager.resolveResource(userDelegate.userId, "mention");
|
||||||
@@ -260,8 +269,8 @@ QQC2.ScrollView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRoomChanged: {
|
onRoomChanged: {
|
||||||
if (root.headerItem) {
|
if (userList.headerItem) {
|
||||||
root.headerItem.userListSearchField.text = "";
|
userList.headerItem.userListSearchField.text = "";
|
||||||
}
|
}
|
||||||
userList.currentIndex = -1;
|
userList.currentIndex = -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ Kirigami.Page {
|
|||||||
|
|
||||||
readonly property bool collapsed: Config.collapsed
|
readonly property bool collapsed: Config.collapsed
|
||||||
|
|
||||||
|
signal search
|
||||||
|
|
||||||
onCurrentWidthChanged: pageStack.defaultColumnWidth = root.currentWidth
|
onCurrentWidthChanged: pageStack.defaultColumnWidth = root.currentWidth
|
||||||
Component.onCompleted: pageStack.defaultColumnWidth = root.currentWidth
|
Component.onCompleted: pageStack.defaultColumnWidth = root.currentWidth
|
||||||
|
|
||||||
@@ -40,41 +42,41 @@ Kirigami.Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function goToNextRoomFiltered(condition) {
|
function goToNextRoomFiltered(condition) {
|
||||||
let index = treeView.currentIndex;
|
let index = treeView.rowAtIndex(RoomManager.sortFilterRoomTreeModel.currentRoomIndex());
|
||||||
while (index++ !== treeView.count - 1) {
|
while (index++ < treeView.rows) {
|
||||||
if (condition(treeView.itemAtIndex(index))) {
|
let item = treeView.itemAtIndex(treeView.index(index, 0))
|
||||||
treeView.currentIndex = index;
|
if (condition(item)) {
|
||||||
treeView.currentItem.clicked();
|
RoomManager.resolveResource(item.currentRoom.id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToPreviousRoomFiltered(condition) {
|
function goToPreviousRoomFiltered(condition) {
|
||||||
let index = treeView.currentIndex;
|
let index = treeView.rowAtIndex(RoomManager.sortFilterRoomTreeModel.currentRoomIndex());
|
||||||
while (index-- !== 0) {
|
while (index-- > 0) {
|
||||||
if (condition(treeView.itemAtIndex(index))) {
|
let item = treeView.itemAtIndex(treeView.index(index, 0))
|
||||||
treeView.currentIndex = index;
|
if (condition(item)) {
|
||||||
treeView.currentItem.clicked();
|
RoomManager.resolveResource(item.currentRoom.id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToNextRoom() {
|
function goToNextRoom() {
|
||||||
goToNextRoomFiltered(item => item.visible);
|
goToNextRoomFiltered(item => (item && item instanceof RoomDelegate));
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToPreviousRoom() {
|
function goToPreviousRoom() {
|
||||||
goToPreviousRoomFiltered(item => item.visible);
|
goToPreviousRoomFiltered(item => (item && item instanceof RoomDelegate));
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToNextUnreadRoom() {
|
function goToNextUnreadRoom() {
|
||||||
goToNextRoomFiltered(item => (item.visible && item.hasUnread));
|
goToNextRoomFiltered(item => (item && item instanceof RoomDelegate && item.hasUnread));
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToPreviousUnreadRoom() {
|
function goToPreviousUnreadRoom() {
|
||||||
goToPreviousRoomFiltered(item => (item.visible && item.hasUnread));
|
goToPreviousRoomFiltered(item => (item && item instanceof RoomDelegate && item.hasUnread));
|
||||||
}
|
}
|
||||||
|
|
||||||
titleDelegate: Loader {
|
titleDelegate: Loader {
|
||||||
@@ -89,6 +91,10 @@ Kirigami.Page {
|
|||||||
function onCurrentSpaceChanged() {
|
function onCurrentSpaceChanged() {
|
||||||
treeView.expandRecursively();
|
treeView.expandRecursively();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onCurrentRoomChanged() {
|
||||||
|
treeView.positionViewAtIndex(RoomManager.sortFilterRoomTreeModel.currentRoomIndex(), TableView.AlignVCenter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
@@ -160,22 +166,6 @@ Kirigami.Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: "search"
|
|
||||||
delegate: Delegates.RoundedItemDelegate {
|
|
||||||
required property TreeView treeView
|
|
||||||
|
|
||||||
implicitWidth: treeView.width
|
|
||||||
onClicked: quickView.item.open()
|
|
||||||
|
|
||||||
contentItem: Kirigami.Icon {
|
|
||||||
width: Kirigami.Units.iconSizes.smallMedium
|
|
||||||
height: Kirigami.Units.iconSizes.smallMedium
|
|
||||||
source: "search"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "addDirect"
|
roleValue: "addDirect"
|
||||||
delegate: Delegates.RoundedItemDelegate {
|
delegate: Delegates.RoundedItemDelegate {
|
||||||
@@ -308,6 +298,8 @@ Kirigami.Page {
|
|||||||
collapsed: root.collapsed
|
collapsed: root.collapsed
|
||||||
connection: root.connection
|
connection: root.connection
|
||||||
|
|
||||||
|
onSearch: root.search()
|
||||||
|
|
||||||
onTextChanged: newText => {
|
onTextChanged: newText => {
|
||||||
RoomManager.sortFilterRoomTreeModel.filterText = newText;
|
RoomManager.sortFilterRoomTreeModel.filterText = newText;
|
||||||
treeView.expandRecursively();
|
treeView.expandRecursively();
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user