Compare commits
449 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
180e927f82 | ||
|
|
fcb32b1974 | ||
|
|
bf9d1e5261 | ||
|
|
d6eb91c476 | ||
|
|
96b03082e3 | ||
|
|
962063e58a | ||
|
|
06a09700a0 | ||
|
|
12657abd03 | ||
|
|
3752c3b872 | ||
|
|
acf3f7030d | ||
|
|
63ed48f283 | ||
|
|
25f2693710 | ||
|
|
2efcc1041b | ||
|
|
1f5823cec0 | ||
|
|
efd18fa2d6 | ||
|
|
98dc2cf41a | ||
|
|
97f27a1ae0 | ||
|
|
46b9566242 | ||
|
|
70ab0374ec | ||
|
|
2b2e991bb8 | ||
|
|
fbf4dfbe35 | ||
|
|
1344e46201 | ||
|
|
728d133b7c | ||
|
|
a41be9e19b | ||
|
|
aa5ece8bfb | ||
|
|
21f5ee74ba | ||
|
|
2e6cf03c15 | ||
|
|
9332910bcb | ||
|
|
157c098af3 | ||
|
|
9fe134e7f0 | ||
|
|
46aaab3fb0 | ||
|
|
a5b37a78a0 | ||
|
|
59699abb94 | ||
|
|
3cc0d89ee5 | ||
|
|
96e83fc71b | ||
|
|
d89019d752 | ||
|
|
51565dfdd2 | ||
|
|
e1d09171d5 | ||
|
|
f86572f880 | ||
|
|
d7451834f3 | ||
|
|
a4767cea7d | ||
|
|
4c43869fd4 | ||
|
|
e603664521 | ||
|
|
369242ab31 | ||
|
|
013773d465 | ||
|
|
20b17a58d3 | ||
|
|
1c4bb79347 | ||
|
|
6d2b49f3eb | ||
|
|
e3d5867da6 | ||
|
|
a046e3ed27 | ||
|
|
5b935c1d33 | ||
|
|
fe6bc5a36e | ||
|
|
c085be4f6e | ||
|
|
1f73a9dc90 | ||
|
|
63206ef1dd | ||
|
|
0d286db0c2 | ||
|
|
7d3f478a74 | ||
|
|
6df2ebd1eb | ||
|
|
252fb6eb21 | ||
|
|
5873092356 | ||
|
|
30822003d1 | ||
|
|
52ae237eb7 | ||
|
|
ee02abfe37 | ||
|
|
f0de235f37 | ||
|
|
9e9fe6d275 | ||
|
|
f4ca5f0f34 | ||
|
|
5f240fa05c | ||
|
|
1e29eca59a | ||
|
|
1f71ec3bf8 | ||
|
|
64c5ad88f6 | ||
|
|
fb5a3c1c5c | ||
|
|
4a5a83f94a | ||
|
|
133edc249f | ||
|
|
da30e66127 | ||
|
|
4516e1e0f4 | ||
|
|
bd80f65163 | ||
|
|
f828ecf282 | ||
|
|
a0483167c5 | ||
|
|
87288f508c | ||
|
|
dc184ed2fd | ||
|
|
49e1bf9ab1 | ||
|
|
74acf3f9dc | ||
|
|
38205d2791 | ||
|
|
81da926d4f | ||
|
|
1018fe5d3f | ||
|
|
58b32dd50f | ||
|
|
82184b895a | ||
|
|
da0f6f78a4 | ||
|
|
cfd06d064c | ||
|
|
a90e9ae92a | ||
|
|
8ab0002057 | ||
|
|
e1840be234 | ||
|
|
d6ecaaa344 | ||
|
|
0c08c2ab89 | ||
|
|
39ff11e059 | ||
|
|
93254431c5 | ||
|
|
fc14a8eac8 | ||
|
|
50759bb3ca | ||
|
|
23134d8e72 | ||
|
|
7cd095f76a | ||
|
|
d5c3054da4 | ||
|
|
ae12c838bd | ||
|
|
51727dd345 | ||
|
|
5611b000fb | ||
|
|
461896e228 | ||
|
|
e388536a03 | ||
|
|
61f22edd86 | ||
|
|
9e368691d6 | ||
|
|
dad2b3ec8f | ||
|
|
8821c37ff8 | ||
|
|
c105170eca | ||
|
|
b07c04eddc | ||
|
|
7aa0f68b10 | ||
|
|
cbdae4c312 | ||
|
|
9210940556 | ||
|
|
d8489527b4 | ||
|
|
64c9cd97de | ||
|
|
119a9890b1 | ||
|
|
69be6b5939 | ||
|
|
112152f2df | ||
|
|
2ef634a6cb | ||
|
|
fd31b4fb74 | ||
|
|
3b12520fa2 | ||
|
|
24718a5f72 | ||
|
|
db62bacc7e | ||
|
|
6500669b67 | ||
|
|
557d151ed4 | ||
|
|
95ffd485b4 | ||
|
|
ebd38fb435 | ||
|
|
a5b999e682 | ||
|
|
41d34fc0e4 | ||
|
|
b51194f90f | ||
|
|
80ac9e1ba7 | ||
|
|
e3874c824a | ||
|
|
6599c6b609 | ||
|
|
13d522221c | ||
|
|
dd8f926f32 | ||
|
|
258312e798 | ||
|
|
43d40c7e75 | ||
|
|
cbcc9a6514 | ||
|
|
625048610b | ||
|
|
fa47b67e3d | ||
|
|
9347a66acf | ||
|
|
317df56ffa | ||
|
|
fed9197716 | ||
|
|
1e892599e9 | ||
|
|
b7229ca0cf | ||
|
|
953b711823 | ||
|
|
01d903efd3 | ||
|
|
241dd81932 | ||
|
|
f6dfe0cbcf | ||
|
|
f10b97139c | ||
|
|
385c5b3405 | ||
|
|
7bc6f906f8 | ||
|
|
b8b1434a95 | ||
|
|
85c7a4bcb3 | ||
|
|
84b698a7e8 | ||
|
|
7b249e9fa6 | ||
|
|
46593ef68f | ||
|
|
b70f73c7d6 | ||
|
|
ece5e34fa2 | ||
|
|
74b400288d | ||
|
|
83f19b0631 | ||
|
|
c905d2d6fb | ||
|
|
d0c1eb2f04 | ||
|
|
d7d9d29c1d | ||
|
|
2a3f019ec6 | ||
|
|
d384d50b0d | ||
|
|
be8cb12bba | ||
|
|
a1aa2918be | ||
|
|
d7536bccb3 | ||
|
|
6b677355e1 | ||
|
|
85d625f6ac | ||
|
|
f5d6f87afe | ||
|
|
31d755f407 | ||
|
|
ebfc20d4b4 | ||
|
|
b83d42103f | ||
|
|
c9856347fe | ||
|
|
7224c92caf | ||
|
|
a84f98c96f | ||
|
|
a40bccc29d | ||
|
|
171897161c | ||
|
|
013ad49e2b | ||
|
|
b357586164 | ||
|
|
5642f3416a | ||
|
|
9bbb1710df | ||
|
|
e2b7679252 | ||
|
|
5c353cd4b5 | ||
|
|
cba6dc994f | ||
|
|
b0c4b7fc2a | ||
|
|
ed7aff1f24 | ||
|
|
33f4be0d88 | ||
|
|
1178cafef0 | ||
|
|
1be97e65b4 | ||
|
|
634cefc694 | ||
|
|
36469c6097 | ||
|
|
0cd9c6a434 | ||
|
|
e285a94273 | ||
|
|
a2ec6d97b1 | ||
|
|
b42fd3fc51 | ||
|
|
12971bb08b | ||
|
|
79deda4f2d | ||
|
|
365af2cd6c | ||
|
|
cc50e76c0d | ||
|
|
16df22af68 | ||
|
|
53a957fa15 | ||
|
|
69571489fa | ||
|
|
3a66b4d67e | ||
|
|
ba8d2b1281 | ||
|
|
11185c127d | ||
|
|
0ab3bfd4f3 | ||
|
|
b5fdb3d0db | ||
|
|
9ef342e448 | ||
|
|
0bda65b5ac | ||
|
|
005b7a760c | ||
|
|
ab3c40a709 | ||
|
|
a809b7f11e | ||
|
|
702c7d49a8 | ||
|
|
a2afaf40cd | ||
|
|
eb900a5c2c | ||
|
|
14eadb3b92 | ||
|
|
a5d84bb266 | ||
|
|
5a03ce4e95 | ||
|
|
607db82db0 | ||
|
|
56b302d4c8 | ||
|
|
1237e9d4bd | ||
|
|
71468e453c | ||
|
|
d0a915e81c | ||
|
|
e7751f40fa | ||
|
|
498240c6ec | ||
|
|
d448cf4c7e | ||
|
|
d7d9f254ff | ||
|
|
aedba5c650 | ||
|
|
a4e9794b13 | ||
|
|
4bd4bd6f22 | ||
|
|
ac9bfbff78 | ||
|
|
e26392ce94 | ||
|
|
a314e56425 | ||
|
|
4af27f7609 | ||
|
|
773017c881 | ||
|
|
153cbeae8a | ||
|
|
777ea9fbe0 | ||
|
|
d22cc7f40a | ||
|
|
c28ca9087c | ||
|
|
857412d9cc | ||
|
|
4b132460f6 | ||
|
|
644f5c0ce1 | ||
|
|
45439e17c9 | ||
|
|
485e0f0510 | ||
|
|
2969d20a92 | ||
|
|
7cf97a5c9b | ||
|
|
f2894ed774 | ||
|
|
3e1044b8fd | ||
|
|
0c6480c5e0 | ||
|
|
232c45979a | ||
|
|
848031c315 | ||
|
|
bf2389c31c | ||
|
|
d87bba7993 | ||
|
|
9b837a8656 | ||
|
|
90061caec3 | ||
|
|
6e81701d4b | ||
|
|
2164c4c3f8 | ||
|
|
a0665187c6 | ||
|
|
77e933f620 | ||
|
|
deed9cf6d7 | ||
|
|
fad4e506bc | ||
|
|
9d6b940b78 | ||
|
|
cfb663d399 | ||
|
|
4620c176b6 | ||
|
|
8c927a59d9 | ||
|
|
2fe9bc9846 | ||
|
|
b9615eadb3 | ||
|
|
e4e5d14d6e | ||
|
|
75eddd2a6f | ||
|
|
634407a22d | ||
|
|
42dd2e5413 | ||
|
|
2a6e3c0add | ||
|
|
abb81e0d8e | ||
|
|
e9a4b43331 | ||
|
|
08b2c39a61 | ||
|
|
f89cec9c55 | ||
|
|
4c49ca2a51 | ||
|
|
52ab6f484b | ||
|
|
2a5359e73b | ||
|
|
977ea73237 | ||
|
|
a769b904dc | ||
|
|
5def5124ef | ||
|
|
40c3cc7f9e | ||
|
|
17c0906044 | ||
|
|
38cfc915f1 | ||
|
|
1821d9fc04 | ||
|
|
ec6a8dd028 | ||
|
|
e0c3b7f808 | ||
|
|
155dc4919e | ||
|
|
a38c53b2be | ||
|
|
67dfc7b32e | ||
|
|
f156551d4f | ||
|
|
5c04eb85af | ||
|
|
1efa27177a | ||
|
|
17da652152 | ||
|
|
4ff866ea29 | ||
|
|
3c9c7abe35 | ||
|
|
157017126a | ||
|
|
928e4ae5ed | ||
|
|
2bc790f4cb | ||
|
|
a3148b264c | ||
|
|
16b27700f5 | ||
|
|
9ee10b6968 | ||
|
|
4d0db0b5c2 | ||
|
|
6e49aaf17b | ||
|
|
1092d75f2e | ||
|
|
8059c3797d | ||
|
|
1302d62ad9 | ||
|
|
8eaae4034d | ||
|
|
354e3414a1 | ||
|
|
fc24beae6d | ||
|
|
923cc67b55 | ||
|
|
30e24069bc | ||
|
|
f7533a454c | ||
|
|
ab4e1a86dc | ||
|
|
d28c2ed113 | ||
|
|
3a467328f5 | ||
|
|
979d83cb01 | ||
|
|
d165cd955d | ||
|
|
6eb770343e | ||
|
|
54be52b855 | ||
|
|
d201333409 | ||
|
|
3db8b4cd17 | ||
|
|
0e246a00bc | ||
|
|
e638fa8929 | ||
|
|
cdc982ad91 | ||
|
|
bff69e21ad | ||
|
|
e117cc0cfb | ||
|
|
3af1a88e05 | ||
|
|
aa116a35f5 | ||
|
|
ac232d7f55 | ||
|
|
928911e33c | ||
|
|
e3c30f5bb3 | ||
|
|
4b51855528 | ||
|
|
79c27db0a9 | ||
|
|
78e42ab352 | ||
|
|
93909c45ee | ||
|
|
eda0bf4b23 | ||
|
|
4f4b10e0b6 | ||
|
|
2b374a8bec | ||
|
|
7821de4a8d | ||
|
|
86b88c851f | ||
|
|
1157882f1b | ||
|
|
594d1373c9 | ||
|
|
1e6948bbc7 | ||
|
|
41845b97d5 | ||
|
|
bb56f74622 | ||
|
|
a98f6ac331 | ||
|
|
15d6287995 | ||
|
|
0242ab72e8 | ||
|
|
4b7cbf37d5 | ||
|
|
0ccfe7d991 | ||
|
|
ab5585cd06 | ||
|
|
b25a0a7a4e | ||
|
|
f574c12adc | ||
|
|
05a2f03c18 | ||
|
|
cbc2e65856 | ||
|
|
1df80a7d2a | ||
|
|
050a014df7 | ||
|
|
4775ae09b0 | ||
|
|
8d4c3bb4fc | ||
|
|
439260ff03 | ||
|
|
5b04ad6805 | ||
|
|
6d77ed1e0e | ||
|
|
cc7f783b50 | ||
|
|
1d7ed1983b | ||
|
|
c0151353c5 | ||
|
|
72994248fa | ||
|
|
af0d3d5ee1 | ||
|
|
07dd1d2e91 | ||
|
|
185a88a16e | ||
|
|
e3059e636a | ||
|
|
aeb566746a | ||
|
|
8da567d9fa | ||
|
|
d99f69cc24 | ||
|
|
8240962400 | ||
|
|
bd1d4289c0 | ||
|
|
5d2139471a | ||
|
|
d49a64ac1e | ||
|
|
cd867ea581 | ||
|
|
32fd62c484 | ||
|
|
f2c561bd15 | ||
|
|
80734944d3 | ||
|
|
b3afa9f595 | ||
|
|
656558850c | ||
|
|
e41cca9be0 | ||
|
|
46916b34d4 | ||
|
|
4f9ca3e74d | ||
|
|
2bcdd0f52b | ||
|
|
56d790dda9 | ||
|
|
149013d2ff | ||
|
|
776807580a | ||
|
|
75e9eee3a9 | ||
|
|
183615fa7b | ||
|
|
7405fbaa16 | ||
|
|
22743b6d8b | ||
|
|
b5864f02cb | ||
|
|
373431fb1a | ||
|
|
29167fbdf2 | ||
|
|
699ac3a8e6 | ||
|
|
d7b572faaf | ||
|
|
a09b4e7f2c | ||
|
|
a794420d3e | ||
|
|
8b606266c5 | ||
|
|
11e4329d5e | ||
|
|
68dfc6ca81 | ||
|
|
e0c8945431 | ||
|
|
fe60ee00fb | ||
|
|
5990e00577 | ||
|
|
358a699290 | ||
|
|
da6e4378d9 | ||
|
|
5edb0629b3 | ||
|
|
5170854a2c | ||
|
|
37d6033df4 | ||
|
|
ea2f891533 | ||
|
|
42cec7d5ba | ||
|
|
2df2e39d43 | ||
|
|
b34525a4d8 | ||
|
|
0a7bd64b0d | ||
|
|
11fd4f88ec | ||
|
|
4d9452b862 | ||
|
|
060e30e612 | ||
|
|
ade7270add | ||
|
|
338428b0c0 | ||
|
|
54574e4450 | ||
|
|
ae564451b8 | ||
|
|
9a4504ce61 | ||
|
|
80785a2ff3 | ||
|
|
cb8ed02e82 | ||
|
|
a64c1b8eab | ||
|
|
d43aa169c3 | ||
|
|
8ae7141851 | ||
|
|
d3908db2c9 | ||
|
|
55de838a55 | ||
|
|
4cdfc38b87 | ||
|
|
51197d7c1a | ||
|
|
2a2a2e0c05 | ||
|
|
07fee30cc0 | ||
|
|
83c6ce0ace | ||
|
|
fb7303efa0 | ||
|
|
ef5585d312 | ||
|
|
11475259a1 | ||
|
|
9df4cd6f13 | ||
|
|
c9583964c8 |
@@ -2,5 +2,5 @@
|
||||
; SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
[BlueprintSettings]
|
||||
kde/frameworks/extra-cmake-modules.version=master
|
||||
kde/applications/neochat.packageAppx=True
|
||||
libs/qt.qtMajorVersion=6
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/quotient-im/libQuotient.git",
|
||||
"branch": "0.8.x",
|
||||
"tag": "0.9.2",
|
||||
"disable-submodules": true
|
||||
}
|
||||
],
|
||||
|
||||
@@ -10,6 +10,8 @@ include:
|
||||
- /gitlab-templates/windows-qt6.yml
|
||||
# - /gitlab-templates/freebsd-qt6.yml
|
||||
- /gitlab-templates/flatpak.yml
|
||||
- /gitlab-templates/snap-snapcraft-lxd.yml
|
||||
- /gitlab-templates/craft-android-qt6-apks.yml
|
||||
- /gitlab-templates/craft-appimage-qt6.yml
|
||||
- /gitlab-templates/craft-windows-x86-64-qt6.yml
|
||||
- /gitlab-templates/craft-windows-appx-qt6.yml
|
||||
|
||||
@@ -14,6 +14,7 @@ Dependencies:
|
||||
'frameworks/kquickcharts': '@latest-kf6'
|
||||
'frameworks/knotifications': '@latest-kf6'
|
||||
'frameworks/kcolorscheme': '@latest-kf6'
|
||||
'frameworks/kiconthemes': '@latest-kf6'
|
||||
'libraries/kquickimageeditor': '@latest-kf6'
|
||||
'frameworks/sonnet': '@latest-kf6'
|
||||
'frameworks/prison': '@latest-kf6'
|
||||
|
||||
@@ -8,13 +8,13 @@ cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# KDE Applications version, managed by release script.
|
||||
set(RELEASE_SERVICE_VERSION_MAJOR "24")
|
||||
set(RELEASE_SERVICE_VERSION_MINOR "08")
|
||||
set(RELEASE_SERVICE_VERSION_MICRO "3")
|
||||
set(RELEASE_SERVICE_VERSION_MINOR "12")
|
||||
set(RELEASE_SERVICE_VERSION_MICRO "2")
|
||||
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||
|
||||
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
|
||||
|
||||
set(KF_MIN_VERSION "6.0")
|
||||
set(KF_MIN_VERSION "6.6")
|
||||
set(QT_MIN_VERSION "6.5")
|
||||
|
||||
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
|
||||
@@ -39,6 +39,8 @@ include(ECMCheckOutboundLicense)
|
||||
include(ECMQtDeclareLoggingCategory)
|
||||
include(ECMAddAndroidApk)
|
||||
include(ECMQmlModule)
|
||||
include(GenerateExportHeader)
|
||||
include(ECMGenerateHeaders)
|
||||
if (NOT ANDROID)
|
||||
include(KDEClangFormat)
|
||||
endif()
|
||||
@@ -64,7 +66,7 @@ if (QT_KNOWN_POLICY_QTP0004)
|
||||
qt_policy(SET QTP0004 NEW)
|
||||
endif ()
|
||||
|
||||
find_package(KF6 ${KF_MIN_VERSION} COMPONENTS Kirigami I18n Notifications Config CoreAddons Sonnet ItemModels ColorScheme)
|
||||
find_package(KF6 ${KF_MIN_VERSION} COMPONENTS Kirigami I18n Notifications Config CoreAddons Sonnet ItemModels IconThemes ColorScheme)
|
||||
set_package_properties(KF6 PROPERTIES
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Basic application components"
|
||||
@@ -101,11 +103,11 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE AND NOT HAIKU)
|
||||
find_package(KF6DBusAddons ${KF_MIN_VERSION} REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(QuotientQt6 0.8.2)
|
||||
find_package(QuotientQt6 0.9)
|
||||
set_package_properties(QuotientQt6 PROPERTIES
|
||||
TYPE REQUIRED
|
||||
DESCRIPTION "Qt wrapper around Matrix API"
|
||||
@@ -113,11 +115,6 @@ set_package_properties(QuotientQt6 PROPERTIES
|
||||
PURPOSE "Talk with matrix server"
|
||||
)
|
||||
|
||||
if (NOT TARGET Olm::Olm)
|
||||
message(FATAL_ERROR "NeoChat requires Quotient with the E2EE feature enabled")
|
||||
endif()
|
||||
|
||||
|
||||
find_package(cmark)
|
||||
set_package_properties(cmark PROPERTIES
|
||||
TYPE REQUIRED
|
||||
|
||||
@@ -11,7 +11,7 @@ A Qt/QML based Matrix client.
|
||||
|
||||
<a href='https://matrix.org'><img src='https://matrix.org/docs/legacy/made-for-matrix.png' alt='Made for Matrix' height=64 target=_blank /></a>
|
||||
<a href='https://flathub.org/apps/details/org.kde.neochat'><img width='190px' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-i-en.png'/></a>
|
||||
<a href='https://snapcraft.io/neochat'><img width='190px' alt='Download on the Snap Store' src='https://snapcraft.io/static/images/badges/en/snap-store-black.svg'/></a>
|
||||
<a href='https://snapcraft.io/neochat'><img width='190px' alt='Download on the Snap Store' src='https://apps.kde.org/store_badges/snapstore/en.svg'/></a>
|
||||
|
||||
## Introduction
|
||||
|
||||
|
||||
@@ -55,5 +55,6 @@
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <!-- for Android >= 33 -->
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -12,7 +12,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.4.1'
|
||||
classpath 'com.android.tools.build:gradle:8.6.0'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,26 @@
|
||||
"!room_id_1234:localhost:1234": {
|
||||
"state": {
|
||||
"events": [
|
||||
{
|
||||
"content": {
|
||||
"m.federate": true,
|
||||
"predecessor": {
|
||||
"event_id": "$something:example.org",
|
||||
"room_id": "!oldroom:example.org"
|
||||
},
|
||||
"room_version": "11"
|
||||
},
|
||||
"event_id": "$143273582443PhrSn:example.org",
|
||||
"origin_server_ts": 1432735824653,
|
||||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||
"sender": "@example:example.org",
|
||||
"state_key": "",
|
||||
"type": "m.room.create",
|
||||
"unsigned": {
|
||||
"age": 1234,
|
||||
"membership": "join"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "m.room.member",
|
||||
"state_key": "@user:localhost:1234",
|
||||
@@ -26,6 +46,26 @@
|
||||
},
|
||||
"timeline": {
|
||||
"events": [
|
||||
{
|
||||
"content": {
|
||||
"m.federate": true,
|
||||
"predecessor": {
|
||||
"event_id": "$something:example.org",
|
||||
"room_id": "!oldroom:example.org"
|
||||
},
|
||||
"room_version": "11"
|
||||
},
|
||||
"event_id": "$143273582443PhrSn:example.org",
|
||||
"origin_server_ts": 1432735824653,
|
||||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||
"sender": "@example:example.org",
|
||||
"state_key": "",
|
||||
"type": "m.room.create",
|
||||
"unsigned": {
|
||||
"age": 1234,
|
||||
"membership": "join"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "m.room.message",
|
||||
"sender": "@user:localhost:1234",
|
||||
|
||||
@@ -11,11 +11,11 @@ ecm_add_test(
|
||||
TEST_NAME neochatroomtest
|
||||
)
|
||||
|
||||
ecm_add_test(
|
||||
texthandlertest.cpp
|
||||
LINK_LIBRARIES neochat Qt::Test
|
||||
TEST_NAME texthandlertest
|
||||
)
|
||||
# ecm_add_test(
|
||||
# texthandlertest.cpp
|
||||
# LINK_LIBRARIES neochat Qt::Test
|
||||
# TEST_NAME texthandlertest
|
||||
# )
|
||||
|
||||
ecm_add_test(
|
||||
delegatesizehelpertest.cpp
|
||||
@@ -53,12 +53,6 @@ ecm_add_test(
|
||||
TEST_NAME messageeventmodeltest
|
||||
)
|
||||
|
||||
ecm_add_test(
|
||||
actionshandlertest.cpp
|
||||
LINK_LIBRARIES neochat Qt::Test
|
||||
TEST_NAME actionshandlertest
|
||||
)
|
||||
|
||||
ecm_add_test(
|
||||
windowcontrollertest.cpp
|
||||
LINK_LIBRARIES neochat Qt::Test
|
||||
@@ -82,3 +76,9 @@ ecm_add_test(
|
||||
LINK_LIBRARIES neochat Qt::Test
|
||||
TEST_NAME linkpreviewertest
|
||||
)
|
||||
|
||||
ecm_add_test(
|
||||
messagecontentmodeltest.cpp
|
||||
LINK_LIBRARIES neochat Qt::Test
|
||||
TEST_NAME messagecontentmodeltest
|
||||
)
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include <QTest>
|
||||
|
||||
#include "actionshandler.h"
|
||||
#include "chatbarcache.h"
|
||||
|
||||
#include "testutils.h"
|
||||
|
||||
class ActionsHandlerTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
Quotient::Connection *connection = Quotient::Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
|
||||
ActionsHandler *actionsHandler = new ActionsHandler(this);
|
||||
|
||||
private Q_SLOTS:
|
||||
void nullObject();
|
||||
};
|
||||
|
||||
void ActionsHandlerTest::nullObject()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "ActionsHandler::handleMessageEvent - called with m_room and/or chatBarCache set to nullptr.");
|
||||
actionsHandler->handleMessageEvent(nullptr);
|
||||
|
||||
auto chatBarCache = new ChatBarCache(this);
|
||||
QTest::ignoreMessage(QtWarningMsg, "ActionsHandler::handleMessageEvent - called with m_room and/or chatBarCache set to nullptr.");
|
||||
actionsHandler->handleMessageEvent(chatBarCache);
|
||||
|
||||
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"));
|
||||
actionsHandler->setRoom(room);
|
||||
QTest::ignoreMessage(QtWarningMsg, "ActionsHandler::handleMessageEvent - called with m_room and/or chatBarCache set to nullptr.");
|
||||
actionsHandler->handleMessageEvent(nullptr);
|
||||
|
||||
// The final one should throw no warning so we make sure.
|
||||
QTest::failOnWarning("ActionsHandler::handleMessageEvent - called with m_room and/or chatBarCache set to nullptr.");
|
||||
actionsHandler->handleMessageEvent(chatBarCache);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(ActionsHandlerTest)
|
||||
#include "actionshandlertest.moc"
|
||||
@@ -51,7 +51,7 @@ void ChatBarCacheTest::empty()
|
||||
QCOMPARE(chatBarCache->replyId(), QString());
|
||||
QCOMPARE(chatBarCache->isEditing(), false);
|
||||
QCOMPARE(chatBarCache->editId(), QString());
|
||||
QCOMPARE(chatBarCache->relationUser(), room->member(QString()));
|
||||
QCOMPARE(chatBarCache->relationAuthor(), room->member(QString()));
|
||||
QCOMPARE(chatBarCache->relationMessage(), QString());
|
||||
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
||||
}
|
||||
@@ -65,7 +65,7 @@ void ChatBarCacheTest::noRoom()
|
||||
// ChatBarCache has no parent.
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.");
|
||||
QCOMPARE(chatBarCache->relationUser(), Quotient::RoomMember());
|
||||
QCOMPARE(chatBarCache->relationAuthor(), Quotient::RoomMember());
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.");
|
||||
QCOMPARE(chatBarCache->relationMessage(), QString());
|
||||
@@ -81,7 +81,7 @@ void ChatBarCacheTest::badParent()
|
||||
// ChatBarCache has no parent.
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.");
|
||||
QCOMPARE(chatBarCache->relationUser(), Quotient::RoomMember());
|
||||
QCOMPARE(chatBarCache->relationAuthor(), Quotient::RoomMember());
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.");
|
||||
QCOMPARE(chatBarCache->relationMessage(), QString());
|
||||
@@ -99,7 +99,7 @@ void ChatBarCacheTest::reply()
|
||||
QCOMPARE(chatBarCache->replyId(), QLatin1String("$153456789:example.org"));
|
||||
QCOMPARE(chatBarCache->isEditing(), false);
|
||||
QCOMPARE(chatBarCache->editId(), QString());
|
||||
QCOMPARE(chatBarCache->relationUser(), room->member(QLatin1String("@example:example.org")));
|
||||
QCOMPARE(chatBarCache->relationAuthor(), room->member(QLatin1String("@example:example.org")));
|
||||
QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message"));
|
||||
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
||||
}
|
||||
@@ -107,8 +107,13 @@ void ChatBarCacheTest::reply()
|
||||
void ChatBarCacheTest::edit()
|
||||
{
|
||||
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
|
||||
|
||||
chatBarCache->setText(QLatin1String("some text"));
|
||||
chatBarCache->setAttachmentPath(QLatin1String("some/path"));
|
||||
connect(chatBarCache.get(), &ChatBarCache::relationIdChanged, this, [](const QString &oldEventId, const QString &newEventId) {
|
||||
QCOMPARE(oldEventId, QString());
|
||||
QCOMPARE(newEventId, QString(QLatin1String("$153456789:example.org")));
|
||||
});
|
||||
chatBarCache->setEditId(QLatin1String("$153456789:example.org"));
|
||||
|
||||
QCOMPARE(chatBarCache->text(), QLatin1String("some text"));
|
||||
@@ -116,7 +121,7 @@ void ChatBarCacheTest::edit()
|
||||
QCOMPARE(chatBarCache->replyId(), QString());
|
||||
QCOMPARE(chatBarCache->isEditing(), true);
|
||||
QCOMPARE(chatBarCache->editId(), QLatin1String("$153456789:example.org"));
|
||||
QCOMPARE(chatBarCache->relationUser(), room->member(QLatin1String("@example:example.org")));
|
||||
QCOMPARE(chatBarCache->relationAuthor(), room->member(QLatin1String("@example:example.org")));
|
||||
QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message"));
|
||||
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
||||
}
|
||||
@@ -133,7 +138,7 @@ void ChatBarCacheTest::attachment()
|
||||
QCOMPARE(chatBarCache->replyId(), QString());
|
||||
QCOMPARE(chatBarCache->isEditing(), false);
|
||||
QCOMPARE(chatBarCache->editId(), QString());
|
||||
QCOMPARE(chatBarCache->relationUser(), room->member(QString()));
|
||||
QCOMPARE(chatBarCache->relationAuthor(), room->member(QString()));
|
||||
QCOMPARE(chatBarCache->relationMessage(), QString());
|
||||
QCOMPARE(chatBarCache->attachmentPath(), QLatin1String("some/path"));
|
||||
}
|
||||
|
||||
@@ -29,8 +29,6 @@ private:
|
||||
Connection *connection = nullptr;
|
||||
TestUtils::TestRoom *room = nullptr;
|
||||
|
||||
EventHandler emptyHandler = EventHandler(nullptr, nullptr);
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
|
||||
@@ -43,7 +41,6 @@ private Q_SLOTS:
|
||||
void time();
|
||||
void nullTime();
|
||||
void timeString();
|
||||
void nullTimeString();
|
||||
void highlighted();
|
||||
void nullHighlighted();
|
||||
void hidden();
|
||||
@@ -65,10 +62,6 @@ private Q_SLOTS:
|
||||
void nullReplyId();
|
||||
void replyAuthor();
|
||||
void nullReplyAuthor();
|
||||
void replyBody();
|
||||
void nullReplyBody();
|
||||
void replyMediaInfo();
|
||||
void nullReplyMediaInfo();
|
||||
void thread();
|
||||
void nullThread();
|
||||
void location();
|
||||
@@ -83,157 +76,136 @@ void EventHandlerTest::initTestCase()
|
||||
|
||||
void EventHandlerTest::eventId()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(0).get());
|
||||
QCOMPARE(eventHandler.getId(), QStringLiteral("$153456789:example.org"));
|
||||
QCOMPARE(EventHandler::id(room->messageEvents().at(0).get()), QStringLiteral("$153456789:example.org"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullEventId()
|
||||
{
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getId called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getId(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "id called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::id(nullptr), QString());
|
||||
}
|
||||
|
||||
void EventHandlerTest::authorDisplayName()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(1).get());
|
||||
QCOMPARE(eventHandler.getAuthorDisplayName(), QStringLiteral("before"));
|
||||
QCOMPARE(EventHandler::authorDisplayName(room, room->messageEvents().at(1).get()), QStringLiteral("before"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullAuthorDisplayName()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_room set to nullptr.");
|
||||
QCOMPARE(emptyHandler.getAuthorDisplayName(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "authorDisplayName called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::authorDisplayName(nullptr, nullptr), QString());
|
||||
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getAuthorDisplayName(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "authorDisplayName called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::authorDisplayName(room, nullptr), QString());
|
||||
}
|
||||
|
||||
void EventHandlerTest::singleLineSidplayName()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(11).get());
|
||||
QCOMPARE(eventHandler.singleLineAuthorDisplayname(), QStringLiteral("Look at me I put newlines in my display name"));
|
||||
QCOMPARE(EventHandler::singleLineAuthorDisplayname(room, room->messageEvents().at(11).get()),
|
||||
QStringLiteral("Look at me I put newlines in my display name"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullSingleLineDisplayName()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_room set to nullptr.");
|
||||
QCOMPARE(emptyHandler.singleLineAuthorDisplayname(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "singleLineAuthorDisplayname called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::singleLineAuthorDisplayname(nullptr, nullptr), QString());
|
||||
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.singleLineAuthorDisplayname(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "singleLineAuthorDisplayname called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::singleLineAuthorDisplayname(room, nullptr), QString());
|
||||
}
|
||||
|
||||
void EventHandlerTest::time()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(0).get());
|
||||
const auto event = room->messageEvents().at(0).get();
|
||||
|
||||
QCOMPARE(eventHandler.getTime(), QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC));
|
||||
QCOMPARE(eventHandler.getTime(true, QDateTime::fromMSecsSinceEpoch(1234, Qt::UTC)), QDateTime::fromMSecsSinceEpoch(1234, Qt::UTC));
|
||||
QCOMPARE(EventHandler::time(event), QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC));
|
||||
QCOMPARE(EventHandler::time(event, true, QDateTime::fromMSecsSinceEpoch(1234, Qt::UTC)), QDateTime::fromMSecsSinceEpoch(1234, Qt::UTC));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullTime()
|
||||
{
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getTime called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getTime(), QDateTime());
|
||||
QTest::ignoreMessage(QtWarningMsg, "time called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::time(nullptr), QDateTime());
|
||||
|
||||
EventHandler eventHandler(room, room->messageEvents().at(0).get());
|
||||
QTest::ignoreMessage(QtWarningMsg, "a value must be provided for lastUpdated for a pending event.");
|
||||
QCOMPARE(eventHandler.getTime(true), QDateTime());
|
||||
QCOMPARE(EventHandler::time(room->messageEvents().at(0).get(), true), QDateTime());
|
||||
}
|
||||
|
||||
void EventHandlerTest::timeString()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(0).get());
|
||||
const auto event = room->messageEvents().at(0).get();
|
||||
|
||||
KFormat format;
|
||||
|
||||
QCOMPARE(eventHandler.getTimeString(false),
|
||||
QCOMPARE(EventHandler::timeString(event, false),
|
||||
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC).toLocalTime().time(), QLocale::ShortFormat));
|
||||
QCOMPARE(eventHandler.getTimeString(true),
|
||||
QCOMPARE(EventHandler::timeString(event, true),
|
||||
format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC).toLocalTime().date(), QLocale::ShortFormat));
|
||||
QCOMPARE(eventHandler.getTimeString(false, QLocale::ShortFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
||||
QCOMPARE(EventHandler::timeString(event, false, QLocale::ShortFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
||||
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC).toLocalTime().time(), QLocale::ShortFormat));
|
||||
QCOMPARE(eventHandler.getTimeString(true, QLocale::ShortFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
||||
QCOMPARE(EventHandler::timeString(event, true, QLocale::ShortFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
||||
format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC).toLocalTime().date(), QLocale::ShortFormat));
|
||||
QCOMPARE(eventHandler.getTimeString(false, QLocale::LongFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
||||
QCOMPARE(EventHandler::timeString(event, false, QLocale::LongFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
||||
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC).toLocalTime().time(), QLocale::LongFormat));
|
||||
QCOMPARE(eventHandler.getTimeString(true, QLocale::LongFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
||||
QCOMPARE(EventHandler::timeString(event, true, QLocale::LongFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
||||
format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC).toLocalTime().date(), QLocale::LongFormat));
|
||||
QCOMPARE(eventHandler.getTimeString(QStringLiteral("hh:mm")), QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC).toString(QStringLiteral("hh:mm")));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullTimeString()
|
||||
{
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getTimeString called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getTimeString(false), QString());
|
||||
|
||||
EventHandler eventHandler(room, room->messageEvents().at(0).get());
|
||||
QTest::ignoreMessage(QtWarningMsg, "a value must be provided for lastUpdated for a pending event.");
|
||||
QCOMPARE(eventHandler.getTimeString(false, QLocale::ShortFormat, true), QString());
|
||||
QCOMPARE(EventHandler::timeString(event, QStringLiteral("hh:mm")),
|
||||
QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC).toString(QStringLiteral("hh:mm")));
|
||||
}
|
||||
|
||||
void EventHandlerTest::highlighted()
|
||||
{
|
||||
EventHandler eventHandlerHighlight(room, room->messageEvents().at(2).get());
|
||||
QCOMPARE(eventHandlerHighlight.isHighlighted(), true);
|
||||
|
||||
EventHandler eventHandlerNoHighlight(room, room->messageEvents().at(0).get());
|
||||
QCOMPARE(eventHandlerNoHighlight.isHighlighted(), false);
|
||||
QCOMPARE(EventHandler::isHighlighted(room, room->messageEvents().at(2).get()), true);
|
||||
QCOMPARE(EventHandler::isHighlighted(room, room->messageEvents().at(0).get()), false);
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullHighlighted()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with m_room set to nullptr.");
|
||||
QCOMPARE(emptyHandler.isHighlighted(), false);
|
||||
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::isHighlighted(nullptr, nullptr), false);
|
||||
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.isHighlighted(), false);
|
||||
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::isHighlighted(room, nullptr), false);
|
||||
}
|
||||
|
||||
void EventHandlerTest::hidden()
|
||||
{
|
||||
EventHandler eventHandlerHidden(room, room->messageEvents().at(3).get());
|
||||
QCOMPARE(eventHandlerHidden.isHidden(), true);
|
||||
|
||||
EventHandler eventHandlerNoHidden(room, room->messageEvents().at(0).get());
|
||||
QCOMPARE(eventHandlerNoHidden.isHidden(), false);
|
||||
QCOMPARE(EventHandler::isHidden(room, room->messageEvents().at(3).get()), true);
|
||||
QCOMPARE(EventHandler::isHidden(room, room->messageEvents().at(0).get()), false);
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullHidden()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "isHidden called with m_room set to nullptr.");
|
||||
QCOMPARE(emptyHandler.isHidden(), false);
|
||||
QTest::ignoreMessage(QtWarningMsg, "isHidden called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::isHidden(nullptr, nullptr), false);
|
||||
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "isHidden called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.isHidden(), false);
|
||||
QTest::ignoreMessage(QtWarningMsg, "isHidden called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::isHidden(room, nullptr), false);
|
||||
}
|
||||
|
||||
void EventHandlerTest::body()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(0).get());
|
||||
const auto event = room->messageEvents().at(0).get();
|
||||
|
||||
QCOMPARE(eventHandler.getRichBody(), QStringLiteral("<b>This is an example<br>text message</b>"));
|
||||
QCOMPARE(eventHandler.getRichBody(true), QStringLiteral("<b>This is an example text message</b>"));
|
||||
QCOMPARE(eventHandler.getPlainBody(), QStringLiteral("This is an example\ntext message"));
|
||||
QCOMPARE(eventHandler.getPlainBody(true), QStringLiteral("This is an example text message"));
|
||||
QCOMPARE(EventHandler::richBody(room, event), QStringLiteral("<b>This is an example<br>text message</b>"));
|
||||
QCOMPARE(EventHandler::richBody(room, event, true), QStringLiteral("<b>This is an example text message</b>"));
|
||||
QCOMPARE(EventHandler::plainBody(room, event), QStringLiteral("This is an example\ntext message"));
|
||||
QCOMPARE(EventHandler::plainBody(room, event, true), QStringLiteral("This is an example text message"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullBody()
|
||||
{
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "richBody called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::richBody(nullptr, nullptr), QString());
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "getRichBody called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getRichBody(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "richBody called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::richBody(room, nullptr), QString());
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "getPlainBody called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getPlainBody(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "plainBody called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::plainBody(nullptr, nullptr), QString());
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "plainBody called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::plainBody(room, nullptr), QString());
|
||||
}
|
||||
|
||||
void EventHandlerTest::genericBody_data()
|
||||
@@ -241,11 +213,13 @@ void EventHandlerTest::genericBody_data()
|
||||
QTest::addColumn<int>("eventNum");
|
||||
QTest::addColumn<QString>("output");
|
||||
|
||||
QTest::newRow("message") << 0 << QStringLiteral("sent a message");
|
||||
QTest::newRow("member") << 1 << QStringLiteral("changed their display name and updated their avatar");
|
||||
QTest::newRow("message 2") << 2 << QStringLiteral("sent a message");
|
||||
QTest::newRow("message") << 0 << QStringLiteral("<a href=\"https://matrix.to/#/@example:example.org\">after</a> sent a message");
|
||||
QTest::newRow("member") << 1
|
||||
<< QStringLiteral(
|
||||
"<a href=\"https://matrix.to/#/@example:example.org\">after</a> changed their display name and updated their avatar");
|
||||
QTest::newRow("message 2") << 2 << QStringLiteral("<a href=\"https://matrix.to/#/@example:example.org\">after</a> sent a message");
|
||||
QTest::newRow("reaction") << 3 << QStringLiteral("Unknown event");
|
||||
QTest::newRow("video") << 4 << QStringLiteral("sent a message");
|
||||
QTest::newRow("video") << 4 << QStringLiteral("<a href=\"https://matrix.to/#/@example:example.org\">after</a> sent a message");
|
||||
}
|
||||
|
||||
void EventHandlerTest::genericBody()
|
||||
@@ -253,54 +227,48 @@ void EventHandlerTest::genericBody()
|
||||
QFETCH(int, eventNum);
|
||||
QFETCH(QString, output);
|
||||
|
||||
EventHandler eventHandler(room, room->messageEvents().at(eventNum).get());
|
||||
|
||||
QCOMPARE(eventHandler.getGenericBody(), output);
|
||||
QCOMPARE(EventHandler::genericBody(room, room->messageEvents().at(eventNum).get()), output);
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullGenericBody()
|
||||
{
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getGenericBody called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getGenericBody(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "genericBody called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::genericBody(nullptr, nullptr), QString());
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "genericBody called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::genericBody(room, nullptr), QString());
|
||||
}
|
||||
|
||||
void EventHandlerTest::markdownBody()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(0).get());
|
||||
|
||||
QCOMPARE(eventHandler.getMarkdownBody(), QStringLiteral("This is an example\ntext message"));
|
||||
QCOMPARE(EventHandler::markdownBody(room->messageEvents().at(0).get()), QStringLiteral("This is an example\ntext message"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::markdownBodyReply()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(5).get());
|
||||
|
||||
QCOMPARE(eventHandler.getMarkdownBody(), QStringLiteral("reply"));
|
||||
QCOMPARE(EventHandler::markdownBody(room->messageEvents().at(5).get()), QStringLiteral("reply"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::subtitle()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(0).get());
|
||||
QCOMPARE(eventHandler.subtitleText(), QStringLiteral("after: This is an example text message"));
|
||||
|
||||
EventHandler eventHandler2(room, room->messageEvents().at(2).get());
|
||||
QCOMPARE(eventHandler2.subtitleText(), QStringLiteral("after: This is a highlight @bob:kde.org and this is a link https://kde.org"));
|
||||
QCOMPARE(EventHandler::subtitleText(room, room->messageEvents().at(0).get()), QStringLiteral("after: This is an example text message"));
|
||||
QCOMPARE(EventHandler::subtitleText(room, room->messageEvents().at(2).get()),
|
||||
QStringLiteral("after: This is a highlight @bob:kde.org and this is a link https://kde.org"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullSubtitle()
|
||||
{
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "subtitleText called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.subtitleText(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "subtitleText called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::subtitleText(nullptr, nullptr), QString());
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "subtitleText called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::subtitleText(room, nullptr), QString());
|
||||
}
|
||||
|
||||
void EventHandlerTest::mediaInfo()
|
||||
{
|
||||
auto event = room->messageEvents().at(4).get();
|
||||
EventHandler eventHandler(room, event);
|
||||
|
||||
auto mediaInfo = eventHandler.getMediaInfo();
|
||||
auto mediaInfo = EventHandler::mediaInfo(room, event);
|
||||
auto thumbnailInfo = mediaInfo["tempInfo"_ls].toMap();
|
||||
|
||||
QCOMPARE(mediaInfo["source"_ls], room->makeMediaUrl(event->id(), QUrl("mxc://kde.org/1234567"_ls)));
|
||||
@@ -320,53 +288,42 @@ void EventHandlerTest::mediaInfo()
|
||||
|
||||
void EventHandlerTest::nullMediaInfo()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "getMediaInfo called with m_room set to nullptr.");
|
||||
QCOMPARE(emptyHandler.getMediaInfo(), QVariantMap());
|
||||
QTest::ignoreMessage(QtWarningMsg, "mediaInfo called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::mediaInfo(nullptr, nullptr), QVariantMap());
|
||||
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getMediaInfo called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getMediaInfo(), QVariantMap());
|
||||
QTest::ignoreMessage(QtWarningMsg, "mediaInfo called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::mediaInfo(room, nullptr), QVariantMap());
|
||||
}
|
||||
|
||||
void EventHandlerTest::hasReply()
|
||||
{
|
||||
EventHandler eventHandlerReply(room, room->messageEvents().at(5).get());
|
||||
QCOMPARE(eventHandlerReply.hasReply(), true);
|
||||
|
||||
EventHandler eventHandlerNoReply(room, room->messageEvents().at(0).get());
|
||||
QCOMPARE(eventHandlerNoReply.hasReply(), false);
|
||||
QCOMPARE(EventHandler::hasReply(room->messageEvents().at(5).get()), true);
|
||||
QCOMPARE(EventHandler::hasReply(room->messageEvents().at(0).get()), false);
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullHasReply()
|
||||
{
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "hasReply called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.hasReply(), false);
|
||||
QTest::ignoreMessage(QtWarningMsg, "hasReply called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::hasReply(nullptr), false);
|
||||
}
|
||||
|
||||
void EventHandlerTest::replyId()
|
||||
{
|
||||
EventHandler eventHandlerReply(room, room->messageEvents().at(5).get());
|
||||
QCOMPARE(eventHandlerReply.getReplyId(), QStringLiteral("$153456789:example.org"));
|
||||
|
||||
EventHandler eventHandlerNoReply(room, room->messageEvents().at(0).get());
|
||||
QCOMPARE(eventHandlerNoReply.getReplyId(), QStringLiteral(""));
|
||||
QCOMPARE(EventHandler::replyId(room->messageEvents().at(5).get()), QStringLiteral("$153456789:example.org"));
|
||||
QCOMPARE(EventHandler::replyId(room->messageEvents().at(0).get()), QStringLiteral(""));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullReplyId()
|
||||
{
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getReplyId called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getReplyId(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "replyId called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::replyId(nullptr), QString());
|
||||
}
|
||||
|
||||
void EventHandlerTest::replyAuthor()
|
||||
{
|
||||
auto replyEvent = room->messageEvents().at(0).get();
|
||||
auto replyAuthor = room->member(replyEvent->senderId());
|
||||
EventHandler eventHandler(room, room->messageEvents().at(5).get());
|
||||
|
||||
auto eventHandlerReplyAuthor = eventHandler.getReplyAuthor();
|
||||
auto eventHandlerReplyAuthor = EventHandler::replyAuthor(room, room->messageEvents().at(5).get());
|
||||
|
||||
QCOMPARE(eventHandlerReplyAuthor.isLocalMember(), replyAuthor.id() == room->localMember().id());
|
||||
QCOMPARE(eventHandlerReplyAuthor.id(), replyAuthor.id());
|
||||
@@ -375,121 +332,58 @@ void EventHandlerTest::replyAuthor()
|
||||
QCOMPARE(eventHandlerReplyAuthor.avatarMediaId(), replyAuthor.avatarMediaId());
|
||||
QCOMPARE(eventHandlerReplyAuthor.color(), replyAuthor.color());
|
||||
|
||||
EventHandler eventHandlerNoAuthor(room, room->messageEvents().at(0).get());
|
||||
QCOMPARE(eventHandlerNoAuthor.getReplyAuthor(), RoomMember());
|
||||
QCOMPARE(EventHandler::replyAuthor(room, room->messageEvents().at(0).get()), RoomMember());
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullReplyAuthor()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "getReplyAuthor called with m_room set to nullptr.");
|
||||
QCOMPARE(emptyHandler.getReplyAuthor(), RoomMember());
|
||||
QTest::ignoreMessage(QtWarningMsg, "replyAuthor called with room set to nullptr.");
|
||||
QCOMPARE(EventHandler::replyAuthor(nullptr, nullptr), RoomMember());
|
||||
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getReplyAuthor called with m_event set to nullptr. Returning empty user.");
|
||||
QCOMPARE(noEventHandler.getReplyAuthor(), RoomMember());
|
||||
}
|
||||
|
||||
void EventHandlerTest::replyBody()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(5).get());
|
||||
|
||||
QCOMPARE(eventHandler.getReplyRichBody(), QStringLiteral("<b>This is an example<br>text message</b>"));
|
||||
QCOMPARE(eventHandler.getReplyRichBody(true), QStringLiteral("<b>This is an example text message</b>"));
|
||||
QCOMPARE(eventHandler.getReplyPlainBody(), QStringLiteral("This is an example\ntext message"));
|
||||
QCOMPARE(eventHandler.getReplyPlainBody(true), QStringLiteral("This is an example text message"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullReplyBody()
|
||||
{
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "getReplyRichBody called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getReplyRichBody(), QString());
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "getReplyPlainBody called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getReplyPlainBody(), QString());
|
||||
}
|
||||
|
||||
void EventHandlerTest::replyMediaInfo()
|
||||
{
|
||||
auto event = room->messageEvents().at(6).get();
|
||||
auto replyEvent = room->messageEvents().at(4).get();
|
||||
EventHandler eventHandler(room, event);
|
||||
|
||||
auto mediaInfo = eventHandler.getReplyMediaInfo();
|
||||
auto thumbnailInfo = mediaInfo["tempInfo"_ls].toMap();
|
||||
|
||||
QCOMPARE(mediaInfo["source"_ls], room->makeMediaUrl(replyEvent->id(), QUrl("mxc://kde.org/1234567"_ls)));
|
||||
QCOMPARE(mediaInfo["mimeType"_ls], QStringLiteral("video/mp4"));
|
||||
QCOMPARE(mediaInfo["mimeIcon"_ls], QStringLiteral("video-mp4"));
|
||||
QCOMPARE(mediaInfo["size"_ls], 62650636);
|
||||
QCOMPARE(mediaInfo["duration"_ls], 10);
|
||||
QCOMPARE(mediaInfo["width"_ls], 1920);
|
||||
QCOMPARE(mediaInfo["height"_ls], 1080);
|
||||
QCOMPARE(thumbnailInfo["source"_ls], room->makeMediaUrl(replyEvent->id(), QUrl("mxc://kde.org/2234567"_ls)));
|
||||
QCOMPARE(thumbnailInfo["mimeType"_ls], QStringLiteral("image/jpeg"));
|
||||
QCOMPARE(thumbnailInfo["mimeIcon"_ls], QStringLiteral("image-jpeg"));
|
||||
QCOMPARE(thumbnailInfo["size"_ls], 382249);
|
||||
QCOMPARE(thumbnailInfo["width"_ls], 800);
|
||||
QCOMPARE(thumbnailInfo["height"_ls], 450);
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullReplyMediaInfo()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "getReplyMediaInfo called with m_room set to nullptr.");
|
||||
QCOMPARE(emptyHandler.getReplyMediaInfo(), QVariantMap());
|
||||
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "getReplyMediaInfo called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.getReplyMediaInfo(), QVariantMap());
|
||||
QTest::ignoreMessage(QtWarningMsg, "replyAuthor called with event set to nullptr. Returning empty user.");
|
||||
QCOMPARE(EventHandler::replyAuthor(room, nullptr), RoomMember());
|
||||
}
|
||||
|
||||
void EventHandlerTest::thread()
|
||||
{
|
||||
EventHandler eventHandlerNoThread(room, room->messageEvents().at(0).get());
|
||||
QCOMPARE(eventHandlerNoThread.isThreaded(), false);
|
||||
QCOMPARE(eventHandlerNoThread.threadRoot(), QString());
|
||||
QCOMPARE(EventHandler::isThreaded(room->messageEvents().at(0).get()), false);
|
||||
QCOMPARE(EventHandler::threadRoot(room->messageEvents().at(0).get()), QString());
|
||||
|
||||
EventHandler eventHandlerThreadRoot(room, room->messageEvents().at(9).get());
|
||||
QCOMPARE(eventHandlerThreadRoot.isThreaded(), true);
|
||||
QCOMPARE(eventHandlerThreadRoot.threadRoot(), QStringLiteral("$threadroot:example.org"));
|
||||
QCOMPARE(eventHandlerThreadRoot.getReplyId(), QStringLiteral("$threadroot:example.org"));
|
||||
QCOMPARE(EventHandler::isThreaded(room->messageEvents().at(9).get()), true);
|
||||
QCOMPARE(EventHandler::threadRoot(room->messageEvents().at(9).get()), QStringLiteral("$threadroot:example.org"));
|
||||
QCOMPARE(EventHandler::replyId(room->messageEvents().at(9).get()), QStringLiteral("$threadroot:example.org"));
|
||||
|
||||
EventHandler eventHandlerThreadReply(room, room->messageEvents().at(10).get());
|
||||
QCOMPARE(eventHandlerThreadReply.isThreaded(), true);
|
||||
QCOMPARE(eventHandlerThreadReply.threadRoot(), QStringLiteral("$threadroot:example.org"));
|
||||
QCOMPARE(eventHandlerThreadReply.getReplyId(), QStringLiteral("$threadmessage1:example.org"));
|
||||
QCOMPARE(EventHandler::isThreaded(room->messageEvents().at(10).get()), true);
|
||||
QCOMPARE(EventHandler::threadRoot(room->messageEvents().at(10).get()), QStringLiteral("$threadroot:example.org"));
|
||||
QCOMPARE(EventHandler::replyId(room->messageEvents().at(10).get()), QStringLiteral("$threadmessage1:example.org"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullThread()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "isThreaded called with m_event set to nullptr.");
|
||||
QCOMPARE(emptyHandler.isThreaded(), false);
|
||||
QTest::ignoreMessage(QtWarningMsg, "isThreaded called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::isThreaded(nullptr), false);
|
||||
|
||||
EventHandler noEventHandler(room, nullptr);
|
||||
QTest::ignoreMessage(QtWarningMsg, "threadRoot called with m_event set to nullptr.");
|
||||
QCOMPARE(noEventHandler.threadRoot(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "threadRoot called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::threadRoot(nullptr), QString());
|
||||
}
|
||||
|
||||
void EventHandlerTest::location()
|
||||
{
|
||||
EventHandler eventHandler(room, room->messageEvents().at(7).get());
|
||||
|
||||
QCOMPARE(eventHandler.getLatitude(), QStringLiteral("51.7035").toFloat());
|
||||
QCOMPARE(eventHandler.getLongitude(), QStringLiteral("-1.14394").toFloat());
|
||||
QCOMPARE(eventHandler.getLocationAssetType(), QStringLiteral("m.pin"));
|
||||
QCOMPARE(EventHandler::latitude(room->messageEvents().at(7).get()), QStringLiteral("51.7035").toFloat());
|
||||
QCOMPARE(EventHandler::longitude(room->messageEvents().at(7).get()), QStringLiteral("-1.14394").toFloat());
|
||||
QCOMPARE(EventHandler::locationAssetType(room->messageEvents().at(7).get()), QStringLiteral("m.pin"));
|
||||
}
|
||||
|
||||
void EventHandlerTest::nullLocation()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg, "getLatitude called with m_event set to nullptr.");
|
||||
QCOMPARE(emptyHandler.getLatitude(), -100.0);
|
||||
QTest::ignoreMessage(QtWarningMsg, "latitude called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::latitude(nullptr), -100.0);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "getLongitude called with m_event set to nullptr.");
|
||||
QCOMPARE(emptyHandler.getLongitude(), -200.0);
|
||||
QTest::ignoreMessage(QtWarningMsg, "longitude called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::longitude(nullptr), -200.0);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "getLocationAssetType called with m_event set to nullptr.");
|
||||
QCOMPARE(emptyHandler.getLocationAssetType(), QString());
|
||||
QTest::ignoreMessage(QtWarningMsg, "locationAssetType called with event set to nullptr.");
|
||||
QCOMPARE(EventHandler::locationAssetType(nullptr), QString());
|
||||
}
|
||||
|
||||
QTEST_MAIN(EventHandlerTest)
|
||||
|
||||
61
autotests/messagecontentmodeltest.cpp
Normal file
61
autotests/messagecontentmodeltest.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include <QObject>
|
||||
#include <QSignalSpy>
|
||||
#include <QTest>
|
||||
|
||||
#include <Quotient/connection.h>
|
||||
#include <Quotient/quotient_common.h>
|
||||
#include <Quotient/roommember.h>
|
||||
#include <Quotient/syncdata.h>
|
||||
|
||||
#include "models/messagecontentmodel.h"
|
||||
|
||||
#include "testutils.h"
|
||||
|
||||
using namespace Quotient;
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
class MessageContentModelTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
Connection *connection = nullptr;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
|
||||
void missingEvent();
|
||||
};
|
||||
|
||||
void MessageContentModelTest::initTestCase()
|
||||
{
|
||||
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
|
||||
}
|
||||
|
||||
void MessageContentModelTest::missingEvent()
|
||||
{
|
||||
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#firstRoom:kde.org"));
|
||||
auto model1 = MessageContentModel(room, "$153456789:example.org"_L1);
|
||||
|
||||
QCOMPARE(model1.rowCount(), 1);
|
||||
QCOMPARE(model1.data(model1.index(0), MessageContentModel::ComponentTypeRole), MessageComponentType::Loading);
|
||||
QCOMPARE(model1.data(model1.index(0), MessageContentModel::DisplayRole), "Loading"_L1);
|
||||
|
||||
auto model2 = MessageContentModel(room, "$153456789:example.org"_L1, true);
|
||||
|
||||
QCOMPARE(model2.rowCount(), 1);
|
||||
QCOMPARE(model2.data(model2.index(0), MessageContentModel::ComponentTypeRole), MessageComponentType::Loading);
|
||||
QCOMPARE(model2.data(model2.index(0), MessageContentModel::DisplayRole), "Loading reply"_L1);
|
||||
|
||||
room->syncNewEvents(QLatin1String("test-min-sync.json"));
|
||||
QCOMPARE(model1.rowCount(), 2);
|
||||
QCOMPARE(model1.data(model1.index(0), MessageContentModel::ComponentTypeRole), MessageComponentType::Author);
|
||||
QCOMPARE(model1.data(model1.index(1), MessageContentModel::ComponentTypeRole), MessageComponentType::Text);
|
||||
QCOMPARE(model1.data(model1.index(1), MessageContentModel::DisplayRole), u"<b>This is an example<br>text message</b>"_s);
|
||||
}
|
||||
|
||||
QTEST_MAIN(MessageContentModelTest)
|
||||
#include "messagecontentmodeltest.moc"
|
||||
@@ -12,9 +12,7 @@
|
||||
|
||||
#include "enums/messagecomponenttype.h"
|
||||
#include "models/customemojimodel.h"
|
||||
#include "models/messagecontentmodel.h"
|
||||
#include "neochatconnection.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "testutils.h"
|
||||
|
||||
@@ -46,6 +44,7 @@ private Q_SLOTS:
|
||||
void sendCustomEmojiCode_data();
|
||||
void sendCustomEmojiCode();
|
||||
|
||||
void receiveSpacelessSelfClosingTag();
|
||||
void receiveStripReply();
|
||||
void receivePlainTextIn();
|
||||
|
||||
@@ -64,6 +63,7 @@ private Q_SLOTS:
|
||||
void receiveRichEdited();
|
||||
void receiveLineSeparator();
|
||||
void receiveRichCodeUrl();
|
||||
void receiveRichColor();
|
||||
|
||||
void componentOutput_data();
|
||||
void componentOutput();
|
||||
@@ -85,11 +85,11 @@ void TextHandlerTest::initTestCase()
|
||||
|
||||
void TextHandlerTest::allowedAttributes()
|
||||
{
|
||||
const QString testInputString1 = QStringLiteral("<p><span data-mx-spoiler><font color=#FFFFFF>Test</font><span></p>");
|
||||
const QString testOutputString1 = QStringLiteral("<p><span data-mx-spoiler><font color=#FFFFFF>Test</font><span></p>");
|
||||
const QString testInputString1 = QStringLiteral("<span data-mx-spoiler><font color=#FFFFFF>Test</font><span>");
|
||||
const QString testOutputString1 = QStringLiteral("<span data-mx-spoiler><font color=#FFFFFF>Test</font><span>");
|
||||
// Handle urls where the href has either single (') or double (") quotes.
|
||||
const QString testInputString2 = QStringLiteral("<p><a href=\"https://kde.org\">link</a><a href='https://kde.org'>link</a></p>");
|
||||
const QString testOutputString2 = QStringLiteral("<p><a href=\"https://kde.org\">link</a><a href='https://kde.org'>link</a></p>");
|
||||
const QString testInputString2 = QStringLiteral("<a href=\"https://kde.org\">link</a><a href='https://kde.org'>link</a>");
|
||||
const QString testOutputString2 = QStringLiteral("<a href=\"https://kde.org\">link</a><a href='https://kde.org'>link</a>");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString1);
|
||||
@@ -117,7 +117,7 @@ void TextHandlerTest::stripDisallowedTags()
|
||||
void TextHandlerTest::stripDisallowedAttributes()
|
||||
{
|
||||
const QString testInputString = QStringLiteral("<p style=\"font-size:50px;\" color=#FFFFFF>Test</p>");
|
||||
const QString testOutputString = QStringLiteral("<p>Test</p>");
|
||||
const QString testOutputString = QStringLiteral("Test");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString);
|
||||
@@ -144,8 +144,8 @@ void TextHandlerTest::emptyCodeTags()
|
||||
|
||||
void TextHandlerTest::sendSimpleStringCase()
|
||||
{
|
||||
const QString testInputString = QStringLiteral("This data should just be put in a paragraph.");
|
||||
const QString testOutputString = QStringLiteral("<p>This data should just be put in a paragraph.</p>");
|
||||
const QString testInputString = QStringLiteral("This data should just be left alone.");
|
||||
const QString testOutputString = QStringLiteral("This data should just be left alone.");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString);
|
||||
@@ -158,8 +158,8 @@ void TextHandlerTest::sendSingleParaMarkup()
|
||||
const QString testInputString = QStringLiteral(
|
||||
"Text para with **bold**, *italic*, [link](https://kde.org), , `inline code`.");
|
||||
const QString testOutputString = QStringLiteral(
|
||||
"<p>Text para with <strong>bold</strong>, <em>italic</em>, <a href=\"https://kde.org\">link</a>, <img "
|
||||
"src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e\" alt=\"image\">, <code>inline code</code>.</p>");
|
||||
"Text para with <strong>bold</strong>, <em>italic</em>, <a href=\"https://kde.org\">link</a>, <img "
|
||||
"src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e\" alt=\"image\">, <code>inline code</code>.");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString);
|
||||
@@ -185,7 +185,7 @@ void TextHandlerTest::sendMultipleSectionMarkup()
|
||||
void TextHandlerTest::sendBadLinks()
|
||||
{
|
||||
const QString testInputString = QStringLiteral("[link](kde.org), ");
|
||||
const QString testOutputString = QStringLiteral("<p><a>link</a>, <img alt=\"image\"></p>");
|
||||
const QString testOutputString = QStringLiteral("<a>link</a>, <img alt=\"image\">");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString);
|
||||
@@ -222,8 +222,8 @@ void TextHandlerTest::sendCodeClass()
|
||||
void TextHandlerTest::sendCustomEmoji()
|
||||
{
|
||||
const QString testInputString = QStringLiteral(":test:");
|
||||
const QString testOutputString = QStringLiteral(
|
||||
"<p><img data-mx-emoticon=\"\" src=\"mxc://example.org/test\" alt=\":test:\" title=\":test:\" height=\"32\" vertical-align=\"middle\" /></p>");
|
||||
const QString testOutputString =
|
||||
QStringLiteral("<img data-mx-emoticon=\"\" src=\"mxc://example.org/test\" alt=\":test:\" title=\":test:\" height=\"32\" vertical-align=\"middle\" />");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString);
|
||||
@@ -236,7 +236,7 @@ void TextHandlerTest::sendCustomEmojiCode_data()
|
||||
QTest::addColumn<QString>("testInputString");
|
||||
QTest::addColumn<QString>("testOutputString");
|
||||
|
||||
QTest::newRow("inline") << QStringLiteral("`:test:`") << QStringLiteral("<p><code>:test:</code></p>");
|
||||
QTest::newRow("inline") << QStringLiteral("`:test:`") << QStringLiteral("<code>:test:</code>");
|
||||
QTest::newRow("block") << QStringLiteral("```\n:test:\n```") << QStringLiteral("<pre><code>:test:\n</code></pre>");
|
||||
}
|
||||
|
||||
@@ -252,6 +252,19 @@ void TextHandlerTest::sendCustomEmojiCode()
|
||||
QCOMPARE(testTextHandler.handleSendText(), testOutputString);
|
||||
}
|
||||
|
||||
void TextHandlerTest::receiveSpacelessSelfClosingTag()
|
||||
{
|
||||
const QString testInputString = QStringLiteral("Test...<br/>...ing");
|
||||
const QString testRichOutputString = QStringLiteral("Test...<br/>...ing");
|
||||
const QString testPlainOutputString = QStringLiteral("Test...\n...ing");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString);
|
||||
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(), testRichOutputString);
|
||||
QCOMPARE(testTextHandler.handleRecievePlainText(Qt::RichText), testPlainOutputString);
|
||||
}
|
||||
|
||||
void TextHandlerTest::receiveStripReply()
|
||||
{
|
||||
const QString testInputString = QStringLiteral(
|
||||
@@ -274,6 +287,7 @@ void TextHandlerTest::receiveRichInPlainOut_data()
|
||||
QTest::newRow("ampersand") << QStringLiteral("a & b") << QStringLiteral("a & b");
|
||||
QTest::newRow("quote") << QStringLiteral(""a and b"") << QStringLiteral("\"a and b\"");
|
||||
QTest::newRow("new line") << QStringLiteral("new<br>line") << QStringLiteral("new\nline");
|
||||
QTest::newRow("unescape") << QStringLiteral("can't") << QStringLiteral("can't");
|
||||
}
|
||||
|
||||
void TextHandlerTest::receiveRichInPlainOut()
|
||||
@@ -360,7 +374,7 @@ void TextHandlerTest::receivePlainStripMarkup()
|
||||
void TextHandlerTest::receiveRichUserPill()
|
||||
{
|
||||
const QString testInputString = QStringLiteral("<p><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a></p>");
|
||||
const QString testOutputString = QStringLiteral("<p><b><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a></b></p>");
|
||||
const QString testOutputString = QStringLiteral("<b><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a></b>");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString);
|
||||
@@ -371,7 +385,7 @@ void TextHandlerTest::receiveRichUserPill()
|
||||
void TextHandlerTest::receiveRichStrikethrough()
|
||||
{
|
||||
const QString testInputString = QStringLiteral("<p><del>Test</del></p>");
|
||||
const QString testOutputString = QStringLiteral("<p><s>Test</s></p>");
|
||||
const QString testOutputString = QStringLiteral("<s>Test</s>");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString);
|
||||
@@ -448,6 +462,9 @@ void TextHandlerTest::receiveRichPlainUrl()
|
||||
QString testOutputStringMxId = QStringLiteral(
|
||||
"<b><a href=\"https://matrix.to/#/@user:kde.org\">@user:kde.org</a></b> <b><a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a></b>");
|
||||
|
||||
QString testInputStringMxIdWithPrefix = QStringLiteral("a @user:kde.org b");
|
||||
QString testOutputStringMxIdWithPrefix = QStringLiteral("a <b><a href=\"https://matrix.to/#/@user:kde.org\">@user:kde.org</a></b> b");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputStringLink1);
|
||||
|
||||
@@ -461,6 +478,9 @@ void TextHandlerTest::receiveRichPlainUrl()
|
||||
|
||||
testTextHandler.setData(testInputStringMxId);
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringMxId);
|
||||
|
||||
testTextHandler.setData(testInputStringMxIdWithPrefix);
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringMxIdWithPrefix);
|
||||
}
|
||||
|
||||
void TextHandlerTest::receiveRichEdited_data()
|
||||
@@ -501,6 +521,25 @@ void TextHandlerTest::receiveRichCodeUrl()
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(), input);
|
||||
}
|
||||
|
||||
void TextHandlerTest::receiveRichColor()
|
||||
{
|
||||
const QString testInputString = QStringLiteral(
|
||||
"<span data-mx-color=\"#ff00be\">¯</span><span data-mx-color=\"#ff3b1d\">\\</span><span data-mx-color=\"#ffa600\">_</span><span "
|
||||
"data-mx-color=\"#64d200\">(</span><span data-mx-color=\"#00e261\">ツ</span><span data-mx-color=\"#00e7ff\">)</span><span "
|
||||
"data-mx-color=\"#00e1ff\">_</span><span data-mx-color=\"#00bdff\">/</span><span data-mx-color=\"#ff60ff\">¯</span>");
|
||||
const QString testOutputString = QStringLiteral(
|
||||
"<span style=\"color: #ff00be;\">¯</span><span style=\"color: #ff3b1d;\">\\</span><span style=\"color: #ffa600;\">_</span><span style=\"color: "
|
||||
"#64d200;\">(</span><span style=\"color: #00e261;\">ツ</span><span style=\"color: #00e7ff;\">)</span><span style=\"color: #00e1ff;\">_</span><span "
|
||||
"style=\"color: #00bdff;\">/</span><span style=\"color: #ff60ff;\">¯</span>");
|
||||
|
||||
TextHandler testTextHandler;
|
||||
testTextHandler.setData(testInputString);
|
||||
|
||||
qInfo() << testTextHandler.handleRecieveRichText();
|
||||
|
||||
QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
|
||||
}
|
||||
|
||||
void TextHandlerTest::componentOutput_data()
|
||||
{
|
||||
QTest::addColumn<QString>("testInputString");
|
||||
@@ -516,7 +555,7 @@ void TextHandlerTest::componentOutput_data()
|
||||
QVariantMap{{QStringLiteral("class"), QStringLiteral("html")}}}};
|
||||
QTest::newRow("quote") << QStringLiteral("<p>Text</p>\n<blockquote>\n<p>blockquote</p>\n</blockquote>")
|
||||
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, QStringLiteral("Text"), {}},
|
||||
MessageComponent{MessageComponentType::Quote, QStringLiteral("\"blockquote\""), {}}};
|
||||
MessageComponent{MessageComponentType::Quote, QStringLiteral("“blockquote”"), {}}};
|
||||
QTest::newRow("no tag first paragraph") << QStringLiteral("Text\n<p>Text</p>")
|
||||
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, QStringLiteral("Text"), {}},
|
||||
MessageComponent{MessageComponentType::Text, QStringLiteral("Text"), {}}};
|
||||
@@ -535,7 +574,7 @@ void TextHandlerTest::componentOutput_data()
|
||||
"someField }\nCustomQml {\n someTextProperty: someField.text\n}\n</code></pre>Sure you can, it's still local to the same file where you "
|
||||
"defined the id")
|
||||
<< QList<MessageComponent>{
|
||||
MessageComponent{MessageComponentType::Text, QStringLiteral("Ah, you mean something like"), {}},
|
||||
MessageComponent{MessageComponentType::Text, QStringLiteral("Ah, you mean something like<br/>"), {}},
|
||||
MessageComponent{
|
||||
MessageComponentType::Code,
|
||||
QStringLiteral(
|
||||
|
||||
@@ -17,7 +17,6 @@ class WindowControllerTest : public QObject
|
||||
|
||||
private Q_SLOTS:
|
||||
void nullWindow();
|
||||
void geometry();
|
||||
void showAndRaise();
|
||||
void toggle();
|
||||
|
||||
@@ -30,32 +29,10 @@ void WindowControllerTest::nullWindow()
|
||||
auto &instance = WindowController::instance();
|
||||
QCOMPARE(instance.window(), nullptr);
|
||||
|
||||
instance.restoreGeometry();
|
||||
instance.saveGeometry();
|
||||
instance.showAndRaiseWindow({});
|
||||
instance.toggleWindow();
|
||||
}
|
||||
|
||||
void WindowControllerTest::geometry()
|
||||
{
|
||||
auto &instance = WindowController::instance();
|
||||
|
||||
QWindow window;
|
||||
window.setGeometry(0, 0, 200, 200);
|
||||
instance.setWindow(&window);
|
||||
QCOMPARE(instance.window(), &window);
|
||||
|
||||
instance.saveGeometry();
|
||||
const auto stateConfig = KSharedConfig::openStateConfig();
|
||||
KConfigGroup windowGroup = stateConfig->group(QStringLiteral("Window"));
|
||||
QCOMPARE(KWindowConfig::hasSavedWindowSize(windowGroup), true);
|
||||
|
||||
window.setGeometry(0, 0, 400, 400);
|
||||
QCOMPARE(window.geometry(), QRect(0, 0, 400, 400));
|
||||
instance.restoreGeometry();
|
||||
QCOMPARE(window.geometry(), QRect(0, 0, 200, 200));
|
||||
}
|
||||
|
||||
void WindowControllerTest::showAndRaise()
|
||||
{
|
||||
auto &instance = WindowController::instance();
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
<name xml:lang="eo">NeoChat</name>
|
||||
<name xml:lang="es">NeoChat</name>
|
||||
<name xml:lang="eu">NeoChat</name>
|
||||
<name xml:lang="fa">نئوچت</name>
|
||||
<name xml:lang="fi">NeoChat</name>
|
||||
<name xml:lang="fr">NeoChat</name>
|
||||
<name xml:lang="gl">NeoChat</name>
|
||||
@@ -51,44 +50,40 @@
|
||||
<name xml:lang="x-test">xxNeoChatxx</name>
|
||||
<name xml:lang="zh-CN">NeoChat</name>
|
||||
<name xml:lang="zh-TW">NeoChat</name>
|
||||
<summary>Chat with your friends on matrix</summary>
|
||||
<summary xml:lang="ar">دردش مع أصدقائك على ماتركس</summary>
|
||||
<summary xml:lang="ca">Xategeu amb els vostres amics a Matrix</summary>
|
||||
<summary xml:lang="ca-valencia">Xategeu amb els vostres amics a Matrix</summary>
|
||||
<summary xml:lang="cs">Mluvte se svými přáteli na Matrixu</summary>
|
||||
<summary xml:lang="de">Mit den Freunden auf Matrix unterhalten</summary>
|
||||
<summary xml:lang="en-GB">Chat with your friends on matrix</summary>
|
||||
<summary xml:lang="eo">Babilu kun viaj amikoj sur matrix</summary>
|
||||
<summary xml:lang="es">Charle con sus amigos en matrix</summary>
|
||||
<summary xml:lang="eu">Berriketan jardun zure lagunekin «Matrix»en</summary>
|
||||
<summary xml:lang="fi">Keskustelu ystäviesi kanssa Matrixissa</summary>
|
||||
<summary xml:lang="fr">Discuter avec vos ami(e)s sur le réseau Matrix</summary>
|
||||
<summary xml:lang="gl">Charle coas súas amizades en Matrix.</summary>
|
||||
<summary xml:lang="he">התכתבות עם החברים שלך ב־matrix</summary>
|
||||
<summary xml:lang="hu">Csevegjen barátaival a matrixon</summary>
|
||||
<summary xml:lang="ia">Starta Conversation con tu amicos sur matrix</summary>
|
||||
<summary xml:lang="it">Conversa con i tuoi contatti su matrix</summary>
|
||||
<summary xml:lang="ka">ესაუბრეთ მეგობრებს Matrix-ზე</summary>
|
||||
<summary xml:lang="ko">Matrix를 사용하여 친구들과 대화하기</summary>
|
||||
<summary xml:lang="lv">Tērzējiet ar saviem draugiem „Matrix“ tīklā</summary>
|
||||
<summary xml:lang="nl">Met uw vrienden chatten op matrix</summary>
|
||||
<summary xml:lang="nn">Prat med vennar på Matrix</summary>
|
||||
<summary xml:lang="pl">Rozmawiaj ze swoimi znajomymi w Matriksie</summary>
|
||||
<summary xml:lang="ru">Общение с друзьями в Matrix</summary>
|
||||
<summary xml:lang="sl">Klepet z vašimi prijatelji na matrixu</summary>
|
||||
<summary xml:lang="sv">Chatta med dina vänner på Matrix</summary>
|
||||
<summary xml:lang="ta">மேட்ரிக்ஸு மூலம் உங்கள் நண்பர்களிடம் பேசலாம்</summary>
|
||||
<summary xml:lang="tr">Matrix’te arkadaşlarınızla sohbet edin</summary>
|
||||
<summary xml:lang="uk">Спілкуйтеся з вашими друзями у matrix</summary>
|
||||
<summary xml:lang="x-test">xxChat with your friends on matrixxx</summary>
|
||||
<summary xml:lang="zh-CN">在 Matrix 上与朋友聊天</summary>
|
||||
<summary xml:lang="zh-TW">在 Matrix 上與您的朋友聊天</summary>
|
||||
<summary>Chat on Matrix</summary>
|
||||
<summary xml:lang="ar">دردش على ماتركس</summary>
|
||||
<summary xml:lang="ca">Xat a Matrix</summary>
|
||||
<summary xml:lang="ca-valencia">Xat a Matrix</summary>
|
||||
<summary xml:lang="de">Über Matrix unterhalten</summary>
|
||||
<summary xml:lang="en-GB">Chat on Matrix</summary>
|
||||
<summary xml:lang="eo">Babilo en Matrix</summary>
|
||||
<summary xml:lang="es">Charle en Matrix</summary>
|
||||
<summary xml:lang="eu">Berriketa Matrix-en</summary>
|
||||
<summary xml:lang="fi">Keskustelu Matrixissä</summary>
|
||||
<summary xml:lang="fr">Discuter sur Matrix</summary>
|
||||
<summary xml:lang="gl">Charlar en Matrix</summary>
|
||||
<summary xml:lang="he">התכתבות דרך Matrix</summary>
|
||||
<summary xml:lang="hu">Csevegés Matrixon</summary>
|
||||
<summary xml:lang="ia">Conversation en ditecto sur Matrix</summary>
|
||||
<summary xml:lang="it">Chat su Matrix</summary>
|
||||
<summary xml:lang="ka">ისაუბრეთ Matrix-ზე</summary>
|
||||
<summary xml:lang="nl">Chat op Matrix</summary>
|
||||
<summary xml:lang="nn">Prat med via Matrix</summary>
|
||||
<summary xml:lang="pl">Rozmawiaj na Matriksie</summary>
|
||||
<summary xml:lang="sl">Klepet na Matrixu</summary>
|
||||
<summary xml:lang="sv">Chatta på Matrix</summary>
|
||||
<summary xml:lang="ta">மேட்ரிக்ஸுக்கான உரையாடல் செயலி</summary>
|
||||
<summary xml:lang="tr">Matrix Üzerinde Sohbet</summary>
|
||||
<summary xml:lang="uk">Спілкування у Matrix</summary>
|
||||
<summary xml:lang="x-test">xxChat on Matrixxx</summary>
|
||||
<summary xml:lang="zh-TW">在 Matrix 上聊天</summary>
|
||||
<description>
|
||||
<p>NeoChat is a chat app that lets you take full advantage of the Matrix network. It provides you with a secure way to send text messages, videos and audio files to your family, colleagues and friends.</p>
|
||||
<p xml:lang="ar">نيوتشات هو تطبيق دردشة يتيح لك الاستفادة الكاملة من شبكة Matrix. فهو يوفر لك طريقة آمنة لإرسال الرسائل النصية ومقاطع الفيديو والملفات الصوتية إلى عائلتك وزملائك وأصدقائك.</p>
|
||||
<p xml:lang="ca">El NeoChat és una aplicació de xat que us permet aprofitar plenament la xarxa Matrix. Proporciona una manera segura d'enviar missatges de text, vídeos i arxius d'àudio a la vostra família, companys i amics.</p>
|
||||
<p xml:lang="ca-valencia">NeoChat és una aplicació de xat que us permet aprofitar plenament la xarxa Matrix. Proporciona una manera segura d'enviar missatges de text, vídeos i arxius d'àudio a la vostra família, companys i amics.</p>
|
||||
<p xml:lang="de">NeoChat ist eine Anwendung für Unterhaltungen mit allen Vorteilen des Matrix-Netzwerkes. Sie bietet eine sichere Möglichkeit zum Versenden von Nachrichten, Videos und Audiodateien and die Familienmitglieder.</p>
|
||||
<p xml:lang="el">Το NeoChat είναι μια εφαρμογή συνομιλίας που σας επιτρέπει να εκμεταλλευτείτε πλήρως το δίκτυο Matrix. Σας παρέχει έναν ασφαλή τρόπο να στέλνετε μηνύματα κειμένου, βίντεο και αρχεία ήχου στην οικογένεια, τους συναδέλφους και τους φίλους σας.</p>
|
||||
<p xml:lang="en-GB">NeoChat is a chat app that lets you take full advantage of the Matrix network. It provides you with a secure way to send text messages, videos and audio files to your family, colleagues and friends.</p>
|
||||
<p xml:lang="eo">NeoChat estas babilej-apo, kiu ebligas al vi plene profiti de la Matrix-reto. Ĝi provizas al vi sekuran manieron sendi tekstmesaĝojn, filmetojn kaj sondosierojn al via familio, kolegoj kaj amikoj.</p>
|
||||
<p xml:lang="es">NeoChat es una aplicación de chat que le permite aprovechar al máximo la red Matrix. Le proporciona un modo seguro de enviar mensajes de texto, vídeos y archivos de sonido a su familia, colegas y amigos.</p>
|
||||
@@ -117,13 +112,14 @@
|
||||
<p xml:lang="ca">NeoChat pretén ser una aplicació amb totes les característiques per a l'especificació de Matrix. Com a tal, s'ha implementat tota l'especificació actual estable amb les notables excepcions de la VoIP, fils i alguns aspectes de l'encriptatge d'extrem a extrem. Hi ha algunes altres omissions més petites a causa del fet que l'especificació de Matrix està evolucionant constantment, però l'objectiu segueix sent proporcionar suport eventual per a tota l'especificació.</p>
|
||||
<p xml:lang="ca-valencia">NeoChat pretén ser una aplicació amb totes les característiques per a l'especificació de Matrix. Com a tal, s'ha implementat tota l'especificació actual estable amb les notables excepcions de la VoIP, fils i alguns aspectes de l'encriptació d'extrem a extrem. Hi ha algunes altres omissions més xicotetes a causa del fet que l'especificació de Matrix està evolucionant constantment, però l'objectiu seguix sent proporcionar suport eventual per a tota l'especificació.</p>
|
||||
<p xml:lang="de">NeoChat versucht eine vollumfängliche Anwendung für die Spezifikation von Matrix zu sein. Damit wird alles der aktuellen stabilen Spezifikation mit den erwähnenswerten Ausnahmen von VoIP, Diskussionsfäden und ein paar Teilen der Ende-zu-Ende-Verschlüsselung unterstützt. Zudem sind andere kleinere Auslassungen vorhanden, da sich die Matrixspezifikation ständig weiterentwickelt. Nichtsdestotrotz soll letztendlich die gesamte Spezifikation unterstützt werden.</p>
|
||||
<p xml:lang="el">Το NeoChat στοχεύει να είναι μια πλήρως εξοπλισμένη εφαρμογή για τις προδιαγραφές Matrix. Ως εκ τούτου, υποστηρίζονται όλα τα στοιχεία της τρέχουσας σταθερής προδιαγραφής με τις αξιοσημείωτες εξαιρέσεις του VoIP, των νημάτων και ορισμένων πτυχών της κρυπτογράφησης στα άκρα. Υπάρχουν μερικές άλλες μικρότερες παραλείψεις που οφείλονται στο γεγονός ότι η προδιαγραφή Matrix εξελίσσεται συνεχώς, αλλά ο στόχος παραμένει να παρέχεται τελικά υποστήριξη για ολόκληρη την προδιαγραφή.</p>
|
||||
<p xml:lang="en-GB">NeoChat aims to be a fully featured application for the Matrix specification. As such everything in the current stable specification with the notable exceptions of VoIP, threads and some aspects of End-to-End Encryption are supported. There are a few other smaller omissions due to the fact that the Matrix spec is constantly evolving but the aim remains to provide eventual support for the entire spec.</p>
|
||||
<p xml:lang="eo">NeoChat celas esti plene kapabla aplikaĵo por la Matrix-specifo. Kiel tia, ĉio en la nuna stabila specifo kun la rimarkindaj esceptoj de VoIP, fadenoj kaj kelkaj aspektoj de Fin-al-Fina Ĉifrado estas subtenataj. Estas kelkaj aliaj pli malgrandaj preterlasoj pro la fakto, ke la Matrix-speco konstante evoluas, sed la celo restas provizi finfine subtenon por la tuta specifaĵo.</p>
|
||||
<p xml:lang="es">NeoChat pretende ser una aplicación con todas las funciones para la especificación de Matrix. Como tal, admite todo en la especificación estable actual, con las notables excepciones de VoIP, subprocesos y algunas funciones de cifrado de extremo a extremo. Existen algunas omisiones menos importantes debido al hecho de que la especificación de Matrix está en constante evolución, pero el objetivo sigue siendo brindar compatibilidad final con toda la especificación.</p>
|
||||
<p xml:lang="eu">«NeoChat»ek «Matrix» zehaztapenaren ezaugarri guztiak eskaintzen dituen aplikazio bat izan nahi du. Beraz, egungo zehaztapen egonkorrean dagoen guztiaren euskarria du, VoIP, hariak eta muturren artean zifratzeko salbuespen nabarmenekin. Badira beste ez-betetze txikiago batzuk, «Matrix»en zehaztapena etengabe eboluzioan dagoelako, baina azken helburua zehaztapen osoaren euskarria ematea izaten jarraitzen du.</p>
|
||||
<p xml:lang="fi">NeoChat pyrkii olemaan Matrix-määritelmän täysominaisuuksinen sovellus, joten se tukee kaikkea nykyisessä vakaassa määritelmässä muutamaa huomattavaa poikkeusta lukuun ottamatta (VoIP, säikeet ja jotkin piirteet päästä päähän -salauksessa). Joitakin pienempiäkin puutteita on Matrix-määritelmän jatkuvan kehityksen vuoksi, mutta lopputavoitteena on tarjota määritelmän täysi tuki.</p>
|
||||
<p xml:lang="fr">L'objectif de NeoChat est d'être une application complète pour le protocole Matrix. En tant que tel, tout dans la spécification stable actuelle avec les exceptions notables de VoIP, les processus et certains aspects du chiffrement de bout en bout sont pris en charge. Il y a quelques autres petites omissions en raison du fait que la spécification du protocole Matrix est en constante évolution. Cependant, l'objectif reste de fournir un soutien éventuel pour l'ensemble de la spécification.</p>
|
||||
<p xml:lang="gl">NeoChat pretende ser unha aplicación completa para a especificación de Matrix. Coas excepcións de VoIP, conversas fiadas e algúns aspectos da cifraxe de extremo a extremo, a versión estábel segue as especificacións. Existen algunhas outras pequenas omisións debido ao feito de que Matrix está en continua evolución pero a intención é implementar a especificación completa.</p>
|
||||
<p xml:lang="gl">NeoChat pretende ser unha aplicación completa para a especificación de Matrix. Coas excepcións de VoIP, conversas fiadas e algúns aspectos da cifraxe de extremo a extremo, a versión estábel segue as especificacións. Existen algunhas outras pequenas omisións debido ao feito de que Matrix está en continua evolución pero a intención é fornecer compatibilidade coa especificación completa.</p>
|
||||
<p xml:lang="he">NeoChat מתיימר להיות יישום עתיר יכולות לפי מפרט Matrix. כיוון שזה ייעודו, כל מה שבמפרט היציב עם חריגות משמעותיות כגון VoIP, שרשורים ועוד מגוון היבטים של הצפנה מקצה לקצה נתמכים גם הם. יש מספר השמטות קטן עקב העובדה שהמפרט של Matrix ממשיך להתפתח אך המטרה היא להמשיך לספק תמיכה בסופו של דבר לכל המפרט.</p>
|
||||
<p xml:lang="hu">A NeoChat célja, hogy a Matrix specifikációnak megfelelő teljes funkcionalitású alkalmazás legyen. Mint ilyen, a jelenlegi stabil specifikáció támogatott a VoIP, a szálak és a végpontok közötti titkosítás egyes elemeinek kivételével. Van még néhány kisebb hiányosság annak köszönhetően, hogy a Matrix specifikáció folyamatosan fejlődik, de végső cél a teljes specifikáció megvalósítása.</p>
|
||||
<p xml:lang="ia">NeoChat aspira a esser un application plenmente eminente per le specification de Matrix. Tal como omne cosas in le specification currentemente stabile con le exceptiones notabile de VOIP, threads e alcun aspectos del cryptation End-to-End es supportate. Il ha ltere pauc omissiones, debite al facto que le specification de Matrix es in evolution constante ma le aspiration remane a fornir supporto eventual per le integre specification.</p>
|
||||
@@ -147,6 +143,7 @@
|
||||
<p xml:lang="ca">A causa de la naturalesa del desenvolupament de l'especificació de Matrix, el NeoChat també implementa nombroses característiques inestables. Actualment són:</p>
|
||||
<p xml:lang="ca-valencia">A causa de la naturalea del desenvolupament de l'especificació de Matrix, NeoChat també implementa nombroses característiques inestables. Actualment són:</p>
|
||||
<p xml:lang="de">Durch die Weiterentwicklung der Matrix-Spezifikation unterstützt auch NeoChat einige als noch instabil gekennzeichnete Funktionen. Derzeit sind das:</p>
|
||||
<p xml:lang="el">Λόγω της φύσης της ανάπτυξης των προδιαγραφών Matrix, το NeoChat υποστηρίζει επίσης πολλά ασταθή χαρακτηριστικά. Επί του παρόντος, αυτά είναι:</p>
|
||||
<p xml:lang="en-GB">Due to the nature of the Matrix specification development NeoChat also supports numerous unstable features. Currently these are:</p>
|
||||
<p xml:lang="eo">Pro la naturo de la Matrix-specifevoluo NeoChat ankaŭ subtenas multajn malstabilajn funkciojn. Nuntempe ĉi tiuj estas:</p>
|
||||
<p xml:lang="es">Debido a la naturaleza del desarrollo de la especificación de Matrix, NeoChat también permite numerosas funciones no estables, como:</p>
|
||||
@@ -178,6 +175,7 @@
|
||||
<li xml:lang="ar">التصويت - MSC3381</li>
|
||||
<li xml:lang="ca">Enquestes - MSC3381</li>
|
||||
<li xml:lang="ca-valencia">Enquestes - MSC3381</li>
|
||||
<li xml:lang="el">Δημοσκοπήσεις - MSC3381</li>
|
||||
<li xml:lang="en-GB">Polls - MSC3381</li>
|
||||
<li xml:lang="eo">Enketoj - MSC3381</li>
|
||||
<li xml:lang="es">Encuestas - MSC3381</li>
|
||||
@@ -208,6 +206,7 @@
|
||||
<li xml:lang="ar">حزم الملصقات - MSC2545</li>
|
||||
<li xml:lang="ca">Paquets d'adhesius - MSC2545</li>
|
||||
<li xml:lang="ca-valencia">Paquets d'adhesius - MSC2545</li>
|
||||
<li xml:lang="el">Πακέτα αυτοκόλλητων - MSC2545</li>
|
||||
<li xml:lang="en-GB">Sticker Packs - MSC2545</li>
|
||||
<li xml:lang="eo">Glumark-Pakoj - MSC2545</li>
|
||||
<li xml:lang="es">Paquetes de pegatinas - MSC2545</li>
|
||||
@@ -238,6 +237,7 @@
|
||||
<li xml:lang="ar">موقع الأحداث - MSC3488</li>
|
||||
<li xml:lang="ca">Esdeveniments d'ubicació - MSC3488</li>
|
||||
<li xml:lang="ca-valencia">Esdeveniments d'ubicació - MSC3488</li>
|
||||
<li xml:lang="el">Τοποθεσία γεγονότα - MSC3488</li>
|
||||
<li xml:lang="en-GB">Location Events - MSC3488</li>
|
||||
<li xml:lang="eo">Lokaj Eventoj - MSC3488</li>
|
||||
<li xml:lang="es">Eventos de ubicación - MSC3488</li>
|
||||
@@ -303,6 +303,7 @@
|
||||
<caption xml:lang="ca">Vista principal amb la llista de sales, xats i informació de les sales</caption>
|
||||
<caption xml:lang="ca-valencia">Vista principal amb la llista de sales, xats i informació de les sales</caption>
|
||||
<caption xml:lang="de">Hauptansicht mit Raumliste, Unterhaltung und Raum-Informationen</caption>
|
||||
<caption xml:lang="el">Κύρια προβολή με λίστα δωματίων, συνομιλία και πληροφορίες δωματίων</caption>
|
||||
<caption xml:lang="en-GB">Main view with room list, chat, and room information</caption>
|
||||
<caption xml:lang="eo">Ĉefa vido kun ĉambra listo, babilejo kaj ĉambra informo</caption>
|
||||
<caption xml:lang="es">Vista principal con la lista de salas, chat e información de la sala</caption>
|
||||
@@ -337,6 +338,7 @@
|
||||
<caption xml:lang="ca">Descobriu comunitats noves amb els espais de Matrix</caption>
|
||||
<caption xml:lang="ca-valencia">Descobriu comunitats noves amb els espais de Matrix</caption>
|
||||
<caption xml:lang="de">Neue Gemeinschaften mit den Umgebungen von Matrix erkunden</caption>
|
||||
<caption xml:lang="el">Ανακαλύψτε νέες κοινότητες με το Matrix Spaces</caption>
|
||||
<caption xml:lang="en-GB">Discover new communities with Matrix Spaces</caption>
|
||||
<caption xml:lang="eo">Malkovru novajn komunumojn per Matrix Spaces</caption>
|
||||
<caption xml:lang="es">Descubra nuevas comunidades con los espacios de Matrix</caption>
|
||||
@@ -376,6 +378,7 @@
|
||||
<caption xml:lang="ca">Vista principal amb la llista de sales, xats i informació de les sales</caption>
|
||||
<caption xml:lang="ca-valencia">Vista principal amb la llista de sales, xats i informació de les sales</caption>
|
||||
<caption xml:lang="de">Hauptansicht mit Raumliste, Unterhaltung und Raum-Informationen</caption>
|
||||
<caption xml:lang="el">Κύρια προβολή με λίστα δωματίων, συνομιλία και πληροφορίες δωματίων</caption>
|
||||
<caption xml:lang="en-GB">Main view with room list, chat, and room information</caption>
|
||||
<caption xml:lang="eo">Ĉefa vido kun ĉambra listo, babilejo kaj ĉambra informo</caption>
|
||||
<caption xml:lang="es">Vista principal con la lista de salas, chat e información de la sala</caption>
|
||||
@@ -411,6 +414,7 @@
|
||||
<caption xml:lang="ca-valencia">Pantalla d'inici de sessió</caption>
|
||||
<caption xml:lang="cs">Přihlašovací obrazovka</caption>
|
||||
<caption xml:lang="de">Anmeldebildschirm</caption>
|
||||
<caption xml:lang="el">Οθόνη εισόδου</caption>
|
||||
<caption xml:lang="en-GB">Login screen</caption>
|
||||
<caption xml:lang="eo">Ensaluta ekrano</caption>
|
||||
<caption xml:lang="es">Pantalla de inicio de sesión</caption>
|
||||
@@ -443,6 +447,9 @@
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
</content_rating>
|
||||
<releases>
|
||||
<release version="24.12.2" date="2025-02-06"/>
|
||||
<release version="24.12.1" date="2025-01-09"/>
|
||||
<release version="24.12.0" date="2024-12-12"/>
|
||||
<release version="24.08.3" date="2024-11-07"/>
|
||||
<release version="24.08.2" date="2024-10-10"/>
|
||||
<release version="24.08.1" date="2024-09-12"/>
|
||||
|
||||
@@ -15,7 +15,6 @@ Name[en_GB]=NeoChat
|
||||
Name[eo]=NeoChat
|
||||
Name[es]=NeoChat
|
||||
Name[eu]=NeoChat
|
||||
Name[fa]=نئوچت
|
||||
Name[fi]=NeoChat
|
||||
Name[fr]=NeoChat
|
||||
Name[gl]=NeoChat
|
||||
@@ -88,47 +87,31 @@ GenericName[uk]=Клієнт Matrix
|
||||
GenericName[x-test]=xxMatrix Clientxx
|
||||
GenericName[zh_CN]=Matrix 客户端
|
||||
GenericName[zh_TW]=Matrix 用戶端
|
||||
Comment=Client for the Matrix protocol
|
||||
Comment[ar]=عميل لميفاق ماتركس
|
||||
Comment[az]=Matrix protokolu üçün müştəri
|
||||
Comment[ca]=Client per al protocol Matrix
|
||||
Comment[ca@valencia]=Client per al protocol Matrix
|
||||
Comment[de]=Programm für das Matrix-Protokoll
|
||||
Comment[el]=Πελάτης για το πρωτόκολλο Matrix
|
||||
Comment[en_GB]=Client for the Matrix protocol
|
||||
Comment[eo]=Kliento por la Matrix-protokolo
|
||||
Comment[es]=Cliente para el protocolo Matrix
|
||||
Comment[eu]=Matrix protokolorako bezeroa
|
||||
Comment[fi]=Asiakas Matrix-yhteyskäytännölle
|
||||
Comment[fr]=Client pour le protocole « Matrix »
|
||||
Comment[gl]=Cliente para o protocolo Matrix.
|
||||
Comment[he]=לקוח לפרוטוקול Matrix
|
||||
Comment[hu]=Kliens a Matrix protokollhoz
|
||||
Comment[ia]=Cliente per le protocollo de Matrix
|
||||
Comment[id]=Klien untuk protokol Matrix
|
||||
Comment[ie]=Un cliente del protocol Matrix
|
||||
Comment[it]=Client per il protocollo Matrix
|
||||
Comment[ka]=კლიენტი Matrix-ის პროტოკოლისთვის
|
||||
Comment[ko]=Matrix 프로토콜용 클라이언트
|
||||
Comment[lt]=Matrix protokolo kliento programa
|
||||
Comment[lv]=Klients „Matrix“ protokolam
|
||||
Comment[nl]=Client voor het Matrix-protocol
|
||||
Comment[nn]=Klient for Matrix-protokollen
|
||||
Comment[pa]=ਮੈਟਰਿਕਸ ਪਰੋਟੋਕਾਲ ਲਈ ਕਲਾਈਂਟ ਹੈ
|
||||
Comment[pl]=Program obsługi protokołu Matriksa
|
||||
Comment[pt]=Cliente para o protocolo Matrix
|
||||
Comment[pt_BR]=Cliente para o protocolo Matrix
|
||||
Comment[ro]=Client pentru protocolul Matrix
|
||||
Comment[ru]=Клиент для протокола Matrix
|
||||
Comment[sk]=Klient protokolu Matrix
|
||||
Comment[sl]=Odjemalec za protokol Matrix
|
||||
Comment[sv]=Klient för protokollet Matrix
|
||||
Comment[ta]=Matrix நெறிமுறைக்கான வாங்கி
|
||||
Comment[tr]=Matrix protokolü için istemci
|
||||
Comment[uk]=Клієнт протоколу Matrix
|
||||
Comment[x-test]=xxClient for the Matrix protocolxx
|
||||
Comment[zh_CN]=为 Matrix 协议打造的客户端
|
||||
Comment[zh_TW]=Matrix 通訊協定的用戶端
|
||||
Comment=Chat on Matrix
|
||||
Comment[ar]=دردش على ماتركس
|
||||
Comment[ca]=Xat a Matrix
|
||||
Comment[ca@valencia]=Xat a Matrix
|
||||
Comment[de]=Über Matrix unterhalten
|
||||
Comment[en_GB]=Chat on Matrix
|
||||
Comment[eo]=Babilo en Matrix
|
||||
Comment[es]=Chat en Matrix
|
||||
Comment[eu]=Berriketa Matrix-en
|
||||
Comment[fi]=Keskustele Matrixissä
|
||||
Comment[fr]=Clavarder sur Matrix
|
||||
Comment[gl]=Charle en Matrix
|
||||
Comment[he]=התכתבות דרך Matrix
|
||||
Comment[hu]=Csevegés Matrixon
|
||||
Comment[ia]=Conversation en ditecto sur Matrix
|
||||
Comment[it]= su Matrix
|
||||
Comment[ka]=საუბარი Matrix-ზე
|
||||
Comment[pl]=Rozmawiaj na Matriksie
|
||||
Comment[sl]=Klepet na Matrixu
|
||||
Comment[sv]=Chatta på Matrix
|
||||
Comment[ta]=மேட்ரிக்ஸில் உரையாட உதவும்
|
||||
Comment[tr]=Matrix üzerinde sohbet edin
|
||||
Comment[uk]=Спілкування у Matrix
|
||||
Comment[zh_CN]=在 Matrix 上聊天
|
||||
Comment[zh_TW]=在 Matrix 上聊天
|
||||
MimeType=x-scheme-handler/matrix;
|
||||
Exec=neochat %u
|
||||
Terminal=false
|
||||
|
||||
2087
po/ar/neochat.po
2087
po/ar/neochat.po
File diff suppressed because it is too large
Load Diff
2003
po/ast/neochat.po
2003
po/ast/neochat.po
File diff suppressed because it is too large
Load Diff
2195
po/az/neochat.po
2195
po/az/neochat.po
File diff suppressed because it is too large
Load Diff
1945
po/ca/neochat.po
1945
po/ca/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2044
po/cs/neochat.po
2044
po/cs/neochat.po
File diff suppressed because it is too large
Load Diff
2010
po/da/neochat.po
2010
po/da/neochat.po
File diff suppressed because it is too large
Load Diff
2257
po/de/neochat.po
2257
po/de/neochat.po
File diff suppressed because it is too large
Load Diff
2707
po/el/neochat.po
2707
po/el/neochat.po
File diff suppressed because it is too large
Load Diff
2094
po/en_GB/neochat.po
2094
po/en_GB/neochat.po
File diff suppressed because it is too large
Load Diff
1953
po/eo/neochat.po
1953
po/eo/neochat.po
File diff suppressed because it is too large
Load Diff
2078
po/es/neochat.po
2078
po/es/neochat.po
File diff suppressed because it is too large
Load Diff
2137
po/eu/neochat.po
2137
po/eu/neochat.po
File diff suppressed because it is too large
Load Diff
5383
po/fa/neochat.po
5383
po/fa/neochat.po
File diff suppressed because it is too large
Load Diff
2923
po/fi/neochat.po
2923
po/fi/neochat.po
File diff suppressed because it is too large
Load Diff
2086
po/fr/neochat.po
2086
po/fr/neochat.po
File diff suppressed because it is too large
Load Diff
2107
po/gl/neochat.po
2107
po/gl/neochat.po
File diff suppressed because it is too large
Load Diff
2080
po/hu/neochat.po
2080
po/hu/neochat.po
File diff suppressed because it is too large
Load Diff
2078
po/ia/neochat.po
2078
po/ia/neochat.po
File diff suppressed because it is too large
Load Diff
2259
po/id/neochat.po
2259
po/id/neochat.po
File diff suppressed because it is too large
Load Diff
2106
po/ie/neochat.po
2106
po/ie/neochat.po
File diff suppressed because it is too large
Load Diff
2081
po/it/neochat.po
2081
po/it/neochat.po
File diff suppressed because it is too large
Load Diff
2001
po/ja/neochat.po
2001
po/ja/neochat.po
File diff suppressed because it is too large
Load Diff
2075
po/ka/neochat.po
2075
po/ka/neochat.po
File diff suppressed because it is too large
Load Diff
2227
po/ko/neochat.po
2227
po/ko/neochat.po
File diff suppressed because it is too large
Load Diff
2006
po/lt/neochat.po
2006
po/lt/neochat.po
File diff suppressed because it is too large
Load Diff
2662
po/lv/neochat.po
2662
po/lv/neochat.po
File diff suppressed because it is too large
Load Diff
2082
po/nl/neochat.po
2082
po/nl/neochat.po
File diff suppressed because it is too large
Load Diff
1931
po/nn/neochat.po
1931
po/nn/neochat.po
File diff suppressed because it is too large
Load Diff
2173
po/pa/neochat.po
2173
po/pa/neochat.po
File diff suppressed because it is too large
Load Diff
2086
po/pl/neochat.po
2086
po/pl/neochat.po
File diff suppressed because it is too large
Load Diff
2257
po/pt/neochat.po
2257
po/pt/neochat.po
File diff suppressed because it is too large
Load Diff
2186
po/pt_BR/neochat.po
2186
po/pt_BR/neochat.po
File diff suppressed because it is too large
Load Diff
2143
po/ru/neochat.po
2143
po/ru/neochat.po
File diff suppressed because it is too large
Load Diff
2209
po/sk/neochat.po
2209
po/sk/neochat.po
File diff suppressed because it is too large
Load Diff
122
po/sl/docs/neochat/man-neochat.1.docbook
Normal file
122
po/sl/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 % Slovenian "INCLUDE">
|
||||
]>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
|
||||
SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
-->
|
||||
|
||||
<refentry lang="&language;">
|
||||
<refentryinfo>
|
||||
<title
|
||||
>Uporabniški priročnik za NeoChat</title>
|
||||
<author
|
||||
><firstname
|
||||
>Carl</firstname
|
||||
><surname
|
||||
>Schwan</surname
|
||||
> <contrib
|
||||
>Stran z navodili za NeoChat.</contrib
|
||||
> <email
|
||||
>carl@carlschwan.eu</email
|
||||
></author>
|
||||
<date
|
||||
>01.11.2022</date>
|
||||
<releaseinfo
|
||||
>22,09</releaseinfo>
|
||||
<productname
|
||||
>NeoChat</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>
|
||||
<command
|
||||
>neochat</command>
|
||||
</refentrytitle>
|
||||
<manvolnum
|
||||
>1</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname
|
||||
>neochat</refname>
|
||||
<refpurpose
|
||||
>Odjemalec za interakcijo s protokolom za matrično sporočanje</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
|
||||
>Opis</title>
|
||||
<para
|
||||
><command
|
||||
>neochat</command
|
||||
> je aplikacija za klepet za matrični protokol, ki deluje na namizju in mobilni napravi. </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="options"
|
||||
><title
|
||||
>Možnosti</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term
|
||||
><option
|
||||
>URI</option
|
||||
></term>
|
||||
<listitem>
|
||||
<para
|
||||
>Uri matrike za uporabnika ali sobo. npr. matrix:u/user:example.org in matrix:r/root:example.org. Tako bo NeoChat poskušal odpreti dano sobo ali pogovor. </para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="bug">
|
||||
<title
|
||||
>Poročanje o napakah</title>
|
||||
<para
|
||||
>Napake in zahteve po funkcijah lahko prijavite na <ulink url="https://bugs.kde.org/enter_bug.cgi?product=NeoChat&component=General"
|
||||
>https://bugs.kde.org/enter_bug.cgi? product=NeoChat&component=General</ulink
|
||||
></para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title
|
||||
>Poglej tudi</title>
|
||||
<simplelist>
|
||||
<member
|
||||
>Seznam pogostih vprašanj o Matrix <ulink url="https://matrix.org/faq/"
|
||||
>https://matrix.org/faq/</ulink
|
||||
> </member>
|
||||
<member
|
||||
>kf5options(7)</member>
|
||||
<member
|
||||
>qt5options(7)</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="copyright"
|
||||
><title
|
||||
>Avtorske pravice</title>
|
||||
<para
|
||||
>Avtorske pravice © 2020-2022 Tobias Fella </para>
|
||||
<para
|
||||
>Avtorske pravice © 2020-2022 Carl Schwan </para>
|
||||
<para
|
||||
>Licenca: GNU General Public različica 3 ali novejša <<ulink url="https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
>https://www.gnu.org/licenses/gpl-3.0 .html</ulink
|
||||
>></para>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
2082
po/sl/neochat.po
2082
po/sl/neochat.po
File diff suppressed because it is too large
Load Diff
2080
po/sv/neochat.po
2080
po/sv/neochat.po
File diff suppressed because it is too large
Load Diff
2075
po/ta/neochat.po
2075
po/ta/neochat.po
File diff suppressed because it is too large
Load Diff
2056
po/tok/neochat.po
2056
po/tok/neochat.po
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
# 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})
|
||||
2052
po/tr/neochat.po
2052
po/tr/neochat.po
File diff suppressed because it is too large
Load Diff
2090
po/uk/neochat.po
2090
po/uk/neochat.po
File diff suppressed because it is too large
Load Diff
1937
po/zh_CN/neochat.po
1937
po/zh_CN/neochat.po
File diff suppressed because it is too large
Load Diff
2052
po/zh_TW/neochat.po
2052
po/zh_TW/neochat.po
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,10 @@ apps:
|
||||
|
||||
compression: lzo
|
||||
|
||||
package-repositories:
|
||||
- type: apt
|
||||
ppa: ubuntu-toolchain-r/test
|
||||
|
||||
slots:
|
||||
session-dbus-interface:
|
||||
interface: dbus
|
||||
@@ -62,7 +66,7 @@ parts:
|
||||
- -Dcrypto=disabled
|
||||
- -Dgtk_doc=false
|
||||
build-packages:
|
||||
- meson
|
||||
- meson
|
||||
- libglib2.0-dev
|
||||
- libgcrypt20-dev
|
||||
prime:
|
||||
@@ -76,6 +80,7 @@ parts:
|
||||
source-depth: 1
|
||||
plugin: cmake
|
||||
build-environment:
|
||||
- PATH: /snap/bin:${PATH}
|
||||
- PKG_CONFIG_PATH: $CRAFT_STAGE/usr/lib/$CRAFT_ARCH_TRIPLET/pkgconfig:$PKG_CONFIG_PATH
|
||||
cmake-parameters:
|
||||
- -DCMAKE_INSTALL_PREFIX=/usr
|
||||
@@ -92,10 +97,16 @@ parts:
|
||||
- olm
|
||||
- qtkeychain
|
||||
source: https://github.com/quotient-im/libQuotient.git
|
||||
source-tag: 0.8.2
|
||||
source-tag: 0.9.1
|
||||
source-depth: 1
|
||||
plugin: cmake
|
||||
build-environment:
|
||||
- PATH: /snap/bin:${PATH}
|
||||
build-snaps:
|
||||
- cmake
|
||||
build-packages:
|
||||
- gcc-13
|
||||
- g++-13
|
||||
- libssl-dev
|
||||
cmake-parameters:
|
||||
- -DCMAKE_INSTALL_PREFIX=/usr
|
||||
@@ -103,6 +114,9 @@ parts:
|
||||
- -DBUILD_TESTING=OFF
|
||||
- -DQuotient_ENABLE_E2EE=ON
|
||||
- -DBUILD_WITH_QT6=ON
|
||||
override-build: |
|
||||
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 100 --slave /usr/bin/g++ g++ /usr/bin/g++-13 --slave /usr/bin/gcov gcov /usr/bin/gcov-13
|
||||
craftctl default
|
||||
prime:
|
||||
- -usr/include
|
||||
- -usr/lib/*/pkgconfig
|
||||
@@ -113,6 +127,8 @@ parts:
|
||||
source-tag: 'v0.3.0'
|
||||
source-depth: 1
|
||||
plugin: cmake
|
||||
build-environment:
|
||||
- PATH: /snap/bin:${PATH}
|
||||
cmake-parameters:
|
||||
- -DCMAKE_INSTALL_PREFIX=/usr
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
@@ -131,8 +147,9 @@ parts:
|
||||
parse-info:
|
||||
- usr/share/metainfo/org.kde.neochat.appdata.xml
|
||||
source: .
|
||||
source-type: local
|
||||
plugin: cmake
|
||||
build-environment:
|
||||
- PATH: /snap/bin:${PATH}
|
||||
build-packages:
|
||||
- cmark
|
||||
- libcmark-dev
|
||||
|
||||
@@ -10,8 +10,6 @@ endif()
|
||||
add_library(neochat STATIC
|
||||
controller.cpp
|
||||
controller.h
|
||||
actionshandler.cpp
|
||||
actionshandler.h
|
||||
models/emojimodel.cpp
|
||||
models/emojimodel.h
|
||||
emojitones.cpp
|
||||
@@ -192,12 +190,22 @@ add_library(neochat STATIC
|
||||
models/readmarkermodel.h
|
||||
neochatroommember.cpp
|
||||
neochatroommember.h
|
||||
models/threadmodel.cpp
|
||||
models/threadmodel.h
|
||||
enums/messagetype.h
|
||||
messagecomponent.h
|
||||
)
|
||||
|
||||
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
|
||||
QT_QML_SINGLETON_TYPE TRUE
|
||||
)
|
||||
|
||||
if(ANDROID OR WIN32)
|
||||
set_source_files_properties(qml/ShareActionStub.qml PROPERTIES
|
||||
QT_QML_SOURCE_TYPENAME ShareAction
|
||||
)
|
||||
endif()
|
||||
|
||||
ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
|
||||
OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/org/kde/neochat
|
||||
QML_FILES
|
||||
@@ -236,15 +244,10 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
|
||||
qml/EmojiSas.qml
|
||||
qml/ConfirmDeactivateAccountDialog.qml
|
||||
qml/VerificationCanceled.qml
|
||||
qml/GlobalMenu.qml
|
||||
qml/EditMenu.qml
|
||||
qml/MessageDelegateContextMenu.qml
|
||||
qml/FileDelegateContextMenu.qml
|
||||
qml/MessageSourceSheet.qml
|
||||
qml/ReportSheet.qml
|
||||
qml/ConfirmEncryptionDialog.qml
|
||||
qml/RemoveSheet.qml
|
||||
qml/BanSheet.qml
|
||||
qml/RoomSearchPage.qml
|
||||
qml/LocationChooser.qml
|
||||
qml/TimelineView.qml
|
||||
@@ -288,6 +291,8 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
|
||||
qml/ConsentDialog.qml
|
||||
qml/AskDirectChatConfirmation.qml
|
||||
qml/HoverLinkIndicator.qml
|
||||
qml/AvatarNotification.qml
|
||||
qml/ReasonDialog.qml
|
||||
DEPENDENCIES
|
||||
QtCore
|
||||
QtQuick
|
||||
@@ -305,16 +310,16 @@ add_subdirectory(devtools)
|
||||
add_subdirectory(login)
|
||||
add_subdirectory(chatbar)
|
||||
|
||||
if(UNIX)
|
||||
qt_target_qml_sources(neochat QML_FILES qml/ShareAction.qml)
|
||||
else()
|
||||
set_source_files_properties(qml/ShareActionStub.qml PROPERTIES
|
||||
QT_RESOURCE_ALIAS qml/ShareAction.qml
|
||||
if(NOT ANDROID AND NOT WIN32)
|
||||
qt_target_qml_sources(neochat QML_FILES
|
||||
qml/ShareAction.qml
|
||||
qml/GlobalMenu.qml
|
||||
qml/EditMenu.qml
|
||||
)
|
||||
else()
|
||||
qt_target_qml_sources(neochat QML_FILES qml/ShareActionStub.qml)
|
||||
endif()
|
||||
|
||||
|
||||
configure_file(config-neochat.h.in ${CMAKE_CURRENT_BINARY_DIR}/config-neochat.h)
|
||||
|
||||
if(WIN32)
|
||||
@@ -384,7 +389,7 @@ if(NOT ANDROID)
|
||||
target_compile_definitions(neochat PUBLIC -DHAVE_ICU)
|
||||
endif()
|
||||
|
||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE AND NOT HAIKU)
|
||||
target_compile_definitions(neochat PUBLIC -DHAVE_RUNNER)
|
||||
target_compile_definitions(neochat PUBLIC -DHAVE_X11=1)
|
||||
target_sources(neochat PRIVATE runner.cpp)
|
||||
@@ -413,6 +418,7 @@ target_link_libraries(neochat PUBLIC
|
||||
KF6::ConfigGui
|
||||
KF6::CoreAddons
|
||||
KF6::SonnetCore
|
||||
KF6::IconThemes
|
||||
KF6::ColorScheme
|
||||
KF6::ItemModels
|
||||
QuotientQt6
|
||||
@@ -425,7 +431,7 @@ if (TARGET KF6::Crash)
|
||||
target_link_libraries(neochat PUBLIC KF6::Crash)
|
||||
endif()
|
||||
|
||||
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
|
||||
kconfig_target_kcfg_file(neochat FILE neochatconfig.kcfg CLASS_NAME NeoChatConfig MUTATORS GENERATE_PROPERTIES DEFAULT_VALUE_GETTERS PARENT_IN_CONSTRUCTOR SINGLETON GENERATE_MOC QML_REGISTRATION)
|
||||
|
||||
if(NEOCHAT_FLATPAK)
|
||||
target_compile_definitions(neochat PUBLIC NEOCHAT_FLATPAK)
|
||||
@@ -440,8 +446,11 @@ if(ANDROID)
|
||||
target_sources(neochat-app PRIVATE notifyrc.qrc)
|
||||
target_link_libraries(neochat PUBLIC Qt::Svg OpenSSL::SSL)
|
||||
kirigami_package_breeze_icons(ICONS
|
||||
"arrow-down"
|
||||
"arrow-up"
|
||||
"arrow-down-symbolic"
|
||||
"arrow-up-symbolic"
|
||||
"arrow-up-double-symbolic"
|
||||
"arrow-left-symbolic"
|
||||
"arrow-right-symbolic"
|
||||
"checkmark"
|
||||
"help-about"
|
||||
"im-user"
|
||||
@@ -450,6 +459,7 @@ if(ANDROID)
|
||||
"mail-attachment"
|
||||
"dialog-cancel"
|
||||
"preferences-desktop-emoticons"
|
||||
"preferences-security"
|
||||
"document-open"
|
||||
"document-save"
|
||||
"document-send"
|
||||
@@ -482,6 +492,7 @@ if(ANDROID)
|
||||
"network-connect"
|
||||
"list-remove-user"
|
||||
"org.kde.neochat"
|
||||
"org.kde.neochat.tray"
|
||||
"preferences-system-users"
|
||||
"preferences-desktop-theme-global"
|
||||
"notifications"
|
||||
@@ -519,11 +530,13 @@ if(ANDROID)
|
||||
"object-rotate-left"
|
||||
"object-rotate-right"
|
||||
"add-subtitle"
|
||||
"security-high"
|
||||
"security-low"
|
||||
"security-low-symbolic"
|
||||
"kde"
|
||||
"list-remove-symbolic"
|
||||
"edit-delete"
|
||||
"user-home-symbolic"
|
||||
)
|
||||
ecm_add_android_apk(neochat-app ANDROID_DIR ${CMAKE_SOURCE_DIR}/android)
|
||||
else()
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2020 Carl Schwan <carlschwan@kde.org>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "actionshandler.h"
|
||||
|
||||
#include <Quotient/csapi/joining.h>
|
||||
#include <Quotient/events/roommemberevent.h>
|
||||
|
||||
#include <cmark.h>
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <QStringBuilder>
|
||||
|
||||
#include "models/actionsmodel.h"
|
||||
#include "neochatconfig.h"
|
||||
#include "texthandler.h"
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
ActionsHandler::ActionsHandler(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
NeoChatRoom *ActionsHandler::room() const
|
||||
{
|
||||
return m_room;
|
||||
}
|
||||
|
||||
void ActionsHandler::setRoom(NeoChatRoom *room)
|
||||
{
|
||||
if (m_room == room) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_room = room;
|
||||
Q_EMIT roomChanged();
|
||||
}
|
||||
|
||||
void ActionsHandler::handleMessageEvent(ChatBarCache *chatBarCache)
|
||||
{
|
||||
if (!m_room || !chatBarCache) {
|
||||
qWarning() << "ActionsHandler::handleMessageEvent - called with m_room and/or chatBarCache set to nullptr.";
|
||||
return;
|
||||
}
|
||||
|
||||
checkEffects(chatBarCache->text());
|
||||
if (!chatBarCache->attachmentPath().isEmpty()) {
|
||||
QUrl url(chatBarCache->attachmentPath());
|
||||
auto path = url.isLocalFile() ? url.toLocalFile() : url.toString();
|
||||
m_room->uploadFile(QUrl(path), chatBarCache->text().isEmpty() ? path.mid(path.lastIndexOf(u'/') + 1) : chatBarCache->text());
|
||||
chatBarCache->setAttachmentPath({});
|
||||
chatBarCache->setText({});
|
||||
return;
|
||||
}
|
||||
|
||||
QString handledText = chatBarCache->text();
|
||||
handledText = handleMentions(handledText, chatBarCache->mentions());
|
||||
handleMessage(m_room->mainCache()->text(), handledText, chatBarCache);
|
||||
}
|
||||
|
||||
QString ActionsHandler::handleMentions(QString handledText, QList<Mention> *mentions)
|
||||
{
|
||||
std::sort(mentions->begin(), mentions->end(), [](const auto &a, const auto &b) -> bool {
|
||||
return a.cursor.anchor() > b.cursor.anchor();
|
||||
});
|
||||
|
||||
for (const auto &mention : *mentions) {
|
||||
if (mention.text.isEmpty() || mention.id.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
handledText = handledText.replace(mention.cursor.anchor(),
|
||||
mention.cursor.position() - mention.cursor.anchor(),
|
||||
QStringLiteral("[%1](https://matrix.to/#/%2)").arg(mention.text.toHtmlEscaped(), mention.id));
|
||||
}
|
||||
mentions->clear();
|
||||
|
||||
return handledText;
|
||||
}
|
||||
|
||||
void ActionsHandler::handleMessage(const QString &text, QString handledText, ChatBarCache *chatBarCache)
|
||||
{
|
||||
Q_ASSERT(m_room);
|
||||
if (NeoChatConfig::allowQuickEdit()) {
|
||||
QRegularExpression sed(QStringLiteral("^s/([^/]*)/([^/]*)(/g)?$"));
|
||||
auto match = sed.match(text);
|
||||
if (match.hasMatch()) {
|
||||
const QString regex = match.captured(1);
|
||||
const QString replacement = match.captured(2).toHtmlEscaped();
|
||||
const QString flags = match.captured(3);
|
||||
|
||||
for (auto it = m_room->messageEvents().crbegin(); it != m_room->messageEvents().crend(); it++) {
|
||||
if (const auto event = eventCast<const RoomMessageEvent>(&**it)) {
|
||||
#if Quotient_VERSION_MINOR > 8
|
||||
if (event->senderId() == m_room->localMember().id() && event->has<EventContent::TextContent>()) {
|
||||
#else
|
||||
if (event->senderId() == m_room->localMember().id() && event->hasTextContent()) {
|
||||
#endif
|
||||
QString originalString;
|
||||
if (event->content()) {
|
||||
#if Quotient_VERSION_MINOR > 8
|
||||
originalString = event->get<EventContent::TextContent>()->body;
|
||||
#else
|
||||
originalString = static_cast<const Quotient::EventContent::TextContent *>(event->content())->body;
|
||||
#endif
|
||||
} else {
|
||||
originalString = event->plainBody();
|
||||
}
|
||||
if (flags == "/g"_ls) {
|
||||
m_room->postHtmlMessage(handledText, originalString.replace(regex, replacement), event->msgtype(), {}, event->id());
|
||||
} else {
|
||||
m_room->postHtmlMessage(handledText,
|
||||
originalString.replace(originalString.indexOf(regex), regex.size(), replacement),
|
||||
event->msgtype(),
|
||||
{},
|
||||
event->id());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto messageType = RoomMessageEvent::MsgType::Text;
|
||||
|
||||
if (handledText.startsWith(QLatin1Char('/'))) {
|
||||
for (const auto &action : ActionsModel::instance().allActions()) {
|
||||
if (handledText.indexOf(action.prefix) == 1
|
||||
&& (handledText.indexOf(" "_ls) == action.prefix.length() + 1 || handledText.length() == action.prefix.length() + 1)) {
|
||||
handledText = action.handle(handledText.mid(action.prefix.length() + 1).trimmed(), m_room, chatBarCache);
|
||||
if (action.messageType.has_value()) {
|
||||
messageType = *action.messageType;
|
||||
}
|
||||
if (action.messageAction) {
|
||||
break;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextHandler textHandler;
|
||||
textHandler.setData(handledText);
|
||||
handledText = textHandler.handleSendText();
|
||||
|
||||
if (handledText.count("<p>"_ls) == 1 && handledText.count("</p>"_ls) == 1) {
|
||||
handledText.remove("<p>"_ls);
|
||||
handledText.remove("</p>"_ls);
|
||||
}
|
||||
|
||||
if (handledText.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_room->postMessage(text, handledText, messageType, chatBarCache->replyId(), chatBarCache->editId(), chatBarCache->threadId());
|
||||
}
|
||||
|
||||
void ActionsHandler::checkEffects(const QString &text)
|
||||
{
|
||||
std::optional<QString> effect = std::nullopt;
|
||||
if (text.contains(QStringLiteral("\u2744"))) {
|
||||
effect = QLatin1String("snowflake");
|
||||
} else if (text.contains(QStringLiteral("\u1F386"))) {
|
||||
effect = QLatin1String("fireworks");
|
||||
} else if (text.contains(QStringLiteral("\u2F387"))) {
|
||||
effect = QLatin1String("fireworks");
|
||||
} else if (text.contains(QStringLiteral("\u1F389"))) {
|
||||
effect = QLatin1String("confetti");
|
||||
} else if (text.contains(QStringLiteral("\u1F38A"))) {
|
||||
effect = QLatin1String("confetti");
|
||||
}
|
||||
if (effect.has_value()) {
|
||||
Q_EMIT showEffect(*effect);
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_actionshandler.cpp"
|
||||
@@ -1,66 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2020 Carl Schwan <carlschwan@kde.org>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include <Quotient/events/roommessageevent.h>
|
||||
|
||||
#include "chatbarcache.h"
|
||||
#include "neochatroom.h"
|
||||
|
||||
class NeoChatRoom;
|
||||
|
||||
/**
|
||||
* @class ActionsHandler
|
||||
*
|
||||
* This class handles chat messages ready for posting to a room.
|
||||
*
|
||||
* Everything that needs to be done to prepare the message for posting in a room
|
||||
* including:
|
||||
* - File handling
|
||||
* - User mentions
|
||||
* - Quick edits
|
||||
* - Chat actions
|
||||
* - Custom emojis
|
||||
*
|
||||
* @note A chat action is a message starting with /, resulting in something other
|
||||
* than a normal message being sent (e.g. /me, /join).
|
||||
*
|
||||
* @sa ActionsModel, NeoChatRoom
|
||||
*/
|
||||
class ActionsHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
/**
|
||||
* @brief The room that messages will be sent to.
|
||||
*/
|
||||
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
|
||||
|
||||
public:
|
||||
explicit ActionsHandler(QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] NeoChatRoom *room() const;
|
||||
void setRoom(NeoChatRoom *room);
|
||||
|
||||
Q_SIGNALS:
|
||||
void roomChanged();
|
||||
void showEffect(const QString &effect);
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* @brief Pre-process text and send message event.
|
||||
*/
|
||||
void handleMessageEvent(ChatBarCache *chatBarCache);
|
||||
|
||||
private:
|
||||
QPointer<NeoChatRoom> m_room;
|
||||
void checkEffects(const QString &text);
|
||||
|
||||
QString handleMentions(QString handledText, QList<Mention> *mentions);
|
||||
void handleMessage(const QString &text, QString handledText, ChatBarCache *chatBarCache);
|
||||
};
|
||||
@@ -11,7 +11,6 @@ ecm_add_qml_module(chatbar GENERATE_PLUGIN_SOURCE
|
||||
CompletionMenu.qml
|
||||
EmojiDelegate.qml
|
||||
EmojiGrid.qml
|
||||
ReplyPane.qml
|
||||
PieProgressBar.qml
|
||||
EmojiPicker.qml
|
||||
EmojiDialog.qml
|
||||
|
||||
@@ -53,14 +53,6 @@ QQC2.Control {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The ActionsHandler object to use.
|
||||
*
|
||||
* This is expected to have the correct room set otherwise messages will be sent
|
||||
* to the wrong room.
|
||||
*/
|
||||
required property ActionsHandler actionsHandler
|
||||
|
||||
/**
|
||||
* @brief The list of actions in the ChatBar.
|
||||
*
|
||||
@@ -175,6 +167,7 @@ QQC2.Control {
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: Kirigami.Units.largeSpacing
|
||||
Layout.preferredHeight: active ? item.implicitHeight : 0
|
||||
|
||||
active: visible
|
||||
visible: root.currentRoom.mainCache.replyId.length > 0 || root.currentRoom.mainCache.attachmentPath.length > 0
|
||||
@@ -183,13 +176,14 @@ QQC2.Control {
|
||||
RowLayout {
|
||||
QQC2.ScrollView {
|
||||
id: chatBarScrollView
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
Layout.bottomMargin: Kirigami.Units.smallSpacing
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumHeight: Kirigami.Units.gridUnit * 8
|
||||
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
Layout.bottomMargin: Kirigami.Units.smallSpacing
|
||||
Layout.minimumHeight: Kirigami.Units.gridUnit * 2
|
||||
Layout.minimumHeight: Kirigami.Units.gridUnit * 3
|
||||
|
||||
// HACK: This is to stop the ScrollBar flickering on and off as the height is increased
|
||||
QQC2.ScrollBar.vertical.policy: chatBarHeightAnimation.running && implicitHeight <= height ? QQC2.ScrollBar.AlwaysOff : QQC2.ScrollBar.AsNeeded
|
||||
@@ -219,7 +213,7 @@ QQC2.Control {
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
if (!repeatTimer.running && Config.typingNotifications) {
|
||||
if (!repeatTimer.running && NeoChatConfig.typingNotifications) {
|
||||
var textExists = text.length > 0;
|
||||
root.currentRoom.sendTypingNotification(textExists);
|
||||
textExists ? repeatTimer.start() : repeatTimer.stop();
|
||||
@@ -258,20 +252,22 @@ QQC2.Control {
|
||||
}
|
||||
}
|
||||
Keys.onEnterPressed: event => {
|
||||
const controlIsPressed = event.modifiers & Qt.ControlModifier;
|
||||
if (completionMenu.visible) {
|
||||
completionMenu.complete();
|
||||
} else if (event.modifiers & Qt.ShiftModifier || Kirigami.Settings.isMobile) {
|
||||
} else if (event.modifiers & Qt.ShiftModifier || Kirigami.Settings.isMobile || NeoChatConfig.sendMessageWith === 1 && !controlIsPressed || NeoChatConfig.sendMessageWith === 0 && controlIsPressed) {
|
||||
textField.insert(cursorPosition, "\n");
|
||||
} else {
|
||||
} else if (NeoChatConfig.sendMessageWith === 0 && !controlIsPressed || NeoChatConfig.sendMessageWith === 1 && controlIsPressed) {
|
||||
_private.postMessage();
|
||||
}
|
||||
}
|
||||
Keys.onReturnPressed: event => {
|
||||
const controlIsPressed = event.modifiers & Qt.ControlModifier;
|
||||
if (completionMenu.visible) {
|
||||
completionMenu.complete();
|
||||
} else if (event.modifiers & Qt.ShiftModifier || Kirigami.Settings.isMobile) {
|
||||
} else if (event.modifiers & Qt.ShiftModifier || Kirigami.Settings.isMobile || NeoChatConfig.sendMessageWith === 1 && !controlIsPressed || NeoChatConfig.sendMessageWith === 0 && controlIsPressed) {
|
||||
textField.insert(cursorPosition, "\n");
|
||||
} else {
|
||||
} else if (NeoChatConfig.sendMessageWith === 0 && !controlIsPressed || NeoChatConfig.sendMessageWith === 1 && controlIsPressed) {
|
||||
_private.postMessage();
|
||||
}
|
||||
}
|
||||
@@ -325,12 +321,11 @@ QQC2.Control {
|
||||
id: actionsRow
|
||||
spacing: 0
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
Layout.bottomMargin: Kirigami.Units.smallSpacing * 1.5
|
||||
Layout.bottomMargin: Kirigami.Units.smallSpacing * 4
|
||||
|
||||
Repeater {
|
||||
model: root.actions
|
||||
delegate: QQC2.ToolButton {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
icon.name: modelData.isBusy ? "" : (modelData.icon.name.length > 0 ? modelData.icon.name : modelData.icon.source)
|
||||
onClicked: modelData.trigger()
|
||||
|
||||
@@ -347,29 +342,45 @@ QQC2.Control {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DelegateSizeHelper {
|
||||
id: chatBarSizeHelper
|
||||
startBreakpoint: Kirigami.Units.gridUnit * 46
|
||||
endBreakpoint: Kirigami.Units.gridUnit * 66
|
||||
startPercentWidth: 100
|
||||
endPercentWidth: Config.compactLayout ? 100 : 85
|
||||
maxWidth: Config.compactLayout ? -1 : Kirigami.Units.gridUnit * 60
|
||||
endPercentWidth: NeoChatConfig.compactLayout ? 100 : 85
|
||||
maxWidth: NeoChatConfig.compactLayout ? -1 : Kirigami.Units.gridUnit * 60
|
||||
|
||||
parentWidth: root.width
|
||||
}
|
||||
|
||||
Component {
|
||||
id: replyPane
|
||||
ReplyPane {
|
||||
userName: _private.chatBarCache.relationUser.displayName
|
||||
userColor: _private.chatBarCache.relationUser.color
|
||||
userAvatar: _private.chatBarCache.relationUser.avatarUrl
|
||||
text: _private.chatBarCache.relationMessage
|
||||
Item {
|
||||
implicitWidth: replyComponent.implicitWidth
|
||||
implicitHeight: replyComponent.implicitHeight
|
||||
ReplyComponent {
|
||||
id: replyComponent
|
||||
replyEventId: _private.chatBarCache.replyId
|
||||
replyAuthor: _private.chatBarCache.relationAuthor
|
||||
replyContentModel: _private.chatBarCache.relationEventContentModel
|
||||
maxContentWidth: paneLoader.item.width
|
||||
}
|
||||
QQC2.Button {
|
||||
id: cancelButton
|
||||
|
||||
onCancel: {
|
||||
_private.chatBarCache.replyId = "";
|
||||
_private.chatBarCache.attachmentPath = "";
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
text: i18nc("@action:button", "Cancel reply")
|
||||
icon.name: "dialog-close"
|
||||
onClicked: {
|
||||
_private.chatBarCache.replyId = "";
|
||||
_private.chatBarCache.attachmentPath = "";
|
||||
}
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -391,11 +402,10 @@ QQC2.Control {
|
||||
onChatBarCacheChanged: documentHandler.chatBarCache = chatBarCache
|
||||
|
||||
function postMessage() {
|
||||
root.actionsHandler.handleMessageEvent(_private.chatBarCache);
|
||||
_private.chatBarCache.postMessage();
|
||||
repeatTimer.stop();
|
||||
root.currentRoom.markAllMessagesAsRead();
|
||||
textField.clear();
|
||||
_private.chatBarCache.replyId = "";
|
||||
messageSent();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ QQC2.ItemDelegate {
|
||||
Kirigami.Icon {
|
||||
width: Kirigami.Units.gridUnit * 0.5
|
||||
height: Kirigami.Units.gridUnit * 0.5
|
||||
source: "arrow-down"
|
||||
source: "arrow-down-symbolic"
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
visible: root.showTones
|
||||
@@ -43,6 +43,9 @@ QQC2.ItemDelegate {
|
||||
anchors.fill: parent
|
||||
visible: root.emoji.startsWith("mxc") || root.isImage
|
||||
source: visible ? root.emoji : ""
|
||||
fillMode: Image.PreserveAspectFit
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ QQC2.ScrollView {
|
||||
|
||||
Kirigami.PlaceholderMessage {
|
||||
anchors.centerIn: parent
|
||||
icon.name: root.stickers ? "stickers" : "preferences-desktop-emoticons"
|
||||
text: root.stickers ? i18n("No stickers") : i18n("No emojis")
|
||||
visible: emojis.count === 0
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: root.categoryIconSize + QQC2.ScrollBar.horizontal.height
|
||||
QQC2.ScrollBar.horizontal.height: QQC2.ScrollBar.horizontal.visible ? QQC2.ScrollBar.horizontal.implicitHeight : 0
|
||||
visible: categories.count !== 0
|
||||
|
||||
ListView {
|
||||
id: categories
|
||||
@@ -201,8 +202,13 @@ ColumnLayout {
|
||||
width: root.categoryIconSize
|
||||
height: width
|
||||
checked: stickerModel.packIndex === model.index
|
||||
padding: Kirigami.Units.largeSpacing
|
||||
|
||||
contentItem: Image {
|
||||
source: model.avatarUrl
|
||||
fillMode: Image.PreserveAspectFit
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
}
|
||||
QQC2.ToolTip.text: model.name
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.de>
|
||||
// SPDX-FileCopyrightText: 2020 Noah Davis <noahadvs@gmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls as QQC2
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
property string userName
|
||||
property color userColor
|
||||
property url userAvatar: ""
|
||||
property var text
|
||||
|
||||
signal cancel
|
||||
|
||||
Rectangle {
|
||||
id: verticalBorder
|
||||
|
||||
Layout.fillHeight: true
|
||||
|
||||
implicitWidth: Kirigami.Units.smallSpacing
|
||||
color: userColor
|
||||
}
|
||||
ColumnLayout {
|
||||
RowLayout {
|
||||
KirigamiComponents.Avatar {
|
||||
id: replyAvatar
|
||||
|
||||
implicitWidth: Kirigami.Units.iconSizes.small
|
||||
implicitHeight: Kirigami.Units.iconSizes.small
|
||||
|
||||
source: userAvatar
|
||||
name: userName
|
||||
color: userColor
|
||||
}
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
|
||||
color: userColor
|
||||
text: userName
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
QQC2.TextArea {
|
||||
id: textArea
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
text: "<style> a{color:" + Kirigami.Theme.linkColor + ";}.user-pill{}</style>" + replyTextMetrics.elidedText
|
||||
selectByMouse: true
|
||||
selectByKeyboard: true
|
||||
readOnly: true
|
||||
wrapMode: TextEdit.Wrap
|
||||
textFormat: TextEdit.RichText
|
||||
background: Item {}
|
||||
HoverHandler {
|
||||
cursorShape: textArea.hoveredLink ? Qt.PointingHandCursor : Qt.IBeamCursor
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: replyTextMetrics
|
||||
|
||||
text: root.text
|
||||
font: textArea.font
|
||||
elide: Qt.ElideRight
|
||||
elideWidth: textArea.width * 2 - Kirigami.Units.smallSpacing * 2
|
||||
}
|
||||
}
|
||||
}
|
||||
QQC2.ToolButton {
|
||||
id: cancelButton
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
text: i18nc("@action:button", "Cancel reply")
|
||||
icon.name: "dialog-close"
|
||||
onClicked: {
|
||||
root.cancel();
|
||||
}
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,9 @@
|
||||
|
||||
#include "chatdocumenthandler.h"
|
||||
#include "eventhandler.h"
|
||||
#include "models/actionsmodel.h"
|
||||
#include "neochatroom.h"
|
||||
#include "texthandler.h"
|
||||
|
||||
ChatBarCache::ChatBarCache(QObject *parent)
|
||||
: QObject(parent)
|
||||
@@ -28,6 +30,37 @@ void ChatBarCache::setText(const QString &text)
|
||||
Q_EMIT textChanged();
|
||||
}
|
||||
|
||||
QString ChatBarCache::sendText() const
|
||||
{
|
||||
if (!attachmentPath().isEmpty()) {
|
||||
QUrl url(attachmentPath());
|
||||
auto path = url.isLocalFile() ? url.toLocalFile() : url.toString();
|
||||
return text().isEmpty() ? path.mid(path.lastIndexOf(u'/') + 1) : text();
|
||||
}
|
||||
|
||||
return formatMentions();
|
||||
}
|
||||
|
||||
QString ChatBarCache::formatMentions() const
|
||||
{
|
||||
auto mentions = m_mentions;
|
||||
std::sort(mentions.begin(), mentions.end(), [](const auto &a, const auto &b) {
|
||||
return a.cursor.anchor() > b.cursor.anchor();
|
||||
});
|
||||
|
||||
auto formattedText = text();
|
||||
for (const auto &mention : mentions) {
|
||||
if (mention.text.isEmpty() || mention.id.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
formattedText = formattedText.replace(mention.cursor.anchor(),
|
||||
mention.cursor.position() - mention.cursor.anchor(),
|
||||
QStringLiteral("[%1](https://matrix.to/#/%2)").arg(mention.text.toHtmlEscaped(), mention.id));
|
||||
}
|
||||
|
||||
return formattedText;
|
||||
}
|
||||
|
||||
bool ChatBarCache::isReplying() const
|
||||
{
|
||||
return m_relationType == Reply && !m_relationId.isEmpty();
|
||||
@@ -53,6 +86,7 @@ void ChatBarCache::setReplyId(const QString &replyId)
|
||||
m_relationType = Reply;
|
||||
}
|
||||
m_attachmentPath = QString();
|
||||
delete m_relationContentModel;
|
||||
Q_EMIT relationIdChanged(oldEventId, m_relationId);
|
||||
Q_EMIT attachmentPathChanged();
|
||||
}
|
||||
@@ -82,11 +116,12 @@ void ChatBarCache::setEditId(const QString &editId)
|
||||
m_relationType = Edit;
|
||||
}
|
||||
m_attachmentPath = QString();
|
||||
delete m_relationContentModel;
|
||||
Q_EMIT relationIdChanged(oldEventId, m_relationId);
|
||||
Q_EMIT attachmentPathChanged();
|
||||
}
|
||||
|
||||
Quotient::RoomMember ChatBarCache::relationUser() const
|
||||
Quotient::RoomMember ChatBarCache::relationAuthor() const
|
||||
{
|
||||
if (parent() == nullptr) {
|
||||
qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.";
|
||||
@@ -119,16 +154,33 @@ QString ChatBarCache::relationMessage() const
|
||||
}
|
||||
|
||||
if (auto event = room->findInTimeline(m_relationId); event != room->historyEdge()) {
|
||||
EventHandler eventhandler(room, &**event);
|
||||
if (isEditing()) {
|
||||
return eventhandler.getMarkdownBody();
|
||||
} else {
|
||||
return eventhandler.getMarkdownBody().toHtmlEscaped();
|
||||
}
|
||||
return EventHandler::markdownBody(&**event);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
MessageContentModel *ChatBarCache::relationEventContentModel()
|
||||
{
|
||||
if (parent() == nullptr) {
|
||||
qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.";
|
||||
return nullptr;
|
||||
}
|
||||
if (m_relationId.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (m_relationContentModel != nullptr) {
|
||||
return m_relationContentModel;
|
||||
}
|
||||
|
||||
auto room = dynamic_cast<NeoChatRoom *>(parent());
|
||||
if (room == nullptr) {
|
||||
qWarning() << "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.";
|
||||
return nullptr;
|
||||
}
|
||||
m_relationContentModel = new MessageContentModel(room, m_relationId, true);
|
||||
return m_relationContentModel;
|
||||
}
|
||||
|
||||
bool ChatBarCache::isThreaded() const
|
||||
{
|
||||
return !m_threadId.isEmpty();
|
||||
@@ -144,8 +196,8 @@ void ChatBarCache::setThreadId(const QString &threadId)
|
||||
if (m_threadId == threadId) {
|
||||
return;
|
||||
}
|
||||
m_threadId = threadId;
|
||||
Q_EMIT threadIdChanged();
|
||||
const auto oldThreadId = std::exchange(m_threadId, threadId);
|
||||
Q_EMIT threadIdChanged(oldThreadId, m_threadId);
|
||||
}
|
||||
|
||||
QString ChatBarCache::attachmentPath() const
|
||||
@@ -161,10 +213,22 @@ void ChatBarCache::setAttachmentPath(const QString &attachmentPath)
|
||||
m_attachmentPath = attachmentPath;
|
||||
m_relationType = None;
|
||||
const auto oldEventId = std::exchange(m_relationId, QString());
|
||||
delete m_relationContentModel;
|
||||
Q_EMIT attachmentPathChanged();
|
||||
Q_EMIT relationIdChanged(oldEventId, m_relationId);
|
||||
}
|
||||
|
||||
void ChatBarCache::clearRelations()
|
||||
{
|
||||
const auto oldEventId = std::exchange(m_relationId, QString());
|
||||
const auto oldThreadId = std::exchange(m_threadId, QString());
|
||||
m_attachmentPath = QString();
|
||||
delete m_relationContentModel;
|
||||
Q_EMIT relationIdChanged(oldEventId, m_relationId);
|
||||
Q_EMIT threadIdChanged(oldThreadId, m_threadId);
|
||||
Q_EMIT attachmentPathChanged();
|
||||
}
|
||||
|
||||
QList<Mention> *ChatBarCache::mentions()
|
||||
{
|
||||
return &m_mentions;
|
||||
@@ -228,4 +292,44 @@ void ChatBarCache::setSavedText(const QString &savedText)
|
||||
m_savedText = savedText;
|
||||
}
|
||||
|
||||
void ChatBarCache::postMessage()
|
||||
{
|
||||
auto room = dynamic_cast<NeoChatRoom *>(parent());
|
||||
if (room == nullptr) {
|
||||
qWarning() << "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!attachmentPath().isEmpty()) {
|
||||
room->uploadFile(QUrl(attachmentPath()), sendText());
|
||||
clearCache();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto result = ActionsModel::handleAction(room, this);
|
||||
if (!result.first.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TextHandler textHandler;
|
||||
textHandler.setData(*std::get<std::optional<QString>>(result));
|
||||
const auto sendText = textHandler.handleSendText();
|
||||
|
||||
if (sendText.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto type = std::get<std::optional<Quotient::RoomMessageEvent::MsgType>>(result);
|
||||
room->postMessage(text(), sendText, type ? *type : Quotient::RoomMessageEvent::MsgType::Text, replyId(), editId(), threadId());
|
||||
clearCache();
|
||||
}
|
||||
|
||||
void ChatBarCache::clearCache()
|
||||
{
|
||||
setText({});
|
||||
m_mentions.clear();
|
||||
m_savedText = QString();
|
||||
clearRelations();
|
||||
}
|
||||
|
||||
#include "moc_chatbarcache.cpp"
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <QQuickTextDocument>
|
||||
#include <QTextCursor>
|
||||
|
||||
#include "models/messagecontentmodel.h"
|
||||
|
||||
class ChatDocumentHandler;
|
||||
|
||||
namespace Quotient
|
||||
@@ -33,7 +35,7 @@ struct Mention {
|
||||
* A class to cache data from a chat bar.
|
||||
*
|
||||
* A chat bar can be anything that allows users to compose or edit message, it doesn't
|
||||
* necessarily have to use the ChatBar component, e.g. MessageEditComponent.
|
||||
* necessarily have to use the ChatBar component, e.g. ChatBarComponent.
|
||||
*
|
||||
* This object is intended to allow the current contents of a chat bar to be cached
|
||||
* between different rooms, i.e. there is an expectation that each NeoChatRoom could
|
||||
@@ -43,7 +45,7 @@ struct Mention {
|
||||
* as it's parent. This is necessary for certain functions which need to get
|
||||
* relevant room information.
|
||||
*
|
||||
* @sa ChatBar, MessageEditComponent, NeoChatRoom
|
||||
* @sa ChatBar, ChatBarComponent, NeoChatRoom
|
||||
*/
|
||||
class ChatBarCache : public QObject
|
||||
{
|
||||
@@ -100,7 +102,7 @@ class ChatBarCache : public QObject
|
||||
*
|
||||
* @sa Quotient::RoomMember
|
||||
*/
|
||||
Q_PROPERTY(Quotient::RoomMember relationUser READ relationUser NOTIFY relationIdChanged)
|
||||
Q_PROPERTY(Quotient::RoomMember relationAuthor READ relationAuthor NOTIFY relationIdChanged)
|
||||
|
||||
/**
|
||||
* @brief The content of the related message.
|
||||
@@ -109,6 +111,13 @@ class ChatBarCache : public QObject
|
||||
*/
|
||||
Q_PROPERTY(QString relationMessage READ relationMessage NOTIFY relationIdChanged)
|
||||
|
||||
/**
|
||||
* @brief The MessageContentModel for the related message.
|
||||
*
|
||||
* Will be nullptr if no related message.
|
||||
*/
|
||||
Q_PROPERTY(MessageContentModel *relationEventContentModel READ relationEventContentModel NOTIFY relationIdChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the chat bar is replying in a thread.
|
||||
*/
|
||||
@@ -144,6 +153,7 @@ public:
|
||||
explicit ChatBarCache(QObject *parent = nullptr);
|
||||
|
||||
QString text() const;
|
||||
QString sendText() const;
|
||||
void setText(const QString &text);
|
||||
|
||||
bool isReplying() const;
|
||||
@@ -154,9 +164,10 @@ public:
|
||||
QString editId() const;
|
||||
void setEditId(const QString &editId);
|
||||
|
||||
Quotient::RoomMember relationUser() const;
|
||||
Quotient::RoomMember relationAuthor() const;
|
||||
|
||||
QString relationMessage() const;
|
||||
MessageContentModel *relationEventContentModel();
|
||||
|
||||
bool isThreaded() const;
|
||||
QString threadId() const;
|
||||
@@ -165,6 +176,13 @@ public:
|
||||
QString attachmentPath() const;
|
||||
void setAttachmentPath(const QString &attachmentPath);
|
||||
|
||||
/**
|
||||
* @brief Clear all relations in the cache.
|
||||
*
|
||||
* This includes relation ID, thread root ID and attachment path.
|
||||
*/
|
||||
Q_INVOKABLE void clearRelations();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the mentions for the current chat bar text.
|
||||
*/
|
||||
@@ -185,18 +203,29 @@ public:
|
||||
*/
|
||||
void setSavedText(const QString &savedText);
|
||||
|
||||
/**
|
||||
* @brief Post the contents of the cache as a message in the room.
|
||||
*/
|
||||
Q_INVOKABLE void postMessage();
|
||||
|
||||
Q_SIGNALS:
|
||||
void textChanged();
|
||||
void relationIdChanged(const QString &oldEventId, const QString &newEventId);
|
||||
void threadIdChanged();
|
||||
void threadIdChanged(const QString &oldThreadId, const QString &newThreadId);
|
||||
void attachmentPathChanged();
|
||||
|
||||
private:
|
||||
QString m_text = QString();
|
||||
QString formatMentions() const;
|
||||
|
||||
QString m_relationId = QString();
|
||||
RelationType m_relationType = RelationType::None;
|
||||
QString m_threadId = QString();
|
||||
QString m_attachmentPath = QString();
|
||||
QList<Mention> m_mentions;
|
||||
QString m_savedText;
|
||||
|
||||
QPointer<MessageContentModel> m_relationContentModel;
|
||||
|
||||
void clearCache();
|
||||
};
|
||||
|
||||
@@ -26,23 +26,9 @@ void ColorSchemer::apply(int idx)
|
||||
c->activateScheme(c->model()->index(idx, 0));
|
||||
}
|
||||
|
||||
void ColorSchemer::apply(const QString &name)
|
||||
int ColorSchemer::indexForCurrentScheme()
|
||||
{
|
||||
c->activateScheme(c->indexForScheme(name));
|
||||
}
|
||||
|
||||
int ColorSchemer::indexForScheme(const QString &name) const
|
||||
{
|
||||
auto index = c->indexForScheme(name).row();
|
||||
if (index == -1) {
|
||||
index = 0;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
QString ColorSchemer::nameForIndex(int index) const
|
||||
{
|
||||
return c->model()->data(c->model()->index(index, 0), Qt::DisplayRole).toString();
|
||||
return c->indexForSchemeId(c->activeSchemeId()).row();
|
||||
}
|
||||
|
||||
#include "moc_colorschemer.cpp"
|
||||
|
||||
@@ -44,21 +44,11 @@ public:
|
||||
Q_INVOKABLE void apply(int idx);
|
||||
|
||||
/**
|
||||
* @brief Activates the KColorScheme with the given name.
|
||||
* @brief Get the row for the current color scheme.
|
||||
*
|
||||
* @sa KColorScheme
|
||||
*/
|
||||
Q_INVOKABLE void apply(const QString &name);
|
||||
|
||||
/**
|
||||
* @brief Returns the index for the scheme with the given name.
|
||||
*/
|
||||
Q_INVOKABLE int indexForScheme(const QString &name) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the name for the scheme with the given index.
|
||||
*/
|
||||
Q_INVOKABLE QString nameForIndex(int index) const;
|
||||
Q_INVOKABLE int indexForCurrentScheme();
|
||||
|
||||
private:
|
||||
KColorSchemeManager *c;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <Quotient/accountregistry.h>
|
||||
#include <Quotient/csapi/notifications.h>
|
||||
#include <Quotient/qt_connection_util.h>
|
||||
#include <Quotient/settings.h>
|
||||
@@ -64,11 +63,7 @@ Controller::Controller(QObject *parent)
|
||||
});
|
||||
} else {
|
||||
auto c = new NeoChatConnection(this);
|
||||
#if Quotient_VERSION_MINOR > 8
|
||||
c->assumeIdentity(QStringLiteral("@user:localhost:1234"), QStringLiteral("device_1234"), QStringLiteral("token_1234"));
|
||||
#else
|
||||
c->assumeIdentity(QStringLiteral("@user:localhost:1234"), QStringLiteral("token_1234"));
|
||||
#endif
|
||||
connect(c, &Connection::connected, this, [c, this]() {
|
||||
m_accountRegistry.add(c);
|
||||
c->syncLoop();
|
||||
@@ -170,6 +165,9 @@ void Controller::addConnection(NeoChatConnection *c)
|
||||
dropConnection(c);
|
||||
});
|
||||
connect(c, &NeoChatConnection::badgeNotificationCountChanged, this, &Controller::updateBadgeNotificationCount);
|
||||
connect(c, &NeoChatConnection::syncDone, this, [this, c]() {
|
||||
m_notificationsManager.handleNotifications(c);
|
||||
});
|
||||
|
||||
c->sync();
|
||||
|
||||
@@ -180,6 +178,8 @@ void Controller::dropConnection(NeoChatConnection *c)
|
||||
{
|
||||
Q_ASSERT_X(c, __FUNCTION__, "Attempt to drop a null connection");
|
||||
|
||||
c->disconnect(this);
|
||||
c->disconnect(&m_notificationsManager);
|
||||
m_accountRegistry.drop(c);
|
||||
Q_EMIT connectionDropped(c);
|
||||
}
|
||||
@@ -225,14 +225,7 @@ void Controller::invokeLogin()
|
||||
Qt::SingleShotConnection);
|
||||
}
|
||||
});
|
||||
connect(connection, &NeoChatConnection::networkError, this, [this](const QString &error, const QString &, int, int) {
|
||||
Q_EMIT errorOccured(i18n("Network Error: %1", error), {});
|
||||
});
|
||||
#if Quotient_VERSION_MINOR > 8
|
||||
connection->assumeIdentity(account.userId(), account.deviceId(), accessToken);
|
||||
#else
|
||||
connection->assumeIdentity(account.userId(), accessToken);
|
||||
#endif
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -252,17 +245,17 @@ QKeychain::ReadPasswordJob *Controller::loadAccessTokenFromKeyChain(const QStrin
|
||||
|
||||
switch (job->error()) {
|
||||
case QKeychain::EntryNotFound:
|
||||
Q_EMIT errorOccured(i18n("Access token wasn't found"), i18n("Maybe it was deleted?"));
|
||||
Q_EMIT errorOccured(i18n("Access token wasn't found: Maybe it was deleted?"));
|
||||
break;
|
||||
case QKeychain::AccessDeniedByUser:
|
||||
case QKeychain::AccessDenied:
|
||||
Q_EMIT errorOccured(i18n("Access to keychain was denied."), i18n("Please allow NeoChat to read the access token"));
|
||||
Q_EMIT errorOccured(i18n("Access to keychain was denied: Please allow NeoChat to read the access token"));
|
||||
break;
|
||||
case QKeychain::NoBackendAvailable:
|
||||
Q_EMIT errorOccured(i18n("No keychain available."), i18n("Please install a keychain, e.g. KWallet or GNOME keyring on Linux"));
|
||||
Q_EMIT errorOccured(i18n("No keychain available: Please install a keychain, e.g. KWallet or GNOME keyring on Linux"));
|
||||
break;
|
||||
case QKeychain::OtherError:
|
||||
Q_EMIT errorOccured(i18n("Unable to read access token"), job->errorString());
|
||||
Q_EMIT errorOccured(i18n("Unable to read access token: %1", job->errorString()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -327,11 +320,18 @@ void Controller::setActiveConnection(NeoChatConnection *connection)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_connection != nullptr) {
|
||||
m_connection->disconnect(this);
|
||||
m_connection->disconnect(&m_notificationsManager);
|
||||
}
|
||||
|
||||
m_connection = connection;
|
||||
|
||||
if (m_connection != nullptr) {
|
||||
m_connection->refreshBadgeNotificationCount();
|
||||
updateBadgeNotificationCount(m_connection, m_connection->badgeNotificationCount());
|
||||
|
||||
connect(m_connection, &NeoChatConnection::errorOccured, this, &Controller::errorOccured);
|
||||
}
|
||||
|
||||
Q_EMIT activeConnectionChanged(m_connection);
|
||||
@@ -346,7 +346,7 @@ void Controller::listenForNotifications()
|
||||
connect(timer, &QTimer::timeout, qGuiApp, &QGuiApplication::quit);
|
||||
|
||||
connect(connector, &KUnifiedPush::Connector::messageReceived, [timer](const QByteArray &data) {
|
||||
NotificationsManager::instance().postPushNotification(data);
|
||||
instance().m_notificationsManager.postPushNotification(data);
|
||||
timer->stop();
|
||||
});
|
||||
|
||||
@@ -358,6 +358,11 @@ void Controller::listenForNotifications()
|
||||
#endif
|
||||
}
|
||||
|
||||
void Controller::clearInvitationNotification(const QString &roomId)
|
||||
{
|
||||
m_notificationsManager.clearInvitationNotification(roomId);
|
||||
}
|
||||
|
||||
void Controller::updateBadgeNotificationCount(NeoChatConnection *connection, int count)
|
||||
{
|
||||
if (connection == m_connection) {
|
||||
@@ -417,21 +422,38 @@ void Controller::setTestMode(bool test)
|
||||
|
||||
void Controller::removeConnection(const QString &userId)
|
||||
{
|
||||
if (m_connectionsLoading.contains(userId) && m_connectionsLoading[userId]) {
|
||||
auto connection = m_connectionsLoading[userId];
|
||||
// When loadAccessTokenFromKeyChain() fails m_connectionsLoading won't have an
|
||||
// entry for it so we need to check both separately.
|
||||
if (m_accountsLoading.contains(userId)) {
|
||||
m_accountsLoading.removeAll(userId);
|
||||
Q_EMIT accountsLoadingChanged();
|
||||
}
|
||||
if (m_connectionsLoading.contains(userId) && m_connectionsLoading[userId]) {
|
||||
auto connection = m_connectionsLoading[userId];
|
||||
SettingsGroup("Accounts"_ls).remove(userId);
|
||||
}
|
||||
}
|
||||
|
||||
bool Controller::csSupported() const
|
||||
{
|
||||
#if Quotient_VERSION_MINOR > 9
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Controller::revertToDefaultConfig()
|
||||
{
|
||||
const auto config = NeoChatConfig::self();
|
||||
config->setDefaults();
|
||||
config->save();
|
||||
}
|
||||
|
||||
bool Controller::isImageShown(const QString &eventId)
|
||||
{
|
||||
return m_shownImages.contains(eventId);
|
||||
}
|
||||
|
||||
void Controller::markImageShown(const QString &eventId)
|
||||
{
|
||||
m_shownImages.append(eventId);
|
||||
}
|
||||
|
||||
#include "moc_controller.cpp"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include "neochatconnection.h"
|
||||
#include "notificationsmanager.h"
|
||||
#include <Quotient/accountregistry.h>
|
||||
|
||||
class TrayIcon;
|
||||
@@ -53,16 +54,6 @@ class Controller : public QObject
|
||||
Q_PROPERTY(bool csSupported READ csSupported CONSTANT)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Define the types on inline messages that can be shown.
|
||||
*/
|
||||
enum MessageType {
|
||||
Positive, /**< Positive message, typically green. */
|
||||
Info, /**< Info message, typically highlight color. */
|
||||
Error, /**< Error message, typically red. */
|
||||
};
|
||||
Q_ENUM(MessageType)
|
||||
|
||||
static Controller &instance();
|
||||
static Controller *create(QQmlEngine *engine, QJSEngine *)
|
||||
{
|
||||
@@ -98,6 +89,13 @@ public:
|
||||
*/
|
||||
static void listenForNotifications();
|
||||
|
||||
/**
|
||||
* @brief Clear an existing invite notification for the given room.
|
||||
*
|
||||
* Nothing happens if the given room doesn't have an invite notification.
|
||||
*/
|
||||
Q_INVOKABLE void clearInvitationNotification(const QString &roomId);
|
||||
|
||||
Q_INVOKABLE QString loadFileContent(const QString &path) const;
|
||||
|
||||
Quotient::AccountRegistry &accounts();
|
||||
@@ -108,6 +106,17 @@ public:
|
||||
|
||||
bool csSupported() const;
|
||||
|
||||
/**
|
||||
* @brief Revert all configuration values to their default.
|
||||
*
|
||||
* The parameters along with their defaults are specified in the config file
|
||||
* neochatconfig.kcfg.
|
||||
*/
|
||||
Q_INVOKABLE void revertToDefaultConfig();
|
||||
|
||||
Q_INVOKABLE bool isImageShown(const QString &eventId);
|
||||
Q_INVOKABLE void markImageShown(const QString &eventId);
|
||||
|
||||
private:
|
||||
explicit Controller(QObject *parent = nullptr);
|
||||
|
||||
@@ -116,13 +125,13 @@ private:
|
||||
|
||||
QKeychain::ReadPasswordJob *loadAccessTokenFromKeyChain(const QString &account);
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings() const;
|
||||
|
||||
Quotient::AccountRegistry m_accountRegistry;
|
||||
QStringList m_accountsLoading;
|
||||
QMap<QString, QPointer<NeoChatConnection>> m_connectionsLoading;
|
||||
QString m_endpoint;
|
||||
QStringList m_shownImages;
|
||||
|
||||
NotificationsManager m_notificationsManager;
|
||||
|
||||
private Q_SLOTS:
|
||||
void invokeLogin();
|
||||
@@ -130,10 +139,12 @@ private Q_SLOTS:
|
||||
void updateBadgeNotificationCount(NeoChatConnection *connection, int count);
|
||||
|
||||
Q_SIGNALS:
|
||||
void errorOccured(const QString &error, const QString &detail);
|
||||
/**
|
||||
* @brief Request a error message be shown to the user.
|
||||
*/
|
||||
void errorOccured(const QString &error);
|
||||
void connectionAdded(NeoChatConnection *connection);
|
||||
void connectionDropped(NeoChatConnection *connection);
|
||||
void activeConnectionChanged(NeoChatConnection *connection);
|
||||
void accountsLoadingChanged();
|
||||
void showMessage(MessageType messageType, const QString &message);
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Window
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
@@ -23,7 +24,7 @@ ColumnLayout {
|
||||
model: root.connection.accountDataEventTypes
|
||||
delegate: FormCard.FormButtonDelegate {
|
||||
text: modelData
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
onClicked: root.Window.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
sourceText: root.connection.accountDataJsonString(modelData)
|
||||
}, {
|
||||
title: i18nc("@title:window", "Event Source"),
|
||||
|
||||
@@ -17,25 +17,25 @@ FormCard.FormCardPage {
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
text: i18nc("@option:check", "Show hidden events in the timeline")
|
||||
checked: Config.showAllEvents
|
||||
checked: NeoChatConfig.showAllEvents
|
||||
|
||||
onToggled: Config.showAllEvents = checked
|
||||
onToggled: NeoChatConfig.showAllEvents = checked
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
id: roomAccountDataVisibleCheck
|
||||
text: i18nc("@option:check Enable the matrix 'threads' feature", "Always allow device verification")
|
||||
description: i18n("Allow the user to start a verification session with devices that were already verified")
|
||||
checked: Config.alwaysVerifyDevice
|
||||
checked: NeoChatConfig.alwaysVerifyDevice
|
||||
|
||||
onToggled: Config.alwaysVerifyDevice = checked
|
||||
onToggled: NeoChatConfig.alwaysVerifyDevice = checked
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
text: i18nc("@option:check", "Show focus in window header")
|
||||
checked: Config.windowTitleFocus
|
||||
checked: NeoChatConfig.windowTitleFocus
|
||||
|
||||
onToggled: {
|
||||
Config.windowTitleFocus = checked;
|
||||
Config.save();
|
||||
NeoChatConfig.windowTitleFocus = checked;
|
||||
NeoChatConfig.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,23 +18,23 @@ FormCard.FormCardPage {
|
||||
FormCard.FormCheckDelegate {
|
||||
id: roomAccountDataVisibleCheck
|
||||
text: i18nc("@option:check Enable the matrix 'threads' feature", "Threads")
|
||||
checked: Config.threads
|
||||
checked: NeoChatConfig.threads
|
||||
|
||||
onToggled: Config.threads = checked
|
||||
onToggled: NeoChatConfig.threads = checked
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
text: i18nc("@option:check Enable the matrix 'secret backup' feature", "Secret Backup")
|
||||
checked: Config.secretBackup
|
||||
checked: NeoChatConfig.secretBackup
|
||||
|
||||
onToggled: Config.secretBackup = checked
|
||||
onToggled: NeoChatConfig.secretBackup = checked
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
text: i18nc("@option:check Enable the matrix feature to add a phone number as a third party ID", "Add phone numbers as 3PIDs")
|
||||
checked: Config.phone3PId
|
||||
checked: NeoChatConfig.phone3PId
|
||||
|
||||
onToggled: {
|
||||
Config.phone3PId = checked
|
||||
Config.save();
|
||||
NeoChatConfig.phone3PId = checked
|
||||
NeoChatConfig.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Window
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
@@ -47,7 +48,7 @@ ColumnLayout {
|
||||
model: root.room.accountDataEventTypes
|
||||
delegate: FormCard.FormButtonDelegate {
|
||||
text: modelData
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
onClicked: root.Window.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
sourceText: root.room.roomAcountDataJson(text)
|
||||
}, {
|
||||
title: i18n("Event Source"),
|
||||
@@ -77,7 +78,7 @@ ColumnLayout {
|
||||
if (model.eventCount === 1) {
|
||||
openEventSource(model.type, model.stateKey);
|
||||
} else {
|
||||
pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.devtools', 'StateKeys'), {
|
||||
root.Window.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.devtools', 'StateKeys'), {
|
||||
room: root.room,
|
||||
eventType: model.type
|
||||
}, {
|
||||
@@ -89,7 +90,7 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
function openEventSource(type: string, stateKey: string): void {
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
onClicked: root.Window.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
|
||||
model: stateModel,
|
||||
allowEdit: true,
|
||||
room: root.room,
|
||||
|
||||
@@ -38,6 +38,8 @@ public:
|
||||
ReadMarker, /**< The local user read marker. */
|
||||
Loading, /**< A delegate to tell the user more messages are being loaded. */
|
||||
TimelineEnd, /**< A delegate to inform that all messages are loaded. */
|
||||
Predecessor, /**< A delegate to show a room predecessor. */
|
||||
Successor, /**< A delegate to show a room successor. */
|
||||
Other, /**< Anything that cannot be classified as another type. */
|
||||
};
|
||||
Q_ENUM(Type);
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
Reply, /**< A component to show a replied-to message. */
|
||||
LinkPreview, /**< A preview of a URL in the message. */
|
||||
LinkPreviewLoad, /**< A loading dialog for a link preview. */
|
||||
Edit, /**< A text edit for editing a message. */
|
||||
ChatBar, /**< A text edit for editing a message. */
|
||||
Verification, /**< A user verification session start message. */
|
||||
Loading, /**< The component is loading. */
|
||||
Other, /**< Anything that cannot be classified as another type. */
|
||||
|
||||
31
src/enums/messagetype.h
Normal file
31
src/enums/messagetype.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
|
||||
/**
|
||||
* @class MessageType
|
||||
*
|
||||
* This class is designed to define the MessageType enumeration.
|
||||
*/
|
||||
class MessageType : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("")
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The types of messages that can be shown.
|
||||
*/
|
||||
enum Type {
|
||||
Information = 0, /**< Info message, typically highlight color. */
|
||||
Positive, /**< Positive message, typically green. */
|
||||
Warning, /**< Warning message, typically amber. */
|
||||
Error, /**< Error message, typically red. */
|
||||
};
|
||||
Q_ENUM(Type);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,24 +3,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <KFormat>
|
||||
|
||||
#include <Quotient/eventitem.h>
|
||||
#include <Quotient/events/roomevent.h>
|
||||
#include <Quotient/events/roommessageevent.h>
|
||||
|
||||
#include "enums/messagecomponenttype.h"
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <Quotient/events/eventcontent.h>
|
||||
|
||||
namespace Quotient
|
||||
{
|
||||
namespace EventContent
|
||||
{
|
||||
class FileInfo;
|
||||
}
|
||||
class RoomEvent;
|
||||
class RoomMember;
|
||||
class RoomMessageEvent;
|
||||
}
|
||||
|
||||
class LinkPreviewer;
|
||||
class NeoChatRoom;
|
||||
class ReactionModel;
|
||||
|
||||
/**
|
||||
* @class EventHandler
|
||||
@@ -38,20 +36,14 @@ class ReactionModel;
|
||||
*/
|
||||
class EventHandler
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
public:
|
||||
EventHandler(const NeoChatRoom *room, const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Return the Matrix ID of the event.
|
||||
* @brief Return the ID of the event.
|
||||
*
|
||||
* Returns the transaction ID if the Matrix ID is empty, which may be the case
|
||||
* for a pending event.
|
||||
*/
|
||||
QString getId() const;
|
||||
|
||||
/**
|
||||
* @brief The MessageComponentType to use to visualise the main event content.
|
||||
*/
|
||||
MessageComponentType::Type messageComponentType() const;
|
||||
static QString id(const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Get the display name of the event author.
|
||||
@@ -64,7 +56,7 @@ public:
|
||||
* @param isPending whether the event is pending as this cannot be derived from
|
||||
* just the event object.
|
||||
*/
|
||||
QString getAuthorDisplayName(bool isPending = false) const;
|
||||
static QString authorDisplayName(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending = false);
|
||||
|
||||
/**
|
||||
* @brief Get the display name of the event author but with any newlines removed.
|
||||
@@ -75,12 +67,12 @@ public:
|
||||
* @param isPending whether the event is pending as this cannot be derived from
|
||||
* just the event object.
|
||||
*/
|
||||
QString singleLineAuthorDisplayname(bool isPending = false) const;
|
||||
static QString singleLineAuthorDisplayname(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending = false);
|
||||
|
||||
/**
|
||||
* @brief Return a QDateTime object for the event timestamp.
|
||||
*/
|
||||
QDateTime getTime(bool isPending = false, QDateTime lastUpdated = {}) const;
|
||||
static QDateTime time(const Quotient::RoomEvent *event, bool isPending = false, QDateTime lastUpdated = {});
|
||||
|
||||
/**
|
||||
* @brief Return a QString for the event timestamp.
|
||||
@@ -96,16 +88,32 @@ public:
|
||||
* @param lastUpdated the time the event was last updated locally as this cannot be
|
||||
* obtained from the event.
|
||||
*/
|
||||
QString getTimeString(bool relative, QLocale::FormatType format = QLocale::ShortFormat, bool isPending = false, QDateTime lastUpdated = {}) const;
|
||||
static QString timeString(const Quotient::RoomEvent *event,
|
||||
bool relative,
|
||||
QLocale::FormatType format = QLocale::ShortFormat,
|
||||
bool isPending = false,
|
||||
QDateTime lastUpdated = {});
|
||||
|
||||
QString getTimeString(const QString &format, bool isPending = false, const QDateTime &lastUpdated = {});
|
||||
/**
|
||||
* @brief Return a QString for the event timestamp.
|
||||
*
|
||||
* This is intended to return a string that is read for display in the UI without
|
||||
* any further manipulation required.
|
||||
*
|
||||
* @param format the format to use as a string.
|
||||
* @param isPending whether the event is pending as this cannot be derived from
|
||||
* just the event object.
|
||||
* @param lastUpdated the time the event was last updated locally as this cannot be
|
||||
* obtained from the event.
|
||||
*/
|
||||
static QString timeString(const Quotient::RoomEvent *event, const QString &format, bool isPending = false, const QDateTime &lastUpdated = {});
|
||||
|
||||
/**
|
||||
* @brief Whether the event should be highlighted in the timeline.
|
||||
*
|
||||
* @note Messages in direct chats are never highlighted.
|
||||
*/
|
||||
bool isHighlighted();
|
||||
static bool isHighlighted(const NeoChatRoom *room, const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Whether the event should be hidden in the timeline.
|
||||
@@ -114,7 +122,7 @@ public:
|
||||
* user has hidden all state events or if the sender has been ignored by the local
|
||||
* user.
|
||||
*/
|
||||
bool isHidden();
|
||||
static bool isHidden(const NeoChatRoom *room, const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief The input format of the body in the message.
|
||||
@@ -146,7 +154,7 @@ public:
|
||||
*
|
||||
* @param stripNewlines whether the output should have new lines in it.
|
||||
*/
|
||||
QString getRichBody(bool stripNewlines = false) const;
|
||||
static QString richBody(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool stripNewlines = false);
|
||||
|
||||
/**
|
||||
* @brief Output a string for the message content ready for display in a plain text field.
|
||||
@@ -162,14 +170,14 @@ public:
|
||||
*
|
||||
* @param stripNewlines whether the output should have new lines in it.
|
||||
*/
|
||||
QString getPlainBody(bool stripNewlines = false) const;
|
||||
static QString plainBody(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool stripNewlines = false);
|
||||
|
||||
/**
|
||||
* @brief Output the original body for the message content, useful for editing the original message.
|
||||
*
|
||||
* The event type must be a room message event.
|
||||
*/
|
||||
QString getMarkdownBody() const;
|
||||
static QString markdownBody(const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Output a generic string for the message content ready for display.
|
||||
@@ -182,9 +190,9 @@ public:
|
||||
* E.g. For a message the text will be:
|
||||
* "sent a message"
|
||||
*
|
||||
* @sa getRichBody(), getPlainBody()
|
||||
* @sa richBody(), plainBody()
|
||||
*/
|
||||
QString getGenericBody() const;
|
||||
static QString genericBody(const NeoChatRoom *room, const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Output a string for the event to be used as a RoomList subtitle.
|
||||
@@ -192,7 +200,7 @@ public:
|
||||
* The output includes the username followed by the plain message, all with no
|
||||
* line breaks.
|
||||
*/
|
||||
QString subtitleText() const;
|
||||
static QString subtitleText(const NeoChatRoom *room, const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Return the media info for the event.
|
||||
@@ -210,22 +218,21 @@ public:
|
||||
* - tempInfo - mediaInfo (with the same properties as this except no tempInfo) for a temporary image while the file downloads.
|
||||
* - isSticker - Whether the image is a sticker or not
|
||||
*/
|
||||
QVariantMap getMediaInfo() const;
|
||||
static QVariantMap mediaInfo(const NeoChatRoom *room, const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Whether the event is a reply to another in the timeline.
|
||||
*
|
||||
* @param showFallbacks whether message that have is_falling_back set true should
|
||||
* show the fallback reply. Leave true for non-threaded
|
||||
* timelines.
|
||||
*/
|
||||
bool hasReply() const;
|
||||
static bool hasReply(const Quotient::RoomEvent *event, bool showFallbacks = true);
|
||||
|
||||
/**
|
||||
* @brief Return the Matrix ID of the event replied to.
|
||||
*/
|
||||
QString getReplyId() const;
|
||||
|
||||
/**
|
||||
* @brief The MessageComponentType to use to visualise the reply content.
|
||||
*/
|
||||
MessageComponentType::Type replyMessageComponentType() const;
|
||||
static QString replyId(const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Get the author of the event replied to in context of the room.
|
||||
@@ -240,73 +247,21 @@ public:
|
||||
*
|
||||
* @sa Quotient::RoomMember
|
||||
*/
|
||||
Quotient::RoomMember getReplyAuthor() const;
|
||||
|
||||
/**
|
||||
* @brief Output a string for the message content of the event replied to ready
|
||||
* for display in a rich text field.
|
||||
*
|
||||
* The output string is dependant upon the event type and the desired output format.
|
||||
*
|
||||
* For most messages this is the body content of the message. For media messages
|
||||
* this will be the caption and for state events it will be a string specific
|
||||
* to that event with some dynamic details about the event added.
|
||||
*
|
||||
* E.g. For a room topic state event the text will be:
|
||||
* "set the topic to: <new topic text>"
|
||||
*
|
||||
* @param stripNewlines whether the output should have new lines in it.
|
||||
*/
|
||||
QString getReplyRichBody(bool stripNewlines = false) const;
|
||||
|
||||
/**
|
||||
* @brief Output a string for the message content of the event replied to ready
|
||||
* for display in a plain text field.
|
||||
*
|
||||
* The output string is dependant upon the event type and the desired output format.
|
||||
*
|
||||
* For most messages this is the body content of the message. For media messages
|
||||
* this will be the caption and for state events it will be a string specific
|
||||
* to that event with some dynamic details about the event added.
|
||||
*
|
||||
* E.g. For a room topic state event the text will be:
|
||||
* "set the topic to: <new topic text>"
|
||||
*
|
||||
* @param stripNewlines whether the output should have new lines in it.
|
||||
*/
|
||||
QString getReplyPlainBody(bool stripNewlines = false) const;
|
||||
|
||||
/**
|
||||
* @brief Return the media info for the event replied to.
|
||||
*
|
||||
* An empty QVariantMap will be returned for any event that doesn't have any
|
||||
* media info.
|
||||
*
|
||||
* @return This should consist of the following:
|
||||
* - source - The mxc URL for the media.
|
||||
* - mimeType - The MIME type of the media (should be image/xxx for this delegate).
|
||||
* - mimeIcon - The MIME icon name (should be image-xxx).
|
||||
* - size - The file size in bytes.
|
||||
* - width - The width in pixels of the audio media.
|
||||
* - height - The height in pixels of the audio media.
|
||||
* - tempInfo - mediaInfo (with the same properties as this except no tempInfo) for a temporary image while the file downloads.
|
||||
* - isSticker - Whether the image is a sticker or not
|
||||
*/
|
||||
QVariantMap getReplyMediaInfo() const;
|
||||
static Quotient::RoomMember replyAuthor(const NeoChatRoom *room, const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Whether the message is part of a thread.
|
||||
*
|
||||
* i.e. There is a rel_type of m.thread.
|
||||
*/
|
||||
bool isThreaded() const;
|
||||
static bool isThreaded(const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Return the Matrix ID of the thread's root message.
|
||||
*
|
||||
* Empty if this not part of a thread.
|
||||
*/
|
||||
QString threadRoot() const;
|
||||
static QString threadRoot(const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Return the latitude for the event.
|
||||
@@ -314,7 +269,7 @@ public:
|
||||
* Returns -100.0 if the event doesn't have a location (latitudes are in the
|
||||
* range -90deg to +90deg so -100 is out of range).
|
||||
*/
|
||||
float getLatitude() const;
|
||||
static float latitude(const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Return the longitude for the event.
|
||||
@@ -322,31 +277,22 @@ public:
|
||||
* Returns -200.0 if the event doesn't have a location (latitudes are in the
|
||||
* range -180deg to +180deg so -200 is out of range).
|
||||
*/
|
||||
float getLongitude() const;
|
||||
static float longitude(const Quotient::RoomEvent *event);
|
||||
|
||||
/**
|
||||
* @brief Return the type of location marker for the event.
|
||||
*/
|
||||
QString getLocationAssetType() const;
|
||||
static QString locationAssetType(const Quotient::RoomEvent *event);
|
||||
|
||||
private:
|
||||
const NeoChatRoom *m_room = nullptr;
|
||||
const Quotient::RoomEvent *m_event = nullptr;
|
||||
static QString getBody(const NeoChatRoom *room, const Quotient::RoomEvent *event, Qt::TextFormat format, bool stripNewlines);
|
||||
static QString getMessageBody(const NeoChatRoom *room, const Quotient::RoomMessageEvent &event, Qt::TextFormat format, bool stripNewlines);
|
||||
|
||||
KFormat m_format;
|
||||
|
||||
QString getBody(const Quotient::RoomEvent *event, Qt::TextFormat format, bool stripNewlines) const;
|
||||
QString getMessageBody(const Quotient::RoomMessageEvent &event, Qt::TextFormat format, bool stripNewlines) const;
|
||||
|
||||
QVariantMap getMediaInfoForEvent(const Quotient::RoomEvent *event) const;
|
||||
QVariantMap getMediaInfoFromFileInfo(
|
||||
#if Quotient_VERSION_MINOR > 8
|
||||
const Quotient::EventContent::FileContentBase *fileContent,
|
||||
#else
|
||||
const Quotient::EventContent::TypedBase *fileContent,
|
||||
#endif
|
||||
const QString &eventId,
|
||||
bool isThumbnail = false,
|
||||
bool isSticker = false) const;
|
||||
QVariantMap getMediaInfoFromTumbnail(const Quotient::EventContent::Thumbnail &thumbnail, const QString &eventId) const;
|
||||
static QVariantMap getMediaInfoForEvent(const NeoChatRoom *room, const Quotient::RoomEvent *event);
|
||||
QVariantMap static getMediaInfoFromFileInfo(const NeoChatRoom *room,
|
||||
const Quotient::EventContent::FileContentBase *fileContent,
|
||||
const QString &eventId,
|
||||
bool isThumbnail = false,
|
||||
bool isSticker = false);
|
||||
static QVariantMap getMediaInfoFromTumbnail(const NeoChatRoom *room, const Quotient::EventContent::Thumbnail &thumbnail, const QString &eventId);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "imagepackevent.h"
|
||||
#include <QJsonObject>
|
||||
#include <Quotient/omittable.h>
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
@@ -11,10 +10,10 @@ ImagePackEventContent::ImagePackEventContent(const QJsonObject &json)
|
||||
{
|
||||
if (json.contains(QStringLiteral("pack"))) {
|
||||
pack = ImagePackEventContent::Pack{
|
||||
fromJson<Omittable<QString>>(json["pack"_ls].toObject()["display_name"_ls]),
|
||||
fromJson<Omittable<QUrl>>(json["pack"_ls].toObject()["avatar_url"_ls]),
|
||||
fromJson<Omittable<QStringList>>(json["pack"_ls].toObject()["usage"_ls]),
|
||||
fromJson<Omittable<QString>>(json["pack"_ls].toObject()["attribution"_ls]),
|
||||
fromJson<std::optional<QString>>(json["pack"_ls].toObject()["display_name"_ls]),
|
||||
fromJson<std::optional<QUrl>>(json["pack"_ls].toObject()["avatar_url"_ls]),
|
||||
fromJson<std::optional<QStringList>>(json["pack"_ls].toObject()["usage"_ls]),
|
||||
fromJson<std::optional<QString>>(json["pack"_ls].toObject()["attribution"_ls]),
|
||||
};
|
||||
} else {
|
||||
pack = std::nullopt;
|
||||
@@ -31,9 +30,9 @@ ImagePackEventContent::ImagePackEventContent(const QJsonObject &json)
|
||||
images += ImagePackImage{
|
||||
k,
|
||||
fromJson<QUrl>(json["images"_ls][k]["url"_ls].toString()),
|
||||
fromJson<Omittable<QString>>(json["images"_ls][k]["body"_ls]),
|
||||
fromJson<std::optional<QString>>(json["images"_ls][k]["body"_ls]),
|
||||
info,
|
||||
fromJson<Omittable<QStringList>>(json["images"_ls][k]["usage"_ls]),
|
||||
fromJson<std::optional<QStringList>>(json["images"_ls][k]["usage"_ls]),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,25 +7,13 @@
|
||||
|
||||
#include <Quotient/accountregistry.h>
|
||||
#include <Quotient/e2ee/sssshandler.h>
|
||||
#include <Quotient/keyimport.h>
|
||||
#include <Quotient/keyverificationsession.h>
|
||||
#include <Quotient/roommember.h>
|
||||
|
||||
#include "controller.h"
|
||||
#include "neochatconfig.h"
|
||||
|
||||
struct ForeignConfig {
|
||||
Q_GADGET
|
||||
QML_FOREIGN(NeoChatConfig)
|
||||
QML_NAMED_ELEMENT(Config)
|
||||
QML_SINGLETON
|
||||
public:
|
||||
static NeoChatConfig *create(QQmlEngine *, QJSEngine *)
|
||||
{
|
||||
QQmlEngine::setObjectOwnership(NeoChatConfig::self(), QQmlEngine::CppOwnership);
|
||||
return NeoChatConfig::self();
|
||||
}
|
||||
};
|
||||
|
||||
struct ForeignAccountRegistry {
|
||||
Q_GADGET
|
||||
QML_FOREIGN(Quotient::AccountRegistry)
|
||||
@@ -51,3 +39,10 @@ struct ForeignSSSSHandler {
|
||||
QML_FOREIGN(Quotient::SSSSHandler)
|
||||
QML_NAMED_ELEMENT(SSSSHandler)
|
||||
};
|
||||
|
||||
struct ForeignKeyImport {
|
||||
Q_GADGET
|
||||
QML_SINGLETON
|
||||
QML_FOREIGN(Quotient::KeyImport)
|
||||
QML_NAMED_ELEMENT(KeyImport)
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
NeochatAdd3PIdJob::NeochatAdd3PIdJob(const QString &clientSecret, const QString &sid, const Omittable<QJsonObject> &auth)
|
||||
NeochatAdd3PIdJob::NeochatAdd3PIdJob(const QString &clientSecret, const QString &sid, const std::optional<QJsonObject> &auth)
|
||||
: BaseJob(HttpVerb::Post, QStringLiteral("Add3PIDJob"), makePath("/_matrix/client/v3", "/account/3pid/add"))
|
||||
{
|
||||
QJsonObject _dataJson;
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <Quotient/jobs/basejob.h>
|
||||
#include <Quotient/omittable.h>
|
||||
|
||||
class NeochatAdd3PIdJob : public Quotient::BaseJob
|
||||
{
|
||||
public:
|
||||
explicit NeochatAdd3PIdJob(const QString &clientSecret, const QString &sid, const Quotient::Omittable<QJsonObject> &auth = {});
|
||||
explicit NeochatAdd3PIdJob(const QString &clientSecret, const QString &sid, const std::optional<QJsonObject> &auth = {});
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
NeochatChangePasswordJob::NeochatChangePasswordJob(const QString &newPassword, bool logoutDevices, const Omittable<QJsonObject> &auth)
|
||||
NeochatChangePasswordJob::NeochatChangePasswordJob(const QString &newPassword, bool logoutDevices, const std::optional<QJsonObject> &auth)
|
||||
: BaseJob(HttpVerb::Post, QStringLiteral("ChangePasswordJob"), "/_matrix/client/r0/account/password")
|
||||
{
|
||||
QJsonObject _data;
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
|
||||
#include <Quotient/jobs/basejob.h>
|
||||
|
||||
#include <Quotient/omittable.h>
|
||||
|
||||
class NeochatChangePasswordJob : public Quotient::BaseJob
|
||||
{
|
||||
public:
|
||||
explicit NeochatChangePasswordJob(const QString &newPassword, bool logoutDevices, const Quotient::Omittable<QJsonObject> &auth = {});
|
||||
explicit NeochatChangePasswordJob(const QString &newPassword, bool logoutDevices, const std::optional<QJsonObject> &auth = {});
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
NeoChatDeactivateAccountJob::NeoChatDeactivateAccountJob(const Omittable<QJsonObject> &auth)
|
||||
NeoChatDeactivateAccountJob::NeoChatDeactivateAccountJob(const std::optional<QJsonObject> &auth)
|
||||
: BaseJob(HttpVerb::Post, QStringLiteral("DisableDeviceJob"), "_matrix/client/v3/account/deactivate")
|
||||
{
|
||||
QJsonObject data;
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <Quotient/jobs/basejob.h>
|
||||
#include <Quotient/omittable.h>
|
||||
|
||||
class NeoChatDeactivateAccountJob : public Quotient::BaseJob
|
||||
{
|
||||
public:
|
||||
explicit NeoChatDeactivateAccountJob(const Quotient::Omittable<QJsonObject> &auth = {});
|
||||
explicit NeoChatDeactivateAccountJob(const std::optional<QJsonObject> &auth = {});
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
NeochatDeleteDeviceJob::NeochatDeleteDeviceJob(const QString &deviceId, const Omittable<QJsonObject> &auth)
|
||||
NeochatDeleteDeviceJob::NeochatDeleteDeviceJob(const QString &deviceId, const std::optional<QJsonObject> &auth)
|
||||
: BaseJob(HttpVerb::Delete, QStringLiteral("DeleteDeviceJob"), QStringLiteral("/_matrix/client/r0/devices/%1").arg(deviceId).toLatin1())
|
||||
{
|
||||
QJsonObject _data;
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <Quotient/jobs/basejob.h>
|
||||
#include <Quotient/omittable.h>
|
||||
|
||||
class NeochatDeleteDeviceJob : public Quotient::BaseJob
|
||||
{
|
||||
public:
|
||||
explicit NeochatDeleteDeviceJob(const QString &deviceId, const Quotient::Omittable<QJsonObject> &auth = {});
|
||||
explicit NeochatDeleteDeviceJob(const QString &deviceId, const std::optional<QJsonObject> &auth = {});
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Quotient/jobs/basejob.h>
|
||||
#include <Quotient/omittable.h>
|
||||
|
||||
// TODO: Upstream to libQuotient
|
||||
class NeochatGetCommonRoomsJob : public Quotient::BaseJob
|
||||
|
||||
@@ -25,8 +25,7 @@ void LoginHelper::init()
|
||||
m_connection = new NeoChatConnection();
|
||||
m_matrixId = QString();
|
||||
m_password = QString();
|
||||
m_deviceName = QStringLiteral("NeoChat %1 %2 %3 %4")
|
||||
.arg(QSysInfo::machineHostName(), QSysInfo::productType(), QSysInfo::productVersion(), QSysInfo::currentCpuArchitecture());
|
||||
m_deviceName = QStringLiteral("NeoChat");
|
||||
m_supportsSso = false;
|
||||
m_supportsPassword = false;
|
||||
m_ssoUrl = QUrl();
|
||||
@@ -85,7 +84,7 @@ void LoginHelper::init()
|
||||
m_connection = nullptr;
|
||||
});
|
||||
connect(m_connection, &Connection::networkError, this, [this](QString error, const QString &, int, int) {
|
||||
Q_EMIT Controller::instance().errorOccured(i18n("Network Error"), std::move(error));
|
||||
Q_EMIT m_connection->errorOccured(i18n("Network Error: %1", std::move(error)));
|
||||
m_isLoggingIn = false;
|
||||
Q_EMIT isLoggingInChanged();
|
||||
});
|
||||
@@ -93,14 +92,14 @@ void LoginHelper::init()
|
||||
if (error == QStringLiteral("Invalid username or password")) {
|
||||
setInvalidPassword(true);
|
||||
} else {
|
||||
Q_EMIT errorOccured(i18n("Login Failed: %1", error));
|
||||
Q_EMIT loginErrorOccured(i18n("Login Failed: %1", error));
|
||||
}
|
||||
m_isLoggingIn = false;
|
||||
Q_EMIT isLoggingInChanged();
|
||||
});
|
||||
|
||||
connect(m_connection, &Connection::resolveError, this, [](QString error) {
|
||||
Q_EMIT Controller::instance().errorOccured(i18n("Network Error"), std::move(error));
|
||||
connect(m_connection, &Connection::resolveError, this, [this](QString error) {
|
||||
Q_EMIT m_connection->errorOccured(i18n("Network Error: %1", std::move(error)));
|
||||
});
|
||||
|
||||
connect(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user