Compare commits
1 Commits
work/adapt
...
work/jz/fl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae155805e9 |
@@ -2,7 +2,7 @@
|
||||
"id": "org.kde.neochat",
|
||||
"branch": "master",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "6.6",
|
||||
"runtime-version": "6.7",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"command": "neochat",
|
||||
"tags": [
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,4 +12,3 @@ kate.project.ctags.*
|
||||
.idea/
|
||||
cmake-build-*
|
||||
src/res.generated.qrc
|
||||
.qmlls.ini
|
||||
|
||||
@@ -28,7 +28,6 @@ Dependencies:
|
||||
'frameworks/kio': '@latest-kf6'
|
||||
'frameworks/kwindowsystem': '@latest-kf6'
|
||||
'frameworks/kstatusnotifieritem': '@latest-kf6'
|
||||
'frameworks/kcrash': '@latest-kf6'
|
||||
- 'on': ['Linux', 'FreeBSD']
|
||||
'require':
|
||||
'frameworks/kdbusaddons': '@latest-kf6'
|
||||
|
||||
@@ -84,7 +84,7 @@ if(ANDROID)
|
||||
)
|
||||
else()
|
||||
find_package(Qt6 ${QT_MIN_VERSION} COMPONENTS Widgets)
|
||||
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle KIO WindowSystem StatusNotifierItem Crash)
|
||||
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle KIO WindowSystem StatusNotifierItem)
|
||||
find_package(KF6SyntaxHighlighting ${KF_MIN_VERSION} REQUIRED)
|
||||
set_package_properties(KF6QQC2DesktopStyle PROPERTIES
|
||||
TYPE RUNTIME
|
||||
|
||||
48
README.md
48
README.md
@@ -1,6 +1,6 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carlschwan@kde.org>
|
||||
SPDX-FileCopyrightText: 2020-2024 Tobias Fella <tobias.fella@kde.org>
|
||||
SPDX-FileCopyrightText: 2020-2021 Tobias Fella <tobias.fella@kde.org>
|
||||
SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
-->
|
||||
@@ -16,18 +16,19 @@ A Qt/QML based Matrix client.
|
||||
## Introduction
|
||||
|
||||
NeoChat is a client for [Matrix](https://matrix.org), the decentralized communication protocol for instant
|
||||
messaging.
|
||||
messaging. It is a fork of Spectral, using KDE frameworks, most notably [Kirigami](https://invent.kde.org/frameworks/kirigami)
|
||||
to provide a convergent experience across multiple platforms.
|
||||
|
||||
NeoChat is based on KDE frameworks and as [libQuotient](https://github.com/quotient-im/libQuotient), a
|
||||
NeoChat also make use of other KDE Frameworks as well as [libQuotient](https://github.com/quotient-im/libQuotient), a
|
||||
Qt-based SDK for the [Matrix Protocol](https://spec.matrix.org/).
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
NeoChat aims to be a fully featured application for the Matrix specification. As such most parts of the current specification are supported, with the notable exceptions
|
||||
of VoIP, threads, and some aspects of End-to-End Encryption. There are a few other smaller omissions due to the fact that the Matrix spec is constantly
|
||||
evolving, but the aim remains to provide eventual support for the entire spec.
|
||||
NeoChat aims to be a fully featured application for the Matrix specification. As such everything in the current stable specification with the notable exceptions
|
||||
of VoIP, threads and some aspects of End-to-End Encryption are supported. There are a few other smaller omissions due to the fact that the Matrix spec is constantly
|
||||
evolving but the aim remains to provide eventual support for the entire spec.
|
||||
|
||||
Due to the nature of the Matrix specification development NeoChat also supports numerous unstable features. Currently these are:
|
||||
- Polls - MSC3381
|
||||
@@ -38,9 +39,26 @@ Due to the nature of the Matrix specification development NeoChat also supports
|
||||
|
||||
Details where to find stable releases for NeoChat can be found on its [homepage](https://apps.kde.org/neochat).
|
||||
|
||||
Nightly builds for linux and windows can be downloaded from [cdn.kde.org](https://cdn.kde.org/ci-builds/network/neochat/).
|
||||
Nightly builds for android are available from [KDE's nightly F-Droid repository](https://community.kde.org/Android/F-Droid).
|
||||
Nightly Flatpaks are available from [KDE's nightly Flatpak repository](https://userbase.kde.org/Tutorials/Flatpak).
|
||||
In addition to the stable builds, unstable nightly builds are available for all platforms. These can be downloaded
|
||||
from the [binary factory](https://binary-factory.kde.org/). There are unstable versions for the following platforms
|
||||
in addition to stable ones:
|
||||
- Android
|
||||
- MacOS
|
||||
- Windows
|
||||
|
||||
Additionally the nightly Flatpak version can be obtained from the nightly Flatpak repo using the following commands in your terminal:
|
||||
|
||||
```
|
||||
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak remote-add --if-not-exists kdeapps --from https://distribute.kde.org/kdeapps.flatpakrepo
|
||||
flatpak install kdeapps org.kde.neochat
|
||||
```
|
||||
|
||||
The unstable Android version can also be obtained from the [KDE nightly F-Droid repo](https://community.kde.org/Android/FDroid).
|
||||
|
||||
## Running
|
||||
|
||||
Just start the executable in your preferred way - either from the build directory or from the installed location.
|
||||
|
||||
## Building NeoChat
|
||||
|
||||
@@ -51,18 +69,14 @@ is primarily aimed at Linux development.
|
||||
For Windows and Android [Craft](https://invent.kde.org/packaging/craft) is the primary choice. There are guides for setting up
|
||||
development environments for [Windows](https://community.kde.org/Get_Involved/development/Windows) and [Android](https://develop.kde.org/docs/packaging/android/building_applications/).
|
||||
|
||||
## Running
|
||||
|
||||
Just start the executable in your preferred way - either from the build directory or from the installed location.
|
||||
|
||||
## Tests
|
||||
|
||||
Tests are in the repository under [autotests](autotests) and [appiumtests](appiumtests).
|
||||
Tests are in the repository under [autotests](autotests) and should all pass for any contribution.
|
||||
|
||||
The project has CI setup to test new commits to the repository. All tests are expected to pass for a merge request to
|
||||
be complete.
|
||||
|
||||
## Current build status
|
||||
Current build status
|
||||
|
||||

|
||||
|
||||
@@ -86,9 +100,9 @@ The best place to reach the maintainers is on the KDE Matrix instance in the Neo
|
||||
|
||||
## Acknowledgement
|
||||
|
||||
NeoChat utilizes [libQuotient](https://github.com/quotient-im/libQuotient/) as its Matrix SDK.
|
||||
This program utilizes [libQuotient](https://github.com/quotient-im/libQuotient/) as its Matrix SDK.
|
||||
|
||||
NeoChat is a fork of [Spectral](https://gitlab.com/spectral-im/spectral/).
|
||||
This program is a fork of [Spectral](https://gitlab.com/spectral-im/spectral/).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -39,10 +39,6 @@ class OpenUserDetailsTest(unittest.TestCase):
|
||||
|
||||
def test_open_sheet(self):
|
||||
self.driver.find_element(by=AppiumBy.NAME, value="@user:localhost:1234").click()
|
||||
try:
|
||||
self.driver.find_element(by=AppiumBy.NAME, value="Expand Normal").click()
|
||||
except:
|
||||
pass
|
||||
self.driver.find_element(by=AppiumBy.NAME, value="Empty room (!room_id_1234:localhost:1234)").click()
|
||||
self.driver.find_element(by=AppiumBy.NAME, value="A Display Name").click()
|
||||
self.driver.find_element(by=AppiumBy.NAME, value="Account Details")
|
||||
|
||||
@@ -130,7 +130,7 @@ void DelegateSizeHelperTest::equalBreakpoint_data()
|
||||
}
|
||||
|
||||
/**
|
||||
* We expect a default return except in the case where the two percentages are
|
||||
* We expect a default return except in the case where the the two percentages are
|
||||
* equal as that case can be calculated without dividing by zero.
|
||||
*/
|
||||
void DelegateSizeHelperTest::equalBreakpoint()
|
||||
|
||||
@@ -105,7 +105,7 @@ void EventHandlerTest::author()
|
||||
|
||||
auto eventHandlerAuthor = eventHandler.getAuthor();
|
||||
|
||||
QCOMPARE(eventHandlerAuthor["isLocalUser"_ls], author->id() == room->localMember().id());
|
||||
QCOMPARE(eventHandlerAuthor["isLocalUser"_ls], author->id() == room->localUser()->id());
|
||||
QCOMPARE(eventHandlerAuthor["id"_ls], author->id());
|
||||
QCOMPARE(eventHandlerAuthor["displayName"_ls], author->displayname(room));
|
||||
QCOMPARE(eventHandlerAuthor["avatarSource"_ls], room->avatarForMember(author));
|
||||
@@ -390,7 +390,7 @@ void EventHandlerTest::replyAuthor()
|
||||
|
||||
auto eventHandlerReplyAuthor = eventHandler.getReplyAuthor();
|
||||
|
||||
QCOMPARE(eventHandlerReplyAuthor["isLocalUser"_ls], replyAuthor->id() == room->localMember().id());
|
||||
QCOMPARE(eventHandlerReplyAuthor["isLocalUser"_ls], replyAuthor->id() == room->localUser()->id());
|
||||
QCOMPARE(eventHandlerReplyAuthor["id"_ls], replyAuthor->id());
|
||||
QCOMPARE(eventHandlerReplyAuthor["displayName"_ls], replyAuthor->displayname(room));
|
||||
QCOMPARE(eventHandlerReplyAuthor["avatarSource"_ls], room->avatarForMember(replyAuthor));
|
||||
|
||||
@@ -32,6 +32,8 @@ private Q_SLOTS:
|
||||
|
||||
void linkPreviewsReject_data();
|
||||
void linkPreviewsReject();
|
||||
|
||||
void editedLink();
|
||||
};
|
||||
|
||||
void LinkPreviewerTest::initTestCase()
|
||||
@@ -57,7 +59,7 @@ void LinkPreviewerTest::linkPreviewsMatch()
|
||||
QFETCH(QUrl, testOutputLink);
|
||||
|
||||
auto event = TestUtils::loadEventFromFile<RoomMessageEvent>(eventSource);
|
||||
auto linkPreviewer = LinkPreviewer(LinkPreviewer::linkPreview(event.get()), connection);
|
||||
auto linkPreviewer = LinkPreviewer(room, event.get());
|
||||
|
||||
QCOMPARE(linkPreviewer.empty(), false);
|
||||
QCOMPARE(linkPreviewer.url(), testOutputLink);
|
||||
@@ -77,7 +79,22 @@ void LinkPreviewerTest::linkPreviewsReject()
|
||||
QFETCH(QString, eventSource);
|
||||
|
||||
auto event = TestUtils::loadEventFromFile<RoomMessageEvent>(eventSource);
|
||||
auto linkPreviewer = LinkPreviewer(LinkPreviewer::linkPreview(event.get()), connection);
|
||||
auto linkPreviewer = LinkPreviewer(room, event.get());
|
||||
|
||||
QCOMPARE(linkPreviewer.empty(), true);
|
||||
QCOMPARE(linkPreviewer.url(), QUrl());
|
||||
}
|
||||
|
||||
void LinkPreviewerTest::editedLink()
|
||||
{
|
||||
room->syncNewEvents(QStringLiteral("test-linkpreviewerintial-sync.json"));
|
||||
auto event = eventCast<const RoomMessageEvent>(room->messageEvents().at(0).get());
|
||||
auto linkPreviewer = LinkPreviewer(room, event);
|
||||
|
||||
QCOMPARE(linkPreviewer.empty(), false);
|
||||
QCOMPARE(linkPreviewer.url(), QUrl("https://kde.org"_ls));
|
||||
|
||||
room->syncNewEvents(QStringLiteral("test-linkpreviewerreplace-sync.json"));
|
||||
|
||||
QCOMPARE(linkPreviewer.empty(), true);
|
||||
QCOMPARE(linkPreviewer.url(), QUrl());
|
||||
|
||||
@@ -394,7 +394,6 @@
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
</content_rating>
|
||||
<releases>
|
||||
<release version="24.02.2" date="2024-04-11"/>
|
||||
<release version="24.02.1" date="2024-03-21"/>
|
||||
<release version="24.02.0" date="2024-02-28">
|
||||
<url>https://kde.org/announcements/megarelease/6/#neochat</url>
|
||||
|
||||
1024
po/ar/neochat.po
1024
po/ar/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1025
po/az/neochat.po
1025
po/az/neochat.po
File diff suppressed because it is too large
Load Diff
987
po/ca/neochat.po
987
po/ca/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
982
po/cs/neochat.po
982
po/cs/neochat.po
File diff suppressed because it is too large
Load Diff
1011
po/da/neochat.po
1011
po/da/neochat.po
File diff suppressed because it is too large
Load Diff
1027
po/de/neochat.po
1027
po/de/neochat.po
File diff suppressed because it is too large
Load Diff
1024
po/el/neochat.po
1024
po/el/neochat.po
File diff suppressed because it is too large
Load Diff
1026
po/en_GB/neochat.po
1026
po/en_GB/neochat.po
File diff suppressed because it is too large
Load Diff
987
po/eo/neochat.po
987
po/eo/neochat.po
File diff suppressed because it is too large
Load Diff
988
po/es/neochat.po
988
po/es/neochat.po
File diff suppressed because it is too large
Load Diff
992
po/eu/neochat.po
992
po/eu/neochat.po
File diff suppressed because it is too large
Load Diff
998
po/fi/neochat.po
998
po/fi/neochat.po
File diff suppressed because it is too large
Load Diff
990
po/fr/neochat.po
990
po/fr/neochat.po
File diff suppressed because it is too large
Load Diff
997
po/hu/neochat.po
997
po/hu/neochat.po
File diff suppressed because it is too large
Load Diff
992
po/ia/neochat.po
992
po/ia/neochat.po
File diff suppressed because it is too large
Load Diff
1026
po/id/neochat.po
1026
po/id/neochat.po
File diff suppressed because it is too large
Load Diff
1001
po/ie/neochat.po
1001
po/ie/neochat.po
File diff suppressed because it is too large
Load Diff
997
po/it/neochat.po
997
po/it/neochat.po
File diff suppressed because it is too large
Load Diff
964
po/ja/neochat.po
964
po/ja/neochat.po
File diff suppressed because it is too large
Load Diff
990
po/ka/neochat.po
990
po/ka/neochat.po
File diff suppressed because it is too large
Load Diff
997
po/ko/neochat.po
997
po/ko/neochat.po
File diff suppressed because it is too large
Load Diff
964
po/lt/neochat.po
964
po/lt/neochat.po
File diff suppressed because it is too large
Load Diff
991
po/lv/neochat.po
991
po/lv/neochat.po
File diff suppressed because it is too large
Load Diff
992
po/nl/neochat.po
992
po/nl/neochat.po
File diff suppressed because it is too large
Load Diff
1001
po/nn/neochat.po
1001
po/nn/neochat.po
File diff suppressed because it is too large
Load Diff
1027
po/pa/neochat.po
1027
po/pa/neochat.po
File diff suppressed because it is too large
Load Diff
993
po/pl/neochat.po
993
po/pl/neochat.po
File diff suppressed because it is too large
Load Diff
1024
po/pt/neochat.po
1024
po/pt/neochat.po
File diff suppressed because it is too large
Load Diff
1027
po/pt_BR/neochat.po
1027
po/pt_BR/neochat.po
File diff suppressed because it is too large
Load Diff
1016
po/ru/neochat.po
1016
po/ru/neochat.po
File diff suppressed because it is too large
Load Diff
1025
po/sk/neochat.po
1025
po/sk/neochat.po
File diff suppressed because it is too large
Load Diff
983
po/sl/neochat.po
983
po/sl/neochat.po
File diff suppressed because it is too large
Load Diff
1012
po/sv/neochat.po
1012
po/sv/neochat.po
File diff suppressed because it is too large
Load Diff
1023
po/ta/neochat.po
1023
po/ta/neochat.po
File diff suppressed because it is too large
Load Diff
1008
po/tok/neochat.po
1008
po/tok/neochat.po
File diff suppressed because it is too large
Load Diff
985
po/tr/neochat.po
985
po/tr/neochat.po
File diff suppressed because it is too large
Load Diff
990
po/uk/neochat.po
990
po/uk/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1058
po/zh_TW/neochat.po
1058
po/zh_TW/neochat.po
File diff suppressed because it is too large
Load Diff
@@ -174,9 +174,6 @@ add_library(neochat STATIC
|
||||
sharehandler.h
|
||||
models/roomtreeitem.cpp
|
||||
models/roomtreeitem.h
|
||||
foreigntypes.h
|
||||
models/threepidmodel.cpp
|
||||
models/threepidmodel.h
|
||||
)
|
||||
|
||||
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
|
||||
@@ -186,7 +183,7 @@ set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
|
||||
qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN
|
||||
OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/org/kde/neochat
|
||||
QML_FILES
|
||||
qml/Main.qml
|
||||
qml/main.qml
|
||||
qml/AccountMenu.qml
|
||||
qml/ExploreComponent.qml
|
||||
qml/ExploreComponentMobile.qml
|
||||
@@ -203,6 +200,7 @@ qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN
|
||||
qml/ExplorerDelegate.qml
|
||||
qml/InviteUserPage.qml
|
||||
qml/ImageEditorPage.qml
|
||||
qml/WelcomePage.qml
|
||||
qml/NeochatMaximizeComponent.qml
|
||||
qml/FancyEffectsContainer.qml
|
||||
qml/TypingPane.qml
|
||||
@@ -215,6 +213,19 @@ qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN
|
||||
qml/PieProgressBar.qml
|
||||
qml/QuickFormatBar.qml
|
||||
qml/EmojiPicker.qml
|
||||
qml/LoginStep.qml
|
||||
qml/Login.qml
|
||||
qml/Homeserver.qml
|
||||
qml/Username.qml
|
||||
qml/RegisterPassword.qml
|
||||
qml/Captcha.qml
|
||||
qml/Terms.qml
|
||||
qml/Email.qml
|
||||
qml/Password.qml
|
||||
qml/LoginRegister.qml
|
||||
qml/Loading.qml
|
||||
qml/LoginMethod.qml
|
||||
qml/Sso.qml
|
||||
qml/UserDetailDialog.qml
|
||||
qml/CreateRoomDialog.qml
|
||||
qml/EmojiDialog.qml
|
||||
@@ -280,7 +291,6 @@ qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN
|
||||
qml/AccountSwitchDialog.qml
|
||||
qml/ConfirmLeaveDialog.qml
|
||||
qml/CodeMaximizeComponent.qml
|
||||
qml/EditStateDialog.qml
|
||||
RESOURCES
|
||||
qml/confetti.png
|
||||
qml/glowdot.png
|
||||
@@ -289,7 +299,6 @@ qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN
|
||||
add_subdirectory(settings)
|
||||
add_subdirectory(timeline)
|
||||
add_subdirectory(devtools)
|
||||
add_subdirectory(login)
|
||||
|
||||
if(UNIX)
|
||||
qt_target_qml_sources(neochat QML_FILES qml/ShareAction.qml)
|
||||
@@ -381,7 +390,7 @@ if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
||||
endif()
|
||||
|
||||
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/models ${CMAKE_CURRENT_SOURCE_DIR}/enums)
|
||||
target_link_libraries(neochat PRIVATE settingsplugin timelineplugin devtoolsplugin loginplugin)
|
||||
target_link_libraries(neochat PRIVATE settingsplugin timelineplugin devtoolsplugin)
|
||||
target_link_libraries(neochat PUBLIC
|
||||
Qt::Core
|
||||
Qt::Quick
|
||||
@@ -405,10 +414,6 @@ target_link_libraries(neochat PUBLIC
|
||||
QCoro::Network
|
||||
)
|
||||
|
||||
if (TARGET KF6::Crash)
|
||||
target_link_libraries(neochat PUBLIC KF6::Crash)
|
||||
endif()
|
||||
|
||||
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
|
||||
|
||||
if(NEOCHAT_FLATPAK)
|
||||
|
||||
@@ -91,7 +91,7 @@ void ActionsHandler::handleMessage(const QString &text, QString handledText, Cha
|
||||
|
||||
for (auto it = m_room->messageEvents().crbegin(); it != m_room->messageEvents().crend(); it++) {
|
||||
if (const auto event = eventCast<const RoomMessageEvent>(&**it)) {
|
||||
if (event->senderId() == m_room->localMember().id() && event->hasTextContent()) {
|
||||
if (event->senderId() == m_room->localUser()->id() && event->hasTextContent()) {
|
||||
QString originalString;
|
||||
if (event->content()) {
|
||||
originalString = static_cast<const Quotient::EventContent::TextContent *>(event->content())->body;
|
||||
|
||||
@@ -91,7 +91,7 @@ class ChatDocumentHandler : public QObject
|
||||
Q_PROPERTY(CompletionModel *completionModel READ completionModel CONSTANT)
|
||||
|
||||
/**
|
||||
* @brief The current room that the text document is being handled for.
|
||||
* @brief The current room that the the text document is being handled for.
|
||||
*/
|
||||
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ void Controller::addConnection(NeoChatConnection *c)
|
||||
});
|
||||
connect(c, &NeoChatConnection::loggedOut, this, [this, c] {
|
||||
if (accounts().count() > 1) {
|
||||
// Only set the connection if the account being logged out is currently active
|
||||
// Only set the connection if the the account being logged out is currently active
|
||||
if (c == activeConnection()) {
|
||||
setActiveConnection(dynamic_cast<NeoChatConnection *>(accounts().accounts()[0]));
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ ColumnLayout {
|
||||
model: root.connection.accountDataEventTypes
|
||||
delegate: FormCard.FormButtonDelegate {
|
||||
text: modelData
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet.qml'), {
|
||||
sourceText: root.connection.accountDataJsonString(modelData)
|
||||
}, {
|
||||
title: i18nc("@title:window", "Event Source"),
|
||||
|
||||
@@ -8,7 +8,6 @@ qt_add_qml_module(devtools
|
||||
QML_FILES
|
||||
DevtoolsPage.qml
|
||||
AccountData.qml
|
||||
DebugOptions.qml
|
||||
FeatureFlagPage.qml
|
||||
RoomData.qml
|
||||
ServerData.qml
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
FormCard.FormCardPage {
|
||||
id: root
|
||||
|
||||
FormCard.FormCard {
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: roomAccountDataVisibleCheck
|
||||
text: i18nc("@option:check Enable the matrix 'threads' feature", "Always allow device verification")
|
||||
description: i18n("Allow the user to start a verification session with devices that were already verified")
|
||||
checked: Config.alwaysVerifyDevice
|
||||
|
||||
onToggled: Config.alwaysVerifyDevice = checked
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,11 +25,6 @@ FormCard.FormCardPage {
|
||||
|
||||
readonly property real tabWidth: tabBar.width / tabBar.count
|
||||
|
||||
QQC2.TabButton {
|
||||
text: i18nc("@title:tab", "Debug Options")
|
||||
|
||||
implicitWidth: tabBar.tabWidth
|
||||
}
|
||||
QQC2.TabButton {
|
||||
text: qsTr("Room Data")
|
||||
|
||||
@@ -57,7 +52,6 @@ FormCard.FormCardPage {
|
||||
|
||||
currentIndex: tabBar.currentIndex
|
||||
|
||||
DebugOptions {}
|
||||
RoomData {
|
||||
room: root.room
|
||||
connection: root.connection
|
||||
|
||||
@@ -7,7 +7,7 @@ import QtQuick.Layouts
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
|
||||
import org.kde.neochat
|
||||
import org.kde.neochat.config
|
||||
|
||||
FormCard.FormCardPage {
|
||||
id: root
|
||||
|
||||
@@ -46,7 +46,7 @@ ColumnLayout {
|
||||
model: root.room.accountDataEventTypes
|
||||
delegate: FormCard.FormButtonDelegate {
|
||||
text: modelData
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet.qml'), {
|
||||
sourceText: root.room.roomAcountDataJson(text)
|
||||
}, {
|
||||
title: i18n("Event Source"),
|
||||
@@ -74,9 +74,14 @@ ColumnLayout {
|
||||
description: i18ncp("'Event' being some JSON data, not something physically happening.", "%1 event of this type", "%1 events of this type", model.eventCount)
|
||||
onClicked: {
|
||||
if (model.eventCount === 1) {
|
||||
openEventSource(model.type, model.stateKey);
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet.qml'), {
|
||||
sourceText: stateModel.stateEventJson(stateModel.index(model.index, 0))
|
||||
}, {
|
||||
title: i18n("Event Source"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
})
|
||||
} else {
|
||||
pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.devtools', 'StateKeys'), {
|
||||
pageStack.pushDialogLayer(stateKeysComponent, {
|
||||
room: root.room,
|
||||
eventType: model.type
|
||||
}, {
|
||||
@@ -86,17 +91,9 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function openEventSource(type: string, stateKey: string): void {
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
model: stateModel,
|
||||
allowEdit: true,
|
||||
room: root.room,
|
||||
type: type,
|
||||
stateKey: stateKey,
|
||||
}, {
|
||||
title: i18n("Event Source"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
Component {
|
||||
id: stateKeysComponent
|
||||
StateKeys {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,21 +31,13 @@ FormCard.FormCardPage {
|
||||
|
||||
delegate: FormCard.FormButtonDelegate {
|
||||
text: model.stateKey
|
||||
onClicked: openEventSource(model.stateKey)
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet.qml'), {
|
||||
sourceText: stateKeysModel.stateEventJson(stateKeysModel.index(model.index, 0))
|
||||
}, {
|
||||
title: i18nc("@title:window", "Event Source"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openEventSource(stateKey: string): void {
|
||||
applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
model: stateKeysModel,
|
||||
allowEdit: true,
|
||||
room: root.room,
|
||||
type: root.eventType,
|
||||
stateKey: stateKey
|
||||
}, {
|
||||
title: i18nc("@title:window", "Event Source"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ QVariantMap EventHandler::getAuthor(bool isPending) const
|
||||
return m_room->getUser(nullptr);
|
||||
}
|
||||
|
||||
const auto author = isPending ? m_room->localMember() : m_room->user(m_event->senderId());
|
||||
const auto author = isPending ? m_room->localUser() : m_room->user(m_event->senderId());
|
||||
return m_room->getUser(author);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ QString EventHandler::getAuthorDisplayName(bool isPending) const
|
||||
}
|
||||
return previousDisplayName;
|
||||
} else {
|
||||
const auto author = isPending ? m_room->localMember() : m_room->user(m_event->senderId());
|
||||
const auto author = isPending ? m_room->localUser() : m_room->user(m_event->senderId());
|
||||
return m_room->htmlSafeMemberName(author->id());
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ QString EventHandler::singleLineAuthorDisplayname(bool isPending) const
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto author = isPending ? m_room->localMember() : m_room->user(m_event->senderId());
|
||||
const auto author = isPending ? m_room->localUser() : m_room->user(m_event->senderId());
|
||||
auto displayName = m_room->safeMemberName(author->id());
|
||||
displayName.replace(QStringLiteral("<br>\n"), QStringLiteral(" "));
|
||||
displayName.replace(QStringLiteral("<br>"), QStringLiteral(" "));
|
||||
@@ -963,7 +963,7 @@ bool EventHandler::hasReadMarkers() const
|
||||
}
|
||||
|
||||
auto userIds = m_room->userIdsAtEvent(m_event->id());
|
||||
userIds.remove(m_room->localMember().id());
|
||||
userIds.remove(m_room->localUser()->id());
|
||||
return userIds.size() > 0;
|
||||
}
|
||||
|
||||
@@ -979,7 +979,7 @@ QVariantList EventHandler::getReadMarkers(int maxMarkers) const
|
||||
}
|
||||
|
||||
auto userIds_temp = m_room->userIdsAtEvent(m_event->id());
|
||||
userIds_temp.remove(m_room->localMember().id());
|
||||
userIds_temp.remove(m_room->localUser()->id());
|
||||
|
||||
auto userIds = userIds_temp.values();
|
||||
if (userIds.count() > maxMarkers) {
|
||||
@@ -1008,7 +1008,7 @@ QString EventHandler::getNumberExcessReadMarkers(int maxMarkers) const
|
||||
}
|
||||
|
||||
auto userIds = m_room->userIdsAtEvent(m_event->id());
|
||||
userIds.remove(m_room->localMember().id());
|
||||
userIds.remove(m_room->localUser()->id());
|
||||
|
||||
if (userIds.count() > maxMarkers) {
|
||||
return QStringLiteral("+ ") + QString::number(userIds.count() - maxMarkers);
|
||||
@@ -1029,7 +1029,7 @@ QString EventHandler::getReadMarkersString() const
|
||||
}
|
||||
|
||||
auto userIds = m_room->userIdsAtEvent(m_event->id());
|
||||
userIds.remove(m_room->localMember().id());
|
||||
userIds.remove(m_room->localUser()->id());
|
||||
|
||||
/**
|
||||
* The string ends up in the form
|
||||
|
||||
@@ -74,9 +74,6 @@ void ImagePackEventContent::fillJson(QJsonObject *o) const
|
||||
}
|
||||
imageJson["usage"_ls] = usageJson;
|
||||
}
|
||||
if (image.info.has_value()) {
|
||||
imageJson["info"_ls] = Quotient::EventContent::toInfoJson(*image.info);
|
||||
}
|
||||
imagesJson[image.shortcode] = imageJson;
|
||||
}
|
||||
(*o)["images"_ls] = imagesJson;
|
||||
|
||||
@@ -89,4 +89,6 @@ public:
|
||||
QUO_EVENT(ImagePackEvent, "im.ponies.room_emotes")
|
||||
using KeyedStateEventBase::KeyedStateEventBase;
|
||||
};
|
||||
|
||||
REGISTER_EVENT_TYPE(ImagePackEvent)
|
||||
}
|
||||
|
||||
@@ -40,4 +40,5 @@ public:
|
||||
*/
|
||||
QJsonArray allow() const;
|
||||
};
|
||||
REGISTER_EVENT_TYPE(JoinRulesEvent)
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2024 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include <Quotient/accountregistry.h>
|
||||
#include <Quotient/keyverificationsession.h>
|
||||
#if __has_include("Quotient/e2ee/sssshandler.h")
|
||||
#include <Quotient/e2ee/sssshandler.h>
|
||||
#endif
|
||||
|
||||
#include "controller.h"
|
||||
#include "neochatconfig.h"
|
||||
|
||||
struct ForeignConfig {
|
||||
Q_GADGET
|
||||
QML_FOREIGN(NeoChatConfig)
|
||||
QML_NAMED_ELEMENT(Config)
|
||||
QML_SINGLETON
|
||||
public:
|
||||
static NeoChatConfig *create(QQmlEngine *, QJSEngine *)
|
||||
{
|
||||
QQmlEngine::setObjectOwnership(NeoChatConfig::self(), QQmlEngine::CppOwnership);
|
||||
return NeoChatConfig::self();
|
||||
}
|
||||
};
|
||||
|
||||
struct ForeignAccountRegistry {
|
||||
Q_GADGET
|
||||
QML_FOREIGN(Quotient::AccountRegistry)
|
||||
QML_NAMED_ELEMENT(AccountRegistry)
|
||||
QML_SINGLETON
|
||||
public:
|
||||
static Quotient::AccountRegistry *create(QQmlEngine *, QJSEngine *)
|
||||
{
|
||||
QQmlEngine::setObjectOwnership(&Controller::instance().accounts(), QQmlEngine::CppOwnership);
|
||||
return &Controller::instance().accounts();
|
||||
}
|
||||
};
|
||||
|
||||
struct ForeignKeyVerificationSession {
|
||||
Q_GADGET
|
||||
QML_FOREIGN(Quotient::KeyVerificationSession)
|
||||
QML_NAMED_ELEMENT(KeyVerificationSession)
|
||||
QML_UNCREATABLE("")
|
||||
};
|
||||
|
||||
#if __has_include("Quotient/e2ee/sssshandler.h")
|
||||
struct ForeignSSSSHandler {
|
||||
Q_GADGET
|
||||
QML_FOREIGN(Quotient::SSSSHandler)
|
||||
QML_NAMED_ELEMENT(SSSSHandler)
|
||||
};
|
||||
#endif
|
||||
@@ -8,22 +8,34 @@
|
||||
#include <Quotient/events/roommessageevent.h>
|
||||
|
||||
#include "neochatconfig.h"
|
||||
#include "neochatconnection.h"
|
||||
#include "neochatroom.h"
|
||||
#include "utils.h"
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
LinkPreviewer::LinkPreviewer(const QUrl &url, QObject *parent)
|
||||
LinkPreviewer::LinkPreviewer(const NeoChatRoom *room, const Quotient::RoomMessageEvent *event, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_currentRoom(room)
|
||||
, m_event(event)
|
||||
, m_loaded(false)
|
||||
, m_url(url)
|
||||
, m_url(linkPreview(event))
|
||||
{
|
||||
Q_ASSERT(dynamic_cast<Connection *>(this->parent()));
|
||||
|
||||
connect(this, &LinkPreviewer::urlChanged, this, &LinkPreviewer::emptyChanged);
|
||||
connect(NeoChatConfig::self(), &NeoChatConfig::ShowLinkPreviewChanged, this, &LinkPreviewer::loadUrlPreview);
|
||||
|
||||
loadUrlPreview();
|
||||
if (m_event != nullptr && m_currentRoom != nullptr) {
|
||||
loadUrlPreview();
|
||||
connect(m_currentRoom, &NeoChatRoom::urlPreviewEnabledChanged, this, &LinkPreviewer::loadUrlPreview);
|
||||
// Make sure that we react to edits
|
||||
connect(m_currentRoom, &NeoChatRoom::replacedEvent, this, [this](const Quotient::RoomEvent *newEvent) {
|
||||
if (m_event->id() == newEvent->id()) {
|
||||
m_event = eventCast<const Quotient::RoomMessageEvent>(newEvent);
|
||||
m_url = linkPreview(m_event);
|
||||
Q_EMIT urlChanged();
|
||||
loadUrlPreview();
|
||||
}
|
||||
});
|
||||
}
|
||||
connect(NeoChatConfig::self(), &NeoChatConfig::ShowLinkPreviewChanged, this, &LinkPreviewer::loadUrlPreview);
|
||||
}
|
||||
|
||||
bool LinkPreviewer::loaded() const
|
||||
@@ -53,14 +65,14 @@ QUrl LinkPreviewer::url() const
|
||||
|
||||
void LinkPreviewer::loadUrlPreview()
|
||||
{
|
||||
if (!m_currentRoom || !NeoChatConfig::showLinkPreview() || !m_currentRoom->urlPreviewEnabled()) {
|
||||
return;
|
||||
}
|
||||
if (m_url.scheme() == QStringLiteral("https")) {
|
||||
m_loaded = false;
|
||||
Q_EMIT loadedChanged();
|
||||
|
||||
auto conn = dynamic_cast<Connection *>(this->parent());
|
||||
if (conn == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto conn = m_currentRoom->connection();
|
||||
GetUrlPreviewJob *job = conn->callApi<GetUrlPreviewJob>(m_url);
|
||||
|
||||
connect(job, &BaseJob::success, this, [this, job, conn]() {
|
||||
|
||||
@@ -53,15 +53,14 @@ class LinkPreviewer : public QObject
|
||||
Q_PROPERTY(QUrl imageSource READ imageSource NOTIFY imageSourceChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether there is a link to preview.
|
||||
* @brief Whether the there is a link to preview.
|
||||
*
|
||||
* A linkPreviwer is empty if the URL is empty.
|
||||
*/
|
||||
Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged)
|
||||
|
||||
public:
|
||||
LinkPreviewer() = default;
|
||||
explicit LinkPreviewer(const QUrl &url, QObject *parent = nullptr);
|
||||
explicit LinkPreviewer(const NeoChatRoom *room = nullptr, const Quotient::RoomMessageEvent *event = nullptr, QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] QUrl url() const;
|
||||
[[nodiscard]] bool loaded() const;
|
||||
@@ -77,15 +76,10 @@ public:
|
||||
*/
|
||||
static bool hasPreviewableLinks(const Quotient::RoomMessageEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Return the link to be previewed from the given event.
|
||||
*
|
||||
* This function is designed to give only links that should be previewed so
|
||||
* http, https or something starting with www. The first valid link is returned.
|
||||
*/
|
||||
static QUrl linkPreview(const Quotient::RoomMessageEvent *event);
|
||||
|
||||
private:
|
||||
const NeoChatRoom *m_currentRoom;
|
||||
const Quotient::RoomMessageEvent *m_event;
|
||||
|
||||
bool m_loaded;
|
||||
QString m_title = QString();
|
||||
QString m_description = QString();
|
||||
@@ -94,6 +88,14 @@ private:
|
||||
|
||||
void loadUrlPreview();
|
||||
|
||||
/**
|
||||
* @brief Return the link to be previewed from the given event.
|
||||
*
|
||||
* This function is designed to give only links that should be previewed so
|
||||
* http, https or something starting with www. The first valid link is returned.
|
||||
*/
|
||||
static QUrl linkPreview(const Quotient::RoomMessageEvent *event);
|
||||
|
||||
Q_SIGNALS:
|
||||
void loadedChanged();
|
||||
void titleChanged();
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
qt_add_library(login STATIC)
|
||||
qt_add_qml_module(login
|
||||
URI org.kde.neochat.login
|
||||
OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/org/kde/neochat/login
|
||||
QML_FILES
|
||||
WelcomePage.qml
|
||||
LoginStep.qml
|
||||
Captcha.qml
|
||||
Email.qml
|
||||
Homeserver.qml
|
||||
Loading.qml
|
||||
Login.qml
|
||||
LoginMethod.qml
|
||||
LoginRegister.qml
|
||||
Password.qml
|
||||
RegisterPassword.qml
|
||||
Sso.qml
|
||||
Terms.qml
|
||||
Username.qml
|
||||
)
|
||||
24
src/main.cpp
24
src/main.cpp
@@ -30,16 +30,16 @@
|
||||
#ifdef HAVE_WINDOWSYSTEM
|
||||
#include <KWindowSystem>
|
||||
#endif
|
||||
|
||||
#if __has_include("KCrash")
|
||||
#include <KCrash>
|
||||
#endif
|
||||
|
||||
#include <KLocalizedContext>
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include "neochat-version.h"
|
||||
|
||||
#include <Quotient/accountregistry.h>
|
||||
#if __has_include("Quotient/e2ee/sssshandler.h")
|
||||
#include <Quotient/e2ee/sssshandler.h>
|
||||
#endif
|
||||
#include <Quotient/keyverificationsession.h>
|
||||
#include <Quotient/networkaccessmanager.h>
|
||||
|
||||
#include "blurhashimageprovider.h"
|
||||
@@ -167,10 +167,6 @@ int main(int argc, char *argv[])
|
||||
KAboutData::setApplicationData(about);
|
||||
QGuiApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("org.kde.neochat")));
|
||||
|
||||
#if __has_include("KCrash")
|
||||
KCrash::initialize();
|
||||
#endif
|
||||
|
||||
initLogging();
|
||||
|
||||
Connection::setEncryptionDefault(true);
|
||||
@@ -235,9 +231,15 @@ int main(int argc, char *argv[])
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_settingsPlugin)
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_timelinePlugin)
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_devtoolsPlugin)
|
||||
Q_IMPORT_QML_PLUGIN(org_kde_neochat_loginPlugin)
|
||||
|
||||
qml_register_types_org_kde_neochat();
|
||||
qmlRegisterSingletonInstance("org.kde.neochat.config", 1, 0, "Config", NeoChatConfig::self());
|
||||
qmlRegisterSingletonInstance("org.kde.neochat.accounts", 1, 0, "AccountRegistry", &Controller::instance().accounts());
|
||||
|
||||
qmlRegisterUncreatableType<KeyVerificationSession>("com.github.quotient_im.libquotient", 1, 0, "KeyVerificationSession", {});
|
||||
#if __has_include("Quotient/e2ee/sssshandler.h")
|
||||
qmlRegisterType<SSSSHandler>("com.github.quotient_im.libquotient", 1, 0, "SSSSHandler");
|
||||
#endif
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
@@ -288,7 +290,7 @@ int main(int argc, char *argv[])
|
||||
engine.addImageProvider(QLatin1String("mxc"), MatrixImageProvider::create(&engine, &engine));
|
||||
engine.addImageProvider(QLatin1String("blurhash"), new BlurhashImageProvider);
|
||||
|
||||
engine.loadFromModule("org.kde.neochat", "Main");
|
||||
engine.load(QUrl(QStringLiteral("qrc:/qt/qml/org/kde/neochat/qml/main.qml")));
|
||||
if (engine.rootObjects().isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -7,5 +7,3 @@ void MediaManager::startPlayback()
|
||||
{
|
||||
Q_EMIT playbackStarted();
|
||||
}
|
||||
|
||||
#include "moc_mediamanager.cpp"
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
|
||||
#include "accountemoticonmodel.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QMimeDatabase>
|
||||
|
||||
#include <Quotient/csapi/content-repo.h>
|
||||
#include <Quotient/events/eventcontent.h>
|
||||
#include <qcoro/qcorosignal.h>
|
||||
|
||||
using namespace Quotient;
|
||||
@@ -166,15 +162,7 @@ QCoro::Task<void> AccountEmoticonModel::doSetEmoticonImage(int index, QUrl sourc
|
||||
co_return;
|
||||
}
|
||||
m_images->images[index].url = job->contentUri();
|
||||
auto mime = QMimeDatabase().mimeTypeForUrl(source);
|
||||
source.setScheme("file"_ls);
|
||||
QFileInfo fileInfo(source.isLocalFile() ? source.toLocalFile() : source.toString());
|
||||
EventContent::ImageInfo info;
|
||||
if (mime.name().startsWith("image/"_ls)) {
|
||||
QImage image(source.toLocalFile());
|
||||
info = EventContent::ImageInfo(source, fileInfo.size(), mime, image.size(), fileInfo.fileName());
|
||||
}
|
||||
m_images->images[index].info = info;
|
||||
m_images->images[index].info = none;
|
||||
QJsonObject data;
|
||||
m_images->fillJson(&data);
|
||||
m_connection->setAccountData("im.ponies.user_emotes"_ls, data);
|
||||
@@ -187,21 +175,11 @@ QCoro::Task<void> AccountEmoticonModel::doAddEmoticon(QUrl source, QString short
|
||||
if (job->error() != BaseJob::NoError) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
auto mime = QMimeDatabase().mimeTypeForUrl(source);
|
||||
source.setScheme("file"_ls);
|
||||
QFileInfo fileInfo(source.isLocalFile() ? source.toLocalFile() : source.toString());
|
||||
EventContent::ImageInfo info;
|
||||
if (mime.name().startsWith("image/"_ls)) {
|
||||
QImage image(source.toLocalFile());
|
||||
info = EventContent::ImageInfo(source, fileInfo.size(), mime, image.size(), fileInfo.fileName());
|
||||
}
|
||||
|
||||
m_images->images.append(ImagePackEventContent::ImagePackImage{
|
||||
shortcode,
|
||||
job->contentUri(),
|
||||
description,
|
||||
info,
|
||||
none,
|
||||
QStringList{type},
|
||||
});
|
||||
QJsonObject data;
|
||||
|
||||
@@ -201,7 +201,7 @@ QList<ActionsModel::Action> actions{
|
||||
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("<user> is banned from this room.", "%1 is banned from this room.", text));
|
||||
return QString();
|
||||
}
|
||||
if (room->localMember().id() == text) {
|
||||
if (room->localUser()->id() == text) {
|
||||
Q_EMIT room->showMessage(NeoChatRoom::Positive, i18n("You are already in this room."));
|
||||
return QString();
|
||||
}
|
||||
@@ -430,11 +430,11 @@ QList<ActionsModel::Action> actions{
|
||||
if (!plEvent) {
|
||||
return QString();
|
||||
}
|
||||
if (plEvent->ban() > plEvent->powerLevelForUser(room->localMember().id())) {
|
||||
if (plEvent->ban() > plEvent->powerLevelForUser(room->localUser()->id())) {
|
||||
Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to ban users from this room."));
|
||||
return QString();
|
||||
}
|
||||
if (plEvent->powerLevelForUser(room->localMember().id()) <= plEvent->powerLevelForUser(parts[0])) {
|
||||
if (plEvent->powerLevelForUser(room->localUser()->id()) <= plEvent->powerLevelForUser(parts[0])) {
|
||||
Q_EMIT room->showMessage(
|
||||
NeoChatRoom::Error,
|
||||
i18nc("You are not allowed to ban <username> from this room.", "You are not allowed to ban %1 from this room.", parts[0]));
|
||||
@@ -463,7 +463,7 @@ QList<ActionsModel::Action> actions{
|
||||
if (!plEvent) {
|
||||
return QString();
|
||||
}
|
||||
if (plEvent->ban() > plEvent->powerLevelForUser(room->localMember().id())) {
|
||||
if (plEvent->ban() > plEvent->powerLevelForUser(room->localUser()->id())) {
|
||||
Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to unban users from this room."));
|
||||
return QString();
|
||||
}
|
||||
@@ -494,7 +494,7 @@ QList<ActionsModel::Action> actions{
|
||||
i18nc("'<text>' does not look like a matrix id.", "'%1' does not look like a matrix id.", parts[0]));
|
||||
return QString();
|
||||
}
|
||||
if (parts[0] == room->localMember().id()) {
|
||||
if (parts[0] == room->localUser()->id()) {
|
||||
Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You cannot kick yourself from the room."));
|
||||
return QString();
|
||||
}
|
||||
@@ -507,11 +507,11 @@ QList<ActionsModel::Action> actions{
|
||||
return QString();
|
||||
}
|
||||
auto kick = plEvent->kick();
|
||||
if (plEvent->powerLevelForUser(room->localMember().id()) < kick) {
|
||||
if (plEvent->powerLevelForUser(room->localUser()->id()) < kick) {
|
||||
Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to kick users from this room."));
|
||||
return QString();
|
||||
}
|
||||
if (plEvent->powerLevelForUser(room->localMember().id()) <= plEvent->powerLevelForUser(parts[0])) {
|
||||
if (plEvent->powerLevelForUser(room->localUser()->id()) <= plEvent->powerLevelForUser(parts[0])) {
|
||||
Q_EMIT room->showMessage(
|
||||
NeoChatRoom::Error,
|
||||
i18nc("You are not allowed to kick <username> from this room", "You are not allowed to kick %1 from this room.", parts[0]));
|
||||
|
||||
@@ -208,5 +208,3 @@ void ItineraryModel::sendToItinerary()
|
||||
job->start();
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "moc_itinerarymodel.cpp"
|
||||
|
||||
@@ -62,5 +62,3 @@ void LineModel::resetModel()
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
#include "moc_linemodel.cpp"
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "messagecontentmodel.h"
|
||||
#include "neochatconfig.h"
|
||||
|
||||
#include <QImageReader>
|
||||
|
||||
#include <Quotient/events/redactionevent.h>
|
||||
#include <Quotient/events/roommessageevent.h>
|
||||
#include <Quotient/events/stickerevent.h>
|
||||
#include <Quotient/room.h>
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
@@ -23,12 +23,9 @@
|
||||
#include "filetype.h"
|
||||
#include "itinerarymodel.h"
|
||||
#include "linkpreviewer.h"
|
||||
#include "neochatconnection.h"
|
||||
#include "neochatroom.h"
|
||||
#include "texthandler.h"
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
MessageContentModel::MessageContentModel(const Quotient::RoomEvent *event, NeoChatRoom *room)
|
||||
: QAbstractListModel(nullptr)
|
||||
, m_room(room)
|
||||
@@ -79,21 +76,6 @@ MessageContentModel::MessageContentModel(const Quotient::RoomEvent *event, NeoCh
|
||||
if (m_event != nullptr && eventId == m_event->id()) {
|
||||
updateComponents();
|
||||
Q_EMIT dataChanged(index(0), index(rowCount() - 1), {FileTransferInfoRole});
|
||||
|
||||
QString mxcUrl;
|
||||
if (auto event = eventCast<const Quotient::RoomMessageEvent>(m_event)) {
|
||||
if (event->hasFileContent()) {
|
||||
mxcUrl = event->content()->fileInfo()->url().toString();
|
||||
}
|
||||
} else if (auto event = eventCast<const Quotient::StickerEvent>(m_event)) {
|
||||
mxcUrl = event->image().fileInfo()->url().toString();
|
||||
}
|
||||
if (mxcUrl.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
auto localPath = m_room->fileTransferInfo(m_event->id()).localPath.toLocalFile();
|
||||
auto config = KSharedConfig::openStateConfig(QStringLiteral("neochatdownloads"))->group(QStringLiteral("downloads"));
|
||||
config.writePathEntry(mxcUrl.mid(6), localPath);
|
||||
}
|
||||
});
|
||||
connect(m_room, &NeoChatRoom::fileTransferFailed, this, [this](const QString &eventId) {
|
||||
@@ -110,11 +92,23 @@ MessageContentModel::MessageContentModel(const Quotient::RoomEvent *event, NeoCh
|
||||
endResetModel();
|
||||
}
|
||||
});
|
||||
connect(m_room, &NeoChatRoom::urlPreviewEnabledChanged, this, &MessageContentModel::updateLinkPreviewer);
|
||||
connect(NeoChatConfig::self(), &NeoChatConfig::ShowLinkPreviewChanged, this, &MessageContentModel::updateLinkPreviewer);
|
||||
}
|
||||
|
||||
updateLinkPreviewer();
|
||||
if (const auto event = eventCast<const Quotient::RoomMessageEvent>(m_event)) {
|
||||
if (LinkPreviewer::hasPreviewableLinks(event)) {
|
||||
m_linkPreviewer = new LinkPreviewer(m_room, event, this);
|
||||
|
||||
connect(m_linkPreviewer, &LinkPreviewer::loadedChanged, [this]() {
|
||||
if (m_linkPreviewer->loaded()) {
|
||||
// HACK: Because DelegateChooser can't switch the delegate on dataChanged it has to think there is a new delegate.
|
||||
beginResetModel();
|
||||
m_components[m_components.size() - 1].type = MessageComponentType::LinkPreview;
|
||||
endResetModel();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updateComponents();
|
||||
}
|
||||
|
||||
@@ -161,7 +155,14 @@ QVariant MessageContentModel::data(const QModelIndex &index, int role) const
|
||||
return eventHandler.getMediaInfo();
|
||||
}
|
||||
if (role == FileTransferInfoRole) {
|
||||
return QVariant::fromValue(fileInfo());
|
||||
if (auto event = eventCast<const Quotient::RoomMessageEvent>(m_event)) {
|
||||
if (event->hasFileContent()) {
|
||||
return QVariant::fromValue(m_room->fileTransferInfo(event->id()));
|
||||
}
|
||||
}
|
||||
if (auto event = eventCast<const Quotient::StickerEvent>(m_event)) {
|
||||
return QVariant::fromValue(m_room->fileTransferInfo(event->id()));
|
||||
}
|
||||
}
|
||||
if (role == ItineraryModelRole) {
|
||||
return QVariant::fromValue<ItineraryModel *>(m_itineraryModel);
|
||||
@@ -269,7 +270,15 @@ void MessageContentModel::updateComponents(bool isEditing)
|
||||
} else if (eventHandler.messageComponentType() == MessageComponentType::File) {
|
||||
m_components += MessageComponent{MessageComponentType::File, QString(), {}};
|
||||
if (m_emptyItinerary) {
|
||||
auto fileTransferInfo = fileInfo();
|
||||
Quotient::FileTransferInfo fileTransferInfo;
|
||||
if (auto event = eventCast<const Quotient::RoomMessageEvent>(m_event)) {
|
||||
if (event->hasFileContent()) {
|
||||
fileTransferInfo = m_room->fileTransferInfo(event->id());
|
||||
}
|
||||
}
|
||||
if (auto event = eventCast<const Quotient::StickerEvent>(m_event)) {
|
||||
fileTransferInfo = m_room->fileTransferInfo(event->id());
|
||||
}
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
KSyntaxHighlighting::Repository repository;
|
||||
@@ -310,44 +319,6 @@ void MessageContentModel::updateComponents(bool isEditing)
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void MessageContentModel::updateLinkPreviewer()
|
||||
{
|
||||
if (m_room == nullptr || m_event == nullptr) {
|
||||
if (m_linkPreviewer != nullptr) {
|
||||
m_linkPreviewer->disconnect(this);
|
||||
m_linkPreviewer = nullptr;
|
||||
updateComponents();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!m_room->urlPreviewEnabled()) {
|
||||
if (m_linkPreviewer != nullptr) {
|
||||
m_linkPreviewer->disconnect(this);
|
||||
m_linkPreviewer = nullptr;
|
||||
updateComponents();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto event = eventCast<const Quotient::RoomMessageEvent>(m_event)) {
|
||||
if (LinkPreviewer::hasPreviewableLinks(event)) {
|
||||
m_linkPreviewer = dynamic_cast<NeoChatConnection *>(m_room->connection())->previewerForLink(LinkPreviewer::linkPreview(event));
|
||||
updateComponents();
|
||||
|
||||
if (m_linkPreviewer != nullptr) {
|
||||
connect(m_linkPreviewer, &LinkPreviewer::loadedChanged, [this]() {
|
||||
if (m_linkPreviewer != nullptr && m_linkPreviewer->loaded()) {
|
||||
// HACK: Because DelegateChooser can't switch the delegate on dataChanged it has to think there is a new delegate.
|
||||
beginResetModel();
|
||||
m_components[m_components.size() - 1].type = MessageComponentType::LinkPreview;
|
||||
endResetModel();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageContentModel::updateItineraryModel()
|
||||
{
|
||||
if (m_room == nullptr || m_event == nullptr) {
|
||||
@@ -356,7 +327,7 @@ void MessageContentModel::updateItineraryModel()
|
||||
|
||||
if (auto event = eventCast<const Quotient::RoomMessageEvent>(m_event)) {
|
||||
if (event->hasFileContent()) {
|
||||
auto filePath = fileInfo().localPath;
|
||||
auto filePath = m_room->fileTransferInfo(event->id()).localPath;
|
||||
if (filePath.isEmpty() && m_itineraryModel != nullptr) {
|
||||
delete m_itineraryModel;
|
||||
m_itineraryModel = nullptr;
|
||||
@@ -383,43 +354,3 @@ void MessageContentModel::updateItineraryModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileTransferInfo MessageContentModel::fileInfo() const
|
||||
{
|
||||
if (m_room == nullptr || m_event == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
QString mxcUrl;
|
||||
int total;
|
||||
if (auto event = eventCast<const Quotient::RoomMessageEvent>(m_event)) {
|
||||
if (event->hasFileContent()) {
|
||||
mxcUrl = event->content()->fileInfo()->url().toString();
|
||||
total = event->content()->fileInfo()->payloadSize;
|
||||
}
|
||||
} else if (auto event = eventCast<const Quotient::StickerEvent>(m_event)) {
|
||||
mxcUrl = event->image().fileInfo()->url().toString();
|
||||
total = event->image().fileInfo()->payloadSize;
|
||||
}
|
||||
auto config = KSharedConfig::openStateConfig(QStringLiteral("neochatdownloads"))->group(QStringLiteral("downloads"));
|
||||
if (!config.hasKey(mxcUrl.mid(6))) {
|
||||
return m_room->fileTransferInfo(m_event->id());
|
||||
}
|
||||
const auto path = config.readPathEntry(mxcUrl.mid(6), QString());
|
||||
QFileInfo info(path);
|
||||
if (!info.isFile()) {
|
||||
config.deleteEntry(mxcUrl);
|
||||
return m_room->fileTransferInfo(m_event->id());
|
||||
}
|
||||
// TODO: we could check the hash here
|
||||
return FileTransferInfo{
|
||||
.status = FileTransferInfo::Completed,
|
||||
.isUpload = false,
|
||||
.progress = total,
|
||||
.total = total,
|
||||
.localDir = QUrl(info.dir().path()),
|
||||
.localPath = QUrl::fromLocalFile(path),
|
||||
};
|
||||
}
|
||||
|
||||
#include "moc_messagecontentmodel.cpp"
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#include <QAbstractListModel>
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include <Quotient/room.h>
|
||||
|
||||
#include "enums/messagecomponenttype.h"
|
||||
#include "eventhandler.h"
|
||||
#include "itinerarymodel.h"
|
||||
@@ -95,12 +93,9 @@ private:
|
||||
QList<MessageComponent> m_components;
|
||||
void updateComponents(bool isEditing = false);
|
||||
|
||||
QPointer<LinkPreviewer> m_linkPreviewer;
|
||||
LinkPreviewer *m_linkPreviewer = nullptr;
|
||||
ItineraryModel *m_itineraryModel = nullptr;
|
||||
|
||||
void updateLinkPreviewer();
|
||||
void updateItineraryModel();
|
||||
bool m_emptyItinerary = false;
|
||||
|
||||
Quotient::FileTransferInfo fileInfo() const;
|
||||
};
|
||||
|
||||
@@ -251,7 +251,7 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
});
|
||||
qCDebug(MessageEvent) << "Connected to room" << room->id() << "as" << room->localMember().id();
|
||||
qCDebug(MessageEvent) << "Connected to room" << room->id() << "as" << room->localUser()->id();
|
||||
} else {
|
||||
lastReadEventId.clear();
|
||||
}
|
||||
@@ -621,7 +621,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
||||
}
|
||||
|
||||
if (role == IsEditableRole) {
|
||||
return eventHandler.messageComponentType() == MessageComponentType::Text && evt.senderId() == m_currentRoom->localMember().id();
|
||||
return eventHandler.messageComponentType() == MessageComponentType::Text && evt.senderId() == m_currentRoom->localUser()->id();
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
@@ -162,5 +162,3 @@ QString NotificationsModel::nextToken() const
|
||||
{
|
||||
return m_nextToken;
|
||||
}
|
||||
|
||||
#include "moc_notificationsmodel.cpp"
|
||||
|
||||
@@ -90,7 +90,7 @@ QVariant ReactionModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
if (role == HasLocalUser) {
|
||||
for (auto author : reaction.authors) {
|
||||
if (author.toMap()[QStringLiteral("id")] == m_room->localMember().id()) {
|
||||
if (author.toMap()[QStringLiteral("id")] == m_room->localUser()->id()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "neochatconfig.h"
|
||||
#include "neochatconnection.h"
|
||||
#include "neochatroomtype.h"
|
||||
#include "roommanager.h"
|
||||
#include "roomtreemodel.h"
|
||||
#include "spacehierarchycache.h"
|
||||
|
||||
@@ -33,12 +32,6 @@ SortFilterRoomTreeModel::SortFilterRoomTreeModel(RoomTreeModel *sourceModel, QOb
|
||||
});
|
||||
|
||||
connect(NeoChatConfig::self(), &NeoChatConfig::CollapsedChanged, this, &SortFilterRoomTreeModel::invalidateFilter);
|
||||
connect(NeoChatConfig::self(), &NeoChatConfig::AllRoomsInHomeChanged, this, [this]() {
|
||||
invalidateFilter();
|
||||
if (NeoChatConfig::self()->allRoomsInHome()) {
|
||||
RoomManager::instance().resetState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SortFilterRoomTreeModel::setRoomSortOrder(SortFilterRoomTreeModel::RoomSortOrder sortOrder)
|
||||
@@ -161,11 +154,6 @@ bool SortFilterRoomTreeModel::filterAcceptsRow(int source_row, const QModelIndex
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto config = NeoChatConfig::self();
|
||||
if (config->allRoomsInHome() && RoomManager::instance().currentSpace().isEmpty()) {
|
||||
return acceptRoom;
|
||||
}
|
||||
|
||||
if (m_activeSpaceId.isEmpty()) {
|
||||
if (!SpaceHierarchyCache::instance().isChild(sourceModel()->data(index, RoomTreeModel::RoomIdRole).toString())) {
|
||||
return acceptRoom;
|
||||
|
||||
@@ -95,11 +95,7 @@ void SpaceChildrenModel::refreshModel()
|
||||
});
|
||||
}
|
||||
|
||||
#if Quotient_VERSION_MINOR >= 9
|
||||
void SpaceChildrenModel::insertChildren(std::vector<Quotient::GetSpaceHierarchyJob::SpaceHierarchyRoomsChunk> children, const QModelIndex &parent)
|
||||
#else
|
||||
void SpaceChildrenModel::insertChildren(std::vector<Quotient::GetSpaceHierarchyJob::ChildRoomsChunk> children, const QModelIndex &parent)
|
||||
#endif
|
||||
{
|
||||
SpaceTreeItem *parentItem = getItem(parent);
|
||||
|
||||
|
||||
@@ -143,10 +143,5 @@ private:
|
||||
SpaceTreeItem *getItem(const QModelIndex &index) const;
|
||||
|
||||
void refreshModel();
|
||||
|
||||
#if Quotient_VERSION_MINOR >= 9
|
||||
void insertChildren(std::vector<Quotient::GetSpaceHierarchyJob::SpaceHierarchyRoomsChunk> children, const QModelIndex &parent = QModelIndex());
|
||||
#else
|
||||
void insertChildren(std::vector<Quotient::GetSpaceHierarchyJob::ChildRoomsChunk> children, const QModelIndex &parent = QModelIndex());
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -77,14 +77,12 @@ void StateKeysModel::setEventType(const QString &eventType)
|
||||
loadState();
|
||||
}
|
||||
|
||||
QByteArray StateKeysModel::stateEventJson(const QString &type, const QString &stateKey)
|
||||
QByteArray StateKeysModel::stateEventJson(const QModelIndex &index)
|
||||
{
|
||||
return QJsonDocument(m_room->currentState().get(type, stateKey)->fullJson()).toJson();
|
||||
}
|
||||
|
||||
QByteArray StateKeysModel::stateEventContentJson(const QString &type, const QString &stateKey)
|
||||
{
|
||||
return QJsonDocument(m_room->currentState().get(type, stateKey)->contentJson()).toJson();
|
||||
const auto row = index.row();
|
||||
const auto event = m_stateKeys[row];
|
||||
const auto json = event->fullJson();
|
||||
return QJsonDocument(json).toJson();
|
||||
}
|
||||
|
||||
#include "moc_statekeysmodel.cpp"
|
||||
|
||||
@@ -69,12 +69,7 @@ public:
|
||||
/**
|
||||
* @brief Get the full JSON for an event.
|
||||
*/
|
||||
Q_INVOKABLE QByteArray stateEventJson(const QString &type, const QString &stateKey);
|
||||
|
||||
/**
|
||||
* @brief Get the content JSON for an event.
|
||||
*/
|
||||
Q_INVOKABLE QByteArray stateEventContentJson(const QString &type, const QString &stateKey);
|
||||
Q_INVOKABLE QByteArray stateEventJson(const QModelIndex &index);
|
||||
|
||||
Q_SIGNALS:
|
||||
void roomChanged();
|
||||
|
||||
@@ -10,11 +10,7 @@ StateModel::StateModel(QObject *parent)
|
||||
|
||||
QHash<int, QByteArray> StateModel::roleNames() const
|
||||
{
|
||||
return {
|
||||
{TypeRole, "type"},
|
||||
{EventCountRole, "eventCount"},
|
||||
{StateKeyRole, "stateKey"},
|
||||
};
|
||||
return {{TypeRole, "type"}, {EventCountRole, "eventCount"}};
|
||||
}
|
||||
QVariant StateModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
@@ -24,8 +20,6 @@ QVariant StateModel::data(const QModelIndex &index, int role) const
|
||||
return m_stateEvents.keys()[row];
|
||||
case EventCountRole:
|
||||
return m_stateEvents.values()[row].count();
|
||||
case StateKeyRole:
|
||||
return m_stateEvents.values()[row][0];
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -69,14 +63,14 @@ void StateModel::setRoom(NeoChatRoom *room)
|
||||
});
|
||||
}
|
||||
|
||||
QByteArray StateModel::stateEventJson(const QString &type, const QString &stateKey)
|
||||
QByteArray StateModel::stateEventJson(const QModelIndex &index)
|
||||
{
|
||||
return QJsonDocument(m_room->currentState().get(type, stateKey)->fullJson()).toJson();
|
||||
}
|
||||
auto row = index.row();
|
||||
const auto type = m_stateEvents.keys()[row];
|
||||
const auto stateKey = m_stateEvents.values()[row][0];
|
||||
const auto event = m_room->currentState().get(type, stateKey);
|
||||
|
||||
QByteArray StateModel::stateEventContentJson(const QString &type, const QString &stateKey)
|
||||
{
|
||||
return QJsonDocument(m_room->currentState().get(type, stateKey)->contentJson()).toJson();
|
||||
return QJsonDocument(event->fullJson()).toJson();
|
||||
}
|
||||
|
||||
#include "moc_statemodel.cpp"
|
||||
|
||||
@@ -30,7 +30,6 @@ public:
|
||||
enum Roles {
|
||||
TypeRole = 0, /**< The type of the state event. */
|
||||
EventCountRole, /**< Number of events of this type. */
|
||||
StateKeyRole, /**<State key. Only valid if there's exactly one event of this type. */
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
@@ -63,12 +62,7 @@ public:
|
||||
/**
|
||||
* @brief Get the full JSON for an event.
|
||||
*/
|
||||
Q_INVOKABLE QByteArray stateEventJson(const QString &type, const QString &stateKey);
|
||||
|
||||
/**
|
||||
* @brief Get the content JSON for an event.
|
||||
*/
|
||||
Q_INVOKABLE QByteArray stateEventContentJson(const QString &type, const QString &stateKey);
|
||||
Q_INVOKABLE QByteArray stateEventJson(const QModelIndex &index);
|
||||
|
||||
Q_SIGNALS:
|
||||
void roomChanged();
|
||||
@@ -77,7 +71,7 @@ private:
|
||||
QPointer<NeoChatRoom> m_room;
|
||||
|
||||
/**
|
||||
* @brief A map from state event type to state keys
|
||||
* @brief A map from state event type to number of events of that type
|
||||
*/
|
||||
QMap<QString, QList<QString>> m_stateEvents;
|
||||
void loadState();
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "threepidmodel.h"
|
||||
|
||||
#include "neochatconnection.h"
|
||||
|
||||
ThreePIdModel::ThreePIdModel(NeoChatConnection *connection)
|
||||
: QAbstractListModel(connection)
|
||||
{
|
||||
Q_ASSERT(connection);
|
||||
connect(connection, &NeoChatConnection::stateChanged, this, [this]() {
|
||||
const auto connection = dynamic_cast<NeoChatConnection *>(this->parent());
|
||||
if (connection != nullptr && connection->isLoggedIn()) {
|
||||
const auto threePIdJob = connection->callApi<Quotient::GetAccount3PIDsJob>();
|
||||
connect(threePIdJob, &Quotient::BaseJob::success, this, [this, threePIdJob]() {
|
||||
beginResetModel();
|
||||
m_threePIds = threePIdJob->threepids();
|
||||
endResetModel();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QVariant ThreePIdModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return {};
|
||||
}
|
||||
if (index.row() >= rowCount()) {
|
||||
qDebug() << "ThreePIdModel, something's wrong: index.row() >= m_threePIds.count()";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (role == AddressRole) {
|
||||
return m_threePIds.at(index.row()).address;
|
||||
}
|
||||
if (role == MediumRole) {
|
||||
return m_threePIds.at(index.row()).medium;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int ThreePIdModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_threePIds.count();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ThreePIdModel::roleNames() const
|
||||
{
|
||||
return {
|
||||
{AddressRole, QByteArrayLiteral("address")},
|
||||
{MediumRole, QByteArrayLiteral("medium")},
|
||||
};
|
||||
}
|
||||
|
||||
#include "moc_threepidmodel.cpp"
|
||||
@@ -1,58 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2024 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 once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include <Quotient/csapi/administrative_contact.h>
|
||||
|
||||
class NeoChatConnection;
|
||||
|
||||
/**
|
||||
* @class ThreePIdModel
|
||||
*
|
||||
* This class defines the model for visualising an account's 3PIDs.
|
||||
*/
|
||||
class ThreePIdModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("")
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Defines the model roles.
|
||||
*/
|
||||
enum EventRoles {
|
||||
AddressRole = Qt::DisplayRole, /**< The third-party identifier address. */
|
||||
MediumRole, /**< The medium of the third-party identifier. One of: [email, msisdn]. */
|
||||
};
|
||||
|
||||
explicit ThreePIdModel(NeoChatConnection *parent);
|
||||
|
||||
/**
|
||||
* @brief Get the given role value at the given index.
|
||||
*
|
||||
* @sa QAbstractItemModel::data
|
||||
*/
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
/**
|
||||
* @brief Number of rows in the model.
|
||||
*
|
||||
* @sa QAbstractItemModel::rowCount
|
||||
*/
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
/**
|
||||
* @brief Returns a mapping from Role enum values to role names.
|
||||
*
|
||||
* @sa EventRoles, QAbstractItemModel::roleNames()
|
||||
*/
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
QVector<Quotient::GetAccount3PIDsJob::ThirdPartyIdentifier> m_threePIds;
|
||||
};
|
||||
@@ -93,5 +93,3 @@ QHash<int, QByteArray> TimelineEndModel::roleNames() const
|
||||
{
|
||||
return {{DelegateTypeRole, "delegateType"}};
|
||||
}
|
||||
|
||||
#include "moc_timelinemodel.cpp"
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="neochatrc" />
|
||||
<group name="General">
|
||||
<entry name="AllRoomsInHome" type="bool">
|
||||
<label>Show all rooms in the home tab</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="CollapsedSections" type="IntList">
|
||||
<label>Collapsed sections in the room list</label>
|
||||
</entry>
|
||||
@@ -160,12 +156,6 @@
|
||||
<default></default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Debug">
|
||||
<entry name="AlwaysVerifyDevice" type="bool">
|
||||
<label>Always allow device verification</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="FeatureFlags">
|
||||
<entry name="Threads" type="bool">
|
||||
<label>Enable threads</label>
|
||||
|
||||
@@ -9,14 +9,11 @@
|
||||
#include "controller.h"
|
||||
#include "jobs/neochatchangepasswordjob.h"
|
||||
#include "jobs/neochatdeactivateaccountjob.h"
|
||||
#include "linkpreviewer.h"
|
||||
#include "neochatconfig.h"
|
||||
#include "neochatroom.h"
|
||||
#include "roommanager.h"
|
||||
#include "spacehierarchycache.h"
|
||||
|
||||
#include <Quotient/connection.h>
|
||||
#include <Quotient/jobs/basejob.h>
|
||||
#include <Quotient/quotient_common.h>
|
||||
#include <qt6keychain/keychain.h>
|
||||
|
||||
@@ -42,14 +39,12 @@ using namespace Qt::StringLiterals;
|
||||
|
||||
NeoChatConnection::NeoChatConnection(QObject *parent)
|
||||
: Connection(parent)
|
||||
, m_threePIdModel(new ThreePIdModel(this))
|
||||
{
|
||||
connectSignals();
|
||||
}
|
||||
|
||||
NeoChatConnection::NeoChatConnection(const QUrl &server, QObject *parent)
|
||||
: Connection(server, parent)
|
||||
, m_threePIdModel(new ThreePIdModel(this))
|
||||
{
|
||||
connectSignals();
|
||||
}
|
||||
@@ -251,11 +246,6 @@ void NeoChatConnection::deactivateAccount(const QString &password)
|
||||
});
|
||||
}
|
||||
|
||||
ThreePIdModel *NeoChatConnection::threePIdModel() const
|
||||
{
|
||||
return m_threePIdModel;
|
||||
}
|
||||
|
||||
void NeoChatConnection::createRoom(const QString &name, const QString &topic, const QString &parent, bool setChildParent)
|
||||
{
|
||||
QList<CreateRoomJob::StateEvent> initialStateEvents;
|
||||
@@ -487,20 +477,4 @@ QString NeoChatConnection::accountDataJsonString(const QString &type) const
|
||||
return QString::fromUtf8(QJsonDocument(accountDataJson(type)).toJson());
|
||||
}
|
||||
|
||||
LinkPreviewer *NeoChatConnection::previewerForLink(const QUrl &link)
|
||||
{
|
||||
if (!NeoChatConfig::showLinkPreview()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto previewer = m_linkPreviewers.value(link, nullptr);
|
||||
if (previewer != nullptr) {
|
||||
return previewer;
|
||||
}
|
||||
|
||||
previewer = new LinkPreviewer(link, this);
|
||||
m_linkPreviewers[link] = previewer;
|
||||
return previewer;
|
||||
}
|
||||
|
||||
#include "moc_neochatconnection.cpp"
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
#include <QCoroTask>
|
||||
#include <Quotient/connection.h>
|
||||
|
||||
#include "models/threepidmodel.h"
|
||||
|
||||
class LinkPreviewer;
|
||||
|
||||
class NeoChatConnection : public Quotient::Connection
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -31,11 +27,6 @@ class NeoChatConnection : public Quotient::Connection
|
||||
Q_PROPERTY(QString deviceKey READ deviceKey CONSTANT)
|
||||
Q_PROPERTY(QString encryptionKey READ encryptionKey CONSTANT)
|
||||
|
||||
/**
|
||||
* @brief The model with the account's 3PIDs.
|
||||
*/
|
||||
Q_PROPERTY(ThreePIdModel *threePIdModel READ threePIdModel CONSTANT)
|
||||
|
||||
/**
|
||||
* @brief The total number of notifications for all direct chats.
|
||||
*/
|
||||
@@ -103,8 +94,6 @@ public:
|
||||
|
||||
Q_INVOKABLE void deactivateAccount(const QString &password);
|
||||
|
||||
ThreePIdModel *threePIdModel() const;
|
||||
|
||||
/**
|
||||
* @brief Create new room for a group chat.
|
||||
*/
|
||||
@@ -158,8 +147,6 @@ public:
|
||||
|
||||
bool isOnline() const;
|
||||
|
||||
LinkPreviewer *previewerForLink(const QUrl &link);
|
||||
|
||||
Q_SIGNALS:
|
||||
void labelChanged();
|
||||
void directChatNotificationsChanged();
|
||||
@@ -176,11 +163,7 @@ private:
|
||||
bool m_isOnline = true;
|
||||
void setIsOnline(bool isOnline);
|
||||
|
||||
ThreePIdModel *m_threePIdModel;
|
||||
|
||||
void connectSignals();
|
||||
|
||||
int m_badgeNotificationCount = 0;
|
||||
|
||||
QHash<QUrl, LinkPreviewer *> m_linkPreviewers;
|
||||
};
|
||||
|
||||
@@ -101,17 +101,15 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
|
||||
if (this->joinState() != JoinState::Invite) {
|
||||
return;
|
||||
}
|
||||
auto roomMemberEvent = currentState().get<RoomMemberEvent>(localMember().id());
|
||||
auto roomMemberEvent = currentState().get<RoomMemberEvent>(localUser()->id());
|
||||
QImage avatar_image;
|
||||
if (roomMemberEvent && !member(roomMemberEvent->senderId()).avatarUrl().isEmpty()) {
|
||||
// TODO: Fix acessing Avatar Image.
|
||||
// avatar_image = member(roomMemberEvent->senderId()).avatarMediaId();
|
||||
avatar_image = avatar(128);
|
||||
if (roomMemberEvent && !user(roomMemberEvent->senderId())->avatarUrl(this).isEmpty()) {
|
||||
avatar_image = user(roomMemberEvent->senderId())->avatar(128, this);
|
||||
} else {
|
||||
qWarning() << "using this room's avatar";
|
||||
avatar_image = avatar(128);
|
||||
}
|
||||
NotificationsManager::instance().postInviteNotification(this, displayName(), member(roomMemberEvent->senderId()).htmlSafeDisplayName(), avatar_image);
|
||||
NotificationsManager::instance().postInviteNotification(this, displayName(), htmlSafeMemberName(roomMemberEvent->senderId()), avatar_image);
|
||||
});
|
||||
connect(this, &Room::changed, this, [this] {
|
||||
Q_EMIT canEncryptRoomChanged();
|
||||
@@ -259,18 +257,18 @@ void NeoChatRoom::forget()
|
||||
|
||||
QVariantList NeoChatRoom::getUsersTyping() const
|
||||
{
|
||||
auto users = membersTyping();
|
||||
users.removeAll(localMember());
|
||||
auto users = usersTyping();
|
||||
users.removeAll(localUser());
|
||||
QVariantList userVariants;
|
||||
for (const auto &user : users) {
|
||||
if (connection()->isIgnored(user.id())) {
|
||||
if (connection()->isIgnored(user->id())) {
|
||||
continue;
|
||||
}
|
||||
userVariants.append(QVariantMap{
|
||||
{"id"_ls, user.id()},
|
||||
{"avatarMediaId"_ls, user.avatarMediaId()},
|
||||
{"displayName"_ls, user.displayName()},
|
||||
{"display"_ls, user.name()},
|
||||
{"id"_ls, user->id()},
|
||||
{"avatarMediaId"_ls, user->avatarMediaId(this)},
|
||||
{"displayName"_ls, user->displayname(this)},
|
||||
{"display"_ls, user->name()},
|
||||
});
|
||||
}
|
||||
return userVariants;
|
||||
@@ -278,7 +276,7 @@ QVariantList NeoChatRoom::getUsersTyping() const
|
||||
|
||||
void NeoChatRoom::sendTypingNotification(bool isTyping)
|
||||
{
|
||||
connection()->callApi<SetTypingJob>(BackgroundRequest, localMember().id(), id(), isTyping, 10000);
|
||||
connection()->callApi<SetTypingJob>(BackgroundRequest, localUser()->id(), id(), isTyping, 10000);
|
||||
}
|
||||
|
||||
const RoomEvent *NeoChatRoom::lastEvent() const
|
||||
@@ -316,7 +314,7 @@ const RoomEvent *NeoChatRoom::lastEvent() const
|
||||
}
|
||||
}
|
||||
|
||||
if (connection()->isIgnored(event->senderId())) {
|
||||
if (connection()->isIgnored(user(event->senderId()))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -376,13 +374,13 @@ bool NeoChatRoom::isEventHighlighted(const RoomEvent *e) const
|
||||
|
||||
void NeoChatRoom::checkForHighlights(const Quotient::TimelineItem &ti)
|
||||
{
|
||||
auto localMemberId = localMember().id();
|
||||
if (ti->senderId() == localMemberId) {
|
||||
auto localUserId = localUser()->id();
|
||||
if (ti->senderId() == localUserId) {
|
||||
return;
|
||||
}
|
||||
if (auto *e = ti.viewAs<RoomMessageEvent>()) {
|
||||
const auto &text = e->plainBody();
|
||||
if (text.contains(localMemberId) || text.contains(member(localMemberId).htmlSafeDisplayName())) {
|
||||
if (text.contains(localUserId) || text.contains(safeMemberName(localUserId))) {
|
||||
highlights.insert(e);
|
||||
}
|
||||
}
|
||||
@@ -441,8 +439,7 @@ static const QVariantMap emptyUser = {
|
||||
|
||||
QVariantMap NeoChatRoom::getUser(const QString &userID) const
|
||||
{
|
||||
auto u = User(userID, connection());
|
||||
return getUser(&u);
|
||||
return getUser(user(userID));
|
||||
}
|
||||
|
||||
QVariantMap NeoChatRoom::getUser(User *user) const
|
||||
@@ -452,13 +449,13 @@ QVariantMap NeoChatRoom::getUser(User *user) const
|
||||
}
|
||||
|
||||
return QVariantMap{
|
||||
{QStringLiteral("isLocalUser"), user->id() == localMember().id()},
|
||||
{QStringLiteral("isLocalUser"), user->id() == localUser()->id()},
|
||||
{QStringLiteral("id"), user->id()},
|
||||
{QStringLiteral("displayName"), user->displayname()},
|
||||
{QStringLiteral("escapedDisplayName"), member(user->id()).htmlSafeDisplayName()},
|
||||
{QStringLiteral("displayName"), user->displayname(this)},
|
||||
{QStringLiteral("escapedDisplayName"), htmlSafeMemberName(user->id())},
|
||||
{QStringLiteral("avatarSource"), avatarForMember(user)},
|
||||
{QStringLiteral("avatarMediaId"), user->avatarMediaId()},
|
||||
{QStringLiteral("color"), member(user->id()).hueF()},
|
||||
{QStringLiteral("avatarMediaId"), user->avatarMediaId(this)},
|
||||
{QStringLiteral("color"), Utils::getUserColor(user->hueF())},
|
||||
{QStringLiteral("object"), QVariant::fromValue(user)},
|
||||
};
|
||||
}
|
||||
@@ -470,10 +467,10 @@ QString NeoChatRoom::avatarMediaId() const
|
||||
}
|
||||
|
||||
// Use the first (excluding self) user's avatar for direct chats
|
||||
const auto dcUsers = directChatMembers();
|
||||
const auto dcUsers = directChatUsers();
|
||||
for (const auto u : dcUsers) {
|
||||
if (u != localMember()) {
|
||||
return u.avatarMediaId();
|
||||
if (u != localUser()) {
|
||||
return u->avatarMediaId(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,7 +637,7 @@ void NeoChatRoom::toggleReaction(const QString &eventId, const QString &reaction
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->senderId() == localMember().id()) {
|
||||
if (e->senderId() == localUser()->id()) {
|
||||
redactEventIds.push_back(e->id());
|
||||
break;
|
||||
}
|
||||
@@ -669,7 +666,7 @@ bool NeoChatRoom::canSendEvent(const QString &eventType) const
|
||||
return false;
|
||||
}
|
||||
auto pl = plEvent->powerLevelForEvent(eventType);
|
||||
auto currentPl = plEvent->powerLevelForUser(localMember().id());
|
||||
auto currentPl = plEvent->powerLevelForUser(localUser()->id());
|
||||
|
||||
return currentPl >= pl;
|
||||
}
|
||||
@@ -681,7 +678,7 @@ bool NeoChatRoom::canSendState(const QString &eventType) const
|
||||
return false;
|
||||
}
|
||||
auto pl = plEvent->powerLevelForState(eventType);
|
||||
auto currentPl = plEvent->powerLevelForUser(localMember().id());
|
||||
auto currentPl = plEvent->powerLevelForUser(localUser()->id());
|
||||
|
||||
return currentPl >= pl;
|
||||
}
|
||||
@@ -859,7 +856,7 @@ void NeoChatRoom::setUrlPreviewEnabled(const bool &urlPreviewEnabled)
|
||||
* "type": "org.matrix.room.preview_urls",
|
||||
* }
|
||||
*/
|
||||
connection()->callApi<SetAccountDataPerRoomJob>(localMember().id(),
|
||||
connection()->callApi<SetAccountDataPerRoomJob>(localUser()->id(),
|
||||
id(),
|
||||
"org.matrix.room.preview_urls"_ls,
|
||||
QJsonObject{{"disable"_ls, !urlPreviewEnabled}});
|
||||
@@ -1771,7 +1768,7 @@ void NeoChatRoom::editLastMessage()
|
||||
}
|
||||
|
||||
// check if the current message's sender's id is same as the user's id
|
||||
if ((*it)->senderId() == localMember().id()) {
|
||||
if ((*it)->senderId() == localUser()->id()) {
|
||||
auto content = (*it)->contentJson();
|
||||
|
||||
if (e->msgtype() != MessageEventType::Unknown) {
|
||||
@@ -1936,16 +1933,16 @@ QByteArray NeoChatRoom::roomAcountDataJson(const QString &eventType)
|
||||
|
||||
QUrl NeoChatRoom::avatarForMember(Quotient::User *user) const
|
||||
{
|
||||
const auto &avatar = memberAvatar(user->id());
|
||||
if (avatar.url().isEmpty() || avatar.url().scheme() != "mxc"_ls) {
|
||||
const auto &url = memberAvatarUrl(user->id());
|
||||
if (url.isEmpty() || url.scheme() != "mxc"_ls) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto localFile = connection()->makeMediaUrl(avatar.url());
|
||||
if (!localFile.isValid() || localFile.scheme() != QStringLiteral("mxc")) {
|
||||
auto avatar = connection()->makeMediaUrl(url);
|
||||
if (avatar.isValid() && avatar.scheme() == QStringLiteral("mxc")) {
|
||||
return avatar;
|
||||
} else {
|
||||
return QUrl();
|
||||
}
|
||||
return localFile;
|
||||
}
|
||||
|
||||
const RoomEvent *NeoChatRoom::getReplyForEvent(const RoomEvent &event) const
|
||||
@@ -1982,9 +1979,4 @@ User *NeoChatRoom::invitingUser() const
|
||||
return connection()->user(currentState().get<RoomMemberEvent>(connection()->userId())->senderId());
|
||||
}
|
||||
|
||||
void NeoChatRoom::setRoomState(const QString &type, const QString &stateKey, const QByteArray &content)
|
||||
{
|
||||
setState(type, stateKey, QJsonDocument::fromJson(content).object());
|
||||
}
|
||||
|
||||
#include "moc_neochatroom.cpp"
|
||||
|
||||
@@ -659,8 +659,6 @@ public:
|
||||
* */
|
||||
Q_INVOKABLE void setCanonicalAlias(const QString &newAlias);
|
||||
|
||||
Q_INVOKABLE void setRoomState(const QString &type, const QString &stateKey, const QByteArray &content);
|
||||
|
||||
PushNotificationState::State pushNotificationState() const;
|
||||
void setPushNotificationState(PushNotificationState::State state);
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ void NotificationsManager::postNotification(NeoChatRoom *room,
|
||||
if (!room) {
|
||||
return;
|
||||
}
|
||||
auto connection = dynamic_cast<NeoChatConnection *>(Controller::instance().accounts().get(room->localMember().id()));
|
||||
auto connection = dynamic_cast<NeoChatConnection *>(Controller::instance().accounts().get(room->localUser()->id()));
|
||||
Controller::instance().setActiveConnection(connection);
|
||||
RoomManager::instance().setConnection(connection);
|
||||
RoomManager::instance().resolveResource(room->id());
|
||||
@@ -230,7 +230,7 @@ void NotificationsManager::postNotification(NeoChatRoom *room,
|
||||
notification->setReplyAction(std::move(replyAction));
|
||||
}
|
||||
|
||||
notification->setHint(QStringLiteral("x-kde-origin-name"), room->localMember().id());
|
||||
notification->setHint(QStringLiteral("x-kde-origin-name"), room->localUser()->id());
|
||||
notification->sendEvent();
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ void NotificationsManager::postInviteNotification(NeoChatRoom *rawRoom, const QS
|
||||
m_invitations.remove(room->id());
|
||||
});
|
||||
|
||||
notification->setHint(QStringLiteral("x-kde-origin-name"), room->localMember().id());
|
||||
notification->setHint(QStringLiteral("x-kde-origin-name"), room->localUser()->id());
|
||||
|
||||
notification->sendEvent();
|
||||
m_invitations.insert(room->id(), notification);
|
||||
|
||||
@@ -154,7 +154,7 @@ void PollHandler::sendPollAnswer(const QString &eventId, const QString &answerId
|
||||
return;
|
||||
}
|
||||
QStringList ownAnswers;
|
||||
for (const auto &answer : m_answers[room->localMember().id()].toArray()) {
|
||||
for (const auto &answer : m_answers[room->localUser()->id()].toArray()) {
|
||||
ownAnswers += answer.toString();
|
||||
}
|
||||
if (ownAnswers.contains(answerId)) {
|
||||
@@ -169,7 +169,7 @@ void PollHandler::sendPollAnswer(const QString &eventId, const QString &answerId
|
||||
}
|
||||
|
||||
auto response = new PollResponseEvent(eventId, ownAnswers);
|
||||
handleAnswer(response->contentJson(), room->localMember().id(), QDateTime::currentDateTime());
|
||||
handleAnswer(response->contentJson(), room->localUser()->id(), QDateTime::currentDateTime());
|
||||
room->postEvent(response);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,5 +33,3 @@ ProxyController::ProxyController(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
#include "moc_proxycontroller.cpp"
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.kde.kirigami as Kirigami
|
||||
import org.kde.neochat
|
||||
import org.kde.neochat.settings
|
||||
import org.kde.neochat.devtools
|
||||
import org.kde.neochat.config
|
||||
|
||||
QQC2.Menu {
|
||||
id: root
|
||||
@@ -21,7 +22,7 @@ QQC2.Menu {
|
||||
QQC2.MenuItem {
|
||||
text: i18n("Edit this account")
|
||||
icon.name: "document-edit"
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.settings', 'AccountEditorPage'), {
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.settings', 'AccountEditorPage.qml'), {
|
||||
connection: root.connection
|
||||
}, {
|
||||
title: i18n("Account editor")
|
||||
@@ -30,7 +31,7 @@ QQC2.Menu {
|
||||
QQC2.MenuItem {
|
||||
text: i18n("Notification settings")
|
||||
icon.name: "notifications"
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.settings', 'NeoChatSettings'), {
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.settings', 'NeoChatSettings.qml'), {
|
||||
defaultPage: "notifications",
|
||||
connection: root.connection
|
||||
}, {
|
||||
@@ -42,7 +43,7 @@ QQC2.Menu {
|
||||
QQC2.MenuItem {
|
||||
text: i18n("Devices")
|
||||
icon.name: "computer-symbolic"
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.settings', 'NeoChatSettings'), {
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.settings', 'NeoChatSettings.qml'), {
|
||||
defaultPage: "devices",
|
||||
connection: root.connection
|
||||
}, {
|
||||
@@ -55,7 +56,7 @@ QQC2.Menu {
|
||||
text: i18n("Open developer tools")
|
||||
icon.name: "tools"
|
||||
visible: Config.developerTools
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.devtools', 'DevtoolsPage'), {
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.devtools', 'DevtoolsPage.qml'), {
|
||||
connection: root.connection
|
||||
}, {
|
||||
title: i18nc("@title:window", "Developer Tools"),
|
||||
@@ -67,7 +68,7 @@ QQC2.Menu {
|
||||
text: i18nc("@action:inmenu", "Open Secret Backup")
|
||||
icon.name: "unlock"
|
||||
visible: Config.secretBackup
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'UnlockSSSSDialog'), {}, {
|
||||
onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'UnlockSSSSDialog.qml'), {}, {
|
||||
title: i18nc("@title:window", "Open Key Backup")
|
||||
})
|
||||
enabled: Controller.ssssSupported
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user