Compare commits
97 Commits
v23.01.0
...
work/nico/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94210a7ce7 | ||
|
|
280d90e191 | ||
|
|
b4b24430a1 | ||
|
|
b7b7f1817a | ||
|
|
3d67a682f4 | ||
|
|
da6df18367 | ||
|
|
0b1b1b8c8c | ||
|
|
2493a00ba4 | ||
|
|
d6ebb1308c | ||
|
|
332c311023 | ||
|
|
27d33d121a | ||
|
|
e954fc204f | ||
|
|
d1f7e7091e | ||
|
|
bd4eeb405b | ||
|
|
e6a060c192 | ||
|
|
f53a7a27f6 | ||
|
|
34384dced4 | ||
|
|
b68cfafab2 | ||
|
|
58b836fd1e | ||
|
|
90cad05bae | ||
|
|
072f7cec37 | ||
|
|
39388e204e | ||
|
|
6ccb201110 | ||
|
|
178b516c7c | ||
|
|
ac88e13e58 | ||
|
|
8d3e145e0b | ||
|
|
f40d1b9f4e | ||
|
|
e9cd165457 | ||
|
|
c0c86c67b6 | ||
|
|
12afa43d23 | ||
|
|
386f637b94 | ||
|
|
d7bd9f4609 | ||
|
|
33c9edc9a3 | ||
|
|
3b2dbc731e | ||
|
|
51a29ac528 | ||
|
|
cc8bf79a9b | ||
|
|
8d47e58861 | ||
|
|
47ce8a4846 | ||
|
|
71c9537c61 | ||
|
|
8825e6ec83 | ||
|
|
44ec93f0a0 | ||
|
|
ed7688e66f | ||
|
|
6b49854b12 | ||
|
|
e8484ebc7a | ||
|
|
17d01c68c4 | ||
|
|
dae2cbab90 | ||
|
|
b8e8fa3ee5 | ||
|
|
9c4a925171 | ||
|
|
8996806b05 | ||
|
|
2bd4579c10 | ||
|
|
0891f32c08 | ||
|
|
5287c2d529 | ||
|
|
084b89f3dc | ||
|
|
2dd3197beb | ||
|
|
6d9dca7da8 | ||
|
|
e0f16054fc | ||
|
|
fa70679439 | ||
|
|
949bd20873 | ||
|
|
79a9eb0de0 | ||
|
|
e1b9bc7d0e | ||
|
|
a1abf22174 | ||
|
|
fa27d993e2 | ||
|
|
d4b750433e | ||
|
|
9df534c72c | ||
|
|
f785e4d5b0 | ||
|
|
f186be7314 | ||
|
|
3cbcc2b597 | ||
|
|
61f3d6c9ae | ||
|
|
d8b2436f0d | ||
|
|
ea76edce74 | ||
|
|
5482aad7ba | ||
|
|
aaa26571d1 | ||
|
|
554e3576fd | ||
|
|
8d2c7ff8c2 | ||
|
|
92261eb94f | ||
|
|
4dfb7fc3e2 | ||
|
|
2728446692 | ||
|
|
dfb32fe687 | ||
|
|
55507112a9 | ||
|
|
d9aa77a9f4 | ||
|
|
c0ea52c331 | ||
|
|
f1b9d2329f | ||
|
|
0707fd8189 | ||
|
|
6bef2205db | ||
|
|
ace62b4df1 | ||
|
|
d76e512785 | ||
|
|
db2692c411 | ||
|
|
4c9bdd03ce | ||
|
|
efa2c012a7 | ||
|
|
072dc1b6a3 | ||
|
|
4066427168 | ||
|
|
b901c1bdf2 | ||
|
|
532310d739 | ||
|
|
4f7d32df2b | ||
|
|
833d2159e7 | ||
|
|
ccf8701395 | ||
|
|
5d696aabc4 |
@@ -2,7 +2,7 @@
|
|||||||
"id": "org.kde.neochat",
|
"id": "org.kde.neochat",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"runtime": "org.kde.Platform",
|
"runtime": "org.kde.Platform",
|
||||||
"runtime-version": "5.15-21.08",
|
"runtime-version": "5.15-22.08",
|
||||||
"sdk": "org.kde.Sdk",
|
"sdk": "org.kde.Sdk",
|
||||||
"command": "neochat",
|
"command": "neochat",
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
include:
|
include:
|
||||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/reuse-lint.yml
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/reuse-lint.yml
|
||||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android.yml
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android.yml
|
||||||
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android-qt6.yml
|
||||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
|
||||||
# TODO enable once we can have qt6 libQuotient on the CI
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
|
||||||
# - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
|
|
||||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
|
||||||
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows-qt6.yml
|
||||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
|
||||||
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd-qt6.yml
|
||||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/flatpak.yml
|
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/flatpak.yml
|
||||||
|
|||||||
37
.kde-ci.yml
37
.kde-ci.yml
@@ -1,8 +1,8 @@
|
|||||||
# SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
# SPDX-FileCopyrightText: 2021 Tobias Fella <tobias.fella@kde.org>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
Dependencies:
|
Dependencies:
|
||||||
- 'on': ['@all']
|
- 'on': ['Linux/Qt5', 'Android/Qt5', 'FreeBSD/Qt5', 'Windows/Qt5']
|
||||||
'require':
|
'require':
|
||||||
'frameworks/extra-cmake-modules': '@stable'
|
'frameworks/extra-cmake-modules': '@stable'
|
||||||
'frameworks/kcoreaddons': '@stable'
|
'frameworks/kcoreaddons': '@stable'
|
||||||
@@ -19,15 +19,42 @@ Dependencies:
|
|||||||
'third-party/qtkeychain': '@latest'
|
'third-party/qtkeychain': '@latest'
|
||||||
'third-party/cmark': '@latest'
|
'third-party/cmark': '@latest'
|
||||||
'third-party/qcoro': '@latest'
|
'third-party/qcoro': '@latest'
|
||||||
- 'on': ['Windows', 'Linux', 'FreeBSD']
|
- 'on': ['Windows/Qt5', 'Linux/Qt5', 'FreeBSD/Qt5']
|
||||||
'require':
|
'require':
|
||||||
'frameworks/qqc2-desktop-style': '@stable'
|
'frameworks/qqc2-desktop-style': '@stable'
|
||||||
'frameworks/kio': '@stable'
|
'frameworks/kio': '@stable'
|
||||||
'frameworks/kwindowsystem': '@stable'
|
'frameworks/kwindowsystem': '@stable'
|
||||||
'frameworks/kconfigwidgets': '@stable'
|
'frameworks/kconfigwidgets': '@stable'
|
||||||
- 'on': ['Linux', 'FreeBSD']
|
- 'on': ['Linux/Qt5', 'FreeBSD/Qt5']
|
||||||
'require':
|
'require':
|
||||||
'frameworks/kdbusaddons': '@stable'
|
'frameworks/kdbusaddons': '@stable'
|
||||||
|
|
||||||
|
- 'on': ['Linux/Qt6', 'Android/Qt6', 'FreeBSD/Qt6', 'Windows/Qt6']
|
||||||
|
'require':
|
||||||
|
'frameworks/extra-cmake-modules': '@latest-kf6'
|
||||||
|
'frameworks/kcoreaddons': '@latest-kf6'
|
||||||
|
'frameworks/kirigami': '@latest-kf6'
|
||||||
|
'frameworks/ki18n': '@latest-kf6'
|
||||||
|
'frameworks/kconfig': '@latest-kf6'
|
||||||
|
'frameworks/syntax-highlighting': '@latest-kf6'
|
||||||
|
'frameworks/kitemmodels': '@latest-kf6'
|
||||||
|
'frameworks/knotifications': '@latest-kf6'
|
||||||
|
'libraries/kquickimageeditor': '@latest-kf6'
|
||||||
|
'frameworks/sonnet': '@latest-kf6'
|
||||||
|
'libraries/kirigami-addons': '@latest-kf6'
|
||||||
|
'third-party/libquotient': '@latest'
|
||||||
|
'third-party/qtkeychain': '@latest'
|
||||||
|
'third-party/cmark': '@latest'
|
||||||
|
'third-party/qcoro': '@latest'
|
||||||
|
- 'on': ['Windows/Qt6', 'Linux/Qt6', 'FreeBSD/Qt6']
|
||||||
|
'require':
|
||||||
|
'frameworks/qqc2-desktop-style': '@latest-kf6'
|
||||||
|
'frameworks/kio': '@latest-kf6'
|
||||||
|
'frameworks/kwindowsystem': '@latest-kf6'
|
||||||
|
'frameworks/kconfigwidgets': '@latest-kf6'
|
||||||
|
- 'on': ['Linux/Qt6', 'FreeBSD/Qt6']
|
||||||
|
'require':
|
||||||
|
'frameworks/kdbusaddons': '@latest-kf6'
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
require-passing-tests-on: [ 'Linux', 'FreeBSD', 'Windows' ]
|
require-passing-tests-on: [ 'Linux/Qt5', 'FreeBSD', 'Windows' ]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Copyright: 2020 Carson Black <uhhadd@gmail.com>
|
|||||||
License: LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
License: LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||||
|
|
||||||
Files: android/res/drawable/splash.xml
|
Files: android/res/drawable/splash.xml
|
||||||
Copyright: 2020 Tobias Fella <fella@posteo.de>
|
Copyright: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
License: BSD-2-Clause
|
License: BSD-2-Clause
|
||||||
|
|
||||||
Files: .gitignore
|
Files: .gitignore
|
||||||
@@ -27,11 +27,11 @@ Copyright: 2021 Carl Schwan <carlschwan@kde.org>
|
|||||||
License: BSD-2-Clause
|
License: BSD-2-Clause
|
||||||
|
|
||||||
Files: src/neochatconfig.kcfg
|
Files: src/neochatconfig.kcfg
|
||||||
Copyright: 2020-2021 Carl Schwan <carlschwan@kde.org>, Tobias Fella <fella@posteo.de>
|
Copyright: 2020-2021 Carl Schwan <carlschwan@kde.org>, Tobias Fella <tobias.fella@kde.org>
|
||||||
License: BSD-2-Clause
|
License: BSD-2-Clause
|
||||||
|
|
||||||
Files: src/neochat.notifyrc
|
Files: src/neochat.notifyrc
|
||||||
Copyright: 2020 Tobias Fella <fella@posteo.de>
|
Copyright: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
License: BSD-2-Clause
|
License: BSD-2-Clause
|
||||||
|
|
||||||
Files: src/qml/Component/confetti.png src/qml/Component/glowdot.png
|
Files: src/qml/Component/confetti.png src/qml/Component/glowdot.png
|
||||||
@@ -39,5 +39,5 @@ Copyright: 2021 Alexey Andreyev <aa13q@ya.ru>
|
|||||||
License: CC0-1.0
|
License: CC0-1.0
|
||||||
|
|
||||||
Files: .flatpak-manifest.json
|
Files: .flatpak-manifest.json
|
||||||
Copyright: 2020-2022 Tobias Fella <fella@posteo.de>
|
Copyright: 2020-2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
License: BSD-2-Clause
|
License: BSD-2-Clause
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
# SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carl@carlschwan.eu>
|
# SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carl@carlschwan.eu>
|
||||||
# SPDX-FileCopyrightText: 2020-2021 Nicolas Fella <nicolas.fella@gmx.de>
|
# SPDX-FileCopyrightText: 2020-2021 Nicolas Fella <nicolas.fella@gmx.de>
|
||||||
# SPDX-FileCopyrightText: 2020-2021 Tobias Fella <fella@posteo.de>
|
# SPDX-FileCopyrightText: 2020-2021 Tobias Fella <tobias.fella@kde.org>
|
||||||
# SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
# SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
set(PROJECT_VERSION "23.01")
|
# KDE Applications version, managed by release script.
|
||||||
project(NeoChat VERSION ${PROJECT_VERSION})
|
set(RELEASE_SERVICE_VERSION_MAJOR "23")
|
||||||
|
set(RELEASE_SERVICE_VERSION_MINOR "03")
|
||||||
|
set(RELEASE_SERVICE_VERSION_MICRO "70")
|
||||||
|
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||||
|
|
||||||
set(KF5_MIN_VERSION "5.91.0")
|
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
|
||||||
|
|
||||||
|
set(KF_MIN_VERSION "5.91.0")
|
||||||
set(QT_MIN_VERSION "5.15.2")
|
set(QT_MIN_VERSION "5.15.2")
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
set(QT_MIN_VERSION "5.15.8")
|
set(QT_MIN_VERSION "5.15.8")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
|
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
@@ -52,16 +57,16 @@ set_package_properties(Qt${QT_MAJOR_VERSION} PROPERTIES
|
|||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
PURPOSE "Basic application components"
|
PURPOSE "Basic application components"
|
||||||
)
|
)
|
||||||
find_package(KF5 ${KF5_MIN_VERSION} COMPONENTS Kirigami2 I18n Notifications Config CoreAddons Sonnet ItemModels)
|
find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} COMPONENTS Kirigami2 I18n Notifications Config CoreAddons Sonnet ItemModels)
|
||||||
set_package_properties(KF5 PROPERTIES
|
set_package_properties(KF${QT_MAJOR_VERSION} PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
PURPOSE "Basic application components"
|
PURPOSE "Basic application components"
|
||||||
)
|
)
|
||||||
set_package_properties(KF5Kirigami2 PROPERTIES
|
set_package_properties(KF${QT_MAJOR_VERSION}Kirigami2 PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
PURPOSE "Kirigami application UI framework"
|
PURPOSE "Kirigami application UI framework"
|
||||||
)
|
)
|
||||||
find_package(KF5KirigamiAddons 0.6 REQUIRED)
|
find_package(KF${QT_MAJOR_VERSION}KirigamiAddons 0.7.2 REQUIRED)
|
||||||
|
|
||||||
find_package(Qt${QT_MAJOR_VERSION}Keychain)
|
find_package(Qt${QT_MAJOR_VERSION}Keychain)
|
||||||
set_package_properties(Qt${QT_MAJOR_VERSION}Keychain PROPERTIES
|
set_package_properties(Qt${QT_MAJOR_VERSION}Keychain PROPERTIES
|
||||||
@@ -77,15 +82,15 @@ if(ANDROID)
|
|||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} COMPONENTS Widgets)
|
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} COMPONENTS Widgets)
|
||||||
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle ConfigWidgets KIO WindowSystem)
|
find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle ConfigWidgets KIO WindowSystem)
|
||||||
set_package_properties(KF5QQC2DesktopStyle PROPERTIES
|
set_package_properties(KF${QT_MAJOR_VERSION}QQC2DesktopStyle PROPERTIES
|
||||||
TYPE RUNTIME
|
TYPE RUNTIME
|
||||||
)
|
)
|
||||||
ecm_find_qmlmodule(org.kde.syntaxhighlighting 1.0)
|
ecm_find_qmlmodule(org.kde.syntaxhighlighting 1.0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
||||||
find_package(KF5DBusAddons ${KF5_MIN_VERSION} REQUIRED)
|
find_package(KF${QT_MAJOR_VERSION}DBusAddons ${KF_MIN_VERSION} REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Quotient 0.6)
|
find_package(Quotient 0.6)
|
||||||
@@ -119,8 +124,8 @@ find_package(QCoro${QT_MAJOR_VERSION} 0.4 COMPONENTS Core REQUIRED)
|
|||||||
|
|
||||||
qcoro_enable_coroutines()
|
qcoro_enable_coroutines()
|
||||||
|
|
||||||
find_package(KF5DocTools ${KF5_MIN_VERSION})
|
find_package(KF${QT_MAJOR_VERSION}DocTools ${KF_MIN_VERSION})
|
||||||
set_package_properties(KF5DocTools PROPERTIES DESCRIPTION
|
set_package_properties(KF${QT_MAJOR_VERSION}DocTools PROPERTIES DESCRIPTION
|
||||||
"Tools to generate documentation"
|
"Tools to generate documentation"
|
||||||
TYPE OPTIONAL
|
TYPE OPTIONAL
|
||||||
)
|
)
|
||||||
@@ -150,7 +155,7 @@ if (BUILD_TESTING AND Quotient_VERSION_MINOR GREATER 6)
|
|||||||
add_subdirectory(autotests)
|
add_subdirectory(autotests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(KF5DocTools_FOUND)
|
if(KF${QT_MAJOR_VERSION}DocTools_FOUND)
|
||||||
kdoctools_install(po)
|
kdoctools_install(po)
|
||||||
add_subdirectory(doc)
|
add_subdirectory(doc)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carlschwan@kde.org>
|
SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carlschwan@kde.org>
|
||||||
SPDX-FileCopyrightText: 2020-2021 Tobias Fella <fella@posteo.de>
|
SPDX-FileCopyrightText: 2020-2021 Tobias Fella <tobias.fella@kde.org>
|
||||||
SPDX-License-Identifier: CC0-1.0
|
SPDX-License-Identifier: CC0-1.0
|
||||||
-->
|
-->
|
||||||
# NeoChat
|
# NeoChat
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<!--
|
<!--
|
||||||
- SPDX-License-Identifier: CC0-1.0
|
- SPDX-License-Identifier: CC0-1.0
|
||||||
- SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carlschwan@kde.org>
|
- SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carlschwan@kde.org>
|
||||||
- SPDX-FileCopyrightText: 2020-2021 Tobias Fella <fella@posteo.de>
|
- SPDX-FileCopyrightText: 2020-2021 Tobias Fella <tobias.fella@kde.org>
|
||||||
-->
|
-->
|
||||||
<component type="desktop">
|
<component type="desktop">
|
||||||
<id>org.kde.neochat</id>
|
<id>org.kde.neochat</id>
|
||||||
@@ -179,7 +179,7 @@
|
|||||||
<category>Network</category>
|
<category>Network</category>
|
||||||
</categories>
|
</categories>
|
||||||
<developer_name>The KDE Community</developer_name>
|
<developer_name>The KDE Community</developer_name>
|
||||||
<developer_name xml:lang="ar">مجتمع كدي</developer_name>
|
<developer_name xml:lang="ar">مجتمع كِيدِي</developer_name>
|
||||||
<developer_name xml:lang="az">KDE Cəmiyyəti</developer_name>
|
<developer_name xml:lang="az">KDE Cəmiyyəti</developer_name>
|
||||||
<developer_name xml:lang="ca">La comunitat KDE</developer_name>
|
<developer_name xml:lang="ca">La comunitat KDE</developer_name>
|
||||||
<developer_name xml:lang="ca-valencia">La comunitat KDE</developer_name>
|
<developer_name xml:lang="ca-valencia">La comunitat KDE</developer_name>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
# SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
# SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Version=1.5
|
Version=1.5
|
||||||
Name=NeoChat
|
Name=NeoChat
|
||||||
|
|||||||
963
po/ar/neochat.po
963
po/ar/neochat.po
File diff suppressed because it is too large
Load Diff
985
po/az/neochat.po
985
po/az/neochat.po
File diff suppressed because it is too large
Load Diff
950
po/ca/neochat.po
950
po/ca/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
945
po/cs/neochat.po
945
po/cs/neochat.po
File diff suppressed because it is too large
Load Diff
950
po/da/neochat.po
950
po/da/neochat.po
File diff suppressed because it is too large
Load Diff
985
po/de/neochat.po
985
po/de/neochat.po
File diff suppressed because it is too large
Load Diff
979
po/el/neochat.po
979
po/el/neochat.po
File diff suppressed because it is too large
Load Diff
1113
po/en_GB/neochat.po
1113
po/en_GB/neochat.po
File diff suppressed because it is too large
Load Diff
969
po/es/neochat.po
969
po/es/neochat.po
File diff suppressed because it is too large
Load Diff
951
po/eu/neochat.po
951
po/eu/neochat.po
File diff suppressed because it is too large
Load Diff
985
po/fi/neochat.po
985
po/fi/neochat.po
File diff suppressed because it is too large
Load Diff
952
po/fr/neochat.po
952
po/fr/neochat.po
File diff suppressed because it is too large
Load Diff
975
po/hu/neochat.po
975
po/hu/neochat.po
File diff suppressed because it is too large
Load Diff
1190
po/ia/neochat.po
1190
po/ia/neochat.po
File diff suppressed because it is too large
Load Diff
970
po/id/neochat.po
970
po/id/neochat.po
File diff suppressed because it is too large
Load Diff
963
po/ie/neochat.po
963
po/ie/neochat.po
File diff suppressed because it is too large
Load Diff
954
po/it/neochat.po
954
po/it/neochat.po
File diff suppressed because it is too large
Load Diff
914
po/ja/neochat.po
914
po/ja/neochat.po
File diff suppressed because it is too large
Load Diff
944
po/ka/neochat.po
944
po/ka/neochat.po
File diff suppressed because it is too large
Load Diff
981
po/ko/neochat.po
981
po/ko/neochat.po
File diff suppressed because it is too large
Load Diff
3743
po/lt/neochat.po
Normal file
3743
po/lt/neochat.po
Normal file
File diff suppressed because it is too large
Load Diff
941
po/nl/neochat.po
941
po/nl/neochat.po
File diff suppressed because it is too large
Load Diff
922
po/nn/neochat.po
922
po/nn/neochat.po
File diff suppressed because it is too large
Load Diff
973
po/pa/neochat.po
973
po/pa/neochat.po
File diff suppressed because it is too large
Load Diff
1205
po/pl/neochat.po
1205
po/pl/neochat.po
File diff suppressed because it is too large
Load Diff
934
po/pt/neochat.po
934
po/pt/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
982
po/ru/neochat.po
982
po/ru/neochat.po
File diff suppressed because it is too large
Load Diff
979
po/sk/neochat.po
979
po/sk/neochat.po
File diff suppressed because it is too large
Load Diff
952
po/sl/neochat.po
952
po/sl/neochat.po
File diff suppressed because it is too large
Load Diff
985
po/sv/neochat.po
985
po/sv/neochat.po
File diff suppressed because it is too large
Load Diff
979
po/ta/neochat.po
979
po/ta/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
5
po/tr/docs/neochat/CMakeLists.txt
Normal file
5
po/tr/docs/neochat/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
kdoctools_create_manpage(man-neochat.1.docbook 1 INSTALL_DESTINATION ${MAN_INSTALL_DIR})
|
||||||
122
po/tr/docs/neochat/man-neochat.1.docbook
Normal file
122
po/tr/docs/neochat/man-neochat.1.docbook
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
<!DOCTYPE refentry PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN" "dtd/kdedbx45.dtd" [
|
||||||
|
<!ENTITY % Turkish "INCLUDE">
|
||||||
|
]>
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
|
||||||
|
SPDX-License-Identifier: CC-BY-SA-4.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
<refentry lang="&language;">
|
||||||
|
<refentryinfo>
|
||||||
|
<title
|
||||||
|
>NeoChat Kullanıcı Kılavuzu</title>
|
||||||
|
<author
|
||||||
|
><firstname
|
||||||
|
>Carl</firstname
|
||||||
|
><surname
|
||||||
|
>Schwan</surname
|
||||||
|
> <contrib
|
||||||
|
>NeoChat man page.</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 iletileşme protokolü ile etkileşim için istemci</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
|
||||||
|
>Açıklama</title>
|
||||||
|
<para
|
||||||
|
><command
|
||||||
|
>neochat</command
|
||||||
|
>, Matrix protokolü için hem masaüstünde hem de taşınabilir aygıtlarda çalışan bir sohbet uygulamasıdır. </para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="options"
|
||||||
|
><title
|
||||||
|
>Seçenekler</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term
|
||||||
|
><option
|
||||||
|
>URI</option
|
||||||
|
></term>
|
||||||
|
<listitem>
|
||||||
|
<para
|
||||||
|
>Bir kullanıcı veya oda için matrix URI'si; örneğin, matrix:u/kullanıcı:örnek.org ve matrix:r/kök:örnek.org. Bu, NeoChat'in verilen odayı veya konuşmayı açmayı denemesini sağlar. </para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="bug">
|
||||||
|
<title
|
||||||
|
>Hata Bildirme</title>
|
||||||
|
<para
|
||||||
|
>Hataları veya özellik isteklerini <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
|
||||||
|
> bağlantısından bildirebilirsiniz</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title
|
||||||
|
>Ayrıca</title>
|
||||||
|
<simplelist>
|
||||||
|
<member
|
||||||
|
>Matrix üzerine sıkça sorulan soruların bir listesi: <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
|
||||||
|
>Telif Hakkı</title>
|
||||||
|
<para
|
||||||
|
>Telif hakkı © 2020-2022 Tobias Fella </para>
|
||||||
|
<para
|
||||||
|
>Telif hakkı © 2020-2022 Carl Schwan </para>
|
||||||
|
<para
|
||||||
|
>Lisans: GNU Genel Kamu Lisansa, 3. sürüm veya sonrası <<ulink url="https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
|
>https://www.gnu.org/licenses/gpl-3.0.html</ulink
|
||||||
|
>></para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
1000
po/tr/neochat.po
1000
po/tr/neochat.po
File diff suppressed because it is too large
Load Diff
946
po/uk/neochat.po
946
po/uk/neochat.po
File diff suppressed because it is too large
Load Diff
1019
po/zh_CN/neochat.po
1019
po/zh_CN/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
# SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carl@carlschwan.eu>
|
# SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carl@carlschwan.eu>
|
||||||
# SPDX-FileCopyrightText: 2020-2021 Nicolas Fella <nicolas.fella@gmx.de>
|
# SPDX-FileCopyrightText: 2020-2021 Nicolas Fella <nicolas.fella@gmx.de>
|
||||||
# SPDX-FileCopyrightText: 2020-2021 Tobias Fella <fella@posteo.de>
|
# SPDX-FileCopyrightText: 2020-2021 Tobias Fella <tobias.fella@kde.org>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
add_library(neochat STATIC
|
add_library(neochat STATIC
|
||||||
@@ -79,7 +79,7 @@ if(NOT ANDROID)
|
|||||||
else()
|
else()
|
||||||
target_sources(neochat PRIVATE trayicon.cpp)
|
target_sources(neochat PRIVATE trayicon.cpp)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(neochat PUBLIC KF5::ConfigWidgets KF5::WindowSystem)
|
target_link_libraries(neochat PUBLIC KF${QT_MAJOR_VERSION}::ConfigWidgets KF${QT_MAJOR_VERSION}::WindowSystem)
|
||||||
target_compile_definitions(neochat PUBLIC -DHAVE_COLORSCHEME)
|
target_compile_definitions(neochat PUBLIC -DHAVE_COLORSCHEME)
|
||||||
target_compile_definitions(neochat PUBLIC -DHAVE_WINDOWSYSTEM)
|
target_compile_definitions(neochat PUBLIC -DHAVE_WINDOWSYSTEM)
|
||||||
endif()
|
endif()
|
||||||
@@ -87,13 +87,14 @@ endif()
|
|||||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
||||||
target_sources(neochat-app PRIVATE res_desktop.qrc)
|
target_sources(neochat-app PRIVATE res_desktop.qrc)
|
||||||
target_compile_definitions(neochat PUBLIC -DHAVE_RUNNER)
|
target_compile_definitions(neochat PUBLIC -DHAVE_RUNNER)
|
||||||
|
target_compile_definitions(neochat PUBLIC -DHAVE_X11)
|
||||||
target_sources(neochat PRIVATE runner.cpp)
|
target_sources(neochat PRIVATE runner.cpp)
|
||||||
else()
|
else()
|
||||||
target_sources(neochat-app PRIVATE res_android.qrc)
|
target_sources(neochat-app PRIVATE res_android.qrc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR})
|
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR})
|
||||||
target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 KF5::I18n KF5::Kirigami2 KF5::Notifications KF5::ConfigCore KF5::ConfigGui KF5::CoreAddons KF5::SonnetCore KF5::ItemModels Quotient cmark::cmark ${QTKEYCHAIN_LIBRARIES} QCoro::Core)
|
target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 KF${QT_MAJOR_VERSION}::I18n KF${QT_MAJOR_VERSION}::Kirigami2 KF${QT_MAJOR_VERSION}::Notifications KF${QT_MAJOR_VERSION}::ConfigCore KF${QT_MAJOR_VERSION}::ConfigGui KF${QT_MAJOR_VERSION}::CoreAddons KF${QT_MAJOR_VERSION}::SonnetCore KF${QT_MAJOR_VERSION}::ItemModels Quotient cmark::cmark ${QTKEYCHAIN_LIBRARIES} QCoro::Core)
|
||||||
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
|
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
|
||||||
|
|
||||||
if(NEOCHAT_FLATPAK)
|
if(NEOCHAT_FLATPAK)
|
||||||
@@ -176,7 +177,7 @@ if(ANDROID)
|
|||||||
"visibility"
|
"visibility"
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(neochat PUBLIC Qt::Widgets KF5::KIOWidgets)
|
target_link_libraries(neochat PUBLIC Qt::Widgets KF${QT_MAJOR_VERSION}::KIOWidgets)
|
||||||
install(FILES neochat.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR})
|
install(FILES neochat.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -184,12 +185,12 @@ if(NOT ANDROID)
|
|||||||
set_target_properties(neochat-app PROPERTIES OUTPUT_NAME "neochat")
|
set_target_properties(neochat-app PROPERTIES OUTPUT_NAME "neochat")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(TARGET KF5::DBusAddons)
|
if(TARGET KF${QT_MAJOR_VERSION}::DBusAddons)
|
||||||
target_link_libraries(neochat PUBLIC KF5::DBusAddons)
|
target_link_libraries(neochat PUBLIC KF${QT_MAJOR_VERSION}::DBusAddons)
|
||||||
target_compile_definitions(neochat PUBLIC -DHAVE_KDBUSADDONS)
|
target_compile_definitions(neochat PUBLIC -DHAVE_KDBUSADDONS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (TARGET KF5::KIOWidgets)
|
if (TARGET KF${QT_MAJOR_VERSION}::KIOWidgets)
|
||||||
target_compile_definitions(neochat PUBLIC -DHAVE_KIO)
|
target_compile_definitions(neochat PUBLIC -DHAVE_KIO)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "models/actionsmodel.h"
|
#include "models/actionsmodel.h"
|
||||||
#include "models/customemojimodel.h"
|
#include "models/customemojimodel.h"
|
||||||
#include "neochatconfig.h"
|
#include "neochatconfig.h"
|
||||||
|
#include "neochatroom.h"
|
||||||
#include "neochatuser.h"
|
#include "neochatuser.h"
|
||||||
#include "roommanager.h"
|
#include "roommanager.h"
|
||||||
|
|
||||||
@@ -58,9 +59,9 @@ void ActionsHandler::setRoom(NeoChatRoom *room)
|
|||||||
Q_EMIT roomChanged();
|
Q_EMIT roomChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionsHandler::handleMessage()
|
void ActionsHandler::handleNewMessage()
|
||||||
{
|
{
|
||||||
checkEffects();
|
checkEffects(m_room->chatBoxText());
|
||||||
if (!m_room->chatBoxAttachmentPath().isEmpty()) {
|
if (!m_room->chatBoxAttachmentPath().isEmpty()) {
|
||||||
QUrl url(m_room->chatBoxAttachmentPath());
|
QUrl url(m_room->chatBoxAttachmentPath());
|
||||||
auto path = url.isLocalFile() ? url.toLocalFile() : url.toString();
|
auto path = url.isLocalFile() ? url.toLocalFile() : url.toString();
|
||||||
@@ -69,13 +70,39 @@ void ActionsHandler::handleMessage()
|
|||||||
m_room->setChatBoxText({});
|
m_room->setChatBoxText({});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QString handledText = m_room->chatBoxText();
|
|
||||||
|
|
||||||
std::sort(m_room->mentions()->begin(), m_room->mentions()->end(), [](const auto &a, const auto &b) -> bool {
|
QString handledText = m_room->chatBoxText();
|
||||||
|
handledText = handleMentions(handledText);
|
||||||
|
handleMessage(m_room->chatBoxText(), handledText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionsHandler::handleEdit()
|
||||||
|
{
|
||||||
|
checkEffects(m_room->editText());
|
||||||
|
|
||||||
|
QString handledText = m_room->editText();
|
||||||
|
handledText = handleMentions(handledText, true);
|
||||||
|
handleMessage(m_room->editText(), handledText, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ActionsHandler::handleMentions(QString handledText, const bool &isEdit)
|
||||||
|
{
|
||||||
|
if (!m_room) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<Mention> *mentions;
|
||||||
|
if (isEdit) {
|
||||||
|
mentions = m_room->editMentions();
|
||||||
|
} else {
|
||||||
|
mentions = m_room->mentions();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(mentions->begin(), mentions->end(), [](const auto &a, const auto &b) -> bool {
|
||||||
return a.cursor.anchor() > b.cursor.anchor();
|
return a.cursor.anchor() > b.cursor.anchor();
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const auto &mention : *m_room->mentions()) {
|
for (const auto &mention : *mentions) {
|
||||||
if (mention.text.isEmpty() || mention.id.isEmpty()) {
|
if (mention.text.isEmpty() || mention.id.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -83,11 +110,16 @@ void ActionsHandler::handleMessage()
|
|||||||
mention.cursor.position() - mention.cursor.anchor(),
|
mention.cursor.position() - mention.cursor.anchor(),
|
||||||
QStringLiteral("[%1](https://matrix.to/#/%2)").arg(mention.text, mention.id));
|
QStringLiteral("[%1](https://matrix.to/#/%2)").arg(mention.text, mention.id));
|
||||||
}
|
}
|
||||||
m_room->mentions()->clear();
|
mentions->clear();
|
||||||
|
|
||||||
|
return handledText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionsHandler::handleMessage(const QString &text, QString handledText, const bool &isEdit)
|
||||||
|
{
|
||||||
if (NeoChatConfig::allowQuickEdit()) {
|
if (NeoChatConfig::allowQuickEdit()) {
|
||||||
QRegularExpression sed("^s/([^/]*)/([^/]*)(/g)?$");
|
QRegularExpression sed("^s/([^/]*)/([^/]*)(/g)?$");
|
||||||
auto match = sed.match(m_room->chatBoxText());
|
auto match = sed.match(text);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
const QString regex = match.captured(1);
|
const QString regex = match.captured(1);
|
||||||
const QString replacement = match.captured(2).toHtmlEscaped();
|
const QString replacement = match.captured(2).toHtmlEscaped();
|
||||||
@@ -146,13 +178,13 @@ void ActionsHandler::handleMessage()
|
|||||||
if (handledText.length() == 0) {
|
if (handledText.length() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_room->postMessage(m_room->chatBoxText(), handledText, messageType, m_room->chatBoxReplyId(), m_room->chatBoxEditId());
|
|
||||||
|
m_room->postMessage(text, handledText, messageType, m_room->chatBoxReplyId(), isEdit ? m_room->chatBoxEditId() : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionsHandler::checkEffects()
|
void ActionsHandler::checkEffects(const QString &text)
|
||||||
{
|
{
|
||||||
std::optional<QString> effect = std::nullopt;
|
std::optional<QString> effect = std::nullopt;
|
||||||
const auto &text = m_room->chatBoxText();
|
|
||||||
if (text.contains("\u2744")) {
|
if (text.contains("\u2744")) {
|
||||||
effect = QLatin1String("snowflake");
|
effect = QLatin1String("snowflake");
|
||||||
} else if (text.contains("\u1F386")) {
|
} else if (text.contains("\u1F386")) {
|
||||||
|
|||||||
@@ -33,14 +33,22 @@ Q_SIGNALS:
|
|||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
|
|
||||||
/// \brief Post a message.
|
/**
|
||||||
///
|
* @brief Pre-process text and send message.
|
||||||
/// This also interprets commands if any.
|
*/
|
||||||
void handleMessage();
|
void handleNewMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pre-process text and send edit.
|
||||||
|
*/
|
||||||
|
void handleEdit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NeoChatRoom *m_room = nullptr;
|
NeoChatRoom *m_room = nullptr;
|
||||||
void checkEffects();
|
void checkEffects(const QString &text);
|
||||||
|
|
||||||
|
QString handleMentions(QString handledText, const bool &isEdit = false);
|
||||||
|
void handleMessage(const QString &text, QString handledText, const bool &isEdit = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
QString markdownToHTML(const QString &markdown);
|
QString markdownToHTML(const QString &markdown);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2021 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#include "blurhashimageprovider.h"
|
#include "blurhashimageprovider.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2021 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -108,11 +108,16 @@ ChatDocumentHandler::ChatDocumentHandler(QObject *parent)
|
|||||||
static QPointer<NeoChatRoom> previousRoom = nullptr;
|
static QPointer<NeoChatRoom> previousRoom = nullptr;
|
||||||
if (previousRoom) {
|
if (previousRoom) {
|
||||||
disconnect(previousRoom, &NeoChatRoom::chatBoxTextChanged, this, nullptr);
|
disconnect(previousRoom, &NeoChatRoom::chatBoxTextChanged, this, nullptr);
|
||||||
|
disconnect(previousRoom, &NeoChatRoom::editTextChanged, this, nullptr);
|
||||||
}
|
}
|
||||||
previousRoom = m_room;
|
previousRoom = m_room;
|
||||||
connect(m_room, &NeoChatRoom::chatBoxTextChanged, this, [this]() {
|
connect(m_room, &NeoChatRoom::chatBoxTextChanged, this, [this]() {
|
||||||
int start = completionStartIndex();
|
int start = completionStartIndex();
|
||||||
m_completionModel->setText(m_room->chatBoxText().mid(start, cursorPosition() - start), m_room->chatBoxText().mid(start));
|
m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start));
|
||||||
|
});
|
||||||
|
connect(m_room, &NeoChatRoom::editTextChanged, this, [this]() {
|
||||||
|
int start = completionStartIndex();
|
||||||
|
m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
connect(this, &ChatDocumentHandler::documentChanged, this, [this]() {
|
connect(this, &ChatDocumentHandler::documentChanged, this, [this]() {
|
||||||
@@ -123,7 +128,7 @@ ChatDocumentHandler::ChatDocumentHandler(QObject *parent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int start = completionStartIndex();
|
int start = completionStartIndex();
|
||||||
m_completionModel->setText(m_room->chatBoxText().mid(start, cursorPosition() - start), m_room->chatBoxText().mid(start));
|
m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +143,7 @@ int ChatDocumentHandler::completionStartIndex() const
|
|||||||
#else
|
#else
|
||||||
const auto cursor = cursorPosition();
|
const auto cursor = cursorPosition();
|
||||||
#endif
|
#endif
|
||||||
const auto &text = m_room->chatBoxText();
|
const auto &text = getText();
|
||||||
auto start = std::min(cursor, text.size()) - 1;
|
auto start = std::min(cursor, text.size()) - 1;
|
||||||
while (start > -1) {
|
while (start > -1) {
|
||||||
if (text.at(start) == QLatin1Char(' ')) {
|
if (text.at(start) == QLatin1Char(' ')) {
|
||||||
@@ -150,6 +155,20 @@ int ChatDocumentHandler::completionStartIndex() const
|
|||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChatDocumentHandler::isEdit() const
|
||||||
|
{
|
||||||
|
return m_isEdit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatDocumentHandler::setIsEdit(bool edit)
|
||||||
|
{
|
||||||
|
if (edit == m_isEdit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_isEdit = edit;
|
||||||
|
Q_EMIT isEditChanged();
|
||||||
|
}
|
||||||
|
|
||||||
QQuickTextDocument *ChatDocumentHandler::document() const
|
QQuickTextDocument *ChatDocumentHandler::document() const
|
||||||
{
|
{
|
||||||
return m_document;
|
return m_document;
|
||||||
@@ -204,7 +223,7 @@ void ChatDocumentHandler::complete(int index)
|
|||||||
if (m_completionModel->autoCompletionType() == CompletionModel::User) {
|
if (m_completionModel->autoCompletionType() == CompletionModel::User) {
|
||||||
auto name = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Text).toString();
|
auto name = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Text).toString();
|
||||||
auto id = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
|
auto id = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
|
||||||
auto text = m_room->chatBoxText();
|
auto text = getText();
|
||||||
auto at = text.lastIndexOf(QLatin1Char('@'), cursorPosition() - 1);
|
auto at = text.lastIndexOf(QLatin1Char('@'), cursorPosition() - 1);
|
||||||
QTextCursor cursor(document()->textDocument());
|
QTextCursor cursor(document()->textDocument());
|
||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
@@ -213,11 +232,11 @@ void ChatDocumentHandler::complete(int index)
|
|||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
cursor.setPosition(cursor.position() + name.size(), QTextCursor::KeepAnchor);
|
cursor.setPosition(cursor.position() + name.size(), QTextCursor::KeepAnchor);
|
||||||
cursor.setKeepPositionOnInsert(true);
|
cursor.setKeepPositionOnInsert(true);
|
||||||
m_room->mentions()->push_back({cursor, name, 0, 0, id});
|
pushMention({cursor, name, 0, 0, id});
|
||||||
m_highlighter->rehighlight();
|
m_highlighter->rehighlight();
|
||||||
} else if (m_completionModel->autoCompletionType() == CompletionModel::Command) {
|
} else if (m_completionModel->autoCompletionType() == CompletionModel::Command) {
|
||||||
auto command = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
|
auto command = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
|
||||||
auto text = m_room->chatBoxText();
|
auto text = getText();
|
||||||
auto at = text.lastIndexOf(QLatin1Char('/'));
|
auto at = text.lastIndexOf(QLatin1Char('/'));
|
||||||
QTextCursor cursor(document()->textDocument());
|
QTextCursor cursor(document()->textDocument());
|
||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
@@ -225,7 +244,7 @@ void ChatDocumentHandler::complete(int index)
|
|||||||
cursor.insertText(QStringLiteral("/%1 ").arg(command));
|
cursor.insertText(QStringLiteral("/%1 ").arg(command));
|
||||||
} else if (m_completionModel->autoCompletionType() == CompletionModel::Room) {
|
} else if (m_completionModel->autoCompletionType() == CompletionModel::Room) {
|
||||||
auto alias = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
|
auto alias = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
|
||||||
auto text = m_room->chatBoxText();
|
auto text = getText();
|
||||||
auto at = text.lastIndexOf(QLatin1Char('#'), cursorPosition() - 1);
|
auto at = text.lastIndexOf(QLatin1Char('#'), cursorPosition() - 1);
|
||||||
QTextCursor cursor(document()->textDocument());
|
QTextCursor cursor(document()->textDocument());
|
||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
@@ -234,11 +253,11 @@ void ChatDocumentHandler::complete(int index)
|
|||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
cursor.setPosition(cursor.position() + alias.size(), QTextCursor::KeepAnchor);
|
cursor.setPosition(cursor.position() + alias.size(), QTextCursor::KeepAnchor);
|
||||||
cursor.setKeepPositionOnInsert(true);
|
cursor.setKeepPositionOnInsert(true);
|
||||||
m_room->mentions()->push_back({cursor, alias, 0, 0, alias});
|
pushMention({cursor, alias, 0, 0, alias});
|
||||||
m_highlighter->rehighlight();
|
m_highlighter->rehighlight();
|
||||||
} else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) {
|
} else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) {
|
||||||
auto shortcode = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
|
auto shortcode = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
|
||||||
auto text = m_room->chatBoxText();
|
auto text = getText();
|
||||||
auto at = text.lastIndexOf(QLatin1Char(':'));
|
auto at = text.lastIndexOf(QLatin1Char(':'));
|
||||||
QTextCursor cursor(document()->textDocument());
|
QTextCursor cursor(document()->textDocument());
|
||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
@@ -281,3 +300,27 @@ void ChatDocumentHandler::setSelectionEnd(int position)
|
|||||||
m_selectionEnd = position;
|
m_selectionEnd = position;
|
||||||
Q_EMIT selectionEndChanged();
|
Q_EMIT selectionEndChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ChatDocumentHandler::getText() const
|
||||||
|
{
|
||||||
|
if (!m_room) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
if (m_isEdit) {
|
||||||
|
return m_room->editText();
|
||||||
|
} else {
|
||||||
|
return m_room->chatBoxText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatDocumentHandler::pushMention(const Mention mention) const
|
||||||
|
{
|
||||||
|
if (!m_room) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_isEdit) {
|
||||||
|
m_room->editMentions()->push_back(mention);
|
||||||
|
} else {
|
||||||
|
m_room->mentions()->push_back(mention);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "models/completionmodel.h"
|
#include "models/completionmodel.h"
|
||||||
#include "models/userlistmodel.h"
|
#include "models/userlistmodel.h"
|
||||||
|
#include "neochatroom.h"
|
||||||
|
|
||||||
class QTextDocument;
|
class QTextDocument;
|
||||||
class NeoChatRoom;
|
class NeoChatRoom;
|
||||||
@@ -17,6 +18,14 @@ class SyntaxHighlighter;
|
|||||||
class ChatDocumentHandler : public QObject
|
class ChatDocumentHandler : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Is the instance being used to handle an edit message.
|
||||||
|
*
|
||||||
|
* This is needed to ensure that the text and mentions are saved and retrieved
|
||||||
|
* from the correct parameters in the assigned room.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool isEdit READ isEdit WRITE setIsEdit NOTIFY isEditChanged)
|
||||||
Q_PROPERTY(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged)
|
Q_PROPERTY(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged)
|
||||||
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
|
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
|
||||||
Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged)
|
Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged)
|
||||||
@@ -24,11 +33,14 @@ class ChatDocumentHandler : public QObject
|
|||||||
|
|
||||||
Q_PROPERTY(CompletionModel *completionModel READ completionModel NOTIFY completionModelChanged)
|
Q_PROPERTY(CompletionModel *completionModel READ completionModel NOTIFY completionModelChanged)
|
||||||
|
|
||||||
Q_PROPERTY(NeoChatRoom *room READ room NOTIFY roomChanged)
|
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ChatDocumentHandler(QObject *parent = nullptr);
|
explicit ChatDocumentHandler(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
[[nodiscard]] bool isEdit() const;
|
||||||
|
void setIsEdit(bool edit);
|
||||||
|
|
||||||
[[nodiscard]] QQuickTextDocument *document() const;
|
[[nodiscard]] QQuickTextDocument *document() const;
|
||||||
void setDocument(QQuickTextDocument *document);
|
void setDocument(QQuickTextDocument *document);
|
||||||
|
|
||||||
@@ -49,6 +61,7 @@ public:
|
|||||||
void updateCompletions();
|
void updateCompletions();
|
||||||
CompletionModel *completionModel() const;
|
CompletionModel *completionModel() const;
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void isEditChanged();
|
||||||
void documentChanged();
|
void documentChanged();
|
||||||
void cursorPositionChanged();
|
void cursorPositionChanged();
|
||||||
void roomChanged();
|
void roomChanged();
|
||||||
@@ -59,6 +72,8 @@ Q_SIGNALS:
|
|||||||
private:
|
private:
|
||||||
int completionStartIndex() const;
|
int completionStartIndex() const;
|
||||||
|
|
||||||
|
bool m_isEdit;
|
||||||
|
|
||||||
QQuickTextDocument *m_document;
|
QQuickTextDocument *m_document;
|
||||||
|
|
||||||
NeoChatRoom *m_room = nullptr;
|
NeoChatRoom *m_room = nullptr;
|
||||||
@@ -68,6 +83,9 @@ private:
|
|||||||
int m_selectionStart;
|
int m_selectionStart;
|
||||||
int m_selectionEnd;
|
int m_selectionEnd;
|
||||||
|
|
||||||
|
QString getText() const;
|
||||||
|
void pushMention(const Mention mention) const;
|
||||||
|
|
||||||
SyntaxHighlighter *m_highlighter = nullptr;
|
SyntaxHighlighter *m_highlighter = nullptr;
|
||||||
|
|
||||||
CompletionModel::AutoCompletionType m_completionType = CompletionModel::None;
|
CompletionModel::AutoCompletionType m_completionType = CompletionModel::None;
|
||||||
|
|||||||
@@ -61,9 +61,21 @@ QString Clipboard::saveImage(QString localPath) const
|
|||||||
|
|
||||||
void Clipboard::saveText(QString message)
|
void Clipboard::saveText(QString message)
|
||||||
{
|
{
|
||||||
QRegularExpression re("<[^>]*>");
|
static QRegularExpression re(QStringLiteral("<[^>]*>"));
|
||||||
auto *mineData = new QMimeData; // ownership is transferred to clipboard
|
auto *mineData = new QMimeData; // ownership is transferred to clipboard
|
||||||
mineData->setHtml(message);
|
mineData->setHtml(message);
|
||||||
mineData->setText(message.replace(re, ""));
|
mineData->setText(message.replace(re, QString()));
|
||||||
m_clipboard->setMimeData(mineData);
|
m_clipboard->setMimeData(mineData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Clipboard::setImage(const QUrl &url)
|
||||||
|
{
|
||||||
|
if (url.isLocalFile()) {
|
||||||
|
QImage img(url.path());
|
||||||
|
auto *mimeData = new QMimeData;
|
||||||
|
mimeData->setImageData(img);
|
||||||
|
if (!img.isNull()) {
|
||||||
|
m_clipboard->setMimeData(mimeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public:
|
|||||||
Q_INVOKABLE QString saveImage(QString localPath = {}) const;
|
Q_INVOKABLE QString saveImage(QString localPath = {}) const;
|
||||||
|
|
||||||
Q_INVOKABLE void saveText(QString message);
|
Q_INVOKABLE void saveText(QString message);
|
||||||
|
Q_INVOKABLE void setImage(const QUrl &image);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QClipboard *m_clipboard;
|
QClipboard *m_clipboard;
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
// SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org>
|
// SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org>
|
||||||
// SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||||
#include <qt5keychain/keychain.h>
|
#include <qt5keychain/keychain.h>
|
||||||
|
#else
|
||||||
|
#include <qt6keychain/keychain.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <KConfig>
|
#include <KConfig>
|
||||||
#include <KConfigGroup>
|
#include <KConfigGroup>
|
||||||
@@ -37,6 +41,7 @@
|
|||||||
#include <csapi/content-repo.h>
|
#include <csapi/content-repo.h>
|
||||||
#include <csapi/logout.h>
|
#include <csapi/logout.h>
|
||||||
#include <csapi/profile.h>
|
#include <csapi/profile.h>
|
||||||
|
#include <jobs/downloadfilejob.h>
|
||||||
#include <qt_connection_util.h>
|
#include <qt_connection_util.h>
|
||||||
|
|
||||||
#ifdef QUOTIENT_07
|
#ifdef QUOTIENT_07
|
||||||
@@ -165,7 +170,9 @@ void Controller::handleNotifications(QPointer<Quotient::Connection> connection)
|
|||||||
auto room = connection->room(notification["room_id"].toString());
|
auto room = connection->room(notification["room_id"].toString());
|
||||||
|
|
||||||
// If room exists, room is NOT active OR the application is NOT active, show notification
|
// If room exists, room is NOT active OR the application is NOT active, show notification
|
||||||
if (room && !(room->id() == RoomManager::instance().currentRoom()->id() && QGuiApplication::applicationState() == Qt::ApplicationActive)) {
|
if (room
|
||||||
|
&& !(RoomManager::instance().currentRoom() && room->id() == RoomManager::instance().currentRoom()->id()
|
||||||
|
&& QGuiApplication::applicationState() == Qt::ApplicationActive)) {
|
||||||
// The room might have been deleted (for example rejected invitation).
|
// The room might have been deleted (for example rejected invitation).
|
||||||
auto sender = room->user(notification["event"].toObject()["sender"].toString());
|
auto sender = room->user(notification["event"].toObject()["sender"].toString());
|
||||||
|
|
||||||
@@ -604,6 +611,11 @@ void Controller::setActiveConnection(Connection *connection)
|
|||||||
m_isOnline = true;
|
m_isOnline = true;
|
||||||
Q_EMIT isOnlineChanged(true);
|
Q_EMIT isOnlineChanged(true);
|
||||||
});
|
});
|
||||||
|
connect(connection, &Connection::requestFailed, this, [=](BaseJob *job) {
|
||||||
|
if (dynamic_cast<DownloadFileJob *>(job) && job->jsonData()["errcode"].toString() == "M_TOO_LARGE"_ls) {
|
||||||
|
RoomManager::instance().warning(i18n("File too large to download."), i18n("Contact your matrix server administrator for support."));
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
NeoChatConfig::self()->setActiveConnection(QString());
|
NeoChatConfig::self()->setActiveConnection(QString());
|
||||||
}
|
}
|
||||||
@@ -632,9 +644,17 @@ NeochatDeleteDeviceJob::NeochatDeleteDeviceJob(const QString &deviceId, const Om
|
|||||||
void Controller::createRoom(const QString &name, const QString &topic)
|
void Controller::createRoom(const QString &name, const QString &topic)
|
||||||
{
|
{
|
||||||
auto createRoomJob = m_connection->createRoom(Connection::PublishRoom, "", name, topic, QStringList());
|
auto createRoomJob = m_connection->createRoom(Connection::PublishRoom, "", name, topic, QStringList());
|
||||||
Quotient::CreateRoomJob::connect(createRoomJob, &CreateRoomJob::failure, [this, createRoomJob] {
|
connect(createRoomJob, &CreateRoomJob::failure, this, [this, createRoomJob] {
|
||||||
Q_EMIT errorOccured(i18n("Room creation failed: \"%1\"", createRoomJob->errorString()));
|
Q_EMIT errorOccured(i18n("Room creation failed: \"%1\"", createRoomJob->errorString()));
|
||||||
});
|
});
|
||||||
|
connectSingleShot(
|
||||||
|
this,
|
||||||
|
&Controller::roomAdded,
|
||||||
|
this,
|
||||||
|
[this](NeoChatRoom *room) {
|
||||||
|
RoomManager::instance().enterRoom(room);
|
||||||
|
},
|
||||||
|
Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Controller::isOnline() const
|
bool Controller::isOnline() const
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ Q_SIGNALS:
|
|||||||
void keyVerificationAccept(const QString &commitment);
|
void keyVerificationAccept(const QString &commitment);
|
||||||
void keyVerificationKey(const QString &sas);
|
void keyVerificationKey(const QString &sas);
|
||||||
void activeConnectionIndexChanged();
|
void activeConnectionIndexChanged();
|
||||||
|
void roomAdded(NeoChatRoom *room);
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void logout(Quotient::Connection *conn, bool serverSideLogout);
|
void logout(Quotient::Connection *conn, bool serverSideLogout);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "filetransferpseudojob.h"
|
#include "filetransferpseudojob.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "login.h"
|
#include "login.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -91,6 +91,10 @@
|
|||||||
#include <QDBusConnection>
|
#include <QDBusConnection>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory
|
class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory
|
||||||
@@ -153,7 +157,7 @@ int main(int argc, char *argv[])
|
|||||||
KAboutLicense::GPL_V3,
|
KAboutLicense::GPL_V3,
|
||||||
i18n("© 2018-2020 Black Hat, 2020-2022 KDE Community"));
|
i18n("© 2018-2020 Black Hat, 2020-2022 KDE Community"));
|
||||||
about.addAuthor(i18n("Carl Schwan"), i18n("Maintainer"), QStringLiteral("carl@carlschwan.eu"), QStringLiteral("https://carlschwan.eu"));
|
about.addAuthor(i18n("Carl Schwan"), i18n("Maintainer"), QStringLiteral("carl@carlschwan.eu"), QStringLiteral("https://carlschwan.eu"));
|
||||||
about.addAuthor(i18n("Tobias Fella"), i18n("Maintainer"), QStringLiteral("fella@posteo.de"), QStringLiteral("https://tobiasfella.de"));
|
about.addAuthor(i18n("Tobias Fella"), i18n("Maintainer"), QStringLiteral("tobias.fella@kde.org"), QStringLiteral("https://tobiasfella.de"));
|
||||||
about.addAuthor(i18n("James Graham"), i18n("Maintainer"), QStringLiteral("james.h.graham@protonmail.com"));
|
about.addAuthor(i18n("James Graham"), i18n("Maintainer"), QStringLiteral("james.h.graham@protonmail.com"));
|
||||||
about.addCredit(i18n("Black Hat"), i18n("Original author of Spectral"), QStringLiteral("bhat@encom.eu.org"));
|
about.addCredit(i18n("Black Hat"), i18n("Original author of Spectral"), QStringLiteral("bhat@encom.eu.org"));
|
||||||
about.addCredit(i18n("Alexey Rusakov"), i18n("Maintainer of Quotient"), QStringLiteral("Kitsune-Ral@users.sf.net"));
|
about.addCredit(i18n("Alexey Rusakov"), i18n("Maintainer of Quotient"), QStringLiteral("Kitsune-Ral@users.sf.net"));
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#include "actionsmodel.h"
|
#include "actionsmodel.h"
|
||||||
@@ -115,7 +115,7 @@ QVector<ActionsModel::Action> actions{
|
|||||||
QStringLiteral("spoiler"),
|
QStringLiteral("spoiler"),
|
||||||
[](const QString &text, NeoChatRoom *room) {
|
[](const QString &text, NeoChatRoom *room) {
|
||||||
// Ideally, we would just return rainbowText and let that do the rest, but the colors don't survive markdownToHTML.
|
// Ideally, we would just return rainbowText and let that do the rest, but the colors don't survive markdownToHTML.
|
||||||
room->postMessage(QStringLiteral("/rainbow %1").arg(text),
|
room->postMessage(QStringLiteral("/spoiler %1").arg(text),
|
||||||
QStringLiteral("<span data-mx-spoiler>%1</span>").arg(text),
|
QStringLiteral("<span data-mx-spoiler>%1</span>").arg(text),
|
||||||
RoomMessageEvent::MsgType::Text,
|
RoomMessageEvent::MsgType::Text,
|
||||||
room->chatBoxReplyId(),
|
room->chatBoxReplyId(),
|
||||||
@@ -209,6 +209,40 @@ QVector<ActionsModel::Action> actions{
|
|||||||
kli18n("<room alias or id>"),
|
kli18n("<room alias or id>"),
|
||||||
kli18n("Joins the given room"),
|
kli18n("Joins the given room"),
|
||||||
},
|
},
|
||||||
|
#ifdef QUOTIENT_07
|
||||||
|
Action{
|
||||||
|
QStringLiteral("knock"),
|
||||||
|
[](const QString &text, NeoChatRoom *room) {
|
||||||
|
auto parts = text.split(QLatin1String(" "));
|
||||||
|
QString roomName = parts[0];
|
||||||
|
QRegularExpression roomRegex(QStringLiteral(R"(^[#!][^:]+:\w(?:\w|\.|-)*\.\w+(?::\d{1,5})?)"));
|
||||||
|
auto regexMatch = roomRegex.match(roomName);
|
||||||
|
if (!regexMatch.hasMatch()) {
|
||||||
|
Q_EMIT room->showMessage(NeoChatRoom::Error,
|
||||||
|
i18nc("'<text>' does not look like a room id or alias.", "'%1' does not look like a room id or alias.", text));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
auto targetRoom = text.startsWith(QLatin1Char('!')) ? room->connection()->room(text) : room->connection()->roomByAlias(text);
|
||||||
|
if (targetRoom) {
|
||||||
|
RoomManager::instance().enterRoom(dynamic_cast<NeoChatRoom *>(targetRoom));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("Knocking room <roomname>.", "Knocking room %1.", text));
|
||||||
|
auto connection = Controller::instance().activeConnection();
|
||||||
|
const auto knownServer = roomName.mid(roomName.indexOf(":") + 1);
|
||||||
|
if (parts.length() >= 2) {
|
||||||
|
RoomManager::instance().knockRoom(connection, roomName, parts[1], QStringList{knownServer});
|
||||||
|
} else {
|
||||||
|
RoomManager::instance().knockRoom(connection, roomName, QString(), QStringList{knownServer});
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
std::nullopt,
|
||||||
|
kli18n("<room alias or id> [<reason>]"),
|
||||||
|
kli18n("Requests to join the given room"),
|
||||||
|
},
|
||||||
|
#endif
|
||||||
Action{
|
Action{
|
||||||
QStringLiteral("j"),
|
QStringLiteral("j"),
|
||||||
[](const QString &text, NeoChatRoom *room) {
|
[](const QString &text, NeoChatRoom *room) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#include "collapsestateproxymodel.h"
|
#include "collapsestateproxymodel.h"
|
||||||
|
#include "messageeventmodel.h"
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
@@ -12,18 +13,17 @@ bool CollapseStateProxyModel::filterAcceptsRow(int source_row, const QModelIndex
|
|||||||
!= MessageEventModel::DelegateType::State // If this is not a state, show it
|
!= MessageEventModel::DelegateType::State // If this is not a state, show it
|
||||||
|| sourceModel()->data(sourceModel()->index(source_row + 1, 0), MessageEventModel::EventTypeRole)
|
|| sourceModel()->data(sourceModel()->index(source_row + 1, 0), MessageEventModel::EventTypeRole)
|
||||||
!= MessageEventModel::DelegateType::State // If this is the first state in a block, show it. TODO hidden events?
|
!= MessageEventModel::DelegateType::State // If this is the first state in a block, show it. TODO hidden events?
|
||||||
|| sourceModel()->data(sourceModel()->index(source_row, 0), MessageEventModel::ShowSectionRole).toBool() // If it's a new day, show it
|
|| sourceModel()->data(sourceModel()->index(source_row, 0), MessageEventModel::ShowSectionRole).toBool(); // If it's a new day, show it
|
||||||
|| sourceModel()->data(sourceModel()->index(source_row, 0), MessageEventModel::EventResolvedTypeRole)
|
|
||||||
!= sourceModel()->data(sourceModel()->index(source_row + 1, 0),
|
|
||||||
MessageEventModel::EventResolvedTypeRole) // Also show it if it's of a different type than the one before TODO improve in
|
|
||||||
|| sourceModel()->data(sourceModel()->index(source_row, 0), MessageEventModel::AuthorIdRole)
|
|
||||||
!= sourceModel()->data(sourceModel()->index(source_row + 1, 0), MessageEventModel::AuthorIdRole); // Also show it if it's a different author
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant CollapseStateProxyModel::data(const QModelIndex &index, int role) const
|
QVariant CollapseStateProxyModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (role == AggregateDisplayRole) {
|
if (role == AggregateDisplayRole) {
|
||||||
return aggregateEventToString(mapToSource(index).row());
|
return aggregateEventToString(mapToSource(index).row());
|
||||||
|
} else if (role == StateEventsRole) {
|
||||||
|
return stateEventsList(mapToSource(index).row());
|
||||||
|
} else if (role == AuthorListRole) {
|
||||||
|
return authorList(mapToSource(index).row());
|
||||||
}
|
}
|
||||||
return sourceModel()->data(mapToSource(index), role);
|
return sourceModel()->data(mapToSource(index), role);
|
||||||
}
|
}
|
||||||
@@ -32,27 +32,29 @@ QHash<int, QByteArray> CollapseStateProxyModel::roleNames() const
|
|||||||
{
|
{
|
||||||
auto roles = sourceModel()->roleNames();
|
auto roles = sourceModel()->roleNames();
|
||||||
roles[AggregateDisplayRole] = "aggregateDisplay";
|
roles[AggregateDisplayRole] = "aggregateDisplay";
|
||||||
|
roles[StateEventsRole] = "stateEvents";
|
||||||
|
roles[AuthorListRole] = "authorList";
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CollapseStateProxyModel::aggregateEventToString(int sourceRow) const
|
QString CollapseStateProxyModel::aggregateEventToString(int sourceRow) const
|
||||||
{
|
{
|
||||||
QStringList parts;
|
QStringList parts;
|
||||||
|
QVariantList uniqueAuthors;
|
||||||
for (int i = sourceRow; i >= 0; i--) {
|
for (int i = sourceRow; i >= 0; i--) {
|
||||||
parts += sourceModel()->data(sourceModel()->index(i, 0), Qt::DisplayRole).toString();
|
parts += sourceModel()->data(sourceModel()->index(i, 0), MessageEventModel::GenericDisplayRole).toString();
|
||||||
if (sourceModel()->data(sourceModel()->index(i, 0), MessageEventModel::EventTypeRole)
|
QVariant nextAuthor = sourceModel()->data(sourceModel()->index(i, 0), MessageEventModel::AuthorRole);
|
||||||
|
if (!uniqueAuthors.contains(nextAuthor)) {
|
||||||
|
uniqueAuthors.append(nextAuthor);
|
||||||
|
}
|
||||||
|
if (sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::EventTypeRole)
|
||||||
!= MessageEventModel::DelegateType::State // If it's not a state event
|
!= MessageEventModel::DelegateType::State // If it's not a state event
|
||||||
|| (i > 0
|
|
||||||
&& sourceModel()->data(sourceModel()->index(i, 0), MessageEventModel::EventResolvedTypeRole)
|
|
||||||
!= sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::EventResolvedTypeRole)) // or of a different type
|
|
||||||
|| (i > 0
|
|
||||||
&& sourceModel()->data(sourceModel()->index(i, 0), MessageEventModel::AuthorIdRole)
|
|
||||||
!= sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::AuthorIdRole)) // or by a different author
|
|
||||||
|| sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::ShowSectionRole).toBool() // or the section needs to be visible
|
|| sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::ShowSectionRole).toBool() // or the section needs to be visible
|
||||||
) {
|
) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
parts.sort(); // Sort them so that all identical events can be collected.
|
||||||
if (!parts.isEmpty()) {
|
if (!parts.isEmpty()) {
|
||||||
QStringList chunks;
|
QStringList chunks;
|
||||||
while (!parts.isEmpty()) {
|
while (!parts.isEmpty()) {
|
||||||
@@ -64,18 +66,27 @@ QString CollapseStateProxyModel::aggregateEventToString(int sourceRow) const
|
|||||||
parts.removeFirst();
|
parts.removeFirst();
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count > 1) {
|
if (count > 1 && uniqueAuthors.length() == 1) {
|
||||||
chunks.last() += i18ncp("[user did something] n times", " %1 time", " %1 times", count);
|
chunks.last() += i18ncp("n times", " %1 time ", " %1 times ", count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QString text = chunks.takeFirst();
|
chunks.removeDuplicates();
|
||||||
|
QString text = "<style>a {text-decoration: none;}</style>"; // There can be links in the event text so make sure all are styled.
|
||||||
|
// The author text is either "n users" if > 1 user or the matrix.to link to a single user.
|
||||||
|
QString userText = uniqueAuthors.length() > 1 ? i18ncp("n users", " %1 user ", " %1 users ", uniqueAuthors.length())
|
||||||
|
: QStringLiteral("<a href=\"https://matrix.to/#/%1\" style=\"color: %2\">%3</a> ")
|
||||||
|
.arg(uniqueAuthors[0].toMap()["id"].toString(),
|
||||||
|
uniqueAuthors[0].toMap()["color"].toString(),
|
||||||
|
uniqueAuthors[0].toMap()["displayName"].toString());
|
||||||
|
text += userText;
|
||||||
|
text += chunks.takeFirst();
|
||||||
|
|
||||||
if (chunks.size() > 0) {
|
if (chunks.size() > 0) {
|
||||||
while (chunks.size() > 1) {
|
while (chunks.size() > 1) {
|
||||||
text += i18nc("[action 1], [action 2 and action 3]", ", ");
|
text += i18nc("[action 1], [action 2 and/or action 3]", ", ");
|
||||||
text += chunks.takeFirst();
|
text += chunks.takeFirst();
|
||||||
}
|
}
|
||||||
text += i18nc("[action 1, action 2] and [action 3]", " and ");
|
text += uniqueAuthors.length() > 1 ? i18nc("[action 1, action 2] or [action 3]", " or ") : i18nc("[action 1, action 2] and [action 3]", " and ");
|
||||||
text += chunks.takeFirst();
|
text += chunks.takeFirst();
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
@@ -83,3 +94,41 @@ QString CollapseStateProxyModel::aggregateEventToString(int sourceRow) const
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantList CollapseStateProxyModel::stateEventsList(int sourceRow) const
|
||||||
|
{
|
||||||
|
QVariantList stateEvents;
|
||||||
|
for (int i = sourceRow; i >= 0; i--) {
|
||||||
|
auto nextState = QVariantMap{
|
||||||
|
{"author", sourceModel()->data(sourceModel()->index(i, 0), MessageEventModel::AuthorRole)},
|
||||||
|
{"authorDisplayName", sourceModel()->data(sourceModel()->index(i, 0), MessageEventModel::AuthorDisplayNameRole).toString()},
|
||||||
|
{"text", sourceModel()->data(sourceModel()->index(i, 0), Qt::DisplayRole).toString()},
|
||||||
|
};
|
||||||
|
stateEvents.append(nextState);
|
||||||
|
if (sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::EventTypeRole)
|
||||||
|
!= MessageEventModel::DelegateType::State // If it's not a state event
|
||||||
|
|| sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::ShowSectionRole).toBool() // or the section needs to be visible
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stateEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList CollapseStateProxyModel::authorList(int sourceRow) const
|
||||||
|
{
|
||||||
|
QVariantList uniqueAuthors;
|
||||||
|
for (int i = sourceRow; i >= 0; i--) {
|
||||||
|
QVariant nextAvatar = sourceModel()->data(sourceModel()->index(i, 0), MessageEventModel::AuthorRole);
|
||||||
|
if (!uniqueAuthors.contains(nextAvatar)) {
|
||||||
|
uniqueAuthors.append(nextAvatar);
|
||||||
|
}
|
||||||
|
if (sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::EventTypeRole)
|
||||||
|
!= MessageEventModel::DelegateType::State // If it's not a state event
|
||||||
|
|| sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::ShowSectionRole).toBool() // or the section needs to be visible
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uniqueAuthors;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -12,10 +12,29 @@ class CollapseStateProxyModel : public QSortFilterProxyModel
|
|||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
AggregateDisplayRole = MessageEventModel::LastRole + 1,
|
AggregateDisplayRole = MessageEventModel::LastRole + 1,
|
||||||
|
StateEventsRole,
|
||||||
|
AuthorListRole,
|
||||||
};
|
};
|
||||||
[[nodiscard]] bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
[[nodiscard]] bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||||
[[nodiscard]] QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
|
[[nodiscard]] QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief QString aggregating the text of consecutive state events starting at row.
|
||||||
|
*
|
||||||
|
* If state events happen on different days they will be split into two aggregate
|
||||||
|
* events.
|
||||||
|
*/
|
||||||
[[nodiscard]] QString aggregateEventToString(int row) const;
|
[[nodiscard]] QString aggregateEventToString(int row) const;
|
||||||
|
/**
|
||||||
|
* @brief Return a list of consecutive state events starting at row.
|
||||||
|
*
|
||||||
|
* If state events happen on different days they will be split into two aggregate
|
||||||
|
* events.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] QVariantList stateEventsList(int row) const;
|
||||||
|
/**
|
||||||
|
* @brief List of unique authors for the aggregate state events starting at row.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] QVariantList authorList(int row) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#include "completionmodel.h"
|
#include "completionmodel.h"
|
||||||
@@ -16,7 +16,7 @@ CompletionModel::CompletionModel(QObject *parent)
|
|||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
, m_filterModel(new CompletionProxyModel())
|
, m_filterModel(new CompletionProxyModel())
|
||||||
, m_userListModel(new UserListModel(this))
|
, m_userListModel(new UserListModel(this))
|
||||||
, m_emojiModel(new KConcatenateRowsProxyModel(this))
|
, m_emojiModel(new QConcatenateTablesProxyModel(this))
|
||||||
{
|
{
|
||||||
connect(this, &CompletionModel::textChanged, this, &CompletionModel::updateCompletion);
|
connect(this, &CompletionModel::textChanged, this, &CompletionModel::updateCompletion);
|
||||||
connect(this, &CompletionModel::roomChanged, this, [this]() {
|
connect(this, &CompletionModel::roomChanged, this, [this]() {
|
||||||
@@ -145,7 +145,7 @@ void CompletionModel::updateCompletion()
|
|||||||
m_filterModel->setFullText(m_fullText);
|
m_filterModel->setFullText(m_fullText);
|
||||||
m_filterModel->setFilterText(m_text);
|
m_filterModel->setFilterText(m_text);
|
||||||
m_filterModel->invalidate();
|
m_filterModel->invalidate();
|
||||||
} else if (text().startsWith(QLatin1Char(':'))
|
} else if (text().startsWith(QLatin1Char(':')) && !text()[1].isUpper()
|
||||||
&& (m_fullText.indexOf(QLatin1Char(':'), 1) == -1
|
&& (m_fullText.indexOf(QLatin1Char(':'), 1) == -1
|
||||||
|| (m_fullText.indexOf(QLatin1Char(' ')) != -1 && m_fullText.indexOf(QLatin1Char(':'), 1) > m_fullText.indexOf(QLatin1Char(' '), 1)))) {
|
|| (m_fullText.indexOf(QLatin1Char(' ')) != -1 && m_fullText.indexOf(QLatin1Char(':'), 1) > m_fullText.indexOf(QLatin1Char(' '), 1)))) {
|
||||||
m_filterModel->setSourceModel(m_emojiModel);
|
m_filterModel->setSourceModel(m_emojiModel);
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QConcatenateTablesProxyModel>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
#include <KConcatenateRowsProxyModel>
|
|
||||||
|
|
||||||
#include "roomlistmodel.h"
|
#include "roomlistmodel.h"
|
||||||
|
|
||||||
class CompletionProxyModel;
|
class CompletionProxyModel;
|
||||||
@@ -75,6 +74,6 @@ private:
|
|||||||
|
|
||||||
UserListModel *m_userListModel;
|
UserListModel *m_userListModel;
|
||||||
RoomListModel *m_roomListModel;
|
RoomListModel *m_roomListModel;
|
||||||
KConcatenateRowsProxyModel *m_emojiModel;
|
QConcatenateTablesProxyModel *m_emojiModel;
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(CompletionModel::AutoCompletionType);
|
Q_DECLARE_METATYPE(CompletionModel::AutoCompletionType);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#include "completionproxymodel.h"
|
#include "completionproxymodel.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "devicesmodel.h"
|
#include "devicesmodel.h"
|
||||||
@@ -70,7 +70,12 @@ void DevicesModel::logout(int index, const QString &password)
|
|||||||
auto job = Controller::instance().activeConnection()->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId);
|
auto job = Controller::instance().activeConnection()->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId);
|
||||||
|
|
||||||
connect(job, &BaseJob::result, this, [this, job, password, index] {
|
connect(job, &BaseJob::result, this, [this, job, password, index] {
|
||||||
if (job->error() != 0) {
|
auto onSuccess = [this, index]() {
|
||||||
|
beginRemoveRows(QModelIndex(), index, index);
|
||||||
|
m_devices.remove(index);
|
||||||
|
endRemoveRows();
|
||||||
|
};
|
||||||
|
if (job->error() != BaseJob::Success) {
|
||||||
QJsonObject replyData = job->jsonData();
|
QJsonObject replyData = job->jsonData();
|
||||||
QJsonObject authData;
|
QJsonObject authData;
|
||||||
authData["session"] = replyData["session"];
|
authData["session"] = replyData["session"];
|
||||||
@@ -79,11 +84,9 @@ void DevicesModel::logout(int index, const QString &password)
|
|||||||
QJsonObject identifier = {{"type", "m.id.user"}, {"user", Controller::instance().activeConnection()->user()->id()}};
|
QJsonObject identifier = {{"type", "m.id.user"}, {"user", Controller::instance().activeConnection()->user()->id()}};
|
||||||
authData["identifier"] = identifier;
|
authData["identifier"] = identifier;
|
||||||
auto *innerJob = Controller::instance().activeConnection()->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId, authData);
|
auto *innerJob = Controller::instance().activeConnection()->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId, authData);
|
||||||
connect(innerJob, &BaseJob::success, this, [this, index]() {
|
connect(innerJob, &BaseJob::success, this, onSuccess);
|
||||||
beginRemoveRows(QModelIndex(), index, index);
|
} else {
|
||||||
m_devices.remove(index);
|
onSuccess();
|
||||||
endRemoveRows();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ QHash<int, QByteArray> MessageEventModel::roleNames() const
|
|||||||
roles[IsNameChangeRole] = "isNameChange";
|
roles[IsNameChangeRole] = "isNameChange";
|
||||||
roles[IsAvatarChangeRole] = "isAvatarChange";
|
roles[IsAvatarChangeRole] = "isAvatarChange";
|
||||||
roles[IsRedactedRole] = "isRedacted";
|
roles[IsRedactedRole] = "isRedacted";
|
||||||
|
roles[GenericDisplayRole] = "genericDisplay";
|
||||||
|
roles[IsPendingRole] = "isPending";
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,6 +177,7 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
|||||||
});
|
});
|
||||||
connect(m_currentRoom, &Room::pendingEventAdded, this, &MessageEventModel::endInsertRows);
|
connect(m_currentRoom, &Room::pendingEventAdded, this, &MessageEventModel::endInsertRows);
|
||||||
connect(m_currentRoom, &Room::pendingEventAboutToMerge, this, [this](RoomEvent *, int i) {
|
connect(m_currentRoom, &Room::pendingEventAboutToMerge, this, [this](RoomEvent *, int i) {
|
||||||
|
Q_EMIT dataChanged(index(i, 0), index(i, 0), {IsPendingRole});
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
return; // No need to move anything, just refresh
|
return; // No need to move anything, just refresh
|
||||||
}
|
}
|
||||||
@@ -462,6 +465,14 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
return m_currentRoom->eventToString(evt, Qt::RichText);
|
return m_currentRoom->eventToString(evt, Qt::RichText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (role == GenericDisplayRole) {
|
||||||
|
if (evt.isRedacted()) {
|
||||||
|
return i18n("<i>[This message was deleted]</i>");
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_currentRoom->eventToGenericString(evt);
|
||||||
|
}
|
||||||
|
|
||||||
if (role == FormattedBodyRole) {
|
if (role == FormattedBodyRole) {
|
||||||
if (auto e = eventCast<const RoomMessageEvent>(&evt)) {
|
if (auto e = eventCast<const RoomMessageEvent>(&evt)) {
|
||||||
if (e->hasTextContent() && e->mimeType().name() != "text/plain") {
|
if (e->hasTextContent() && e->mimeType().name() != "text/plain") {
|
||||||
@@ -560,7 +571,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (role == HighlightRole) {
|
if (role == HighlightRole) {
|
||||||
return m_currentRoom->isEventHighlighted(&evt);
|
return !m_currentRoom->isDirectChat() && m_currentRoom->isEventHighlighted(&evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == FileMimetypeIcon) {
|
if (role == FileMimetypeIcon) {
|
||||||
@@ -899,6 +910,10 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
return evt.isRedacted();
|
return evt.isRedacted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (role == IsPendingRole) {
|
||||||
|
return row < m_currentRoom->pendingEvents().size();
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,6 +981,9 @@ QVariant MessageEventModel::getLatestMessageFromIndex(const int baseline)
|
|||||||
for (auto it = timelineBottom; it != limit; ++it) {
|
for (auto it = timelineBottom; it != limit; ++it) {
|
||||||
auto evt = it->event();
|
auto evt = it->event();
|
||||||
auto e = eventCast<const RoomMessageEvent>(evt);
|
auto e = eventCast<const RoomMessageEvent>(evt);
|
||||||
|
if (!e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto content = (*it)->contentJson();
|
auto content = (*it)->contentJson();
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public:
|
|||||||
AnnotationRole,
|
AnnotationRole,
|
||||||
UserMarkerRole,
|
UserMarkerRole,
|
||||||
FormattedBodyRole,
|
FormattedBodyRole,
|
||||||
|
GenericDisplayRole,
|
||||||
|
|
||||||
MimeTypeRole,
|
MimeTypeRole,
|
||||||
FileMimetypeIcon,
|
FileMimetypeIcon,
|
||||||
@@ -72,6 +73,7 @@ public:
|
|||||||
IsNameChangeRole,
|
IsNameChangeRole,
|
||||||
IsAvatarChangeRole,
|
IsAvatarChangeRole,
|
||||||
IsRedactedRole,
|
IsRedactedRole,
|
||||||
|
IsPendingRole,
|
||||||
LastRole, // Keep this last
|
LastRole, // Keep this last
|
||||||
};
|
};
|
||||||
Q_ENUM(EventRoles)
|
Q_ENUM(EventRoles)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "roomlistmodel.h"
|
#include "roomlistmodel.h"
|
||||||
|
|
||||||
|
#include "controller.h"
|
||||||
#include "neochatconfig.h"
|
#include "neochatconfig.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
#include "roommanager.h"
|
#include "roommanager.h"
|
||||||
@@ -143,6 +144,7 @@ void RoomListModel::doAddRoom(Room *r)
|
|||||||
m_rooms.append(room);
|
m_rooms.append(room);
|
||||||
connectRoomSignals(room);
|
connectRoomSignals(room);
|
||||||
Q_EMIT roomAdded(room);
|
Q_EMIT roomAdded(room);
|
||||||
|
Q_EMIT Controller::instance().roomAdded(room);
|
||||||
} else {
|
} else {
|
||||||
qCritical() << "Attempt to add nullptr to the room list";
|
qCritical() << "Attempt to add nullptr to the room list";
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
@@ -200,7 +202,11 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room)
|
|||||||
}
|
}
|
||||||
Q_EMIT newHighlight(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128));
|
Q_EMIT newHighlight(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128));
|
||||||
});
|
});
|
||||||
|
#ifndef QUOTIENT_07
|
||||||
connect(room, &Room::notificationCountChanged, this, &RoomListModel::refreshNotificationCount);
|
connect(room, &Room::notificationCountChanged, this, &RoomListModel::refreshNotificationCount);
|
||||||
|
#else
|
||||||
|
connect(room, &Room::unreadStatsChanged, this, &RoomListModel::refreshNotificationCount);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QUOTIENT_07
|
#ifndef QUOTIENT_07
|
||||||
@@ -229,10 +235,13 @@ void RoomListModel::handleNotifications()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
oldNotifications += notification["event"].toObject()["event_id"].toString();
|
oldNotifications += notification["event"].toObject()["event_id"].toString();
|
||||||
|
|
||||||
auto room = m_connection->room(notification["room_id"].toString());
|
auto room = m_connection->room(notification["room_id"].toString());
|
||||||
|
auto currentRoom = RoomManager::instance().currentRoom();
|
||||||
|
bool roomIsActive = currentRoom && room->id() == currentRoom->id();
|
||||||
|
|
||||||
// If room exists, room is NOT active OR the application is NOT active, show notification
|
// If room exists, room is NOT active OR the application is NOT active, show notification
|
||||||
if (room && !(room->id() == RoomManager::instance().currentRoom()->id() && QGuiApplication::applicationState() == Qt::ApplicationActive)) {
|
if (room && !(roomIsActive && QGuiApplication::applicationState() == Qt::ApplicationActive)) {
|
||||||
// The room might have been deleted (for example rejected invitation).
|
// The room might have been deleted (for example rejected invitation).
|
||||||
auto sender = room->user(notification["event"].toObject()["sender"].toString());
|
auto sender = room->user(notification["event"].toObject()["sender"].toString());
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#include "searchmodel.h"
|
#include "searchmodel.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "sortfilterroomlistmodel.h"
|
#include "sortfilterroomlistmodel.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#include "statemodel.h"
|
#include "statemodel.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// SPDX-FileCopyrightText: Kitsune Ral <Kitsune-Ral@users.sf.net>
|
// SPDX-FileCopyrightText: Kitsune Ral <Kitsune-Ral@users.sf.net>
|
||||||
// SPDX-FileCopyrightText: Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
#include "neochataccountregistry.h"
|
#include "neochataccountregistry.h"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 Kitsune Ral <Kitsune-Ral@users.sf.net>
|
// SPDX-FileCopyrightText: 2020 Kitsune Ral <Kitsune-Ral@users.sf.net>
|
||||||
// SPDX-FileCopyrightText: Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -41,9 +41,6 @@
|
|||||||
<label>"Show your messages on the right</label>
|
<label>"Show your messages on the right</label>
|
||||||
<default>true</default>
|
<default>true</default>
|
||||||
</entry>
|
</entry>
|
||||||
<entry name="RoomListPageWidth" type="int">
|
|
||||||
<default>-1</default>
|
|
||||||
</entry>
|
|
||||||
<entry name="RoomDrawerWidth" type="int">
|
<entry name="RoomDrawerWidth" type="int">
|
||||||
<default>-1</default>
|
<default>-1</default>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -108,6 +105,10 @@
|
|||||||
<label>Show avatar in the room drawer</label>
|
<label>Show avatar in the room drawer</label>
|
||||||
<default>true</default>
|
<default>true</default>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry name="Collapsed" type="bool">
|
||||||
|
<label>Save the collapsed state of the room list</label>
|
||||||
|
<default>false</default>
|
||||||
|
</entry>
|
||||||
</group>
|
</group>
|
||||||
<group name="NetworkProxy">
|
<group name="NetworkProxy">
|
||||||
<entry name="ProxyType" type="Enum">
|
<entry name="ProxyType" type="Enum">
|
||||||
|
|||||||
@@ -658,6 +658,135 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
|
|||||||
i18n("Unknown event"));
|
i18n("Unknown event"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString NeoChatRoom::eventToGenericString(const RoomEvent &evt) const
|
||||||
|
{
|
||||||
|
#ifdef QUOTIENT_07
|
||||||
|
return switchOnType(
|
||||||
|
#else
|
||||||
|
return visit(
|
||||||
|
#endif
|
||||||
|
evt,
|
||||||
|
[](const RoomMessageEvent &e) {
|
||||||
|
Q_UNUSED(e)
|
||||||
|
return i18n("sent a message");
|
||||||
|
},
|
||||||
|
[](const StickerEvent &e) {
|
||||||
|
Q_UNUSED(e)
|
||||||
|
return i18n("sent a sticker");
|
||||||
|
},
|
||||||
|
[](const RoomMemberEvent &e) {
|
||||||
|
switch (e.membership()) {
|
||||||
|
case MembershipType::Invite:
|
||||||
|
if (e.repeatsState()) {
|
||||||
|
return i18n("reinvited someone to the room");
|
||||||
|
}
|
||||||
|
Q_FALLTHROUGH();
|
||||||
|
case MembershipType::Join: {
|
||||||
|
QString text{};
|
||||||
|
// Part 1: invites and joins
|
||||||
|
if (e.repeatsState()) {
|
||||||
|
text = i18n("joined the room (repeated)");
|
||||||
|
} else if (e.changesMembership()) {
|
||||||
|
text = e.membership() == MembershipType::Invite ? i18n("invited someone to the room") : i18n("joined the room");
|
||||||
|
}
|
||||||
|
if (!text.isEmpty()) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
// Part 2: profile changes of joined members
|
||||||
|
if (e.isRename()) {
|
||||||
|
if (e.displayName().isEmpty()) {
|
||||||
|
text = i18nc("their refers to a singular user", "cleared their display name");
|
||||||
|
} else {
|
||||||
|
text = i18nc("their refers to a singular user", "changed their display name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e.isAvatarUpdate()) {
|
||||||
|
if (!text.isEmpty()) {
|
||||||
|
text += i18n(" and ");
|
||||||
|
}
|
||||||
|
if (e.avatarUrl().isEmpty()) {
|
||||||
|
text += i18nc("their refers to a singular user", "cleared their avatar");
|
||||||
|
#ifdef QUOTIENT_07
|
||||||
|
} else if (!e.prevContent()->avatarUrl) {
|
||||||
|
#else
|
||||||
|
} else if (e.prevContent()->avatarUrl.isEmpty()) {
|
||||||
|
#endif
|
||||||
|
text += i18n("set an avatar");
|
||||||
|
} else {
|
||||||
|
text += i18nc("their refers to a singular user", "updated their avatar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
text = i18nc("<user> changed nothing", "changed nothing");
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
case MembershipType::Leave:
|
||||||
|
if (e.prevContent() && e.prevContent()->membership == MembershipType::Invite) {
|
||||||
|
return (e.senderId() != e.userId()) ? i18n("withdrew a user's invitation") : i18n("rejected the invitation");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.prevContent() && e.prevContent()->membership == MembershipType::Ban) {
|
||||||
|
return (e.senderId() != e.userId()) ? i18n("unbanned a user") : i18n("self-unbanned");
|
||||||
|
}
|
||||||
|
return (e.senderId() != e.userId()) ? i18n("put a user out of the room") : i18n("left the room");
|
||||||
|
case MembershipType::Ban:
|
||||||
|
if (e.senderId() != e.userId()) {
|
||||||
|
return i18n("banned a user from the room");
|
||||||
|
} else {
|
||||||
|
return i18n("self-banned from the room");
|
||||||
|
}
|
||||||
|
case MembershipType::Knock: {
|
||||||
|
return i18n("requested an invite");
|
||||||
|
}
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
return i18n("made something unknown");
|
||||||
|
},
|
||||||
|
[](const RoomCanonicalAliasEvent &e) {
|
||||||
|
return (e.alias().isEmpty()) ? i18n("cleared the room main alias") : i18n("set the room main alias");
|
||||||
|
},
|
||||||
|
[](const RoomNameEvent &e) {
|
||||||
|
return (e.name().isEmpty()) ? i18n("cleared the room name") : i18n("set the room name");
|
||||||
|
},
|
||||||
|
[](const RoomTopicEvent &e) {
|
||||||
|
return (e.topic().isEmpty()) ? i18n("cleared the topic") : i18n("set the topic");
|
||||||
|
},
|
||||||
|
[](const RoomAvatarEvent &) {
|
||||||
|
return i18n("changed the room avatar");
|
||||||
|
},
|
||||||
|
[](const EncryptionEvent &) {
|
||||||
|
return i18n("activated End-to-End Encryption");
|
||||||
|
},
|
||||||
|
[](const RoomCreateEvent &e) {
|
||||||
|
return e.isUpgrade() ? i18n("upgraded the room version") : i18n("created the room");
|
||||||
|
},
|
||||||
|
[](const RoomPowerLevelsEvent &) {
|
||||||
|
return i18nc("'power level' means permission level", "changed the power levels for this room");
|
||||||
|
},
|
||||||
|
[](const StateEventBase &e) {
|
||||||
|
if (e.matrixType() == QLatin1String("m.room.server_acl")) {
|
||||||
|
return i18n("changed the server access control lists for this room");
|
||||||
|
}
|
||||||
|
if (e.matrixType() == QLatin1String("im.vector.modular.widgets")) {
|
||||||
|
if (e.fullJson()["unsigned"]["prev_content"].toObject().isEmpty()) {
|
||||||
|
return i18n("added a widget");
|
||||||
|
}
|
||||||
|
if (e.contentJson().isEmpty()) {
|
||||||
|
return i18n("removed a widget");
|
||||||
|
}
|
||||||
|
return i18n("configured a widget");
|
||||||
|
}
|
||||||
|
return i18n("updated the state");
|
||||||
|
},
|
||||||
|
#ifdef QUOTIENT_07
|
||||||
|
[](const PollStartEvent &e) {
|
||||||
|
return i18n("started a poll");
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
i18n("Unknown event"));
|
||||||
|
}
|
||||||
|
|
||||||
void NeoChatRoom::changeAvatar(const QUrl &localFile)
|
void NeoChatRoom::changeAvatar(const QUrl &localFile)
|
||||||
{
|
{
|
||||||
const auto job = connection()->uploadFile(localFile.toLocalFile());
|
const auto job = connection()->uploadFile(localFile.toLocalFile());
|
||||||
@@ -946,6 +1075,12 @@ void NeoChatRoom::setHistoryVisibility(const QString &historyVisibilityRule)
|
|||||||
// Not emitting historyVisibilityChanged() here, since that would override the change in the UI with the *current* value, which is not the *new* value.
|
// Not emitting historyVisibilityChanged() here, since that would override the change in the UI with the *current* value, which is not the *new* value.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int NeoChatRoom::getUserPowerLevel(const QString &userId) const
|
||||||
|
{
|
||||||
|
auto powerLevelEvent = getCurrentState<RoomPowerLevelsEvent>();
|
||||||
|
return powerLevelEvent->powerLevelForUser(userId);
|
||||||
|
}
|
||||||
|
|
||||||
void NeoChatRoom::setUserPowerLevel(const QString &userID, const int &powerLevel)
|
void NeoChatRoom::setUserPowerLevel(const QString &userID, const int &powerLevel)
|
||||||
{
|
{
|
||||||
if (joinedCount() <= 1) {
|
if (joinedCount() <= 1) {
|
||||||
@@ -1497,6 +1632,17 @@ void NeoChatRoom::setChatBoxText(const QString &text)
|
|||||||
Q_EMIT chatBoxTextChanged();
|
Q_EMIT chatBoxTextChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString NeoChatRoom::editText() const
|
||||||
|
{
|
||||||
|
return m_editText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeoChatRoom::setEditText(const QString &text)
|
||||||
|
{
|
||||||
|
m_editText = text;
|
||||||
|
Q_EMIT editTextChanged();
|
||||||
|
}
|
||||||
|
|
||||||
QString NeoChatRoom::chatBoxReplyId() const
|
QString NeoChatRoom::chatBoxReplyId() const
|
||||||
{
|
{
|
||||||
return m_chatBoxReplyId;
|
return m_chatBoxReplyId;
|
||||||
@@ -1573,6 +1719,11 @@ QVector<Mention> *NeoChatRoom::mentions()
|
|||||||
return &m_mentions;
|
return &m_mentions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<Mention> *NeoChatRoom::editMentions()
|
||||||
|
{
|
||||||
|
return &m_editMentions;
|
||||||
|
}
|
||||||
|
|
||||||
QString NeoChatRoom::savedText() const
|
QString NeoChatRoom::savedText() const
|
||||||
{
|
{
|
||||||
return m_savedText;
|
return m_savedText;
|
||||||
@@ -1684,3 +1835,7 @@ int NeoChatRoom::maxRoomVersion() const
|
|||||||
}
|
}
|
||||||
return maxVersion;
|
return maxVersion;
|
||||||
}
|
}
|
||||||
|
NeoChatUser *NeoChatRoom::directChatRemoteUser() const
|
||||||
|
{
|
||||||
|
return dynamic_cast<NeoChatUser *>(connection()->directChatUsers(this)[0]);
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
#include <qcoro/task.h>
|
#include <qcoro/task.h>
|
||||||
|
|
||||||
class PollHandler;
|
#include "neochatuser.h"
|
||||||
class NeoChatUser;
|
#include "pollhandler.h"
|
||||||
|
|
||||||
class PushNotificationState : public QObject
|
class PushNotificationState : public QObject
|
||||||
{
|
{
|
||||||
@@ -79,6 +79,11 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
|
|
||||||
// Due to problems with QTextDocument, unlike the other properties here, chatBoxText is *not* used to store the text when switching rooms
|
// Due to problems with QTextDocument, unlike the other properties here, chatBoxText is *not* used to store the text when switching rooms
|
||||||
Q_PROPERTY(QString chatBoxText READ chatBoxText WRITE setChatBoxText NOTIFY chatBoxTextChanged)
|
Q_PROPERTY(QString chatBoxText READ chatBoxText WRITE setChatBoxText NOTIFY chatBoxTextChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The text for any message currently being edited in the room.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QString editText READ editText WRITE setEditText NOTIFY editTextChanged)
|
||||||
Q_PROPERTY(QString chatBoxReplyId READ chatBoxReplyId WRITE setChatBoxReplyId NOTIFY chatBoxReplyIdChanged)
|
Q_PROPERTY(QString chatBoxReplyId READ chatBoxReplyId WRITE setChatBoxReplyId NOTIFY chatBoxReplyIdChanged)
|
||||||
Q_PROPERTY(QString chatBoxEditId READ chatBoxEditId WRITE setChatBoxEditId NOTIFY chatBoxEditIdChanged)
|
Q_PROPERTY(QString chatBoxEditId READ chatBoxEditId WRITE setChatBoxEditId NOTIFY chatBoxEditIdChanged)
|
||||||
Q_PROPERTY(NeoChatUser *chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
|
Q_PROPERTY(NeoChatUser *chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
|
||||||
@@ -94,6 +99,7 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
* Only returns main integer room versions (i.e. no msc room versions).
|
* Only returns main integer room versions (i.e. no msc room versions).
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(int maxRoomVersion READ maxRoomVersion NOTIFY maxRoomVersionChanged)
|
Q_PROPERTY(int maxRoomVersion READ maxRoomVersion NOTIFY maxRoomVersionChanged)
|
||||||
|
Q_PROPERTY(NeoChatUser *directChatRemoteUser READ directChatRemoteUser CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum MessageType {
|
enum MessageType {
|
||||||
@@ -147,6 +153,14 @@ public:
|
|||||||
[[nodiscard]] QString historyVisibility() const;
|
[[nodiscard]] QString historyVisibility() const;
|
||||||
void setHistoryVisibility(const QString &historyVisibilityRule);
|
void setHistoryVisibility(const QString &historyVisibilityRule);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the power level for the given user ID in the room.
|
||||||
|
*
|
||||||
|
* Returns the default value for a user in the room if they have no escalated
|
||||||
|
* privileges or if they are not a member so membership should be known before using.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE [[nodiscard]] int getUserPowerLevel(const QString &userId) const;
|
||||||
|
|
||||||
Q_INVOKABLE void setUserPowerLevel(const QString &userID, const int &powerLevel);
|
Q_INVOKABLE void setUserPowerLevel(const QString &userID, const int &powerLevel);
|
||||||
|
|
||||||
[[nodiscard]] int powerLevel(const QString &eventName, const bool &isStateEvent = false) const;
|
[[nodiscard]] int powerLevel(const QString &eventName, const bool &isStateEvent = false) const;
|
||||||
@@ -249,6 +263,7 @@ public:
|
|||||||
[[nodiscard]] QString avatarMediaId() const;
|
[[nodiscard]] QString avatarMediaId() const;
|
||||||
|
|
||||||
[[nodiscard]] QString eventToString(const Quotient::RoomEvent &evt, Qt::TextFormat format = Qt::PlainText, bool removeReply = true) const;
|
[[nodiscard]] QString eventToString(const Quotient::RoomEvent &evt, Qt::TextFormat format = Qt::PlainText, bool removeReply = true) const;
|
||||||
|
[[nodiscard]] QString eventToGenericString(const Quotient::RoomEvent &evt) const;
|
||||||
|
|
||||||
Q_INVOKABLE [[nodiscard]] bool containsUser(const QString &userID) const;
|
Q_INVOKABLE [[nodiscard]] bool containsUser(const QString &userID) const;
|
||||||
Q_INVOKABLE [[nodiscard]] bool isUserBanned(const QString &user) const;
|
Q_INVOKABLE [[nodiscard]] bool isUserBanned(const QString &user) const;
|
||||||
@@ -270,6 +285,9 @@ public:
|
|||||||
QString chatBoxText() const;
|
QString chatBoxText() const;
|
||||||
void setChatBoxText(const QString &text);
|
void setChatBoxText(const QString &text);
|
||||||
|
|
||||||
|
QString editText() const;
|
||||||
|
void setEditText(const QString &text);
|
||||||
|
|
||||||
QString chatBoxReplyId() const;
|
QString chatBoxReplyId() const;
|
||||||
void setChatBoxReplyId(const QString &replyId);
|
void setChatBoxReplyId(const QString &replyId);
|
||||||
|
|
||||||
@@ -287,6 +305,11 @@ public:
|
|||||||
|
|
||||||
QVector<Mention> *mentions();
|
QVector<Mention> *mentions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vector of mentions in the current edit text.
|
||||||
|
*/
|
||||||
|
QVector<Mention> *editMentions();
|
||||||
|
|
||||||
QString savedText() const;
|
QString savedText() const;
|
||||||
void setSavedText(const QString &savedText);
|
void setSavedText(const QString &savedText);
|
||||||
|
|
||||||
@@ -316,6 +339,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int maxRoomVersion() const;
|
int maxRoomVersion() const;
|
||||||
|
NeoChatUser *directChatRemoteUser() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSet<const Quotient::RoomEvent *> highlights;
|
QSet<const Quotient::RoomEvent *> highlights;
|
||||||
@@ -336,10 +360,12 @@ private:
|
|||||||
QCoro::Task<void> doUploadFile(QUrl url, QString body = QString());
|
QCoro::Task<void> doUploadFile(QUrl url, QString body = QString());
|
||||||
|
|
||||||
QString m_chatBoxText;
|
QString m_chatBoxText;
|
||||||
|
QString m_editText;
|
||||||
QString m_chatBoxReplyId;
|
QString m_chatBoxReplyId;
|
||||||
QString m_chatBoxEditId;
|
QString m_chatBoxEditId;
|
||||||
QString m_chatBoxAttachmentPath;
|
QString m_chatBoxAttachmentPath;
|
||||||
QVector<Mention> m_mentions;
|
QVector<Mention> m_mentions;
|
||||||
|
QVector<Mention> m_editMentions;
|
||||||
QString m_savedText;
|
QString m_savedText;
|
||||||
#ifdef QUOTIENT_07
|
#ifdef QUOTIENT_07
|
||||||
QCache<QString, PollHandler> m_polls;
|
QCache<QString, PollHandler> m_polls;
|
||||||
@@ -362,6 +388,7 @@ Q_SIGNALS:
|
|||||||
void pushNotificationStateChanged(PushNotificationState::State state);
|
void pushNotificationStateChanged(PushNotificationState::State state);
|
||||||
void showMessage(MessageType messageType, const QString &message);
|
void showMessage(MessageType messageType, const QString &message);
|
||||||
void chatBoxTextChanged();
|
void chatBoxTextChanged();
|
||||||
|
void editTextChanged();
|
||||||
void chatBoxReplyIdChanged();
|
void chatBoxReplyIdChanged();
|
||||||
void chatBoxEditIdChanged();
|
void chatBoxEditIdChanged();
|
||||||
void chatBoxAttachmentPathChanged();
|
void chatBoxAttachmentPathChanged();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "notificationsmanager.h"
|
#include "notificationsmanager.h"
|
||||||
@@ -268,6 +268,10 @@ void NotificationsManager::updateNotificationRules(const QString &type)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Controller::instance().activeConnection()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const QJsonObject accountData = Controller::instance().activeConnection()->accountDataJson("m.push_rules");
|
const QJsonObject accountData = Controller::instance().activeConnection()->accountDataJson("m.push_rules");
|
||||||
|
|
||||||
// Update override rules
|
// Update override rules
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#include "pollevent.h"
|
#include "pollevent.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#include "pollhandler.h"
|
#include "pollhandler.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ QQC2.Control {
|
|||||||
|
|
||||||
property alias textField: textField
|
property alias textField: textField
|
||||||
property bool isReplying: currentRoom.chatBoxReplyId.length > 0
|
property bool isReplying: currentRoom.chatBoxReplyId.length > 0
|
||||||
property bool isEditing: currentRoom.chatBoxEditId.length > 0
|
property NeoChatUser replyUser: currentRoom.chatBoxReplyUser
|
||||||
property bool replyPaneVisible: isReplying || isEditing
|
|
||||||
property NeoChatUser replyUser: currentRoom.chatBoxReplyUser ?? currentRoom.chatBoxEditUser
|
|
||||||
property bool attachmentPaneVisible: currentRoom.chatBoxAttachmentPath.length > 0
|
property bool attachmentPaneVisible: currentRoom.chatBoxAttachmentPath.length > 0
|
||||||
|
|
||||||
signal messageSent()
|
signal messageSent()
|
||||||
@@ -122,7 +120,7 @@ QQC2.Control {
|
|||||||
leftPadding: LayoutMirroring.enabled ? actionsRow.width : (root.width > chatBoxMaxWidth ? 0 : Kirigami.Units.largeSpacing)
|
leftPadding: LayoutMirroring.enabled ? actionsRow.width : (root.width > chatBoxMaxWidth ? 0 : Kirigami.Units.largeSpacing)
|
||||||
rightPadding: LayoutMirroring.enabled ? (root.width > chatBoxMaxWidth ? 0 : Kirigami.Units.largeSpacing) : actionsRow.width
|
rightPadding: LayoutMirroring.enabled ? (root.width > chatBoxMaxWidth ? 0 : Kirigami.Units.largeSpacing) : actionsRow.width
|
||||||
|
|
||||||
placeholderText: readOnly ? i18n("This room is encrypted. Build libQuotient with encryption enabled to send encrypted messages.") : currentRoom.chatBoxEditId.length > 0 ? i18n("Edit Message") : currentRoom.usesEncryption ? i18n("Send an encrypted message…") : currentRoom.chatBoxAttachmentPath.length > 0 ? i18n("Set an attachment caption...") : i18n("Send a message…")
|
placeholderText: readOnly ? i18n("This room is encrypted. Build libQuotient with encryption enabled to send encrypted messages.") : currentRoom.usesEncryption ? i18n("Send an encrypted message…") : currentRoom.chatBoxAttachmentPath.length > 0 ? i18n("Set an attachment caption...") : i18n("Send a message…")
|
||||||
verticalAlignment: TextEdit.AlignVCenter
|
verticalAlignment: TextEdit.AlignVCenter
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
readOnly: (currentRoom.usesEncryption && !Controller.encryptionSupported)
|
readOnly: (currentRoom.usesEncryption && !Controller.encryptionSupported)
|
||||||
@@ -187,6 +185,13 @@ QQC2.Control {
|
|||||||
repeatTimer.stop()
|
repeatTimer.stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Keys.onShortcutOverride: {
|
||||||
|
// Accept the event only when there was something to cancel. Otherwise, let the event go to the RoomPage.
|
||||||
|
if (cancelButton.visible && event.key === Qt.Key_Escape) {
|
||||||
|
cancelButton.action.trigger();
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: paneLoader
|
id: paneLoader
|
||||||
@@ -198,8 +203,8 @@ QQC2.Control {
|
|||||||
anchors.rightMargin: root.width > chatBoxMaxWidth ? 0 : (chatBarScrollView.QQC2.ScrollBar.vertical.visible ? Kirigami.Units.largeSpacing * 3.5 : Kirigami.Units.largeSpacing)
|
anchors.rightMargin: root.width > chatBoxMaxWidth ? 0 : (chatBarScrollView.QQC2.ScrollBar.vertical.visible ? Kirigami.Units.largeSpacing * 3.5 : Kirigami.Units.largeSpacing)
|
||||||
|
|
||||||
active: visible
|
active: visible
|
||||||
visible: root.replyPaneVisible || root.attachmentPaneVisible
|
visible: root.isReplying || root.attachmentPaneVisible
|
||||||
sourceComponent: root.replyPaneVisible ? replyPane : attachmentPane
|
sourceComponent: root.isReplying ? replyPane : attachmentPane
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
id: replyPane
|
id: replyPane
|
||||||
@@ -207,8 +212,7 @@ QQC2.Control {
|
|||||||
userName: root.replyUser ? root.replyUser.displayName : ""
|
userName: root.replyUser ? root.replyUser.displayName : ""
|
||||||
userColor: root.replyUser ? root.replyUser.color : ""
|
userColor: root.replyUser ? root.replyUser.color : ""
|
||||||
userAvatar: root.replyUser ? "image://mxc/" + currentRoom.getUser(root.replyUser.id).avatarMediaId : ""
|
userAvatar: root.replyUser ? "image://mxc/" + currentRoom.getUser(root.replyUser.id).avatarMediaId : ""
|
||||||
isReply: root.isReplying
|
text: currentRoom.chatBoxReplyMessage
|
||||||
text: isEditing ? currentRoom.chatBoxEditMessage : currentRoom.chatBoxReplyMessage
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
@@ -263,18 +267,16 @@ QQC2.Control {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: (root.width - chatBoxMaxWidth) / 2 + Kirigami.Units.largeSpacing + (chatBarScrollView.QQC2.ScrollBar.vertical.visible && !(root.width > chatBoxMaxWidth) ? Kirigami.Units.largeSpacing * 2.5 : 0)
|
anchors.rightMargin: (root.width - chatBoxMaxWidth) / 2 + Kirigami.Units.largeSpacing + (chatBarScrollView.QQC2.ScrollBar.vertical.visible && !(root.width > chatBoxMaxWidth) ? Kirigami.Units.largeSpacing * 2.5 : 0)
|
||||||
|
|
||||||
visible: root.replyPaneVisible
|
visible: root.isReplying
|
||||||
display: QQC2.AbstractButton.IconOnly
|
display: QQC2.AbstractButton.IconOnly
|
||||||
action: Kirigami.Action {
|
action: Kirigami.Action {
|
||||||
text: root.isReplying ? i18nc("@action:button", "Cancel reply") : i18nc("@action:button", "Cancel edit")
|
text: i18nc("@action:button", "Cancel reply")
|
||||||
icon.name: "dialog-close"
|
icon.name: "dialog-close"
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
currentRoom.chatBoxReplyId = "";
|
currentRoom.chatBoxReplyId = "";
|
||||||
currentRoom.chatBoxEditId = "";
|
|
||||||
currentRoom.chatBoxAttachmentPath = "";
|
currentRoom.chatBoxAttachmentPath = "";
|
||||||
root.forceActiveFocus()
|
root.forceActiveFocus()
|
||||||
}
|
}
|
||||||
shortcut: "Escape"
|
|
||||||
}
|
}
|
||||||
QQC2.ToolTip.text: text
|
QQC2.ToolTip.text: text
|
||||||
QQC2.ToolTip.visible: hovered
|
QQC2.ToolTip.visible: hovered
|
||||||
@@ -356,15 +358,6 @@ QQC2.Control {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: currentRoom
|
|
||||||
function onChatBoxEditIdChanged() {
|
|
||||||
if (currentRoom.chatBoxEditMessage.length > 0) {
|
|
||||||
textField.text = currentRoom.chatBoxEditMessage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatDocumentHandler {
|
ChatDocumentHandler {
|
||||||
id: documentHandler
|
id: documentHandler
|
||||||
document: textField.textDocument
|
document: textField.textDocument
|
||||||
@@ -398,12 +391,11 @@ QQC2.Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function postMessage() {
|
function postMessage() {
|
||||||
actionsHandler.handleMessage();
|
actionsHandler.handleNewMessage();
|
||||||
repeatTimer.stop()
|
repeatTimer.stop()
|
||||||
currentRoom.markAllMessagesAsRead();
|
currentRoom.markAllMessagesAsRead();
|
||||||
textField.clear();
|
textField.clear();
|
||||||
currentRoom.chatBoxReplyId = "";
|
currentRoom.chatBoxReplyId = "";
|
||||||
currentRoom.chatBoxEditId = "";
|
|
||||||
messageSent()
|
messageSent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ QQC2.Popup {
|
|||||||
connection: Controller.activeConnection
|
connection: Controller.activeConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
required property var chatDocumentHandler
|
property var chatDocumentHandler
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
chatDocumentHandler.completionModel.roomListModel = roomListModel;
|
chatDocumentHandler.completionModel.roomListModel = roomListModel;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ GridLayout {
|
|||||||
property string userName
|
property string userName
|
||||||
property color userColor: Kirigami.Theme.highlightColor
|
property color userColor: Kirigami.Theme.highlightColor
|
||||||
property var userAvatar: ""
|
property var userAvatar: ""
|
||||||
property bool isReply
|
|
||||||
property var text
|
property var text
|
||||||
|
|
||||||
rows: 3
|
rows: 3
|
||||||
@@ -30,7 +29,7 @@ GridLayout {
|
|||||||
Layout.columnSpan: 3
|
Layout.columnSpan: 3
|
||||||
topPadding: Kirigami.Units.smallSpacing
|
topPadding: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
text: isReply ? i18n("Replying to:") : i18n("Editing message:")
|
text: i18n("Replying to:")
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: verticalBorder
|
id: verticalBorder
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user