Compare commits
1 Commits
work/tobia
...
work/redst
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e0f0182cb |
@@ -2,5 +2,7 @@
|
||||
; SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
[BlueprintSettings]
|
||||
kde/frameworks/extra-cmake-modules.version=master
|
||||
kde/unreleased/kirigami-addons.version=master
|
||||
kde/applications/neochat.packageAppx=True
|
||||
libs/qt.qtMajorVersion=6
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"id": "org.kde.neochat",
|
||||
"branch": "master",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "6.9",
|
||||
"runtime-version": "6.8",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"command": "neochat",
|
||||
"tags": [
|
||||
@@ -20,16 +20,8 @@
|
||||
"--talk-name=org.kde.kwalletd5",
|
||||
"--talk-name=org.kde.StatusNotifierWatcher",
|
||||
"--talk-name=org.freedesktop.secrets",
|
||||
"--talk-name=org.kde.kuiserver",
|
||||
"--own-name=org.kde.StatusNotifierItem-2-2"
|
||||
],
|
||||
"cleanup": [
|
||||
"/include",
|
||||
"/lib/*.a",
|
||||
"/lib/cmake",
|
||||
"/lib/pkgconfig",
|
||||
"/share/ndk-modules"
|
||||
],
|
||||
"modules": [
|
||||
{
|
||||
"name": "kirigamiaddons",
|
||||
@@ -90,8 +82,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://download.gnome.org/sources/libsecret/0.21/libsecret-0.21.7.tar.xz",
|
||||
"sha256": "6b452e4750590a2b5617adc40026f28d2f4903de15f1250e1d1c40bfd68ed55e",
|
||||
"url": "https://download.gnome.org/sources/libsecret/0.21/libsecret-0.21.6.tar.xz",
|
||||
"sha256": "747b8c175be108c880d3adfb9c3537ea66e520e4ad2dccf5dce58003aeeca090",
|
||||
"x-checker-data": {
|
||||
"type": "gnome",
|
||||
"name": "libsecret",
|
||||
@@ -157,6 +149,27 @@
|
||||
],
|
||||
"builddir": true
|
||||
},
|
||||
{
|
||||
"name": "qcoro",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"config-opts": [
|
||||
"-DQCORO_BUILD_EXAMPLES=OFF",
|
||||
"-DBUILD_TESTING=OFF"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/danvratil/qcoro/archive/refs/tags/v0.11.0.tar.gz",
|
||||
"sha256": "9942c5b4c533192f6c5954dc6d10178b3829075e6a621b67df73f0a4b74d8297",
|
||||
"x-checker-data": {
|
||||
"type": "anitya",
|
||||
"project-id": 236236,
|
||||
"stable-only": true,
|
||||
"url-template": "https://github.com/danvratil/qcoro/archive/refs/tags/v$version.tar.gz"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "kunifiedpush",
|
||||
"buildsystem": "cmake-ninja",
|
||||
@@ -164,13 +177,13 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://download.kde.org/stable/release-service/25.04.3/src/kunifiedpush-25.04.3.tar.xz",
|
||||
"sha256": "a16ffe4117b14baa02f3b8ae7de9e509a17359c1b67dcd851aef4f3c3661a1df",
|
||||
"url": "https://download.kde.org/stable/kunifiedpush/kunifiedpush-1.0.0.tar.xz",
|
||||
"sha256": "2ddeba21306d0307114ec50a2c38159ec62359f9fc6cdd58da30a369fbd550cf",
|
||||
"x-checker-data": {
|
||||
"type": "anitya",
|
||||
"project-id": 8763,
|
||||
"project-id": 375055,
|
||||
"stable-only": true,
|
||||
"url-template": "https://download.kde.org/stable/release-service/$version/src/kunifiedpush-$version.tar.xz"
|
||||
"url-template": "https://download.kde.org/stable/kunifiedpush/kunifiedpush-$version.tar.xz"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# KDE Applications version, managed by release script.
|
||||
set(RELEASE_SERVICE_VERSION_MAJOR "25")
|
||||
set(RELEASE_SERVICE_VERSION_MINOR "11")
|
||||
set(RELEASE_SERVICE_VERSION_MINOR "07")
|
||||
set(RELEASE_SERVICE_VERSION_MICRO "70")
|
||||
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <QObject>
|
||||
#include <QTest>
|
||||
|
||||
#include <QSignalSpy>
|
||||
#include <Quotient/roommember.h>
|
||||
#include <Quotient/syncdata.h>
|
||||
#include <qtestcase.h>
|
||||
@@ -33,7 +32,6 @@ private Q_SLOTS:
|
||||
void noRoom();
|
||||
void badParent();
|
||||
void reply();
|
||||
void replyMissingUser();
|
||||
void edit();
|
||||
void attachment();
|
||||
};
|
||||
@@ -104,33 +102,6 @@ void ChatBarCacheTest::reply()
|
||||
QCOMPARE(chatBarCache->relationAuthor(), room->member(u"@example:example.org"_s));
|
||||
QCOMPARE(chatBarCache->relationMessage(), u"This is an example\ntext message"_s);
|
||||
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
||||
QCOMPARE(chatBarCache->relationAuthorIsPresent(), true);
|
||||
}
|
||||
|
||||
void ChatBarCacheTest::replyMissingUser()
|
||||
{
|
||||
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
|
||||
chatBarCache->setText(u"some text"_s);
|
||||
chatBarCache->setAttachmentPath(u"some/path"_s);
|
||||
chatBarCache->setReplyId(u"$153456789:example.org"_s);
|
||||
|
||||
QCOMPARE(chatBarCache->text(), u"some text"_s);
|
||||
QCOMPARE(chatBarCache->isReplying(), true);
|
||||
QCOMPARE(chatBarCache->replyId(), u"$153456789:example.org"_s);
|
||||
QCOMPARE(chatBarCache->isEditing(), false);
|
||||
QCOMPARE(chatBarCache->editId(), QString());
|
||||
QCOMPARE(chatBarCache->relationAuthor(), room->member(u"@example:example.org"_s));
|
||||
QCOMPARE(chatBarCache->relationMessage(), u"This is an example\ntext message"_s);
|
||||
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
||||
QCOMPARE(chatBarCache->relationAuthorIsPresent(), true);
|
||||
|
||||
QSignalSpy relationAuthorIsPresentSpy(chatBarCache.get(), &ChatBarCache::relationAuthorIsPresentChanged);
|
||||
|
||||
// sync again, which will simulate the reply user leaving the room
|
||||
room->syncNewEvents(u"test-min-sync-extra-sync.json"_s);
|
||||
|
||||
QTRY_COMPARE(relationAuthorIsPresentSpy.count(), 1);
|
||||
QCOMPARE(chatBarCache->relationAuthorIsPresent(), false);
|
||||
}
|
||||
|
||||
void ChatBarCacheTest::edit()
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"state": {
|
||||
"events": [
|
||||
{
|
||||
"content": {
|
||||
"membership": "leave"
|
||||
},
|
||||
"event_id": "$1432735824666PhrSA:example.org",
|
||||
"origin_server_ts": 1432735824666,
|
||||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||
"sender": "@example:example.org",
|
||||
"state_key": "@example:example.org",
|
||||
"type": "m.room.member",
|
||||
"unsigned": {
|
||||
"replaces_state": "$143273582443PhrSn:example.org"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -130,8 +130,7 @@ void EventHandlerTest::timeString()
|
||||
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)).toLocalTime().time(), QLocale::ShortFormat));
|
||||
QCOMPARE(EventHandler::timeString(room, event, true),
|
||||
format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)).toLocalTime().date(), QLocale::ShortFormat));
|
||||
QCOMPARE(EventHandler::timeString(room, event, u"hh:mm"_s),
|
||||
QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::LocalTime)).toString(u"hh:mm"_s));
|
||||
QCOMPARE(EventHandler::timeString(room, event, u"hh:mm"_s), QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)).toString(u"hh:mm"_s));
|
||||
|
||||
const auto txID = room->postJson("m.room.message"_L1, event->fullJson());
|
||||
QCOMPARE(room->pendingEvents().size(), 1);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <Quotient/roommember.h>
|
||||
#include <Quotient/syncdata.h>
|
||||
|
||||
#include "models/eventmessagecontentmodel.h"
|
||||
#include "models/messagecontentmodel.h"
|
||||
|
||||
#include "neochatconnection.h"
|
||||
#include "testutils.h"
|
||||
@@ -39,13 +39,13 @@ void MessageContentModelTest::initTestCase()
|
||||
void MessageContentModelTest::missingEvent()
|
||||
{
|
||||
auto room = new TestUtils::TestRoom(connection, u"#firstRoom:kde.org"_s);
|
||||
auto model1 = EventMessageContentModel(room, u"$153456789:example.org"_s);
|
||||
auto model1 = MessageContentModel(room, u"$153456789:example.org"_s);
|
||||
|
||||
QCOMPARE(model1.rowCount(), 1);
|
||||
QCOMPARE(model1.data(model1.index(0), MessageContentModel::ComponentTypeRole), MessageComponentType::Loading);
|
||||
QCOMPARE(model1.data(model1.index(0), MessageContentModel::DisplayRole), u"Loading"_s);
|
||||
|
||||
auto model2 = EventMessageContentModel(room, u"$153456789:example.org"_s, true);
|
||||
auto model2 = MessageContentModel(room, u"$153456789:example.org"_s, true);
|
||||
|
||||
QCOMPARE(model2.rowCount(), 1);
|
||||
QCOMPARE(model2.data(model2.index(0), MessageContentModel::ComponentTypeRole), MessageComponentType::Loading);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <Quotient/events/roommessageevent.h>
|
||||
|
||||
#include "models/eventmessagecontentmodel.h"
|
||||
#include "models/messagecontentmodel.h"
|
||||
#include "testutils.h"
|
||||
|
||||
using namespace Quotient;
|
||||
@@ -21,7 +21,7 @@ class ReactionModelTest : public QObject
|
||||
private:
|
||||
Connection *connection = nullptr;
|
||||
TestUtils::TestRoom *room = nullptr;
|
||||
EventMessageContentModel *parentModel;
|
||||
MessageContentModel *parentModel;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
@@ -34,7 +34,7 @@ void ReactionModelTest::initTestCase()
|
||||
{
|
||||
connection = Connection::makeMockConnection(u"@bob:kde.org"_s);
|
||||
room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-reactionmodel-sync.json"_s);
|
||||
parentModel = new EventMessageContentModel(room, "123456"_L1);
|
||||
parentModel = new MessageContentModel(room, "123456"_L1);
|
||||
}
|
||||
|
||||
void ReactionModelTest::basicReaction()
|
||||
|
||||
@@ -61,7 +61,6 @@ private Q_SLOTS:
|
||||
void receiveRichStrikethrough();
|
||||
void receiveRichtextIn();
|
||||
void receiveRichMxcUrl();
|
||||
void receiveRichPlainUrl_data();
|
||||
void receiveRichPlainUrl();
|
||||
void receiveRichEdited_data();
|
||||
void receiveRichEdited();
|
||||
@@ -451,32 +450,6 @@ void TextHandlerTest::receiveRichMxcUrl()
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, room->messageEvents().at(0).get()), testOutputString);
|
||||
}
|
||||
|
||||
void TextHandlerTest::receiveRichPlainUrl_data()
|
||||
{
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<QString>("output");
|
||||
|
||||
// This is an actual link that caused trouble which is why it's so long. Keeping
|
||||
// so we can confirm consistent behaviour for complex urls.
|
||||
QTest::addRow("link 1")
|
||||
<< u"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im <a href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">Link already rich</a>"_s
|
||||
<< u"<a href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im</a> <a href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">Link already rich</a>"_s;
|
||||
|
||||
// Another real case. The linkification wasn't handling it when a single link
|
||||
// contains what looks like and email. It was broken into 3 but needs to
|
||||
// be just single link.
|
||||
QTest::addRow("link 2")
|
||||
<< u"https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/"_s
|
||||
<< u"<a href=\"https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/\">https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/</a>"_s;
|
||||
|
||||
QTest::addRow("email") << uR"(email@example.com <a href="mailto:email@example.com">Link already rich</a>)"_s
|
||||
<< uR"(<a href="mailto:email@example.com">email@example.com</a> <a href="mailto:email@example.com">Link already rich</a>)"_s;
|
||||
QTest::addRow("mxid")
|
||||
<< u"@user:kde.org <a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a>"_s
|
||||
<< u"<b><a href=\"https://matrix.to/#/@user:kde.org\">@user:kde.org</a></b> <b><a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a></b>"_s;
|
||||
QTest::addRow("mxid with prefix") << u"a @user:kde.org b"_s << u"a <b><a href=\"https://matrix.to/#/@user:kde.org\">@user:kde.org</a></b> b"_s;
|
||||
}
|
||||
|
||||
/**
|
||||
* For when your rich input string has a plain text url left in.
|
||||
*
|
||||
@@ -485,13 +458,46 @@ void TextHandlerTest::receiveRichPlainUrl_data()
|
||||
*/
|
||||
void TextHandlerTest::receiveRichPlainUrl()
|
||||
{
|
||||
QFETCH(QString, input);
|
||||
QFETCH(QString, output);
|
||||
// This is an actual link that caused trouble which is why it's so long. Keeping
|
||||
// so we can confirm consistent behaviour for complex urls.
|
||||
const QString testInputStringLink1 =
|
||||
u"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im <a href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">Link already rich</a>"_s;
|
||||
const QString testOutputStringLink1 =
|
||||
u"<a href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im</a> <a href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">Link already rich</a>"_s;
|
||||
|
||||
// Another real case. The linkification wasn't handling it when a single link
|
||||
// contains what looks like and email. It was been broken into 3 but needs to
|
||||
// be just single link.
|
||||
const QString testInputStringLink2 = u"https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/"_s;
|
||||
const QString testOutputStringLink2 =
|
||||
u"<a href=\"https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/\">https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/</a>"_s;
|
||||
|
||||
QString testInputStringEmail = uR"(email@example.com <a href="mailto:email@example.com">Link already rich</a>)"_s;
|
||||
QString testOutputStringEmail = uR"(<a href="mailto:email@example.com">email@example.com</a> <a href="mailto:email@example.com">Link already rich</a>)"_s;
|
||||
|
||||
QString testInputStringMxId = u"@user:kde.org <a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a>"_s;
|
||||
QString testOutputStringMxId =
|
||||
u"<b><a href=\"https://matrix.to/#/@user:kde.org\">@user:kde.org</a></b> <b><a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a></b>"_s;
|
||||
|
||||
QString testInputStringMxIdWithPrefix = u"a @user:kde.org b"_s;
|
||||
QString testOutputStringMxIdWithPrefix = u"a <b><a href=\"https://matrix.to/#/@user:kde.org\">@user:kde.org</a></b> b"_s;
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(input);
|
||||
testTextHandler.setData(testInputStringLink1);
|
||||
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), output);
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringLink1);
|
||||
|
||||
testTextHandler.setData(testInputStringLink2);
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringLink2);
|
||||
|
||||
testTextHandler.setData(testInputStringEmail);
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringEmail);
|
||||
|
||||
testTextHandler.setData(testInputStringMxId);
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringMxId);
|
||||
|
||||
testTextHandler.setData(testInputStringMxIdWithPrefix);
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringMxIdWithPrefix);
|
||||
}
|
||||
|
||||
void TextHandlerTest::receiveRichEdited_data()
|
||||
|
||||
@@ -57,7 +57,7 @@ void TimelineMessageModelTest::switchEmptyRoom()
|
||||
auto firstRoom = new TestUtils::TestRoom(connection, u"#firstRoom:kde.org"_s);
|
||||
auto secondRoom = new TestUtils::TestRoom(connection, u"#secondRoom:kde.org"_s);
|
||||
|
||||
QSignalSpy spy(model, SIGNAL(roomChanged(NeoChatRoom *, NeoChatRoom *)));
|
||||
QSignalSpy spy(model, SIGNAL(roomChanged()));
|
||||
|
||||
QCOMPARE(model->room(), nullptr);
|
||||
model->setRoom(firstRoom);
|
||||
@@ -77,7 +77,7 @@ void TimelineMessageModelTest::switchSyncedRoom()
|
||||
auto firstRoom = new TestUtils::TestRoom(connection, u"#firstRoom:kde.org"_s, u"test-messageventmodel-sync.json"_s);
|
||||
auto secondRoom = new TestUtils::TestRoom(connection, u"#secondRoom:kde.org"_s, u"test-messageventmodel-sync.json"_s);
|
||||
|
||||
QSignalSpy spy(model, SIGNAL(roomChanged(NeoChatRoom *, NeoChatRoom *)));
|
||||
QSignalSpy spy(model, SIGNAL(roomChanged()));
|
||||
|
||||
QCOMPARE(model->room(), nullptr);
|
||||
model->setRoom(firstRoom);
|
||||
@@ -208,7 +208,7 @@ void TimelineMessageModelTest::idToRow()
|
||||
auto room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-min-sync.json"_s);
|
||||
model->setRoom(room);
|
||||
|
||||
QCOMPARE(model->indexforEventId(u"$153456789:example.org"_s).row(), 0);
|
||||
QCOMPARE(model->eventIdToRow(u"$153456789:example.org"_s), 0);
|
||||
}
|
||||
|
||||
void TimelineMessageModelTest::cleanup()
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
<summary xml:lang="nl">Chat op Matrix</summary>
|
||||
<summary xml:lang="nn">Prat med via Matrix</summary>
|
||||
<summary xml:lang="pl">Rozmawiaj na Matriksie</summary>
|
||||
<summary xml:lang="pt-BR">Bate-papo na Matrix</summary>
|
||||
<summary xml:lang="ru">Общение в Matrix</summary>
|
||||
<summary xml:lang="sa">Matrix इत्यत्र गपशपं कुर्वन्तु</summary>
|
||||
<summary xml:lang="sl">Klepet na Matrixu</summary>
|
||||
@@ -110,7 +109,6 @@
|
||||
<p xml:lang="nl">NeoChat is een chat-toepassing die u het volledige voordeel van het Matrix-netwerk laat genieten. Het levert u op een veilige manier tekstberichten, video's en geluidsbestanden naar uw familie, collega's en vrienden te verzenden.</p>
|
||||
<p xml:lang="nn">NeoChat er ein prateapp som lèt deg bruka all funksjonalitet i Matrix-nettverket. Du kan utveksla tekst, lyd og videoar med vennar, familie og kollegaar på ein trygg måte.</p>
|
||||
<p xml:lang="pl">NoeChat to aplikacja do rozmów, która umożliwia wykorzystanie wszystkich możliwości Matriksa. Umożliwia wysyłanie wiadomości tekstowych, filmów i dźwięków w bezpieczny sposób do twojej rodziny, kolegów i przyjaciół.</p>
|
||||
<p xml:lang="pt-BR">O NeoChat é um aplicativo de bate-papo que permite que você aproveite ao máximo a rede Matrix. Ele oferece uma maneira segura de enviar mensagens de texto, vídeos e arquivos de áudio para sua família, colegas e amigos.</p>
|
||||
<p xml:lang="ru">NeoChat — приложение для общения, предоставляющее все преимущества сети Matrix. С его помощью можно безопасно отправлять текстовые сообщения, видеозаписи и звуковые файлы родственникам, коллегам и друзьям.</p>
|
||||
<p xml:lang="sa">NeoChat इति एकं गपशप-अनुप्रयोगं यत् भवान् Matrix-जालस्य पूर्णं लाभं ग्रहीतुं शक्नोति । एतत् भवन्तं भवतः परिवाराय, सहकारिभ्यः, मित्रेभ्यः च पाठसन्देशान्, भिडियो, श्रव्यसञ्चिकाः च प्रेषयितुं सुरक्षितं मार्गं प्रदाति ।</p>
|
||||
<p xml:lang="sl">NeoChat je aplikacija za klepet, ki vam omogoča, da v celoti izkoristite omrežje Matrix. Zagotavlja vam varen način za pošiljanje besedilnih sporočil, videoposnetkov in zvočnih datotek vaši družini, sodelavcem in prijateljem.</p>
|
||||
@@ -144,7 +142,6 @@
|
||||
<p xml:lang="nn">NeoChat har som mål å støtta all funksjonalitet i Matrix-spesifikasjonen. Førebels er alt i den gjeldande stabile spesifikasjonen støtta, med unntak av VoIP, trådar og nokre delar av ende-til-kryptering. Det finst òg andre småting som ikkje er støtta, sidan Matrix-spesifikasjon er i stadig endring, men målet er altså støtte for alt.</p>
|
||||
<p xml:lang="pl">NeoChat w zamyśle ma być pełnowartościową aplikacją wg wytycznych Matriksa. Z tego powodu, wszystko, co jest obecnie w stabilnych wytycznych z pominięciem VoIP, wątków i niektórych części szyfrowania Użytkownik-do-Użytkownika są obecnie obsługiwane. Pominięto też kilka mniejszych rzeczy ze względu na ciągły rozwój wytycznych Matriksa, lecz celem nadal jest zapewnienie obsługi wszystkich wytycznych.</p>
|
||||
<p xml:lang="pt">O NeoChat pretende ser uma aplicação completa para a especificação do Matrix. Como tal, tudo o que existe na especificação estável actual, com as notáveis excepções do VoIP, tópicos e alguns aspectos da Encriptação Ponto-a-Ponto, são suportados. Existem mais algumas omissões, devido ao facto que a norma do Matrix está em constante evolução, mas o objectivo continua a ser oferecer o suporte eventual para a norma por inteiro.</p>
|
||||
<p xml:lang="pt-BR">O NeoChat pretende ser um aplicativo completo para a especificação Matrix. Dessa forma, tudo na especificação estável atual, com as notáveis exceções de VoIP, tópicos e alguns aspectos da criptografia de ponta a ponta, é suportado. Há algumas outras pequenas omissões devido ao fato de a especificação Matrix estar em constante evolução, mas o objetivo continua sendo fornecer suporte eventual para toda a especificação.</p>
|
||||
<p xml:lang="ru">Целью создания NeoChat является полноценная реализация программы для спецификации Matrix. Как следствие, реализовано всё в текущей стабильной спецификации (за исключением голосовой интернет-связи, потоков и некоторых аспектов сквозного шифрования). Есть также несколько других незначительных пробелов, обусловленных постоянными изменениями спецификации Matrix. Тем не менее, стоит задача в итоге предоставить полную поддержку спецификации.</p>
|
||||
<p xml:lang="sa">NeoChat इत्यस्य उद्देश्यं Matrix विनिर्देशस्य कृते पूर्णतया विशेषतायुक्तः अनुप्रयोगः भवितुम् अस्ति । यथा तथा वर्तमानस्थिरविनिर्देशे सर्वं VoIP इत्यस्य उल्लेखनीयअपवादैः सह, थ्रेड्स तथा च End-to-End Encryption इत्यस्य केचन पक्षाः समर्थिताः सन्ति । अन्ये कतिचन लघु लोपाः सन्ति यतोहि Matrix spec निरन्तरं विकसितः अस्ति परन्तु उद्देश्यं सम्पूर्ण spec कृते अन्ततः समर्थनं प्रदातुं अवशिष्टम् अस्ति</p>
|
||||
<p xml:lang="sl">Neochat cilja, da bi bila popolna aplikacija po specifikaciji Matrixa. Kot takšna vsebuje vse v trenutni stabilni specifikaciji z pomembnimi izjemami pri VoIP, nitih in nekaterih vidikov šifriranja od konca do konca. Obstaja nekaj drugih manjših opustitev zaradi dejstva, da se specifikacija Matrix nenehno razvija, vendar cilj ostaja zagotoviti morebitno podporo celotni specifikaciji.</p>
|
||||
@@ -178,7 +175,6 @@
|
||||
<p xml:lang="nn">På grunn av måten Matrix-spesifikasjonen vert utvikla på, støttar NeoChat òg nokre uferdige funksjonar:</p>
|
||||
<p xml:lang="pl">Ze względu na sposób rozwoju Matriksa, NeoChat obsługuje także kilka niestabilnych możliwości. Obecnie są to:</p>
|
||||
<p xml:lang="pt">Devido à natureza do desenvolvimento da especificação do Matrix, o NeoChat também suporta diversas funcionalidades instáveis. De momento são:</p>
|
||||
<p xml:lang="pt-BR">Devido à natureza do desenvolvimento da especificação Matrix, o NeoChat também suporta diversos recursos instáveis. Atualmente, são eles:</p>
|
||||
<p xml:lang="ru">В силу природы разработки спецификации Matrix в NeoChat тоже предусмотрена поддержка многочисленных нестабильных возможностей. В текущей версии это следующие возможности:</p>
|
||||
<p xml:lang="sa">Matrix विनिर्देशविकासस्य प्रकृतेः कारणात् NeoChat अपि अनेकानाम् अस्थिरविशेषतानां समर्थनं करोति । सम्प्रति एते सन्ति :</p>
|
||||
<p xml:lang="sl">Zaradi narave razvoja specifikacije Matrixa NeoChat podpira tudi številne nestabilne zmožnosti. Trenutno so to:</p>
|
||||
@@ -191,8 +187,8 @@
|
||||
<ul>
|
||||
<li>Polls - MSC3381</li>
|
||||
<li xml:lang="ar">التصويت - MSC3381</li>
|
||||
<li xml:lang="ca">Votacions - MSC3381</li>
|
||||
<li xml:lang="ca-valencia">Votacions - MSC3381</li>
|
||||
<li xml:lang="ca">Enquestes - MSC3381</li>
|
||||
<li xml:lang="ca-valencia">Enquestes - MSC3381</li>
|
||||
<li xml:lang="el">Δημοσκοπήσεις - MSC3381</li>
|
||||
<li xml:lang="en-GB">Polls - MSC3381</li>
|
||||
<li xml:lang="eo">Enketoj - MSC3381</li>
|
||||
@@ -213,7 +209,6 @@
|
||||
<li xml:lang="nn">Avstemmingar – MSC3381</li>
|
||||
<li xml:lang="pl">Ankiety - MSC3381</li>
|
||||
<li xml:lang="pt">Inquéritos - MSC3381</li>
|
||||
<li xml:lang="pt-BR">Enquetes - MSC3381</li>
|
||||
<li xml:lang="ru">Голосования — MSC3381</li>
|
||||
<li xml:lang="sa">मतदान - MSC3381</li>
|
||||
<li xml:lang="sl">Polls - MSC3381</li>
|
||||
@@ -247,7 +242,6 @@
|
||||
<li xml:lang="nn">Klistremerke-pakkar – MSC2545</li>
|
||||
<li xml:lang="pl">Paczki naklejek - MSC2545</li>
|
||||
<li xml:lang="pt">Pacotes de Autocolantes - MSC2545</li>
|
||||
<li xml:lang="pt-BR">Pacotes de Stickers - MSC2545</li>
|
||||
<li xml:lang="ru">Наборы стикеров — MSC2545</li>
|
||||
<li xml:lang="sa">स्टिकर पैक - MSC2545</li>
|
||||
<li xml:lang="sl">Sticker Packs - MSC2545</li>
|
||||
@@ -281,7 +275,6 @@
|
||||
<li xml:lang="nn">Posisjonshendingar – MSC3488</li>
|
||||
<li xml:lang="pl">Wydarzenia w miejscach - MSC3488</li>
|
||||
<li xml:lang="pt">Eventos com Localizações - MSC3488</li>
|
||||
<li xml:lang="pt-BR">Localização de eventos - MSC3488</li>
|
||||
<li xml:lang="ru">События местоположения — MSC3488</li>
|
||||
<li xml:lang="sa">स्थान घटनाएँ - MSC3488</li>
|
||||
<li xml:lang="sl">Location Events - MSC3488</li>
|
||||
@@ -351,7 +344,6 @@
|
||||
<caption xml:lang="nn">Hovudvising med romliste, pratevindauge og rominformasjon</caption>
|
||||
<caption xml:lang="pl">Główny widok z wykazem pokojów, rozmowami i szczegółami pokojów</caption>
|
||||
<caption xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</caption>
|
||||
<caption xml:lang="pt-BR">Visão principal com lista de salas, bate-papo e informações sobre as salas</caption>
|
||||
<caption xml:lang="ru">Главное окно со списком комнат, чатом и информацией о комнате</caption>
|
||||
<caption xml:lang="sa">कक्षसूची, गपशपः, कक्षसूचना च सह मुख्यदृश्यम्</caption>
|
||||
<caption xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</caption>
|
||||
@@ -388,7 +380,6 @@
|
||||
<caption xml:lang="nl">Ontdek nieuwe gemeenschappen met Matrix-ruimten</caption>
|
||||
<caption xml:lang="nn">Oppdag nye fellesskap med Matrix Spaces</caption>
|
||||
<caption xml:lang="pl">Odkrywaj nowe społeczności w Przestrzeniach Matriksa</caption>
|
||||
<caption xml:lang="pt-BR">Descubra novas comunidades com os Espaços Matrix</caption>
|
||||
<caption xml:lang="ru">Поиск новых сообществ с помощью Matrix Spaces</caption>
|
||||
<caption xml:lang="sa">Matrix Spaces इत्यनेन सह नूतनानां समुदायानाम् अन्वेषणं कुर्वन्तु</caption>
|
||||
<caption xml:lang="sl">Odkrijte nove skupnosti z Matrix Spaces</caption>
|
||||
@@ -433,7 +424,6 @@
|
||||
<caption xml:lang="nn">Hovudvising med romliste, pratevindauge og rominformasjon</caption>
|
||||
<caption xml:lang="pl">Główny widok z wykazem pokojów, rozmowami i szczegółami pokojów</caption>
|
||||
<caption xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</caption>
|
||||
<caption xml:lang="pt-BR">Visão principal com lista de salas, bate-papo e informações sobre as salas</caption>
|
||||
<caption xml:lang="ru">Главное окно со списком комнат, чатом и информацией о комнате</caption>
|
||||
<caption xml:lang="sa">कक्षसूची, गपशपः, कक्षसूचना च सह मुख्यदृश्यम्</caption>
|
||||
<caption xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</caption>
|
||||
@@ -472,7 +462,6 @@
|
||||
<caption xml:lang="nn">Innloggingsbilete</caption>
|
||||
<caption xml:lang="pl">Ekran logowania</caption>
|
||||
<caption xml:lang="pt">Ecrã de autenticação</caption>
|
||||
<caption xml:lang="pt-BR">Tela de login</caption>
|
||||
<caption xml:lang="ru">Окно входа</caption>
|
||||
<caption xml:lang="sa">लॉगिन् स्क्रीन</caption>
|
||||
<caption xml:lang="sl">Prijavni zaslon</caption>
|
||||
@@ -488,9 +477,6 @@
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
</content_rating>
|
||||
<releases>
|
||||
<release version="25.08.0" date="2025-08-14"/>
|
||||
<release version="25.04.3" date="2025-07-03"/>
|
||||
<release version="25.04.2" date="2025-06-05"/>
|
||||
<release version="25.04.1" date="2025-05-08"/>
|
||||
<release version="25.04.0" date="2025-04-17"/>
|
||||
<release version="24.12.3" date="2025-03-06"/>
|
||||
|
||||
2055
po/ar/neochat.po
2055
po/ar/neochat.po
File diff suppressed because it is too large
Load Diff
1892
po/ast/neochat.po
1892
po/ast/neochat.po
File diff suppressed because it is too large
Load Diff
2007
po/az/neochat.po
2007
po/az/neochat.po
File diff suppressed because it is too large
Load Diff
1967
po/ca/neochat.po
1967
po/ca/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2014
po/cs/neochat.po
2014
po/cs/neochat.po
File diff suppressed because it is too large
Load Diff
1985
po/da/neochat.po
1985
po/da/neochat.po
File diff suppressed because it is too large
Load Diff
2028
po/de/neochat.po
2028
po/de/neochat.po
File diff suppressed because it is too large
Load Diff
2013
po/el/neochat.po
2013
po/el/neochat.po
File diff suppressed because it is too large
Load Diff
2027
po/en_GB/neochat.po
2027
po/en_GB/neochat.po
File diff suppressed because it is too large
Load Diff
2019
po/eo/neochat.po
2019
po/eo/neochat.po
File diff suppressed because it is too large
Load Diff
1943
po/es/neochat.po
1943
po/es/neochat.po
File diff suppressed because it is too large
Load Diff
2258
po/eu/neochat.po
2258
po/eu/neochat.po
File diff suppressed because it is too large
Load Diff
2285
po/fi/neochat.po
2285
po/fi/neochat.po
File diff suppressed because it is too large
Load Diff
2131
po/fr/neochat.po
2131
po/fr/neochat.po
File diff suppressed because it is too large
Load Diff
2359
po/gl/neochat.po
2359
po/gl/neochat.po
File diff suppressed because it is too large
Load Diff
1960
po/he/neochat.po
1960
po/he/neochat.po
File diff suppressed because it is too large
Load Diff
2023
po/hi/neochat.po
2023
po/hi/neochat.po
File diff suppressed because it is too large
Load Diff
2819
po/hu/neochat.po
2819
po/hu/neochat.po
File diff suppressed because it is too large
Load Diff
2033
po/ia/neochat.po
2033
po/ia/neochat.po
File diff suppressed because it is too large
Load Diff
2021
po/id/neochat.po
2021
po/id/neochat.po
File diff suppressed because it is too large
Load Diff
1972
po/ie/neochat.po
1972
po/ie/neochat.po
File diff suppressed because it is too large
Load Diff
1969
po/it/neochat.po
1969
po/it/neochat.po
File diff suppressed because it is too large
Load Diff
1884
po/ja/neochat.po
1884
po/ja/neochat.po
File diff suppressed because it is too large
Load Diff
1956
po/ka/neochat.po
1956
po/ka/neochat.po
File diff suppressed because it is too large
Load Diff
2221
po/ko/neochat.po
2221
po/ko/neochat.po
File diff suppressed because it is too large
Load Diff
1902
po/lt/neochat.po
1902
po/lt/neochat.po
File diff suppressed because it is too large
Load Diff
2390
po/lv/neochat.po
2390
po/lv/neochat.po
File diff suppressed because it is too large
Load Diff
1955
po/nl/neochat.po
1955
po/nl/neochat.po
File diff suppressed because it is too large
Load Diff
1985
po/nn/neochat.po
1985
po/nn/neochat.po
File diff suppressed because it is too large
Load Diff
2004
po/pa/neochat.po
2004
po/pa/neochat.po
File diff suppressed because it is too large
Load Diff
2043
po/pl/neochat.po
2043
po/pl/neochat.po
File diff suppressed because it is too large
Load Diff
2015
po/pt/neochat.po
2015
po/pt/neochat.po
File diff suppressed because it is too large
Load Diff
5441
po/pt_BR/neochat.po
5441
po/pt_BR/neochat.po
File diff suppressed because it is too large
Load Diff
@@ -1,122 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<!DOCTYPE refentry PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN" "dtd/kdedbx45.dtd" [
|
||||
<!ENTITY % Russian "INCLUDE">
|
||||
]>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
|
||||
SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
-->
|
||||
|
||||
<refentry lang="&language;">
|
||||
<refentryinfo>
|
||||
<title
|
||||
>Руководство пользователя NeoChat</title>
|
||||
<author
|
||||
><firstname
|
||||
>Carl</firstname
|
||||
><surname
|
||||
>Schwan</surname
|
||||
> <contrib
|
||||
>man-страница NeoChat.</contrib
|
||||
> <email
|
||||
>carl@carlschwan.eu</email
|
||||
></author>
|
||||
<date
|
||||
>2022-11-01</date>
|
||||
<releaseinfo
|
||||
>22.09</releaseinfo>
|
||||
<productname
|
||||
>NeoChat</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>
|
||||
<command
|
||||
>neochat</command>
|
||||
</refentrytitle>
|
||||
<manvolnum
|
||||
>1</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname
|
||||
>neochat</refname>
|
||||
<refpurpose
|
||||
>Клиент для взаимодействия с протоколом обмена сообщениями Matrix</refpurpose>
|
||||
</refnamediv>
|
||||
<!-- body begins here -->
|
||||
<refsynopsisdiv id='synopsis'>
|
||||
<cmdsynopsis
|
||||
><command
|
||||
>neochat</command
|
||||
> <arg choice="opt"
|
||||
><replaceable
|
||||
>URI</replaceable
|
||||
></arg
|
||||
> </cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsect1 id="description">
|
||||
<title
|
||||
>Описание</title>
|
||||
<para
|
||||
><command
|
||||
>neochat</command
|
||||
> — приложение для настольных и мобильных устройств, позволяющее общаться в чатах с помощью протокола Matrix. </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="options"
|
||||
><title
|
||||
>Параметры</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term
|
||||
><option
|
||||
>URI</option
|
||||
></term>
|
||||
<listitem>
|
||||
<para
|
||||
>URI-адрес пользователя или комнаты в Matrix, например: matrix:u/user:example.org и matrix:r/root:example.org. NeoChat попытается открыть указанную комнату или беседу. </para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="bug">
|
||||
<title
|
||||
>Отчёты об ошибках</title>
|
||||
<para
|
||||
>Сообщать об ошибках и отправлять предложения по улучшению можно по адресу <ulink url="https://bugs.kde.org/enter_bug.cgi?product=NeoChat&component=General"
|
||||
>https://bugs.kde.org/enter_bug.cgi?product=NeoChat&component=General</ulink
|
||||
></para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title
|
||||
>Смотрите также</title>
|
||||
<simplelist>
|
||||
<member
|
||||
>Список наиболее часто задаваемых вопросов о Matrix <ulink url="https://matrix.org/faq/"
|
||||
>https://matrix.org/faq/</ulink
|
||||
> </member>
|
||||
<member
|
||||
>kf5options(7)</member>
|
||||
<member
|
||||
>qt5options(7)</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="copyright"
|
||||
><title
|
||||
>Авторские права</title>
|
||||
<para
|
||||
>Авторские права © Tobias Fella, 2020–2022 </para>
|
||||
<para
|
||||
>Авторские права © Carl Schwan, 2020–2022 </para>
|
||||
<para
|
||||
>Лицензия: стандартная общественная лицензия GNU версии 3 или любой более поздней версии <<ulink url="https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
>https://www.gnu.org/licenses/gpl-3.0.html</ulink
|
||||
>></para>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
2350
po/ru/neochat.po
2350
po/ru/neochat.po
File diff suppressed because it is too large
Load Diff
2019
po/sa/neochat.po
2019
po/sa/neochat.po
File diff suppressed because it is too large
Load Diff
2006
po/sk/neochat.po
2006
po/sk/neochat.po
File diff suppressed because it is too large
Load Diff
1973
po/sl/neochat.po
1973
po/sl/neochat.po
File diff suppressed because it is too large
Load Diff
1958
po/sv/neochat.po
1958
po/sv/neochat.po
File diff suppressed because it is too large
Load Diff
2031
po/ta/neochat.po
2031
po/ta/neochat.po
File diff suppressed because it is too large
Load Diff
1989
po/tok/neochat.po
1989
po/tok/neochat.po
File diff suppressed because it is too large
Load Diff
1949
po/tr/neochat.po
1949
po/tr/neochat.po
File diff suppressed because it is too large
Load Diff
1969
po/uk/neochat.po
1969
po/uk/neochat.po
File diff suppressed because it is too large
Load Diff
1905
po/zh_CN/neochat.po
1905
po/zh_CN/neochat.po
File diff suppressed because it is too large
Load Diff
1933
po/zh_TW/neochat.po
1933
po/zh_TW/neochat.po
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,6 @@ add_subdirectory(libneochat)
|
||||
add_subdirectory(login)
|
||||
add_subdirectory(rooms)
|
||||
add_subdirectory(roominfo)
|
||||
add_subdirectory(messagecontent)
|
||||
add_subdirectory(timeline)
|
||||
add_subdirectory(spaces)
|
||||
add_subdirectory(chatbar)
|
||||
|
||||
@@ -20,6 +20,8 @@ add_library(neochat STATIC
|
||||
windowcontroller.h
|
||||
models/serverlistmodel.cpp
|
||||
models/serverlistmodel.h
|
||||
logger.cpp
|
||||
logger.h
|
||||
models/notificationsmodel.cpp
|
||||
models/notificationsmodel.h
|
||||
proxycontroller.cpp
|
||||
@@ -59,7 +61,9 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
|
||||
qml/RoomPage.qml
|
||||
qml/ManualRoomDialog.qml
|
||||
qml/ExplorerDelegate.qml
|
||||
qml/ImageEditorPage.qml
|
||||
qml/NeochatMaximizeComponent.qml
|
||||
qml/TypingPane.qml
|
||||
qml/QuickSwitcher.qml
|
||||
qml/AttachmentPane.qml
|
||||
qml/QuickFormatBar.qml
|
||||
@@ -104,11 +108,12 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
|
||||
DEPENDENCIES
|
||||
QtCore
|
||||
QtQuick
|
||||
org.kde.prison
|
||||
org.kde.prison.scanner
|
||||
IMPORTS
|
||||
org.kde.neochat.libneochat
|
||||
org.kde.neochat.rooms
|
||||
org.kde.neochat.roominfo
|
||||
org.kde.neochat.messagecontent
|
||||
org.kde.neochat.timeline
|
||||
org.kde.neochat.spaces
|
||||
org.kde.neochat.settings
|
||||
@@ -177,7 +182,7 @@ else()
|
||||
endif()
|
||||
|
||||
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/models)
|
||||
target_link_libraries(neochat PRIVATE Loginplugin Roomsplugin RoomInfoplugin MessageContentplugin Timelineplugin Spacesplugin Chatbarplugin Settingsplugin Devtoolsplugin)
|
||||
target_link_libraries(neochat PRIVATE Loginplugin Roomsplugin RoomInfoplugin Timelineplugin Spacesplugin Chatbarplugin Settingsplugin Devtoolsplugin)
|
||||
target_link_libraries(neochat PUBLIC
|
||||
LibNeoChat
|
||||
Timeline
|
||||
@@ -202,7 +207,6 @@ target_link_libraries(neochat PUBLIC
|
||||
QuotientQt6
|
||||
Login
|
||||
Rooms
|
||||
MessageContent
|
||||
Spaces
|
||||
)
|
||||
|
||||
@@ -357,10 +361,3 @@ install(TARGETS neochat-app ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
||||
install(FILES plasma-runner-neochat.desktop DESTINATION ${KDE_INSTALL_DATAROOTDIR}/krunner/dbusplugins)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set_target_properties(neochat-app PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "org.kde.neochat")
|
||||
set_target_properties(neochat-app PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "NeoChat")
|
||||
set_target_properties(neochat-app PROPERTIES MACOSX_BUNDLE_SHORT_VERSION_STRING ${RELEASE_SERVICE_VERSION})
|
||||
set_target_properties(neochat-app PROPERTIES MACOSX_BUNDLE_BUNDLE_VERSION ${RELEASE_SERVICE_VERSION})
|
||||
endif ()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "controller.h"
|
||||
|
||||
#include <Quotient/connection.h>
|
||||
#include <qt6keychain/keychain.h>
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
@@ -13,6 +14,7 @@
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <Quotient/csapi/notifications.h>
|
||||
#include <Quotient/events/roommemberevent.h>
|
||||
#include <Quotient/qt_connection_util.h>
|
||||
#include <Quotient/settings.h>
|
||||
@@ -22,6 +24,7 @@
|
||||
#include "mediasizehelper.h"
|
||||
#include "models/actionsmodel.h"
|
||||
#include "models/messagemodel.h"
|
||||
#include "models/pushrulemodel.h"
|
||||
#include "models/roomlistmodel.h"
|
||||
#include "models/roomtreemodel.h"
|
||||
#include "neochatconfig.h"
|
||||
@@ -404,9 +407,4 @@ void Controller::markImageShown(const QString &eventId)
|
||||
m_shownImages.append(eventId);
|
||||
}
|
||||
|
||||
void Controller::markImageHidden(const QString &eventId)
|
||||
{
|
||||
m_shownImages.removeAll(eventId);
|
||||
}
|
||||
|
||||
#include "moc_controller.cpp"
|
||||
|
||||
@@ -99,7 +99,6 @@ public:
|
||||
|
||||
Q_INVOKABLE bool isImageShown(const QString &eventId);
|
||||
Q_INVOKABLE void markImageShown(const QString &eventId);
|
||||
Q_INVOKABLE void markImageHidden(const QString &eventId);
|
||||
|
||||
private:
|
||||
explicit Controller(QObject *parent = nullptr);
|
||||
|
||||
223
src/app/logger.cpp
Normal file
223
src/app/logger.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
// SPDX-FileCopyrightText: 1997 Matthias Kalle Dalheimer <kalle@kde.org>
|
||||
// SPDX-FileCopyrightText: 2002 Holger Freyther <freyther@kde.org>
|
||||
// SPDX-FileCopyrightText: 2008 Volker Krause <vkrause@kde.org>
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMutex>
|
||||
#include <QStandardPaths>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static QLoggingCategory::CategoryFilter oldCategoryFilter = nullptr;
|
||||
static QtMessageHandler oldHandler = nullptr;
|
||||
static bool e2eeDebugEnabled = false;
|
||||
|
||||
class FileDebugStream : public QIODevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileDebugStream()
|
||||
: mType(QtCriticalMsg)
|
||||
{
|
||||
open(WriteOnly);
|
||||
}
|
||||
|
||||
bool isSequential() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
qint64 readData(char *, qint64) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
qint64 readLineData(char *, qint64) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
qint64 writeData(const char *data, qint64 len) override
|
||||
{
|
||||
if (!mFileName.isEmpty()) {
|
||||
QFile outputFile(mFileName);
|
||||
outputFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered);
|
||||
outputFile.write(data, len);
|
||||
outputFile.putChar('\n');
|
||||
outputFile.close();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void setFileName(const QString &fileName)
|
||||
{
|
||||
mFileName = fileName;
|
||||
}
|
||||
|
||||
void setType(QtMsgType type)
|
||||
{
|
||||
mType = type;
|
||||
}
|
||||
|
||||
private:
|
||||
QString mFileName;
|
||||
QtMsgType mType;
|
||||
};
|
||||
|
||||
class DebugPrivate
|
||||
{
|
||||
public:
|
||||
DebugPrivate()
|
||||
: origHandler(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
~DebugPrivate()
|
||||
{
|
||||
qInstallMessageHandler(origHandler);
|
||||
file.close();
|
||||
}
|
||||
|
||||
void log(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
QByteArray buf;
|
||||
QTextStream str(&buf);
|
||||
str << QDateTime::currentDateTime().toString(Qt::ISODate) << u" ["_s;
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
str << u"DEBUG"_s;
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
str << u"INFO "_s;
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
str << u"WARN "_s;
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
str << u"FATAL"_s;
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
str << u"CRITICAL"_s;
|
||||
break;
|
||||
}
|
||||
str << u"] "_s << context.category << u": "_s;
|
||||
if (context.file && *context.file && context.line) {
|
||||
str << context.file << u":"_s << context.line << u": "_s;
|
||||
}
|
||||
if (context.function && *context.function) {
|
||||
str << context.function << u": "_s;
|
||||
}
|
||||
str << message << u"\n"_s;
|
||||
str.flush();
|
||||
file.write(buf.constData(), buf.size());
|
||||
file.flush();
|
||||
|
||||
if (oldHandler && (!context.category || (strcmp(context.category, "quotient.e2ee") != 0 || e2eeDebugEnabled))) {
|
||||
oldHandler(type, context, message);
|
||||
}
|
||||
}
|
||||
|
||||
void setName(const QString &appName)
|
||||
{
|
||||
name = appName;
|
||||
|
||||
if (file.isOpen()) {
|
||||
file.close();
|
||||
}
|
||||
const auto &filePath = u"%1%2%3"_s.arg(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), QDir::separator(), appName);
|
||||
|
||||
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QDir::separator());
|
||||
auto entryList = dir.entryList({appName + u".*"_s});
|
||||
std::sort(entryList.begin(), entryList.end(), [](const auto &left, const auto &right) {
|
||||
auto leftIndex = left.split(u"."_s).last().toInt();
|
||||
auto rightIndex = right.split(u"."_s).last().toInt();
|
||||
return leftIndex > rightIndex;
|
||||
});
|
||||
for (const auto &entry : entryList) {
|
||||
bool ok = false;
|
||||
const auto index = entry.split(u"."_s).last().toInt(&ok);
|
||||
if (!ok) {
|
||||
continue;
|
||||
}
|
||||
QFileInfo info(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QDir::separator() + entry);
|
||||
if (info.exists()) {
|
||||
QFile file(info.absoluteFilePath());
|
||||
if (index > 50) {
|
||||
file.remove();
|
||||
continue;
|
||||
}
|
||||
const auto &newName = u"%1.%2"_s.arg(filePath, QString::number(index + 1));
|
||||
const auto success = file.copy(newName);
|
||||
if (success) {
|
||||
file.remove();
|
||||
} else {
|
||||
qFatal("Cannot rename log file '%s' to '%s': %s",
|
||||
qUtf8Printable(file.fileName()),
|
||||
qUtf8Printable(newName),
|
||||
qUtf8Printable(file.errorString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QFileInfo finfo(filePath);
|
||||
if (!finfo.absoluteDir().exists()) {
|
||||
QDir().mkpath(finfo.absolutePath());
|
||||
}
|
||||
file.setFileName(filePath + u".0"_s);
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Unbuffered);
|
||||
}
|
||||
|
||||
void setOrigHandler(QtMessageHandler origHandler_)
|
||||
{
|
||||
origHandler = origHandler_;
|
||||
}
|
||||
|
||||
QMutex mutex;
|
||||
QFile file;
|
||||
QString name;
|
||||
QtMessageHandler origHandler;
|
||||
QByteArray loggingCategory;
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(DebugPrivate, sInstance)
|
||||
|
||||
void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
case QtInfoMsg:
|
||||
case QtWarningMsg:
|
||||
case QtCriticalMsg:
|
||||
sInstance()->log(type, context, message);
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
sInstance()->log(QtInfoMsg, context, message);
|
||||
}
|
||||
}
|
||||
|
||||
void filter(QLoggingCategory *category)
|
||||
{
|
||||
if (qstrcmp(category->categoryName(), "quotient.e2ee") == 0) {
|
||||
category->setEnabled(QtDebugMsg, true);
|
||||
} else if (oldCategoryFilter) {
|
||||
oldCategoryFilter(category);
|
||||
}
|
||||
}
|
||||
|
||||
void initLogging()
|
||||
{
|
||||
e2eeDebugEnabled = QLoggingCategory("quotient.e2ee", QtInfoMsg).isEnabled(QtDebugMsg);
|
||||
oldCategoryFilter = QLoggingCategory::installFilter(filter);
|
||||
oldHandler = qInstallMessageHandler(messageHandler);
|
||||
sInstance->setOrigHandler(oldHandler);
|
||||
sInstance->setName(u"neochat.log"_s);
|
||||
}
|
||||
|
||||
#include "logger.moc"
|
||||
9
src/app/logger.h
Normal file
9
src/app/logger.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Initlalize logging to file and enables some additional categories, which will only be logged to the file
|
||||
*/
|
||||
void initLogging();
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "blurhashimageprovider.h"
|
||||
#include "colorschemer.h"
|
||||
#include "controller.h"
|
||||
#include "logger.h"
|
||||
#include "login.h"
|
||||
#include "registration.h"
|
||||
#include "roommanager.h"
|
||||
@@ -137,11 +138,6 @@ int main(int argc, char *argv[])
|
||||
font.setHintingPreference(QFont::PreferNoHinting);
|
||||
app.setFont(font);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
QApplication::setStyle(u"breeze"_s);
|
||||
#endif
|
||||
|
||||
KLocalizedString::setApplicationDomain(QByteArrayLiteral("neochat"));
|
||||
|
||||
QGuiApplication::setOrganizationName("KDE"_L1);
|
||||
@@ -181,6 +177,8 @@ int main(int argc, char *argv[])
|
||||
KCrash::initialize();
|
||||
#endif
|
||||
|
||||
initLogging();
|
||||
|
||||
Connection::setEncryptionDefault(true);
|
||||
Connection::setDirectChatEncryptionDefault(true);
|
||||
|
||||
@@ -197,9 +195,6 @@ int main(int argc, char *argv[])
|
||||
parser.addPositionalArgument(u"urls"_s, i18n("Supports matrix: url scheme"));
|
||||
parser.addOption(QCommandLineOption("ignore-ssl-errors"_L1, i18n("Ignore all SSL Errors, e.g., unsigned certificates.")));
|
||||
|
||||
QCommandLineOption replaceOption({QStringLiteral("replace")}, i18nc("command line description", "Replace an existing instance"));
|
||||
parser.addOption(replaceOption);
|
||||
|
||||
QCommandLineOption testOption("test"_L1, i18n("Only used for autotests"));
|
||||
testOption.setFlags(QCommandLineOption::HiddenFromHelp);
|
||||
parser.addOption(testOption);
|
||||
@@ -236,7 +231,7 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KDBUSADDONS
|
||||
KDBusService service(KDBusService::Unique | (parser.isSet(replaceOption) ? KDBusService::Replace : KDBusService::StartupOption(0)));
|
||||
KDBusService service(KDBusService::Unique);
|
||||
#endif
|
||||
|
||||
const auto accountManager = std::make_unique<AccountManager>(parser.isSet("test"_L1));
|
||||
@@ -244,6 +239,13 @@ int main(int argc, char *argv[])
|
||||
LoginHelper::instance().setAccountManager(accountManager.get());
|
||||
Registration::instance().setAccountManager(accountManager.get());
|
||||
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_settingsPlugin)
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_roomsPlugin)
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_timelinePlugin)
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_devtoolsPlugin)
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_loginPlugin)
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_chatbarPlugin)
|
||||
|
||||
qml_register_types_org_kde_neochat();
|
||||
qmlRegisterUncreatableMetaObject(Quotient::staticMetaObject, "Quotient", 1, 0, "JoinRule", u"Access to JoinRule enum only"_s);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include "neochatconnection.h"
|
||||
#include "neochatroom.h"
|
||||
|
||||
#include <Quotient/events/roommessageevent.h>
|
||||
#include <Quotient/roommember.h>
|
||||
@@ -24,7 +25,11 @@ class CommonRoomsModel : public QAbstractListModel
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
RoomIdRole = Qt::DisplayRole,
|
||||
TextRole = Qt::DisplayRole,
|
||||
LongitudeRole,
|
||||
LatitudeRole,
|
||||
AssetRole,
|
||||
AuthorRole,
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ void ServerListModel::initialize()
|
||||
true,
|
||||
false,
|
||||
});
|
||||
endResetModel();
|
||||
beginResetModel();
|
||||
}
|
||||
|
||||
#include "moc_serverlistmodel.cpp"
|
||||
|
||||
@@ -78,12 +78,6 @@
|
||||
<label>Use a compact room list layout</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="MarkReadCondition" type="Enum">
|
||||
<label>The sort order for the rooms in the list.</label>
|
||||
<choices name="::TimelineMarkReadCondition::Condition">
|
||||
</choices>
|
||||
<default>2</default>
|
||||
</entry>
|
||||
<entry name="ShowStateEvent" type="bool">
|
||||
<label>Show state events in the timeline</label>
|
||||
<default>true</default>
|
||||
@@ -189,10 +183,6 @@
|
||||
<label>Don't hide any events in the timeline</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="RelateAnyEvent" type="bool">
|
||||
<label>Send relations to any event, including state events and events normally hidden.</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="AlwaysVerifyDevice" type="bool">
|
||||
<label>Always allow device verification</label>
|
||||
<default>false</default>
|
||||
@@ -215,10 +205,6 @@
|
||||
<label>Enable add phone numbers as 3PIDs</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="Calls" type="bool">
|
||||
<label>Enable audio and video calling</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Security">
|
||||
<entry name="RejectUnknownInvites" type="bool">
|
||||
|
||||
@@ -93,3 +93,4 @@ X-Plasma-API=DBus
|
||||
X-Plasma-DBusRunner-Service=org.kde.neochat
|
||||
X-Plasma-DBusRunner-Path=/RoomRunner
|
||||
X-Plasma-Request-Actions-Once=true
|
||||
X-Plasma-Runner-Min-Letter-Count=3
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.components as KirigamiComponents
|
||||
@@ -19,45 +18,44 @@ KirigamiComponents.ConvergentContextMenu {
|
||||
required property NeoChatConnection connection
|
||||
required property Kirigami.ApplicationWindow window
|
||||
|
||||
Kirigami.Action {
|
||||
QQC2.Action {
|
||||
text: i18nc("@action:button", "Show QR Code")
|
||||
icon.name: "view-barcode-qr-symbolic"
|
||||
onTriggered: {
|
||||
(Qt.createComponent('org.kde.neochat', 'QrCodeMaximizeComponent').createObject(QQC2.Overlay.overlay, {
|
||||
let qrMax = Qt.createComponent('org.kde.neochat', 'QrCodeMaximizeComponent').createObject(QQC2.Overlay.overlay, {
|
||||
text: "https://matrix.to/#/" + root.connection.localUser.id,
|
||||
title: root.connection.localUser.displayName,
|
||||
subtitle: root.connection.localUser.id,
|
||||
// Note: User::avatarUrl does not set user_id, and thus cannot be used directly here. Hence the makeMediaUrl.
|
||||
avatarSource: root.connection.localUser.avatarUrl.toString().length > 0 ? root.connection.makeMediaUrl(root.connection.localUser.avatarUrl) : ""
|
||||
}) as QrCodeMaximizeComponent).open();
|
||||
});
|
||||
if (typeof root.closeDialog === "function") {
|
||||
root.closeDialog();
|
||||
}
|
||||
qrMax.open();
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:inmenu", "Switch Account")
|
||||
icon.name: "system-switch-user"
|
||||
shortcut: "Ctrl+U"
|
||||
onTriggered: (Qt.createComponent("org.kde.neochat", "AccountSwitchDialog").createObject(QQC2.Overlay.overlay, {
|
||||
connection: root.connection
|
||||
}) as Kirigami.Dialog).open();
|
||||
}
|
||||
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:inmenu", "Edit This Account")
|
||||
QQC2.Action {
|
||||
text: i18n("Edit This Account")
|
||||
icon.name: "document-edit"
|
||||
onTriggered: NeoChatSettingsView.openWithInitialProperties("accounts", {initialAccount: root.connection});
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.settings', 'AccountEditorPage'), {
|
||||
connection: root.connection
|
||||
}, {
|
||||
title: i18n("Account editor")
|
||||
})
|
||||
}
|
||||
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:inmenu", "Notification Settings")
|
||||
QQC2.Action {
|
||||
text: i18n("Notification Settings")
|
||||
icon.name: "notifications"
|
||||
onTriggered: {
|
||||
NeoChatSettingsView.open('notifications');
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:inmenu", "Devices")
|
||||
QQC2.Action {
|
||||
text: i18n("Devices")
|
||||
icon.name: "computer-symbolic"
|
||||
onTriggered: {
|
||||
NeoChatSettingsView.open('devices');
|
||||
@@ -65,10 +63,10 @@ KirigamiComponents.ConvergentContextMenu {
|
||||
}
|
||||
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:inmenu", "Open Developer Tools")
|
||||
text: i18n("Open Developer Tools")
|
||||
icon.name: "tools"
|
||||
visible: NeoChatConfig.developerTools
|
||||
onTriggered: root.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.devtools', 'DevtoolsPage'), {
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.devtools', 'DevtoolsPage'), {
|
||||
connection: root.connection
|
||||
}, {
|
||||
title: i18nc("@title:window", "Developer Tools"),
|
||||
@@ -86,10 +84,9 @@ KirigamiComponents.ConvergentContextMenu {
|
||||
})
|
||||
}
|
||||
|
||||
Kirigami.Action {
|
||||
QQC2.Action {
|
||||
text: i18nc("@action:inmenu", "Verify This Device")
|
||||
icon.name: "security-low"
|
||||
visible: !root.connection.isVerifiedSession()
|
||||
onTriggered: {
|
||||
root.connection.startSelfVerification();
|
||||
const dialog = Qt.createComponent("org.kde.kirigami", "PromptDialog").createObject(QQC2.Overlay.overlay, {
|
||||
@@ -98,17 +95,19 @@ KirigamiComponents.ConvergentContextMenu {
|
||||
standardButtons: Kirigami.Dialog.Ok
|
||||
})
|
||||
dialog.open();
|
||||
root.connection.newKeyVerificationSession.connect(() => {
|
||||
root.connection.onNewKeyVerificationSession.connect(() => {
|
||||
dialog.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:inmenu", "Logout…")
|
||||
QQC2.Action {
|
||||
text: i18n("Logout")
|
||||
icon.name: "im-kick-user"
|
||||
onTriggered: (Qt.createComponent("org.kde.neochat", "ConfirmLogoutDialog").createObject(QQC2.Overlay.overlay, {
|
||||
connection: root.connection
|
||||
}) as Kirigami.Dialog).open()
|
||||
onTriggered: confirmLogoutDialogComponent.createObject(root).open()
|
||||
}
|
||||
|
||||
readonly property Component confirmLogoutDialogComponent: ConfirmLogoutDialog {
|
||||
connection: root.connection
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
@@ -17,6 +16,8 @@ Kirigami.Dialog {
|
||||
|
||||
required property NeoChatConnection connection
|
||||
|
||||
parent: applicationWindow().overlay
|
||||
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
@@ -24,7 +25,7 @@ Kirigami.Dialog {
|
||||
|
||||
standardButtons: Kirigami.Dialog.NoButton
|
||||
|
||||
width: Math.min(QQC2.ApplicationWindow.window.width, Kirigami.Units.gridUnit * 24)
|
||||
width: Math.min(applicationWindow().width, Kirigami.Units.gridUnit * 24)
|
||||
title: i18nc("@title: dialog to switch between logged in accounts", "Switch Account")
|
||||
|
||||
onVisibleChanged: if (visible) {
|
||||
@@ -52,7 +53,7 @@ Kirigami.Dialog {
|
||||
}
|
||||
text: i18nc("@button: login to or register a new account.", "Add Account")
|
||||
contentItem: Delegates.SubtitleContentItem {
|
||||
itemDelegate: addDelegate
|
||||
itemDelegate: parent
|
||||
subtitle: i18n("Log in or create a new account")
|
||||
labelItem.textFormat: Text.PlainText
|
||||
subtitleItem.textFormat: Text.PlainText
|
||||
|
||||
@@ -33,7 +33,7 @@ ColumnLayout {
|
||||
}
|
||||
QQC2.ToolButton {
|
||||
id: editImageButton
|
||||
visible: root.hasImage
|
||||
visible: hasImage
|
||||
icon.name: "document-edit"
|
||||
text: i18n("Edit")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
@@ -46,9 +46,9 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
let imageEditor = (Kirigami.PageStack.pageStack as Kirigami.PageRow).pushDialogLayer(imageEditorPage);
|
||||
let imageEditor = applicationWindow().pageStack.pushDialogLayer(imageEditorPage);
|
||||
imageEditor.newPathChanged.connect(function (newPath) {
|
||||
imageEditor.closeDialog();
|
||||
applicationWindow().pageStack.layers.pop();
|
||||
root.attachmentPath = newPath;
|
||||
});
|
||||
}
|
||||
@@ -61,7 +61,7 @@ ColumnLayout {
|
||||
action: Kirigami.Action {
|
||||
text: i18n("Cancel sending attachment")
|
||||
icon.name: "dialog-close"
|
||||
onTriggered: root.attachmentCancelled()
|
||||
onTriggered: attachmentCancelled()
|
||||
shortcut: "Escape"
|
||||
}
|
||||
QQC2.ToolTip.text: text
|
||||
@@ -75,8 +75,8 @@ ColumnLayout {
|
||||
|
||||
asynchronous: true
|
||||
cache: false // Cache is not needed. Images will rarely be shown repeatedly.
|
||||
source: root.hasImage ? root.attachmentPath : ""
|
||||
visible: root.hasImage
|
||||
source: hasImage ? root.attachmentPath : ""
|
||||
visible: hasImage
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
onSourceChanged: {
|
||||
@@ -114,11 +114,11 @@ ColumnLayout {
|
||||
id: mimetypeIcon
|
||||
implicitWidth: Kirigami.Units.iconSizes.smallMedium
|
||||
implicitHeight: Kirigami.Units.iconSizes.smallMedium
|
||||
source: root.attachmentMimetype.iconName
|
||||
source: attachmentMimetype.iconName
|
||||
}
|
||||
QQC2.Label {
|
||||
id: fileLabel
|
||||
text: root.baseFileName
|
||||
text: baseFileName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Templates as T
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.delegates as Delegates
|
||||
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: root
|
||||
|
||||
@@ -8,6 +8,7 @@ import QtQml.Models
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
|
||||
import org.kde.kitemmodels
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ ApplicationWindow {
|
||||
|
||||
Connections {
|
||||
target: mapView.map
|
||||
function onCopyrightLinkActivated(link: string): void {
|
||||
function onCopyrightLinkActivated() {
|
||||
Qt.openUrlExternally(link);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,23 @@ Labs.MenuBar {
|
||||
|
||||
required property NeoChatConnection connection
|
||||
|
||||
Labs.Menu {
|
||||
title: i18nc("menu", "NeoChat")
|
||||
|
||||
Labs.MenuItem {
|
||||
enabled: pageStack.layers.currentItem.title !== i18n("Configure NeoChat…")
|
||||
text: i18nc("menu", "Configure NeoChat…")
|
||||
|
||||
shortcut: StandardKey.Preferences
|
||||
onTriggered: NeoChatSettingsView.open()
|
||||
}
|
||||
Labs.MenuItem {
|
||||
text: i18nc("menu", "Quit NeoChat")
|
||||
|
||||
shortcut: StandardKey.Quit
|
||||
onTriggered: Qt.quit()
|
||||
}
|
||||
}
|
||||
Labs.Menu {
|
||||
title: i18nc("menu", "File")
|
||||
|
||||
@@ -57,19 +74,6 @@ Labs.MenuBar {
|
||||
});
|
||||
}
|
||||
}
|
||||
Labs.MenuItem {
|
||||
enabled: pageStack.layers.currentItem.title !== i18n("Configure NeoChat…")
|
||||
text: i18nc("menu", "Configure NeoChat…")
|
||||
|
||||
shortcut: StandardKey.Preferences
|
||||
onTriggered: NeoChatSettingsView.open()
|
||||
}
|
||||
Labs.MenuItem {
|
||||
text: i18nc("menu", "Quit NeoChat")
|
||||
|
||||
shortcut: StandardKey.Quit
|
||||
onTriggered: Qt.quit()
|
||||
}
|
||||
}
|
||||
EditMenu {
|
||||
title: i18nc("menu", "Edit")
|
||||
|
||||
@@ -100,7 +100,7 @@ Kirigami.Page {
|
||||
}
|
||||
Connections {
|
||||
target: selectionTool.selectionArea
|
||||
function onDoubleClicked(): void {
|
||||
function onDoubleClicked() {
|
||||
rootEditorView.crop();
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ ColumnLayout {
|
||||
id: root
|
||||
|
||||
required property NeoChatRoom currentRoom
|
||||
readonly property var invitingMember: currentRoom.qmlSafeMember(currentRoom.invitingUserId)
|
||||
readonly property var invitingMember: currentRoom.member(currentRoom.invitingUserId)
|
||||
readonly property string inviteTimestamp: root.currentRoom.inviteTimestamp.toLocaleString(Qt.locale(), Locale.ShortFormat)
|
||||
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
@@ -33,7 +33,7 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
name: root.invitingMember.displayName
|
||||
source: NeoChatConfig.hideImages ? undefined : root.invitingMember.avatarUrl
|
||||
source: root.invitingMember.avatarUrl
|
||||
color: root.invitingMember.color
|
||||
}
|
||||
|
||||
@@ -52,15 +52,6 @@ ColumnLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
Kirigami.SelectableLabel {
|
||||
Layout.fillWidth: true
|
||||
font: Kirigami.Theme.smallFont
|
||||
textFormat: TextEdit.PlainText
|
||||
visible: root.currentRoom && root.currentRoom.canonicalAlias
|
||||
text: root.currentRoom && root.currentRoom.canonicalAlias ? root.currentRoom.canonicalAlias : ""
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
|
||||
Kirigami.Heading {
|
||||
text: root.currentRoom.displayName
|
||||
|
||||
@@ -79,14 +70,7 @@ ColumnLayout {
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Kirigami.Heading {
|
||||
text: root.invitingMember.displayName
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
text: root.invitingMember.id
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: root.currentRoom.displayName
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
@@ -175,7 +159,7 @@ ColumnLayout {
|
||||
|
||||
QQC2.Label {
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: xi18nc("@info:label Ensure you are referring to the same translation used for that settings page", "You can reject invitations from unknown users under the <interface>Security & Safety</interface> settings.")
|
||||
text: i18nc("@info:label", "You can reject invitations from unknown users under Security settings.")
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
// + 5 to prevent it from wrapping unnecessarily
|
||||
|
||||
@@ -8,6 +8,7 @@ import QtQuick.Layouts
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.components as KirigamiComponents
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
import org.kde.prison
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
@@ -24,7 +25,7 @@ Kirigami.Dialog {
|
||||
|
||||
standardButtons: Kirigami.Dialog.NoButton
|
||||
|
||||
width: Math.min(QQC2.ApplicationWindow.window.width, Kirigami.Units.gridUnit * 24)
|
||||
width: Math.min(applicationWindow().width, Kirigami.Units.gridUnit * 24)
|
||||
title: i18nc("@title:dialog", "Join Room")
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
|
||||
@@ -41,7 +41,6 @@ Kirigami.ApplicationWindow {
|
||||
showExisting: true
|
||||
onConnectionChosen: root.load()
|
||||
}
|
||||
columnView.columnResizeMode: pageStack.wideMode ? Kirigami.ColumnView.DynamicColumns : Kirigami.ColumnView.SingleColumn
|
||||
globalToolBar.canContainHandles: true
|
||||
globalToolBar {
|
||||
style: Kirigami.ApplicationHeaderStyle.ToolBar
|
||||
@@ -60,21 +59,21 @@ Kirigami.ApplicationWindow {
|
||||
|
||||
Connections {
|
||||
target: LoginHelper
|
||||
function onLoaded(): void {
|
||||
function onLoaded() {
|
||||
root.load();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Registration
|
||||
function onLoaded(): void {
|
||||
function onLoaded() {
|
||||
root.load();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.quitAction
|
||||
function onTriggered(): void {
|
||||
function onTriggered() {
|
||||
Qt.quit();
|
||||
}
|
||||
}
|
||||
@@ -98,40 +97,42 @@ Kirigami.ApplicationWindow {
|
||||
Connections {
|
||||
target: RoomManager
|
||||
|
||||
function onCurrentRoomChanged(): void {
|
||||
function onCurrentRoomChanged() {
|
||||
if (RoomManager.currentRoom && pageStack.depth <= 1 && root.initialized && Kirigami.Settings.isMobile) {
|
||||
let roomPage = pageStack.layers.push(Qt.createComponent('org.kde.neochat', 'RoomPage'));
|
||||
let roomPage = pageStack.layers.push(Qt.createComponent('org.kde.neochat', 'RoomPage'), {
|
||||
connection: root.connection
|
||||
});
|
||||
roomPage.backRequested.connect(event => {
|
||||
RoomManager.clearCurrentRoom();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onAskJoinRoom(room: NeoChatRoom): void {
|
||||
function onAskJoinRoom(room) {
|
||||
Qt.createComponent("org.kde.neochat", "JoinRoomDialog").createObject(root, {
|
||||
room: room,
|
||||
connection: root.connection
|
||||
}).open();
|
||||
}
|
||||
|
||||
function onShowUserDetail(user, room: NeoChatRoom): void {
|
||||
function onShowUserDetail(user, room) {
|
||||
root.showUserDetail(user, room);
|
||||
}
|
||||
|
||||
function goToEvent(event: string): void {
|
||||
function goToEvent(event) {
|
||||
if (event.length > 0) {
|
||||
roomItem.goToEvent(event);
|
||||
}
|
||||
roomItem.forceActiveFocus();
|
||||
}
|
||||
|
||||
function onAskDirectChatConfirmation(user): void {
|
||||
function onAskDirectChatConfirmation(user) {
|
||||
Qt.createComponent("org.kde.neochat", "AskDirectChatConfirmation").createObject(this, {
|
||||
user: user
|
||||
}).open();
|
||||
}
|
||||
|
||||
function onExternalUrl(url): void {
|
||||
function onExternalUrl(url) {
|
||||
let dialog = Qt.createComponent("org.kde.neochat", "ConfirmUrlDialog").createObject(this);
|
||||
dialog.link = url;
|
||||
dialog.open();
|
||||
@@ -336,7 +337,7 @@ Kirigami.ApplicationWindow {
|
||||
}
|
||||
}
|
||||
function handleShare(): void {
|
||||
const dialog = root.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ChooseRoomDialog'), {
|
||||
const dialog = applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ChooseRoomDialog'), {
|
||||
connection: root.connection
|
||||
}, {
|
||||
title: i18nc("@title", "Share"),
|
||||
@@ -363,7 +364,9 @@ Kirigami.ApplicationWindow {
|
||||
RoomManager.loadInitialRoom();
|
||||
|
||||
if (!Kirigami.Settings.isMobile) {
|
||||
let roomPage = pageStack.push(Qt.createComponent('org.kde.neochat', 'RoomPage'));
|
||||
let roomPage = pageStack.push(Qt.createComponent('org.kde.neochat', 'RoomPage'), {
|
||||
connection: root.connection
|
||||
});
|
||||
roomPage.forceActiveFocus();
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ Kirigami.Page {
|
||||
icon.name: "document-edit"
|
||||
visible: root.allowEdit
|
||||
enabled: room.canSendState(root.type) && (!root.stateKey.startsWith("@") || root.stateKey === root.room.connection.localUserId) && root.type !== "m.room.create"
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat", "EditStateDialog"), {
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat", "EditStateDialog.qml"), {
|
||||
room: root.room,
|
||||
type: root.type,
|
||||
stateKey: root.stateKey,
|
||||
|
||||
@@ -72,7 +72,7 @@ Components.AlbumMaximizeComponent {
|
||||
|
||||
Connections {
|
||||
target: MediaManager
|
||||
function onPlaybackStarted(): void {
|
||||
function onPlaybackStarted() {
|
||||
if (currentItem.playbackState === MediaPlayer.PlayingState) {
|
||||
currentItem.pause();
|
||||
}
|
||||
@@ -82,7 +82,7 @@ Components.AlbumMaximizeComponent {
|
||||
Connections {
|
||||
target: currentRoom
|
||||
|
||||
function onFileTransferProgress(id: string, progress: int, total: int): void {
|
||||
function onFileTransferProgress(id, progress, total) {
|
||||
if (id == root.currentEventId) {
|
||||
root.downloadAction.progress = progress / total * 100.0;
|
||||
}
|
||||
@@ -130,7 +130,7 @@ Components.AlbumMaximizeComponent {
|
||||
|
||||
Connections {
|
||||
target: RoomManager
|
||||
function onCloseFullScreen(): void {
|
||||
function onCloseFullScreen() {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ Components.AlbumMaximizeComponent {
|
||||
id: saveAsDialog
|
||||
Dialogs.FileDialog {
|
||||
fileMode: Dialogs.FileDialog.SaveFile
|
||||
currentFolder: NeoChatConfig.lastSaveDirectory.length > 0 ? NeoChatConfig.lastSaveDirectory : Core.StandardPaths.writableLocation(Core.StandardPaths.DownloadLocation)
|
||||
currentFolder: root.saveFolder
|
||||
onAccepted: {
|
||||
NeoChatConfig.lastSaveDirectory = currentFolder;
|
||||
NeoChatConfig.save();
|
||||
|
||||
@@ -34,7 +34,7 @@ Kirigami.Dialog {
|
||||
}
|
||||
]
|
||||
|
||||
width: Math.min(QQC2.ApplicationWindow.window.width, Kirigami.Units.gridUnit * 24)
|
||||
width: Math.min(applicationWindow().width, Kirigami.Units.gridUnit * 24)
|
||||
title: i18nc("@title: create new poll in the room", "Create Poll")
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
|
||||
@@ -22,7 +22,7 @@ Kirigami.Page {
|
||||
|
||||
Connections {
|
||||
target: root.QQC2.ApplicationWindow.window
|
||||
function onClosing(): void {
|
||||
function onClosing() {
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kitemmodels
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
|
||||
@@ -28,14 +28,6 @@ Kirigami.Page {
|
||||
placeholderText: root.placeholder
|
||||
anchors.fill: parent
|
||||
wrapMode: TextEdit.Wrap
|
||||
focus: true
|
||||
|
||||
Keys.onReturnPressed: event => {
|
||||
if (event.modifiers & Qt.ControlModifier) {
|
||||
root.accepted(reason.text);
|
||||
root.closeDialog();
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
@@ -58,7 +50,6 @@ Kirigami.Page {
|
||||
}
|
||||
}
|
||||
QQC2.Button {
|
||||
icon.name: "dialog-cancel-symbolic"
|
||||
text: i18nc("@action", "Cancel")
|
||||
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
|
||||
onClicked: root.closeDialog()
|
||||
|
||||
@@ -15,6 +15,8 @@ Kirigami.Dialog {
|
||||
|
||||
property var connection
|
||||
|
||||
parent: applicationWindow().overlay
|
||||
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
@@ -22,7 +24,7 @@ Kirigami.Dialog {
|
||||
|
||||
title: i18nc("@title Join <name of a space>", "Join %1", SpaceHierarchyCache.recommendedSpaceDisplayName)
|
||||
|
||||
width: Math.min(QQC2.ApplicationWindow.window.width, Kirigami.Units.gridUnit * 24)
|
||||
width: Math.min(applicationWindow().width, Kirigami.Units.gridUnit * 24)
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
FormCard.AbstractFormDelegate {
|
||||
|
||||
@@ -8,16 +8,18 @@ import QtQuick.Layouts
|
||||
import QtQuick.Window
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kitemmodels
|
||||
|
||||
import org.kde.neochat
|
||||
import org.kde.neochat.chatbar
|
||||
|
||||
Kirigami.Page {
|
||||
id: root
|
||||
|
||||
/**
|
||||
* @brief The NeoChatRoom the delegate is being displayed in.
|
||||
*/
|
||||
readonly property NeoChatRoom currentRoom: RoomManager.currentRoom
|
||||
/// Not readonly because of the separate window view.
|
||||
property NeoChatRoom currentRoom: RoomManager.currentRoom
|
||||
|
||||
required property NeoChatConnection connection
|
||||
|
||||
/**
|
||||
* @brief The TimelineModel to use.
|
||||
@@ -57,15 +59,20 @@ Kirigami.Page {
|
||||
*/
|
||||
property MediaMessageFilterModel mediaMessageFilterModel: RoomManager.mediaMessageFilterModel
|
||||
|
||||
property bool loading: !root.currentRoom || (root.currentRoom.timelineSize === 0 && !root.currentRoom.allHistoryLoaded)
|
||||
|
||||
/// Disable cancel shortcut. Used by the separate window since it provides its own cancel implementation.
|
||||
property bool disableCancelShortcut: false
|
||||
|
||||
title: root.currentRoom ? root.currentRoom.displayName : ""
|
||||
focus: true
|
||||
padding: 0
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
visible: Kirigami.Settings.isMobile || !root.Kirigami.PageStack.pageStack.wideMode
|
||||
visible: Kirigami.Settings.isMobile || !applicationWindow().pageStack.wideMode
|
||||
icon.name: "view-right-new"
|
||||
onTriggered: (root.QQC2.ApplicationWindow.window as Main).openRoomDrawer()
|
||||
onTriggered: applicationWindow().openRoomDrawer()
|
||||
}
|
||||
]
|
||||
|
||||
@@ -79,10 +86,10 @@ Kirigami.Page {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.currentRoom.connection
|
||||
function onIsOnlineChanged(): void {
|
||||
if (!root.currentRoom.connection.isOnline) {
|
||||
banner.text = i18nc("@info:status", "NeoChat is offline. Please check your network connection.");
|
||||
target: root.connection
|
||||
function onIsOnlineChanged() {
|
||||
if (!root.connection.isOnline) {
|
||||
banner.text = i18n("NeoChat is offline. Please check your network connection.");
|
||||
banner.visible = true;
|
||||
banner.type = Kirigami.MessageType.Error;
|
||||
} else {
|
||||
@@ -102,15 +109,18 @@ Kirigami.Page {
|
||||
Loader {
|
||||
id: timelineViewLoader
|
||||
anchors.fill: parent
|
||||
active: root.currentRoom && !root.currentRoom.isInvite && !root.currentRoom.isSpace
|
||||
// We need the loader to be active but invisible while the room is loading messages so signals in TimelineView work.
|
||||
visible: !root.loading
|
||||
active: root.currentRoom && !root.currentRoom.isInvite && !root.loading && !root.currentRoom.isSpace
|
||||
sourceComponent: TimelineView {
|
||||
id: timelineView
|
||||
currentRoom: root.currentRoom
|
||||
page: root
|
||||
timelineModel: root.timelineModel
|
||||
messageFilterModel: root.messageFilterModel
|
||||
compactLayout: NeoChatConfig.compactLayout
|
||||
fileDropEnabled: !Controller.isFlatpak
|
||||
markReadCondition: NeoChatConfig.markReadCondition
|
||||
onFocusChatBar: {
|
||||
if (chatBarLoader.item) {
|
||||
chatBarLoader.item.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,8 +147,16 @@ Kirigami.Page {
|
||||
anchors.centerIn: parent
|
||||
sourceComponent: Kirigami.PlaceholderMessage {
|
||||
icon.name: "org.kde.neochat"
|
||||
text: i18nc("@title", "Welcome to NeoChat")
|
||||
explanation: i18nc("@info:usagetip", "Select or join a room to get started")
|
||||
text: i18n("Welcome to NeoChat")
|
||||
explanation: i18n("Select or join a room to get started")
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: root.loading && !invitationLoader.active && RoomManager.currentRoom && !spaceLoader.active
|
||||
anchors.centerIn: parent
|
||||
sourceComponent: Kirigami.LoadingPlaceholder {
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,26 +174,44 @@ Kirigami.Page {
|
||||
id: chatBar
|
||||
width: parent.width
|
||||
currentRoom: root.currentRoom
|
||||
connection: root.currentRoom.connection
|
||||
connection: root.connection
|
||||
onMessageSent: {
|
||||
if (!timelineViewLoader.item.atYEnd) {
|
||||
timelineViewLoader.item.goToLastMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: RoomManager
|
||||
function onCurrentRoomChanged(): void {
|
||||
function onCurrentRoomChanged() {
|
||||
if (root.currentRoom && root.currentRoom.isInvite) {
|
||||
Controller.clearInvitationNotification(root.currentRoom.id);
|
||||
}
|
||||
}
|
||||
|
||||
function onGoToEvent(eventId: string): void {
|
||||
function onGoToEvent(eventId) {
|
||||
(timelineViewLoader.item as TimelineView).goToEvent(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: StandardKey.Cancel
|
||||
onActivated: {
|
||||
if (!timelineViewLoader.item.atYEnd || !root.currentRoom.partiallyReadStats.empty()) {
|
||||
timelineViewLoader.item.goToLastMessage();
|
||||
root.currentRoom.markAllMessagesAsRead();
|
||||
} else {
|
||||
applicationWindow().pageStack.get(0).forceActiveFocus();
|
||||
}
|
||||
}
|
||||
enabled: !root.disableCancelShortcut
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.currentRoom.connection
|
||||
function onJoinedRoom(room: NeoChatRoom, invited: NeoChatRoom): void {
|
||||
target: root.connection
|
||||
function onJoinedRoom(room, invited) {
|
||||
if (root.currentRoom.id === invited.id) {
|
||||
RoomManager.resolveResource(room.id);
|
||||
}
|
||||
@@ -195,22 +231,22 @@ Kirigami.Page {
|
||||
Connections {
|
||||
target: RoomManager
|
||||
|
||||
function onShowMessage(messageType: Kirigami.MessageType, message: string): void {
|
||||
function onShowMessage(messageType, message) {
|
||||
banner.text = message;
|
||||
banner.type = messageType;
|
||||
banner.visible = true;
|
||||
}
|
||||
|
||||
function onShowEventSource(eventId: string): void {
|
||||
(root.Kirigami.PageStack.pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
function onShowEventSource(eventId) {
|
||||
applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
sourceText: root.currentRoom.getEventJsonSource(eventId)
|
||||
}, {
|
||||
title: i18nc("@title:dialog", "Message Source"),
|
||||
title: i18n("Message Source"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
}
|
||||
|
||||
function onShowMessageMenu(eventId: string, author, messageComponentType, plainText: string, htmlText: string, selectedText: string, hoveredLink: string, isThread: bool): void {
|
||||
function onShowMessageMenu(eventId, author, messageComponentType, plainText, htmlText, selectedText, hoveredLink, isThread) {
|
||||
const contextMenu = messageDelegateContextMenu.createObject(root, {
|
||||
selectedText: selectedText,
|
||||
hoveredLink: hoveredLink,
|
||||
@@ -260,7 +296,7 @@ Kirigami.Page {
|
||||
id: messageDelegateContextMenu
|
||||
MessageDelegateContextMenu {
|
||||
room: root.currentRoom
|
||||
connection: root.currentRoom.connection
|
||||
connection: root.connection
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +304,7 @@ Kirigami.Page {
|
||||
id: fileDelegateContextMenu
|
||||
FileDelegateContextMenu {
|
||||
room: root.currentRoom
|
||||
connection: root.currentRoom.connection
|
||||
connection: root.connection
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,14 +67,10 @@ QQC2.ComboBox {
|
||||
QQC2.ToolButton {
|
||||
visible: serverItem.isAddServerDelegate || serverItem.isDeletable
|
||||
icon.name: serverItem.isAddServerDelegate ? "list-add" : "dialog-close"
|
||||
text: serverItem.isAddServerDelegate ? i18nc("@action:button", "Add new server") : i18nc("@action:button", "Remove server")
|
||||
text: i18nc("@action:button", "Add new server")
|
||||
Accessible.name: text
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
|
||||
onClicked: {
|
||||
if (root.currentIndex === serverItem.index && serverItem.isDeletable) {
|
||||
root.currentIndex = 0;
|
||||
@@ -177,7 +173,7 @@ QQC2.ComboBox {
|
||||
|
||||
Connections {
|
||||
target: serverListModel
|
||||
function onServerCheckComplete(url: string, valid: bool): void {
|
||||
function onServerCheckComplete(url, valid) {
|
||||
if (url == serverUrlField.text && valid) {
|
||||
serverUrlField.isValidServer = true;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ Kirigami.Action {
|
||||
text: i18n("Share")
|
||||
tooltip: i18n("Share the selected media")
|
||||
|
||||
visible: false
|
||||
|
||||
/**
|
||||
* This property holds the input data for purpose.
|
||||
*
|
||||
@@ -58,7 +60,7 @@ Kirigami.Action {
|
||||
if (id != root.eventId) {
|
||||
return;
|
||||
}
|
||||
pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat", "ShareDialog"), {
|
||||
applicationWindow().pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat", "ShareDialog"), {
|
||||
title: root.text,
|
||||
index: index,
|
||||
model: root._instantiator.model
|
||||
|
||||
@@ -80,6 +80,7 @@ Kirigami.Dialog {
|
||||
text: root.user.id
|
||||
elide: Qt.ElideRight
|
||||
elideWidth: root.availableWidth - avatar.width - qrButton.width - detailRow.spacing * 2 - detailRow.Layout.leftMargin - detailRow.Layout.rightMargin
|
||||
onElideWidthChanged: console.warn(root.availableWidth, avatar.width, qrButton.width, elideWidth, elidedText)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +262,7 @@ Kirigami.Dialog {
|
||||
icon.name: "delete"
|
||||
icon.color: Kirigami.Theme.negativeTextColor
|
||||
onTriggered: {
|
||||
let dialog = pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
let dialog = applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Remove Messages"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for removing this user's recent messages"),
|
||||
actionText: i18nc("@action:button 'Remove' as in 'Remove these messages'", "Remove"),
|
||||
|
||||
@@ -59,9 +59,9 @@ RoomManager::RoomManager(QObject *parent)
|
||||
m_directChatsConfig = m_config->group(u"DirectChatsActive"_s);
|
||||
|
||||
connect(this, &RoomManager::currentRoomChanged, this, [this]() {
|
||||
m_userListModel->setRoom(m_currentRoom);
|
||||
m_timelineModel->setRoom(m_currentRoom);
|
||||
m_sortFilterRoomTreeModel->setCurrentRoom(m_currentRoom);
|
||||
m_userListModel->setRoom(m_currentRoom);
|
||||
});
|
||||
|
||||
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [this](NeoChatConnection *connection) {
|
||||
@@ -96,7 +96,6 @@ RoomManager::RoomManager(QObject *parent)
|
||||
m_messageFilterModel->invalidate();
|
||||
}
|
||||
});
|
||||
connect(m_timelineModel->timelineMessageModel(), &MessageModel::modelResetComplete, this, &RoomManager::activateUserModel);
|
||||
MessageFilterModel::setShowAllEvents(NeoChatConfig::self()->showAllEvents());
|
||||
connect(NeoChatConfig::self(), &NeoChatConfig::ShowAllEventsChanged, this, [this] {
|
||||
MessageFilterModel::setShowAllEvents(NeoChatConfig::self()->showAllEvents());
|
||||
@@ -236,18 +235,11 @@ void RoomManager::resolveResource(Uri uri, const QString &action)
|
||||
}
|
||||
}
|
||||
|
||||
void RoomManager::maximizeMedia(const QString &eventId)
|
||||
void RoomManager::maximizeMedia(int index)
|
||||
{
|
||||
if (eventId.isEmpty()) {
|
||||
qWarning() << "Tried to open media for empty event id";
|
||||
if (index < -1 || index > m_mediaMessageFilterModel->rowCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto index = m_mediaMessageFilterModel->getRowForEventId(eventId);
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Q_EMIT showMaximizedMedia(index);
|
||||
}
|
||||
|
||||
@@ -271,17 +263,8 @@ void RoomManager::viewEventSource(const QString &eventId)
|
||||
|
||||
void RoomManager::viewEventMenu(const QString &eventId, NeoChatRoom *room, NeochatRoomMember *sender, const QString &selectedText, const QString &hoveredLink)
|
||||
{
|
||||
if (eventId.isEmpty()) {
|
||||
qWarning() << "Tried to open event menu with empty event id";
|
||||
return;
|
||||
}
|
||||
const auto &event = **room->findInTimeline(eventId);
|
||||
|
||||
const auto it = room->findInTimeline(eventId);
|
||||
if (it == room->historyEdge()) {
|
||||
// This is probably a pending event
|
||||
return;
|
||||
}
|
||||
const auto &event = **it;
|
||||
if (EventHandler::mediaInfo(room, &event).contains("mimeType"_L1)) {
|
||||
Q_EMIT showFileMenu(eventId,
|
||||
sender,
|
||||
@@ -374,6 +357,19 @@ void RoomManager::visitRoom(Room *r, const QString &eventId)
|
||||
if (m_currentRoom && !m_currentRoom->editCache()->editId().isEmpty()) {
|
||||
m_currentRoom->editCache()->setEditId({});
|
||||
}
|
||||
if (m_currentRoom && !m_currentRoom->isSpace() && m_chatDocumentHandler) {
|
||||
// We're doing these things here because it is critical that they are switched at the same time
|
||||
if (m_chatDocumentHandler->document()) {
|
||||
m_currentRoom->mainCache()->setSavedText(m_chatDocumentHandler->document()->textDocument()->toPlainText());
|
||||
m_chatDocumentHandler->setRoom(room);
|
||||
if (room) {
|
||||
m_chatDocumentHandler->document()->textDocument()->setPlainText(room->mainCache()->savedText());
|
||||
room->mainCache()->setText(room->mainCache()->savedText());
|
||||
}
|
||||
} else {
|
||||
m_chatDocumentHandler->setRoom(room);
|
||||
}
|
||||
}
|
||||
|
||||
if (!room) {
|
||||
setCurrentRoom({});
|
||||
@@ -396,9 +392,7 @@ void RoomManager::joinRoom(Quotient::Connection *account, const QString &roomAli
|
||||
|
||||
// If no one gives us a homeserver suggestion, try the server specified in the alias/id.
|
||||
// Otherwise joining a remote room not on our homeserver will fail.
|
||||
// This is a hack and we're not supposed to do it. With room ids not containing the server going forward, it won't work anymore for new room versions.
|
||||
// FIXME: Let's keep it around anyway for now, remove it at some point, though
|
||||
if (vias.empty() && roomAliasOrId.contains(':'_L1)) {
|
||||
if (vias.empty()) {
|
||||
vias.append(roomAliasOrId.mid(roomAliasOrId.lastIndexOf(':'_L1) + 1));
|
||||
}
|
||||
|
||||
@@ -473,6 +467,18 @@ bool RoomManager::visitNonMatrix(const QUrl &url)
|
||||
return true;
|
||||
}
|
||||
|
||||
ChatDocumentHandler *RoomManager::chatDocumentHandler() const
|
||||
{
|
||||
return m_chatDocumentHandler;
|
||||
}
|
||||
|
||||
void RoomManager::setChatDocumentHandler(ChatDocumentHandler *handler)
|
||||
{
|
||||
m_chatDocumentHandler = handler;
|
||||
m_chatDocumentHandler->setRoom(m_currentRoom);
|
||||
Q_EMIT chatDocumentHandlerChanged();
|
||||
}
|
||||
|
||||
void RoomManager::setConnection(NeoChatConnection *connection)
|
||||
{
|
||||
if (m_connection == connection) {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <Quotient/roommember.h>
|
||||
#include <Quotient/uriresolver.h>
|
||||
|
||||
#include "chatdocumenthandler.h"
|
||||
#include "enums/messagecomponenttype.h"
|
||||
#include "enums/messagetype.h"
|
||||
#include "models/mediamessagefiltermodel.h"
|
||||
@@ -136,6 +137,13 @@ class RoomManager : public QObject, public UriResolverBase
|
||||
*/
|
||||
Q_PROPERTY(bool hasOpenRoom READ hasOpenRoom NOTIFY currentRoomChanged)
|
||||
|
||||
/**
|
||||
* @brief The ChatDocumentHandler for the open room.
|
||||
*
|
||||
* @sa ChatDocumentHandler
|
||||
*/
|
||||
Q_PROPERTY(ChatDocumentHandler *chatDocumentHandler READ chatDocumentHandler WRITE setChatDocumentHandler NOTIFY chatDocumentHandlerChanged)
|
||||
|
||||
public:
|
||||
virtual ~RoomManager();
|
||||
static RoomManager &instance();
|
||||
@@ -204,8 +212,12 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Show a media item maximized.
|
||||
*
|
||||
* @param index the index to open the maximize delegate model at. This is the
|
||||
* index in the MediaMessageFilterModel owned by this RoomManager. A value
|
||||
* of -1 opens a the default item.
|
||||
*/
|
||||
Q_INVOKABLE void maximizeMedia(const QString &eventId);
|
||||
Q_INVOKABLE void maximizeMedia(int index);
|
||||
|
||||
Q_INVOKABLE void maximizeCode(NeochatRoomMember *author, const QDateTime &time, const QString &codeText, const QString &language);
|
||||
|
||||
@@ -225,6 +237,9 @@ public:
|
||||
Q_INVOKABLE void
|
||||
viewEventMenu(const QString &eventId, NeoChatRoom *room, NeochatRoomMember *sender, const QString &selectedText = {}, const QString &hoveredLink = {});
|
||||
|
||||
ChatDocumentHandler *chatDocumentHandler() const;
|
||||
void setChatDocumentHandler(ChatDocumentHandler *handler);
|
||||
|
||||
/**
|
||||
* @brief Set a URL to be loaded as the initial room.
|
||||
*/
|
||||
@@ -327,6 +342,8 @@ Q_SIGNALS:
|
||||
*/
|
||||
void showMessage(MessageType::Type messageType, const QString &message);
|
||||
|
||||
void chatDocumentHandlerChanged();
|
||||
|
||||
void connectionChanged();
|
||||
|
||||
void directChatsActiveChanged();
|
||||
@@ -355,6 +372,7 @@ private:
|
||||
KConfigGroup m_lastRoomConfig;
|
||||
KConfigGroup m_lastSpaceConfig;
|
||||
KConfigGroup m_directChatsConfig;
|
||||
QPointer<ChatDocumentHandler> m_chatDocumentHandler;
|
||||
|
||||
RoomListModel *m_roomListModel;
|
||||
SortFilterRoomListModel *m_sortFilterRoomListModel;
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
#include <QDBusMetaType>
|
||||
|
||||
#include <KWindowSystem>
|
||||
|
||||
#include "controller.h"
|
||||
#include "models/roomlistmodel.h"
|
||||
#include "models/sortfilterroomlistmodel.h"
|
||||
@@ -88,9 +86,4 @@ void Runner::Run(const QString &id, const QString &actionId)
|
||||
WindowController::instance().showAndRaiseWindow(QString());
|
||||
}
|
||||
|
||||
void Runner::SetActivationToken(const QString &token)
|
||||
{
|
||||
KWindowSystem::setCurrentXdgActivationToken(token);
|
||||
}
|
||||
|
||||
#include "moc_runner.cpp"
|
||||
|
||||
@@ -190,8 +190,6 @@ public:
|
||||
*/
|
||||
Q_SCRIPTABLE void Run(const QString &id, const QString &actionId);
|
||||
|
||||
Q_SCRIPTABLE void SetActivationToken(const QString &token);
|
||||
|
||||
Q_SIGNALS:
|
||||
void roomListModelChanged();
|
||||
|
||||
|
||||
@@ -15,5 +15,4 @@ ecm_add_qml_module(Chatbar GENERATE_PLUGIN_SOURCE
|
||||
EmojiPicker.qml
|
||||
EmojiDialog.qml
|
||||
EmojiTonesPicker.qml
|
||||
ImageEditorPage.qml
|
||||
)
|
||||
|
||||
@@ -87,7 +87,7 @@ QQC2.Control {
|
||||
displayHint: Kirigami.DisplayHint.IconOnly
|
||||
|
||||
onTriggered: {
|
||||
let dialog = (Clipboard.hasImage ? attachDialog : openFileDialog).createObject(root.QQC2.Overlay.overlay);
|
||||
let dialog = (Clipboard.hasImage ? attachDialog : openFileDialog).createObject(applicationWindow().overlay);
|
||||
dialog.chosen.connect(path => _private.chatBarCache.attachmentPath = path);
|
||||
dialog.open();
|
||||
}
|
||||
@@ -160,6 +160,11 @@ QQC2.Control {
|
||||
}
|
||||
]
|
||||
|
||||
/**
|
||||
* @brief A message has been sent from the chat bar.
|
||||
*/
|
||||
signal messageSent
|
||||
|
||||
spacing: 0
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
@@ -197,22 +202,6 @@ QQC2.Control {
|
||||
visible: root.currentRoom.mainCache.replyId.length > 0
|
||||
sourceComponent: replyPane
|
||||
}
|
||||
RowLayout {
|
||||
visible: replyLoader.visible && !root.currentRoom.mainCache.relationAuthorIsPresent
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Kirigami.Icon {
|
||||
source: "help-hint-symbolic"
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.small
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.small
|
||||
}
|
||||
QQC2.Label {
|
||||
text: i18nc("@info", "The user you're replying to has left the room, and can't be notified.")
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
id: attachLoader
|
||||
|
||||
@@ -398,6 +387,8 @@ QQC2.Control {
|
||||
implicitHeight: replyComponent.implicitHeight
|
||||
ReplyComponent {
|
||||
id: replyComponent
|
||||
replyEventId: _private.chatBarCache.replyId
|
||||
replyAuthor: _private.chatBarCache.relationAuthor
|
||||
replyContentModel: ContentProvider.contentModelForEvent(root.currentRoom, _private.chatBarCache.replyId, true)
|
||||
Message.maxContentWidth: replyLoader.item.width
|
||||
|
||||
@@ -438,12 +429,14 @@ QQC2.Control {
|
||||
QtObject {
|
||||
id: _private
|
||||
property ChatBarCache chatBarCache
|
||||
onChatBarCacheChanged: documentHandler.chatBarCache = chatBarCache
|
||||
|
||||
function postMessage() {
|
||||
_private.chatBarCache.postMessage();
|
||||
repeatTimer.stop();
|
||||
root.currentRoom.markAllMessagesAsRead();
|
||||
textField.clear();
|
||||
messageSent();
|
||||
}
|
||||
|
||||
function formatText(format, selectionStart, selectionEnd) {
|
||||
@@ -499,14 +492,15 @@ QQC2.Control {
|
||||
|
||||
ChatDocumentHandler {
|
||||
id: documentHandler
|
||||
type: ChatBarType.Room
|
||||
room: root.currentRoom
|
||||
document: textField.textDocument
|
||||
cursorPosition: textField.cursorPosition
|
||||
selectionStart: textField.selectionStart
|
||||
selectionEnd: textField.selectionEnd
|
||||
mentionColor: Kirigami.Theme.linkColor
|
||||
errorColor: Kirigami.Theme.negativeTextColor
|
||||
Component.onCompleted: {
|
||||
RoomManager.chatDocumentHandler = documentHandler;
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
|
||||
@@ -25,7 +25,7 @@ QQC2.Popup {
|
||||
|
||||
Connections {
|
||||
target: RoomManager
|
||||
function onCurrentRoomChanged(): void {
|
||||
function onCurrentRoomChanged() {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ QQC2.Popup {
|
||||
padding: 2
|
||||
|
||||
implicitHeight: Kirigami.Units.gridUnit * 20 + 2 * padding
|
||||
width: Math.min(contentItem.categoryIconSize * 11 + 2 * padding, QQC2.ApplicationWindow.window.width)
|
||||
width: Math.min(contentItem.categoryIconSize * 11 + 2 * padding, applicationWindow().width)
|
||||
contentItem: EmojiPicker {
|
||||
id: emojiPicker
|
||||
height: 400
|
||||
|
||||
@@ -207,7 +207,7 @@ ColumnLayout {
|
||||
padding: Kirigami.Units.largeSpacing
|
||||
|
||||
contentItem: Image {
|
||||
source: model.url
|
||||
source: model.avatarUrl
|
||||
fillMode: Image.PreserveAspectFit
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
|
||||
@@ -20,13 +20,6 @@ FormCard.FormCard {
|
||||
|
||||
onToggled: NeoChatConfig.showAllEvents = checked
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
text: i18nc("@option:check", "Allow sending relations to any event in the timeline")
|
||||
description: i18nc("@info", "This includes state events")
|
||||
checked: NeoChatConfig.relateAnyEvent
|
||||
|
||||
onToggled: NeoChatConfig.relateAnyEvent = checked
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
id: roomAccountDataVisibleCheck
|
||||
text: i18nc("@option:check Enable the matrix 'threads' feature", "Always allow device verification")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user